core: move TestContractCall into the contract package
It belongs there and now it can be moved. No functional changes.
This commit is contained in:
parent
bb021d0778
commit
ff1545b7eb
2 changed files with 157 additions and 140 deletions
|
@ -2,19 +2,27 @@ package contract_test
|
|||
|
||||
import (
|
||||
"math/big"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/internal/contracts"
|
||||
"github.com/nspcc-dev/neo-go/internal/random"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest/chain"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var pathToInternalContracts = filepath.Join("..", "..", "..", "..", "internal", "contracts")
|
||||
|
||||
func TestGetCallFlags(t *testing.T) {
|
||||
bc, _ := chain.NewSingle(t)
|
||||
ic := bc.GetTestVM(trigger.Application, &transaction.Transaction{}, &block.Block{})
|
||||
|
@ -23,3 +31,152 @@ func TestGetCallFlags(t *testing.T) {
|
|||
require.NoError(t, contract.GetCallFlags(ic))
|
||||
require.Equal(t, int64(callflag.All), ic.VM.Estack().Pop().Value().(*big.Int).Int64())
|
||||
}
|
||||
|
||||
func TestCall(t *testing.T) {
|
||||
bc, _ := chain.NewSingle(t)
|
||||
ic := bc.GetTestVM(trigger.Application, &transaction.Transaction{}, &block.Block{})
|
||||
|
||||
cs, currCs := contracts.GetTestContractState(t, pathToInternalContracts, 4, 5, random.Uint160()) // sender and IDs are not important for the test
|
||||
require.NoError(t, native.PutContractState(ic.DAO, cs))
|
||||
require.NoError(t, native.PutContractState(ic.DAO, currCs))
|
||||
|
||||
currScript := currCs.NEF.Script
|
||||
h := cs.Hash
|
||||
|
||||
addArgs := stackitem.NewArray([]stackitem.Item{stackitem.Make(1), stackitem.Make(2)})
|
||||
t.Run("Good", func(t *testing.T) {
|
||||
t.Run("2 arguments", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(addArgs)
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("add")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.NoError(t, ic.VM.Run())
|
||||
require.Equal(t, 2, ic.VM.Estack().Len())
|
||||
require.Equal(t, big.NewInt(3), ic.VM.Estack().Pop().Value())
|
||||
require.Equal(t, big.NewInt(42), ic.VM.Estack().Pop().Value())
|
||||
})
|
||||
t.Run("3 arguments", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(stackitem.NewArray(
|
||||
append(addArgs.Value().([]stackitem.Item), stackitem.Make(3))))
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("add")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.NoError(t, ic.VM.Run())
|
||||
require.Equal(t, 2, ic.VM.Estack().Len())
|
||||
require.Equal(t, big.NewInt(6), ic.VM.Estack().Pop().Value())
|
||||
require.Equal(t, big.NewInt(42), ic.VM.Estack().Pop().Value())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("CallExInvalidFlag", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(addArgs)
|
||||
ic.VM.Estack().PushVal(byte(0xFF))
|
||||
ic.VM.Estack().PushVal("add")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.Error(t, contract.Call(ic))
|
||||
})
|
||||
|
||||
runInvalid := func(args ...interface{}) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
loadScriptWithHashAndFlags(ic, currScript, h, callflag.All, 42)
|
||||
for i := range args {
|
||||
ic.VM.Estack().PushVal(args[i])
|
||||
}
|
||||
// interops can both return error and panic,
|
||||
// we don't care which kind of error has occurred
|
||||
require.Panics(t, func() {
|
||||
err := contract.Call(ic)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("Invalid", func(t *testing.T) {
|
||||
t.Run("Hash", runInvalid(addArgs, "add", h.BytesBE()[1:]))
|
||||
t.Run("MissingHash", runInvalid(addArgs, "add", util.Uint160{}.BytesBE()))
|
||||
t.Run("Method", runInvalid(addArgs, stackitem.NewInterop("add"), h.BytesBE()))
|
||||
t.Run("MissingMethod", runInvalid(addArgs, "sub", h.BytesBE()))
|
||||
t.Run("DisallowedMethod", runInvalid(stackitem.NewArray(nil), "ret7", h.BytesBE()))
|
||||
t.Run("Arguments", runInvalid(1, "add", h.BytesBE()))
|
||||
t.Run("NotEnoughArguments", runInvalid(
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Make(1)}), "add", h.BytesBE()))
|
||||
t.Run("TooMuchArguments", runInvalid(
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.Make(1), stackitem.Make(2), stackitem.Make(3), stackitem.Make(4)}),
|
||||
"add", h.BytesBE()))
|
||||
})
|
||||
|
||||
t.Run("ReturnValues", func(t *testing.T) {
|
||||
t.Run("Many", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(stackitem.NewArray(nil))
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("invalidReturn")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.Error(t, ic.VM.Run())
|
||||
})
|
||||
t.Run("Void", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(stackitem.NewArray(nil))
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("justReturn")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.NoError(t, ic.VM.Run())
|
||||
require.Equal(t, 2, ic.VM.Estack().Len())
|
||||
require.Equal(t, stackitem.Null{}, ic.VM.Estack().Pop().Item())
|
||||
require.Equal(t, big.NewInt(42), ic.VM.Estack().Pop().Value())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("IsolatedStack", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(stackitem.NewArray(nil))
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("drop")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.Error(t, ic.VM.Run())
|
||||
})
|
||||
|
||||
t.Run("CallInitialize", func(t *testing.T) {
|
||||
t.Run("Directly", runInvalid(stackitem.NewArray([]stackitem.Item{}), "_initialize", h.BytesBE()))
|
||||
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(stackitem.NewArray([]stackitem.Item{stackitem.Make(5)}))
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("add3")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.NoError(t, ic.VM.Run())
|
||||
require.Equal(t, 2, ic.VM.Estack().Len())
|
||||
require.Equal(t, big.NewInt(8), ic.VM.Estack().Pop().Value())
|
||||
require.Equal(t, big.NewInt(42), ic.VM.Estack().Pop().Value())
|
||||
})
|
||||
}
|
||||
|
||||
func loadScript(ic *interop.Context, script []byte, args ...interface{}) {
|
||||
ic.SpawnVM()
|
||||
ic.VM.LoadScriptWithFlags(script, callflag.AllowCall)
|
||||
for i := range args {
|
||||
ic.VM.Estack().PushVal(args[i])
|
||||
}
|
||||
ic.VM.GasLimit = -1
|
||||
}
|
||||
|
||||
func loadScriptWithHashAndFlags(ic *interop.Context, script []byte, hash util.Uint160, f callflag.CallFlag, args ...interface{}) {
|
||||
ic.SpawnVM()
|
||||
ic.VM.LoadScriptWithHash(script, hash, f)
|
||||
for i := range args {
|
||||
ic.VM.Estack().PushVal(args[i])
|
||||
}
|
||||
ic.VM.GasLimit = -1
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/iterator"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
||||
istorage "github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
|
||||
|
@ -558,15 +557,6 @@ func createVMAndContractState(t testing.TB) (*vm.VM, *state.Contract, *interop.C
|
|||
return v, contractState, context, chain
|
||||
}
|
||||
|
||||
func loadScript(ic *interop.Context, script []byte, args ...interface{}) {
|
||||
ic.SpawnVM()
|
||||
ic.VM.LoadScriptWithFlags(script, callflag.AllowCall)
|
||||
for i := range args {
|
||||
ic.VM.Estack().PushVal(args[i])
|
||||
}
|
||||
ic.VM.GasLimit = -1
|
||||
}
|
||||
|
||||
func loadScriptWithHashAndFlags(ic *interop.Context, script []byte, hash util.Uint160, f callflag.CallFlag, args ...interface{}) {
|
||||
ic.SpawnVM()
|
||||
ic.VM.LoadScriptWithHash(script, hash, f)
|
||||
|
@ -576,136 +566,6 @@ func loadScriptWithHashAndFlags(ic *interop.Context, script []byte, hash util.Ui
|
|||
ic.VM.GasLimit = -1
|
||||
}
|
||||
|
||||
func TestContractCall(t *testing.T) {
|
||||
_, ic, _ := createVM(t)
|
||||
|
||||
cs, currCs := contracts.GetTestContractState(t, pathToInternalContracts, 4, 5, random.Uint160()) // sender and IDs are not important for the test
|
||||
require.NoError(t, native.PutContractState(ic.DAO, cs))
|
||||
require.NoError(t, native.PutContractState(ic.DAO, currCs))
|
||||
|
||||
currScript := currCs.NEF.Script
|
||||
h := cs.Hash
|
||||
|
||||
addArgs := stackitem.NewArray([]stackitem.Item{stackitem.Make(1), stackitem.Make(2)})
|
||||
t.Run("Good", func(t *testing.T) {
|
||||
t.Run("2 arguments", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(addArgs)
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("add")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.NoError(t, ic.VM.Run())
|
||||
require.Equal(t, 2, ic.VM.Estack().Len())
|
||||
require.Equal(t, big.NewInt(3), ic.VM.Estack().Pop().Value())
|
||||
require.Equal(t, big.NewInt(42), ic.VM.Estack().Pop().Value())
|
||||
})
|
||||
t.Run("3 arguments", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(stackitem.NewArray(
|
||||
append(addArgs.Value().([]stackitem.Item), stackitem.Make(3))))
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("add")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.NoError(t, ic.VM.Run())
|
||||
require.Equal(t, 2, ic.VM.Estack().Len())
|
||||
require.Equal(t, big.NewInt(6), ic.VM.Estack().Pop().Value())
|
||||
require.Equal(t, big.NewInt(42), ic.VM.Estack().Pop().Value())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("CallExInvalidFlag", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(addArgs)
|
||||
ic.VM.Estack().PushVal(byte(0xFF))
|
||||
ic.VM.Estack().PushVal("add")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.Error(t, contract.Call(ic))
|
||||
})
|
||||
|
||||
runInvalid := func(args ...interface{}) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
loadScriptWithHashAndFlags(ic, currScript, h, callflag.All, 42)
|
||||
for i := range args {
|
||||
ic.VM.Estack().PushVal(args[i])
|
||||
}
|
||||
// interops can both return error and panic,
|
||||
// we don't care which kind of error has occurred
|
||||
require.Panics(t, func() {
|
||||
err := contract.Call(ic)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("Invalid", func(t *testing.T) {
|
||||
t.Run("Hash", runInvalid(addArgs, "add", h.BytesBE()[1:]))
|
||||
t.Run("MissingHash", runInvalid(addArgs, "add", util.Uint160{}.BytesBE()))
|
||||
t.Run("Method", runInvalid(addArgs, stackitem.NewInterop("add"), h.BytesBE()))
|
||||
t.Run("MissingMethod", runInvalid(addArgs, "sub", h.BytesBE()))
|
||||
t.Run("DisallowedMethod", runInvalid(stackitem.NewArray(nil), "ret7", h.BytesBE()))
|
||||
t.Run("Arguments", runInvalid(1, "add", h.BytesBE()))
|
||||
t.Run("NotEnoughArguments", runInvalid(
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Make(1)}), "add", h.BytesBE()))
|
||||
t.Run("TooMuchArguments", runInvalid(
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.Make(1), stackitem.Make(2), stackitem.Make(3), stackitem.Make(4)}),
|
||||
"add", h.BytesBE()))
|
||||
})
|
||||
|
||||
t.Run("ReturnValues", func(t *testing.T) {
|
||||
t.Run("Many", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(stackitem.NewArray(nil))
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("invalidReturn")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.Error(t, ic.VM.Run())
|
||||
})
|
||||
t.Run("Void", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(stackitem.NewArray(nil))
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("justReturn")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.NoError(t, ic.VM.Run())
|
||||
require.Equal(t, 2, ic.VM.Estack().Len())
|
||||
require.Equal(t, stackitem.Null{}, ic.VM.Estack().Pop().Item())
|
||||
require.Equal(t, big.NewInt(42), ic.VM.Estack().Pop().Value())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("IsolatedStack", func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(stackitem.NewArray(nil))
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("drop")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.Error(t, ic.VM.Run())
|
||||
})
|
||||
|
||||
t.Run("CallInitialize", func(t *testing.T) {
|
||||
t.Run("Directly", runInvalid(stackitem.NewArray([]stackitem.Item{}), "_initialize", h.BytesBE()))
|
||||
|
||||
loadScript(ic, currScript, 42)
|
||||
ic.VM.Estack().PushVal(stackitem.NewArray([]stackitem.Item{stackitem.Make(5)}))
|
||||
ic.VM.Estack().PushVal(callflag.All)
|
||||
ic.VM.Estack().PushVal("add3")
|
||||
ic.VM.Estack().PushVal(h.BytesBE())
|
||||
require.NoError(t, contract.Call(ic))
|
||||
require.NoError(t, ic.VM.Run())
|
||||
require.Equal(t, 2, ic.VM.Estack().Len())
|
||||
require.Equal(t, big.NewInt(8), ic.VM.Estack().Pop().Value())
|
||||
require.Equal(t, big.NewInt(42), ic.VM.Estack().Pop().Value())
|
||||
})
|
||||
}
|
||||
|
||||
func TestRuntimeCheckWitness(t *testing.T) {
|
||||
_, ic, _ := createVM(t)
|
||||
|
||||
|
|
Loading…
Reference in a new issue