97 lines
3.1 KiB
OCaml
97 lines
3.1 KiB
OCaml
|
type result = Decoded of Yojson.Basic.t | Diagnostic of string
|
||
|
|
||
|
type test = {
|
||
|
cbor : string;
|
||
|
result : result;
|
||
|
noncanonical : bool;
|
||
|
}
|
||
|
|
||
|
let (@@) f x = f x
|
||
|
let (|>) x f = f x
|
||
|
let eprintfn fmt = Printf.ksprintf prerr_endline fmt
|
||
|
let fail fmt = Printf.ksprintf failwith fmt
|
||
|
|
||
|
let of_hex s =
|
||
|
assert (String.length s mod 2 = 0);
|
||
|
let n = String.length s / 2 in
|
||
|
let r = Bytes.create n in
|
||
|
for i = 0 to pred n do
|
||
|
Bytes.set r i @@ Char.chr @@ int_of_string ("0x" ^ String.sub s (i*2) 2)
|
||
|
done;
|
||
|
Bytes.to_string r
|
||
|
|
||
|
let read file =
|
||
|
let open Yojson.Basic in
|
||
|
Yojson.Safe.from_file file (* large ints *)
|
||
|
|> Yojson.Safe.to_basic
|
||
|
|> Util.to_list
|
||
|
|> List.map begin function
|
||
|
| `Assoc a ->
|
||
|
let cbor = of_hex @@ Util.to_string @@ List.assoc "hex" a in
|
||
|
let result =
|
||
|
try
|
||
|
Diagnostic (Util.to_string @@ List.assoc "diagnostic" a)
|
||
|
with Not_found ->
|
||
|
Decoded (List.assoc "decoded" a)
|
||
|
in
|
||
|
let noncanonical = try
|
||
|
Util.to_bool @@ List.assoc "noncanonical" a
|
||
|
with Not_found -> false
|
||
|
in
|
||
|
{ cbor; result; noncanonical }
|
||
|
| _ -> assert false
|
||
|
end
|
||
|
|
||
|
let rec json_of_cbor : CBOR.Simple.t -> Yojson.Basic.t = function
|
||
|
| (`Null | `Bool _ | `Int _ | `Float _ as x) -> x
|
||
|
| `Undefined | `Simple _ -> `Null
|
||
|
| `Bytes x -> `String x
|
||
|
| `Text x -> `String x
|
||
|
| `Array x -> `List (List.map json_of_cbor x)
|
||
|
| `Map x -> `Assoc (List.map (fun (k,v) ->
|
||
|
match k with
|
||
|
| `Text s -> s, json_of_cbor v
|
||
|
| _ -> fail "json_of_cbor: expected string key") x)
|
||
|
|
||
|
let () =
|
||
|
match List.tl @@ Array.to_list Sys.argv with
|
||
|
| file::[] ->
|
||
|
eprintfn "I: running tests from %s" file;
|
||
|
let tests = read file in
|
||
|
eprintfn "I: total tests = %d" (List.length tests);
|
||
|
let ok = ref 0 in
|
||
|
let failed = ref 0 in
|
||
|
let ignored = ref 0 in
|
||
|
let nr = ref (-1) in
|
||
|
tests |> List.iter begin fun test ->
|
||
|
try
|
||
|
incr nr;
|
||
|
if test.noncanonical then
|
||
|
try let cbor = CBOR.Simple.decode test.cbor in
|
||
|
fail "expected reject noncanonical CBOR, got %s"
|
||
|
(CBOR.Simple.to_diagnostic cbor)
|
||
|
with CBOR.Noncanonical _ -> incr ok
|
||
|
else
|
||
|
let cbor = CBOR.Simple.decode test.cbor in
|
||
|
let diag = CBOR.Simple.to_diagnostic cbor in
|
||
|
let () = match test.result with
|
||
|
| Diagnostic s ->
|
||
|
if s <> diag then fail "expected %s, got %s" s diag
|
||
|
| Decoded json ->
|
||
|
let json' = json_of_cbor cbor in
|
||
|
if json <> json' then fail "expected %s, got %s, aka %s"
|
||
|
(Yojson.Basic.to_string json) (Yojson.Basic.to_string json') diag
|
||
|
in
|
||
|
incr ok
|
||
|
with exn ->
|
||
|
let ignore = List.mem !nr [10; 12] in
|
||
|
eprintfn "%s test %d: %s"
|
||
|
(if ignore then "W: ignoring" else "E:") !nr (match exn with Failure s -> s | _ -> Printexc.to_string exn);
|
||
|
incr (if ignore then ignored else failed)
|
||
|
end;
|
||
|
eprintfn "I: finished. tests ok = %d failed = %d ignored = %d" !ok !failed !ignored;
|
||
|
exit (if !failed = 0 then 0 else 1)
|
||
|
| _ ->
|
||
|
eprintfn "E: no test file given";
|
||
|
exit 2
|