swh:1:snp:61dcfc0dd5674a0e65803e88039c122d9532074e
Tip revision: 2908d8885e537c9e2c345e3b65654c163b3465f8 authored by Raphaƫl Proust on 07 June 2022, 15:02:52 UTC
Add another test for mu
Add another test for mu
Tip revision: 2908d88
compact.ml
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2022 Nomadic Labs, <contact@nomadic-labs.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
let documentation_mentions_correct_tag_bit_counts () =
let open Data_encoding.Compact in
let int = payload Data_encoding.int31 in
assert (tag_bit_count (payload Data_encoding.unit) = 0) ;
assert (tag_bit_count (payload Data_encoding.int32) = 0) ;
assert (tag_bit_count int = 0) ;
assert (tag_bit_count void = 0) ;
assert (tag_bit_count (option (payload Data_encoding.unit)) = 1) ;
assert (tag_bit_count (option int) = 1) ;
assert (tag_bit_count (tup1 int) = 0) ;
assert (tag_bit_count (tup1 (option int)) = 1) ;
assert (tag_bit_count (tup2 (option int) int) = 1) ;
assert (tag_bit_count (tup2 (option int) (option int)) = 2) ;
assert (tag_bit_count (obj1 (req "one" int)) = 0) ;
assert (tag_bit_count (obj1 (opt "one" int)) = 1) ;
assert (tag_bit_count (obj2 (opt "one" int) (req "two" int)) = 1) ;
assert (tag_bit_count (obj2 (opt "one" int) (opt "two" int)) = 2) ;
assert (tag_bit_count int32 = 2) ;
assert (tag_bit_count int64 = 2) ;
assert (
tag_bit_count
(or_int32 ~int32_title:"i32" ~alt_title:"alt" Data_encoding.unit)
= 2) ;
assert (tag_bit_count (list ~bits:0 Data_encoding.int31) = 0) ;
assert (tag_bit_count (list ~bits:1 Data_encoding.int31) = 1) ;
assert (tag_bit_count (list ~bits:2 Data_encoding.int31) = 2) ;
assert (tag_bit_count (list ~bits:3 Data_encoding.int31) = 3) ;
assert (tag_bit_count (list ~bits:4 Data_encoding.int31) = 4) ;
assert (
tag_bit_count
(union
~union_tag_bits:0
~cases_tag_bits:0
[case ~title:"unit" unit Option.some Fun.id])
= 0) ;
assert (
tag_bit_count
(union
~union_tag_bits:1
~cases_tag_bits:0
[case ~title:"unit" unit Option.some Fun.id])
= 1) ;
assert (
tag_bit_count
(union
~union_tag_bits:0
~cases_tag_bits:1
[case ~title:"unit" (option unit) Option.some Fun.id])
= 1) ;
assert (
tag_bit_count
(union
~union_tag_bits:1
~cases_tag_bits:1
[case ~title:"unit" unit Option.some Fun.id])
= 2) ;
assert (
tag_bit_count
(union
~union_tag_bits:3
~cases_tag_bits:2
[case ~title:"unit" unit Option.some Fun.id])
= 5) ;
assert (
tag_bit_count
(union
~union_tag_bits:7
~cases_tag_bits:6
[
case ~title:"unit" unit Option.some Fun.id;
void_case ~title:"VOID01";
void_case ~title:"VOID10";
void_case ~title:"VOID11";
])
= 13) ;
assert (
let either a b =
union
[
case ~title:"Left" a Either.find_left Either.left;
case ~title:"Right" b Either.find_right Either.right;
]
in
(* [bool] takes 1 bit of tag (0 bytes of case) *)
(* [option] takes 1 bit of union-tag + the bits the case needs *)
(* [(option bool)] takes 2 bits of tag (1 + 1) *)
(* [either] takes 1 bit of union-tag (2 cases) + the bits the cases needs *)
(* [(either bool bool)] takes 2 bits of tag (1 + max (1, 1)) *)
(* the whole encoding takes takes 3 bits of tag (1 + max (2, 2)) *)
tag_bit_count (either (either bool bool) (option bool)) = 3) ;
()
let roundtrip_binary loc encoding1 encoding2 value =
let blob = Data_encoding.Binary.to_string_exn encoding1 value in
let value' = Data_encoding.Binary.of_string_exn encoding2 blob in
if value <> value' then raise (Failure ("Roundtrip failure at " ^ loc))
let no_roundtrip_binary loc encoding1 encoding2 value =
let blob = Data_encoding.Binary.to_string_exn encoding1 value in
match Data_encoding.Binary.of_string_exn encoding2 blob with
| exception Data_encoding.Binary.Read_error _ -> ()
| value' ->
if value = value' then
raise (Failure ("Unexpected successful rountrip at " ^ loc))
let roundtrip_with_voids () =
let open Data_encoding.Compact in
let casel =
case
~title:"Left"
(payload Data_encoding.uint8)
Either.find_left
Either.left
in
let caser =
case
~title:"Right"
(payload Data_encoding.uint8)
Either.find_right
Either.right
in
let all_inputs = List.init 256 Either.left @ List.init 256 Either.right in
let compatible_unions =
[
union ~union_tag_bits:1 [casel; caser];
union ~union_tag_bits:2 [casel; caser];
union
~union_tag_bits:2
[casel; caser; void_case ~title:"a"; void_case ~title:"b"];
]
in
let incompatible_unions =
[
union ~union_tag_bits:1 [caser; casel];
union
~union_tag_bits:2
[void_case ~title:"a"; void_case ~title:"b"; casel; caser];
union
~union_tag_bits:2
[void_case ~title:"a"; casel; void_case ~title:"b"; caser];
union
~union_tag_bits:2
[void_case ~title:"a"; casel; caser; void_case ~title:"b"];
]
in
List.iter
(fun encoding1 ->
let encoding1 = make ~tag_size:`Uint8 encoding1 in
List.iter
(fun encoding2 ->
let encoding2 = make ~tag_size:`Uint8 encoding2 in
List.iter
(fun value -> roundtrip_binary __LOC__ encoding1 encoding2 value)
all_inputs)
compatible_unions)
compatible_unions ;
List.iter
(fun encoding1 ->
let encoding1 = make ~tag_size:`Uint8 encoding1 in
List.iter
(fun encoding2 ->
let encoding2 = make ~tag_size:`Uint8 encoding2 in
List.iter
(fun value ->
no_roundtrip_binary __LOC__ encoding1 encoding2 value ;
no_roundtrip_binary __LOC__ encoding2 encoding1 value)
all_inputs)
compatible_unions)
incompatible_unions
let roundtrip_option_bool () =
let open Data_encoding in
let encoding =
let open Compact in
let either a b =
union
[
case ~title:"Left" a Either.find_left Either.left;
case ~title:"Right" b Either.find_right Either.right;
]
in
(* We also check that the whole data is encoding onto exactly one byte using
this [check_size] combinator. *)
check_size 1
@@ make ~tag_size:`Uint8 (either (option bool) (either bool unit))
in
let inputs =
[
Either.Left None;
Either.Left (Some true);
Either.Left (Some false);
Either.Right (Either.Left true);
Either.Right (Either.Left false);
Either.Right (Either.Right ());
]
in
List.iter (roundtrip_binary __LOC__ encoding encoding) inputs
let tests =
[
( "tag_bit_count documentation",
`Quick,
documentation_mentions_correct_tag_bit_counts );
("roundtrip (heavy on void)", `Quick, roundtrip_with_voids);
("roundtrip (option bool)", `Quick, roundtrip_option_bool);
]