Testsuite: testing Data_encoding module
This commit is contained in:
parent
026007e7f1
commit
cdf7265693
1
.gitignore
vendored
1
.gitignore
vendored
@ -26,6 +26,7 @@
|
|||||||
/test/test-state
|
/test/test-state
|
||||||
/test/test-context
|
/test/test-context
|
||||||
/test/test-basic
|
/test/test-basic
|
||||||
|
/test/test-data-encoding
|
||||||
/test/LOG
|
/test/LOG
|
||||||
|
|
||||||
*~
|
*~
|
||||||
|
@ -17,6 +17,8 @@ S ../src/client
|
|||||||
B ../src/client
|
B ../src/client
|
||||||
S ../src/client/embedded
|
S ../src/client/embedded
|
||||||
B ../src/client/embedded
|
B ../src/client/embedded
|
||||||
|
S ./lib
|
||||||
|
B ./lib
|
||||||
FLG -w -40
|
FLG -w -40
|
||||||
PKG lwt
|
PKG lwt
|
||||||
PKG sodium
|
PKG sodium
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
TESTS := store context state basic basic.sh
|
TESTS := data-encoding store context state basic basic.sh
|
||||||
|
|
||||||
all: test
|
all: test
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ ${NODELIB} ${CLIENTLIB}:
|
|||||||
.PHONY: build-test run-test test
|
.PHONY: build-test run-test test
|
||||||
build-test: ${addprefix build-test-,${TESTS}}
|
build-test: ${addprefix build-test-,${TESTS}}
|
||||||
run-test:
|
run-test:
|
||||||
@$(patsubst %,${MAKE} run-test-% &&, ${TESTS}) \
|
@$(patsubst %,${MAKE} run-test-% ; , ${TESTS}) \
|
||||||
echo && echo "Success" && echo
|
echo && echo "Success" && echo
|
||||||
test:
|
test:
|
||||||
@${MAKE} --no-print-directory build-test
|
@${MAKE} --no-print-directory build-test
|
||||||
@ -168,6 +168,27 @@ test-basic: ${NODELIB} ${CLIENTLIB} ${TEST_BASIC_IMPLS:.ml=.cmx}
|
|||||||
clean::
|
clean::
|
||||||
rm -f test-basic
|
rm -f test-basic
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
## data encoding test program
|
||||||
|
|
||||||
|
.PHONY:build-test-data-encoding run-test-data-encoding
|
||||||
|
build-test-data-encoding: test-data-encoding
|
||||||
|
run-test-data-encoding:
|
||||||
|
./test-data-encoding
|
||||||
|
|
||||||
|
TEST_DATA_ENCODING_INTFS =
|
||||||
|
|
||||||
|
TEST_DATA_ENCODING_IMPLS = \
|
||||||
|
lib/assert.ml \
|
||||||
|
lib/test.ml \
|
||||||
|
test_data_encoding.ml
|
||||||
|
|
||||||
|
${TEST_DATA_ENCODING_IMPLS:.ml=.cmx}: ${NODELIB}
|
||||||
|
test-data-encoding: ${NODELIB} ${TEST_DATA_ENCODING_IMPLS:.ml=.cmx}
|
||||||
|
ocamlfind ocamlopt -linkall -linkpkg ${OCAMLFLAGS} -o $@ $^
|
||||||
|
|
||||||
|
clean::
|
||||||
|
rm -f test-data-encoding
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
## Generic rules
|
## Generic rules
|
||||||
|
@ -11,12 +11,6 @@ open Kaputt.Abbreviations
|
|||||||
|
|
||||||
include Kaputt.Assertion
|
include Kaputt.Assertion
|
||||||
|
|
||||||
let fail_msg fmt =
|
|
||||||
Format.kasprintf Assert.fail_msg fmt
|
|
||||||
|
|
||||||
let fail expected given fmt =
|
|
||||||
Format.kasprintf (Assert.fail expected given) fmt
|
|
||||||
|
|
||||||
let format_msg = function None -> None | Some msg -> Some (msg ^ "\n")
|
let format_msg = function None -> None | Some msg -> Some (msg ^ "\n")
|
||||||
|
|
||||||
let equal_persist_list ?msg l1 l2 =
|
let equal_persist_list ?msg l1 l2 =
|
||||||
@ -80,3 +74,25 @@ let equal_result ?msg r1 r2 ~equal_ok ~equal_err =
|
|||||||
| Error e1, Error e2 -> equal_err ?msg e1 e2
|
| Error e1, Error e2 -> equal_err ?msg e1 e2
|
||||||
| Ok r, Error e | Error e, Ok r ->
|
| Ok r, Error e | Error e, Ok r ->
|
||||||
Assert.fail_msg "Results are not the same"
|
Assert.fail_msg "Results are not the same"
|
||||||
|
|
||||||
|
let equal_exn ?msg exn1 exn2 =
|
||||||
|
let msg = format_msg msg in
|
||||||
|
let prn = Printexc.to_string in
|
||||||
|
Assert.equal ?msg ~prn exn1 exn2
|
||||||
|
|
||||||
|
let test_fail ?(msg = "") ?(prn = Assert.default_printer) f may_fail =
|
||||||
|
try
|
||||||
|
let value = f () in
|
||||||
|
fail "any exception" ("no exception: " ^ prn value) msg
|
||||||
|
with exn ->
|
||||||
|
if not (may_fail exn) then
|
||||||
|
fail "exception"
|
||||||
|
(Printf.sprintf "unexpectec exception: %s" (Printexc.to_string exn))
|
||||||
|
msg
|
||||||
|
|
||||||
|
let fail_msg fmt =
|
||||||
|
Format.kasprintf Assert.fail_msg fmt
|
||||||
|
|
||||||
|
let fail expected given fmt =
|
||||||
|
Format.kasprintf (Assert.fail expected given) fmt
|
||||||
|
|
||||||
|
@ -42,3 +42,12 @@ val equal_result :
|
|||||||
('a, 'b) result ->
|
('a, 'b) result ->
|
||||||
equal_ok:(?msg:string -> 'a -> 'a -> 'c) ->
|
equal_ok:(?msg:string -> 'a -> 'a -> 'c) ->
|
||||||
equal_err:(?msg:string -> 'b -> 'b -> 'c) -> 'c
|
equal_err:(?msg:string -> 'b -> 'b -> 'c) -> 'c
|
||||||
|
|
||||||
|
val equal_exn : ?msg:string -> exn -> exn -> unit
|
||||||
|
|
||||||
|
val test_fail :
|
||||||
|
?msg:string ->
|
||||||
|
?prn:('a -> string) ->
|
||||||
|
(unit -> 'a) ->
|
||||||
|
(exn -> bool) ->
|
||||||
|
unit
|
||||||
|
@ -11,6 +11,9 @@ open Kaputt.Abbreviations
|
|||||||
|
|
||||||
let keep_dir = try ignore (Sys.getenv "KEEPDIR") ; true with _ -> false
|
let keep_dir = try ignore (Sys.getenv "KEEPDIR") ; true with _ -> false
|
||||||
|
|
||||||
|
let make_test ~title test =
|
||||||
|
Test.add_simple_test ~title (fun () -> Lwt_main.run (test ()))
|
||||||
|
|
||||||
let rec remove_dir dir =
|
let rec remove_dir dir =
|
||||||
Array.iter (fun file ->
|
Array.iter (fun file ->
|
||||||
let f = Filename.concat dir file in
|
let f = Filename.concat dir file in
|
||||||
|
306
test/test_data_encoding.ml
Normal file
306
test/test_data_encoding.ml
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
open Data_encoding
|
||||||
|
open Context
|
||||||
|
open Hash
|
||||||
|
|
||||||
|
let (>>=) = Lwt.bind
|
||||||
|
let (>|=) = Lwt.(>|=)
|
||||||
|
let (//) = Filename.concat
|
||||||
|
|
||||||
|
let write_file dir ~name content =
|
||||||
|
let file = (dir // name) in
|
||||||
|
let oc = open_out file in
|
||||||
|
output_string oc content ;
|
||||||
|
close_out oc ;
|
||||||
|
file
|
||||||
|
|
||||||
|
let is_invalid_arg = function
|
||||||
|
| Invalid_argument _ -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let test_simple_json ?msg ?eq:(equal=Assert.equal) encoding value =
|
||||||
|
let json = Json.construct encoding value in
|
||||||
|
let result = Json.destruct encoding json in
|
||||||
|
equal ?msg value result
|
||||||
|
|
||||||
|
let test_simple_bin ?msg ?(equal=Assert.equal) encoding value =
|
||||||
|
let bin = Binary.to_bytes encoding value in
|
||||||
|
let opt = Binary.of_bytes encoding bin in
|
||||||
|
Assert.is_some ?msg opt;
|
||||||
|
let result = match opt with None -> assert false | Some v -> v in
|
||||||
|
equal ?msg value result
|
||||||
|
|
||||||
|
let test_json_exn ?msg ?(equal=Assert.equal) encoding value fail =
|
||||||
|
let get_result () =
|
||||||
|
let bin = Json.construct encoding value in
|
||||||
|
Json.destruct encoding bin in
|
||||||
|
Assert.test_fail ?msg get_result fail
|
||||||
|
|
||||||
|
let test_bin_exn ?msg ?(equal=Assert.equal) encoding value fail =
|
||||||
|
let get_result () =
|
||||||
|
let bin = Binary.to_bytes encoding value in
|
||||||
|
Binary.of_bytes encoding bin in
|
||||||
|
Assert.test_fail ?msg get_result fail
|
||||||
|
|
||||||
|
let test_simple ~msg enc value =
|
||||||
|
test_simple_json ~msg:(msg ^ ": json") enc value ;
|
||||||
|
test_simple_bin ~msg:(msg ^ ": binary") enc value
|
||||||
|
|
||||||
|
let test_simple_int ~msg ?(boundary=true) encoding i =
|
||||||
|
let pow y = int_of_float @@ (2. ** float_of_int y) in
|
||||||
|
let i = i - 1 in
|
||||||
|
let range_min = - pow i in
|
||||||
|
let range_max = pow i - 1 in
|
||||||
|
let out_max = pow i in
|
||||||
|
let out_min = - pow i - 1 in
|
||||||
|
test_simple ~msg encoding range_min ;
|
||||||
|
test_simple ~msg encoding range_max ;
|
||||||
|
if boundary then begin
|
||||||
|
test_simple_bin ~msg ~equal:(Assert.not_equal) encoding out_max ;
|
||||||
|
test_simple_bin ~msg ~equal:(Assert.not_equal) encoding out_min
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
let test_simple_values _ =
|
||||||
|
test_simple ~msg:__LOC__ null ();
|
||||||
|
test_simple ~msg:__LOC__ empty ();
|
||||||
|
test_simple ~msg:__LOC__ (constant "toto") ();
|
||||||
|
test_simple_int ~msg:__LOC__ int8 8;
|
||||||
|
test_simple_int ~msg:__LOC__ int16 16;
|
||||||
|
test_simple_int ~msg:__LOC__ ~boundary:false int31 31;
|
||||||
|
test_simple ~msg:__LOC__ int32 Int32.min_int;
|
||||||
|
test_simple ~msg:__LOC__ int32 Int32.max_int;
|
||||||
|
test_simple ~msg:__LOC__ int64 Int64.min_int;
|
||||||
|
test_simple ~msg:__LOC__ int64 Int64.max_int;
|
||||||
|
test_simple ~msg:__LOC__ bool true;
|
||||||
|
test_simple ~msg:__LOC__ bool false;
|
||||||
|
test_simple ~msg:__LOC__ string "tutu";
|
||||||
|
test_simple ~msg:__LOC__ bytes (MBytes.of_string "titi");
|
||||||
|
test_simple ~msg:__LOC__ float 42.;
|
||||||
|
test_simple ~msg:__LOC__ (option string) (Some "thing");
|
||||||
|
test_simple ~msg:__LOC__ (option string) None;
|
||||||
|
let enum_enc =
|
||||||
|
["one", 1; "two", 2; "three", 3; "four", 4; "five", 6; "six", 6] in
|
||||||
|
test_simple_bin ~msg:__LOC__ (string_enum enum_enc) 4;
|
||||||
|
test_json_exn ~msg:__LOC__ (string_enum enum_enc) 7 is_invalid_arg ;
|
||||||
|
test_bin_exn ~msg:__LOC__ (string_enum enum_enc) 7
|
||||||
|
(function
|
||||||
|
| No_case_matched -> true
|
||||||
|
| _ -> false) ;
|
||||||
|
(* Should fail *)
|
||||||
|
(* test_bin_exn ~msg:__LOC__ (string_enum ["a", 1; "a", 2]) 2 (...duplicatate...); *)
|
||||||
|
(* test_json_exn ~msg:__LOC__ (string_enum ["a", 1; "a", 2]) 1 (... duplicate...); *)
|
||||||
|
|
||||||
|
Lwt.return_unit
|
||||||
|
|
||||||
|
let test_json testdir =
|
||||||
|
let file = testdir // "testing_data_encoding.tezos" in
|
||||||
|
let v = `Float 42. in
|
||||||
|
let f_str = Json.to_string v in
|
||||||
|
Assert.equal_string ~msg:__LOC__ f_str "[\n 42\n]";
|
||||||
|
Json.read_file (testdir // "NONEXISTINGFILE") >>= fun rf ->
|
||||||
|
Assert.is_none ~msg:__LOC__ rf;
|
||||||
|
Json.write_file file v >>= fun success ->
|
||||||
|
Assert.is_true ~msg:__LOC__ success;
|
||||||
|
Json.read_file file >>= fun opt ->
|
||||||
|
Assert.is_some ~msg:__LOC__ opt;
|
||||||
|
Lwt.return ()
|
||||||
|
|
||||||
|
type t = A of int | B of string | C of int | D of string | E
|
||||||
|
|
||||||
|
let prn_t = function
|
||||||
|
| A i -> Printf.sprintf "A %d" i
|
||||||
|
| B s -> Printf.sprintf "B %s" s
|
||||||
|
| C i -> Printf.sprintf "C %d" i
|
||||||
|
| D s -> Printf.sprintf "D %s" s
|
||||||
|
| E -> "E"
|
||||||
|
|
||||||
|
let test_tag_errors _ =
|
||||||
|
let duplicate_tag () =
|
||||||
|
union [
|
||||||
|
case ~tag:1
|
||||||
|
int8
|
||||||
|
(fun i -> i)
|
||||||
|
(fun i -> Some i) ;
|
||||||
|
case ~tag:1
|
||||||
|
int8
|
||||||
|
(fun i -> i)
|
||||||
|
(fun i -> Some i)] in
|
||||||
|
Assert.test_fail ~msg:__LOC__ duplicate_tag
|
||||||
|
(function Duplicated_tag _ -> true
|
||||||
|
| _ -> false) ;
|
||||||
|
let invalid_tag () =
|
||||||
|
union [
|
||||||
|
case ~tag:(2 lsl 7)
|
||||||
|
int8
|
||||||
|
(fun i -> i)
|
||||||
|
(fun i -> Some i)] in
|
||||||
|
Assert.test_fail ~msg:__LOC__ invalid_tag
|
||||||
|
(function (Invalid_tag (_, `Int8)) -> true
|
||||||
|
| _ -> false) ;
|
||||||
|
Lwt.return_unit
|
||||||
|
|
||||||
|
let test_union _ =
|
||||||
|
let enc =
|
||||||
|
(union [
|
||||||
|
case ~tag:1
|
||||||
|
int8
|
||||||
|
(function A i -> Some i | _ -> None)
|
||||||
|
(fun i -> A i) ;
|
||||||
|
case ~tag:2
|
||||||
|
string
|
||||||
|
(function B s -> Some s | _ -> None)
|
||||||
|
(fun s -> B s) ;
|
||||||
|
case ~tag:3
|
||||||
|
int8
|
||||||
|
(function C i -> Some i | _ -> None)
|
||||||
|
(fun i -> C i) ;
|
||||||
|
case ~tag:4
|
||||||
|
(obj2
|
||||||
|
(req "kind" (constant "D"))
|
||||||
|
(req "data" (string)))
|
||||||
|
(function D s -> Some ((), s) | _ -> None)
|
||||||
|
(fun ((), s) -> D s) ;
|
||||||
|
]) in
|
||||||
|
let jsonA = Json.construct enc (A 1) in
|
||||||
|
let jsonB = Json.construct enc (B "2") in
|
||||||
|
let jsonC = Json.construct enc (C 3) in
|
||||||
|
let jsonD = Json.construct enc (D"4") in
|
||||||
|
Assert.test_fail
|
||||||
|
~msg:__LOC__ (fun () -> Json.construct enc E) is_invalid_arg ;
|
||||||
|
Assert.equal ~prn:prn_t ~msg:__LOC__ (A 1) (Json.destruct enc jsonA) ;
|
||||||
|
Assert.equal ~prn:prn_t ~msg:__LOC__ (B "2") (Json.destruct enc jsonB) ;
|
||||||
|
Assert.equal ~prn:prn_t ~msg:__LOC__ (A 3) (Json.destruct enc jsonC) ;
|
||||||
|
Assert.equal ~prn:prn_t ~msg:__LOC__ (D "4") (Json.destruct enc jsonD) ;
|
||||||
|
let binA = Binary.to_bytes enc (A 1) in
|
||||||
|
let binB = Binary.to_bytes enc (B "2") in
|
||||||
|
let binC = Binary.to_bytes enc (C 3) in
|
||||||
|
let binD = Binary.to_bytes enc (D "4") in
|
||||||
|
Assert.test_fail ~msg:__LOC__ (fun () -> Binary.to_bytes enc E)
|
||||||
|
(function
|
||||||
|
| No_case_matched -> true
|
||||||
|
| _ -> false) ;
|
||||||
|
let get_result ~msg bin =
|
||||||
|
match Binary.of_bytes enc bin with
|
||||||
|
| None -> Assert.fail_msg "%s" msg
|
||||||
|
| Some bin -> bin in
|
||||||
|
Assert.equal ~prn:prn_t ~msg:__LOC__ (A 1) (get_result ~msg:__LOC__ binA) ;
|
||||||
|
Assert.equal ~prn:prn_t ~msg:__LOC__ (B "2") (get_result ~msg:__LOC__ binB) ;
|
||||||
|
Assert.equal ~prn:prn_t ~msg:__LOC__ (C 3) (get_result ~msg:__LOC__ binC) ;
|
||||||
|
Assert.equal ~prn:prn_t ~msg:__LOC__ (D "4") (get_result ~msg:__LOC__ binD) ;
|
||||||
|
Lwt.return_unit
|
||||||
|
|
||||||
|
|
||||||
|
type s = { field : int }
|
||||||
|
|
||||||
|
let test_splitted _ =
|
||||||
|
let s_enc =
|
||||||
|
def "s" @@
|
||||||
|
describe
|
||||||
|
~title:"testsuite encoding test"
|
||||||
|
~description: "A human readable description" @@
|
||||||
|
conv
|
||||||
|
(fun s -> string_of_int s.field)
|
||||||
|
(fun s -> { field = int_of_string s })
|
||||||
|
string in
|
||||||
|
let enc =
|
||||||
|
(splitted
|
||||||
|
~binary:string
|
||||||
|
~json:
|
||||||
|
(union [
|
||||||
|
case ~tag:1
|
||||||
|
string
|
||||||
|
(fun _ -> None)
|
||||||
|
(fun s -> s) ;
|
||||||
|
case ~tag:2
|
||||||
|
s_enc
|
||||||
|
(fun s -> Some { field = int_of_string s })
|
||||||
|
(fun s -> string_of_int s.field) ;
|
||||||
|
])) in
|
||||||
|
let get_result ~msg bin =
|
||||||
|
match Binary.of_bytes enc bin with
|
||||||
|
| None -> Assert.fail_msg "%s: Cannot parse." msg
|
||||||
|
| Some bin -> bin in
|
||||||
|
let jsonA = Json.construct enc "41" in
|
||||||
|
let jsonB = Json.construct s_enc {field = 42} in
|
||||||
|
let binA = Binary.to_bytes enc "43" in
|
||||||
|
let binB = Binary.to_bytes s_enc {field = 44} in
|
||||||
|
Assert.equal ~msg:__LOC__ "41" (Json.destruct enc jsonA);
|
||||||
|
Assert.equal ~msg:__LOC__ "42" (Json.destruct enc jsonB);
|
||||||
|
Assert.equal ~msg:__LOC__ "43" (get_result ~msg:__LOC__ binA);
|
||||||
|
Assert.equal ~msg:__LOC__ "44" (get_result ~msg:__LOC__ binB);
|
||||||
|
Lwt.return_unit
|
||||||
|
|
||||||
|
let test_json_input testdir =
|
||||||
|
let enc =
|
||||||
|
obj1
|
||||||
|
(req "menu" (
|
||||||
|
obj3
|
||||||
|
(req "id" string)
|
||||||
|
(req "value" string)
|
||||||
|
(opt "popup" (
|
||||||
|
obj2
|
||||||
|
(req "width" int64)
|
||||||
|
(req "height" int64))))) in
|
||||||
|
begin
|
||||||
|
let file =
|
||||||
|
write_file testdir ~name:"good.json" {|
|
||||||
|
{
|
||||||
|
"menu": {
|
||||||
|
"id": "file",
|
||||||
|
"value": "File",
|
||||||
|
"popup": {
|
||||||
|
"width" : 42,
|
||||||
|
"height" : 52
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|}
|
||||||
|
in
|
||||||
|
Json.read_file file >>= function
|
||||||
|
None -> Assert.fail_msg "Cannot parse \"good.json\"."
|
||||||
|
| Some json ->
|
||||||
|
let (id, value, popup) = Json.destruct enc json in
|
||||||
|
Assert.equal_string ~msg:__LOC__ "file" id;
|
||||||
|
Assert.equal_string ~msg:__LOC__ "File" value;
|
||||||
|
Assert.is_some ~msg:__LOC__ popup;
|
||||||
|
let w,h = match popup with None -> assert false | Some (w,h) -> w,h in
|
||||||
|
Assert.equal_int64 ~msg:__LOC__ 42L w;
|
||||||
|
Assert.equal_int64 ~msg:__LOC__ 52L h;
|
||||||
|
Lwt.return_unit
|
||||||
|
end >>= fun () ->
|
||||||
|
let enc =
|
||||||
|
obj2
|
||||||
|
(req "kind" (string))
|
||||||
|
(req "data" (int64)) in
|
||||||
|
begin
|
||||||
|
let file =
|
||||||
|
write_file testdir ~name:"unknown.json" {|
|
||||||
|
{
|
||||||
|
"kind" : "int64",
|
||||||
|
"data" : "42",
|
||||||
|
"unknown" : 2
|
||||||
|
}
|
||||||
|
|}
|
||||||
|
in
|
||||||
|
Json.read_file file >>= function
|
||||||
|
None -> Assert.fail_msg "Cannot parse \"unknown.json\"."
|
||||||
|
| Some json ->
|
||||||
|
Assert.test_fail ~msg:__LOC__
|
||||||
|
(fun () -> ignore (Json.destruct enc json))
|
||||||
|
(function
|
||||||
|
| Json.Unexpected_field "unknown" -> true
|
||||||
|
| _ -> false) ;
|
||||||
|
Lwt.return_unit
|
||||||
|
end
|
||||||
|
|
||||||
|
let tests = [
|
||||||
|
"simple", test_simple_values ;
|
||||||
|
"json", test_json ;
|
||||||
|
"union", test_union ;
|
||||||
|
"splitted", test_splitted ;
|
||||||
|
"json.input", test_json_input ;
|
||||||
|
"tags", test_tag_errors ;
|
||||||
|
]
|
||||||
|
|
||||||
|
let () =
|
||||||
|
Test.run "data_encoding." tests
|
Loading…
Reference in New Issue
Block a user