Skip to content

Commit

Permalink
test: abstract test helper methods in hidden interface
Browse files Browse the repository at this point in the history
  • Loading branch information
leovct committed Jul 26, 2024
1 parent d0fc9d3 commit 5fd5c18
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 46 deletions.
11 changes: 0 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,6 @@ type IEVM interface {
ISHA3Ops
IStackOps
IMemoryOps

// Helper methods.
// TODO: Get rid of these methods if possible.
// Push an item to the stack.
HelperPush(*uint256.Int) error
// Pop an item of the stack.
HelperPop() (*uint256.Int, error)
// Write byte slice to memory at the specified offset.
HelperStore(value []byte, offset int)
// Load a chunck of the memory.
HelperLoad(size int) []byte
}

// EVM represents an Ethereum Virtual Machine.
Expand Down
27 changes: 0 additions & 27 deletions evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,6 @@ type IEVM interface {
ISHA3Ops
IStackOps
IMemoryOps

// Helper methods.
// TODO: Get rid of these methods if possible.
// Push an item to the stack.
HelperPush(*uint256.Int) error
// Pop an item of the stack.
HelperPop() (*uint256.Int, error)
// Write byte slice to memory at the specified offset.
HelperStore(value []byte, offset int)
// Load a chunck of the memory.
HelperLoad(size int) []byte
}

// EVM represents an Ethereum Virtual Machine.
Expand Down Expand Up @@ -60,22 +49,6 @@ func NewEVM(code []byte) IEVM {
}
}

func (e *EVM) HelperPop() (*uint256.Int, error) {
return e.stack.Pop()
}

func (e *EVM) HelperPush(value *uint256.Int) error {
return e.stack.Push(value)
}

func (e *EVM) HelperStore(value []byte, offset int) {
e.memory.Store(value, offset)
}

func (e *EVM) HelperLoad(size int) []byte {
return e.memory.Load(0, size)
}

// Perform an arithmetic or a bitwise operation on the top two elements on the stack.
// It pops two values from the stack, applies the operation, and pushes the result back to the stack.
func (e *EVM) performBinaryStackOperation(numOperands int, operation func(...*uint256.Int) *uint256.Int) error {
Expand Down
46 changes: 42 additions & 4 deletions evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,38 @@ import (
"github.com/holiman/uint256"
)

// internalEVM defines the methods that an Ethereum Virtual Machine implementation should have, including helper methods.
// It is only used for testing.
type internalEVM interface {
IEVM

// Helper methods.
// Push an item to the stack.
HelperPush(*uint256.Int) error
// Pop an item of the stack.
HelperPop() (*uint256.Int, error)
// Write byte slice to memory at the specified offset.
HelperStore(value []byte, offset int)
// Load a chunck of the memory.
HelperLoad(size int) []byte
}

func (e *EVM) HelperPop() (*uint256.Int, error) {
return e.stack.Pop()
}

func (e *EVM) HelperPush(value *uint256.Int) error {
return e.stack.Push(value)
}

func (e *EVM) HelperStore(value []byte, offset int) {
e.memory.Store(value, offset)
}

func (e *EVM) HelperLoad(size int) []byte {
return e.memory.Load(0, size)
}

func TestNewEVM(t *testing.T) {
evm := NewEVM(nil)
if evm == nil {
Expand Down Expand Up @@ -59,15 +91,21 @@ func testStackOperationWithNewEVM(t *testing.T, op func(evm IEVM) error, expecte

// Helper function to test stack operations with an existing EVM.
func testStackOperationWithExistingEVM(t *testing.T, evm IEVM, op func(evm IEVM) error, expectedErr error, initialStack, expectedStack []uint64, initialMemory, expectedMemory []byte) {
// Extend the capabilities of the EVM using the internal EVM which defines helper methods to access the states of the stack and the memory.
internalEVM, ok := evm.(internalEVM)

Check failure on line 95 in evm_test.go

View workflow job for this annotation

GitHub Actions / lint

declaration of "internalEVM" shadows declaration at line 12
if !ok {
t.Fatal("IEVM does not implement internalEVM")
}

// Push initial elements to the stack.
for i, v := range initialStack {
if err := evm.HelperPush(uint256.NewInt(v)); err != nil {
if err := internalEVM.HelperPush(uint256.NewInt(v)); err != nil {
t.Errorf("Push() returned an unexpected error at iteration %d: %v", i, err)
}
}

// Load initial elements to the memory.
evm.HelperStore(initialMemory, 0)
internalEVM.HelperStore(initialMemory, 0)

// Perform the operation.
if err := op(evm); err != expectedErr {
Expand All @@ -76,7 +114,7 @@ func testStackOperationWithExistingEVM(t *testing.T, evm IEVM, op func(evm IEVM)

// Check the stack after the operation.
for i := len(expectedStack) - 1; i >= 0; i-- {
popped, err := evm.HelperPop()
popped, err := internalEVM.HelperPop()
if err != nil {
t.Errorf("Pop() returned an unexpected error: %v", err)
}
Expand All @@ -92,7 +130,7 @@ func testStackOperationWithExistingEVM(t *testing.T, evm IEVM, op func(evm IEVM)
}

// Check the memory after the operation.
actualMemory := evm.HelperLoad(len(expectedMemory))
actualMemory := internalEVM.HelperLoad(len(expectedMemory))
if !bytes.Equal(actualMemory, expectedMemory) {
t.Errorf("Memory mismatch. Expected: %v, got: %v", expectedMemory, actualMemory)
}
Expand Down
20 changes: 16 additions & 4 deletions stack_ops_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,22 @@ func TestPushOnFullStack(t *testing.T) {
code := []byte{0x60, 0x11}
evm := NewEVM(code)

// Extend the capabilities of the EVM using the internal EVM which defines helper methods to access the states of the stack and the memory.
internalEVM, ok := evm.(internalEVM)

Check failure on line 50 in stack_ops_test.go

View workflow job for this annotation

GitHub Actions / lint

declaration of "internalEVM" shadows declaration at line 12
if !ok {
t.Fatal("IEVM does not implement internalEVM")
}

// Push elements to the stack until its full.
for i := 0; i < 1024; i++ {
if err := evm.HelperPush(uint256.NewInt(uint64(i))); err != nil {
if err := internalEVM.HelperPush(uint256.NewInt(uint64(i))); err != nil {
t.Errorf("Push() returned an unexpected error at iteration %d: %v", i, err)
break
}
}

// Try to push the first element (0x11) from code.
if err := evm.Push1(); err == nil {
if err := internalEVM.Push1(); err == nil {
t.Errorf("Operation returned an unexpected error: %v, wanted: %v", err, ErrStackOverflow)
}
}
Expand Down Expand Up @@ -119,16 +125,22 @@ func TestDupOnFullStack(t *testing.T) {
// Create a new EVM.
evm := NewEVM(nil)

// Extend the capabilities of the EVM using the internal EVM which defines helper methods to access the states of the stack and the memory.
internalEVM, ok := evm.(internalEVM)

Check failure on line 129 in stack_ops_test.go

View workflow job for this annotation

GitHub Actions / lint

declaration of "internalEVM" shadows declaration at line 12
if !ok {
t.Fatal("IEVM does not implement internalEVM")
}

// Push elements to the stack until its full.
for i := 0; i < 1024; i++ {
if err := evm.HelperPush(uint256.NewInt(uint64(i))); err != nil {
if err := internalEVM.HelperPush(uint256.NewInt(uint64(i))); err != nil {
t.Errorf("Push() returned an unexpected error at iteration %d: %v", i, err)
break
}
}

// Try to duplicate the first element.
if err := evm.Dup1(); err == nil {
if err := internalEVM.Dup1(); err == nil {
t.Errorf("Operation returned an unexpected error: %v, wanted: %v", err, ErrStackOverflow)
}
}
Expand Down

0 comments on commit 5fd5c18

Please sign in to comment.