neo-go/pkg/compiler/panic_test.go
Evgenii Stratonikov d2326a8b96 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.
2020-01-29 12:28:38 +03:00

71 lines
1.5 KiB
Go

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
},
}
}
}