diff options
Diffstat (limited to 'ocaml/test')
-rw-r--r-- | ocaml/test/bench_nock.ml | 132 | ||||
-rw-r--r-- | ocaml/test/dune | 23 | ||||
-rw-r--r-- | ocaml/test/test_hex.ml | 26 | ||||
-rw-r--r-- | ocaml/test/test_jam_debug.ml | 20 | ||||
-rw-r--r-- | ocaml/test/test_nock.ml | 284 | ||||
-rw-r--r-- | ocaml/test/test_serial.ml | 185 |
6 files changed, 670 insertions, 0 deletions
diff --git a/ocaml/test/bench_nock.ml b/ocaml/test/bench_nock.ml new file mode 100644 index 0000000..a71b3da --- /dev/null +++ b/ocaml/test/bench_nock.ml @@ -0,0 +1,132 @@ +open Nock_lib.Noun +open Nock_lib.Nock + +(** Benchmark utilities *) + +let time_ms () = + Unix.gettimeofday () *. 1000.0 + +let bench_nock name subject formula iterations = + (* Warmup *) + for _i = 1 to 100 do + let _ = nock subject formula in () + done; + + (* Actual benchmark *) + Gc.compact (); + let start = time_ms () in + + for _i = 1 to iterations do + let _result = nock subject formula in () + done; + + let finish = time_ms () in + let total = finish -. start in + let per_iter = total /. (float_of_int iterations) in + let ops_per_sec = 1000.0 /. per_iter in + + Printf.printf "%-30s %8d iterations in %10.2f ms (%10.6f ms/iter, %10.0f ops/sec)\n" + name iterations total per_iter ops_per_sec + +(** Benchmarks *) + +let () = + Printf.printf "Nock Benchmark - OCaml Implementation\n"; + Printf.printf "======================================\n\n"; + + let iterations = 1_000_000 in (* 1M iterations for fast ops *) + let slow_iters = 100_000 in (* 100K for slower ops *) + + (* Benchmark 0: slot lookup *) + begin + let subject = cell (atom 42) (atom 99) in + let formula = cell (atom 0) (atom 2) in (* [0 2] - get head *) + bench_nock "Opcode 0: slot/fragment" subject formula iterations + end; + + (* Benchmark 1: constant *) + begin + let subject = atom 0 in + let formula = cell (atom 1) (atom 42) in (* [1 42] *) + bench_nock "Opcode 1: constant" subject formula iterations + end; + + (* Benchmark 3: is-cell *) + begin + let subject = atom 0 in + let formula = cell (atom 3) (cell (atom 1) (atom 42)) in (* [3 [1 42]] *) + bench_nock "Opcode 3: is-cell (atom)" subject formula iterations + end; + + (* Benchmark 4: increment *) + begin + let subject = atom 0 in + let formula = cell (atom 4) (cell (atom 1) (atom 1000)) in (* [4 [1 1000]] *) + bench_nock "Opcode 4: increment" subject formula iterations + end; + + (* Benchmark 5: equality *) + begin + let subject = atom 0 in + (* [5 [1 42] [1 42]] *) + let formula = cell (atom 5) (cell (cell (atom 1) (atom 42)) (cell (atom 1) (atom 42))) in + bench_nock "Opcode 5: equality (equal)" subject formula iterations + end; + + (* Benchmark 6: if-then-else *) + begin + let subject = atom 0 in + (* [6 [1 0] [1 11] [1 22]] *) + let formula = cell (atom 6) + (cell (cell (atom 1) (atom 0)) + (cell (cell (atom 1) (atom 11)) + (cell (atom 1) (atom 22)))) in + bench_nock "Opcode 6: if-then-else" subject formula iterations + end; + + (* Benchmark 7: composition *) + begin + let subject = atom 42 in + (* [7 [1 99] [0 1]] *) + let formula = cell (atom 7) (cell (cell (atom 1) (atom 99)) (cell (atom 0) (atom 1))) in + bench_nock "Opcode 7: composition" subject formula iterations + end; + + (* Benchmark 8: push *) + begin + let subject = atom 42 in + (* [8 [1 99] [0 1]] *) + let formula = cell (atom 8) (cell (cell (atom 1) (atom 99)) (cell (atom 0) (atom 1))) in + bench_nock "Opcode 8: push" subject formula iterations + end; + + (* Benchmark: Decrement-like operation (slower) *) + begin + (* [6 [5 [0 1] [1 0]] [1 0] [8 [1 0] [4 [0 3]]]] *) + (* This is: if(subject == 0) 0 else subject+1 (simplified) *) + let dec_fol = cell (atom 6) + (cell (cell (atom 5) (cell (cell (atom 0) (atom 1)) (cell (atom 1) (atom 0)))) + (cell (cell (atom 1) (atom 0)) + (cell (atom 8) (cell (cell (atom 1) (atom 0)) (cell (atom 4) (cell (atom 0) (atom 3))))))) in + + let subject = atom 10 in + bench_nock "Complex: decrement loop" subject dec_fol slow_iters + end; + + (* Benchmark: Tree construction *) + begin + let subject = atom 0 in + (* [[1 1] [1 2]] - constructs a cell *) + let formula = cell (cell (atom 1) (atom 1)) (cell (atom 1) (atom 2)) in + bench_nock "Cell construction" subject formula iterations + end; + + (* Benchmark: Deep slot lookup *) + begin + (* Build a deep tree: [[[[1 2] 3] 4] 5] *) + let subject = cell (cell (cell (cell (atom 1) (atom 2)) (atom 3)) (atom 4)) (atom 5) in + let formula = cell (atom 0) (atom 16) in (* slot 16 = deepest left (1) *) + bench_nock "Deep slot lookup (depth 4)" subject formula iterations + end; + + Printf.printf "\n" diff --git a/ocaml/test/dune b/ocaml/test/dune new file mode 100644 index 0000000..b0ad51d --- /dev/null +++ b/ocaml/test/dune @@ -0,0 +1,23 @@ +(test + (name test_nock) + (modules test_nock) + (libraries nock_lib zarith)) + +(test + (name test_serial) + (modules test_serial) + (libraries nock_lib zarith)) + +(test + (name test_jam_debug) + (modules test_jam_debug) + (libraries nock_lib zarith)) + +(test + (name bench_nock) + (modules bench_nock) + (libraries nock_lib zarith unix)) + +(executable + (name test_hex) + (libraries nock_lib)) diff --git a/ocaml/test/test_hex.ml b/ocaml/test/test_hex.ml new file mode 100644 index 0000000..a228682 --- /dev/null +++ b/ocaml/test/test_hex.ml @@ -0,0 +1,26 @@ +open Nock_lib.Noun +open Nock_lib.Serial + +let () = + for i = 0 to 10 do + let n = atom i in + let jammed = jam n in + Printf.printf "jam(%d) = %s (%d bytes)\n" i (bytes_to_hex jammed) (Bytes.length jammed) + done + +let () = + Printf.printf "\nRound-trip tests:\n"; + for i = 0 to 50 do + let n = atom i in + let jammed = jam n in + let cued = cue jammed in + match cued with + | Atom a when Z.equal a (Z.of_int i) -> + Printf.printf "OK: %d\n" i + | Atom a -> + Printf.printf "FAIL: %d -> %s\n" i (Z.to_string a); + exit 1 + | Cell _ -> + Printf.printf "FAIL: %d -> cell\n" i; + exit 1 + done diff --git a/ocaml/test/test_jam_debug.ml b/ocaml/test/test_jam_debug.ml new file mode 100644 index 0000000..cad3ee9 --- /dev/null +++ b/ocaml/test/test_jam_debug.ml @@ -0,0 +1,20 @@ +open Nock_lib.Noun +open Nock_lib.Serial + +let () = + Printf.printf "Testing jam encoding:\n"; + + (* Test 0 *) + let n0 = atom 0 in + let j0 = jam n0 in + Printf.printf "jam(0) = %s\n" (bytes_to_hex j0); + + (* Test 1 *) + let n1 = atom 1 in + let j1 = jam n1 in + Printf.printf "jam(1) = %s\n" (bytes_to_hex j1); + + (* Test 2 *) + let n2 = atom 2 in + let j2 = jam n2 in + Printf.printf "jam(2) = %s\n" (bytes_to_hex j2); diff --git a/ocaml/test/test_nock.ml b/ocaml/test/test_nock.ml new file mode 100644 index 0000000..73f2ce2 --- /dev/null +++ b/ocaml/test/test_nock.ml @@ -0,0 +1,284 @@ +open Nock_lib.Noun +open Nock_lib.Nock + +(** Test utilities *) + +let assert_equal expected actual msg = + if not (equal expected actual) then begin + Printf.printf "FAIL: %s\n" msg; + Format.printf " Expected: %a@." pp_noun expected; + Format.printf " Actual: %a@." pp_noun actual; + exit 1 + end else + Printf.printf "PASS: %s\n" msg + +let _assert_raises_exit f msg = + try + let _ = f () in + Printf.printf "FAIL: %s (expected Exit exception)\n" msg; + exit 1 + with Exit -> + Printf.printf "PASS: %s\n" msg + +(** Basic noun tests *) + +let test_noun_basics () = + Printf.printf "\n=== Testing basic noun operations ===\n"; + + (* Test atom creation *) + let a = atom 42 in + assert_equal (atom 42) a "atom creation"; + + (* Test cell creation *) + let c = cell (atom 1) (atom 2) in + assert_equal (atom 1) (head c) "cell head"; + assert_equal (atom 2) (tail c) "cell tail"; + + (* Test is_cell and is_atom *) + if not (is_atom a) then Printf.printf "FAIL: is_atom on atom\n" else Printf.printf "PASS: is_atom on atom\n"; + if not (is_cell c) then Printf.printf "FAIL: is_cell on cell\n" else Printf.printf "PASS: is_cell on cell\n"; + if is_atom c then Printf.printf "FAIL: not is_atom on cell\n" else Printf.printf "PASS: not is_atom on cell\n"; + if is_cell a then Printf.printf "FAIL: not is_cell on atom\n" else Printf.printf "PASS: not is_cell on atom\n" + +(** Test slot/fragment addressing *) +let test_slots () = + Printf.printf "\n=== Testing slot/fragment addressing ===\n"; + + (* Build tree: [[1 2] [3 4]] *) + let tree = cell (cell (atom 1) (atom 2)) (cell (atom 3) (atom 4)) in + + (* Test slot addressing + 1 = whole tree + 2 = head = [1 2] + 3 = tail = [3 4] + 4 = head of head = 1 + 5 = tail of head = 2 + 6 = head of tail = 3 + 7 = tail of tail = 4 + *) + assert_equal tree (slot Z.one tree) "slot 1 (root)"; + assert_equal (cell (atom 1) (atom 2)) (slot (Z.of_int 2) tree) "slot 2 (head)"; + assert_equal (cell (atom 3) (atom 4)) (slot (Z.of_int 3) tree) "slot 3 (tail)"; + assert_equal (atom 1) (slot (Z.of_int 4) tree) "slot 4"; + assert_equal (atom 2) (slot (Z.of_int 5) tree) "slot 5"; + assert_equal (atom 3) (slot (Z.of_int 6) tree) "slot 6"; + assert_equal (atom 4) (slot (Z.of_int 7) tree) "slot 7" + +(** Test Nock opcode 0: slot lookup *) +let test_nock_0 () = + Printf.printf "\n=== Testing Nock opcode 0 (slot) ===\n"; + + let subject = cell (atom 4) (atom 5) in + + (* *[subject [0 1]] = subject *) + assert_equal subject (nock subject (cell (atom 0) (atom 1))) "nock 0: axis 1"; + + (* *[[4 5] [0 2]] = 4 *) + assert_equal (atom 4) (nock subject (cell (atom 0) (atom 2))) "nock 0: axis 2"; + + (* *[[4 5] [0 3]] = 5 *) + assert_equal (atom 5) (nock subject (cell (atom 0) (atom 3))) "nock 0: axis 3" + +(** Test Nock opcode 1: constant *) +let test_nock_1 () = + Printf.printf "\n=== Testing Nock opcode 1 (constant) ===\n"; + + let subject = atom 99 in + + (* *[subject [1 42]] = 42 *) + assert_equal (atom 42) (nock subject (cell (atom 1) (atom 42))) "nock 1: return constant"; + + (* *[subject [1 [1 2]]] = [1 2] *) + assert_equal + (cell (atom 1) (atom 2)) + (nock subject (cell (atom 1) (cell (atom 1) (atom 2)))) + "nock 1: return constant cell" + +(** Test Nock opcode 2: recursion *) +let test_nock_2 () = + Printf.printf "\n=== Testing Nock opcode 2 (nock) ===\n"; + + (* *[42 [2 [0 1] [1 0]]] = *[42 0] = crash *) + (* *[42 [2 [1 99] [1 0 1]]] = *[99 [0 1]] = 99 *) + let subject = atom 42 in + let formula = cell (atom 2) (cell (cell (atom 1) (atom 99)) (cell (atom 1) (cell (atom 0) (atom 1)))) in + assert_equal (atom 99) (nock subject formula) "nock 2: evaluate with new subject" + +(** Test Nock opcode 3: is-cell *) +let test_nock_3 () = + Printf.printf "\n=== Testing Nock opcode 3 (is-cell) ===\n"; + + (* *[42 [3 1 42]] = 1 (atom) *) + assert_equal (atom 1) (nock (atom 42) (cell (atom 3) (cell (atom 1) (atom 42)))) "nock 3: is-cell of atom"; + + (* *[42 [3 1 [1 2]]] = 0 (cell) *) + assert_equal + (atom 0) + (nock (atom 42) (cell (atom 3) (cell (atom 1) (cell (atom 1) (atom 2))))) + "nock 3: is-cell of cell" + +(** Test Nock opcode 4: increment *) +let test_nock_4 () = + Printf.printf "\n=== Testing Nock opcode 4 (increment) ===\n"; + + (* *[42 [4 1 41]] = 42 *) + assert_equal (atom 42) (nock (atom 0) (cell (atom 4) (cell (atom 1) (atom 41)))) "nock 4: increment"; + + (* *[0 [4 0 1]] = 1 *) + assert_equal (atom 1) (nock (atom 0) (cell (atom 4) (cell (atom 0) (atom 1)))) "nock 4: increment subject" + +(** Test Nock opcode 5: equality *) +let test_nock_5 () = + Printf.printf "\n=== Testing Nock opcode 5 (equality) ===\n"; + + (* *[0 [5 [1 4] [1 5]]] = 1 (not equal) *) + assert_equal + (atom 1) + (nock (atom 0) (cell (atom 5) (cell (cell (atom 1) (atom 4)) (cell (atom 1) (atom 5))))) + "nock 5: not equal"; + + (* *[0 [5 [1 4] [1 4]]] = 0 (equal) *) + assert_equal + (atom 0) + (nock (atom 0) (cell (atom 5) (cell (cell (atom 1) (atom 4)) (cell (atom 1) (atom 4))))) + "nock 5: equal" + +(** Test Nock opcode 6: if-then-else *) +let test_nock_6 () = + Printf.printf "\n=== Testing Nock opcode 6 (if-then-else) ===\n"; + + (* *[42 [6 [1 0] [1 11] [1 22]]] = 11 (if 0 then 11 else 22) *) + assert_equal + (atom 11) + (nock (atom 42) (cell (atom 6) (cell (cell (atom 1) (atom 0)) (cell (cell (atom 1) (atom 11)) (cell (atom 1) (atom 22)))))) + "nock 6: if true"; + + (* *[42 [6 [1 1] [1 11] [1 22]]] = 22 (if 1 then 11 else 22) *) + assert_equal + (atom 22) + (nock (atom 42) (cell (atom 6) (cell (cell (atom 1) (atom 1)) (cell (cell (atom 1) (atom 11)) (cell (atom 1) (atom 22)))))) + "nock 6: if false" + +(** Test Nock opcode 7: composition *) +let test_nock_7 () = + Printf.printf "\n=== Testing Nock opcode 7 (composition) ===\n"; + + (* *[42 [7 [1 99] [0 1]]] = *[99 [0 1]] = 99 *) + assert_equal + (atom 99) + (nock (atom 42) (cell (atom 7) (cell (cell (atom 1) (atom 99)) (cell (atom 0) (atom 1))))) + "nock 7: composition" + +(** Test Nock opcode 8: push *) +let test_nock_8 () = + Printf.printf "\n=== Testing Nock opcode 8 (push) ===\n"; + + (* *[42 [8 [1 99] [0 1]]] = *[[99 42] [0 1]] = [99 42] *) + assert_equal + (cell (atom 99) (atom 42)) + (nock (atom 42) (cell (atom 8) (cell (cell (atom 1) (atom 99)) (cell (atom 0) (atom 1))))) + "nock 8: push" + +(** Test Nock opcode 9: call *) +let test_nock_9 () = + Printf.printf "\n=== Testing Nock opcode 9 (call) ===\n"; + + (* Simplest test: *[42 [9 1 [0 1]]] + = evaluate [0 1] with 42 -> 42 + = slot 1 of 42 -> 42 + = *[42 42] -> should crash since 42 is not a valid formula + + Better test: create subject with formula at position 3 + *[[formula value] [9 2 [0 1]]] + where formula = [0 3] (get tail) + + Actually: *[[1 2] [9 2 [1 [0 3]]]] + = evaluate [1 [0 3]] with [1 2] -> [0 3] + = slot 2 of [1 2] -> 1 + + Wait, that's wrong. Let me think about what 9 does: + *[subject [9 axis formula]] + = *[subject *[*[subject formula] axis]] + + So: *[[1 2] [9 3 [0 1]]] + = *[*[[1 2] [0 1]] 3] + = *[[1 2] 3] + = slot 3 of [1 2] + = 2 + + But that's not right either. Let me re-read the spec. + + Actually from the C code: + seb = nock(bus, c_gal) + nex = slot(b_gal, seb) + result = nock(seb, nex) + + So for [9 b c]: + 1. Evaluate c with subject -> seb + 2. Get slot b from seb -> nex (this is the formula) + 3. Evaluate nex with seb as subject + + Test: *[[99 [4 [0 2]]] [9 3 [0 1]]] + 1. seb = *[[99 [4 [0 2]]] [0 1]] = [99 [4 [0 2]]] + 2. nex = slot 3 of [99 [4 [0 2]]] = [4 [0 2]] + 3. result = *[[99 [4 [0 2]]] [4 [0 2]]] + = increment of *[[99 [4 [0 2]]] [0 2]] + = increment of 99 + = 100 + *) + let subj = cell (atom 99) (cell (atom 4) (cell (atom 0) (atom 2))) in + assert_equal + (atom 100) + (nock subj (cell (atom 9) (cell (atom 3) (cell (atom 0) (atom 1))))) + "nock 9: call formula at axis 3" + +(** Test Nock opcode 10: hint *) +let test_nock_10 () = + Printf.printf "\n=== Testing Nock opcode 10 (hint) ===\n"; + + (* *[42 [10 99 [1 11]]] = 11 (hint ignored) *) + assert_equal + (atom 11) + (nock (atom 42) (cell (atom 10) (cell (atom 99) (cell (atom 1) (atom 11))))) + "nock 10: hint with value (ignored)"; + + (* *[42 [10 [99 [1 88]] [1 11]]] = 11 (hint ignored) *) + assert_equal + (atom 11) + (nock (atom 42) (cell (atom 10) (cell (cell (atom 99) (cell (atom 1) (atom 88))) (cell (atom 1) (atom 11))))) + "nock 10: hint with computed value (ignored)" + +(** Test Nock cell constructor shorthand *) +let test_nock_cons () = + Printf.printf "\n=== Testing Nock cons (cell auto-construction) ===\n"; + + (* *[42 [[1 6] [1 7]]] = [6 7] *) + assert_equal + (cell (atom 6) (atom 7)) + (nock (atom 42) (cell (cell (atom 1) (atom 6)) (cell (atom 1) (atom 7)))) + "nock cons: [[1 6] [1 7]]" + +(** Run all tests *) +let () = + Printf.printf "=================================\n"; + Printf.printf "Nock OCaml Test Suite\n"; + Printf.printf "=================================\n"; + + test_noun_basics (); + test_slots (); + test_nock_0 (); + test_nock_1 (); + test_nock_2 (); + test_nock_3 (); + test_nock_4 (); + test_nock_5 (); + test_nock_6 (); + test_nock_7 (); + test_nock_8 (); + test_nock_9 (); + test_nock_10 (); + test_nock_cons (); + + Printf.printf "\n=================================\n"; + Printf.printf "All tests passed!\n"; + Printf.printf "=================================\n" diff --git a/ocaml/test/test_serial.ml b/ocaml/test/test_serial.ml new file mode 100644 index 0000000..fca30f8 --- /dev/null +++ b/ocaml/test/test_serial.ml @@ -0,0 +1,185 @@ +open Nock_lib.Noun +open Nock_lib.Serial + +(** Test utilities *) + +let assert_equal expected actual msg = + if not (equal expected actual) then begin + Printf.printf "FAIL: %s\n" msg; + Format.printf " Expected: %a@." pp_noun expected; + Format.printf " Actual: %a@." pp_noun actual; + exit 1 + end else + Printf.printf "PASS: %s\n" msg + +let _assert_bytes_equal expected actual msg = + if expected <> actual then begin + Printf.printf "FAIL: %s\n" msg; + Printf.printf " Expected: %s\n" (bytes_to_hex expected); + Printf.printf " Actual: %s\n" (bytes_to_hex actual); + exit 1 + end else + Printf.printf "PASS: %s\n" msg + +(** Round-trip test: jam then cue should give original *) +let test_roundtrip noun msg = + let jammed = jam noun in + let cued = cue jammed in + assert_equal noun cued msg + +(** Test basic atoms *) +let test_atoms () = + Printf.printf "\n=== Testing atom serialization ===\n"; + + (* Test 0 *) + let n = atom 0 in + test_roundtrip n "atom 0 roundtrip"; + + (* Test small atoms *) + test_roundtrip (atom 1) "atom 1 roundtrip"; + test_roundtrip (atom 2) "atom 2 roundtrip"; + test_roundtrip (atom 42) "atom 42 roundtrip"; + test_roundtrip (atom 255) "atom 255 roundtrip"; + test_roundtrip (atom 256) "atom 256 roundtrip"; + + (* Test larger atoms *) + test_roundtrip (atom 65535) "atom 65535 roundtrip"; + test_roundtrip (atom 1000000) "atom 1000000 roundtrip" + +(** Test basic cells *) +let test_cells () = + Printf.printf "\n=== Testing cell serialization ===\n"; + + (* Simple cell [1 2] *) + let c = cell (atom 1) (atom 2) in + test_roundtrip c "cell [1 2] roundtrip"; + + (* Nested cells [[1 2] 3] *) + let c = cell (cell (atom 1) (atom 2)) (atom 3) in + test_roundtrip c "cell [[1 2] 3] roundtrip"; + + (* Deep nesting *) + let c = cell (cell (cell (atom 1) (atom 2)) (atom 3)) (atom 4) in + test_roundtrip c "cell [[[1 2] 3] 4] roundtrip"; + + (* Larger values *) + let c = cell (atom 1000) (atom 2000) in + test_roundtrip c "cell [1000 2000] roundtrip" + +(** Test trees *) +let test_trees () = + Printf.printf "\n=== Testing tree serialization ===\n"; + + (* Binary tree *) + let tree = cell (cell (atom 1) (atom 2)) (cell (atom 3) (atom 4)) in + test_roundtrip tree "binary tree roundtrip"; + + (* Unbalanced tree *) + let tree = cell (atom 1) (cell (atom 2) (cell (atom 3) (atom 4))) in + test_roundtrip tree "right-leaning tree roundtrip"; + + (* List-like structure [1 [2 [3 0]]] *) + let list = cell (atom 1) (cell (atom 2) (cell (atom 3) (atom 0))) in + test_roundtrip list "list-like structure roundtrip" + +(** Test backreferences + + When the same sub-noun appears multiple times, jam should use backreferences +*) +let test_backrefs () = + Printf.printf "\n=== Testing backreferences ===\n"; + + (* Create a noun with shared structure: [42 42] + The second 42 should be a backref to the first *) + let shared = atom 42 in + let n = cell shared shared in + test_roundtrip n "shared atom [42 42] roundtrip"; + + (* More complex sharing: [[1 2] [1 2]] + Second cell should backref to first *) + let sub = cell (atom 1) (atom 2) in + let n = cell sub sub in + test_roundtrip n "shared cell [[1 2] [1 2]] roundtrip"; + + (* Test that backrefs actually save space *) + let sub = cell (atom 100) (atom 200) in + let with_backref = cell sub sub in + let without_backref = cell (cell (atom 100) (atom 200)) (cell (atom 100) (atom 200)) in + + let jammed_with = jam with_backref in + let jammed_without = jam without_backref in + + Printf.printf " Shared structure size: %d bytes\n" (Bytes.length jammed_with); + Printf.printf " Duplicated structure size: %d bytes\n" (Bytes.length jammed_without); + + (* Note: Due to how OCaml constructs values, physical equality might not work as expected, + but logical equality should still work for roundtrip *) + test_roundtrip with_backref "backref optimization roundtrip" + +(** Test known encodings + + These test vectors would ideally come from the Vere test suite or Urbit dojo +*) +let test_known_encodings () = + Printf.printf "\n=== Testing known encodings ===\n"; + + (* We can generate these from Urbit with (jam 0), (jam 1), etc. *) + + (* jam of 0 should be simple *) + let n = atom 0 in + let jammed = jam n in + Printf.printf " jam(0) = %s (%d bytes)\n" (bytes_to_hex jammed) (Bytes.length jammed); + test_roundtrip n "known encoding: 0"; + + (* jam of 1 *) + let n = atom 1 in + let jammed = jam n in + Printf.printf " jam(1) = %s (%d bytes)\n" (bytes_to_hex jammed) (Bytes.length jammed); + test_roundtrip n "known encoding: 1"; + + (* jam of [0 0] *) + let n = cell (atom 0) (atom 0) in + let jammed = jam n in + Printf.printf " jam([0 0]) = %s (%d bytes)\n" (bytes_to_hex jammed) (Bytes.length jammed); + test_roundtrip n "known encoding: [0 0]" + +(** Test edge cases *) +let test_edge_cases () = + Printf.printf "\n=== Testing edge cases ===\n"; + + (* Very large atom *) + let big = Atom (Z.of_string "123456789012345678901234567890") in + test_roundtrip big "very large atom roundtrip"; + + (* Deep nesting *) + let rec make_deep n = + if n = 0 then atom 0 + else cell (atom n) (make_deep (n - 1)) + in + let deep = make_deep 50 in + test_roundtrip deep "deeply nested structure (50 levels) roundtrip"; + + (* Wide tree *) + let rec make_wide n = + if n = 0 then atom 0 + else cell (make_wide (n - 1)) (make_wide (n - 1)) + in + let wide = make_wide 6 in (* 2^6 = 64 leaves *) + test_roundtrip wide "wide binary tree (6 levels) roundtrip" + +(** Run all tests *) +let () = + Printf.printf "=================================\n"; + Printf.printf "Jam/Cue Serialization Test Suite\n"; + Printf.printf "=================================\n"; + + test_atoms (); + test_cells (); + test_trees (); + test_backrefs (); + test_known_encodings (); + test_edge_cases (); + + Printf.printf "\n=================================\n"; + Printf.printf "All tests passed!\n"; + Printf.printf "=================================\n" |