Files
cell/tests/wota.cm
2026-01-13 22:16:28 -06:00

130 lines
4.6 KiB
Plaintext

var wota = use('wota')
var os = use('os')
var blob = use('blob')
var math = use('math/radians')
var EPSILON = 1e-12
function stone_if_needed(b) { if (!stone.p(b)) stone(b) }
/* Deep comparison capable of blobs + tolerance for floating diff */
function deep_compare(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 = number.abs(expected - actual)
if (diff <= EPSILON) return { passed: true, messages: [] }
return { passed: false, messages: [`Value mismatch at ${path}: ${expected} vs ${actual} (diff ${diff})`] }
}
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.length} vs ${actual.length}`] }
var msgs = []
for (var i = 0; i < expected.length; i++) {
var res = deep_compare(expected[i], actual[i], `${path}[${i}]`)
if (!res.passed) {
for(var m of res.messages) msgs.push(m)
}
}
return { passed: msgs.length == 0, messages: msgs }
}
if (is_object(expected) && is_object(actual)) {
var expKeys = array(expected).sort()
var actKeys = array(actual).sort()
if (JSON.stringify(expKeys) != JSON.stringify(actKeys))
return { passed: false, messages: [`Object keys mismatch at ${path}: ${expKeys} vs ${actKeys}`] }
var msgs = []
for (var k of expKeys) {
var res = deep_compare(expected[k], actual[k], `${path}.${k}`)
if (!res.passed) {
for(var m of res.messages) msgs.push(m)
}
}
return { passed: msgs.length == 0, messages: msgs }
}
return { passed: false, messages: [`Value mismatch at ${path}: ${JSON.stringify(expected)} vs ${JSON.stringify(actual)}`] }
}
var testarr = []
for (var i = 0; i < 500; i++) { testarr.push(1) }
var testCases = [
{ name: 'zero', input: 0 },
{ name: '2023', input: 2023 },
{ name: 'neg1', input: -1 },
{ name: '7', input: 7 },
{ name: 'neg7', input: -7 },
{ name: '1023', input: 1023 },
{ name: 'neg1023', input: -1023 },
{ name: 'large_pos', input: math.power(2, 55) - 1 },
{ name: 'large_neg', input: -math.power(2, 55) },
{ 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: 'float_pow2_55', input: math.power(2, 55) },
{ name: 'empty_string', input: '' },
{ name: 'string_cat', input: 'cat' },
{ name: 'string_unicode', input: 'U+1F4A9 「うんち絵文字」 «💩»' },
{ 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: 'nested_object', input: { num: 42, arr: [1, -1, 2.5], str: 'test', obj: { x: true } } },
{ name: 'empty_blob', input: blob() },
{ name: 'nested_array', input: [[]] },
{ name: 'empty_key_val', input: { '': '' } },
{ name: 'small_float', input: 1e-10 }
]
function make_test(t) {
return function() {
var enc = wota.encode(t.input)
if (!is_blob(enc)) throw 'encode() should return a blob'
var dec = wota.decode(enc)
var cmp = deep_compare(t.input, dec)
if (!cmp.passed) throw cmp.messages.join('; ')
}
}
var tests = {}
for (var i = 0; i < testCases.length; i++) {
var t = testCases[i]
var name = t.name || ('case_' + i)
tests[name] = make_test(t)
}
return tests