diff options
Diffstat (limited to 'vm/vm_test.go')
-rw-r--r-- | vm/vm_test.go | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/vm/vm_test.go b/vm/vm_test.go new file mode 100644 index 000000000..84cca3a9d --- /dev/null +++ b/vm/vm_test.go @@ -0,0 +1,155 @@ +package vm + +import ( + "bytes" + "fmt" + "io/ioutil" + "log" + "math/big" + "os" + "testing" + + "github.com/ethereum/go-ethereum/ethcrypto" + "github.com/ethereum/go-ethereum/ethlog" + "github.com/ethereum/go-ethereum/ethstate" + "github.com/ethereum/go-ethereum/ethtrie" + "github.com/ethereum/go-ethereum/ethutil" +) + +type TestEnv struct { +} + +func (self TestEnv) Origin() []byte { return nil } +func (self TestEnv) BlockNumber() *big.Int { return nil } +func (self TestEnv) BlockHash() []byte { return nil } +func (self TestEnv) PrevHash() []byte { return nil } +func (self TestEnv) Coinbase() []byte { return nil } +func (self TestEnv) Time() int64 { return 0 } +func (self TestEnv) Difficulty() *big.Int { return nil } +func (self TestEnv) Value() *big.Int { return nil } + +// This is likely to fail if anything ever gets looked up in the state trie :-) +func (self TestEnv) State() *ethstate.State { return ethstate.New(ethtrie.New(nil, "")) } + +const mutcode = ` +var x = 0; +for i := 0; i < 10; i++ { + x = i +} + +return x` + +func setup(level ethlog.LogLevel, typ Type) (*Closure, VirtualMachine) { + code, err := ethutil.Compile(mutcode, true) + if err != nil { + log.Fatal(err) + } + + // Pipe output to /dev/null + ethlog.AddLogSystem(ethlog.NewStdLogSystem(ioutil.Discard, log.LstdFlags, level)) + + ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "") + + stateObject := ethstate.NewStateObject([]byte{'j', 'e', 'f', 'f'}) + callerClosure := NewClosure(nil, stateObject, stateObject, code, big.NewInt(1000000), big.NewInt(0)) + + return callerClosure, New(TestEnv{}, typ) +} + +func TestDebugVm(t *testing.T) { + closure, vm := setup(ethlog.DebugLevel, DebugVmTy) + ret, _, e := closure.Call(vm, nil) + if e != nil { + fmt.Println("error", e) + } + + if ret[len(ret)-1] != 9 { + t.Errorf("Expected VM to return 9, got", ret, "instead.") + } +} + +func TestVm(t *testing.T) { + closure, vm := setup(ethlog.DebugLevel, StandardVmTy) + ret, _, e := closure.Call(vm, nil) + if e != nil { + fmt.Println("error", e) + } + + if ret[len(ret)-1] != 9 { + t.Errorf("Expected VM to return 9, got", ret, "instead.") + } +} + +func BenchmarkDebugVm(b *testing.B) { + closure, vm := setup(ethlog.InfoLevel, DebugVmTy) + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + closure.Call(vm, nil) + } +} + +func BenchmarkVm(b *testing.B) { + closure, vm := setup(ethlog.InfoLevel, StandardVmTy) + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + closure.Call(vm, nil) + } +} + +func RunCode(mutCode string, typ Type) []byte { + code, err := ethutil.Compile(mutCode, true) + if err != nil { + log.Fatal(err) + } + + ethlog.AddLogSystem(ethlog.NewStdLogSystem(os.Stdout, log.LstdFlags, ethlog.InfoLevel)) + + ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "") + + stateObject := ethstate.NewStateObject([]byte{'j', 'e', 'f', 'f'}) + closure := NewClosure(nil, stateObject, stateObject, code, big.NewInt(1000000), big.NewInt(0)) + + vm := New(TestEnv{}, typ) + ret, _, e := closure.Call(vm, nil) + if e != nil { + fmt.Println(e) + } + + return ret +} + +func TestBuildInSha256(t *testing.T) { + ret := RunCode(` + var in = 42 + var out = 0 + + call(0x2, 0, 10000, in, out) + + return out + `, DebugVmTy) + + exp := ethcrypto.Sha256(ethutil.LeftPadBytes([]byte{42}, 32)) + if bytes.Compare(ret, exp) != 0 { + t.Errorf("Expected %x, got %x", exp, ret) + } +} + +func TestBuildInRipemd(t *testing.T) { + ret := RunCode(` + var in = 42 + var out = 0 + + call(0x3, 0, 10000, in, out) + + return out + `, DebugVmTy) + + exp := ethutil.RightPadBytes(ethcrypto.Ripemd160(ethutil.LeftPadBytes([]byte{42}, 32)), 32) + if bytes.Compare(ret, exp) != 0 { + t.Errorf("Expected %x, got %x", exp, ret) + } +} |