316 lines
8.3 KiB
Vala
316 lines
8.3 KiB
Vala
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);
|
|
});
|
|
|
|
Test.add_func("/encode/choice/1:foo", () => {
|
|
var choice = new Der.Choice(1, new Utf8String("foo"));
|
|
var expected = new uint8[] {
|
|
0xa1, 0x05, 0x0c, 0x03, 0x66, 0x6f, 0x6f
|
|
};
|
|
test_encode(choice, expected);
|
|
});
|
|
|
|
Test.add_func("/encode/null", () => {
|
|
test_encode(new Der.Null(), { 0x05, 0x00 });
|
|
});
|
|
|
|
/*
|
|
* 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 expected_len = 2;
|
|
var bytes = new uint8[] {
|
|
0x30, 0x08, 0x0c, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x2a
|
|
};
|
|
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_len) {
|
|
Test.message(
|
|
@"Expected $expected_len elements, got $(elems.length)");
|
|
Test.fail();
|
|
return;
|
|
}
|
|
test_utf8string_value("foo", elems[0]);
|
|
test_integer_value(42, elems[1]);
|
|
});
|
|
|
|
Test.add_func("/decode/choice/1:foo", () => {
|
|
var expected_id = 1;
|
|
var bytes = new uint8[] {
|
|
0xa1, 0x05, 0x0c, 0x03, 0x66, 0x6f, 0x6f
|
|
};
|
|
Der.Choice choice;
|
|
try {
|
|
choice = decode(bytes) as Der.Choice;
|
|
} catch (DecodeError err) {
|
|
Test.message("Decoding failed: %s", err.message);
|
|
Test.fail();
|
|
return;
|
|
}
|
|
if (choice == null) {
|
|
Test.message("Bytes were not decoded as a CHOICE");
|
|
Test.fail();
|
|
return;
|
|
}
|
|
if (choice.id != expected_id) {
|
|
Test.message(@"Expected ID $expected_id, got $(choice.id)");
|
|
Test.fail();
|
|
return;
|
|
}
|
|
test_utf8string_value("foo", choice.value);
|
|
});
|
|
|
|
Test.add_func("/decode/null", () => {
|
|
var bytes = new uint8[] { 0x05, 0x00 };
|
|
Der.Null @null;
|
|
try {
|
|
@null = decode(bytes) as Der.Null;
|
|
} catch (DecodeError err) {
|
|
Test.message("Decoding failed: %s", err.message);
|
|
Test.fail();
|
|
return;
|
|
}
|
|
if (@null == null) {
|
|
Test.message("Bytes were not decoded as a NULL");
|
|
Test.fail();
|
|
return;
|
|
}
|
|
});
|
|
|
|
|
|
Test.run();
|
|
}
|