diff --git a/src/cbor/tests/appendix_a.json b/src/cbor/tests/appendix_a.json new file mode 100644 index 00000000..037ddd07 --- /dev/null +++ b/src/cbor/tests/appendix_a.json @@ -0,0 +1,638 @@ + +[ + { + "cbor": "AA==", + "hex": "00", + "roundtrip": true, + "decoded": 0 + }, + { + "cbor": "AQ==", + "hex": "01", + "roundtrip": true, + "decoded": 1 + }, + { + "cbor": "Cg==", + "hex": "0a", + "roundtrip": true, + "decoded": 10 + }, + { + "cbor": "Fw==", + "hex": "17", + "roundtrip": true, + "decoded": 23 + }, + { + "cbor": "GBg=", + "hex": "1818", + "roundtrip": true, + "decoded": 24 + }, + { + "cbor": "GBk=", + "hex": "1819", + "roundtrip": true, + "decoded": 25 + }, + { + "cbor": "GGQ=", + "hex": "1864", + "roundtrip": true, + "decoded": 100 + }, + { + "cbor": "GQPo", + "hex": "1903e8", + "roundtrip": true, + "decoded": 1000 + }, + { + "cbor": "GgAPQkA=", + "hex": "1a000f4240", + "roundtrip": true, + "decoded": 1000000 + }, + { + "cbor": "GwAAAOjUpRAA", + "hex": "1b000000e8d4a51000", + "roundtrip": true, + "decoded": 1000000000000 + }, + { + "cbor": "G///////////", + "hex": "1bffffffffffffffff", + "roundtrip": true, + "decoded": 18446744073709551615 + }, + { + "cbor": "wkkBAAAAAAAAAAA=", + "hex": "c249010000000000000000", + "roundtrip": true, + "decoded": 18446744073709551616 + }, + { + "cbor": "O///////////", + "hex": "3bffffffffffffffff", + "roundtrip": true, + "decoded": -18446744073709551616 + }, + { + "cbor": "w0kBAAAAAAAAAAA=", + "hex": "c349010000000000000000", + "roundtrip": true, + "decoded": -18446744073709551617 + }, + { + "cbor": "IA==", + "hex": "20", + "roundtrip": true, + "decoded": -1 + }, + { + "cbor": "KQ==", + "hex": "29", + "roundtrip": true, + "decoded": -10 + }, + { + "cbor": "OGM=", + "hex": "3863", + "roundtrip": true, + "decoded": -100 + }, + { + "cbor": "OQPn", + "hex": "3903e7", + "roundtrip": true, + "decoded": -1000 + }, + { + "cbor": "+QAA", + "hex": "f90000", + "roundtrip": true, + "decoded": 0.0 + }, + { + "cbor": "+YAA", + "hex": "f98000", + "roundtrip": true, + "decoded": -0.0 + }, + { + "cbor": "+TwA", + "hex": "f93c00", + "roundtrip": true, + "decoded": 1.0 + }, + { + "cbor": "+z/xmZmZmZma", + "hex": "fb3ff199999999999a", + "roundtrip": true, + "decoded": 1.1 + }, + { + "cbor": "+T4A", + "hex": "f93e00", + "roundtrip": true, + "decoded": 1.5 + }, + { + "cbor": "+Xv/", + "hex": "f97bff", + "roundtrip": true, + "decoded": 65504.0 + }, + { + "cbor": "+kfDUAA=", + "hex": "fa47c35000", + "roundtrip": true, + "decoded": 100000.0 + }, + { + "cbor": "+n9///8=", + "hex": "fa7f7fffff", + "roundtrip": true, + "decoded": 3.4028234663852886e+38 + }, + { + "cbor": "+3435DyIAHWc", + "hex": "fb7e37e43c8800759c", + "roundtrip": true, + "decoded": 1.0e+300 + }, + { + "cbor": "+QAB", + "hex": "f90001", + "roundtrip": true, + "decoded": 5.960464477539063e-08 + }, + { + "cbor": "+QQA", + "hex": "f90400", + "roundtrip": true, + "decoded": 6.103515625e-05 + }, + { + "cbor": "+cQA", + "hex": "f9c400", + "roundtrip": true, + "decoded": -4.0 + }, + { + "cbor": "+8AQZmZmZmZm", + "hex": "fbc010666666666666", + "roundtrip": true, + "decoded": -4.1 + }, + { + "cbor": "+XwA", + "hex": "f97c00", + "roundtrip": true, + "diagnostic": "Infinity" + }, + { + "cbor": "+X4A", + "hex": "f97e00", + "roundtrip": true, + "diagnostic": "NaN" + }, + { + "cbor": "+fwA", + "hex": "f9fc00", + "roundtrip": true, + "diagnostic": "-Infinity" + }, + { + "cbor": "+n+AAAA=", + "hex": "fa7f800000", + "roundtrip": false, + "diagnostic": "Infinity" + }, + { + "cbor": "+n/AAAA=", + "hex": "fa7fc00000", + "roundtrip": false, + "diagnostic": "NaN" + }, + { + "cbor": "+v+AAAA=", + "hex": "faff800000", + "roundtrip": false, + "diagnostic": "-Infinity" + }, + { + "cbor": "+3/wAAAAAAAA", + "hex": "fb7ff0000000000000", + "roundtrip": false, + "diagnostic": "Infinity" + }, + { + "cbor": "+3/4AAAAAAAA", + "hex": "fb7ff8000000000000", + "roundtrip": false, + "diagnostic": "NaN" + }, + { + "cbor": "+//wAAAAAAAA", + "hex": "fbfff0000000000000", + "roundtrip": false, + "diagnostic": "-Infinity" + }, + { + "cbor": "9A==", + "hex": "f4", + "roundtrip": true, + "decoded": false + }, + { + "cbor": "9Q==", + "hex": "f5", + "roundtrip": true, + "decoded": true + }, + { + "cbor": "9g==", + "hex": "f6", + "roundtrip": true, + "decoded": null + }, + { + "cbor": "9w==", + "hex": "f7", + "roundtrip": true, + "diagnostic": "undefined" + }, + { + "cbor": "8A==", + "hex": "f0", + "roundtrip": true, + "diagnostic": "simple(16)" + }, + { + "cbor": "+Bg=", + "hex": "f818", + "roundtrip": true, + "diagnostic": "simple(24)" + }, + { + "cbor": "+P8=", + "hex": "f8ff", + "roundtrip": true, + "diagnostic": "simple(255)" + }, + { + "cbor": "wHQyMDEzLTAzLTIxVDIwOjA0OjAwWg==", + "hex": "c074323031332d30332d32315432303a30343a30305a", + "roundtrip": true, + "diagnostic": "0(\"2013-03-21T20:04:00Z\")" + }, + { + "cbor": "wRpRS2ew", + "hex": "c11a514b67b0", + "roundtrip": true, + "diagnostic": "1(1363896240)" + }, + { + "cbor": "wftB1FLZ7CAAAA==", + "hex": "c1fb41d452d9ec200000", + "roundtrip": true, + "diagnostic": "1(1363896240.5)" + }, + { + "cbor": "10QBAgME", + "hex": "d74401020304", + "roundtrip": true, + "diagnostic": "23(h'01020304')" + }, + { + "cbor": "2BhFZElFVEY=", + "hex": "d818456449455446", + "roundtrip": true, + "diagnostic": "24(h'6449455446')" + }, + { + "cbor": "2CB2aHR0cDovL3d3dy5leGFtcGxlLmNvbQ==", + "hex": "d82076687474703a2f2f7777772e6578616d706c652e636f6d", + "roundtrip": true, + "diagnostic": "32(\"http://www.example.com\")" + }, + { + "cbor": "QA==", + "hex": "40", + "roundtrip": true, + "diagnostic": "h''" + }, + { + "cbor": "RAECAwQ=", + "hex": "4401020304", + "roundtrip": true, + "diagnostic": "h'01020304'" + }, + { + "cbor": "YA==", + "hex": "60", + "roundtrip": true, + "decoded": "" + }, + { + "cbor": "YWE=", + "hex": "6161", + "roundtrip": true, + "decoded": "a" + }, + { + "cbor": "ZElFVEY=", + "hex": "6449455446", + "roundtrip": true, + "decoded": "IETF" + }, + { + "cbor": "YiJc", + "hex": "62225c", + "roundtrip": true, + "decoded": "\"\\" + }, + { + "cbor": "YsO8", + "hex": "62c3bc", + "roundtrip": true, + "decoded": "ü" + }, + { + "cbor": "Y+awtA==", + "hex": "63e6b0b4", + "roundtrip": true, + "decoded": "水" + }, + { + "cbor": "ZPCQhZE=", + "hex": "64f0908591", + "roundtrip": true, + "decoded": "𐅑" + }, + { + "cbor": "gA==", + "hex": "80", + "roundtrip": true, + "decoded": [ + + ] + }, + { + "cbor": "gwECAw==", + "hex": "83010203", + "roundtrip": true, + "decoded": [ + 1, + 2, + 3 + ] + }, + { + "cbor": "gwGCAgOCBAU=", + "hex": "8301820203820405", + "roundtrip": true, + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "cbor": "mBkBAgMEBQYHCAkKCwwNDg8QERITFBUWFxgYGBk=", + "hex": "98190102030405060708090a0b0c0d0e0f101112131415161718181819", + "roundtrip": true, + "decoded": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ] + }, + { + "cbor": "oA==", + "hex": "a0", + "roundtrip": true, + "decoded": { + } + }, + { + "cbor": "ogECAwQ=", + "hex": "a201020304", + "roundtrip": true, + "diagnostic": "{1: 2, 3: 4}" + }, + { + "cbor": "omFhAWFiggID", + "hex": "a26161016162820203", + "roundtrip": true, + "decoded": { + "a": 1, + "b": [ + 2, + 3 + ] + } + }, + { + "cbor": "gmFhoWFiYWM=", + "hex": "826161a161626163", + "roundtrip": true, + "decoded": [ + "a", + { + "b": "c" + } + ] + }, + { + "cbor": "pWFhYUFhYmFCYWNhQ2FkYURhZWFF", + "hex": "a56161614161626142616361436164614461656145", + "roundtrip": true, + "decoded": { + "a": "A", + "b": "B", + "c": "C", + "d": "D", + "e": "E" + } + }, + { + "cbor": "X0IBAkMDBAX/", + "hex": "5f42010243030405ff", + "roundtrip": false, + "diagnostic": "(_ h'0102', h'030405')" + }, + { + "cbor": "f2VzdHJlYWRtaW5n/w==", + "hex": "7f657374726561646d696e67ff", + "roundtrip": false, + "decoded": "streaming" + }, + { + "cbor": "n/8=", + "hex": "9fff", + "roundtrip": false, + "decoded": [ + + ] + }, + { + "cbor": "nwGCAgOfBAX//w==", + "hex": "9f018202039f0405ffff", + "roundtrip": false, + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "cbor": "nwGCAgOCBAX/", + "hex": "9f01820203820405ff", + "roundtrip": false, + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "cbor": "gwGCAgOfBAX/", + "hex": "83018202039f0405ff", + "roundtrip": false, + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "cbor": "gwGfAgP/ggQF", + "hex": "83019f0203ff820405", + "roundtrip": false, + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "cbor": "nwECAwQFBgcICQoLDA0ODxAREhMUFRYXGBgYGf8=", + "hex": "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff", + "roundtrip": false, + "decoded": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ] + }, + { + "cbor": "v2FhAWFinwID//8=", + "hex": "bf61610161629f0203ffff", + "roundtrip": false, + "decoded": { + "a": 1, + "b": [ + 2, + 3 + ] + } + }, + { + "cbor": "gmFhv2FiYWP/", + "hex": "826161bf61626163ff", + "roundtrip": false, + "decoded": [ + "a", + { + "b": "c" + } + ] + }, + { + "cbor": "v2NGdW71Y0FtdCH/", + "hex": "bf6346756ef563416d7421ff", + "roundtrip": false, + "decoded": { + "Fun": true, + "Amt": -2 + } + } +] + diff --git a/src/cbor/tests/dune b/src/cbor/tests/dune new file mode 100644 index 00000000..5a03065e --- /dev/null +++ b/src/cbor/tests/dune @@ -0,0 +1,13 @@ +(executable + (name t_appendix_a) + (libraries yojson containers containers.cbor)) + +(rule + (targets t_appendix_a.out) + (action + (with-stdout-to %{targets} + (run ./t_appendix_a.exe ./appendix_a.json)))) + +(rule + (alias runtest) + (action (diff ./t_appendix_a.expected ./t_appendix_a.out))) diff --git a/src/cbor/tests/t_appendix_a.expected b/src/cbor/tests/t_appendix_a.expected new file mode 100644 index 00000000..6fc06cac --- /dev/null +++ b/src/cbor/tests/t_appendix_a.expected @@ -0,0 +1,322 @@ + decoded into 0 +> RUN test "00" + roundtrip ok + expect: OK + decoded into 1 +> RUN test "01" + roundtrip ok + expect: OK + decoded into 10 +> RUN test "0a" + roundtrip ok + expect: OK + decoded into 23 +> RUN test "17" + roundtrip ok + expect: OK + decoded into 24 +> RUN test "1818" + roundtrip ok + expect: OK + decoded into 25 +> RUN test "1819" + roundtrip ok + expect: OK + decoded into 100 +> RUN test "1864" + roundtrip ok + expect: OK + decoded into 1000 +> RUN test "1903e8" + roundtrip ok + expect: OK + decoded into 1000000 +> RUN test "1a000f4240" + roundtrip ok + expect: OK + decoded into 1000000000000 +> RUN test "1b000000e8d4a51000" + roundtrip ok + expect: OK + decoded into -1 +> SKIP "1bffffffffffffffff" (reason: (requires int64 loss of precision)) + decoded into 2(h'010000000000000000') +> SKIP "c249010000000000000000" (reason: (bigint)) + decoded into 0 +> SKIP "3bffffffffffffffff" (reason: (requires int64, loss of precision)) + decoded into 3(h'010000000000000000') +> RUN test "c349010000000000000000" + roundtrip ok + TODO: compare with `Intlit ("-18446744073709551617") + expect: OK + decoded into -1 +> RUN test "20" + roundtrip ok + expect: OK + decoded into -10 +> RUN test "29" + roundtrip ok + expect: OK + decoded into -100 +> RUN test "3863" + roundtrip ok + expect: OK + decoded into -1000 +> RUN test "3903e7" + roundtrip ok + expect: OK + decoded into 0. +> RUN test "f90000" + TODO: compare with `Float (0.) + expect: OK + decoded into -0. +> RUN test "f98000" + TODO: compare with `Float (-0.) + expect: OK + decoded into 1. +> RUN test "f93c00" + TODO: compare with `Float (1.) + expect: OK + decoded into 1.1 +> RUN test "fb3ff199999999999a" + TODO: compare with `Float (1.1) + expect: OK + decoded into 1.5 +> RUN test "f93e00" + TODO: compare with `Float (1.5) + expect: OK + decoded into 65504. +> RUN test "f97bff" + TODO: compare with `Float (65504.) + expect: OK + decoded into 100000. +> RUN test "fa47c35000" + TODO: compare with `Float (100000.) + expect: OK + decoded into 3.40282346639e+38 +> RUN test "fa7f7fffff" + TODO: compare with `Float (3.40282346639e+38) + expect: OK + decoded into 1e+300 +> RUN test "fb7e37e43c8800759c" + TODO: compare with `Float (1e+300) + expect: OK + decoded into 5.96046447754e-08 +> RUN test "f90001" + TODO: compare with `Float (5.96046447754e-08) + expect: OK + decoded into 6.103515625e-05 +> RUN test "f90400" + TODO: compare with `Float (6.103515625e-05) + expect: OK + decoded into -4. +> RUN test "f9c400" + TODO: compare with `Float (-4.) + expect: OK + decoded into -4.1 +> RUN test "fbc010666666666666" + TODO: compare with `Float (-4.1) + expect: OK + decoded into inf +> RUN test "f97c00" + OK + decoded into nan +> RUN test "f97e00" + OK + decoded into -inf +> RUN test "f9fc00" + OK + decoded into inf +> RUN test "fa7f800000" + OK + decoded into nan +> RUN test "fa7fc00000" + OK + decoded into -inf +> RUN test "faff800000" + OK + decoded into inf +> RUN test "fb7ff0000000000000" + OK + decoded into nan +> RUN test "fb7ff8000000000000" + OK + decoded into -inf +> RUN test "fbfff0000000000000" + OK + decoded into false +> RUN test "f4" + roundtrip ok + TODO: compare with `Bool (false) + expect: OK + decoded into true +> RUN test "f5" + roundtrip ok + TODO: compare with `Bool (true) + expect: OK + decoded into null +> RUN test "f6" + roundtrip ok + TODO: compare with `Null + expect: OK + decoded into undefined +> RUN test "f7" + roundtrip ok + OK + decoded into simple(16) +> RUN test "f0" + roundtrip ok + OK + decoded into simple(24) +> RUN test "f818" + roundtrip ok + OK + decoded into simple(255) +> RUN test "f8ff" + roundtrip ok + OK + decoded into 0("2013-03-21T20:04:00Z") +> RUN test "c074323031332d30332d32315432303a30343a30305a" + roundtrip ok + OK + decoded into 1(1363896240) +> RUN test "c11a514b67b0" + roundtrip ok + OK + decoded into 1(1363896240.5) +> RUN test "c1fb41d452d9ec200000" + roundtrip ok + OK + decoded into 23(h'01020304') +> RUN test "d74401020304" + roundtrip ok + OK + decoded into 24(h'6449455446') +> RUN test "d818456449455446" + roundtrip ok + OK + decoded into 32("http://www.example.com") +> RUN test "d82076687474703a2f2f7777772e6578616d706c652e636f6d" + roundtrip ok + OK + decoded into h'' +> RUN test "40" + roundtrip ok + OK + decoded into h'01020304' +> RUN test "4401020304" + roundtrip ok + OK + decoded into "" +> RUN test "60" + roundtrip ok + expect: OK + decoded into "a" +> RUN test "6161" + roundtrip ok + expect: OK + decoded into "IETF" +> RUN test "6449455446" + roundtrip ok + expect: OK + decoded into "\"\\" +> RUN test "62225c" + roundtrip ok + expect: OK + decoded into "\195\188" +> RUN test "62c3bc" + roundtrip ok + expect: OK + decoded into "\230\176\180" +> RUN test "63e6b0b4" + roundtrip ok + expect: OK + decoded into "\240\144\133\145" +> RUN test "64f0908591" + roundtrip ok + expect: OK + decoded into [] +> RUN test "80" + roundtrip ok + expect: OK + decoded into [1, 2, 3] +> RUN test "83010203" + roundtrip ok + expect: OK + decoded into [1, [2, 3], [4, 5]] +> RUN test "8301820203820405" + roundtrip ok + expect: OK + decoded into [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25] +> RUN test "98190102030405060708090a0b0c0d0e0f101112131415161718181819" + roundtrip ok + expect: OK + decoded into {} +> RUN test "a0" + roundtrip ok + TODO: compare with `Assoc ([]) + expect: OK + decoded into {1: 2, 3: 4} +> RUN test "a201020304" + roundtrip ok + OK + decoded into {"a": 1, "b": [2, 3]} +> RUN test "a26161016162820203" + roundtrip ok + TODO: compare with `Assoc ([("a", `Int (1)); + ("b", `List ([`Int (2); `Int (3)]))]) + expect: OK + decoded into ["a", {"b": "c"}] +> RUN test "826161a161626163" + roundtrip ok + TODO: compare with `Assoc ([("b", `String ("c"))]) + expect: OK + decoded into {"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"} +> RUN test "a56161614161626142616361436164614461656145" + roundtrip ok + TODO: compare with `Assoc ([("a", `String ("A")); ("b", `String ("B")); + ("c", `String ("C")); ("d", `String ("D")); + ("e", `String ("E"))]) + expect: OK + decoded into h'0102030405' +> SKIP "5f42010243030405ff" (reason: (requires representation of indefinite length)) + decoded into "streaming" +> RUN test "7f657374726561646d696e67ff" + expect: OK + decoded into [] +> RUN test "9fff" + expect: OK + decoded into [1, [2, 3], [4, 5]] +> RUN test "9f018202039f0405ffff" + expect: OK + decoded into [1, [2, 3], [4, 5]] +> RUN test "9f01820203820405ff" + expect: OK + decoded into [1, [2, 3], [4, 5]] +> RUN test "83018202039f0405ff" + expect: OK + decoded into [1, [2, 3], [4, 5]] +> RUN test "83019f0203ff820405" + expect: OK + decoded into [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25] +> RUN test "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff" + expect: OK + decoded into {"a": 1, "b": [2, 3]} +> RUN test "bf61610161629f0203ffff" + TODO: compare with `Assoc ([("a", `Int (1)); + ("b", `List ([`Int (2); `Int (3)]))]) + expect: OK + decoded into ["a", {"b": "c"}] +> RUN test "826161bf61626163ff" + TODO: compare with `Assoc ([("b", `String ("c"))]) + expect: OK + decoded into {"Fun": true, "Amt": -2} +> RUN test "bf6346756ef563416d7421ff" + TODO: compare with `Assoc ([("Fun", `Bool (true)); ("Amt", `Int (-2))]) + expect: OK + + +##### +OK: 78 ok, 4 skip diff --git a/src/cbor/tests/t_appendix_a.ml b/src/cbor/tests/t_appendix_a.ml new file mode 100644 index 00000000..47f662bc --- /dev/null +++ b/src/cbor/tests/t_appendix_a.ml @@ -0,0 +1,163 @@ +module J = Yojson.Safe +module Fmt = CCFormat +module Cbor = Containers_cbor + +type json = Yojson.Safe.t + +let pp_json = J.pretty_print ~std:true +let spf = Printf.sprintf + +module Test = struct + type expect = + | Diagnostic of string + | Decoded of json + + type t = { + hex: string; + raw: string; + expect: expect; + roundtrip: bool; + } + + let pp_expect out = function + | Diagnostic s -> Fmt.fprintf out "(diagnostic %S)" s + | Decoded j -> Fmt.fprintf out "(@[decoded:@ %a@])" J.pp j + + let pp out (self:t) = + Fmt.fprintf out "{@[hex: %S,@ expected: %a,@ roundtrip: %b@]}" + self.hex pp_expect self.expect self.roundtrip +end + + +let extract_tests (j:json) : Test.t list = + let l = J.Util.to_list j in + List.map (fun o -> + let o = J.Util.to_assoc o in + let hex = J.Util.to_string @@ List.assoc "hex" o in + let raw = CCString.of_hex_exn @@ hex in + let roundtrip = J.Util.to_bool @@ List.assoc "roundtrip" o in + let expect = + match List.assoc_opt "decoded" o, List.assoc_opt "diagnostic" o with + | None, Some (`String s) -> Test.Diagnostic s + | Some o, _ -> Test.Decoded o + | _ -> failwith "cannot find expected result" + in + {Test.hex; raw; expect; roundtrip} + ) l + +(* a few tests we need to skip *) +let skip = [ + "c249010000000000000000", "(bigint)"; + "1BFFFFFFFFFFFFFFFF", "(requires int64, loss of precision)"; + "3bffffffffffffffff", "(requires int64, loss of precision)"; + "1bffffffffffffffff", "(requires int64 loss of precision)"; + "5f42010243030405ff", "(requires representation of indefinite length)"; +] + +type count = { + mutable n_ok: int; + mutable n_err: int; + mutable n_skip: int; +} + +let run_test (c:count) (t:Test.t) : unit = + try + match Cbor.decode_exn t.raw with + | exception e -> + c.n_err <- c.n_err + 1; + Fmt.printf "error when decoding %S: %s@." t.hex (Printexc.to_string e) + | cbor -> + Fmt.printf " decoded into %a@." Cbor.pp_diagnostic cbor; + + (* do we skip the rest of the test? *) + match List.assoc_opt t.hex skip with + | Some reason -> + c.n_skip <- 1 + c.n_skip; + Fmt.printf "> @{SKIP@} %S (reason: %s)@." t.hex reason + + | None -> + Fmt.printf "> RUN test %S@." t.hex; + + (* check roundtrip, except on floats because we always use float64 *) + if t.roundtrip && (match cbor with `Float _ -> false | _ -> true) then ( + let hex' = Cbor.encode cbor |> CCString.to_hex in + if hex' <> t.hex then ( + Fmt.printf " @[@{mismatch@} on roundtrip:@ from %S@ to %S@]@." + t.hex hex'; + c.n_err <- c.n_err + 1; + raise Exit; + ) else ( + Fmt.printf " roundtrip ok@."; + ) + ); + + begin match t.expect with + | Test.Diagnostic s -> + let s' = Cbor.to_string_diagnostic cbor in + (* adjust display *) + let s' = match s' with + | "inf" -> "Infinity" + | "-inf" -> "-Infinity" + | "nan" -> "NaN" + | _ -> s' + in + if s=s' then ( + c.n_ok <- c.n_ok + 1; + Fmt.printf " @{OK@}@." + ) else ( + Fmt.printf " @{ERR@}: expected diagnostic %S, got %S@." s s'; + c.n_err <- c.n_err + 1; + ) + | Test.Decoded j -> + let rec compare_cj (cbor:Cbor.t) (j:json) = + match cbor, j with + | `Int i, `Int j -> i=j + | `Text s1, `String s2 -> s1=s2 + | `Array l1, `List l2 -> + List.length l1 = List.length l2 && + List.for_all2 compare_cj l1 l2 + | _ -> + Fmt.printf " TODO: compare with %a@." J.pp j; + true + in + + let ok = compare_cj cbor j in + + if ok then ( + c.n_ok <- 1 + c.n_ok; + Fmt.printf " expect: @{OK@}@." + ) else ( + c.n_err <- 1 + c.n_err; + Fmt.printf " expect: @{ERROR@} (got %a, expected %a)@." + Cbor.pp_diagnostic cbor J.pp j + ) + end + with Exit -> () + +let run_tests (l:Test.t list) = + let c = {n_err=0; n_ok=0; n_skip=0} in + List.iter (run_test c) l; + + let total = c.n_err + c.n_ok + c.n_skip in + if total <> List.length l then + Fmt.printf "@{warning@}: ran %d tests, for list of %d tests@." + total (List.length l); + + if c.n_err > 0 then ( + Fmt.printf "@.@.#####@.@{FAIL@}: %d errors, %d ok, %d skip@." + c.n_err c.n_ok c.n_skip; + exit 1 + ) else ( + Fmt.printf "@.@.#####@.@{OK@}: %d ok, %d skip@." c.n_ok c.n_skip; + ) + + +let () = + let color = try Sys.getenv "COLOR"="1" with _ -> false in + if color then CCFormat.set_color_default true; + let content = CCIO.File.read_exn Sys.argv.(1) in + let j = Yojson.Safe.from_string content in + let tests = extract_tests j in + (*Format.printf "tests: %a@." (Fmt.Dump.list Test.pp) tests;*) + run_tests tests; + ()