using StudySystemClient; using StudySystemClient.Der; static bool bytes_equal(uint8[] expected, uint8[] actual) { if (expected.length != actual.length) return false; return Memory.cmp(expected, actual, expected.length) == 0; } static string bytes_to_string(uint8[] bytes) { var s = ""; foreach (var byte in bytes) s += "%02x".printf(byte); return s; } static void test_encode(Datum datum, uint8[] expected) { var bytes = datum.encode(); if (!bytes_equal(expected, bytes)) { Test.message("Encoding is incorrect: expected %s got %s", bytes_to_string(expected), bytes_to_string(bytes)); Test.fail(); return; } } static void test_decode_boolean(uint8[] bytes, bool expected) { Boolean boolean; try { boolean = decode(bytes) as Boolean; } catch (DecodeError err) { Test.message("Decoding failed: %s", err.message); Test.fail(); return; } if (boolean == null) { Test.message("Bytes were not decoded as a BOOLEAN"); Test.fail(); return; } if (boolean.value != expected) { Test.message(@"Expected $expected got $(boolean.value)"); Test.fail(); return; } } static void test_decode_integer(uint8[] bytes, int64 expected) { Datum datum; try { datum = decode(bytes); } catch (DecodeError err) { Test.message("Decoding failed: %s", err.message); Test.fail(); return; } test_integer_value(expected, datum); } static void test_decode_utf8string(uint8[] bytes, string expected) { Datum datum; try { datum = decode(bytes); } catch (DecodeError err) { Test.message("Decoding failed: %s", err.message); Test.fail(); return; } test_utf8string_value(expected, datum); } static void test_integer_value(int64 expected, Datum datum) { var integer = datum as Integer; if (integer == null) { Test.message("Bytes were not decoded as a INTEGER"); Test.fail(); return; } if (integer.value != expected) { Test.message(@"Expected $expected got $(integer.value)"); Test.fail(); return; } } static void test_utf8string_value(string expected, Datum datum) { var utf8string = datum as Utf8String; if (utf8string == null) { Test.message("Bytes were not decoded as a UTF8String"); Test.fail(); return; } if (utf8string.value != expected) { Test.message(@"Expected $expected got $(utf8string.value)"); Test.fail(); return; } } void main(string[] args) { Test.init(ref args); /* * Encoding */ Test.add_func("/encode/boolean/true", () => { test_encode(new Boolean(true), {0x01, 0x01, 0xff}); }); Test.add_func("/encode/boolean/false", () => { test_encode(new Boolean(false), {0x01, 0x01, 0x00}); }); Test.add_func("/encode/integer/small/0", () => { test_encode(new Integer(0), {0x02, 0x01, 0x00}); }); Test.add_func("/encode/integer/small/5", () => { test_encode(new Integer(5), {0x02, 0x01, 0x05}); }); Test.add_func("/encode/integer/small/42", () => { test_encode(new Integer(42), {0x02, 0x01, 0x2a}); }); Test.add_func("/encode/integer/large/1337", () => { test_encode(new Integer(1337), {0x02, 0x02, 0x05, 0x39}); }); Test.add_func("/encode/integer/sign/128", () => { test_encode(new Integer(128), {0x02, 0x02, 0x00, 0x80}); }); Test.add_func("/encode/integer/sign/0xbeef", () => { test_encode(new Integer(0xbeef), {0x02, 0x03, 0x00, 0xbe, 0xef}); }); Test.add_func("/encode/integer/sign/-128", () => { test_encode(new Integer(-128), {0x02, 0x01, 0x80}); }); Test.add_func("/encode/integer/sign/-1337", () => { test_encode(new Integer(-1337), {0x02, 0x02, 0xfa, 0xc7}); }); Test.add_func("/encode/utf8string/short/foo", () => { test_encode(new Utf8String("foo"), {0x0c, 0x03, 0x66, 0x6f, 0x6f}); }); Test.add_func("/encode/utf8string/short/bar", () => { test_encode(new Utf8String("bar"), {0x0c, 0x03, 0x62, 0x61, 0x72}); }); Test.add_func("/encode/utf8string/long/x300", () => { var expected = new uint8[304]; expected[0] = 0x0c; expected[1] = 0x82; expected[2] = 0x01; expected[3] = 0x2c; Memory.set(expected[4:], 0x78, 300); test_encode(new Utf8String(string.nfill(300, 'x')), expected); }); Test.add_func("/encode/utf8string/long/x128", () => { var expected = new uint8[131]; expected[0] = 0x0c; expected[1] = 0x81; expected[2] = 0x80; Memory.set(expected[3:], 0x78, 128); test_encode(new Utf8String(string.nfill(128, 'x')), expected); }); Test.add_func("/encode/sequence/foo,42", () => { var sequence = new Der.Sequence( {new Utf8String("foo"), new Integer(42)}); var expected = new uint8[] { 0x30, 0x08, 0x0c, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x2a }; test_encode(sequence, expected); }); /* * Decoding */ Test.add_func("/decode/boolean/true", () => { test_decode_boolean({0x01, 0x01, 0xff}, true); }); Test.add_func("/decode/boolean/false", () => { test_decode_boolean({0x01, 0x01, 0x00}, false); }); Test.add_func("/decode/integer/small/42", () => { test_decode_integer({0x02, 0x01, 0x2a}, 42); }); Test.add_func("/decode/integer/large/1337", () => { test_decode_integer({0x02, 0x02, 0x05, 0x39}, 1337); }); Test.add_func("/decode/integer/sign/128", () => { test_decode_integer({0x02, 0x02, 0x00, 0x80}, 128); }); Test.add_func("/decode/integer/sign/0xbeef", () => { test_decode_integer({0x02, 0x03, 0x00, 0xbe, 0xef}, 0xbeef); }); Test.add_func("/decode/integer/sign/-128", () => { test_decode_integer({0x02, 0x01, 0x80}, -128); }); Test.add_func("/decode/integer/sign/-1337", () => { test_decode_integer({0x02, 0x02, 0xfa, 0xc7}, -1337); }); Test.add_func("/decode/utf8string/short/foo", () => { test_decode_utf8string({0x0c, 0x03, 0x66, 0x6f, 0x6f}, "foo"); }); Test.add_func("/decode/utf8string/short/bar", () => { test_decode_utf8string({0x0c, 0x03, 0x62, 0x61, 0x72}, "bar"); }); Test.add_func("/decode/utf8string/long/x300", () => { var bytes = new uint8[304]; bytes[0] = 0x0c; bytes[1] = 0x82; bytes[2] = 0x01; bytes[3] = 0x2c; Memory.set(bytes[4:], 0x78, 300); test_decode_utf8string(bytes, string.nfill(300, 'x')); }); Test.add_func("/decode/utf8string/long/x128", () => { var bytes = new uint8[131]; bytes[0] = 0x0c; bytes[1] = 0x81; bytes[2] = 0x80; Memory.set(bytes[3:], 0x78, 128); test_decode_utf8string(bytes, string.nfill(128, 'x')); }); Test.add_func("/decode/sequence/foo,42", () => { var bytes = new uint8[] { 0x30, 0x08, 0x0c, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x2a }; var expected = 2; Der.Sequence sequence; try { sequence = decode(bytes) as Der.Sequence; } catch (DecodeError err) { Test.message("Decoding failed: %s", err.message); Test.fail(); return; } if (sequence == null) { Test.message("Bytes were not decoded as a SEQUENCE"); Test.fail(); return; } Datum[] elems = sequence.value; if (elems.length != expected) { Test.message( @"Expected $expected elements, got $(elems.length)"); Test.fail(); return; } test_utf8string_value("foo", elems[0]); test_integer_value(42, elems[1]); }); Test.run(); }