123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178(*****************************************************************************)(* *)(* SPDX-License-Identifier: MIT *)(* Copyright (c) 2023 Nomadic Labs <contact@nomadic-labs.com> *)(* *)(*****************************************************************************)openProtocolopenAlpha_contextopenTezos_michelinetypeunit_test_with_source={source:string;parsed:stringMichelson_v1_parser.parser_result;}letconvert_errortrace=letopenResult_syntaxinletopenMichelineinfunction|Script_interpreter.Reject(_loc,value,_trace)->letvalue=Michelson_v1_primitives.strings_of_primsvalueinreturn(Prim(0,"Failed",[rootvalue],[]))|Tez_repr.Addition_overflow_|Tez_repr.Multiplication_overflow_|Script_interpreter.Overflow_->return(Prim(0,"Overflow",[],[]))|Tez_repr.Subtraction_underflow(a,b)->return(Prim(0,"MutezUnderflow",[Int(0,Z.of_int64@@Tez_repr.to_muteza);Int(0,Z.of_int64@@Tez_repr.to_mutezb);],[]))|Tez_repr.Negative_multiplicator_->return(Prim(0,"NegMul",[],[]))|Tez_repr.Invalid_divisor_->return(Prim(0,"InvalidDivisor",[],[]))|Raw_context.Operation_quota_exceeded|Raw_context.Block_quota_exceeded->return(Prim(0,"Gas_exhaustion",[],[]))|_->return(Prim(0,"StaticError",[String(0,Format.asprintf"%a"Error_monad.pp_print_tracetrace)],[]))letconvert_trace=function|Environment.Ecoproto_errorerr::_astrace->convert_errortraceerr|_->assertfalseletmatch_output~got~expected=letopenResult_syntaxinletopenMichelineinletrecmatch_patternpatternexpression=match(pattern,expression)with(* Wildcard *)|Prim(_,"_",[],[]),_->true(* Int *)|Int(_p_loc,p),Int(_e_loc,e)->Z.equalpe|Int_,_|_,Int_->false(* String *)|String(_p_loc,p),String(_e_loc,e)->Compare.String.(p=e)|String_,_|_,String_->false(* Bytes *)|Bytes(_p_loc,p),Bytes(_e_loc,e)->Compare.Bytes.(p=e)|Bytes_,_|_,Bytes_->false(* Seq *)|Seq(_p_loc,p),Seq(_e_loc,e)->(matchList.for_all2~when_different_lengths:()match_patternpewith|Okb->b|Error()->false)|Seq_,_|_,Seq_->false(* Prim *)|(Prim(_p_loc,p_prim,p_args,p_annots),Prim(_e_loc,e_prim,e_args,e_annots))->(Compare.String.(p_prim="_"||p_prim=e_prim)&&(matchList.for_all2~when_different_lengths:()match_patternp_argse_argswith|Okb->b|Error()->false)&&matchList.for_all2~when_different_lengths:()Compare.String.(=)p_annotse_annotswith|Okb->b|Error()->false)inifmatch_patternexpectedgotthenreturn_unitelseletppfmte=Micheline_printer.print_expr_unwrappedfmt(Micheline_printer.printableFun.id(Micheline.strip_locationse))in(* TODO: proper error instead of failwith *)error_with"Got output: %a@.Expected: %a@."ppgotppexpectedletrun_unit_test(cctxt:#Protocol_client_context.rpc_context)~(chain:Chain_services.chain)~block~(test:unit_test_with_source)()=letopenLwt_result_syntaxinlet*?ut=Michelson_v1_stack.parse_unit_testtest.parsedinletall_contracts=letother_contracts=Option.value~default:[]ut.optional.other_contractsinmatch(ut.optional.self,ut.optional.parameter)with|Someself,Someparam->RPC.Scripts.S.{address=self;ty=param}::other_contracts|None,_|Some_,None->other_contractsinlet*chain_id=matchut.optional.chain_idwith|Somechain_id->returnchain_id|None->Chain_services.chain_idcctxt~chain()inletamount=Option.value~default:Tez.zerout.optional.amountinlet*!res=matchut.outputwith|Micheline.Seq_asstack->let*?stack=Michelson_v1_stack.parse_stack~node:stacktest.parsedinlet*stack=Plugin.RPC.Scripts.normalize_stackcctxt(chain,block)~stack~unparsing_mode:Readable~legacy:true~other_contracts:(Someall_contracts)~extra_big_maps:ut.optional.extra_big_mapsinreturn(Michelson_v1_printer.unparse_stack0stack)|expected_output->returnexpected_outputin(* Wildcard patterns in output stack is incompatible with output stack normalization.
When the output stack contains a wildcard pattern, the normalization is expected
to fail. To support wildcard patterns, we silently skip output stack normalization
when it fails. *)letexpected_output=matchreswithOkx->x|Error_->ut.outputinlet*!res=Plugin.RPC.Scripts.run_instr~legacy:true~gas:None~input:ut.input~code:ut.code~now:ut.optional.now~level:ut.optional.level~sender:ut.optional.sender~source:ut.optional.source~chain_id~self:ut.optional.self~parameter:ut.optional.parameter~amount~balance:ut.optional.balance~other_contracts:(Someall_contracts)~extra_big_maps:ut.optional.extra_big_maps~unparsing_mode:Nonecctxt(chain,block)inlet*?output=matchreswith|Ok(output,_gas)->Result_syntax.return(Michelson_v1_printer.unparse_stack0output)|Errorerr->convert_traceerrinlet*?()=match_output~expected:expected_output~got:outputinreturn_unit