diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index c436b7df4d..cb6fc48254 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -19,6 +19,7 @@ package vm import ( "bytes" "encoding/json" + "errors" "fmt" "os" "testing" @@ -763,10 +764,11 @@ func TestEIP8024_Execution(t *testing.T) { evm := NewCVM(BlockContext{}, nil, params.TestChainConfig, Config{}) tests := []struct { - name string - codeHex string - wantErr bool - wantVals []uint64 + name string + codeHex string + wantErr error + wantOpcode OpCode + wantVals []uint64 }{ { name: "DUPN", @@ -819,55 +821,70 @@ func TestEIP8024_Execution(t *testing.T) { }, }, { - name: "INVALID_SWAPN_LOW", - codeHex: "e75b", - wantErr: true, + name: "INVALID_SWAPN_LOW", + codeHex: "e75b", + wantErr: &ErrInvalidOpCode{}, + wantOpcode: SWAPN, }, { name: "JUMP over INVALID_DUPN", codeHex: "600456e65b", - wantErr: false, + wantErr: nil, + }, + { + name: "UNDERFLOW_DUPN_1", + codeHex: "6000808080808080808080808080808080e600", + wantErr: &ErrStackUnderflow{}, + wantOpcode: DUPN, }, // Additional test cases { - name: "INVALID_DUPN_LOW", - codeHex: "e65b", - wantErr: true, + name: "INVALID_DUPN_LOW", + codeHex: "e65b", + wantErr: &ErrInvalidOpCode{}, + wantOpcode: DUPN, }, { - name: "INVALID_EXCHANGE_LOW", - codeHex: "e850", - wantErr: true, + name: "INVALID_EXCHANGE_LOW", + codeHex: "e850", + wantErr: &ErrInvalidOpCode{}, + wantOpcode: EXCHANGE, }, { - name: "INVALID_DUPN_HIGH", - codeHex: "e67f", - wantErr: true, + name: "INVALID_DUPN_HIGH", + codeHex: "e67f", + wantErr: &ErrInvalidOpCode{}, + wantOpcode: DUPN, }, { - name: "INVALID_SWAPN_HIGH", - codeHex: "e77f", - wantErr: true, + name: "INVALID_SWAPN_HIGH", + codeHex: "e77f", + wantErr: &ErrInvalidOpCode{}, + wantOpcode: SWAPN, }, { - name: "INVALID_EXCHANGE_HIGH", - codeHex: "e87f", - wantErr: true, + name: "INVALID_EXCHANGE_HIGH", + codeHex: "e87f", + wantErr: &ErrInvalidOpCode{}, + wantOpcode: EXCHANGE, }, { - name: "UNDERFLOW_DUPN", - codeHex: "5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5fe600", // (n=17, need 17 items, have 16) - wantErr: true, + name: "UNDERFLOW_DUPN_2", + codeHex: "5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5fe600", // (n=17, need 17 items, have 16) + wantErr: &ErrStackUnderflow{}, + wantOpcode: DUPN, }, { - name: "UNDERFLOW_SWAPN", - codeHex: "5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5fe700", // (n=17, need 18 items, have 17) - wantErr: true, + name: "UNDERFLOW_SWAPN", + codeHex: "5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5fe700", // (n=17, need 18 items, have 17) + wantErr: &ErrStackUnderflow{}, + wantOpcode: SWAPN, }, { - name: "UNDERFLOW_EXCHANGE", - codeHex: "60016002e801", // (n,m)=(1,2), need 3 items, have 2 - wantErr: true, + name: "UNDERFLOW_EXCHANGE", + codeHex: "60016002e801", // (n,m)=(1,2), need 3 items, have 2 + wantErr: &ErrStackUnderflow{}, + wantOpcode: EXCHANGE, }, { name: "PC_INCREMENT", @@ -883,6 +900,7 @@ func TestEIP8024_Execution(t *testing.T) { pc := uint64(0) scope := &ScopeContext{Stack: stack, Contract: &Contract{Code: code}} var err error + var errOp OpCode for pc < uint64(len(code)) && err == nil { op := code[pc] switch OpCode(op) { @@ -908,14 +926,37 @@ func TestEIP8024_Execution(t *testing.T) { case EXCHANGE: _, err = opExchange(&pc, evm, scope) default: - err = &ErrInvalidOpCode{opcode: OpCode(op)} + t.Fatalf("unexpected opcode %s at pc=%d", OpCode(op), pc) + } + if err != nil { + errOp = OpCode(op) } pc++ } - if tc.wantErr { + if tc.wantErr != nil { + // Fail because we wanted an error, but didn't get one. if err == nil { t.Fatalf("expected error, got nil") } + // Fail if the wrong opcode threw an error. + if errOp != tc.wantOpcode { + t.Fatalf("expected error from opcode %s, got %s", tc.wantOpcode, errOp) + } + // Fail if we don't get the error we expect. + switch tc.wantErr.(type) { + case *ErrInvalidOpCode: + var want *ErrInvalidOpCode + if !errors.As(err, &want) { + t.Fatalf("expected ErrInvalidOpCode, got %v", err) + } + case *ErrStackUnderflow: + var want *ErrStackUnderflow + if !errors.As(err, &want) { + t.Fatalf("expected ErrStackUnderflow, got %v", err) + } + default: + t.Fatalf("unsupported wantErr type %T", tc.wantErr) + } return } if err != nil {