open Chusai_serialization

let of_bytes s = (Bytes.of_string (Hex.to_string (`Hex s)))

module Ligo_bytes_repr = struct
  (* Those values has been generated by the command
     - ligo run test test_pack.mligo
     - ligo run test test_unpack.mligo
   *)
  open Serializable.Pack

  type 'a t = { raw_ligo : 'a; value: string; msg: string}
  
  let check pack t =
    Alcotest.(check bytes) t.msg
      (of_bytes t.value)
      (pack t.raw_ligo)

  let test_bytes () =
    let pack b = Serializable.Pack.pack (Bytes_t, of_bytes b) in
    let test_data =
      [ { raw_ligo = "0974657374207061636b"
        ; value = "050a0000000a0974657374207061636b"
        ; msg = "test pack arbitrary bytes"}
      ; { raw_ligo = "00"
        ; value = "050a0000000100"
        ; msg = "test pack bytes 00"}
      ]
    in
    let _ = List.map (check pack) test_data in
    ()


  let test_string () =
    let pack s = Serializable.Pack.pack (String_t, s) in
    let test_data =
      [ { raw_ligo = "pack test"
        ; value = "0501000000097061636b2074657374"
        ; msg = "test pack arbitrary string"}
      ; { raw_ligo = ""
        ; value = "050100000000"
        ; msg = "test pack empty string"}
      ]
    in
    let _ = List.map (check pack) test_data in
    ()

  let test_int () =
    let pack i = Serializable.Pack.pack (Int_t, Z.of_int i) in

    let test_data =
      [ { raw_ligo = 1
        ; value = "050001"
        ; msg = "test pack arbitrary postive int"}
      ; { raw_ligo = (-1)
        ; value = "050041"
        ; msg = "test pack arbitrary negative int"}
      ; { raw_ligo = 0
        ; value = "050000"
        ; msg = "test pack int 0"}
      ]
    in
    let _ = List.map (check pack) test_data in
    ()

  let test_list_of_int () =
    let pack l = Serializable.Pack.pack (List_t Int_t, List.map Z.of_int l) in
    let test_data =
      [ { raw_ligo = []
        ; value = "050200000000"
        ; msg = "test pack empty list of int"}
      ; { raw_ligo = [1;2;3;4]
        ; value = "0502000000080001000200030004"
        ; msg = "test pack list of int"}
      ]
    in
    let _ = List.map (check pack) test_data in
    ()

  let test_list_of_string () =
    let pack l = Serializable.Pack.pack (List_t String_t, l) in
    let test_data =
      { raw_ligo = []
      ; value = "050200000000"
      ; msg = "test pack empty list of string"
      }
    in
    check pack test_data

  let test_list_of_pair () =
    let pack l = Serializable.Pack.pack (List_t (Pair_t (Int_t, String_t)), l) in
    let test_data =
      { raw_ligo = [(Z.one,"one"); (Z.of_int 2, "two")]
      ; value = "0502000000180707000101000000036f6e6507070002010000000374776f"
      ; msg = "test pack list of pair"
      }
    in
    check pack test_data

  let test_pair () =
    let pack l = Serializable.Pack.pack (Pair_t (String_t, Int_t), l) in
    let test_data =
      { raw_ligo = ("test", Z.of_int 100)
      ; value = "05070701000000047465737400a401"
      ; msg = "test pack pair"
      }
    in
    check pack test_data

* Ligo supports tuple but it transplies pair in pair in  , not tuple in  . 
       The following is a test for tuple in 
      The following is a test for tuple in michelson *)
  let test_tuple () =
    Alcotest.(check bytes) "test pack tuple"
      (of_bytes "0509070000001501000000047465737400a40101000000047061636b00000000")
      (Serializable.Pack.pack (Tuple_t (String_t, Int_t, String_t), ("test", Z.of_int 100, "pack")))

  let test () =
    let open Alcotest in
    "pack test", [
      test_case "bytes" `Quick test_bytes;
      test_case "string" `Quick test_string;
      test_case "int" `Quick test_int;
      test_case "list of int" `Quick test_list_of_int;
      test_case "list of string" `Quick test_list_of_string;
      test_case "list of pair" `Quick test_list_of_pair;
      test_case "pair" `Quick test_pair;
      test_case "tuple" `Quick test_tuple;
    ] ;
end

 Those values has been generated by the command
     - ligo run test test_pack.mligo
     - ligo run test test_unpack.mligo
   
open Chusai_serialization

let of_bytes s = (Bytes.of_string (Hex.to_string (`Hex s)))

