github.com/shrimpyuk/bor@v0.2.15-0.20220224151350-fb4ec6020bae/cmd/evm/t8n_test.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "reflect" 8 "strings" 9 "testing" 10 11 "github.com/docker/docker/pkg/reexec" 12 "github.com/ethereum/go-ethereum/internal/cmdtest" 13 ) 14 15 func TestMain(m *testing.M) { 16 // Run the app if we've been exec'd as "ethkey-test" in runEthkey. 17 reexec.Register("evm-test", func() { 18 if err := app.Run(os.Args); err != nil { 19 fmt.Fprintln(os.Stderr, err) 20 os.Exit(1) 21 } 22 os.Exit(0) 23 }) 24 // check if we have been reexec'd 25 if reexec.Init() { 26 return 27 } 28 os.Exit(m.Run()) 29 } 30 31 type testT8n struct { 32 *cmdtest.TestCmd 33 } 34 35 type t8nInput struct { 36 inAlloc string 37 inTxs string 38 inEnv string 39 stFork string 40 stReward string 41 } 42 43 func (args *t8nInput) get(base string) []string { 44 var out []string 45 if opt := args.inAlloc; opt != "" { 46 out = append(out, "--input.alloc") 47 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 48 } 49 if opt := args.inTxs; opt != "" { 50 out = append(out, "--input.txs") 51 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 52 } 53 if opt := args.inEnv; opt != "" { 54 out = append(out, "--input.env") 55 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 56 } 57 if opt := args.stFork; opt != "" { 58 out = append(out, "--state.fork", opt) 59 } 60 if opt := args.stReward; opt != "" { 61 out = append(out, "--state.reward", opt) 62 } 63 return out 64 } 65 66 type t8nOutput struct { 67 alloc bool 68 result bool 69 body bool 70 } 71 72 func (args *t8nOutput) get() (out []string) { 73 if args.body { 74 out = append(out, "--output.body", "stdout") 75 } else { 76 out = append(out, "--output.body", "") // empty means ignore 77 } 78 if args.result { 79 out = append(out, "--output.result", "stdout") 80 } else { 81 out = append(out, "--output.result", "") 82 } 83 if args.alloc { 84 out = append(out, "--output.alloc", "stdout") 85 } else { 86 out = append(out, "--output.alloc", "") 87 } 88 return out 89 } 90 91 func TestT8n(t *testing.T) { 92 tt := new(testT8n) 93 tt.TestCmd = cmdtest.NewTestCmd(t, tt) 94 for i, tc := range []struct { 95 base string 96 input t8nInput 97 output t8nOutput 98 expExitCode int 99 expOut string 100 }{ 101 { // Test exit (3) on bad config 102 base: "./testdata/1", 103 input: t8nInput{ 104 "alloc.json", "txs.json", "env.json", "Frontier+1346", "", 105 }, 106 output: t8nOutput{alloc: true, result: true}, 107 expExitCode: 3, 108 }, 109 { 110 base: "./testdata/1", 111 input: t8nInput{ 112 "alloc.json", "txs.json", "env.json", "Byzantium", "", 113 }, 114 output: t8nOutput{alloc: true, result: true}, 115 expOut: "exp.json", 116 }, 117 { // blockhash test 118 base: "./testdata/3", 119 input: t8nInput{ 120 "alloc.json", "txs.json", "env.json", "Berlin", "", 121 }, 122 output: t8nOutput{alloc: true, result: true}, 123 expOut: "exp.json", 124 }, 125 { // missing blockhash test 126 base: "./testdata/4", 127 input: t8nInput{ 128 "alloc.json", "txs.json", "env.json", "Berlin", "", 129 }, 130 output: t8nOutput{alloc: true, result: true}, 131 expExitCode: 4, 132 }, 133 { // Ommer test 134 base: "./testdata/5", 135 input: t8nInput{ 136 "alloc.json", "txs.json", "env.json", "Byzantium", "0x80", 137 }, 138 output: t8nOutput{alloc: true, result: true}, 139 expOut: "exp.json", 140 }, 141 { // Sign json transactions 142 base: "./testdata/13", 143 input: t8nInput{ 144 "alloc.json", "txs.json", "env.json", "London", "", 145 }, 146 output: t8nOutput{body: true}, 147 expOut: "exp.json", 148 }, 149 { // Already signed transactions 150 base: "./testdata/13", 151 input: t8nInput{ 152 "alloc.json", "signed_txs.rlp", "env.json", "London", "", 153 }, 154 output: t8nOutput{result: true}, 155 expOut: "exp2.json", 156 }, 157 { // Difficulty calculation - no uncles 158 base: "./testdata/14", 159 input: t8nInput{ 160 "alloc.json", "txs.json", "env.json", "London", "", 161 }, 162 output: t8nOutput{result: true}, 163 expOut: "exp.json", 164 }, 165 { // Difficulty calculation - with uncles 166 base: "./testdata/14", 167 input: t8nInput{ 168 "alloc.json", "txs.json", "env.uncles.json", "London", "", 169 }, 170 output: t8nOutput{result: true}, 171 expOut: "exp2.json", 172 }, 173 } { 174 175 args := []string{"t8n"} 176 args = append(args, tc.output.get()...) 177 args = append(args, tc.input.get(tc.base)...) 178 tt.Run("evm-test", args...) 179 tt.Logf("args: %v\n", strings.Join(args, " ")) 180 // Compare the expected output, if provided 181 if tc.expOut != "" { 182 want, err := os.ReadFile(fmt.Sprintf("%v/%v", tc.base, tc.expOut)) 183 if err != nil { 184 t.Fatalf("test %d: could not read expected output: %v", i, err) 185 } 186 have := tt.Output() 187 ok, err := cmpJson(have, want) 188 switch { 189 case err != nil: 190 t.Fatalf("test %d, json parsing failed: %v", i, err) 191 case !ok: 192 t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want)) 193 } 194 } 195 tt.WaitExit() 196 if have, want := tt.ExitStatus(), tc.expExitCode; have != want { 197 t.Fatalf("test %d: wrong exit code, have %d, want %d", i, have, want) 198 } 199 } 200 } 201 202 type t9nInput struct { 203 inTxs string 204 stFork string 205 } 206 207 func (args *t9nInput) get(base string) []string { 208 var out []string 209 if opt := args.inTxs; opt != "" { 210 out = append(out, "--input.txs") 211 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 212 } 213 if opt := args.stFork; opt != "" { 214 out = append(out, "--state.fork", opt) 215 } 216 return out 217 } 218 219 func TestT9n(t *testing.T) { 220 tt := new(testT8n) 221 tt.TestCmd = cmdtest.NewTestCmd(t, tt) 222 for i, tc := range []struct { 223 base string 224 input t9nInput 225 expExitCode int 226 expOut string 227 }{ 228 { // London txs on homestead 229 base: "./testdata/15", 230 input: t9nInput{ 231 inTxs: "signed_txs.rlp", 232 stFork: "Homestead", 233 }, 234 expOut: "exp.json", 235 }, 236 { // London txs on London 237 base: "./testdata/15", 238 input: t9nInput{ 239 inTxs: "signed_txs.rlp", 240 stFork: "London", 241 }, 242 expOut: "exp2.json", 243 }, 244 { // An RLP list (a blockheader really) 245 base: "./testdata/15", 246 input: t9nInput{ 247 inTxs: "blockheader.rlp", 248 stFork: "London", 249 }, 250 expOut: "exp3.json", 251 }, 252 { // Transactions with too low gas 253 base: "./testdata/16", 254 input: t9nInput{ 255 inTxs: "signed_txs.rlp", 256 stFork: "London", 257 }, 258 expOut: "exp.json", 259 }, 260 } { 261 262 args := []string{"t9n"} 263 args = append(args, tc.input.get(tc.base)...) 264 265 tt.Run("evm-test", args...) 266 tt.Logf("args:\n go run . %v\n", strings.Join(args, " ")) 267 // Compare the expected output, if provided 268 if tc.expOut != "" { 269 want, err := os.ReadFile(fmt.Sprintf("%v/%v", tc.base, tc.expOut)) 270 if err != nil { 271 t.Fatalf("test %d: could not read expected output: %v", i, err) 272 } 273 have := tt.Output() 274 ok, err := cmpJson(have, want) 275 switch { 276 case err != nil: 277 t.Logf(string(have)) 278 t.Fatalf("test %d, json parsing failed: %v", i, err) 279 case !ok: 280 t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want)) 281 } 282 } 283 tt.WaitExit() 284 if have, want := tt.ExitStatus(), tc.expExitCode; have != want { 285 t.Fatalf("test %d: wrong exit code, have %d, want %d", i, have, want) 286 } 287 } 288 } 289 290 // cmpJson compares the JSON in two byte slices. 291 func cmpJson(a, b []byte) (bool, error) { 292 var j, j2 interface{} 293 if err := json.Unmarshal(a, &j); err != nil { 294 return false, err 295 } 296 if err := json.Unmarshal(b, &j2); err != nil { 297 return false, err 298 } 299 return reflect.DeepEqual(j2, j), nil 300 }