neoneo-go/pkg/compiler/interop_test.go
Anna Shaleva b5494320f9 compiler, cli: support events from .yml config file
We currently can't process events in codegen, so we have to provide
them via .yml config file. Do not delete the rest of the code connected
with conversion of MethodDebugInfo.Event into manifest.Event as we have
issue #1038.
2020-08-11 13:42:06 +03:00

240 lines
5.7 KiB
Go

package compiler_test
import (
"fmt"
"math/big"
"strings"
"testing"
"github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/dao"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)
func TestFromAddress(t *testing.T) {
as1 := "NQRLhCpAru9BjGsMwk67vdMwmzKMRgsnnN"
addr1, err := address.StringToUint160(as1)
require.NoError(t, err)
as2 := "NPAsqZkx9WhNd4P72uhZxBhLinSuNkxfB8"
addr2, err := address.StringToUint160(as2)
require.NoError(t, err)
t.Run("append 2 addresses", func(t *testing.T) {
src := `
package foo
import "github.com/nspcc-dev/neo-go/pkg/interop/util"
func Main() []byte {
addr1 := util.FromAddress("` + as1 + `")
addr2 := util.FromAddress("` + as2 + `")
sum := append(addr1, addr2...)
return sum
}
`
eval(t, src, append(addr1.BytesBE(), addr2.BytesBE()...))
})
t.Run("append 2 addresses inline", func(t *testing.T) {
src := `
package foo
import "github.com/nspcc-dev/neo-go/pkg/interop/util"
func Main() []byte {
addr1 := util.FromAddress("` + as1 + `")
sum := append(addr1, util.FromAddress("` + as2 + `")...)
return sum
}
`
eval(t, src, append(addr1.BytesBE(), addr2.BytesBE()...))
})
}
func spawnVM(t *testing.T, ic *interop.Context, src string) *vm.VM {
b, di, err := compiler.CompileWithDebugInfo(strings.NewReader(src))
require.NoError(t, err)
v := core.SpawnVM(ic)
invokeMethod(t, testMainIdent, b, v, di)
v.LoadScriptWithFlags(b, smartcontract.All)
return v
}
func TestAppCall(t *testing.T) {
srcInner := `
package foo
var a int = 3
func Main(a []byte, b []byte) []byte {
panic("Main was called")
}
func Append(a []byte, b []byte) []byte {
return append(a, b...)
}
func Add3(n int) int {
return a + n
}
`
inner, di, err := compiler.CompileWithDebugInfo(strings.NewReader(srcInner))
require.NoError(t, err)
m, err := di.ConvertToManifest(smartcontract.NoProperties, nil)
require.NoError(t, err)
ih := hash.Hash160(inner)
ic := interop.NewContext(trigger.Application, nil, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), nil, nil, nil, zaptest.NewLogger(t))
require.NoError(t, ic.DAO.PutContractState(&state.Contract{
Script: inner,
Manifest: *m,
}))
t.Run("valid script", func(t *testing.T) {
src := getAppCallScript(fmt.Sprintf("%#v", ih.BytesBE()))
v := spawnVM(t, ic, src)
require.NoError(t, v.Run())
assertResult(t, v, []byte{1, 2, 3, 4})
})
t.Run("missing script", func(t *testing.T) {
h := ih
h[0] = ^h[0]
src := getAppCallScript(fmt.Sprintf("%#v", h.BytesBE()))
v := spawnVM(t, ic, src)
require.Error(t, v.Run())
})
t.Run("convert from string constant", func(t *testing.T) {
src := `
package foo
import "github.com/nspcc-dev/neo-go/pkg/interop/engine"
const scriptHash = ` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `
func Main() []byte {
x := []byte{1, 2}
y := []byte{3, 4}
result := engine.AppCall([]byte(scriptHash), "append", x, y)
return result.([]byte)
}
`
v := spawnVM(t, ic, src)
require.NoError(t, v.Run())
assertResult(t, v, []byte{1, 2, 3, 4})
})
t.Run("convert from var", func(t *testing.T) {
src := `
package foo
import "github.com/nspcc-dev/neo-go/pkg/interop/engine"
func Main() []byte {
x := []byte{1, 2}
y := []byte{3, 4}
var addr = []byte(` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `)
result := engine.AppCall(addr, "append", x, y)
return result.([]byte)
}
`
v := spawnVM(t, ic, src)
require.NoError(t, v.Run())
assertResult(t, v, []byte{1, 2, 3, 4})
})
t.Run("InitializedGlobals", func(t *testing.T) {
src := `package foo
import "github.com/nspcc-dev/neo-go/pkg/interop/engine"
func Main() int {
var addr = []byte(` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `)
result := engine.AppCall(addr, "add3", 39)
return result.(int)
}`
v := spawnVM(t, ic, src)
require.NoError(t, v.Run())
assertResult(t, v, big.NewInt(42))
})
}
func getAppCallScript(h string) string {
return `
package foo
import "github.com/nspcc-dev/neo-go/pkg/interop/engine"
func Main() []byte {
x := []byte{1, 2}
y := []byte{3, 4}
result := engine.AppCall(` + h + `, "append", x, y)
return result.([]byte)
}
`
}
func TestBuiltinDoesNotCompile(t *testing.T) {
src := `package foo
import "github.com/nspcc-dev/neo-go/pkg/interop/util"
func Main() bool {
a := 1
b := 2
return util.Equals(a, b)
}`
v := vmAndCompile(t, src)
ctx := v.Context()
retCount := 0
for op, _, err := ctx.Next(); err == nil; op, _, err = ctx.Next() {
if ctx.IP() > len(ctx.Program()) {
break
}
if op == opcode.RET {
retCount++
}
}
require.Equal(t, 1, retCount)
}
func TestInteropPackage(t *testing.T) {
src := `package foo
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/block"
func Main() int {
b := block.Block{}
a := block.GetTransactionCount(b)
return a
}`
eval(t, src, big.NewInt(42))
}
func TestBuiltinPackage(t *testing.T) {
src := `package foo
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/util"
func Main() int {
if util.Equals(1, 2) { // always returns true
return 1
}
return 2
}`
eval(t, src, big.NewInt(1))
}
func TestLenForNil(t *testing.T) {
src := `
package foo
func Main() bool {
var a []int = nil
return len(a) == 0
}`
eval(t, src, true)
}