module Ligo_bytes_repr = struct
  open Serializable.Pack

  type 'a t = { raw_ligo : 'a; value: string; msg: string}
  
  let check pack t =
    Alcotest.(check bytes) t.msg
      (of_bytes t.value)
      (pack t.raw_ligo)

  let test_bytes () =
    let pack b = Serializable.Pack.pack (Bytes_t, of_bytes b) in
    let test_data =
      [ { raw_ligo = "0974657374207061636b"
        ; value = "050a0000000a0974657374207061636b"
        ; msg = "test pack arbitrary bytes"}
      ; { raw_ligo = "00"
        ; value = "050a0000000100"
        ; msg = "test pack bytes 00"}
      ]
    in
    let _ = List.map (check pack) test_data in
    ()


  let test_string () =
    let pack s = Serializable.Pack.pack (String_t, s) in
    let test_data =
      [ { raw_ligo = "pack test"
        ; value = "0501000000097061636b2074657374"
        ; msg = "test pack arbitrary string"}
      ; { raw_ligo = ""
        ; value = "050100000000"
        ; msg = "test pack empty string"}
      ]
    in
    let _ = List.map (check pack) test_data in
    ()

  let test_int () =
    let pack i = Serializable.Pack.pack (Int_t, Z.of_int i) in

    let test_data =
      [ { raw_ligo = 1
        ; value = "050001"
        ; msg = "test pack arbitrary postive int"}
      ; { raw_ligo = (-1)
        ; value = "050041"
        ; msg = "test pack arbitrary negative int"}
      ; { raw_ligo = 0
        ; value = "050000"
        ; msg = "test pack int 0"}
      ]
    in
    let _ = List.map (check pack) test_data in
    ()

  let test_list_of_int () =
    let pack l = Serializable.Pack.pack (List_t Int_t, List.map Z.of_int l) in
    let test_data =
      [ { raw_ligo = []
        ; value = "050200000000"
        ; msg = "test pack empty list of int"}
      ; { raw_ligo = [1;2;3;4]
        ; value = "0502000000080001000200030004"
        ; msg = "test pack list of int"}
      ]
    in
    let _ = List.map (check pack) test_data in
    ()

  let test_list_of_string () =
    let pack l = Serializable.Pack.pack (List_t String_t, l) in
    let test_data =
      { raw_ligo = []
      ; value = "050200000000"
      ; msg = "test pack empty list of string"
      }
    in
    check pack test_data

  let test_list_of_pair () =
    let pack l = Serializable.Pack.pack (List_t (Pair_t (Int_t, String_t)), l) in
    let test_data =
      { raw_ligo = [(Z.one,"one"); (Z.of_int 2, "two")]
      ; value = "0502000000180707000101000000036f6e6507070002010000000374776f"
      ; msg = "test pack list of pair"
      }
    in
    check pack test_data

  let test_pair () =
    let pack l = Serializable.Pack.pack (Pair_t (String_t, Int_t), l) in
    let test_data =
      { raw_ligo = ("test", Z.of_int 100)
      ; value = "05070701000000047465737400a401"
      ; msg = "test pack pair"
      }
    in
    check pack test_data

* Ligo supports tuple but it transplies pair in pair in  , not tuple in  . 
       The following is a test for tuple in 
      The following is a test for tuple in michelson *)
  let test_tuple () =
    Alcotest.(check bytes) "test pack tuple"
      (of_bytes "0509070000001501000000047465737400a40101000000047061636b00000000")
      (Serializable.Pack.pack (Tuple_t (String_t, Int_t, String_t), ("test", Z.of_int 100, "pack")))

  let test () =
    let open Alcotest in
    "pack test", [
      test_case "bytes" `Quick test_bytes;
      test_case "string" `Quick test_string;
      test_case "int" `Quick test_int;
      test_case "list of int" `Quick test_list_of_int;
      test_case "list of string" `Quick test_list_of_string;
      test_case "list of pair" `Quick test_list_of_pair;
      test_case "pair" `Quick test_pair;
      test_case "tuple" `Quick test_tuple;
    ] ;
end
