compiler: support panic
in source
In situations where VM's FAULT state needs to be reached, panic function can be used. It compiles to THROW instruction.
This commit is contained in:
parent
a839efb35e
commit
d2326a8b96
3 changed files with 89 additions and 0 deletions
71
pkg/compiler/panic_test.go
Normal file
71
pkg/compiler/panic_test.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
package compiler_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPanic(t *testing.T) {
|
||||
t.Run("no panic", func(t *testing.T) {
|
||||
src := getPanicSource(false, `"execution fault"`)
|
||||
eval(t, src, big.NewInt(7))
|
||||
})
|
||||
|
||||
t.Run("panic with message", func(t *testing.T) {
|
||||
var logs []string
|
||||
src := getPanicSource(true, `"execution fault"`)
|
||||
v := vmAndCompile(t, src)
|
||||
v.RegisterInteropGetter(logGetter(&logs))
|
||||
|
||||
require.Error(t, v.Run())
|
||||
require.True(t, v.HasFailed())
|
||||
require.Equal(t, 1, len(logs))
|
||||
require.Equal(t, "execution fault", logs[0])
|
||||
})
|
||||
|
||||
t.Run("panic with nil", func(t *testing.T) {
|
||||
var logs []string
|
||||
src := getPanicSource(true, `nil`)
|
||||
v := vmAndCompile(t, src)
|
||||
v.RegisterInteropGetter(logGetter(&logs))
|
||||
|
||||
require.Error(t, v.Run())
|
||||
require.True(t, v.HasFailed())
|
||||
require.Equal(t, 0, len(logs))
|
||||
})
|
||||
}
|
||||
|
||||
func getPanicSource(need bool, message string) string {
|
||||
return fmt.Sprintf(`
|
||||
package main
|
||||
func Main() int {
|
||||
needPanic := %#v
|
||||
if needPanic {
|
||||
panic(%s)
|
||||
return 5
|
||||
}
|
||||
return 7
|
||||
}
|
||||
`, need, message)
|
||||
}
|
||||
|
||||
func logGetter(logs *[]string) vm.InteropGetterFunc {
|
||||
logID := vm.InteropNameToID([]byte("Neo.Runtime.Log"))
|
||||
return func(id uint32) *vm.InteropFuncPrice {
|
||||
if id != logID {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &vm.InteropFuncPrice{
|
||||
Func: func(v *vm.VM) error {
|
||||
msg := string(v.Estack().Pop().Bytes())
|
||||
*logs = append(*logs, msg)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue