1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package unicorntest
import (
"bytes"
"os"
"path"
"testing"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/cannon/mipsevm"
)
// baseAddrStart - baseAddrEnd is used in tests to write the results to
const baseAddrEnd = 0xbf_ff_ff_f0
const baseAddrStart = 0xbf_c0_00_00
// endAddr is used as return-address for tests
const endAddr = 0xa7ef00d0
func TestState(t *testing.T) {
testFiles, err := os.ReadDir("../../mipsevm/open_mips_tests/test/bin")
require.NoError(t, err)
for _, f := range testFiles {
t.Run(f.Name(), func(t *testing.T) {
if f.Name() == "oracle.bin" {
t.Skip("oracle test needs to be updated to use syscall pre-image oracle")
}
fn := path.Join("../../mipsevm/open_mips_tests/test/bin", f.Name())
programMem, err := os.ReadFile(fn)
require.NoError(t, err)
state := &mipsevm.State{PC: 0, NextPC: 4, Memory: mipsevm.NewMemory()}
err = state.Memory.SetMemoryRange(0, bytes.NewReader(programMem))
require.NoError(t, err, "load program into state")
// set the return address ($ra) to jump into when test completes
state.Registers[31] = endAddr
mu, err := NewUnicorn()
require.NoError(t, err, "load unicorn")
defer mu.Close()
require.NoError(t, mu.MemMap(baseAddrStart, ((baseAddrEnd-baseAddrStart)&^mipsevm.PageAddrMask)+mipsevm.PageSize))
require.NoError(t, mu.MemMap(endAddr&^mipsevm.PageAddrMask, mipsevm.PageSize))
err = LoadUnicorn(state, mu)
require.NoError(t, err, "load state into unicorn")
us, err := NewUnicornState(mu, state, nil, os.Stdout, os.Stderr)
require.NoError(t, err, "hook unicorn to state")
for i := 0; i < 1000; i++ {
if us.state.PC == endAddr {
break
}
_, err := us.Step(false)
require.NoError(t, err)
}
require.Equal(t, uint32(endAddr), us.state.PC, "must reach end")
// inspect test result
done, result := state.Memory.GetMemory(baseAddrEnd+4), state.Memory.GetMemory(baseAddrEnd+8)
require.Equal(t, done, uint32(1), "must be done")
require.Equal(t, result, uint32(1), "must have success result")
})
}
}