Files
cell/tests/nota.ce
2025-06-16 08:07:45 -05:00

272 lines
8.5 KiB
Plaintext

var nota = use('nota');
var os = use('os');
// Helper function to convert hex string to ArrayBuffer
function hexToBuffer(hex) {
let bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2)
bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
return bytes.buffer;
}
// Helper function to convert ArrayBuffer to hex string
function bufferToHex(buffer) {
return Array.from(new Uint8Array(buffer))
.map(b => b.toString(16).padStart(2, '0'))
.join('')
.toLowerCase();
}
var EPSILON = 1e-12
// Deep comparison function for objects and arrays
function deepCompare(expected, actual, path = '') {
if (expected === actual) return { passed: true, messages: [] };
if (typeof expected === 'number' && typeof actual === 'number') {
if (isNaN(expected) && isNaN(actual))
return { passed: true, messages: [] };
def diff = Math.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 (expected instanceof ArrayBuffer && actual instanceof ArrayBuffer) {
def expArray = Array.from(new Uint8Array(expected));
def actArray = Array.from(new Uint8Array(actual));
return deepCompare(expArray, actArray, path);
}
if (actual instanceof ArrayBuffer)
actual = Array.from(new Uint8Array(actual));
if (Array.isArray(expected) && Array.isArray(actual)) {
if (expected.length !== actual.length)
return {
passed: false,
messages: [`Array length mismatch at ${path}: expected ${expected.length}, got ${actual.length}`]
};
let messages = [];
for (let i = 0; i < expected.length; i++) {
def result = deepCompare(expected[i], actual[i], `${path}[${i}]`);
if (!result.passed) messages.push(...result.messages);
}
return { passed: messages.length === 0, messages };
}
if (typeof expected === 'object' && expected !== null &&
typeof actual === 'object' && actual !== null) {
def expKeys = Object.keys(expected).sort();
def actKeys = Object.keys(actual).sort();
if (JSON.stringify(expKeys) !== JSON.stringify(actKeys))
return {
passed: false,
messages: [`Object keys mismatch at ${path}: expected ${expKeys}, got ${actKeys}`]
};
let messages = [];
for (let key of expKeys) {
def result = deepCompare(expected[key], actual[key], `${path}.${key}`);
if (!result.passed) messages.push(...result.messages);
}
return { passed: messages.length === 0, messages };
}
return {
passed: false,
messages: [`Value mismatch at ${path}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`]
};
}
// Extended test cases covering all Nota types from documentation
var testarr = []
var hex = "a374"
for (var i = 0; i < 500; i++) {
testarr.push(1)
hex += "61"
}
var testCases = [
// Integer tests
{ input: 0, expectedHex: "60" },
{ input: 2023, expectedHex: "e08f67" },
{ input: -1, expectedHex: "69" },
{ input: 7, expectedHex: "67" },
{ input: -7, expectedHex: "6f" },
{ input: 1023, expectedHex: "e07f" },
{ input: -1023, expectedHex: "ef7f" },
// Symbol tests
{ input: undefined, expectedHex: "70" },
{ input: false, expectedHex: "72" },
{ input: true, expectedHex: "73" },
// Floating Point tests
{ input: -1.01, expectedHex: "5a65" },
{ input: 98.6, expectedHex: "51875a" },
{ input: -0.5772156649, expectedHex: "d80a95c0b0bd69" },
{ input: -1.00000000000001, expectedHex: "d80e96deb183e98001" },
{ input: -10000000000000, expectedHex: "c80d01" },
// Text tests
{ input: "", expectedHex: "10" },
{ input: "cat", expectedHex: "13636174" },
{ input: "U+1F4A9 「うんち絵文字」 «💩»",
expectedHex: "9014552b314634413920e00ce046e113e06181fa7581cb0781b657e00d20812b87e929813b" },
// Blob tests
{ input: new Uint8Array([0xFF, 0xAA]).buffer, expectedHex: "8010ffaa" },
{ input: new Uint8Array([0b11110000, 0b11100011, 0b00100000, 0b10000000]).buffer,
expectedHex: "8019f0e32080" },
{ input: testarr, expectedHex: hex },
// Array tests
{ input: [], expectedHex: "20" },
{ input: [1, 2, 3], expectedHex: "23616263" },
{ input: [-1, 0, 1.5], expectedHex: "2369605043" },
// Record tests
{ input: {}, expectedHex: "30" },
{ input: { a: 1, b: 2 }, expectedHex: "32116161116262" },
// Complex nested structures
{ input: {
num: 42,
arr: [1, -1, 2.5],
str: "test",
obj: { x: true }
},
expectedHex: "34216e756d622a2173747214746573742161727223616965235840216f626a21117873" },
// Private prefix test
{ input: { private: { address: "test" } },
expectedHex: "317821616464726573731474657374" },
// System prefix test
{ input: { system: { msg: "hello" } },
expectedHex: "3179216d73671568656c6c6f" },
{ input: [{ system: {msg: "hello" } }, {
num: 42,
arr: [1, -1, 2.5],
str: "test",
obj: { x: true }
}], expectedHex: "223179216d73671568656c6c6f34216e756d622a2173747214746573742161727223616965235840216f626a21117873" },
// Additional edge cases
{ input: new Uint8Array([]).buffer, expectedHex: "00" },
{ input: [[]], expectedHex: "2120" },
{ input: { "": "" }, expectedHex: "311010" },
{ input: 1e-10, expectedHex: "d00a01" },
// Replacer tests
{ input: { a: 1, b: 2 },
replacer: (key, value) => typeof value === 'number' ? value * 2 : value,
expected: { a: 2, b: 4 },
testType: 'replacer' },
{ input: { x: "test", y: 5 },
replacer: (key, value) => key === 'x' ? value + "!" : value,
expected: { x: "test!", y: 5 },
testType: 'replacer' },
// Reviver tests
{ input: { a: 1, b: 2 },
reviver: (key, value) => typeof value === 'number' ? value * 3 : value,
expected: { a: 3, b: 6 },
testType: 'reviver' },
{ input: { x: "test", y: 10 },
reviver: (key, value) => key === 'y' ? value + 1 : value,
expected: { x: "test", y: 11 },
testType: 'reviver' }
];
// Run tests and collect results
let results = [];
let testCount = 0;
for (let test of testCases) {
testCount++;
let testName = `Test ${testCount}: ${JSON.stringify(test.input)}${test.testType ? ` (${test.testType})` : ''}`;
let passed = true;
let messages = [];
// Test encoding
let encoded = test.replacer ? nota.encode(test.input, test.replacer) : nota.encode(test.input);
if (!(encoded instanceof ArrayBuffer)) {
passed = false;
messages.push("Encode should return ArrayBuffer");
} else {
if (test.expectedHex) {
let encodedHex = bufferToHex(encoded);
if (encodedHex !== test.expectedHex.toLowerCase()) {
messages.push(
`Hex encoding differs (informational):
Expected: ${test.expectedHex}
Got: ${encodedHex}`
);
}
}
// Test decoding
let decoded = test.reviver ? nota.decode(encoded, test.reviver) : nota.decode(encoded);
let expected = test.expected || test.input;
// Normalize ArrayBuffer and special cases for comparison
if (expected instanceof ArrayBuffer)
expected = Array.from(new Uint8Array(expected));
if (decoded instanceof ArrayBuffer)
decoded = Array.from(new Uint8Array(decoded));
if (expected && (expected.private || expected.system)) {
def key = expected.private ? 'private' : 'system';
expected = { [key]: expected[key] };
}
def compareResult = deepCompare(expected, decoded);
if (!compareResult.passed) {
passed = false;
messages.push("Decoding failed:");
messages.push(...compareResult.messages);
}
}
results.push({ testName, passed, messages });
if (!passed) {
log.console(`\nDetailed Failure Report for ${testName}:`);
log.console(`Input: ${JSON.stringify(test.input)}`);
if (test.replacer) log.console(`Replacer: ${test.replacer.toString()}`);
if (test.reviver) log.console(`Reviver: ${test.reviver.toString()}`);
log.console(messages.join("\n"));
log.console("");
}
}
// Summary
log.console("\nTest Summary:");
results.forEach(result => {
log.console(`${result.testName} - ${result.passed ? "Passed" : "Failed"}`);
if (!result.passed)
log.console(result.messages)
});
let passedCount = results.filter(r => r.passed).length;
log.console(`\nResult: ${passedCount}/${testCount} tests passed`);
if (passedCount < testCount) {
log.console("Overall: FAILED");
// os.exit(1);
} else {
log.console("Overall: PASSED");
// os.exit(0);
}