From 545c3ad7319d015213adfec30231b682fe8da432 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sat, 3 Dec 2022 19:00:52 +0800 Subject: [PATCH] Test: migrate test_contract.py::TestView to Tezt --- .../expected/views.ml/Alpha- Run views.out | 102 ++-- tezt/tests/views.ml | 471 +++++++++++++++++- 2 files changed, 504 insertions(+), 69 deletions(-) diff --git a/tezt/tests/expected/views.ml/Alpha- Run views.out b/tezt/tests/expected/views.ml/Alpha- Run views.out index 23f5e391928f..7376d59f74a6 100644 --- a/tezt/tests/expected/views.ml/Alpha- Run views.out +++ b/tezt/tests/expected/views.ml/Alpha- Run views.out @@ -1,5 +1,5 @@ -./octez-client --mode mockup --base-dir '' --wait none originate contract register_calls transferring 0 from bootstrap1 running ' +./octez-client --mode mockup --wait none originate contract register_calls transferring 0 from bootstrap1 running ' parameter unit; storage (list address); code { @@ -16,23 +16,23 @@ Node is bootstrapped. Estimated gas: 1430.736 units (will add 100 for safety) Estimated storage: 409 bytes added (will add 20 for safety) Operation successfully injected in the node. -Operation hash is 'ooRkfUHnsTEfQ8SKpGCSop6iptg4dosoRybUNnZ2DD1Zw4RSAFJ' +Operation hash is '[OPERATION_HASH]' NOT waiting for the operation to be included. Use command - octez-client wait for ooRkfUHnsTEfQ8SKpGCSop6iptg4dosoRybUNnZ2DD1Zw4RSAFJ to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: - From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + From: [PUBLIC_KEY_HASH] Fee to the baker: ꜩ0.000533 Expected counter: 1 Gas limit: 1531 Storage limit: 429 bytes Balance updates: - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.000533 + [PUBLIC_KEY_HASH] ... -ꜩ0.000533 payload fees(the block proposer) ....... +ꜩ0.000533 Origination: - From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + From: [PUBLIC_KEY_HASH] Credit: ꜩ0 Script: { parameter unit ; @@ -47,20 +47,20 @@ This sequence of operations was run: No delegate for this contract This origination was successfully applied Originated contracts: - KT1PgzSR3Q6vij3daRpdNfQyffBmYK4BkwW7 + [CONTRACT_HASH] Storage size: 152 bytes Paid storage size diff: 152 bytes Consumed gas: 1430.736 Balance updates: - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.038 + [PUBLIC_KEY_HASH] ... -ꜩ0.038 storage fees ........................... +ꜩ0.038 - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 storage fees ........................... +ꜩ0.06425 -New contract KT1PgzSR3Q6vij3daRpdNfQyffBmYK4BkwW7 originated. +New contract [CONTRACT_HASH] originated. Contract memorized as register_calls. -./octez-client --mode mockup --base-dir '' --wait none originate contract check_caller transferring 0 from bootstrap1 running ' +./octez-client --mode mockup --wait none originate contract check_caller transferring 0 from bootstrap1 running ' parameter address ; storage (option address) ; code { @@ -91,23 +91,23 @@ Node is bootstrapped. Estimated gas: 1454.220 units (will add 100 for safety) Estimated storage: 465 bytes added (will add 20 for safety) Operation successfully injected in the node. -Operation hash is 'oojctTDMYh47PEbLRq7feuBf77DG8PcPD137Uqi6cCo9My6Wgva' +Operation hash is '[OPERATION_HASH]' NOT waiting for the operation to be included. Use command - octez-client wait for oojctTDMYh47PEbLRq7feuBf77DG8PcPD137Uqi6cCo9My6Wgva to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: - From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + From: [PUBLIC_KEY_HASH] Fee to the baker: ꜩ0.000591 Expected counter: 2 Gas limit: 1555 Storage limit: 485 bytes Balance updates: - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.000591 + [PUBLIC_KEY_HASH] ... -ꜩ0.000591 payload fees(the block proposer) ....... +ꜩ0.000591 Origination: - From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + From: [PUBLIC_KEY_HASH] Credit: ꜩ0 Script: { parameter address ; @@ -130,122 +130,122 @@ This sequence of operations was run: No delegate for this contract This origination was successfully applied Originated contracts: - KT1BEZadf1sAZ3jjoBJzEgBLhNXpv7WZHDc3 + [CONTRACT_HASH] Storage size: 208 bytes Paid storage size diff: 208 bytes Consumed gas: 1454.220 Balance updates: - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.052 + [PUBLIC_KEY_HASH] ... -ꜩ0.052 storage fees ........................... +ꜩ0.052 - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 storage fees ........................... +ꜩ0.06425 -New contract KT1BEZadf1sAZ3jjoBJzEgBLhNXpv7WZHDc3 originated. +New contract [CONTRACT_HASH] originated. Contract memorized as check_caller. -./octez-client --mode mockup --base-dir '' --wait none transfer 1 from bootstrap1 to KT1BEZadf1sAZ3jjoBJzEgBLhNXpv7WZHDc3 --burn-cap 1 --arg '"KT1PgzSR3Q6vij3daRpdNfQyffBmYK4BkwW7"' +./octez-client --mode mockup --wait none transfer 1 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg '"[CONTRACT_HASH]"' Node is bootstrapped. Estimated gas: 4413.514 units (will add 100 for safety) Estimated storage: no bytes added Operation successfully injected in the node. -Operation hash is 'opJoacsqxhcszPfYAgwpBGKqMfoyjZmu9CqBmmiiQtLQB5emLRa' +Operation hash is '[OPERATION_HASH]' NOT waiting for the operation to be included. Use command - octez-client wait for opJoacsqxhcszPfYAgwpBGKqMfoyjZmu9CqBmmiiQtLQB5emLRa to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: - From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + From: [PUBLIC_KEY_HASH] Fee to the baker: ꜩ0.000748 Expected counter: 3 Gas limit: 4514 Storage limit: 0 bytes Balance updates: - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.000748 + [PUBLIC_KEY_HASH] ... -ꜩ0.000748 payload fees(the block proposer) ....... +ꜩ0.000748 Transaction: Amount: ꜩ1 - From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx - To: KT1BEZadf1sAZ3jjoBJzEgBLhNXpv7WZHDc3 - Parameter: "KT1PgzSR3Q6vij3daRpdNfQyffBmYK4BkwW7" + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" This transaction was successfully applied Updated storage: None Storage size: 208 bytes Consumed gas: 4414.159 Balance updates: - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ1 - KT1BEZadf1sAZ3jjoBJzEgBLhNXpv7WZHDc3 ... +ꜩ1 + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 -./octez-client --mode mockup --base-dir '' --wait none transfer 1 from bootstrap1 to KT1PgzSR3Q6vij3daRpdNfQyffBmYK4BkwW7 --burn-cap 1 +./octez-client --mode mockup --wait none transfer 1 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 Node is bootstrapped. Estimated gas: 2117.241 units (will add 100 for safety) Estimated storage: 27 bytes added (will add 20 for safety) Operation successfully injected in the node. -Operation hash is 'onmjSitNnrxA6xCd4u2Ti6Kzyx8HJJoeYW6gs7rk5wdCZkgY2jE' +Operation hash is '[OPERATION_HASH]' NOT waiting for the operation to be included. Use command - octez-client wait for onmjSitNnrxA6xCd4u2Ti6Kzyx8HJJoeYW6gs7rk5wdCZkgY2jE to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: - From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + From: [PUBLIC_KEY_HASH] Fee to the baker: ꜩ0.000472 Expected counter: 4 Gas limit: 2218 Storage limit: 47 bytes Balance updates: - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.000472 + [PUBLIC_KEY_HASH] ... -ꜩ0.000472 payload fees(the block proposer) ....... +ꜩ0.000472 Transaction: Amount: ꜩ1 - From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx - To: KT1PgzSR3Q6vij3daRpdNfQyffBmYK4BkwW7 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] This transaction was successfully applied Updated storage: { 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 } Storage size: 179 bytes Paid storage size diff: 27 bytes Consumed gas: 2117.929 Balance updates: - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.00675 + [PUBLIC_KEY_HASH] ... -ꜩ0.00675 storage fees ........................... +ꜩ0.00675 - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ1 - KT1PgzSR3Q6vij3daRpdNfQyffBmYK4BkwW7 ... +ꜩ1 + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 -./octez-client --mode mockup --base-dir '' --wait none transfer 1 from bootstrap1 to KT1BEZadf1sAZ3jjoBJzEgBLhNXpv7WZHDc3 --burn-cap 1 --arg '"KT1PgzSR3Q6vij3daRpdNfQyffBmYK4BkwW7"' +./octez-client --mode mockup --wait none transfer 1 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg '"[CONTRACT_HASH]"' Node is bootstrapped. Estimated gas: 4417.116 units (will add 100 for safety) Estimated storage: 27 bytes added (will add 20 for safety) Operation successfully injected in the node. -Operation hash is 'oof17dNHXXM2Wc6Nv7iM6utwj7NPQPi1oSPdpFWu5PtafGYCAn9' +Operation hash is '[OPERATION_HASH]' NOT waiting for the operation to be included. Use command - octez-client wait for oof17dNHXXM2Wc6Nv7iM6utwj7NPQPi1oSPdpFWu5PtafGYCAn9 to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: - From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + From: [PUBLIC_KEY_HASH] Fee to the baker: ꜩ0.000748 Expected counter: 5 Gas limit: 4518 Storage limit: 47 bytes Balance updates: - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.000748 + [PUBLIC_KEY_HASH] ... -ꜩ0.000748 payload fees(the block proposer) ....... +ꜩ0.000748 Transaction: Amount: ꜩ1 - From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx - To: KT1BEZadf1sAZ3jjoBJzEgBLhNXpv7WZHDc3 - Parameter: "KT1PgzSR3Q6vij3daRpdNfQyffBmYK4BkwW7" + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" This transaction was successfully applied Updated storage: (Some 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78) Storage size: 235 bytes Paid storage size diff: 27 bytes Consumed gas: 4417.761 Balance updates: - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.00675 + [PUBLIC_KEY_HASH] ... -ꜩ0.00675 storage fees ........................... +ꜩ0.00675 - tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ1 - KT1BEZadf1sAZ3jjoBJzEgBLhNXpv7WZHDc3 ... +ꜩ1 + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 diff --git a/tezt/tests/views.ml b/tezt/tests/views.ml index 36c2fbe0d422..b32d5e15ab64 100644 --- a/tezt/tests/views.ml +++ b/tezt/tests/views.ml @@ -32,6 +32,16 @@ (* This contract registers all SOURCE addresses that ever call it. It has views that return registered callers count and the last caller address respectively. *) + +let contract_path protocol kind contract = + sf + "file:tests_python/contracts_%s/%s/%s" + (match protocol with + | Protocol.Alpha -> "alpha" + | _ -> sf "%03d" @@ Protocol.number protocol) + kind + contract + let register_callers_src = {| parameter unit; @@ -79,22 +89,9 @@ code { } |} -(* Normally "--base-dir" would appear in regression logs. However, since - it is a different dir on every run, we need to mask it in regression - logs so that it doesn't cause false differences. *) -let hooks = - let rec mask_temp_dir = function - | [] -> [] - | "--base-dir" :: _ :: rest -> "--base-dir" :: "" :: rest - | arg :: args -> arg :: mask_temp_dir args - in - { - Regression.hooks with - on_spawn = - (fun cmd args -> mask_temp_dir args |> Regression.hooks.on_spawn cmd); - } - -let register = +let hooks = Tezos_regression.hooks + +let test_regression = Protocol.register_regression_test ~__FILE__ ~title:"Run views" @@ -112,7 +109,7 @@ let register = ~init:"{}" client in - let arg = Format.sprintf "\"%s\"" register_callers in + let arg = sf "%S" register_callers in let* check_caller = Client.originate_contract ~hooks @@ -153,4 +150,442 @@ let register = ~arg client in - return () + unit + +let deploy_lib_contract ?(amount = Tez.zero) ~protocol client = + Client.originate_contract + ~hooks + ~burn_cap:Tez.one + ~alias:"lib" + ~amount + ~src:Constant.bootstrap1.alias + ~prg:(contract_path protocol "opcodes" "view_toplevel_lib.tz") + ~init:"3" + client + +let test_run_view protocol ~contract ~init ~expected = + let* client = Client.init_mockup ~protocol () in + let* lib_contract = deploy_lib_contract ~protocol client in + let prg = contract_path protocol "opcodes" @@ sf "view_%s.tz" contract in + let* contract = + Client.originate_contract + ~hooks + ~burn_cap:Tez.one + ~alias:"view" + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~prg + ~init + client + in + let arg = sf "(Pair 10 \"%s\")" lib_contract in + let* () = + Client.transfer + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract + ~arg + client + in + let* actual = + Client.contract_storage ~unparsing_mode:Optimized contract client + in + Check.((String.trim actual = expected) string) + ~error_msg:"expected storage %R, got %L" ; + unit + +let test_all_view_runs protocols = + [ + ("op_id", "(Pair 0 0)", "Pair 10 3"); + ("op_add", "42", "13"); + ("fib", "0", "55"); + ("mutual_recursion", "0", "20"); + ("op_nonexistent_func", "True", "False"); + ("op_nonexistent_addr", "True", "False"); + ("op_toplevel_inconsistent_input_type", "5", "0"); + ("op_toplevel_inconsistent_output_type", "True", "False"); + ] + |> List.iter @@ fun (contract, init, expected) -> + Protocol.register_test + ~__FILE__ + ~title:(sf "Test view runtimes - %s - %s" contract init) + ~tags:["client"; "michelson"] + (fun protocol -> test_run_view ~contract ~init ~expected protocol) + protocols + +let test_create_contract = + Protocol.register_test + ~__FILE__ + ~title:"Create contract with view" + ~tags:["client"; "michelson"] + @@ fun protocol -> + let* client = Client.init_mockup ~protocol () in + let* contract = + Client.originate_contract + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~prg:(contract_path protocol "opcodes" "create_contract_with_view.tz") + ~init:"None" + ~alias:"view" + client + in + let* () = + Client.transfer + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract + ~arg:"Unit" + client + in + let* addr = + Client.contract_storage ~unparsing_mode:Optimized contract client + in + let addr = String.sub addr 5 @@ (String.length addr - 5) in + let* contract = + Client.originate_contract + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~prg:(contract_path protocol "opcodes" "view_op_constant.tz") + ~init:"2" + ~alias:"contract" + client + in + let expected = "10" in + let* () = + Client.transfer + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract + ~arg:(sf "Pair %s %s" expected addr) + client + in + let* actual = + Client.contract_storage ~unparsing_mode:Optimized contract client + in + Check.((String.trim actual = expected) string ~__LOC__) + ~error_msg:"expected storage %R, got %L" ; + unit + +let test_view_step_constant = + Protocol.register_test + ~__FILE__ + ~title:"Step constants in view" + ~tags:["client"; "michelson"] + @@ fun protocol -> + let* client = Client.init_mockup ~protocol () in + let amount = 999000000 in + let* lib_contract = + deploy_lib_contract ~protocol ~amount:(Tez.of_mutez_int amount) client + in + let* contract = + Client.originate_contract + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~prg:(contract_path protocol "opcodes" "view_op_test_step_contants.tz") + ~init:"None" + ~alias:"view" + client + in + let* () = + Client.transfer + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract + ~arg:(sf "\"%s\"" lib_contract) + client + in + let* actual = + Client.contract_storage ~unparsing_mode:Readable contract client + in + let expected = + sf + {|Some (Pair (Pair 0 %d) + (Pair "%s" "%s") + "%s") +|} + amount + lib_contract + contract + Constant.bootstrap1.public_key_hash + in + Check.((actual = expected) string ~__LOC__) + ~error_msg:"expected storage %R, got %L" ; + unit + +let test_consts_after_view ~contract ~expected protocol = + let* client = Client.init_mockup ~protocol () in + let* lib_contract = deploy_lib_contract ~protocol client in + let* contract = + Client.originate_contract + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.one + ~src:Constant.bootstrap1.alias + ~prg:(contract_path protocol "opcodes" @@ sf "%s.tz" contract) + ~init:(sf "%S" lib_contract) + ~alias:"view" + client + in + let* () = + Client.transfer + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract + ~arg:(sf "%S" lib_contract) + client + in + let expected = + match expected with + | `Contract -> sf "%S\n" contract + | `Sender -> sf "%S\n" Constant.bootstrap1.public_key_hash + in + let* actual = + Client.contract_storage ~unparsing_mode:Readable contract client + in + Check.((actual = expected) string ~__LOC__) + ~error_msg:"expected storage %R, got %L" ; + unit + +let test_self_after_view_suite protocols = + ["self_after_view"; "self_after_fib_view"; "self_after_nonexistent_view"] + |> List.iter @@ fun contract -> + Protocol.register_test + ~__FILE__ + ~title:(sf "self after view - %s" contract) + ~tags:["client"; "michelson"] + (test_consts_after_view ~contract ~expected:`Contract) + protocols + +let test_self_address_after_view_suite protocols = + [ + "self_address_after_view"; + "self_address_after_fib_view"; + "self_address_after_nonexistent_view"; + ] + |> List.iter @@ fun contract -> + Protocol.register_test + ~__FILE__ + ~title:(sf "self address after view - %s" contract) + ~tags:["client"; "michelson"] + (test_consts_after_view ~contract ~expected:`Contract) + protocols + +let test_sender_after_view_suite protocols = + [ + "sender_after_view"; "sender_after_fib_view"; "sender_after_nonexistent_view"; + ] + |> List.iter @@ fun contract -> + Protocol.register_test + ~__FILE__ + ~title:(sf "sender after view - %s" contract) + ~tags:["client"; "michelson"] + (test_consts_after_view ~contract ~expected:`Sender) + protocols + +let test_balance_after_view ~contract protocol = + let* client = Client.init_mockup ~protocol () in + let* lib_contract = deploy_lib_contract ~protocol client in + let contract_amount = Tez.of_int 1000 in + let transfer_amount = Tez.of_int 10 in + let* contract = + Client.originate_contract + ~hooks + ~burn_cap:Tez.one + ~amount:contract_amount + ~src:Constant.bootstrap1.alias + ~prg:(contract_path protocol "opcodes" @@ sf "%s.tz" contract) + ~init:"0" + ~alias:"view" + client + in + let* () = + Client.transfer + ~hooks + ~burn_cap:Tez.one + ~amount:transfer_amount + ~giver:Constant.bootstrap1.alias + ~receiver:contract + ~arg:(sf "\"%s\"" lib_contract) + client + in + let* actual = + Client.contract_storage ~unparsing_mode:Readable contract client + in + let expected = + Tez.(contract_amount + transfer_amount |> to_mutez) |> sf "%d\n" + in + Check.((actual = expected) string ~__LOC__) + ~error_msg:"expected storage %R, got %L" ; + unit + +let test_balance_after_view_suite protocols = + [ + "balance_after_view"; + "balance_after_fib_view"; + "balance_after_nonexistent_view"; + ] + |> List.iter @@ fun contract -> + Protocol.register_test + ~__FILE__ + ~title:(sf "balance after view - %s" contract) + ~tags:["client"; "michelson"] + (test_balance_after_view ~contract) + protocols + +let test_amount_after_view ~contract protocol = + let* client = Client.init_mockup ~protocol () in + let* lib_contract = deploy_lib_contract ~protocol client in + let* contract = + Client.originate_contract + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.(of_int 1000) + ~src:Constant.bootstrap1.alias + ~prg:(contract_path protocol "opcodes" @@ sf "%s.tz" contract) + ~init:"0" + ~alias:"view" + client + in + let amount = Tez.of_int 3 in + let* () = + Client.transfer + ~hooks + ~burn_cap:Tez.one + ~amount + ~giver:Constant.bootstrap1.alias + ~receiver:contract + ~arg:(sf "\"%s\"" lib_contract) + client + in + let* actual = + Client.contract_storage ~unparsing_mode:Readable contract client + in + let expected = amount |> Tez.to_mutez |> sf "%d\n" in + Check.((actual = expected) string ~__LOC__) + ~error_msg:"expected storage %R, got %L" ; + unit + +let test_amount_after_view_suite protocols = + [ + "amount_after_view"; "amount_after_fib_view"; "amount_after_nonexistent_view"; + ] + |> List.iter @@ fun contract -> + Protocol.register_test + ~__FILE__ + ~title:(sf "amount after view - %s" contract) + ~tags:["client"; "michelson"] + (test_amount_after_view ~contract) + protocols + +let test_recursive_view = + Protocol.register_test + ~__FILE__ + ~title:"Recursive view" + ~tags:["client"; "michelson"] + @@ fun protocol -> + let* client = Client.init_mockup ~protocol () in + let* contract = + Client.originate_contract + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~prg:(contract_path protocol "opcodes" "view_rec.tz") + ~init:"Unit" + ~alias:"view" + client + in + Client.spawn_transfer + ~hooks + ~gas_limit:5000 + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract + ~arg:"Unit" + client + |> Process.check_error + ~msg:(rex "Gas limit exceeded during typechecking or execution\\.") + +let test_typecheck ~contract ~error protocol = + let* client = Client.init_mockup ~protocol () in + Client.spawn_originate_contract + ~hooks + ~burn_cap:Tez.one + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~prg:(contract_path protocol "ill_typed" @@ sf "%s.tz" contract) + ~init:"4" + ~alias:"view" + client + |> Process.check_error ~msg:error + +let test_typecheck_suite protocols = + [ + ( "view_toplevel_bad_type", + rex "the return of a view block did not match the expected type\\." ); + ( "view_toplevel_bad_return_type", + rex "the return of a view block did not match the expected type\\." ); + ( "view_toplevel_bad_input_type", + rex "operator ADD is undefined between string" ); + ("view_toplevel_invalid_arity", rex "primitive view expects 4 arguments"); + ( "view_toplevel_bad_name_too_long", + rex "exceeds the maximum length of 31 characters" ); + ("view_toplevel_bad_name_invalid_type", rex "only a string can be used here"); + ( "view_toplevel_bad_name_non_printable_char", + rex "string \\[a-zA-Z0-9_.%@\\]" ); + ( "view_toplevel_duplicated_name", + rex "the name of view in toplevel should be unique" ); + ("view_toplevel_dupable_type_output", rex "Ticket in unauthorized position"); + ("view_toplevel_dupable_type_input", rex "Ticket in unauthorized position"); + ( "view_toplevel_lazy_storage_input", + rex "big_map or sapling_state type not expected here" ); + ( "view_toplevel_lazy_storage_output", + rex "big_map or sapling_state type not expected here" ); + ("view_op_invalid_arity", rex "primitive VIEW expects 2 arguments"); + ("view_op_bad_name_invalid_type", rex "unexpected int, only a string"); + ( "view_op_bad_name_too_long", + rex "exceeds the maximum length of 31 characters" ); + ("view_op_bad_name_non_printable_char", rex "string \\[a-zA-Z0-9_.%@\\]"); + ("view_op_bad_name_invalid_char_set", rex "string \\[a-zA-Z0-9_.%@\\]"); + ( "view_op_bad_return_type", + rex "two branches don't end with the same stack type" ); + ("view_op_dupable_type", rex "Ticket in unauthorized position"); + ( "view_op_lazy_storage", + rex "big_map or sapling_state type not expected here" ); + ] + |> List.iter @@ fun (contract, error) -> + Protocol.register_test + ~__FILE__ + ~title:(sf "Typecheck view - %s" contract) + ~tags:["client"; "michelson"] + (test_typecheck ~contract ~error) + protocols + +let register protocols = + test_regression protocols ; + test_all_view_runs protocols ; + test_create_contract protocols ; + test_view_step_constant protocols ; + test_self_after_view_suite protocols ; + test_self_address_after_view_suite protocols ; + test_sender_after_view_suite protocols ; + test_balance_after_view_suite protocols ; + test_amount_after_view_suite protocols ; + test_recursive_view protocols ; + test_typecheck_suite protocols -- GitLab