(**************************************************************************) (* *) (* Copyright (c) 2014 - 2016. *) (* Dynamic Ledger Solutions, Inc. *) (* *) (* All rights reserved. No warranty, explicit or implicit, provided. *) (* *) (**************************************************************************) let name = "Isolate Michelson" module Logger = Logging.Make(struct let name = name end) let section = Lwt_log.Section.make name let () = Lwt_log.Section.set_level section Lwt_log.Debug(*.Warning*) open Logger open Isolate_helpers open Shorthands let (>>??) = Assert.(>>??) let (>>=??) = Assert.(>>=??) open Tezos_micheline let parse_param s : Proto_alpha.Tezos_context.Script.expr = let (parsed, _) = Michelson_v1_parser.parse_expression s in parsed.expanded let parse_script code_str storage_str : Proto_alpha.Tezos_context.Script.t = let code = parse_param code_str in let storage = parse_param storage_str in let return: Proto_alpha.Tezos_context.Script.t = {code ; storage} in return let program param ret st code = let storage s = " storage " ^ s ^ " ; \n" in let parameter s = " parameter " ^ s ^ " ; \n" in let return s = " return " ^ s ^ " ; \n" in "{\n" ^ (storage st) ^ (parameter param) ^ (return ret) ^ " " ^ code ^ "}" let quote s = "\"" ^ s ^ "\"" let test parse_execute = let dir_path = "test/contracts/" in let test ?tc (file_name: string) (storage: string) (input: string) = let full_path = dir_path ^ file_name ^ ".tz" in let file = Helpers_misc.read_file full_path in let spaced_file = Str.global_replace (Str.regexp_string "\n") "\n " file in let program = "{" ^ spaced_file ^ "}" in parse_execute ?tc program input storage in test let test_fails ?location parse_execute f s i = test parse_execute f s i >>= fun x -> let msg = Option.unopt ~default:"Not failing" location in Assert.generic_economic_error ~msg x ; return () let string_of_canon output_prim = let output_can = Proto_alpha.Michelson_v1_primitives.strings_of_prims output_prim in let location_maker _ = let ret : Micheline_printer.location = {comment=None} in ret in let output_node = Micheline.inject_locations location_maker output_can in Format.fprintf Format.str_formatter "%a" Micheline_printer.print_expr output_node ; let output = Format.flush_str_formatter () in output let test_print parse_execute fn s i = test parse_execute fn s i >>=? fun (sp, op, _) -> let ss = string_of_canon sp in let os = string_of_canon op in debug "Storage : %s" ss ; debug "Output : %s" os ; return () let test_output parse_execute ?location (file_name: string) (storage: string) (input: string) (expected_output: string) = test parse_execute file_name storage input >>=? fun (_storage_prim, output_prim, _tc, _contracts) -> let output = string_of_canon output_prim in let msg = Option.unopt ~default:"strings aren't equal" location in Assert.equal_string ~msg expected_output output ; return () let test_tc ?tc parse_execute (file_name: string) (storage: string) (input: string) = test parse_execute ?tc file_name storage input >>=? fun (_storage_prim, _output_prim, tc, _contracts) -> return (tc) let test_contract ?tc parse_execute (file_name: string) (storage: string) (input: string) = test parse_execute ?tc file_name storage input >>=? fun (_storage_prim, _output_prim, tc, contracts) -> return (contracts, tc) let test_storage parse_execute ?location (file_name: string) (storage: string) (input: string) (expected_storage: string) = test parse_execute file_name storage input >>=? fun (storage_prim, _output_prim, _tc, _contracts) -> let storage = string_of_canon storage_prim in let msg = Option.unopt ~default:"strings aren't equal" location in Assert.equal_string ~msg expected_storage storage ; return () let test_example parse_execute sb = let test_output ?location a b c d = test_output ?location parse_execute a b c d >>= function | Ok(x) -> return x | Error(errs) -> ( match location with | None -> () | Some(loc) -> debug "loc : %s" loc ) ; Lwt.return (Error(errs)) in let test_fails ?location = test_fails ?location parse_execute in let test_tc ?tc = test_tc ?tc parse_execute in let test_contract ?tc = test_contract ?tc parse_execute in (* let test_print ?location = test_print ?location parse_execute in*) let test_storage ?location = test_storage ?location parse_execute in (* FORMAT: assert_output contract_file storage input expected_result *) test_output ~location: __LOC__ "ret_int" "Unit" "Unit" "300" >>=? fun _ -> (* Identity on strings *) test_output ~location: __LOC__ "str_id" "Unit" "\"Hello\"" "\"Hello\"" >>=? fun _ -> test_output ~location: __LOC__ "str_id" "Unit" "\"abcd\"" "\"abcd\"" >>=? fun _ -> (* Identity on pairs *) test_output ~location: __LOC__ "pair_id" "Unit" "(Pair True False)" "(Pair True False)" >>=? fun _ -> test_output ~location: __LOC__ "pair_id" "Unit" "(Pair False True)" "(Pair False True)" >>=? fun _ -> test_output ~location: __LOC__ "pair_id" "Unit" "(Pair True True)" "(Pair True True)" >>=? fun _ -> test_output ~location: __LOC__ "pair_id" "Unit" "(Pair False False)" "(Pair False False)" >>=? fun _ -> (* Logical not *) test_output ~location: __LOC__ "not" "Unit" "True" "False" >>=? fun _ -> test_output ~location: __LOC__ "not" "Unit" "False" "True" >>=? fun _ -> (* Logical and *) test_output ~location: __LOC__ "and" "Unit" "(Pair False False)" "False" >>=? fun _ -> test_output ~location: __LOC__ "and" "Unit" "(Pair False True)" "False" >>=? fun _ -> test_output ~location: __LOC__ "and" "Unit" "(Pair True False)" "False" >>=? fun _ -> test_output ~location: __LOC__ "and" "Unit" "(Pair True True)" "True" >>=? fun _ -> (* Logical or *) test_output ~location: __LOC__ "or" "Unit" "(Pair False False)" "False" >>=? fun _ -> test_output ~location: __LOC__ "or" "Unit" "(Pair False True)" "True" >>=? fun _ -> test_output ~location: __LOC__ "or" "Unit" "(Pair True False)" "True" >>=? fun _ -> test_output ~location: __LOC__ "or" "Unit" "(Pair True True)" "True" >>=? fun _ -> (* XOR *) test_output ~location: __LOC__ "xor" "Unit" "(Pair False False)" "False" >>=? fun _ -> test_output ~location: __LOC__ "xor" "Unit" "(Pair False True)" "True" >>=? fun _ -> test_output ~location: __LOC__ "xor" "Unit" "(Pair True False)" "True" >>=? fun _ -> test_output ~location: __LOC__ "xor" "Unit" "(Pair True True)" "False" >>=? fun _ -> (* Build list *) test_output ~location: __LOC__ "build_list" "Unit" "0" "{ 0 }" >>=? fun _ -> test_output ~location: __LOC__ "build_list" "Unit" "3" "{ 0 ; 1 ; 2 ; 3 }" >>=? fun _ -> test_output ~location: __LOC__ "build_list" "Unit" "10" "{ 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 ; 10 }" >>=? fun _ -> (* Concatenate all strings of a list into one string *) test_output ~location: __LOC__ "concat_list" "Unit" "{ \"a\" ; \"b\" ; \"c\" }" "\"abc\"" >>=? fun _ -> test_output ~location: __LOC__ "concat_list" "Unit" "{}" "\"\"" >>=? fun _ -> test_output ~location: __LOC__ "concat_list" "Unit" "{ \"Hello\" ; \" \" ; \"World\" ; \"!\" }" "\"Hello World!\"" >>=? fun _ -> (* Find maximum int in list -- returns None if not found *) test_output ~location: __LOC__ "max_in_list" "Unit" "{}" "None" >>=? fun _ -> test_output ~location: __LOC__ "max_in_list" "Unit" "{ 1 }" "(Some 1)" >>=? fun _ -> test_output ~location: __LOC__ "max_in_list" "Unit" "{ -1 }" "(Some -1)" >>=? fun _ -> test_output ~location: __LOC__ "max_in_list" "Unit" "{ 10 ; -1 ; -20 ; 100 ; 0 }" "(Some 100)" >>=? fun _ -> test_output ~location: __LOC__ "max_in_list" "Unit" "{ 10 ; -1 ; -20 ; 100 ; 0 }" "(Some 100)" >>=? fun _ -> test_output ~location: __LOC__ "max_in_list" "Unit" "{ -10 ; -1 ; -20 ; -100 }" "(Some -1)" >>=? fun _ -> (* Identity on lists *) test_output ~location: __LOC__ "list_id" "Unit" "{ \"1\" ; \"2\" ; \"3\" }" "{ \"1\" ; \"2\" ; \"3\" }" >>=? fun _ -> test_output ~location: __LOC__ "list_id" "Unit" "{}" "{}" >>=? fun _ -> test_output ~location: __LOC__ "list_id" "Unit" "{ \"a\" ; \"b\" ; \"c\" }" "{ \"a\" ; \"b\" ; \"c\" }" >>=? fun _ -> test_output ~location: __LOC__ "list_id_map" "Unit" "{ \"1\" ; \"2\" ; \"3\" }" "{ \"1\" ; \"2\" ; \"3\" }" >>=? fun _ -> test_output ~location: __LOC__ "list_id_map" "Unit" "{}" "{}" >>=? fun _ -> test_output ~location: __LOC__ "list_id_map" "Unit" "{ \"a\" ; \"b\" ; \"c\" }" "{ \"a\" ; \"b\" ; \"c\" }" >>=? fun _ -> (* Identity on maps *) test_output ~location: __LOC__ "map_id" "Unit" "{ Elt 0 1 }" "{ Elt 0 1 }" >>=? fun _ -> test_output ~location: __LOC__ "map_id" "Unit" "{ Elt 0 0 }" "{ Elt 0 0 }" >>=? fun _ -> test_output ~location: __LOC__ "map_id" "Unit" "{ Elt 0 0 ; Elt 3 4 }" "{ Elt 0 0 ; Elt 3 4 }" >>=? fun _ -> (* Map block on lists *) test_output ~location: __LOC__ "list_map_block" "Unit" "{}" "{}" >>=? fun _ -> test_output ~location: __LOC__ "list_map_block" "Unit" "{ 1 ; 1 ; 1 ; 1 }" "{ 1 ; 2 ; 3 ; 4 }" >>=? fun _ -> test_output ~location: __LOC__ "list_map_block" "Unit" "{ 1 ; 2 ; 3 ; 0 }" "{ 1 ; 3 ; 5 ; 3 }" >>=? fun _ -> (* List iter *) test_output ~location: __LOC__ "list_iter" "Unit" "{ 10 ; 2 ; 1 }" "20" >>=? fun _ -> test_output ~location: __LOC__ "list_iter" "Unit" "{ 3 ; 6 ; 9 }" "162" >>=? fun _ -> test_output ~location: __LOC__ "list_iter2" "Unit" "{ \"a\" ; \"b\" ; \"c\" }" "\"cba\"" >>=? fun _ -> test_output ~location: __LOC__ "list_iter2" "Unit" "{}" "\"\"" >>=? fun _ -> (* Identity on sets *) test_output ~location: __LOC__ "set_id" "Unit" "{ \"a\" ; \"b\" ; \"c\" }" "{ \"a\" ; \"b\" ; \"c\" }" >>=? fun _ -> test_output ~location: __LOC__ "set_id" "Unit" "{}" "{}" >>=? fun _ -> test_output ~location: __LOC__ "set_id" "Unit" "{ \"asdf\" ; \"bcde\" }" "{ \"asdf\" ; \"bcde\" }" >>=? fun _ -> (* Set member -- set is in storage *) test_output ~location: __LOC__ "set_member" "{}" "\"Hi\"" "False" >>=? fun _ -> test_output ~location: __LOC__ "set_member" "{ \"Hi\" }" "\"Hi\"" "True" >>=? fun _ -> test_output ~location: __LOC__ "set_member" "{ \"Hello\" ; \"World\" }" "\"\"" "False" >>=? fun _ -> (* Set size *) test_output ~location: __LOC__ "set_size" "Unit" "{}" "0" >>=? fun _ -> test_output ~location: __LOC__ "set_size" "Unit" "{ 1 }" "1" >>=? fun _ -> test_output ~location: __LOC__ "set_size" "Unit" "{ 1 ; 2 ; 3 }" "3" >>=? fun _ -> test_output ~location: __LOC__ "set_size" "Unit" "{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }" "6" >>=? fun _ -> (* Set iter *) test_output ~location: __LOC__ "set_iter" "Unit" "{}" "0" >>=? fun _ -> test_output ~location: __LOC__ "set_iter" "Unit" "{ 1 }" "1" >>=? fun _ -> test_output ~location: __LOC__ "set_iter" "Unit" "{ -100 ; 1 ; 2 ; 3 }" "-94" >>=? fun _ -> (* Map size *) test_output ~location: __LOC__ "map_size" "Unit" "{}" "0" >>=? fun _ -> test_output ~location: __LOC__ "map_size" "Unit" "{ Elt \"a\" 1 }" "1" >>=? fun _ -> test_output ~location: __LOC__ "map_size" "Unit" "{ Elt \"a\" 1 ; Elt \"b\" 2 ; Elt \"c\" 3 }" "3" >>=? fun _ -> test_output ~location: __LOC__ "map_size" "Unit" "{ Elt \"a\" 1 ; Elt \"b\" 2 ; Elt \"c\" 3 ; Elt \"d\" 4 ; Elt \"e\" 5 ; Elt \"f\" 6 }" "6" >>=? fun _ -> (* Contains all elements -- does the second list contain all of the same elements *) (* as the first one? I'm ignoring element multiplicity *) test_output ~location: __LOC__ "contains_all" "Unit" "(Pair {} {})" "True" >>=? fun _ -> test_output ~location: __LOC__ "contains_all" "Unit" "(Pair { \"a\" } { \"B\" })" "False" >>=? fun _ -> test_output ~location: __LOC__ "contains_all" "Unit" "(Pair { \"A\" } { \"B\" })" "False" >>=? fun _ -> test_output ~location: __LOC__ "contains_all" "Unit" "(Pair { \"B\" } { \"B\" })" "True" >>=? fun _ -> test_output ~location: __LOC__ "contains_all" "Unit" "(Pair { \"B\" ; \"C\" ; \"asdf\" } { \"B\" ; \"B\" ; \"asdf\" ; \"C\" })" "True" >>=? fun _ -> test_output ~location: __LOC__ "contains_all" "Unit" "(Pair { \"B\" ; \"B\" ; \"asdf\" ; \"C\" } { \"B\" ; \"C\" ; \"asdf\" })" "True" >>=? fun _ -> (* Concatenate the string in storage with all strings in the given list *) test_output ~location: __LOC__ "concat_hello" "Unit" "{ \"World!\" }" "{ \"Hello World!\" }" >>=? fun _ -> test_output ~location: __LOC__ "concat_hello" "Unit" "{}" "{}" >>=? fun _ -> test_output ~location: __LOC__ "concat_hello" "Unit" "{ \"test1\" ; \"test2\" }" "{ \"Hello test1\" ; \"Hello test2\" }" >>=? fun _ -> (* Create an empty map and add a string to it *) test_output ~location: __LOC__ "empty_map" "Unit" "Unit" "{ Elt \"hello\" \"world\" }" >>=? fun _ -> (* Get the value stored at the given key in the map *) test_output ~location: __LOC__ "get_map_value" "{ Elt \"hello\" \"hi\" }" "\"hello\"" "(Some \"hi\")" >>=? fun _ -> test_output ~location: __LOC__ "get_map_value" "{ Elt \"hello\" \"hi\" }" "\"\"" "None" >>=? fun _ -> test_output ~location: __LOC__ "get_map_value" "{ Elt \"1\" \"one\" ; Elt \"2\" \"two\" }" "\"1\"" "(Some \"one\")" >>=? fun _ -> (* Map iter *) test_output ~location: __LOC__ "map_iter" "Unit" "{ Elt 0 100 ; Elt 2 100 }" "(Pair 2 200)" >>=? fun _ -> test_output ~location: __LOC__ "map_iter" "Unit" "{ Elt 1 1 ; Elt 2 100 }" "(Pair 3 101)" >>=? fun _ -> (* Return True if True branch of if was taken and False otherwise *) test_output ~location: __LOC__ "if" "Unit" "True" "True" >>=? fun _ -> test_output ~location: __LOC__ "if" "Unit" "False" "False" >>=? fun _ -> (* Generate a pair of or types *) test_output ~location: __LOC__ "swap_left_right" "Unit" "(Left True)" "(Right True)" >>=? fun _ -> test_output ~location: __LOC__ "swap_left_right" "Unit" "(Right \"a\")" "(Left \"a\")" >>=? fun _ -> (* Reverse a list *) test_output ~location: __LOC__ "reverse" "Unit" "{}" "{}" >>=? fun _ -> test_output ~location: __LOC__ "reverse" "Unit" "{ \"c\" ; \"b\" ; \"a\" }" "{ \"a\" ; \"b\" ; \"c\" }" >>=? fun _ -> test_output ~location: __LOC__ "reverse_loop" "Unit" "{}" "{}" >>=? fun _ -> test_output ~location: __LOC__ "reverse_loop" "Unit" "{ \"c\" ; \"b\" ; \"a\" }" "{ \"a\" ; \"b\" ; \"c\" }" >>=? fun _ -> (* Reverse using LOOP_LEFT *) test_output ~location: __LOC__ "loop_left" "Unit" "{}" "{}" >>=? fun _ -> test_output ~location: __LOC__ "loop_left" "Unit" "{ \"c\" ; \"b\" ; \"a\" }" "{ \"a\" ; \"b\" ; \"c\" }" >>=? fun _ -> (* Exec concat contract *) test_output ~location: __LOC__ "exec_concat" "Unit" "\"\"" "\"_abc\"" >>=? fun _ -> test_output ~location: __LOC__ "exec_concat" "Unit" "\"test\"" "\"test_abc\"" >>=? fun _ -> (* Get current steps to quota *) test_output ~location: __LOC__ "steps_to_quota" "Unit" "Unit" "39991" >>=? fun _ -> let bootstrap_0 = List.nth Account.bootstrap_accounts 0 in get_balance_res bootstrap_0 sb >>=?? fun _balance -> let amount = Proto_alpha.Tezos_context.Tez.to_string @@ Cast.cents_of_int Script.init_amount in (* Get the current balance of the contract *) test_output ~location: __LOC__ "balance" "Unit" "Unit" ("\"" ^ amount ^ "\"") >>=? fun _ -> (* Test comparisons on tez { EQ ; GT ; LT ; GE ; LE } *) test_output ~location: __LOC__ "compare" "Unit" "(Pair \"1.00\" \"2.00\")" "{ False ; False ; True ; False ; True }" >>=? fun _ -> test_output ~location: __LOC__ "compare" "Unit" "(Pair \"2.00\" \"1.00\")" "{ False ; True ; False ; True ; False }" >>=? fun _ -> test_output ~location: __LOC__ "compare" "Unit" "(Pair \"2.37\" \"2.37\")" "{ True ; False ; False ; True ; True }" >>=? fun _ -> (* Test addition and subtraction on tez *) test_output ~location: __LOC__ "tez_add_sub" "Unit" "(Pair \"2\" \"1\")" "(Pair \"3\" \"1\")" >>=? fun _ -> test_output ~location: __LOC__ "tez_add_sub" "Unit" "(Pair \"2.31\" \"1.01\")" "(Pair \"3.32\" \"1.3\")" >>=? fun _ -> (* Test get first element of list *) test_output ~location: __LOC__ "first" "Unit" "{ 1 ; 2 ; 3 ; 4 }" "1" >>=? fun _ -> test_output ~location: __LOC__ "first" "Unit" "{ 4 }" "4" >>=? fun _ -> (* Hash input string *) (* Test assumed to be correct -- hash is based on encoding of AST *) test_output ~location: __LOC__ "hash_string" "Unit" "\"abcdefg\"" "\"exprv3MnhXvjthGzZ7jDtXRRFremZyey9rsGtL7JRkeaQX1fThN7WF\"" >>=? fun _ -> test_output ~location: __LOC__ "hash_string" "Unit" "\"12345\"" "\"expru81QVHsW2qaWLNHnMHSxDNhqtat17ajadri6mKUvXyc2EWHZC3\"" >>=? fun _ -> (* Test ASSERT *) test_output ~location: __LOC__ "assert" "Unit" "True" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert" "Unit" "False" >>=? fun _ -> (* COMPARE ; ASSERT_ *) test_output ~location: __LOC__ "assert_eq" "Unit" "(Pair -1 -1)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_eq" "Unit" "(Pair 0 -1)" >>=? fun _ -> test_output ~location: __LOC__ "assert_eq" "Unit" "(Pair -1 -1)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_eq" "Unit" "(Pair 0 -1)" >>=? fun _ -> test_output ~location: __LOC__ "assert_neq" "Unit" "(Pair 0 -1)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_neq" "Unit" "(Pair -1 -1)" >>=? fun _ -> test_output ~location: __LOC__ "assert_lt" "Unit" "(Pair -1 0)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_lt" "Unit" "(Pair 0 -1)" >>=? fun _ -> test_fails ~location: __LOC__ "assert_lt" "Unit" "(Pair 0 0)" >>=? fun _ -> test_output ~location: __LOC__ "assert_le" "Unit" "(Pair 0 0)" "Unit" >>=? fun _ -> test_output ~location: __LOC__ "assert_le" "Unit" "(Pair -1 0)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_le" "Unit" "(Pair 0 -1)" >>=? fun _ -> test_output ~location: __LOC__ "assert_gt" "Unit" "(Pair 0 -1)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_gt" "Unit" "(Pair -1 0)" >>=? fun _ -> test_fails ~location: __LOC__ "assert_gt" "Unit" "(Pair 0 0)" >>=? fun _ -> test_output ~location: __LOC__ "assert_ge" "Unit" "(Pair 0 0)" "Unit" >>=? fun _ -> test_output ~location: __LOC__ "assert_ge" "Unit" "(Pair 0 -1)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_ge" "Unit" "(Pair -1 0)" >>=? fun _ -> (* ASSERT_CMP *) test_output ~location: __LOC__ "assert_cmpeq" "Unit" "(Pair -1 -1)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_cmpeq" "Unit" "(Pair 0 -1)" >>=? fun _ -> test_output ~location: __LOC__ "assert_cmpeq" "Unit" "(Pair -1 -1)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_cmpeq" "Unit" "(Pair 0 -1)" >>=? fun _ -> test_output ~location: __LOC__ "assert_cmpneq" "Unit" "(Pair 0 -1)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_cmpneq" "Unit" "(Pair -1 -1)" >>=? fun _ -> test_output ~location: __LOC__ "assert_cmplt" "Unit" "(Pair -1 0)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_cmplt" "Unit" "(Pair 0 -1)" >>=? fun _ -> test_fails ~location: __LOC__ "assert_cmplt" "Unit" "(Pair 0 0)" >>=? fun _ -> test_output ~location: __LOC__ "assert_cmple" "Unit" "(Pair 0 0)" "Unit" >>=? fun _ -> test_output ~location: __LOC__ "assert_cmple" "Unit" "(Pair -1 0)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_cmple" "Unit" "(Pair 0 -1)" >>=? fun _ -> test_output ~location: __LOC__ "assert_cmpgt" "Unit" "(Pair 0 -1)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_cmpgt" "Unit" "(Pair -1 0)" >>=? fun _ -> test_fails ~location: __LOC__ "assert_cmpgt" "Unit" "(Pair 0 0)" >>=? fun _ -> test_output ~location: __LOC__ "assert_cmpge" "Unit" "(Pair 0 0)" "Unit" >>=? fun _ -> test_output ~location: __LOC__ "assert_cmpge" "Unit" "(Pair 0 -1)" "Unit" >>=? fun _ -> test_fails ~location: __LOC__ "assert_cmpge" "Unit" "(Pair -1 0)" >>=? fun _ -> (* IF_SOME *) test_output ~location: __LOC__ "if_some" "Unit" "(Some \"hello\")" "\"hello\"" >>=? fun _ -> test_output ~location: __LOC__ "if_some" "Unit" "None" "\"\"" >>=? fun _ -> (* Tests the SET_CAR and SET_CDR instructions *) test_output ~location: __LOC__ "set_car" "(Pair \"hello\" 0)" "\"world\"" "(Pair \"world\" 0)" >>=? fun _ -> test_output ~location: __LOC__ "set_car" "(Pair \"hello\" 0)" "\"abc\"" "(Pair \"abc\" 0)" >>=? fun _ -> test_output ~location: __LOC__ "set_car" "(Pair \"hello\" 0)" "\"\"" "(Pair \"\" 0)" >>=? fun _ -> test_output ~location: __LOC__ "set_cdr" "(Pair \"hello\" 0)" "1" "(Pair \"hello\" 1)" >>=? fun _ -> test_output ~location: __LOC__ "set_cdr" "(Pair \"hello\" 500)" "3" "(Pair \"hello\" 3)" >>=? fun _ -> test_output ~location: __LOC__ "set_cdr" "(Pair \"hello\" 7)" "100" "(Pair \"hello\" 100)" >>=? fun _ -> test_storage ~location: __LOC__ "set_caddaadr" "(Pair (Pair 1 (Pair 2 (Pair (Pair (Pair 3 \"0\") 4) 5))) 6)" "\"3\"" "(Pair (Pair 1 (Pair 2 (Pair (Pair (Pair 3 \"3\") 4) 5))) 6)" >>=? fun _ -> test_storage ~location: __LOC__ "map_caddaadr" "(Pair (Pair 1 (Pair 2 (Pair (Pair (Pair 3 \"0\") 4) 5))) 6)" "Unit" "(Pair (Pair 1 (Pair 2 (Pair (Pair (Pair 3 \"1\") 4) 5))) 6)" >>=? fun _ -> (* Did the given key sign the string? (key is bootstrap1) *) test_output ~location: __LOC__ "check_signature" "(Pair \"26981d372a7b3866621bf79713d249197fe6d518ef702fa65738e1715bde9da54df04fefbcc84287ecaa9f74ad9296462731aa24bbcece63c6bf73a8f5752309\" \"hello\")" "\"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav\"" "True" >>=? fun _ -> test_output ~location: __LOC__ "check_signature" "(Pair \"26981d372a7b3866621bf79713d249197fe6d518ef702fa65738e1715bde9da54df04fefbcc84287ecaa9f74ad9296462731aa24bbcece63c6bf73a8f5752309\" \"abcd\")" "\"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav\"" "False" >>=? fun _ -> (* Convert a public key to a public key hash *) test_output ~location: __LOC__ "hash_key" "Unit" "\"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav\"" "\"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx\"" >>=? fun _ -> test_output ~location: __LOC__ "hash_key" "Unit" "\"edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTawUPqR8vZTAMcx61ES\"" "\"tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k\"" >>=? fun _ -> (* Test timestamp operations *) test_output ~location: __LOC__ "add_timestamp_delta" "Unit" "(Pair 100 100)" "\"1970-01-01T00:03:20Z\"" >>=? fun _ -> test_output ~location: __LOC__ "add_timestamp_delta" "Unit" "(Pair 100 -100)" "\"1970-01-01T00:00:00Z\"" >>=? fun _ -> test_output ~location: __LOC__ "add_timestamp_delta" "Unit" "(Pair \"1970-01-01T00:00:00Z\" 0)" "\"1970-01-01T00:00:00Z\"" >>=? fun _ -> test_output ~location: __LOC__ "add_delta_timestamp" "Unit" "(Pair 100 100)" "\"1970-01-01T00:03:20Z\"" >>=? fun _ -> test_output ~location: __LOC__ "add_delta_timestamp" "Unit" "(Pair -100 100)" "\"1970-01-01T00:00:00Z\"" >>=? fun _ -> test_output ~location: __LOC__ "add_delta_timestamp" "Unit" "(Pair 0 \"1970-01-01T00:00:00Z\")" "\"1970-01-01T00:00:00Z\"" >>=? fun _ -> test_output ~location: __LOC__ "sub_timestamp_delta" "Unit" "(Pair 100 100)" "\"1970-01-01T00:00:00Z\"" >>=? fun _ -> test_output ~location: __LOC__ "sub_timestamp_delta" "Unit" "(Pair 100 -100)" "\"1970-01-01T00:03:20Z\"" >>=? fun _ -> test_output ~location: __LOC__ "sub_timestamp_delta" "Unit" "(Pair 100 2000000000000000000)" "-1999999999999999900" >>=? fun _ -> test_output ~location: __LOC__ "diff_timestamps" "Unit" "(Pair 0 0)" "0" >>=? fun _ -> test_output ~location: __LOC__ "diff_timestamps" "Unit" "(Pair 0 1)" "-1" >>=? fun _ -> test_output ~location: __LOC__ "diff_timestamps" "Unit" "(Pair 1 0)" "1" >>=? fun _ -> test_output ~location: __LOC__ "diff_timestamps" "Unit" "(Pair \"1970-01-01T00:03:20Z\" \"1970-01-01T00:00:00Z\")" "200" >>=? fun _ -> (* Test NOW *) let now = sb.tezos_header.shell.timestamp in let now_str = quote @@ Tezos_base.Time.to_notation now in test_storage ~location: __LOC__ "store_now" "\"1970-01-01T00:03:20Z\"" "Unit" now_str >>=? fun _ -> (* Test TRANSFER_TO *) Account.make_account ~tc: sb.tezos_context >>=?? fun (account, tc) -> let account_str = quote @@ Ed25519.Public_key_hash.to_b58check account.hpub in test_tc ~tc "transfer_to" "Unit" account_str >>=? fun tc -> let amount = Account.init_amount + 100 in Assert.equal_cents_balance ~tc (account.contract, amount * 100) >>=?? fun _ -> (* Test CREATE_ACCOUNT *) Account.make_account ~tc: sb.tezos_context >>=?? fun (account, tc) -> let account_str = quote @@ Ed25519.Public_key_hash.to_b58check account.hpub in test_contract ~tc "create_account" account_str account_str >>=? fun (cs, tc) -> Assert.equal_int 1 @@ List.length cs ; (* Test CREATE_CONTRACT *) test_contract ~tc "create_contract" account_str account_str >>=? fun (cs, tc) -> Assert.equal_int 1 @@ List.length cs ; let contract = List.hd cs in Proto_alpha.Tezos_context.Contract.get_script tc contract >>=?? fun res -> let script = Option.unopt_exn (Failure "get_script") res in Script.execute_code_pred ~tc sb script (parse_param "\"abc\"") >>=?? fun (_, ret, _, _, _) -> Assert.equal_string ~msg: __LOC__ "\"abc\"" @@ string_of_canon ret ; (* Test DEFAULT_ACCOUNT *) let account = Account.new_account () in let b_str = quote @@ Ed25519.Public_key_hash.to_b58check account.hpub in test_contract ~tc "default_account" "Unit" b_str >>=? fun (_cs, tc) -> Assert.equal_cents_balance ~tc (account.contract, 100 * 100) >>=?? fun _ -> return () let test_program parse_execute = let open Error_monad in let id_code = "code { DUP ; PAIR ; CAR }" in let id_int_program = program "int" "int" "int" id_code in let id_ill_param_program = program "string" "int" "string" id_code in let id_ill_return_program = program "int" "string" "int" id_code in let id_pbool_program = program "(pair bool bool)" "(pair bool bool)" "unit" id_code in let push_300_code = "code { CAR ; PUSH nat 300 ; PAIR }" in let push_300 = program "unit" "nat" "unit" push_300_code in parse_execute id_int_program "2" "3" >>=? fun _ -> parse_execute id_ill_param_program "2" "3" >>= fun x -> Assert.ill_typed_data_error ~msg: "Good data type" x ; parse_execute id_ill_return_program "2" "3" >>= fun x -> Assert.ill_typed_return_error ~msg: "Good return type" x ; parse_execute push_300 "Unit" "Unit" >>=? fun _ -> parse_execute id_pbool_program "(Pair True True)" "Unit" >>=? fun _ -> return () let main (): unit Error_monad.tzresult Lwt.t = Init.main () >>=? fun sb -> let execute_code ?tc = Script.execute_code_pred ?tc sb in let parse_execute ?tc code_str param_str storage_str = let param = parse_param param_str in let script = parse_script code_str storage_str in execute_code ?tc script param >>=?? fun (ret, st, _, tc, nonce) -> let contracts = Proto_alpha.Tezos_context.Contract.originated_contracts nonce in return (ret, st, tc, contracts) in test_program parse_execute >>=? fun _x -> test_example parse_execute sb >>=? fun _x -> return () let tests = [ "main", (fun _ -> main ()) ; ] let main () = Test.run "michelson." tests