From 945e9410e415078cb2bff54ccb8f0e59276c8f0d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 2 Oct 2020 14:16:25 +0300 Subject: [PATCH] cli: add test for `testinvokefunction` Check that contract can be properly deployed and invoked. --- cli/contract_test.go | 106 +++++++++++++++++++++++++++++++++ cli/executor_test.go | 5 +- cli/testdata/deploy/main.go | 31 ++++++++++ cli/testdata/deploy/neo-go.yml | 1 + cli/testdata/deploy/sub/put.go | 14 +++++ cli/testdata/deploy/updated.go | 6 ++ 6 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 cli/contract_test.go create mode 100644 cli/testdata/deploy/main.go create mode 100644 cli/testdata/deploy/neo-go.yml create mode 100644 cli/testdata/deploy/sub/put.go create mode 100644 cli/testdata/deploy/updated.go diff --git a/cli/contract_test.go b/cli/contract_test.go new file mode 100644 index 000000000..99c93ea4b --- /dev/null +++ b/cli/contract_test.go @@ -0,0 +1,106 @@ +package main + +import ( + "encoding/hex" + "encoding/json" + "io/ioutil" + "os" + "path" + "strings" + "testing" + + "github.com/nspcc-dev/neo-go/pkg/config" + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" + "github.com/nspcc-dev/neo-go/pkg/rpc/response/result" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm" + "github.com/stretchr/testify/require" +) + +func TestComlileAndInvokeFunction(t *testing.T) { + e := newExecutor(t, true) + defer e.Close(t) + + // For proper nef generation. + config.Version = "0.90.0-test" + + tmpDir := os.TempDir() + nefName := path.Join(tmpDir, "deploy.nef") + manifestName := path.Join(tmpDir, "deploy.manifest.json") + e.Run(t, "neo-go", "contract", "compile", + "--in", "testdata/deploy/main.go", // compile single file + "--config", "testdata/deploy/neo-go.yml", + "--out", nefName, "--manifest", manifestName) + + defer func() { + os.Remove(nefName) + os.Remove(manifestName) + }() + + e.In.WriteString("one\r") + e.Run(t, "neo-go", "contract", "deploy", + "--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr, + "--wallet", validatorWallet, "--address", validatorAddr, + "--in", nefName, "--manifest", manifestName) + + line, err := e.Out.ReadString('\n') + require.NoError(t, err) + line = strings.TrimSpace(strings.TrimPrefix(line, "Contract: ")) + h, err := util.Uint160DecodeStringLE(line) + require.NoError(t, err) + e.checkTxPersisted(t) + + e.In.WriteString("one\r") + e.Run(t, "neo-go", "contract", "testinvokefunction", + "--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr, + h.StringLE(), "getValue") + + res := new(result.Invoke) + require.NoError(t, json.Unmarshal(e.Out.Bytes(), res)) + require.Equal(t, vm.HaltState.String(), res.State) + require.Len(t, res.Stack, 1) + require.Equal(t, []byte("on create|sub create"), res.Stack[0].Value()) + + t.Run("Update", func(t *testing.T) { + nefName := path.Join(tmpDir, "updated.nef") + manifestName := path.Join(tmpDir, "updated.manifest.json") + e.Run(t, "neo-go", "contract", "compile", + "--config", "testdata/deploy/neo-go.yml", + "--in", "testdata/deploy/", // compile all files in dir + "--out", nefName, "--manifest", manifestName) + + defer func() { + os.Remove(nefName) + os.Remove(manifestName) + }() + + rawNef, err := ioutil.ReadFile(nefName) + require.NoError(t, err) + realNef, err := nef.FileFromBytes(rawNef) + require.NoError(t, err) + rawManifest, err := ioutil.ReadFile(manifestName) + require.NoError(t, err) + + e.In.WriteString("one\r") + e.Run(t, "neo-go", "contract", "invokefunction", + "--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr, + "--wallet", validatorWallet, "--address", validatorAddr, + h.StringLE(), "update", + "bytes:"+hex.EncodeToString(realNef.Script), + "bytes:"+hex.EncodeToString(rawManifest), + ) + e.checkTxPersisted(t, "Sent invocation transaction ") + + e.In.WriteString("one\r") + e.Run(t, "neo-go", "contract", "testinvokefunction", + "--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr, + hash.Hash160(realNef.Script).StringLE(), "getValue") + + res := new(result.Invoke) + require.NoError(t, json.Unmarshal(e.Out.Bytes(), res)) + require.Equal(t, vm.HaltState.String(), res.State) + require.Len(t, res.Stack, 1) + require.Equal(t, []byte("on update|sub update"), res.Stack[0].Value()) + }) +} diff --git a/cli/executor_test.go b/cli/executor_test.go index e4198d437..53c403b36 100644 --- a/cli/executor_test.go +++ b/cli/executor_test.go @@ -185,11 +185,14 @@ func (e *executor) run(args ...string) error { return e.CLI.Run(args) } -func (e *executor) checkTxPersisted(t *testing.T) (*transaction.Transaction, uint32) { +func (e *executor) checkTxPersisted(t *testing.T, prefix ...string) (*transaction.Transaction, uint32) { line, err := e.Out.ReadString('\n') require.NoError(t, err) line = strings.TrimSpace(line) + if len(prefix) > 0 { + line = strings.TrimPrefix(line, prefix[0]) + } h, err := util.Uint256DecodeStringLE(line) require.NoError(t, err, "can't decode tx hash: %s", line) diff --git a/cli/testdata/deploy/main.go b/cli/testdata/deploy/main.go new file mode 100644 index 000000000..f1d39360e --- /dev/null +++ b/cli/testdata/deploy/main.go @@ -0,0 +1,31 @@ +package deploy + +import ( + "github.com/nspcc-dev/neo-go/cli/testdata/deploy/sub" + "github.com/nspcc-dev/neo-go/pkg/interop/contract" + "github.com/nspcc-dev/neo-go/pkg/interop/storage" +) + +var key = "key" + +func _deploy(isUpdate bool) { + ctx := storage.GetContext() + value := "on create" + if isUpdate { + value = "on update" + } + storage.Put(ctx, key, value) +} + +// Update updates contract with the new one. +func Update(script, manifest []byte) { + contract.Update(script, manifest) +} + +// GetValue returns stored value. +func GetValue() string { + ctx := storage.GetReadOnlyContext() + val1 := storage.Get(ctx, key) + val2 := storage.Get(ctx, sub.Key) + return val1.(string) + "|" + val2.(string) +} diff --git a/cli/testdata/deploy/neo-go.yml b/cli/testdata/deploy/neo-go.yml new file mode 100644 index 000000000..3a9140d76 --- /dev/null +++ b/cli/testdata/deploy/neo-go.yml @@ -0,0 +1 @@ +hasstorage: true diff --git a/cli/testdata/deploy/sub/put.go b/cli/testdata/deploy/sub/put.go new file mode 100644 index 000000000..c3fe1c6ea --- /dev/null +++ b/cli/testdata/deploy/sub/put.go @@ -0,0 +1,14 @@ +package sub + +import "github.com/nspcc-dev/neo-go/pkg/interop/storage" + +var Key = "sub" + +func _deploy(isUpdate bool) { + ctx := storage.GetContext() + value := "sub create" + if isUpdate { + value = "sub update" + } + storage.Put(ctx, Key, value) +} diff --git a/cli/testdata/deploy/updated.go b/cli/testdata/deploy/updated.go new file mode 100644 index 000000000..fb6681d0f --- /dev/null +++ b/cli/testdata/deploy/updated.go @@ -0,0 +1,6 @@ +package deploy + +// NewMethod in updated contract. +func NewMethod() int { + return 42 +}