183 lines
6.0 KiB
Plaintext
183 lines
6.0 KiB
Plaintext
var nota = use('nota');
|
|
var os = use('os');
|
|
var blob = use('blob')
|
|
|
|
var EPSILON = 1e-12
|
|
|
|
function stone_if_needed(b) { if (!stone.p(b)) stone(b) }
|
|
|
|
function bytes_to_blob(bytes) {
|
|
var b = blob()
|
|
for (var i = 0; i < bytes.length; i++) {
|
|
var byte = bytes[i]
|
|
for (var bit = 7; bit >= 0; bit--) b.write_bit((byte >> bit) & 1)
|
|
}
|
|
stone(b)
|
|
return b
|
|
}
|
|
|
|
function deepCompare(expected, actual, path) {
|
|
path = path || ''
|
|
if (expected == actual) return { passed: true, messages: [] };
|
|
|
|
if (is_number(expected) && is_number(actual)) {
|
|
if (isNaN(expected) && isNaN(actual))
|
|
return { passed: true, messages: [] };
|
|
|
|
var diff = abs(expected - actual);
|
|
if (diff <= EPSILON)
|
|
return { passed: true, messages: [] };
|
|
|
|
return {
|
|
passed: false,
|
|
messages: [
|
|
`Value mismatch at ${path}: expected ${expected}, got ${actual}`,
|
|
`Difference of ${diff} is larger than tolerance ${EPSILON}`
|
|
]
|
|
};
|
|
}
|
|
|
|
if (is_blob(expected) && is_blob(actual)) {
|
|
stone_if_needed(expected); stone_if_needed(actual)
|
|
if (expected.length != actual.length)
|
|
return { passed: false, messages: [`blob length mismatch at ${path}: ${expected.length} vs ${actual.length}`] }
|
|
for (var i = 0; i < expected.length; i++) {
|
|
if (expected.read_logical(i) != actual.read_logical(i))
|
|
return { passed: false, messages: [`blob bit mismatch at ${path}[${i}]`] }
|
|
}
|
|
return { passed: true, messages: [] }
|
|
}
|
|
|
|
if (is_array(expected) && is_array(actual)) {
|
|
if (expected.length != actual.length)
|
|
return {
|
|
passed: false,
|
|
messages: [`Array length mismatch at ${path}: expected ${expected.length}, got ${actual.length}`]
|
|
};
|
|
var messages = [];
|
|
for (var i = 0; i < expected.length; i++) {
|
|
var result = deepCompare(expected[i], actual[i], `${path}[${i}]`);
|
|
if (!result.passed) {
|
|
for(var m of result.messages) messages.push(m);
|
|
}
|
|
}
|
|
return { passed: messages.length == 0, messages: messages };
|
|
}
|
|
|
|
if (is_object(expected) && is_object(actual)) {
|
|
var expKeys = sort(array(expected))
|
|
var actKeys = sort(array(actual))
|
|
if (JSON.stringify(expKeys) != JSON.stringify(actKeys))
|
|
return {
|
|
passed: false,
|
|
messages: [`Object keys mismatch at ${path}: expected ${expKeys}, got ${actKeys}`]
|
|
};
|
|
var messages = [];
|
|
for (var key of expKeys) {
|
|
var result = deepCompare(expected[key], actual[key], `${path}.${key}`);
|
|
if (!result.passed) {
|
|
for(var m of result.messages) messages.push(m);
|
|
}
|
|
}
|
|
return { passed: messages.length == 0, messages: messages };
|
|
}
|
|
|
|
return {
|
|
passed: false,
|
|
messages: [`Value mismatch at ${path}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`]
|
|
};
|
|
}
|
|
|
|
function makeTest(test) {
|
|
return function() {
|
|
var encoded = test.replacer ? nota.encode(test.input, test.replacer) : nota.encode(test.input);
|
|
if (!is_blob(encoded)){
|
|
throw "encode() should return blob";
|
|
}
|
|
|
|
var decoded = test.reviver ? nota.decode(encoded, test.reviver) : nota.decode(encoded);
|
|
var expected = test.expected || test.input;
|
|
if (expected && (expected.private || expected.system)) {
|
|
var key = expected.private ? 'private' : 'system';
|
|
expected = { [key]: expected[key] };
|
|
}
|
|
|
|
var compareResult = deepCompare(expected, decoded);
|
|
if (!compareResult.passed) {
|
|
throw text(compareResult.messages, '; ');
|
|
}
|
|
};
|
|
}
|
|
|
|
var testarr = []
|
|
for (var i = 0; i < 500; i++) {
|
|
testarr.push(1)
|
|
}
|
|
|
|
var testCases = [
|
|
{ name: 'zero', input: 0 },
|
|
{ name: 'positive_2023', input: 2023 },
|
|
{ name: 'neg1', input: -1 },
|
|
{ name: 'positive_7', input: 7 },
|
|
{ name: 'neg7', input: -7 },
|
|
{ name: 'positive_1023', input: 1023 },
|
|
{ name: 'neg1023', input: -1023 },
|
|
{ name: 'null', input: null },
|
|
{ name: 'false', input: false },
|
|
{ name: 'true', input: true },
|
|
{ name: 'float_neg1_01', input: -1.01 },
|
|
{ name: 'float_98_6', input: 98.6 },
|
|
{ name: 'float_euler', input: -0.5772156649 },
|
|
{ name: 'float_precision', input: -1.00000000000001 },
|
|
{ name: 'float_large_neg', input: -10000000000000 },
|
|
{ name: 'empty_string', input: "" },
|
|
{ name: 'string_cat', input: "cat" },
|
|
{ name: 'string_unicode', input: "U+1F4A9 「うんち絵文字」 «💩»" },
|
|
{ name: 'buffer_ffaa', input: bytes_to_blob([0xFF, 0xAA]) },
|
|
{ name: 'buffer_f0e32080', input: bytes_to_blob([0b11110000, 0b11100011, 0b00100000, 0b10000000]) },
|
|
{ name: 'large_array', input: testarr },
|
|
{ name: 'empty_array', input: [] },
|
|
{ name: 'array_123', input: [1, 2, 3] },
|
|
{ name: 'array_mixed', input: [-1, 0, 1.5] },
|
|
{ name: 'empty_object', input: {} },
|
|
{ name: 'object_ab', input: { a: 1, b: 2 } },
|
|
{ name: 'object_nested', input: {
|
|
num: 42,
|
|
arr: [1, -1, 2.5],
|
|
str: "test",
|
|
obj: { x: true }
|
|
} },
|
|
{ name: 'object_private', input: { private: { address: "test" } } },
|
|
{ name: 'object_system', input: { system: { msg: "hello" } } },
|
|
{ name: 'array_system_nested', input: [{ system: {msg: "hello" } }, {
|
|
num: 42,
|
|
arr: [1, -1, 2.5],
|
|
str: "test",
|
|
obj: { x: true }
|
|
}] },
|
|
{ name: 'empty_buffer', input: blob() },
|
|
{ name: 'nested_empty_array', input: [[]] },
|
|
{ name: 'empty_key_value', input: { "": "" } },
|
|
{ name: 'small_float', input: 1e-10 },
|
|
{ name: 'replacer_multiply', input: { a: 1, b: 2 },
|
|
replacer: (key, value) => is_number(value) ? value * 2 : value,
|
|
expected: { a: 2, b: 4 } },
|
|
{ name: 'replacer_string_append', input: { x: "test", y: 5 },
|
|
replacer: (key, value) => key == 'x' ? value + "!" : value,
|
|
expected: { x: "test!", y: 5 } },
|
|
{ name: 'reviver_multiply', input: { a: 1, b: 2 },
|
|
reviver: (key, value) => is_number(value) ? value * 3 : value,
|
|
expected: { a: 3, b: 6 } },
|
|
{ name: 'reviver_increment', input: { x: "test", y: 10 },
|
|
reviver: (key, value) => key == 'y' ? value + 1 : value,
|
|
expected: { x: "test", y: 11 } }
|
|
];
|
|
|
|
var tests = {};
|
|
for (var i = 0; i < testCases.length; i++) {
|
|
var t = testCases[i];
|
|
tests[t.name] = makeTest(t);
|
|
}
|
|
|
|
return tests;
|