@@ -2,11 +2,13 @@ package api
22
33import (
44 "crypto/sha256"
5+ "encoding/hex"
56 "encoding/json"
67 "fmt"
78 "io/ioutil"
89 "os"
910 "path/filepath"
11+ "strings"
1012 "testing"
1113 "time"
1214
@@ -907,6 +909,10 @@ func createReflectContract(t *testing.T, cache Cache) []byte {
907909 return createContract (t , cache , "../../testdata/reflect.wasm" )
908910}
909911
912+ func createFloaty2 (t * testing.T , cache Cache ) []byte {
913+ return createContract (t , cache , "../../testdata/floaty_2.0.wasm" )
914+ }
915+
910916func createContract (t * testing.T , cache Cache , wasmFile string ) []byte {
911917 wasm , err := ioutil .ReadFile (wasmFile )
912918 require .NoError (t , err )
@@ -1055,3 +1061,100 @@ func TestCustomReflectQuerier(t *testing.T) {
10551061 require .NoError (t , err )
10561062 require .Equal (t , "SMALL FRYS :)" , response .Text )
10571063}
1064+
1065+ // TestFloats is a port of the float_instrs_are_deterministic test in cosmwasm-vm
1066+ func TestFloats (t * testing.T ) {
1067+ type Value struct {
1068+ U32 * uint32 `json:"u32,omitempty"`
1069+ U64 * uint64 `json:"u64,omitempty"`
1070+ F32 * uint32 `json:"f32,omitempty"`
1071+ F64 * uint64 `json:"f64,omitempty"`
1072+ }
1073+
1074+ // helper to print the value in the same format as Rust's Debug trait
1075+ debugStr := func (value Value ) string {
1076+ if value .U32 != nil {
1077+ return fmt .Sprintf ("U32(%d)" , * value .U32 )
1078+ } else if value .U64 != nil {
1079+ return fmt .Sprintf ("U64(%d)" , * value .U64 )
1080+ } else if value .F32 != nil {
1081+ return fmt .Sprintf ("F32(%d)" , * value .F32 )
1082+ } else if value .F64 != nil {
1083+ return fmt .Sprintf ("F64(%d)" , * value .F64 )
1084+ } else {
1085+ t .FailNow ()
1086+ return ""
1087+ }
1088+ }
1089+
1090+ cache , cleanup := withCache (t )
1091+ defer cleanup ()
1092+ checksum := createFloaty2 (t , cache )
1093+
1094+ gasMeter := NewMockGasMeter (TESTING_GAS_LIMIT )
1095+ igasMeter := types .GasMeter (gasMeter )
1096+ // instantiate it with this store
1097+ store := NewLookup (gasMeter )
1098+ api := NewMockAPI ()
1099+ querier := DefaultQuerier (MOCK_CONTRACT_ADDR , nil )
1100+ env := MockEnvBin (t )
1101+
1102+ // query instructions
1103+ query := []byte (`{"instructions":{}}` )
1104+ data , _ , err := Query (cache , checksum , env , query , & igasMeter , store , api , & querier , TESTING_GAS_LIMIT , TESTING_PRINT_DEBUG )
1105+ require .NoError (t , err )
1106+ var qres types.QueryResponse
1107+ err = json .Unmarshal (data , & qres )
1108+ require .NoError (t , err )
1109+ require .Equal (t , "" , qres .Err )
1110+ var instructions []string
1111+ err = json .Unmarshal (qres .Ok , & instructions )
1112+ require .NoError (t , err )
1113+ // little sanity check
1114+ require .Equal (t , 70 , len (instructions ))
1115+
1116+ hasher := sha256 .New ()
1117+ const RUNS_PER_INSTRUCTION = 150
1118+ for _ , instr := range instructions {
1119+ for seed := 0 ; seed < RUNS_PER_INSTRUCTION ; seed ++ {
1120+ // query some input values for the instruction
1121+ msg := fmt .Sprintf (`{"random_args_for":{"instruction":"%s","seed":%d}}` , instr , seed )
1122+ data , _ , err = Query (cache , checksum , env , []byte (msg ), & igasMeter , store , api , & querier , TESTING_GAS_LIMIT , TESTING_PRINT_DEBUG )
1123+ require .NoError (t , err )
1124+ err = json .Unmarshal (data , & qres )
1125+ require .NoError (t , err )
1126+ require .Equal (t , "" , qres .Err )
1127+ var args []Value
1128+ err = json .Unmarshal (qres .Ok , & args )
1129+ require .NoError (t , err )
1130+
1131+ // build the run message
1132+ argStr , err := json .Marshal (args )
1133+ require .NoError (t , err )
1134+ msg = fmt .Sprintf (`{"run":{"instruction":"%s","args":%s}}` , instr , argStr )
1135+
1136+ // run the instruction
1137+ // this might throw a runtime error (e.g. if the instruction traps)
1138+ data , _ , err = Query (cache , checksum , env , []byte (msg ), & igasMeter , store , api , & querier , TESTING_GAS_LIMIT , TESTING_PRINT_DEBUG )
1139+ var result string
1140+ if err != nil {
1141+ assert .ErrorContains (t , err , "Error calling the VM: Error executing Wasm: " )
1142+ // remove the prefix to make the error message the same as in the cosmwasm-vm test
1143+ result = strings .Replace (err .Error (), "Error calling the VM: Error executing Wasm: " , "" , 1 )
1144+ } else {
1145+ err = json .Unmarshal (data , & qres )
1146+ require .NoError (t , err )
1147+ require .Equal (t , "" , qres .Err )
1148+ var response Value
1149+ err = json .Unmarshal (qres .Ok , & response )
1150+ require .NoError (t , err )
1151+ result = debugStr (response )
1152+ }
1153+ // add the result to the hash
1154+ hasher .Write ([]byte (fmt .Sprintf ("%s%d%s" , instr , seed , result )))
1155+ }
1156+ }
1157+
1158+ hash := hasher .Sum (nil )
1159+ require .Equal (t , "95f70fa6451176ab04a9594417a047a1e4d8e2ff809609b8f81099496bee2393" , hex .EncodeToString (hash ))
1160+ }
0 commit comments