cli: move tests to subpackages

Refs. #2379, but not completely solves it, one package seriously outweights
others:

?       github.com/nspcc-dev/neo-go/cli [no test files]
ok      github.com/nspcc-dev/neo-go/cli/app     0.036s  coverage: 100.0% of statements
ok      github.com/nspcc-dev/neo-go/cli/cmdargs 0.011s  coverage: 60.8% of statements
ok      github.com/nspcc-dev/neo-go/cli/flags   0.009s  coverage: 97.7% of statements
?       github.com/nspcc-dev/neo-go/cli/input   [no test files]
ok      github.com/nspcc-dev/neo-go/cli/options 0.033s  coverage: 50.0% of statements
?       github.com/nspcc-dev/neo-go/cli/paramcontext    [no test files]
ok      github.com/nspcc-dev/neo-go/cli/query   2.155s  coverage: 45.3% of statements
ok      github.com/nspcc-dev/neo-go/cli/server  1.373s  coverage: 67.8% of statements
ok      github.com/nspcc-dev/neo-go/cli/smartcontract   8.819s  coverage: 94.3% of statements
ok      github.com/nspcc-dev/neo-go/cli/util    0.006s  coverage: 10.9% of statements
?       github.com/nspcc-dev/neo-go/cli/vm      [no test files]
ok      github.com/nspcc-dev/neo-go/cli/wallet  72.103s coverage: 88.2% of statements

Still a nice thing to have.
This commit is contained in:
Roman Khimov 2022-10-05 09:44:10 +03:00
parent 48567fbc61
commit 1ac60ada19
38 changed files with 633 additions and 593 deletions

41
cli/app/app.go Normal file
View file

@ -0,0 +1,41 @@
package app
import (
"fmt"
"os"
"runtime"
"github.com/nspcc-dev/neo-go/cli/query"
"github.com/nspcc-dev/neo-go/cli/server"
"github.com/nspcc-dev/neo-go/cli/smartcontract"
"github.com/nspcc-dev/neo-go/cli/util"
"github.com/nspcc-dev/neo-go/cli/vm"
"github.com/nspcc-dev/neo-go/cli/wallet"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/urfave/cli"
)
func versionPrinter(c *cli.Context) {
_, _ = fmt.Fprintf(c.App.Writer, "NeoGo\nVersion: %s\nGoVersion: %s\n",
config.Version,
runtime.Version(),
)
}
// New creates a NeoGo instance of [cli.App] with all commands included.
func New() *cli.App {
cli.VersionPrinter = versionPrinter
ctl := cli.NewApp()
ctl.Name = "neo-go"
ctl.Version = config.Version
ctl.Usage = "Official Go client for Neo"
ctl.ErrWriter = os.Stdout
ctl.Commands = append(ctl.Commands, server.NewCommands()...)
ctl.Commands = append(ctl.Commands, smartcontract.NewCommands()...)
ctl.Commands = append(ctl.Commands, wallet.NewCommands()...)
ctl.Commands = append(ctl.Commands, vm.NewCommands()...)
ctl.Commands = append(ctl.Commands, util.NewCommands()...)
ctl.Commands = append(ctl.Commands, query.NewCommands()...)
return ctl
}

18
cli/app/main_test.go Normal file
View file

@ -0,0 +1,18 @@
package app_test
import (
"testing"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/config"
)
func TestCLIVersion(t *testing.T) {
config.Version = "0.90.0-test" // Zero-length version string disables '--version' completely.
e := testcli.NewExecutor(t, false)
e.Run(t, "neo-go", "--version")
e.CheckNextLine(t, "^NeoGo")
e.CheckNextLine(t, "^Version:")
e.CheckNextLine(t, "^GoVersion:")
e.CheckEOF(t)
}

View file

@ -1,48 +1,15 @@
package main package main
import ( import (
"fmt"
"os" "os"
"runtime"
"github.com/nspcc-dev/neo-go/cli/query" "github.com/nspcc-dev/neo-go/cli/app"
"github.com/nspcc-dev/neo-go/cli/server"
"github.com/nspcc-dev/neo-go/cli/smartcontract"
"github.com/nspcc-dev/neo-go/cli/util"
"github.com/nspcc-dev/neo-go/cli/vm"
"github.com/nspcc-dev/neo-go/cli/wallet"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/urfave/cli"
) )
func main() { func main() {
ctl := newApp() ctl := app.New()
if err := ctl.Run(os.Args); err != nil { if err := ctl.Run(os.Args); err != nil {
panic(err) panic(err)
} }
} }
func versionPrinter(c *cli.Context) {
_, _ = fmt.Fprintf(c.App.Writer, "NeoGo\nVersion: %s\nGoVersion: %s\n",
config.Version,
runtime.Version(),
)
}
func newApp() *cli.App {
cli.VersionPrinter = versionPrinter
ctl := cli.NewApp()
ctl.Name = "neo-go"
ctl.Version = config.Version
ctl.Usage = "Official Go client for Neo"
ctl.ErrWriter = os.Stdout
ctl.Commands = append(ctl.Commands, server.NewCommands()...)
ctl.Commands = append(ctl.Commands, smartcontract.NewCommands()...)
ctl.Commands = append(ctl.Commands, wallet.NewCommands()...)
ctl.Commands = append(ctl.Commands, vm.NewCommands()...)
ctl.Commands = append(ctl.Commands, util.NewCommands()...)
ctl.Commands = append(ctl.Commands, query.NewCommands()...)
return ctl
}

View file

@ -1,14 +0,0 @@
package main
import (
"testing"
)
func TestCLIVersion(t *testing.T) {
e := newExecutor(t, false)
e.Run(t, "neo-go", "--version")
e.checkNextLine(t, "^NeoGo")
e.checkNextLine(t, "^Version:")
e.checkNextLine(t, "^GoVersion:")
e.checkEOF(t)
}

View file

@ -1,20 +1,22 @@
package main package options_test
import ( import (
"flag" "flag"
"testing" "testing"
"github.com/nspcc-dev/neo-go/cli/app"
"github.com/nspcc-dev/neo-go/cli/options" "github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
func TestGetRPCClient(t *testing.T) { func TestGetRPCClient(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
t.Run("no endpoint", func(t *testing.T) { t.Run("no endpoint", func(t *testing.T) {
set := flag.NewFlagSet("flagSet", flag.ExitOnError) set := flag.NewFlagSet("flagSet", flag.ExitOnError)
ctx := cli.NewContext(cli.NewApp(), set, nil) ctx := cli.NewContext(app.New(), set, nil)
gctx, _ := options.GetTimeoutContext(ctx) gctx, _ := options.GetTimeoutContext(ctx)
_, ec := options.GetRPCClient(gctx, ctx) _, ec := options.GetRPCClient(gctx, ctx)
require.Equal(t, 1, ec.ExitCode()) require.Equal(t, 1, ec.ExitCode())
@ -23,7 +25,7 @@ func TestGetRPCClient(t *testing.T) {
t.Run("success", func(t *testing.T) { t.Run("success", func(t *testing.T) {
set := flag.NewFlagSet("flagSet", flag.ExitOnError) set := flag.NewFlagSet("flagSet", flag.ExitOnError)
set.String(options.RPCEndpointFlag, "http://"+e.RPC.Addr, "") set.String(options.RPCEndpointFlag, "http://"+e.RPC.Addr, "")
ctx := cli.NewContext(cli.NewApp(), set, nil) ctx := cli.NewContext(app.New(), set, nil)
gctx, _ := options.GetTimeoutContext(ctx) gctx, _ := options.GetTimeoutContext(ctx)
_, ec := options.GetRPCClient(gctx, ctx) _, ec := options.GetRPCClient(gctx, ctx)
require.Nil(t, ec) require.Nil(t, ec)

View file

@ -1,4 +1,4 @@
package main package query_test
import ( import (
"encoding/base64" "encoding/base64"
@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/internal/random"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
@ -22,24 +23,24 @@ import (
) )
func TestQueryTx(t *testing.T) { func TestQueryTx(t *testing.T) {
e := newExecutorSuspended(t) e := testcli.NewExecutorSuspended(t)
w, err := wallet.NewWalletFromFile("testdata/testwallet.json") w, err := wallet.NewWalletFromFile("../testdata/testwallet.json")
require.NoError(t, err) require.NoError(t, err)
transferArgs := []string{ transferArgs := []string{
"neo-go", "wallet", "nep17", "transfer", "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--to", w.Accounts[0].Address, "--to", w.Accounts[0].Address,
"--token", "NEO", "--token", "NEO",
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
} }
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, append(transferArgs, "--amount", "1")...) e.Run(t, append(transferArgs, "--amount", "1")...)
line := e.getNextLine(t) line := e.GetNextLine(t)
txHash, err := util.Uint256DecodeStringLE(line) txHash, err := util.Uint256DecodeStringLE(line)
require.NoError(t, err) require.NoError(t, err)
@ -48,42 +49,42 @@ func TestQueryTx(t *testing.T) {
args := []string{"neo-go", "query", "tx", "--rpc-endpoint", "http://" + e.RPC.Addr} args := []string{"neo-go", "query", "tx", "--rpc-endpoint", "http://" + e.RPC.Addr}
e.Run(t, append(args, txHash.StringLE())...) e.Run(t, append(args, txHash.StringLE())...)
e.checkNextLine(t, `Hash:\s+`+txHash.StringLE()) e.CheckNextLine(t, `Hash:\s+`+txHash.StringLE())
e.checkNextLine(t, `OnChain:\s+false`) e.CheckNextLine(t, `OnChain:\s+false`)
e.checkNextLine(t, `ValidUntil:\s+`+strconv.FormatUint(uint64(tx.ValidUntilBlock), 10)) e.CheckNextLine(t, `ValidUntil:\s+`+strconv.FormatUint(uint64(tx.ValidUntilBlock), 10))
e.checkEOF(t) e.CheckEOF(t)
height := e.Chain.BlockHeight() height := e.Chain.BlockHeight()
go e.Chain.Run() go e.Chain.Run()
require.Eventually(t, func() bool { return e.Chain.BlockHeight() > height }, time.Second*2, time.Millisecond*50) require.Eventually(t, func() bool { return e.Chain.BlockHeight() > height }, time.Second*2, time.Millisecond*50)
e.Run(t, append(args, txHash.StringLE())...) e.Run(t, append(args, txHash.StringLE())...)
e.checkNextLine(t, `Hash:\s+`+txHash.StringLE()) e.CheckNextLine(t, `Hash:\s+`+txHash.StringLE())
e.checkNextLine(t, `OnChain:\s+true`) e.CheckNextLine(t, `OnChain:\s+true`)
_, height, err = e.Chain.GetTransaction(txHash) _, height, err = e.Chain.GetTransaction(txHash)
require.NoError(t, err) require.NoError(t, err)
e.checkNextLine(t, `BlockHash:\s+`+e.Chain.GetHeaderHash(int(height)).StringLE()) e.CheckNextLine(t, `BlockHash:\s+`+e.Chain.GetHeaderHash(int(height)).StringLE())
e.checkNextLine(t, `Success:\s+true`) e.CheckNextLine(t, `Success:\s+true`)
e.checkEOF(t) e.CheckEOF(t)
t.Run("verbose", func(t *testing.T) { t.Run("verbose", func(t *testing.T) {
e.Run(t, append(args, "--verbose", txHash.StringLE())...) e.Run(t, append(args, "--verbose", txHash.StringLE())...)
e.compareQueryTxVerbose(t, tx) compareQueryTxVerbose(t, e, tx)
t.Run("FAULT", func(t *testing.T) { t.Run("FAULT", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "invokefunction", e.Run(t, "neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorAddr, "--address", testcli.ValidatorAddr,
"--force", "--force",
random.Uint160().StringLE(), random.Uint160().StringLE(),
"randomMethod") "randomMethod")
e.checkNextLine(t, `Warning:`) e.CheckNextLine(t, `Warning:`)
e.checkNextLine(t, "Sending transaction") e.CheckNextLine(t, "Sending transaction")
line := strings.TrimPrefix(e.getNextLine(t), "Sent invocation transaction ") line := strings.TrimPrefix(e.GetNextLine(t), "Sent invocation transaction ")
txHash, err := util.Uint256DecodeStringLE(line) txHash, err := util.Uint256DecodeStringLE(line)
require.NoError(t, err) require.NoError(t, err)
@ -93,7 +94,7 @@ func TestQueryTx(t *testing.T) {
tx, _, err := e.Chain.GetTransaction(txHash) tx, _, err := e.Chain.GetTransaction(txHash)
require.NoError(t, err) require.NoError(t, err)
e.Run(t, append(args, "--verbose", txHash.StringLE())...) e.Run(t, append(args, "--verbose", txHash.StringLE())...)
e.compareQueryTxVerbose(t, tx) compareQueryTxVerbose(t, e, tx)
}) })
}) })
@ -113,43 +114,43 @@ func TestQueryTx(t *testing.T) {
}) })
} }
func (e *executor) compareQueryTxVerbose(t *testing.T, tx *transaction.Transaction) { func compareQueryTxVerbose(t *testing.T, e *testcli.Executor, tx *transaction.Transaction) {
e.checkNextLine(t, `Hash:\s+`+tx.Hash().StringLE()) e.CheckNextLine(t, `Hash:\s+`+tx.Hash().StringLE())
e.checkNextLine(t, `OnChain:\s+true`) e.CheckNextLine(t, `OnChain:\s+true`)
_, height, err := e.Chain.GetTransaction(tx.Hash()) _, height, err := e.Chain.GetTransaction(tx.Hash())
require.NoError(t, err) require.NoError(t, err)
e.checkNextLine(t, `BlockHash:\s+`+e.Chain.GetHeaderHash(int(height)).StringLE()) e.CheckNextLine(t, `BlockHash:\s+`+e.Chain.GetHeaderHash(int(height)).StringLE())
res, _ := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application) res, _ := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
e.checkNextLine(t, fmt.Sprintf(`Success:\s+%t`, res[0].Execution.VMState == vmstate.Halt)) e.CheckNextLine(t, fmt.Sprintf(`Success:\s+%t`, res[0].Execution.VMState == vmstate.Halt))
for _, s := range tx.Signers { for _, s := range tx.Signers {
e.checkNextLine(t, fmt.Sprintf(`Signer:\s+%s\s*\(%s\)`, address.Uint160ToString(s.Account), s.Scopes.String())) e.CheckNextLine(t, fmt.Sprintf(`Signer:\s+%s\s*\(%s\)`, address.Uint160ToString(s.Account), s.Scopes.String()))
} }
e.checkNextLine(t, `SystemFee:\s+`+fixedn.Fixed8(tx.SystemFee).String()+" GAS$") e.CheckNextLine(t, `SystemFee:\s+`+fixedn.Fixed8(tx.SystemFee).String()+" GAS$")
e.checkNextLine(t, `NetworkFee:\s+`+fixedn.Fixed8(tx.NetworkFee).String()+" GAS$") e.CheckNextLine(t, `NetworkFee:\s+`+fixedn.Fixed8(tx.NetworkFee).String()+" GAS$")
e.checkNextLine(t, `Script:\s+`+regexp.QuoteMeta(base64.StdEncoding.EncodeToString(tx.Script))) e.CheckNextLine(t, `Script:\s+`+regexp.QuoteMeta(base64.StdEncoding.EncodeToString(tx.Script)))
c := vm.NewContext(tx.Script) c := vm.NewContext(tx.Script)
n := 0 n := 0
for ; c.NextIP() < c.LenInstr(); _, _, err = c.Next() { for ; c.NextIP() < c.LenInstr(); _, _, err = c.Next() {
require.NoError(t, err) require.NoError(t, err)
n++ n++
} }
e.checkScriptDump(t, n) e.CheckScriptDump(t, n)
if res[0].Execution.VMState != vmstate.Halt { if res[0].Execution.VMState != vmstate.Halt {
e.checkNextLine(t, `Exception:\s+`+regexp.QuoteMeta(res[0].Execution.FaultException)) e.CheckNextLine(t, `Exception:\s+`+regexp.QuoteMeta(res[0].Execution.FaultException))
} }
e.checkEOF(t) e.CheckEOF(t)
} }
func TestQueryHeight(t *testing.T) { func TestQueryHeight(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
args := []string{"neo-go", "query", "height", "--rpc-endpoint", "http://" + e.RPC.Addr} args := []string{"neo-go", "query", "height", "--rpc-endpoint", "http://" + e.RPC.Addr}
e.Run(t, args...) e.Run(t, args...)
e.checkNextLine(t, `^Latest block: [0-9]+$`) e.CheckNextLine(t, `^Latest block: [0-9]+$`)
e.checkNextLine(t, `^Validated state: [0-9]+$`) e.CheckNextLine(t, `^Validated state: [0-9]+$`)
e.checkEOF(t) e.CheckEOF(t)
t.Run("excessive arguments", func(t *testing.T) { t.Run("excessive arguments", func(t *testing.T) {
e.RunWithError(t, append(args, "something")...) e.RunWithError(t, append(args, "something")...)
}) })

View file

@ -1,4 +1,4 @@
package main package server_test
import ( import (
"os" "os"
@ -6,6 +6,7 @@ import (
"strconv" "strconv"
"testing" "testing"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
@ -16,7 +17,7 @@ func TestDBRestoreDump(t *testing.T) {
loadConfig := func(t *testing.T) config.Config { loadConfig := func(t *testing.T) config.Config {
chainPath := filepath.Join(tmpDir, "neogotestchain") chainPath := filepath.Join(tmpDir, "neogotestchain")
cfg, err := config.LoadFile(filepath.Join("..", "config", "protocol.unit_testnet.yml")) cfg, err := config.LoadFile(filepath.Join("..", "..", "config", "protocol.unit_testnet.yml"))
require.NoError(t, err, "could not load config") require.NoError(t, err, "could not load config")
cfg.ApplicationConfiguration.DBConfiguration.Type = "leveldb" cfg.ApplicationConfiguration.DBConfiguration.Type = "leveldb"
cfg.ApplicationConfiguration.DBConfiguration.LevelDBOptions.DataDirectoryPath = chainPath cfg.ApplicationConfiguration.DBConfiguration.LevelDBOptions.DataDirectoryPath = chainPath
@ -30,9 +31,9 @@ func TestDBRestoreDump(t *testing.T) {
cfgPath := filepath.Join(tmpDir, "protocol.unit_testnet.yml") cfgPath := filepath.Join(tmpDir, "protocol.unit_testnet.yml")
require.NoError(t, os.WriteFile(cfgPath, out, os.ModePerm)) require.NoError(t, os.WriteFile(cfgPath, out, os.ModePerm))
// generated via `go run ./scripts/gendump/main.go --out ./cli/testdata/chain50x2.acc --blocks 50 --txs 2` // generated via `go run ./scripts/gendump/main.go --out ./cli/server/testdata/chain50x2.acc --blocks 50 --txs 2`
const inDump = "./testdata/chain50x2.acc" const inDump = "./testdata/chain50x2.acc"
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
stateDump := filepath.Join(tmpDir, "neogo.teststate") stateDump := filepath.Join(tmpDir, "neogo.teststate")
baseArgs := []string{"neo-go", "db", "restore", "--unittest", baseArgs := []string{"neo-go", "db", "restore", "--unittest",

View file

@ -1,4 +1,4 @@
package main package server_test
import ( import (
"errors" "errors"
@ -11,6 +11,7 @@ import (
"time" "time"
"github.com/nspcc-dev/neo-go/cli/server" "github.com/nspcc-dev/neo-go/cli/server"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
@ -18,7 +19,7 @@ import (
func TestServerStart(t *testing.T) { func TestServerStart(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
goodCfg, err := config.LoadFile(filepath.Join("..", "config", "protocol.unit_testnet.yml")) goodCfg, err := config.LoadFile(filepath.Join("..", "..", "config", "protocol.unit_testnet.yml"))
require.NoError(t, err, "could not load config") require.NoError(t, err, "could not load config")
ptr := &goodCfg ptr := &goodCfg
saveCfg := func(t *testing.T, f func(cfg *config.Config)) string { saveCfg := func(t *testing.T, f func(cfg *config.Config)) string {
@ -39,7 +40,7 @@ func TestServerStart(t *testing.T) {
} }
baseCmd := []string{"neo-go", "node", "--unittest", "--config-path", tmpDir} baseCmd := []string{"neo-go", "node", "--unittest", "--config-path", tmpDir}
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
t.Run("invalid config path", func(t *testing.T) { t.Run("invalid config path", func(t *testing.T) {
e.RunWithError(t, baseCmd...) e.RunWithError(t, baseCmd...)
@ -120,11 +121,11 @@ func TestServerStart(t *testing.T) {
for _, expected := range lines { for _, expected := range lines {
// It should be regexp, so escape all backslashes. // It should be regexp, so escape all backslashes.
expected = strings.ReplaceAll(expected, `\`, `\\`) expected = strings.ReplaceAll(expected, `\`, `\\`)
e.checkLine(t, line, expected) e.CheckLine(t, line, expected)
line = e.getNextLine(t) line = e.GetNextLine(t)
} }
e.checkNextLine(t, "") e.CheckNextLine(t, "")
e.checkEOF(t) e.CheckEOF(t)
}) })
} }
} }

View file

@ -1,4 +1,4 @@
package main package smartcontract_test
import ( import (
"bytes" "bytes"
@ -12,6 +12,7 @@ import (
"github.com/nspcc-dev/neo-go/cli/smartcontract" "github.com/nspcc-dev/neo-go/cli/smartcontract"
"github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/internal/random"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core/interop/storage" "github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
@ -32,7 +33,7 @@ import (
func TestCalcHash(t *testing.T) { func TestCalcHash(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
nefPath := "./testdata/verify.nef" nefPath := "./testdata/verify.nef"
src, err := os.ReadFile(nefPath) src, err := os.ReadFile(nefPath)
@ -83,15 +84,15 @@ func TestCalcHash(t *testing.T) {
}) })
t.Run("valid, uint160", func(t *testing.T) { t.Run("valid, uint160", func(t *testing.T) {
e.Run(t, append(cmd, "--sender", sender.StringLE())...) e.Run(t, append(cmd, "--sender", sender.StringLE())...)
e.checkNextLine(t, expected.StringLE()) e.CheckNextLine(t, expected.StringLE())
}) })
t.Run("valid, uint160 with 0x", func(t *testing.T) { t.Run("valid, uint160 with 0x", func(t *testing.T) {
e.Run(t, append(cmd, "--sender", "0x"+sender.StringLE())...) e.Run(t, append(cmd, "--sender", "0x"+sender.StringLE())...)
e.checkNextLine(t, expected.StringLE()) e.CheckNextLine(t, expected.StringLE())
}) })
t.Run("valid, address", func(t *testing.T) { t.Run("valid, address", func(t *testing.T) {
e.Run(t, append(cmd, "--sender", address.Uint160ToString(sender))...) e.Run(t, append(cmd, "--sender", address.Uint160ToString(sender))...)
e.checkNextLine(t, expected.StringLE()) e.CheckNextLine(t, expected.StringLE())
}) })
} }
@ -103,7 +104,7 @@ func TestContractBindings(t *testing.T) {
smartcontract.ModVersion = "v0.0.0" smartcontract.ModVersion = "v0.0.0"
tmpDir := t.TempDir() tmpDir := t.TempDir()
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
ctrPath := filepath.Join(tmpDir, "testcontract") ctrPath := filepath.Join(tmpDir, "testcontract")
e.Run(t, "neo-go", "contract", "init", "--name", ctrPath) e.Run(t, "neo-go", "contract", "init", "--name", ctrPath)
@ -152,7 +153,7 @@ func Blocks() []*alias.Block {
wd, err := os.Getwd() wd, err := os.Getwd()
require.NoError(t, err) require.NoError(t, err)
data = append(data, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "...) data = append(data, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "...)
data = append(data, filepath.Join(wd, "../pkg/interop")...) data = append(data, filepath.Join(wd, "../../pkg/interop")...)
require.NoError(t, os.WriteFile(goMod, data, os.ModePerm)) require.NoError(t, os.WriteFile(goMod, data, os.ModePerm))
cmd = append(cmd, "--config", cfgPath, cmd = append(cmd, "--config", cfgPath,
@ -163,7 +164,7 @@ func Blocks() []*alias.Block {
e.RunWithError(t, append(cmd, "something")...) e.RunWithError(t, append(cmd, "something")...)
}) })
e.Run(t, cmd...) e.Run(t, cmd...)
e.checkEOF(t) e.CheckEOF(t)
require.FileExists(t, bindingsPath) require.FileExists(t, bindingsPath)
outPath := filepath.Join(t.TempDir(), "binding.go") outPath := filepath.Join(t.TempDir(), "binding.go")
@ -216,7 +217,7 @@ func TestContractInitAndCompile(t *testing.T) {
smartcontract.ModVersion = "v0.0.0" smartcontract.ModVersion = "v0.0.0"
tmpDir := t.TempDir() tmpDir := t.TempDir()
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
t.Run("no path is provided", func(t *testing.T) { t.Run("no path is provided", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "init") e.RunWithError(t, "neo-go", "contract", "init")
@ -269,7 +270,7 @@ func TestContractInitAndCompile(t *testing.T) {
wd, err := os.Getwd() wd, err := os.Getwd()
require.NoError(t, err) require.NoError(t, err)
data = append(data, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "...) data = append(data, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "...)
data = append(data, filepath.Join(wd, "../pkg/interop")...) data = append(data, filepath.Join(wd, "../../pkg/interop")...)
require.NoError(t, os.WriteFile(goMod, data, os.ModePerm)) require.NoError(t, os.WriteFile(goMod, data, os.ModePerm))
cmd = append(cmd, "--config", cfgPath) cmd = append(cmd, "--config", cfgPath)
@ -279,20 +280,20 @@ func TestContractInitAndCompile(t *testing.T) {
}) })
e.Run(t, cmd...) e.Run(t, cmd...)
e.checkEOF(t) e.CheckEOF(t)
require.FileExists(t, nefPath) require.FileExists(t, nefPath)
require.FileExists(t, manifestPath) require.FileExists(t, manifestPath)
t.Run("output hex script with --verbose", func(t *testing.T) { t.Run("output hex script with --verbose", func(t *testing.T) {
e.Run(t, append(cmd, "--verbose")...) e.Run(t, append(cmd, "--verbose")...)
e.checkNextLine(t, "^[0-9a-hA-H]+$") e.CheckNextLine(t, "^[0-9a-hA-H]+$")
}) })
} }
// Checks that error is returned if GAS available for test-invoke exceeds // Checks that error is returned if GAS available for test-invoke exceeds
// GAS needed to be consumed. // GAS needed to be consumed.
func TestDeployBigContract(t *testing.T) { func TestDeployBigContract(t *testing.T) {
e := newExecutorWithConfig(t, true, true, func(c *config.Config) { e := testcli.NewExecutorWithConfig(t, true, true, func(c *config.Config) {
c.ApplicationConfiguration.RPC.MaxGasInvoke = fixedn.Fixed8(1) c.ApplicationConfiguration.RPC.MaxGasInvoke = fixedn.Fixed8(1)
}) })
@ -307,15 +308,15 @@ func TestDeployBigContract(t *testing.T) {
"--config", "testdata/deploy/neo-go.yml", "--config", "testdata/deploy/neo-go.yml",
"--out", nefName, "--manifest", manifestName) "--out", nefName, "--manifest", manifestName)
e.In.WriteString("one\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName) "--in", nefName, "--manifest", manifestName)
} }
func TestContractDeployWithData(t *testing.T) { func TestContractDeployWithData(t *testing.T) {
eCompile := newExecutor(t, false) eCompile := testcli.NewExecutor(t, false)
// For proper nef generation. // For proper nef generation.
config.Version = "0.90.0-test" config.Version = "0.90.0-test"
@ -329,11 +330,11 @@ func TestContractDeployWithData(t *testing.T) {
"--out", nefName, "--manifest", manifestName) "--out", nefName, "--manifest", manifestName)
deployContract := func(t *testing.T, haveData bool, scope string) { deployContract := func(t *testing.T, haveData bool, scope string) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
cmd := []string{ cmd := []string{
"neo-go", "contract", "deploy", "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"--force", "--force",
} }
@ -342,14 +343,14 @@ func TestContractDeployWithData(t *testing.T) {
cmd = append(cmd, "[", "key1", "12", "key2", "take_me_to_church", "]") cmd = append(cmd, "[", "key1", "12", "key2", "take_me_to_church", "]")
} }
if scope != "" { if scope != "" {
cmd = append(cmd, "--", validatorAddr+":"+scope) cmd = append(cmd, "--", testcli.ValidatorAddr+":"+scope)
} else { } else {
scope = "CalledByEntry" scope = "CalledByEntry"
} }
e.In.WriteString("one\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.Run(t, cmd...) e.Run(t, cmd...)
tx, _ := e.checkTxPersisted(t, "Sent invocation transaction ") tx, _ := e.CheckTxPersisted(t, "Sent invocation transaction ")
require.Equal(t, scope, tx.Signers[0].Scopes.String()) require.Equal(t, scope, tx.Signers[0].Scopes.String())
if !haveData { if !haveData {
return return
@ -392,7 +393,7 @@ func TestContractDeployWithData(t *testing.T) {
} }
func TestDeployWithSigners(t *testing.T) { func TestDeployWithSigners(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
// For proper nef generation. // For proper nef generation.
config.Version = "0.90.0-test" config.Version = "0.90.0-test"
@ -408,61 +409,61 @@ func TestDeployWithSigners(t *testing.T) {
t.Run("missing nef", func(t *testing.T) { t.Run("missing nef", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", "", "--manifest", manifestName) "--in", "", "--manifest", manifestName)
}) })
t.Run("missing manifest", func(t *testing.T) { t.Run("missing manifest", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", "") "--in", nefName, "--manifest", "")
}) })
t.Run("corrupted data", func(t *testing.T) { t.Run("corrupted data", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"[", "str1") "[", "str1")
}) })
t.Run("invalid data", func(t *testing.T) { t.Run("invalid data", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"str1", "str2") "str1", "str2")
}) })
t.Run("missing wallet", func(t *testing.T) { t.Run("missing wallet", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--address", validatorAddr, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"[", "str1", "str2", "]") "[", "str1", "str2", "]")
}) })
t.Run("missing RPC", func(t *testing.T) { t.Run("missing RPC", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "deploy", e.RunWithError(t, "neo-go", "contract", "deploy",
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"[", "str1", "str2", "]") "[", "str1", "str2", "]")
}) })
e.In.WriteString("one\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.Run(t, "neo-go", "contract", "deploy", e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"--force", "--force",
"--", validatorAddr+":Global") "--", testcli.ValidatorAddr+":Global")
tx, _ := e.checkTxPersisted(t, "Sent invocation transaction ") tx, _ := e.CheckTxPersisted(t, "Sent invocation transaction ")
require.Equal(t, transaction.Global, tx.Signers[0].Scopes) require.Equal(t, transaction.Global, tx.Signers[0].Scopes)
} }
func TestContractManifestGroups(t *testing.T) { func TestContractManifestGroups(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
// For proper nef generation. // For proper nef generation.
config.Version = "0.90.0-test" config.Version = "0.90.0-test"
tmpDir := t.TempDir() tmpDir := t.TempDir()
_, err := wallet.NewWalletFromFile(testWalletPath) _, err := wallet.NewWalletFromFile(testcli.TestWalletPath)
require.NoError(t, err) require.NoError(t, err)
nefName := filepath.Join(tmpDir, "deploy.nef") nefName := filepath.Join(tmpDir, "deploy.nef")
@ -481,93 +482,70 @@ func TestContractManifestGroups(t *testing.T) {
}) })
t.Run("invalid sender", func(t *testing.T) { t.Run("invalid sender", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "manifest", "add-group", e.RunWithError(t, "neo-go", "contract", "manifest", "add-group",
"--wallet", testWalletPath, "--address", testWalletAccount, "--wallet", testcli.TestWalletPath, "--address", testcli.TestWalletAccount,
"--sender", "not-a-sender") "--sender", "not-a-sender")
}) })
t.Run("invalid NEF file", func(t *testing.T) { t.Run("invalid NEF file", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "manifest", "add-group", e.RunWithError(t, "neo-go", "contract", "manifest", "add-group",
"--wallet", testWalletPath, "--address", testWalletAccount, "--wallet", testcli.TestWalletPath, "--address", testcli.TestWalletAccount,
"--sender", testWalletAccount, "--nef", tmpDir) "--sender", testcli.TestWalletAccount, "--nef", tmpDir)
}) })
t.Run("corrupted NEF file", func(t *testing.T) { t.Run("corrupted NEF file", func(t *testing.T) {
f := filepath.Join(tmpDir, "invalid.nef") f := filepath.Join(tmpDir, "invalid.nef")
require.NoError(t, os.WriteFile(f, []byte{1, 2, 3}, os.ModePerm)) require.NoError(t, os.WriteFile(f, []byte{1, 2, 3}, os.ModePerm))
e.RunWithError(t, "neo-go", "contract", "manifest", "add-group", e.RunWithError(t, "neo-go", "contract", "manifest", "add-group",
"--wallet", testWalletPath, "--address", testWalletAccount, "--wallet", testcli.TestWalletPath, "--address", testcli.TestWalletAccount,
"--sender", testWalletAccount, "--nef", f) "--sender", testcli.TestWalletAccount, "--nef", f)
}) })
t.Run("invalid manifest file", func(t *testing.T) { t.Run("invalid manifest file", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "manifest", "add-group", e.RunWithError(t, "neo-go", "contract", "manifest", "add-group",
"--wallet", testWalletPath, "--address", testWalletAccount, "--wallet", testcli.TestWalletPath, "--address", testcli.TestWalletAccount,
"--sender", testWalletAccount, "--nef", nefName, "--sender", testcli.TestWalletAccount, "--nef", nefName,
"--manifest", tmpDir) "--manifest", tmpDir)
}) })
t.Run("corrupted manifest file", func(t *testing.T) { t.Run("corrupted manifest file", func(t *testing.T) {
f := filepath.Join(tmpDir, "invalid.manifest.json") f := filepath.Join(tmpDir, "invalid.manifest.json")
require.NoError(t, os.WriteFile(f, []byte{1, 2, 3}, os.ModePerm)) require.NoError(t, os.WriteFile(f, []byte{1, 2, 3}, os.ModePerm))
e.RunWithError(t, "neo-go", "contract", "manifest", "add-group", e.RunWithError(t, "neo-go", "contract", "manifest", "add-group",
"--wallet", testWalletPath, "--address", testWalletAccount, "--wallet", testcli.TestWalletPath, "--address", testcli.TestWalletAccount,
"--sender", testWalletAccount, "--nef", nefName, "--sender", testcli.TestWalletAccount, "--nef", nefName,
"--manifest", f) "--manifest", f)
}) })
t.Run("unknown account", func(t *testing.T) { t.Run("unknown account", func(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "manifest", "add-group", e.RunWithError(t, "neo-go", "contract", "manifest", "add-group",
"--wallet", testWalletPath, "--address", util.Uint160{}.StringLE(), "--wallet", testcli.TestWalletPath, "--address", util.Uint160{}.StringLE(),
"--sender", testWalletAccount, "--nef", nefName, "--sender", testcli.TestWalletAccount, "--nef", nefName,
"--manifest", manifestName) "--manifest", manifestName)
}) })
cmd := []string{"neo-go", "contract", "manifest", "add-group", cmd := []string{"neo-go", "contract", "manifest", "add-group",
"--nef", nefName, "--manifest", manifestName} "--nef", nefName, "--manifest", manifestName}
t.Run("excessive parameters", func(t *testing.T) { t.Run("excessive parameters", func(t *testing.T) {
e.RunWithError(t, append(cmd, "--wallet", testWalletPath, e.RunWithError(t, append(cmd, "--wallet", testcli.TestWalletPath,
"--sender", testWalletAccount, "--address", testWalletAccount, "something")...) "--sender", testcli.TestWalletAccount, "--address", testcli.TestWalletAccount, "something")...)
}) })
e.In.WriteString("testpass\r") e.In.WriteString("testpass\r")
e.Run(t, append(cmd, "--wallet", testWalletPath, e.Run(t, append(cmd, "--wallet", testcli.TestWalletPath,
"--sender", testWalletAccount, "--address", testWalletAccount)...) "--sender", testcli.TestWalletAccount, "--address", testcli.TestWalletAccount)...)
e.In.WriteString("testpass\r") // should override signature with the previous sender e.In.WriteString("testpass\r") // should override signature with the previous sender
e.Run(t, append(cmd, "--wallet", testWalletPath, e.Run(t, append(cmd, "--wallet", testcli.TestWalletPath,
"--sender", validatorAddr, "--address", testWalletAccount)...) "--sender", testcli.ValidatorAddr, "--address", testcli.TestWalletAccount)...)
e.In.WriteString("one\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.Run(t, "neo-go", "contract", "deploy", e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--in", nefName, "--manifest", manifestName, "--in", nefName, "--manifest", manifestName,
"--force", "--force",
"--wallet", validatorWallet, "--address", validatorAddr) "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr)
} }
func deployVerifyContract(t *testing.T, e *executor) util.Uint160 { func deployVerifyContract(t *testing.T, e *testcli.Executor) util.Uint160 {
return deployContract(t, e, "testdata/verify.go", "testdata/verify.yml", validatorWallet, validatorAddr, "one") return testcli.DeployContract(t, e, "testdata/verify.go", "testdata/verify.yml", testcli.ValidatorWallet, testcli.ValidatorAddr, testcli.ValidatorPass)
}
func deployContract(t *testing.T, e *executor, inPath, configPath, wallet, address, pass string) util.Uint160 {
tmpDir := t.TempDir()
nefName := filepath.Join(tmpDir, "contract.nef")
manifestName := filepath.Join(tmpDir, "contract.manifest.json")
e.Run(t, "neo-go", "contract", "compile",
"--in", inPath,
"--config", configPath,
"--out", nefName, "--manifest", manifestName)
e.In.WriteString(pass + "\r")
e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", wallet, "--address", address,
"--force",
"--in", nefName, "--manifest", manifestName)
e.checkTxPersisted(t, "Sent invocation transaction ")
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)
return h
} }
func TestContract_TestInvokeScript(t *testing.T) { func TestContract_TestInvokeScript(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
tmpDir := t.TempDir() tmpDir := t.TempDir()
badNef := filepath.Join(tmpDir, "invalid.nef") badNef := filepath.Join(tmpDir, "invalid.nef")
goodNef := filepath.Join(tmpDir, "deploy.nef") goodNef := filepath.Join(tmpDir, "deploy.nef")
@ -638,7 +616,7 @@ func TestContract_TestInvokeScript(t *testing.T) {
} }
func TestComlileAndInvokeFunction(t *testing.T) { func TestComlileAndInvokeFunction(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
// For proper nef generation. // For proper nef generation.
config.Version = "0.90.0-test" config.Version = "0.90.0-test"
@ -654,18 +632,18 @@ func TestComlileAndInvokeFunction(t *testing.T) {
tmp := t.TempDir() tmp := t.TempDir()
configPath := filepath.Join(tmp, "config.yaml") configPath := filepath.Join(tmp, "config.yaml")
cfg := config.Wallet{ cfg := config.Wallet{
Path: validatorWallet, Path: testcli.ValidatorWallet,
Password: "one", Password: testcli.ValidatorPass,
} }
yml, err := yaml.Marshal(cfg) yml, err := yaml.Marshal(cfg)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, os.WriteFile(configPath, yml, 0666)) require.NoError(t, os.WriteFile(configPath, yml, 0666))
e.Run(t, "neo-go", "contract", "deploy", e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--force", "--rpc-endpoint", "http://"+e.RPC.Addr, "--force",
"--wallet-config", configPath, "--address", validatorAddr, "--wallet-config", configPath, "--address", testcli.ValidatorAddr,
"--in", nefName, "--manifest", manifestName) "--in", nefName, "--manifest", manifestName)
e.checkTxPersisted(t, "Sent invocation transaction ") e.CheckTxPersisted(t, "Sent invocation transaction ")
line, err := e.Out.ReadString('\n') line, err := e.Out.ReadString('\n')
require.NoError(t, err) require.NoError(t, err)
line = strings.TrimSpace(strings.TrimPrefix(line, "Contract: ")) line = strings.TrimSpace(strings.TrimPrefix(line, "Contract: "))
@ -679,9 +657,9 @@ func TestComlileAndInvokeFunction(t *testing.T) {
"--manifest", manifestName) "--manifest", manifestName)
e.Run(t, "neo-go", "contract", "calc-hash", e.Run(t, "neo-go", "contract", "calc-hash",
"--sender", validatorAddr, "--in", nefName, "--sender", testcli.ValidatorAddr, "--in", nefName,
"--manifest", manifestName) "--manifest", manifestName)
e.checkNextLine(t, h.StringLE()) e.CheckNextLine(t, h.StringLE())
}) })
cmd := []string{"neo-go", "contract", "testinvokefunction", cmd := []string{"neo-go", "contract", "testinvokefunction",
@ -746,28 +724,28 @@ func TestComlileAndInvokeFunction(t *testing.T) {
e.RunWithError(t, cmd...) e.RunWithError(t, cmd...)
}) })
t.Run("non-existent address", func(t *testing.T) { t.Run("non-existent address", func(t *testing.T) {
cmd := append(cmd, "--wallet", validatorWallet, cmd := append(cmd, "--wallet", testcli.ValidatorWallet,
"--address", random.Uint160().StringLE(), "--address", random.Uint160().StringLE(),
h.StringLE(), "getValue") h.StringLE(), "getValue")
e.RunWithError(t, cmd...) e.RunWithError(t, cmd...)
}) })
t.Run("invalid password", func(t *testing.T) { t.Run("invalid password", func(t *testing.T) {
e.In.WriteString("invalid_password\r") e.In.WriteString("invalid_password\r")
cmd := append(cmd, "--wallet", validatorWallet, cmd := append(cmd, "--wallet", testcli.ValidatorWallet,
h.StringLE(), "getValue") h.StringLE(), "getValue")
e.RunWithError(t, cmd...) e.RunWithError(t, cmd...)
}) })
t.Run("good: default address", func(t *testing.T) { t.Run("good: default address", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.In.WriteString("y\r") e.In.WriteString("y\r")
e.Run(t, append(cmd, "--wallet", validatorWallet, h.StringLE(), "getValue")...) e.Run(t, append(cmd, "--wallet", testcli.ValidatorWallet, h.StringLE(), "getValue")...)
}) })
t.Run("good: from wallet config", func(t *testing.T) { t.Run("good: from wallet config", func(t *testing.T) {
e.In.WriteString("y\r") e.In.WriteString("y\r")
e.Run(t, append(cmd, "--wallet-config", configPath, h.StringLE(), "getValue")...) e.Run(t, append(cmd, "--wallet-config", configPath, h.StringLE(), "getValue")...)
}) })
cmd = append(cmd, "--wallet", validatorWallet, "--address", validatorAddr) cmd = append(cmd, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr)
t.Run("cancelled", func(t *testing.T) { t.Run("cancelled", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.In.WriteString("n\r") e.In.WriteString("n\r")
@ -792,7 +770,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.In.WriteString("y\r") e.In.WriteString("y\r")
e.Run(t, append(cmd, h.StringLE(), "getValue", e.Run(t, append(cmd, h.StringLE(), "getValue",
"--", validatorAddr, hVerify.StringLE())...) "--", testcli.ValidatorAddr, hVerify.StringLE())...)
}) })
}) })
@ -802,7 +780,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
cmd = []string{"neo-go", "contract", "invokefunction", cmd = []string{"neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--out", txout, "--out", txout,
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
} }
t.Run("without cosigner", func(t *testing.T) { t.Run("without cosigner", func(t *testing.T) {
@ -813,15 +791,15 @@ func TestComlileAndInvokeFunction(t *testing.T) {
t.Run("with cosigner", func(t *testing.T) { t.Run("with cosigner", func(t *testing.T) {
t.Run("cosigner is sender (none)", func(t *testing.T) { t.Run("cosigner is sender (none)", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.RunWithError(t, append(cmd, h.StringLE(), "checkSenderWitness", "--", validatorAddr+":None")...) e.RunWithError(t, append(cmd, h.StringLE(), "checkSenderWitness", "--", testcli.ValidatorAddr+":None")...)
}) })
t.Run("cosigner is sender (customcontract)", func(t *testing.T) { t.Run("cosigner is sender (customcontract)", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, append(cmd, h.StringLE(), "checkSenderWitness", "--", validatorAddr+":CustomContracts:"+h.StringLE())...) e.Run(t, append(cmd, h.StringLE(), "checkSenderWitness", "--", testcli.ValidatorAddr+":CustomContracts:"+h.StringLE())...)
}) })
t.Run("cosigner is sender (global)", func(t *testing.T) { t.Run("cosigner is sender (global)", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, append(cmd, h.StringLE(), "checkSenderWitness", "--", validatorAddr+":Global")...) e.Run(t, append(cmd, h.StringLE(), "checkSenderWitness", "--", testcli.ValidatorAddr+":Global")...)
}) })
acc, err := wallet.NewAccount() acc, err := wallet.NewAccount()
@ -839,7 +817,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
t.Run("good", func(t *testing.T) { t.Run("good", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, append(cmd, hVerify.StringLE(), "verify", "--", multisigAddr)...) e.Run(t, append(cmd, hVerify.StringLE(), "verify", "--", testcli.MultisigAddr)...)
}) })
}) })
@ -924,13 +902,13 @@ func TestComlileAndInvokeFunction(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "invokefunction", e.Run(t, "neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--force", "--force",
h.StringLE(), "update", h.StringLE(), "update",
"bytes:"+hex.EncodeToString(rawNef), "bytes:"+hex.EncodeToString(rawNef),
"bytes:"+hex.EncodeToString(rawManifest), "bytes:"+hex.EncodeToString(rawManifest),
) )
e.checkTxPersisted(t, "Sent invocation transaction ") e.CheckTxPersisted(t, "Sent invocation transaction ")
indexAfterUpdate = e.Chain.BlockHeight() indexAfterUpdate = e.Chain.BlockHeight()
e.In.WriteString("one\r") e.In.WriteString("one\r")
@ -970,7 +948,7 @@ func TestComlileAndInvokeFunction(t *testing.T) {
} }
func TestContractInspect(t *testing.T) { func TestContractInspect(t *testing.T) {
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
// For proper nef generation. // For proper nef generation.
config.Version = "0.90.0-test" config.Version = "0.90.0-test"
@ -1004,14 +982,14 @@ func TestContractInspect(t *testing.T) {
func TestCompileExamples(t *testing.T) { func TestCompileExamples(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
const examplePath = "../examples" const examplePath = "../../examples"
infos, err := os.ReadDir(examplePath) infos, err := os.ReadDir(examplePath)
require.NoError(t, err) require.NoError(t, err)
// For proper nef generation. // For proper nef generation.
config.Version = "0.90.0-test" config.Version = "0.90.0-test"
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
for _, info := range infos { for _, info := range infos {
if !info.IsDir() { if !info.IsDir() {

View file

@ -1,7 +1,7 @@
package deploy package deploy
import ( import (
"github.com/nspcc-dev/neo-go/cli/testdata/deploy/sub" "github.com/nspcc-dev/neo-go/cli/smartcontract/testdata/deploy/sub"
"github.com/nspcc-dev/neo-go/pkg/interop" "github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/contract"
"github.com/nspcc-dev/neo-go/pkg/interop/iterator" "github.com/nspcc-dev/neo-go/pkg/interop/iterator"

26
cli/util/util_test.go Normal file
View file

@ -0,0 +1,26 @@
package util_test
import (
"testing"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/util"
)
func TestUtilConvert(t *testing.T) {
e := testcli.NewExecutor(t, false)
e.Run(t, "neo-go", "util", "convert", util.Uint160{1, 2, 3}.StringLE())
e.CheckNextLine(t, "f975") // int to hex
e.CheckNextLine(t, "\\+XU=") // int to base64
e.CheckNextLine(t, "NKuyBkoGdZZSLyPbJEetheRhMrGSCQx7YL") // BE to address
e.CheckNextLine(t, "NL1JGiyJXdTkvFksXbFxgLJcWLj8Ewe7HW") // LE to address
e.CheckNextLine(t, "Hex to String") // hex to string
e.CheckNextLine(t, "5753853598078696051256155186041784866529345536") // hex to int
e.CheckNextLine(t, "0102030000000000000000000000000000000000") // swap endianness
e.CheckNextLine(t, "Base64 to String") // base64 to string
e.CheckNextLine(t, "368753434210909009569191652203865891677393101439813372294890211308228051") // base64 to bigint
e.CheckNextLine(t, "30303030303030303030303030303030303030303030303030303030303030303030303330323031") // string to hex
e.CheckNextLine(t, "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzMDIwMQ==") // string to base64
e.CheckEOF(t)
}

View file

@ -1,25 +0,0 @@
package main
import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/util"
)
func TestUtilConvert(t *testing.T) {
e := newExecutor(t, false)
e.Run(t, "neo-go", "util", "convert", util.Uint160{1, 2, 3}.StringLE())
e.checkNextLine(t, "f975") // int to hex
e.checkNextLine(t, "\\+XU=") // int to base64
e.checkNextLine(t, "NKuyBkoGdZZSLyPbJEetheRhMrGSCQx7YL") // BE to address
e.checkNextLine(t, "NL1JGiyJXdTkvFksXbFxgLJcWLj8Ewe7HW") // LE to address
e.checkNextLine(t, "Hex to String") // hex to string
e.checkNextLine(t, "5753853598078696051256155186041784866529345536") // hex to int
e.checkNextLine(t, "0102030000000000000000000000000000000000") // swap endianness
e.checkNextLine(t, "Base64 to String") // base64 to string
e.checkNextLine(t, "368753434210909009569191652203865891677393101439813372294890211308228051") // base64 to bigint
e.checkNextLine(t, "30303030303030303030303030303030303030303030303030303030303030303030303330323031") // string to hex
e.checkNextLine(t, "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzMDIwMQ==") // string to base64
e.checkEOF(t)
}

View file

@ -1,4 +1,4 @@
package main package wallet_test
import ( import (
"encoding/hex" "encoding/hex"
@ -6,6 +6,7 @@ import (
"strconv" "strconv"
"testing" "testing"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -13,135 +14,137 @@ import (
// We don't create a new account here, because chain will // We don't create a new account here, because chain will
// stop working after validator will change. // stop working after validator will change.
func TestRegisterCandidate(t *testing.T) { func TestRegisterCandidate(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
validatorHex := hex.EncodeToString(validatorPriv.PublicKey().Bytes()) validatorAddress := testcli.ValidatorPriv.Address()
validatorPublic := testcli.ValidatorPriv.PublicKey()
validatorHex := hex.EncodeToString(validatorPublic.Bytes())
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer", e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
"NEO:"+validatorPriv.Address()+":10", "NEO:"+validatorAddress+":10",
"GAS:"+validatorPriv.Address()+":10000") "GAS:"+validatorAddress+":10000")
e.checkTxPersisted(t) e.CheckTxPersisted(t)
e.Run(t, "neo-go", "query", "committee", e.Run(t, "neo-go", "query", "committee",
"--rpc-endpoint", "http://"+e.RPC.Addr) "--rpc-endpoint", "http://"+e.RPC.Addr)
e.checkNextLine(t, "^\\s*"+validatorHex) e.CheckNextLine(t, "^\\s*"+validatorHex)
e.Run(t, "neo-go", "query", "candidates", e.Run(t, "neo-go", "query", "candidates",
"--rpc-endpoint", "http://"+e.RPC.Addr) "--rpc-endpoint", "http://"+e.RPC.Addr)
e.checkNextLine(t, "^\\s*Key.+$") // Header. e.CheckNextLine(t, "^\\s*Key.+$") // Header.
e.checkEOF(t) e.CheckEOF(t)
// missing address // missing address
e.RunWithError(t, "neo-go", "wallet", "candidate", "register", e.RunWithError(t, "neo-go", "wallet", "candidate", "register",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet) "--wallet", testcli.ValidatorWallet)
// additional parameter // additional parameter
e.RunWithError(t, "neo-go", "wallet", "candidate", "register", e.RunWithError(t, "neo-go", "wallet", "candidate", "register",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorPriv.Address(), "--address", validatorAddress,
"error") "error")
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "register", e.Run(t, "neo-go", "wallet", "candidate", "register",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorPriv.Address()) "--address", validatorAddress)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
vs, err := e.Chain.GetEnrollments() vs, err := e.Chain.GetEnrollments()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(vs)) require.Equal(t, 1, len(vs))
require.Equal(t, validatorPriv.PublicKey(), vs[0].Key) require.Equal(t, validatorPublic, vs[0].Key)
require.Equal(t, big.NewInt(0), vs[0].Votes) require.Equal(t, big.NewInt(0), vs[0].Votes)
t.Run("VoteUnvote", func(t *testing.T) { t.Run("VoteUnvote", func(t *testing.T) {
// positional instead of a flag. // positional instead of a flag.
e.RunWithError(t, "neo-go", "wallet", "candidate", "vote", e.RunWithError(t, "neo-go", "wallet", "candidate", "vote",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorPriv.Address(), "--address", validatorAddress,
validatorHex) // not "--candidate hex", but "hex". validatorHex) // not "--candidate hex", but "hex".
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "vote", e.Run(t, "neo-go", "wallet", "candidate", "vote",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorPriv.Address(), "--address", validatorAddress,
"--candidate", validatorHex) "--candidate", validatorHex)
_, index := e.checkTxPersisted(t) _, index := e.CheckTxPersisted(t)
vs, err = e.Chain.GetEnrollments() vs, err = e.Chain.GetEnrollments()
require.Equal(t, 1, len(vs)) require.Equal(t, 1, len(vs))
require.Equal(t, validatorPriv.PublicKey(), vs[0].Key) require.Equal(t, validatorPublic, vs[0].Key)
b, _ := e.Chain.GetGoverningTokenBalance(validatorPriv.GetScriptHash()) b, _ := e.Chain.GetGoverningTokenBalance(testcli.ValidatorPriv.GetScriptHash())
require.Equal(t, b, vs[0].Votes) require.Equal(t, b, vs[0].Votes)
e.Run(t, "neo-go", "query", "committee", e.Run(t, "neo-go", "query", "committee",
"--rpc-endpoint", "http://"+e.RPC.Addr) "--rpc-endpoint", "http://"+e.RPC.Addr)
e.checkNextLine(t, "^\\s*"+validatorHex) e.CheckNextLine(t, "^\\s*"+validatorHex)
e.Run(t, "neo-go", "query", "candidates", e.Run(t, "neo-go", "query", "candidates",
"--rpc-endpoint", "http://"+e.RPC.Addr) "--rpc-endpoint", "http://"+e.RPC.Addr)
e.checkNextLine(t, "^\\s*Key.+$") // Header. e.CheckNextLine(t, "^\\s*Key.+$") // Header.
e.checkNextLine(t, "^\\s*"+validatorHex+"\\s*"+b.String()+"\\s*true\\s*true$") e.CheckNextLine(t, "^\\s*"+validatorHex+"\\s*"+b.String()+"\\s*true\\s*true$")
e.checkEOF(t) e.CheckEOF(t)
// check state // check state
e.Run(t, "neo-go", "query", "voter", e.Run(t, "neo-go", "query", "voter",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
validatorPriv.Address()) validatorAddress)
e.checkNextLine(t, "^\\s*Voted:\\s+"+validatorHex+"\\s+\\("+validatorPriv.Address()+"\\)$") e.CheckNextLine(t, "^\\s*Voted:\\s+"+validatorHex+"\\s+\\("+validatorAddress+"\\)$")
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$") e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$")
e.checkNextLine(t, "^\\s*Block\\s*:\\s*"+strconv.FormatUint(uint64(index), 10)) e.CheckNextLine(t, "^\\s*Block\\s*:\\s*"+strconv.FormatUint(uint64(index), 10))
e.checkEOF(t) e.CheckEOF(t)
// unvote // unvote
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "vote", e.Run(t, "neo-go", "wallet", "candidate", "vote",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorPriv.Address()) "--address", validatorAddress)
_, index = e.checkTxPersisted(t) _, index = e.CheckTxPersisted(t)
vs, err = e.Chain.GetEnrollments() vs, err = e.Chain.GetEnrollments()
require.Equal(t, 1, len(vs)) require.Equal(t, 1, len(vs))
require.Equal(t, validatorPriv.PublicKey(), vs[0].Key) require.Equal(t, validatorPublic, vs[0].Key)
require.Equal(t, big.NewInt(0), vs[0].Votes) require.Equal(t, big.NewInt(0), vs[0].Votes)
// check state // check state
e.Run(t, "neo-go", "query", "voter", e.Run(t, "neo-go", "query", "voter",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
validatorPriv.Address()) validatorAddress)
e.checkNextLine(t, "^\\s*Voted:\\s+"+"null") // no vote. e.CheckNextLine(t, "^\\s*Voted:\\s+"+"null") // no vote.
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$") e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$")
e.checkNextLine(t, "^\\s*Block\\s*:\\s*"+strconv.FormatUint(uint64(index), 10)) e.CheckNextLine(t, "^\\s*Block\\s*:\\s*"+strconv.FormatUint(uint64(index), 10))
e.checkEOF(t) e.CheckEOF(t)
}) })
// missing address // missing address
e.RunWithError(t, "neo-go", "wallet", "candidate", "unregister", e.RunWithError(t, "neo-go", "wallet", "candidate", "unregister",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet) "--wallet", testcli.ValidatorWallet)
// additional argument // additional argument
e.RunWithError(t, "neo-go", "wallet", "candidate", "unregister", e.RunWithError(t, "neo-go", "wallet", "candidate", "unregister",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorPriv.Address(), "--address", validatorAddress,
"argument") "argument")
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "candidate", "unregister", e.Run(t, "neo-go", "wallet", "candidate", "unregister",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--address", validatorPriv.Address()) "--address", validatorAddress)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
vs, err = e.Chain.GetEnrollments() vs, err = e.Chain.GetEnrollments()
require.Equal(t, 0, len(vs)) require.Equal(t, 0, len(vs))
@ -149,7 +152,7 @@ func TestRegisterCandidate(t *testing.T) {
// query voter: missing address // query voter: missing address
e.RunWithError(t, "neo-go", "query", "voter") e.RunWithError(t, "neo-go", "query", "voter")
// Excessive parameters. // Excessive parameters.
e.RunWithError(t, "neo-go", "query", "voter", "--rpc-endpoint", "http://"+e.RPC.Addr, validatorPriv.Address(), validatorPriv.Address()) e.RunWithError(t, "neo-go", "query", "voter", "--rpc-endpoint", "http://"+e.RPC.Addr, validatorAddress, validatorAddress)
e.RunWithError(t, "neo-go", "query", "committee", "--rpc-endpoint", "http://"+e.RPC.Addr, "something") e.RunWithError(t, "neo-go", "query", "committee", "--rpc-endpoint", "http://"+e.RPC.Addr, "something")
e.RunWithError(t, "neo-go", "query", "candidates", "--rpc-endpoint", "http://"+e.RPC.Addr, "something") e.RunWithError(t, "neo-go", "query", "candidates", "--rpc-endpoint", "http://"+e.RPC.Addr, "something")
} }

View file

@ -1,4 +1,4 @@
package main package wallet_test
import ( import (
"encoding/hex" "encoding/hex"
@ -9,6 +9,7 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
@ -24,9 +25,9 @@ import (
// 1. Transfer funds to a created multisig address. // 1. Transfer funds to a created multisig address.
// 2. Transfer from multisig to another account. // 2. Transfer from multisig to another account.
func TestSignMultisigTx(t *testing.T) { func TestSignMultisigTx(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
privs, pubs := generateKeys(t, 3) privs, pubs := testcli.GenerateKeys(t, 3)
script, err := smartcontract.CreateMultiSigRedeemScript(2, pubs) script, err := smartcontract.CreateMultiSigRedeemScript(2, pubs)
require.NoError(t, err) require.NoError(t, err)
multisigHash := hash.Hash160(script) multisigHash := hash.Hash160(script)
@ -55,12 +56,12 @@ func TestSignMultisigTx(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer", e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
"NEO:"+multisigAddr+":4", "NEO:"+multisigAddr+":4",
"GAS:"+multisigAddr+":1") "GAS:"+multisigAddr+":1")
e.checkTxPersisted(t) e.CheckTxPersisted(t)
// Sign and transfer funds to another account. // Sign and transfer funds to another account.
priv, err := keys.NewPrivateKey() priv, err := keys.NewPrivateKey()
@ -145,8 +146,8 @@ func TestSignMultisigTx(t *testing.T) {
t.Run("no invoke", func(t *testing.T) { t.Run("no invoke", func(t *testing.T) {
e.Run(t, "neo-go", "util", "txdump", txPath) e.Run(t, "neo-go", "util", "txdump", txPath)
e.checkTxTestInvokeOutput(t, 11) e.CheckTxTestInvokeOutput(t, 11)
e.checkEOF(t) e.CheckEOF(t)
}) })
t.Run("excessive parameters", func(t *testing.T) { t.Run("excessive parameters", func(t *testing.T) {
@ -157,7 +158,7 @@ func TestSignMultisigTx(t *testing.T) {
e.Run(t, "neo-go", "util", "txdump", e.Run(t, "neo-go", "util", "txdump",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
txPath) txPath)
e.checkTxTestInvokeOutput(t, 11) e.CheckTxTestInvokeOutput(t, 11)
res := new(result.Invoke) res := new(result.Invoke)
require.NoError(t, json.Unmarshal(e.Out.Bytes(), res)) require.NoError(t, json.Unmarshal(e.Out.Bytes(), res))
require.Equal(t, vmstate.Halt.String(), res.State, res.FaultException) require.Equal(t, vmstate.Halt.String(), res.State, res.FaultException)
@ -196,7 +197,7 @@ func TestSignMultisigTx(t *testing.T) {
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", wallet2Path, "--address", multisigAddr, "--wallet", wallet2Path, "--address", multisigAddr,
"--in", txPath, "--out", txPath) "--in", txPath, "--out", txPath)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
}) })
t.Run("double-sign", func(t *testing.T) { t.Run("double-sign", func(t *testing.T) {
e.In.WriteString("pass\r") e.In.WriteString("pass\r")
@ -251,7 +252,7 @@ func TestSignMultisigTx(t *testing.T) {
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", wallet1Path, "--address", address.Uint160ToString(h), "--wallet", wallet1Path, "--address", address.Uint160ToString(h),
"--in", txPath, "--out", txPath) "--in", txPath, "--out", txPath)
tx, _ := e.checkTxPersisted(t) tx, _ := e.CheckTxPersisted(t)
require.Equal(t, 3, len(tx.Signers)) require.Equal(t, 3, len(tx.Signers))
b, _ := e.Chain.GetGoverningTokenBalance(priv.GetScriptHash()) b, _ := e.Chain.GetGoverningTokenBalance(priv.GetScriptHash())
@ -261,20 +262,6 @@ func TestSignMultisigTx(t *testing.T) {
}) })
} }
func (e *executor) checkTxTestInvokeOutput(t *testing.T, scriptSize int) { func deployVerifyContract(t *testing.T, e *testcli.Executor) util.Uint160 {
e.checkNextLine(t, `Hash:\s+`) return testcli.DeployContract(t, e, "../smartcontract/testdata/verify.go", "../smartcontract/testdata/verify.yml", testcli.ValidatorWallet, testcli.ValidatorAddr, testcli.ValidatorPass)
e.checkNextLine(t, `OnChain:\s+false`)
e.checkNextLine(t, `ValidUntil:\s+\d+`)
e.checkNextLine(t, `Signer:\s+\w+`)
e.checkNextLine(t, `SystemFee:\s+(\d|\.)+`)
e.checkNextLine(t, `NetworkFee:\s+(\d|\.)+`)
e.checkNextLine(t, `Script:\s+\w+`)
e.checkScriptDump(t, scriptSize)
}
func (e *executor) checkScriptDump(t *testing.T, scriptSize int) {
e.checkNextLine(t, `INDEX\s+`)
for i := 0; i < scriptSize; i++ {
e.checkNextLine(t, `\d+\s+\w+`)
}
} }

View file

@ -1,4 +1,4 @@
package main package wallet_test
import ( import (
"bytes" "bytes"
@ -13,6 +13,7 @@ import (
"strconv" "strconv"
"testing" "testing"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
@ -26,12 +27,12 @@ import (
const ( const (
// nftOwnerAddr is the owner of NFT-ND HASHY token (../examples/nft-nd/nft.go). // nftOwnerAddr is the owner of NFT-ND HASHY token (../examples/nft-nd/nft.go).
nftOwnerAddr = "NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB" nftOwnerAddr = "NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB"
nftOwnerWallet = "../examples/my_wallet.json" nftOwnerWallet = "../../examples/my_wallet.json"
nftOwnerPass = "qwerty" nftOwnerPass = "qwerty"
) )
func TestNEP11Import(t *testing.T) { func TestNEP11Import(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
tmpDir := t.TempDir() tmpDir := t.TempDir()
walletPath := filepath.Join(tmpDir, "walletForImport.json") walletPath := filepath.Join(tmpDir, "walletForImport.json")
@ -68,12 +69,12 @@ func TestNEP11Import(t *testing.T) {
e.RunWithError(t, append(args, "--token", neoContractHash.StringLE())...) e.RunWithError(t, append(args, "--token", neoContractHash.StringLE())...)
checkInfo := func(t *testing.T, h util.Uint160, name string, symbol string, decimals int) { checkInfo := func(t *testing.T, h util.Uint160, name string, symbol string, decimals int) {
e.checkNextLine(t, "^Name:\\s*"+name) e.CheckNextLine(t, "^Name:\\s*"+name)
e.checkNextLine(t, "^Symbol:\\s*"+symbol) e.CheckNextLine(t, "^Symbol:\\s*"+symbol)
e.checkNextLine(t, "^Hash:\\s*"+h.StringLE()) e.CheckNextLine(t, "^Hash:\\s*"+h.StringLE())
e.checkNextLine(t, "^Decimals:\\s*"+strconv.Itoa(decimals)) e.CheckNextLine(t, "^Decimals:\\s*"+strconv.Itoa(decimals))
e.checkNextLine(t, "^Address:\\s*"+address.Uint160ToString(h)) e.CheckNextLine(t, "^Address:\\s*"+address.Uint160ToString(h))
e.checkNextLine(t, "^Standard:\\s*"+string(manifest.NEP11StandardName)) e.CheckNextLine(t, "^Standard:\\s*"+string(manifest.NEP11StandardName))
} }
t.Run("Info", func(t *testing.T) { t.Run("Info", func(t *testing.T) {
t.Run("excessive parameters", func(t *testing.T) { t.Run("excessive parameters", func(t *testing.T) {
@ -89,7 +90,7 @@ func TestNEP11Import(t *testing.T) {
e.Run(t, "neo-go", "wallet", "nep11", "info", e.Run(t, "neo-go", "wallet", "nep11", "info",
"--wallet", walletPath) "--wallet", walletPath)
checkInfo(t, nnsContractHash, "NameService", "NNS", 0) checkInfo(t, nnsContractHash, "NameService", "NNS", 0)
e.checkNextLine(t, "") e.CheckNextLine(t, "")
checkInfo(t, nfsContractHash, "NeoFS Object NFT", "NFSO", 2) checkInfo(t, nfsContractHash, "NeoFS Object NFT", "NFSO", 2)
}) })
}) })
@ -109,7 +110,7 @@ func TestNEP11Import(t *testing.T) {
} }
func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) { func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
tmpDir := t.TempDir() tmpDir := t.TempDir()
// copy wallet to temp dir in order not to overwrite the original file // copy wallet to temp dir in order not to overwrite the original file
@ -123,13 +124,13 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "transfer", e.Run(t, "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--to", nftOwnerAddr, "--to", nftOwnerAddr,
"--token", "GAS", "--token", "GAS",
"--amount", "10000", "--amount", "10000",
"--force", "--force",
"--from", validatorAddr) "--from", testcli.ValidatorAddr)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
// deploy NFT HASHY contract // deploy NFT HASHY contract
h := deployNFTContract(t, e) h := deployNFTContract(t, e)
@ -145,7 +146,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
"--amount", "10", "--amount", "10",
"--force", "--force",
"--from", nftOwnerAddr) "--from", nftOwnerAddr)
txMint, _ := e.checkTxPersisted(t) txMint, _ := e.CheckTxPersisted(t)
// get NFT ID from AER // get NFT ID from AER
aer, err := e.Chain.GetAppExecResults(txMint.Hash(), trigger.Application) aer, err := e.Chain.GetAppExecResults(txMint.Hash(), trigger.Application)
@ -169,8 +170,8 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
"--wallet", wall, "--wallet", wall,
"--address", nftOwnerAddr} "--address", nftOwnerAddr}
checkBalanceResult := func(t *testing.T, acc string, ids ...[]byte) { checkBalanceResult := func(t *testing.T, acc string, ids ...[]byte) {
e.checkNextLine(t, "^\\s*Account\\s+"+acc) e.CheckNextLine(t, "^\\s*Account\\s+"+acc)
e.checkNextLine(t, "^\\s*HASHY:\\s+HASHY NFT \\("+h.StringLE()+"\\)") e.CheckNextLine(t, "^\\s*HASHY:\\s+HASHY NFT \\("+h.StringLE()+"\\)")
// Hashes can be ordered in any way, so make a regexp for them. // Hashes can be ordered in any way, so make a regexp for them.
var tokstring = "(" var tokstring = "("
@ -183,11 +184,11 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
tokstring += ")" tokstring += ")"
for range ids { for range ids {
e.checkNextLine(t, "^\\s*Token: "+tokstring+"\\s*$") e.CheckNextLine(t, "^\\s*Token: "+tokstring+"\\s*$")
e.checkNextLine(t, "^\\s*Amount: 1\\s*$") e.CheckNextLine(t, "^\\s*Amount: 1\\s*$")
e.checkNextLine(t, "^\\s*Updated: [0-9]+\\s*$") e.CheckNextLine(t, "^\\s*Updated: [0-9]+\\s*$")
} }
e.checkEOF(t) e.CheckEOF(t)
} }
// balance check: by symbol, token is not imported // balance check: by symbol, token is not imported
e.Run(t, append(cmdCheckBalance, "--token", "HASHY")...) e.Run(t, append(cmdCheckBalance, "--token", "HASHY")...)
@ -233,7 +234,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// ownerOf: good // ownerOf: good
e.Run(t, cmdOwnerOf...) e.Run(t, cmdOwnerOf...)
e.checkNextLine(t, nftOwnerAddr) e.CheckNextLine(t, nftOwnerAddr)
// tokensOf: missing contract hash // tokensOf: missing contract hash
cmdTokensOf := []string{"neo-go", "wallet", "nep11", "tokensOf", cmdTokensOf := []string{"neo-go", "wallet", "nep11", "tokensOf",
@ -248,7 +249,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// tokensOf: good // tokensOf: good
e.Run(t, cmdTokensOf...) e.Run(t, cmdTokensOf...)
require.Equal(t, hex.EncodeToString(tokenID), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(tokenID), e.GetNextLine(t))
// properties: no contract // properties: no contract
cmdProperties := []string{ cmdProperties := []string{
@ -264,7 +265,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// properties: ok // properties: ok
e.Run(t, cmdProperties...) e.Run(t, cmdProperties...)
require.Equal(t, fmt.Sprintf(`{"name":"HASHY %s"}`, base64.StdEncoding.EncodeToString(tokenID)), e.getNextLine(t)) require.Equal(t, fmt.Sprintf(`{"name":"HASHY %s"}`, base64.StdEncoding.EncodeToString(tokenID)), e.GetNextLine(t))
// tokensOf: good, several tokens // tokensOf: good, several tokens
tokenID1 := mint(t) tokenID1 := mint(t)
@ -274,8 +275,8 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
fst, snd = snd, fst fst, snd = snd, fst
} }
require.Equal(t, hex.EncodeToString(fst), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(fst), e.GetNextLine(t))
require.Equal(t, hex.EncodeToString(snd), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(snd), e.GetNextLine(t))
// tokens: missing contract hash // tokens: missing contract hash
cmdTokens := []string{"neo-go", "wallet", "nep11", "tokens", cmdTokens := []string{"neo-go", "wallet", "nep11", "tokens",
@ -288,8 +289,8 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
e.RunWithError(t, append(cmdTokens, "additional")...) e.RunWithError(t, append(cmdTokens, "additional")...)
// tokens: good, several tokens // tokens: good, several tokens
e.Run(t, cmdTokens...) e.Run(t, cmdTokens...)
require.Equal(t, hex.EncodeToString(fst), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(fst), e.GetNextLine(t))
require.Equal(t, hex.EncodeToString(snd), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(snd), e.GetNextLine(t))
// balance check: several tokens, ok // balance check: several tokens, ok
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...) e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
@ -299,7 +300,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
"neo-go", "wallet", "nep11", "transfer", "neo-go", "wallet", "nep11", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", wall, "--wallet", wall,
"--to", validatorAddr, "--to", testcli.ValidatorAddr,
"--from", nftOwnerAddr, "--from", nftOwnerAddr,
"--force", "--force",
} }
@ -317,7 +318,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// transfer: good // transfer: good
e.In.WriteString(nftOwnerPass + "\r") e.In.WriteString(nftOwnerPass + "\r")
e.Run(t, append(cmdTransfer, "--id", hex.EncodeToString(tokenID))...) e.Run(t, append(cmdTransfer, "--id", hex.EncodeToString(tokenID))...)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
// check balance after transfer // check balance after transfer
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...) e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
@ -338,7 +339,7 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
} }
e.In.WriteString(nftOwnerPass + "\r") e.In.WriteString(nftOwnerPass + "\r")
e.Run(t, cmdTransfer...) e.Run(t, cmdTransfer...)
tx, _ := e.checkTxPersisted(t) tx, _ := e.CheckTxPersisted(t)
// check OnNEP11Payment event // check OnNEP11Payment event
aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application) aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
require.NoError(t, err) require.NoError(t, err)
@ -363,28 +364,28 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// historic calls still remember the good old days. // historic calls still remember the good old days.
cmdOwnerOf = append(cmdOwnerOf, "--historic", hashBeforeTransfer.StringLE()) cmdOwnerOf = append(cmdOwnerOf, "--historic", hashBeforeTransfer.StringLE())
e.Run(t, cmdOwnerOf...) e.Run(t, cmdOwnerOf...)
e.checkNextLine(t, nftOwnerAddr) e.CheckNextLine(t, nftOwnerAddr)
cmdTokensOf = append(cmdTokensOf, "--historic", hashBeforeTransfer.StringLE()) cmdTokensOf = append(cmdTokensOf, "--historic", hashBeforeTransfer.StringLE())
e.Run(t, cmdTokensOf...) e.Run(t, cmdTokensOf...)
require.Equal(t, hex.EncodeToString(tokenID), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(tokenID), e.GetNextLine(t))
cmdTokens = append(cmdTokens, "--historic", hashBeforeTransfer.StringLE()) cmdTokens = append(cmdTokens, "--historic", hashBeforeTransfer.StringLE())
e.Run(t, cmdTokens...) e.Run(t, cmdTokens...)
require.Equal(t, hex.EncodeToString(tokenID), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(tokenID), e.GetNextLine(t))
// this one is not affected by transfer, but anyway // this one is not affected by transfer, but anyway
cmdProperties = append(cmdProperties, "--historic", hashBeforeTransfer.StringLE()) cmdProperties = append(cmdProperties, "--historic", hashBeforeTransfer.StringLE())
e.Run(t, cmdProperties...) e.Run(t, cmdProperties...)
require.Equal(t, fmt.Sprintf(`{"name":"HASHY %s"}`, base64.StdEncoding.EncodeToString(tokenID)), e.getNextLine(t)) require.Equal(t, fmt.Sprintf(`{"name":"HASHY %s"}`, base64.StdEncoding.EncodeToString(tokenID)), e.GetNextLine(t))
} }
func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) { func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
tmpDir := t.TempDir() tmpDir := t.TempDir()
// copy wallet to temp dir in order not to overwrite the original file // copy wallet to temp dir in order not to overwrite the original file
bytesRead, err := os.ReadFile(validatorWallet) bytesRead, err := os.ReadFile(testcli.ValidatorWallet)
require.NoError(t, err) require.NoError(t, err)
wall := filepath.Join(tmpDir, "my_wallet.json") wall := filepath.Join(tmpDir, "my_wallet.json")
err = os.WriteFile(wall, bytesRead, 0755) err = os.WriteFile(wall, bytesRead, 0755)
@ -395,7 +396,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
mint := func(t *testing.T, containerID, objectID util.Uint256) []byte { mint := func(t *testing.T, containerID, objectID util.Uint256) []byte {
// mint 1.00 NFSO token by transferring 10 GAS to NFSO contract // mint 1.00 NFSO token by transferring 10 GAS to NFSO contract
e.In.WriteString(validatorPass + "\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.Run(t, "neo-go", "wallet", "nep17", "transfer", e.Run(t, "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", wall, "--wallet", wall,
@ -403,10 +404,10 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
"--token", "GAS", "--token", "GAS",
"--amount", "10", "--amount", "10",
"--force", "--force",
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--", "[", "hash256:"+containerID.StringLE(), "hash256:"+objectID.StringLE(), "]", "--", "[", "hash256:"+containerID.StringLE(), "hash256:"+objectID.StringLE(), "]",
) )
txMint, _ := e.checkTxPersisted(t) txMint, _ := e.CheckTxPersisted(t)
// get NFT ID from AER // get NFT ID from AER
aer, err := e.Chain.GetAppExecResults(txMint.Hash(), trigger.Application) aer, err := e.Chain.GetAppExecResults(txMint.Hash(), trigger.Application)
@ -434,12 +435,12 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--token", h.StringLE(), "--token", h.StringLE(),
"--id", hex.EncodeToString(token1ID)) "--id", hex.EncodeToString(token1ID))
jProps := e.getNextLine(t) jProps := e.GetNextLine(t)
props := make(map[string]string) props := make(map[string]string)
require.NoError(t, json.Unmarshal([]byte(jProps), &props)) require.NoError(t, json.Unmarshal([]byte(jProps), &props))
require.Equal(t, base64.StdEncoding.EncodeToString(container1ID.BytesBE()), props["containerID"]) require.Equal(t, base64.StdEncoding.EncodeToString(container1ID.BytesBE()), props["containerID"])
require.Equal(t, base64.StdEncoding.EncodeToString(object1ID.BytesBE()), props["objectID"]) require.Equal(t, base64.StdEncoding.EncodeToString(object1ID.BytesBE()), props["objectID"])
e.checkEOF(t) e.CheckEOF(t)
type idAmount struct { type idAmount struct {
id string id string
@ -450,17 +451,17 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
cmdCheckBalance := []string{"neo-go", "wallet", "nep11", "balance", cmdCheckBalance := []string{"neo-go", "wallet", "nep11", "balance",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", wall, "--wallet", wall,
"--address", validatorAddr} "--address", testcli.ValidatorAddr}
checkBalanceResult := func(t *testing.T, acc string, objs ...idAmount) { checkBalanceResult := func(t *testing.T, acc string, objs ...idAmount) {
e.checkNextLine(t, "^\\s*Account\\s+"+acc) e.CheckNextLine(t, "^\\s*Account\\s+"+acc)
e.checkNextLine(t, "^\\s*NFSO:\\s+NeoFS Object NFT \\("+h.StringLE()+"\\)") e.CheckNextLine(t, "^\\s*NFSO:\\s+NeoFS Object NFT \\("+h.StringLE()+"\\)")
for _, o := range objs { for _, o := range objs {
e.checkNextLine(t, "^\\s*Token: "+o.id+"\\s*$") e.CheckNextLine(t, "^\\s*Token: "+o.id+"\\s*$")
e.checkNextLine(t, "^\\s*Amount: "+o.amount+"\\s*$") e.CheckNextLine(t, "^\\s*Amount: "+o.amount+"\\s*$")
e.checkNextLine(t, "^\\s*Updated: [0-9]+\\s*$") e.CheckNextLine(t, "^\\s*Updated: [0-9]+\\s*$")
} }
e.checkEOF(t) e.CheckEOF(t)
} }
tokz := []idAmount{ tokz := []idAmount{
{hex.EncodeToString(token1ID), "1"}, {hex.EncodeToString(token1ID), "1"},
@ -468,15 +469,15 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
} }
// balance check: by symbol, token is not imported // balance check: by symbol, token is not imported
e.Run(t, append(cmdCheckBalance, "--token", "NFSO")...) e.Run(t, append(cmdCheckBalance, "--token", "NFSO")...)
checkBalanceResult(t, validatorAddr, tokz...) checkBalanceResult(t, testcli.ValidatorAddr, tokz...)
// overall NFSO balance check: by hash, ok // overall NFSO balance check: by hash, ok
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...) e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
checkBalanceResult(t, validatorAddr, tokz...) checkBalanceResult(t, testcli.ValidatorAddr, tokz...)
// particular NFSO balance check: by hash, ok // particular NFSO balance check: by hash, ok
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE(), "--id", hex.EncodeToString(token2ID))...) e.Run(t, append(cmdCheckBalance, "--token", h.StringLE(), "--id", hex.EncodeToString(token2ID))...)
checkBalanceResult(t, validatorAddr, tokz[1]) checkBalanceResult(t, testcli.ValidatorAddr, tokz[1])
// import token // import token
e.Run(t, "neo-go", "wallet", "nep11", "import", e.Run(t, "neo-go", "wallet", "nep11", "import",
@ -486,11 +487,11 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// overall balance check: by symbol, ok // overall balance check: by symbol, ok
e.Run(t, append(cmdCheckBalance, "--token", "NFSO")...) e.Run(t, append(cmdCheckBalance, "--token", "NFSO")...)
checkBalanceResult(t, validatorAddr, tokz...) checkBalanceResult(t, testcli.ValidatorAddr, tokz...)
// particular balance check: by symbol, ok // particular balance check: by symbol, ok
e.Run(t, append(cmdCheckBalance, "--token", "NFSO", "--id", hex.EncodeToString(token1ID))...) e.Run(t, append(cmdCheckBalance, "--token", "NFSO", "--id", hex.EncodeToString(token1ID))...)
checkBalanceResult(t, validatorAddr, tokz[0]) checkBalanceResult(t, testcli.ValidatorAddr, tokz[0])
// remove token from wallet // remove token from wallet
e.In.WriteString("y\r") e.In.WriteString("y\r")
@ -510,7 +511,7 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// ownerOfD: good // ownerOfD: good
e.Run(t, cmdOwnerOf...) e.Run(t, cmdOwnerOf...)
e.checkNextLine(t, validatorAddr) e.CheckNextLine(t, testcli.ValidatorAddr)
// tokensOf: missing contract hash // tokensOf: missing contract hash
cmdTokensOf := []string{"neo-go", "wallet", "nep11", "tokensOf", cmdTokensOf := []string{"neo-go", "wallet", "nep11", "tokensOf",
@ -521,13 +522,13 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// tokensOf: missing owner address // tokensOf: missing owner address
e.RunWithError(t, cmdTokensOf...) e.RunWithError(t, cmdTokensOf...)
cmdTokensOf = append(cmdTokensOf, "--address", validatorAddr) cmdTokensOf = append(cmdTokensOf, "--address", testcli.ValidatorAddr)
// tokensOf: good // tokensOf: good
e.Run(t, cmdTokensOf...) e.Run(t, cmdTokensOf...)
require.Equal(t, hex.EncodeToString(token1ID), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(token1ID), e.GetNextLine(t))
require.Equal(t, hex.EncodeToString(token2ID), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(token2ID), e.GetNextLine(t))
e.checkEOF(t) e.CheckEOF(t)
// properties: no contract // properties: no contract
cmdProperties := []string{ cmdProperties := []string{
@ -546,12 +547,12 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// properties: ok // properties: ok
e.Run(t, cmdProperties...) e.Run(t, cmdProperties...)
jProps = e.getNextLine(t) jProps = e.GetNextLine(t)
props = make(map[string]string) props = make(map[string]string)
require.NoError(t, json.Unmarshal([]byte(jProps), &props)) require.NoError(t, json.Unmarshal([]byte(jProps), &props))
require.Equal(t, base64.StdEncoding.EncodeToString(container2ID.BytesBE()), props["containerID"]) require.Equal(t, base64.StdEncoding.EncodeToString(container2ID.BytesBE()), props["containerID"])
require.Equal(t, base64.StdEncoding.EncodeToString(object2ID.BytesBE()), props["objectID"]) require.Equal(t, base64.StdEncoding.EncodeToString(object2ID.BytesBE()), props["objectID"])
e.checkEOF(t) e.CheckEOF(t)
// tokensOf: good, several tokens // tokensOf: good, several tokens
e.Run(t, cmdTokensOf...) e.Run(t, cmdTokensOf...)
@ -560,8 +561,8 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
fst, snd = snd, fst fst, snd = snd, fst
} }
require.Equal(t, hex.EncodeToString(fst), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(fst), e.GetNextLine(t))
require.Equal(t, hex.EncodeToString(snd), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(snd), e.GetNextLine(t))
// tokens: missing contract hash // tokens: missing contract hash
cmdTokens := []string{"neo-go", "wallet", "nep11", "tokens", cmdTokens := []string{"neo-go", "wallet", "nep11", "tokens",
@ -572,40 +573,40 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// tokens: good, several tokens // tokens: good, several tokens
e.Run(t, cmdTokens...) e.Run(t, cmdTokens...)
require.Equal(t, hex.EncodeToString(fst), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(fst), e.GetNextLine(t))
require.Equal(t, hex.EncodeToString(snd), e.getNextLine(t)) require.Equal(t, hex.EncodeToString(snd), e.GetNextLine(t))
// balance check: several tokens, ok // balance check: several tokens, ok
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...) e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
checkBalanceResult(t, validatorAddr, tokz...) checkBalanceResult(t, testcli.ValidatorAddr, tokz...)
cmdTransfer := []string{ cmdTransfer := []string{
"neo-go", "wallet", "nep11", "transfer", "neo-go", "wallet", "nep11", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", wall, "--wallet", wall,
"--to", nftOwnerAddr, "--to", nftOwnerAddr,
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
} }
// transfer: unimported token with symbol id specified // transfer: unimported token with symbol id specified
e.In.WriteString(validatorPass + "\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.RunWithError(t, append(cmdTransfer, e.RunWithError(t, append(cmdTransfer,
"--token", "NFSO")...) "--token", "NFSO")...)
cmdTransfer = append(cmdTransfer, "--token", h.StringLE()) cmdTransfer = append(cmdTransfer, "--token", h.StringLE())
// transfer: no id specified // transfer: no id specified
e.In.WriteString(validatorPass + "\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.RunWithError(t, cmdTransfer...) e.RunWithError(t, cmdTransfer...)
// transfer: good // transfer: good
e.In.WriteString(validatorPass + "\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.Run(t, append(cmdTransfer, "--id", hex.EncodeToString(token1ID))...) e.Run(t, append(cmdTransfer, "--id", hex.EncodeToString(token1ID))...)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
// check balance after transfer // check balance after transfer
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...) e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
checkBalanceResult(t, validatorAddr, tokz[1]) // only token2ID expected to be on the balance checkBalanceResult(t, testcli.ValidatorAddr, tokz[1]) // only token2ID expected to be on the balance
// transfer: good, 1/4 of the balance, to NEP-11-Payable contract, with data // transfer: good, 1/4 of the balance, to NEP-11-Payable contract, with data
verifyH := deployVerifyContract(t, e) verifyH := deployVerifyContract(t, e)
@ -614,21 +615,21 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", wall, "--wallet", wall,
"--to", verifyH.StringLE(), "--to", verifyH.StringLE(),
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--token", h.StringLE(), "--token", h.StringLE(),
"--id", hex.EncodeToString(token2ID), "--id", hex.EncodeToString(token2ID),
"--amount", "0.25", "--amount", "0.25",
"--force", "--force",
"string:some_data", "string:some_data",
} }
e.In.WriteString(validatorPass + "\r") e.In.WriteString(testcli.ValidatorPass + "\r")
e.Run(t, cmdTransfer...) e.Run(t, cmdTransfer...)
tx, _ := e.checkTxPersisted(t) tx, _ := e.CheckTxPersisted(t)
// check OnNEP11Payment event // check OnNEP11Payment event
aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application) aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(aer[0].Events)) require.Equal(t, 2, len(aer[0].Events))
validatorHash, err := address.StringToUint160(validatorAddr) validatorHash, err := address.StringToUint160(testcli.ValidatorAddr)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, state.NotificationEvent{ require.Equal(t, state.NotificationEvent{
ScriptHash: verifyH, ScriptHash: verifyH,
@ -644,17 +645,17 @@ func TestNEP11_D_OwnerOf_BalanceOf_Transfer(t *testing.T) {
// check balance after transfer // check balance after transfer
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...) e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
tokz[1].amount = "0.75" tokz[1].amount = "0.75"
checkBalanceResult(t, validatorAddr, tokz[1]) checkBalanceResult(t, testcli.ValidatorAddr, tokz[1])
} }
func deployNFSContract(t *testing.T, e *executor) util.Uint160 { func deployNFSContract(t *testing.T, e *testcli.Executor) util.Uint160 {
return deployContract(t, e, "../examples/nft-d/nft.go", "../examples/nft-d/nft.yml", validatorWallet, validatorAddr, validatorPass) return testcli.DeployContract(t, e, "../../examples/nft-d/nft.go", "../../examples/nft-d/nft.yml", testcli.ValidatorWallet, testcli.ValidatorAddr, testcli.ValidatorPass)
} }
func deployNFTContract(t *testing.T, e *executor) util.Uint160 { func deployNFTContract(t *testing.T, e *testcli.Executor) util.Uint160 {
return deployContract(t, e, "../examples/nft-nd/nft.go", "../examples/nft-nd/nft.yml", nftOwnerWallet, nftOwnerAddr, nftOwnerPass) return testcli.DeployContract(t, e, "../../examples/nft-nd/nft.go", "../../examples/nft-nd/nft.yml", nftOwnerWallet, nftOwnerAddr, nftOwnerPass)
} }
func deployNNSContract(t *testing.T, e *executor) util.Uint160 { func deployNNSContract(t *testing.T, e *testcli.Executor) util.Uint160 {
return deployContract(t, e, "../examples/nft-nd-nns/", "../examples/nft-nd-nns/nns.yml", validatorWallet, validatorAddr, validatorPass) return testcli.DeployContract(t, e, "../../examples/nft-nd-nns/", "../../examples/nft-nd-nns/nns.yml", testcli.ValidatorWallet, testcli.ValidatorAddr, testcli.ValidatorPass)
} }

View file

@ -1,4 +1,4 @@
package main package wallet_test
import ( import (
"io" "io"
@ -8,6 +8,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
@ -17,24 +18,24 @@ import (
) )
func TestNEP17Balance(t *testing.T) { func TestNEP17Balance(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
cmdbalance := []string{"neo-go", "wallet", "nep17", "balance"} cmdbalance := []string{"neo-go", "wallet", "nep17", "balance"}
cmdbase := append(cmdbalance, cmdbase := append(cmdbalance,
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
) )
cmd := append(cmdbase, "--address", validatorAddr) cmd := append(cmdbase, "--address", testcli.ValidatorAddr)
t.Run("excessive parameters", func(t *testing.T) { t.Run("excessive parameters", func(t *testing.T) {
e.RunWithError(t, append(cmd, "--token", "NEO", "gas")...) e.RunWithError(t, append(cmd, "--token", "NEO", "gas")...)
}) })
t.Run("NEO", func(t *testing.T) { t.Run("NEO", func(t *testing.T) {
b, index := e.Chain.GetGoverningTokenBalance(validatorHash) b, index := e.Chain.GetGoverningTokenBalance(testcli.ValidatorHash)
checkResult := func(t *testing.T) { checkResult := func(t *testing.T) {
e.checkNextLine(t, "^\\s*Account\\s+"+validatorAddr) e.CheckNextLine(t, "^\\s*Account\\s+"+testcli.ValidatorAddr)
e.checkNextLine(t, "^\\s*NEO:\\s+NeoToken \\("+e.Chain.GoverningTokenHash().StringLE()+"\\)") e.CheckNextLine(t, "^\\s*NEO:\\s+NeoToken \\("+e.Chain.GoverningTokenHash().StringLE()+"\\)")
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$") e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$")
e.checkNextLine(t, "^\\s*Updated\\s*:\\s*"+strconv.FormatUint(uint64(index), 10)) e.CheckNextLine(t, "^\\s*Updated\\s*:\\s*"+strconv.FormatUint(uint64(index), 10))
e.checkEOF(t) e.CheckEOF(t)
} }
t.Run("Alias", func(t *testing.T) { t.Run("Alias", func(t *testing.T) {
e.Run(t, append(cmd, "--token", "NEO")...) e.Run(t, append(cmd, "--token", "NEO")...)
@ -47,67 +48,67 @@ func TestNEP17Balance(t *testing.T) {
}) })
t.Run("GAS", func(t *testing.T) { t.Run("GAS", func(t *testing.T) {
e.Run(t, append(cmd, "--token", "GAS")...) e.Run(t, append(cmd, "--token", "GAS")...)
e.checkNextLine(t, "^\\s*Account\\s+"+validatorAddr) e.CheckNextLine(t, "^\\s*Account\\s+"+testcli.ValidatorAddr)
e.checkNextLine(t, "^\\s*GAS:\\s+GasToken \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)") e.CheckNextLine(t, "^\\s*GAS:\\s+GasToken \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
b := e.Chain.GetUtilityTokenBalance(validatorHash) b := e.Chain.GetUtilityTokenBalance(testcli.ValidatorHash)
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(b.Int64()).String()+"$") e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(b.Int64()).String()+"$")
}) })
t.Run("zero balance of known token", func(t *testing.T) { t.Run("zero balance of known token", func(t *testing.T) {
e.Run(t, append(cmdbase, []string{"--token", "NEO"}...)...) e.Run(t, append(cmdbase, []string{"--token", "NEO"}...)...)
addr1, err := address.StringToUint160("Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn") addr1, err := address.StringToUint160("Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn")
require.NoError(t, err) require.NoError(t, err)
e.checkNextLine(t, "^Account "+address.Uint160ToString(addr1)) e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr1))
e.checkNextLine(t, "^\\s*NEO:\\s+NeoToken \\("+e.Chain.GoverningTokenHash().StringLE()+"\\)") e.CheckNextLine(t, "^\\s*NEO:\\s+NeoToken \\("+e.Chain.GoverningTokenHash().StringLE()+"\\)")
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(0).String()+"$") e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(0).String()+"$")
e.checkNextLine(t, "^\\s*Updated:") e.CheckNextLine(t, "^\\s*Updated:")
e.checkNextLine(t, "^\\s*$") e.CheckNextLine(t, "^\\s*$")
}) })
t.Run("all accounts", func(t *testing.T) { t.Run("all accounts", func(t *testing.T) {
e.Run(t, cmdbase...) e.Run(t, cmdbase...)
addr1, err := address.StringToUint160("Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn") addr1, err := address.StringToUint160("Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn")
require.NoError(t, err) require.NoError(t, err)
e.checkNextLine(t, "^Account "+address.Uint160ToString(addr1)) e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr1))
e.checkNextLine(t, "^\\s*GAS:\\s+GasToken \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)") e.CheckNextLine(t, "^\\s*GAS:\\s+GasToken \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
balance := e.Chain.GetUtilityTokenBalance(addr1) balance := e.Chain.GetUtilityTokenBalance(addr1)
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String()+"$") e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String()+"$")
e.checkNextLine(t, "^\\s*Updated:") e.CheckNextLine(t, "^\\s*Updated:")
e.checkNextLine(t, "^\\s*$") e.CheckNextLine(t, "^\\s*$")
addr2, err := address.StringToUint160("NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq") addr2, err := address.StringToUint160("NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq")
require.NoError(t, err) require.NoError(t, err)
e.checkNextLine(t, "^Account "+address.Uint160ToString(addr2)) e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr2))
e.checkNextLine(t, "^\\s*$") e.CheckNextLine(t, "^\\s*$")
addr3, err := address.StringToUint160("NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP") addr3, err := address.StringToUint160("NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP")
require.NoError(t, err) require.NoError(t, err)
e.checkNextLine(t, "^Account "+address.Uint160ToString(addr3)) e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr3))
// The order of assets is undefined. // The order of assets is undefined.
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
line := e.getNextLine(t) line := e.GetNextLine(t)
if strings.Contains(line, "GAS") { if strings.Contains(line, "GAS") {
e.checkLine(t, line, "^\\s*GAS:\\s+GasToken \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)") e.CheckLine(t, line, "^\\s*GAS:\\s+GasToken \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
balance = e.Chain.GetUtilityTokenBalance(addr3) balance = e.Chain.GetUtilityTokenBalance(addr3)
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String()+"$") e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String()+"$")
e.checkNextLine(t, "^\\s*Updated:") e.CheckNextLine(t, "^\\s*Updated:")
} else { } else {
balance, index := e.Chain.GetGoverningTokenBalance(validatorHash) balance, index := e.Chain.GetGoverningTokenBalance(testcli.ValidatorHash)
e.checkLine(t, line, "^\\s*NEO:\\s+NeoToken \\("+e.Chain.GoverningTokenHash().StringLE()+"\\)") e.CheckLine(t, line, "^\\s*NEO:\\s+NeoToken \\("+e.Chain.GoverningTokenHash().StringLE()+"\\)")
e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+balance.String()+"$") e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+balance.String()+"$")
e.checkNextLine(t, "^\\s*Updated\\s*:\\s*"+strconv.FormatUint(uint64(index), 10)) e.CheckNextLine(t, "^\\s*Updated\\s*:\\s*"+strconv.FormatUint(uint64(index), 10))
} }
} }
e.checkNextLine(t, "^\\s*$") e.CheckNextLine(t, "^\\s*$")
addr4, err := address.StringToUint160("NQ3nAdFQXzemHC9uvr4af2Ysap6aZJpqgN") // deployed verify.go contract addr4, err := address.StringToUint160("NQ3nAdFQXzemHC9uvr4af2Ysap6aZJpqgN") // deployed verify.go contract
require.NoError(t, err) require.NoError(t, err)
e.checkNextLine(t, "^Account "+address.Uint160ToString(addr4)) e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr4))
e.checkEOF(t) e.CheckEOF(t)
}) })
t.Run("Bad token", func(t *testing.T) { t.Run("Bad token", func(t *testing.T) {
e.Run(t, append(cmd, "--token", "kek")...) e.Run(t, append(cmd, "--token", "kek")...)
e.checkNextLine(t, "^\\s*Account\\s+"+validatorAddr) e.CheckNextLine(t, "^\\s*Account\\s+"+testcli.ValidatorAddr)
e.checkNextLine(t, `^\s*Can't find data for "kek" token\s*`) e.CheckNextLine(t, `^\s*Can't find data for "kek" token\s*`)
e.checkEOF(t) e.CheckEOF(t)
}) })
t.Run("Bad wallet", func(t *testing.T) { t.Run("Bad wallet", func(t *testing.T) {
e.RunWithError(t, append(cmdbalance, "--wallet", "/dev/null")...) e.RunWithError(t, append(cmdbalance, "--wallet", "/dev/null")...)
@ -115,18 +116,18 @@ func TestNEP17Balance(t *testing.T) {
} }
func TestNEP17Transfer(t *testing.T) { func TestNEP17Transfer(t *testing.T) {
w, err := wallet.NewWalletFromFile("testdata/testwallet.json") w, err := wallet.NewWalletFromFile("../testdata/testwallet.json")
require.NoError(t, err) require.NoError(t, err)
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
args := []string{ args := []string{
"neo-go", "wallet", "nep17", "transfer", "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--to", w.Accounts[0].Address, "--to", w.Accounts[0].Address,
"--token", "NEO", "--token", "NEO",
"--amount", "1", "--amount", "1",
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
} }
t.Run("missing receiver", func(t *testing.T) { t.Run("missing receiver", func(t *testing.T) {
@ -157,10 +158,10 @@ func TestNEP17Transfer(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.In.WriteString("Y\r") e.In.WriteString("Y\r")
e.Run(t, args...) e.Run(t, args...)
e.checkNextLine(t, `^Network fee:\s*(\d|\.)+`) e.CheckNextLine(t, `^Network fee:\s*(\d|\.)+`)
e.checkNextLine(t, `^System fee:\s*(\d|\.)+`) e.CheckNextLine(t, `^System fee:\s*(\d|\.)+`)
e.checkNextLine(t, `^Total fee:\s*(\d|\.)+`) e.CheckNextLine(t, `^Total fee:\s*(\d|\.)+`)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
sh := w.Accounts[0].ScriptHash() sh := w.Accounts[0].ScriptHash()
b, _ := e.Chain.GetGoverningTokenBalance(sh) b, _ := e.Chain.GetGoverningTokenBalance(sh)
@ -169,7 +170,7 @@ func TestNEP17Transfer(t *testing.T) {
t.Run("with force", func(t *testing.T) { t.Run("with force", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, append(args, "--force")...) e.Run(t, append(args, "--force")...)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
b, _ := e.Chain.GetGoverningTokenBalance(sh) b, _ := e.Chain.GetGoverningTokenBalance(sh)
require.Equal(t, big.NewInt(2), b) require.Equal(t, big.NewInt(2), b)
@ -182,18 +183,18 @@ func TestNEP17Transfer(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer", e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
"NEO:"+validatorDefault+":42", "NEO:"+validatorDefault+":42",
"GAS:"+validatorDefault+":7") "GAS:"+validatorDefault+":7")
e.checkTxPersisted(t) e.CheckTxPersisted(t)
args := args[:len(args)-2] // cut '--from' argument args := args[:len(args)-2] // cut '--from' argument
args = append(args, "--force") args = append(args, "--force")
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, args...) e.Run(t, args...)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
b, _ := e.Chain.GetGoverningTokenBalance(sh) b, _ := e.Chain.GetGoverningTokenBalance(sh)
require.Equal(t, big.NewInt(3), b) require.Equal(t, big.NewInt(3), b)
@ -208,62 +209,62 @@ func TestNEP17Transfer(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer", e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
"NEO:"+validatorDefault+":42", "NEO:"+validatorDefault+":42",
"GAS:"+validatorDefault+":7", "GAS:"+validatorDefault+":7",
"--", validatorAddr+":Global") "--", testcli.ValidatorAddr+":Global")
e.checkTxPersisted(t) e.CheckTxPersisted(t)
}) })
validTil := e.Chain.BlockHeight() + 100 validTil := e.Chain.BlockHeight() + 100
cmd := []string{ cmd := []string{
"neo-go", "wallet", "nep17", "transfer", "neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--to", address.Uint160ToString(e.Chain.GetNotaryContractScriptHash()), "--to", address.Uint160ToString(e.Chain.GetNotaryContractScriptHash()),
"--token", "GAS", "--token", "GAS",
"--amount", "1", "--amount", "1",
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
"[", validatorAddr, strconv.Itoa(int(validTil)), "]"} "[", testcli.ValidatorAddr, strconv.Itoa(int(validTil)), "]"}
t.Run("with data", func(t *testing.T) { t.Run("with data", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, cmd...) e.Run(t, cmd...)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
}) })
t.Run("with data and signers", func(t *testing.T) { t.Run("with data and signers", func(t *testing.T) {
t.Run("invalid sender's scope", func(t *testing.T) { t.Run("invalid sender's scope", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.RunWithError(t, append(cmd, "--", validatorAddr+":None")...) e.RunWithError(t, append(cmd, "--", testcli.ValidatorAddr+":None")...)
}) })
t.Run("good", func(t *testing.T) { t.Run("good", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, append(cmd, "--", validatorAddr+":Global")...) // CalledByEntry is enough, but it's the default value, so check something else e.Run(t, append(cmd, "--", testcli.ValidatorAddr+":Global")...) // CalledByEntry is enough, but it's the default value, so check something else
e.checkTxPersisted(t) e.CheckTxPersisted(t)
}) })
t.Run("several signers", func(t *testing.T) { t.Run("several signers", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, append(cmd, "--", validatorAddr, hVerify.StringLE())...) e.Run(t, append(cmd, "--", testcli.ValidatorAddr, hVerify.StringLE())...)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
}) })
}) })
} }
func TestNEP17MultiTransfer(t *testing.T) { func TestNEP17MultiTransfer(t *testing.T) {
privs, _ := generateKeys(t, 3) privs, _ := testcli.GenerateKeys(t, 3)
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
neoContractHash, err := e.Chain.GetNativeContractScriptHash(nativenames.Neo) neoContractHash, err := e.Chain.GetNativeContractScriptHash(nativenames.Neo)
require.NoError(t, err) require.NoError(t, err)
args := []string{ args := []string{
"neo-go", "wallet", "nep17", "multitransfer", "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
"NEO:" + privs[0].Address() + ":42", "NEO:" + privs[0].Address() + ":42",
"GAS:" + privs[1].Address() + ":7", "GAS:" + privs[1].Address() + ":7",
@ -274,7 +275,7 @@ func TestNEP17MultiTransfer(t *testing.T) {
t.Run("no cosigners", func(t *testing.T) { t.Run("no cosigners", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, args...) e.Run(t, args...)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
b, _ := e.Chain.GetGoverningTokenBalance(privs[0].GetScriptHash()) b, _ := e.Chain.GetGoverningTokenBalance(privs[0].GetScriptHash())
require.Equal(t, big.NewInt(42), b) require.Equal(t, big.NewInt(42), b)
@ -287,24 +288,24 @@ func TestNEP17MultiTransfer(t *testing.T) {
t.Run("invalid sender scope", func(t *testing.T) { t.Run("invalid sender scope", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.RunWithError(t, append(args, e.RunWithError(t, append(args,
"--", validatorAddr+":None")...) // invalid sender scope "--", testcli.ValidatorAddr+":None")...) // invalid sender scope
}) })
t.Run("Global sender scope", func(t *testing.T) { t.Run("Global sender scope", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, append(args, e.Run(t, append(args,
"--", validatorAddr+":Global")...) "--", testcli.ValidatorAddr+":Global")...)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
}) })
t.Run("Several cosigners", func(t *testing.T) { t.Run("Several cosigners", func(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, append(args, e.Run(t, append(args,
"--", validatorAddr, hVerify.StringLE())...) "--", testcli.ValidatorAddr, hVerify.StringLE())...)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
}) })
} }
func TestNEP17ImportToken(t *testing.T) { func TestNEP17ImportToken(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
tmpDir := t.TempDir() tmpDir := t.TempDir()
walletPath := filepath.Join(tmpDir, "walletForImport.json") walletPath := filepath.Join(tmpDir, "walletForImport.json")
@ -342,12 +343,12 @@ func TestNEP17ImportToken(t *testing.T) {
t.Run("Info", func(t *testing.T) { t.Run("Info", func(t *testing.T) {
checkGASInfo := func(t *testing.T) { checkGASInfo := func(t *testing.T) {
e.checkNextLine(t, "^Name:\\s*GasToken") e.CheckNextLine(t, "^Name:\\s*GasToken")
e.checkNextLine(t, "^Symbol:\\s*GAS") e.CheckNextLine(t, "^Symbol:\\s*GAS")
e.checkNextLine(t, "^Hash:\\s*"+gasContractHash.StringLE()) e.CheckNextLine(t, "^Hash:\\s*"+gasContractHash.StringLE())
e.checkNextLine(t, "^Decimals:\\s*8") e.CheckNextLine(t, "^Decimals:\\s*8")
e.checkNextLine(t, "^Address:\\s*"+address.Uint160ToString(gasContractHash)) e.CheckNextLine(t, "^Address:\\s*"+address.Uint160ToString(gasContractHash))
e.checkNextLine(t, "^Standard:\\s*"+string(manifest.NEP17StandardName)) e.CheckNextLine(t, "^Standard:\\s*"+string(manifest.NEP17StandardName))
} }
t.Run("excessive parameters", func(t *testing.T) { t.Run("excessive parameters", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "nep17", "info", e.RunWithError(t, "neo-go", "wallet", "nep17", "info",
@ -364,12 +365,12 @@ func TestNEP17ImportToken(t *testing.T) {
checkGASInfo(t) checkGASInfo(t)
_, err := e.Out.ReadString('\n') _, err := e.Out.ReadString('\n')
require.NoError(t, err) require.NoError(t, err)
e.checkNextLine(t, "^Name:\\s*NeoToken") e.CheckNextLine(t, "^Name:\\s*NeoToken")
e.checkNextLine(t, "^Symbol:\\s*NEO") e.CheckNextLine(t, "^Symbol:\\s*NEO")
e.checkNextLine(t, "^Hash:\\s*"+neoContractHash.StringLE()) e.CheckNextLine(t, "^Hash:\\s*"+neoContractHash.StringLE())
e.checkNextLine(t, "^Decimals:\\s*0") e.CheckNextLine(t, "^Decimals:\\s*0")
e.checkNextLine(t, "^Address:\\s*"+address.Uint160ToString(neoContractHash)) e.CheckNextLine(t, "^Address:\\s*"+address.Uint160ToString(neoContractHash))
e.checkNextLine(t, "^Standard:\\s*"+string(manifest.NEP17StandardName)) e.CheckNextLine(t, "^Standard:\\s*"+string(manifest.NEP17StandardName))
}) })
t.Run("Remove", func(t *testing.T) { t.Run("Remove", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "nep17", "remove", e.RunWithError(t, "neo-go", "wallet", "nep17", "remove",

View file

@ -1,4 +1,4 @@
package main package wallet_test
import ( import (
"encoding/hex" "encoding/hex"
@ -10,6 +10,7 @@ import (
"testing" "testing"
"github.com/chzyer/readline" "github.com/chzyer/readline"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
@ -23,7 +24,7 @@ import (
func TestWalletAccountRemove(t *testing.T) { func TestWalletAccountRemove(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
walletPath := filepath.Join(tmpDir, "wallet.json") walletPath := filepath.Join(tmpDir, "wallet.json")
e.In.WriteString("acc1\r") e.In.WriteString("acc1\r")
@ -71,7 +72,7 @@ func TestWalletAccountRemove(t *testing.T) {
func TestWalletChangePassword(t *testing.T) { func TestWalletChangePassword(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
walletPath := filepath.Join(tmpDir, "wallet.json") walletPath := filepath.Join(tmpDir, "wallet.json")
e.In.WriteString("acc1\r") e.In.WriteString("acc1\r")
@ -142,7 +143,7 @@ func TestWalletChangePassword(t *testing.T) {
} }
func TestWalletInit(t *testing.T) { func TestWalletInit(t *testing.T) {
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
t.Run("missing path", func(t *testing.T) { t.Run("missing path", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "init") e.RunWithError(t, "neo-go", "wallet", "init")
@ -363,7 +364,7 @@ func TestWalletInit(t *testing.T) {
"--wallet", walletPath, "--wallet", walletPath,
"--min", "2") "--min", "2")
}) })
privs, pubs := generateKeys(t, 4) privs, pubs := testcli.GenerateKeys(t, 4)
cmd := []string{"neo-go", "wallet", "import-multisig", cmd := []string{"neo-go", "wallet", "import-multisig",
"--wallet", walletPath, "--wallet", walletPath,
"--min", "2"} "--min", "2"}
@ -423,94 +424,94 @@ func TestWalletInit(t *testing.T) {
} }
func TestWalletExport(t *testing.T) { func TestWalletExport(t *testing.T) {
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
t.Run("missing wallet", func(t *testing.T) { t.Run("missing wallet", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "export") e.RunWithError(t, "neo-go", "wallet", "export")
}) })
t.Run("invalid address", func(t *testing.T) { t.Run("invalid address", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "export", e.RunWithError(t, "neo-go", "wallet", "export",
"--wallet", validatorWallet, "not-an-address") "--wallet", testcli.ValidatorWallet, "not-an-address")
}) })
t.Run("Encrypted", func(t *testing.T) { t.Run("Encrypted", func(t *testing.T) {
e.Run(t, "neo-go", "wallet", "export", e.Run(t, "neo-go", "wallet", "export",
"--wallet", validatorWallet, validatorAddr) "--wallet", testcli.ValidatorWallet, testcli.ValidatorAddr)
line, err := e.Out.ReadString('\n') line, err := e.Out.ReadString('\n')
require.NoError(t, err) require.NoError(t, err)
enc, err := keys.NEP2Encrypt(validatorPriv, "one", keys.ScryptParams{N: 2, R: 1, P: 1}) // these params used in validator wallet for better resources consumption enc, err := keys.NEP2Encrypt(testcli.ValidatorPriv, "one", keys.ScryptParams{N: 2, R: 1, P: 1}) // these params used in validator wallet for better resources consumption
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, enc, strings.TrimSpace(line)) require.Equal(t, enc, strings.TrimSpace(line))
}) })
t.Run("Decrypted", func(t *testing.T) { t.Run("Decrypted", func(t *testing.T) {
t.Run("NoAddress", func(t *testing.T) { t.Run("NoAddress", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "export", e.RunWithError(t, "neo-go", "wallet", "export",
"--wallet", validatorWallet, "--decrypt") "--wallet", testcli.ValidatorWallet, "--decrypt")
}) })
t.Run("EOF reading password", func(t *testing.T) { t.Run("EOF reading password", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "export", e.RunWithError(t, "neo-go", "wallet", "export",
"--wallet", validatorWallet, "--decrypt", validatorAddr) "--wallet", testcli.ValidatorWallet, "--decrypt", testcli.ValidatorAddr)
}) })
t.Run("invalid password", func(t *testing.T) { t.Run("invalid password", func(t *testing.T) {
e.In.WriteString("invalid_pass\r") e.In.WriteString("invalid_pass\r")
e.RunWithError(t, "neo-go", "wallet", "export", e.RunWithError(t, "neo-go", "wallet", "export",
"--wallet", validatorWallet, "--decrypt", validatorAddr) "--wallet", testcli.ValidatorWallet, "--decrypt", testcli.ValidatorAddr)
}) })
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "export", e.Run(t, "neo-go", "wallet", "export",
"--wallet", validatorWallet, "--decrypt", validatorAddr) "--wallet", testcli.ValidatorWallet, "--decrypt", testcli.ValidatorAddr)
line, err := e.Out.ReadString('\n') line, err := e.Out.ReadString('\n')
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, validatorWIF, strings.TrimSpace(line)) require.Equal(t, testcli.ValidatorWIF, strings.TrimSpace(line))
}) })
} }
func TestWalletClaimGas(t *testing.T) { func TestWalletClaimGas(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
t.Run("missing wallet path", func(t *testing.T) { t.Run("missing wallet path", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "claim", e.RunWithError(t, "neo-go", "wallet", "claim",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--address", testWalletAccount) "--address", testcli.TestWalletAccount)
}) })
t.Run("missing address", func(t *testing.T) { t.Run("missing address", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "claim", e.RunWithError(t, "neo-go", "wallet", "claim",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", testWalletPath) "--wallet", testcli.TestWalletPath)
}) })
t.Run("invalid address", func(t *testing.T) { t.Run("invalid address", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "claim", e.RunWithError(t, "neo-go", "wallet", "claim",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", testWalletPath, "--wallet", testcli.TestWalletPath,
"--address", util.Uint160{}.StringLE()) "--address", util.Uint160{}.StringLE())
}) })
t.Run("missing endpoint", func(t *testing.T) { t.Run("missing endpoint", func(t *testing.T) {
e.In.WriteString("testpass\r") e.In.WriteString("testpass\r")
e.RunWithError(t, "neo-go", "wallet", "claim", e.RunWithError(t, "neo-go", "wallet", "claim",
"--wallet", testWalletPath, "--wallet", testcli.TestWalletPath,
"--address", testWalletAccount) "--address", testcli.TestWalletAccount)
}) })
t.Run("insufficient funds", func(t *testing.T) { t.Run("insufficient funds", func(t *testing.T) {
e.In.WriteString("testpass\r") e.In.WriteString("testpass\r")
e.RunWithError(t, "neo-go", "wallet", "claim", e.RunWithError(t, "neo-go", "wallet", "claim",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", testWalletPath, "--wallet", testcli.TestWalletPath,
"--address", testWalletAccount) "--address", testcli.TestWalletAccount)
}) })
args := []string{ args := []string{
"neo-go", "wallet", "nep17", "multitransfer", "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", validatorWallet, "--wallet", testcli.ValidatorWallet,
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--force", "--force",
"NEO:" + testWalletAccount + ":1000", "NEO:" + testcli.TestWalletAccount + ":1000",
"GAS:" + testWalletAccount + ":1000", // for tx send "GAS:" + testcli.TestWalletAccount + ":1000", // for tx send
} }
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, args...) e.Run(t, args...)
e.checkTxPersisted(t) e.CheckTxPersisted(t)
h, err := address.StringToUint160(testWalletAccount) h, err := address.StringToUint160(testcli.TestWalletAccount)
require.NoError(t, err) require.NoError(t, err)
balanceBefore := e.Chain.GetUtilityTokenBalance(h) balanceBefore := e.Chain.GetUtilityTokenBalance(h)
@ -522,9 +523,9 @@ func TestWalletClaimGas(t *testing.T) {
e.In.WriteString("testpass\r") e.In.WriteString("testpass\r")
e.Run(t, "neo-go", "wallet", "claim", e.Run(t, "neo-go", "wallet", "claim",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", testWalletPath, "--wallet", testcli.TestWalletPath,
"--address", testWalletAccount) "--address", testcli.TestWalletAccount)
tx, height := e.checkTxPersisted(t) tx, height := e.CheckTxPersisted(t)
balanceBefore.Sub(balanceBefore, big.NewInt(tx.NetworkFee+tx.SystemFee)) balanceBefore.Sub(balanceBefore, big.NewInt(tx.NetworkFee+tx.SystemFee))
balanceBefore.Add(balanceBefore, cl) balanceBefore.Add(balanceBefore, cl)
@ -539,7 +540,7 @@ func TestWalletClaimGas(t *testing.T) {
func TestWalletImportDeployed(t *testing.T) { func TestWalletImportDeployed(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
h := deployVerifyContract(t, e) h := deployVerifyContract(t, e)
walletPath := filepath.Join(tmpDir, "wallet.json") walletPath := filepath.Join(tmpDir, "wallet.json")
@ -606,11 +607,11 @@ func TestWalletImportDeployed(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer", e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--from", validatorAddr, "--wallet", testcli.ValidatorWallet, "--from", testcli.ValidatorAddr,
"--force", "--force",
"NEO:"+contractAddr+":10", "NEO:"+contractAddr+":10",
"GAS:"+contractAddr+":10") "GAS:"+contractAddr+":10")
e.checkTxPersisted(t) e.CheckTxPersisted(t)
privTo, err := keys.NewPrivateKey() privTo, err := keys.NewPrivateKey()
require.NoError(t, err) require.NoError(t, err)
@ -621,7 +622,7 @@ func TestWalletImportDeployed(t *testing.T) {
"--wallet", walletPath, "--from", contractAddr, "--wallet", walletPath, "--from", contractAddr,
"--force", "--force",
"--to", privTo.Address(), "--token", "NEO", "--amount", "1") "--to", privTo.Address(), "--token", "NEO", "--amount", "1")
e.checkTxPersisted(t) e.CheckTxPersisted(t)
b, _ := e.Chain.GetGoverningTokenBalance(h) b, _ := e.Chain.GetGoverningTokenBalance(h)
require.Equal(t, big.NewInt(9), b) require.Equal(t, big.NewInt(9), b)
@ -631,7 +632,7 @@ func TestWalletImportDeployed(t *testing.T) {
} }
func TestStripKeys(t *testing.T) { func TestStripKeys(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
tmpDir := t.TempDir() tmpDir := t.TempDir()
walletPath := filepath.Join(tmpDir, "wallet.json") walletPath := filepath.Join(tmpDir, "wallet.json")
e.In.WriteString("acc1\r") e.In.WriteString("acc1\r")
@ -661,13 +662,13 @@ func TestStripKeys(t *testing.T) {
} }
func TestOfflineSigning(t *testing.T) { func TestOfflineSigning(t *testing.T) {
e := newExecutor(t, true) e := testcli.NewExecutor(t, true)
tmpDir := t.TempDir() tmpDir := t.TempDir()
walletPath := filepath.Join(tmpDir, "wallet.json") walletPath := filepath.Join(tmpDir, "wallet.json")
txPath := filepath.Join(tmpDir, "tx.json") txPath := filepath.Join(tmpDir, "tx.json")
// Copy wallet. // Copy wallet.
w, err := wallet.NewWalletFromFile(validatorWallet) w, err := wallet.NewWalletFromFile(testcli.ValidatorWallet)
require.NoError(t, err) require.NoError(t, err)
jOut, err := w.JSON() jOut, err := w.JSON()
require.NoError(t, err) require.NoError(t, err)
@ -680,7 +681,7 @@ func TestOfflineSigning(t *testing.T) {
args := []string{"neo-go", "wallet", "nep17", "transfer", args := []string{"neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", walletPath, "--wallet", walletPath,
"--from", validatorAddr, "--from", testcli.ValidatorAddr,
"--to", w.Accounts[0].Address, "--to", w.Accounts[0].Address,
"--token", "NEO", "--token", "NEO",
"--amount", "1", "--amount", "1",
@ -692,7 +693,7 @@ func TestOfflineSigning(t *testing.T) {
e.Run(t, append(args, "--out", txPath)...) e.Run(t, append(args, "--out", txPath)...)
// It can't be signed with the original wallet. // It can't be signed with the original wallet.
e.RunWithError(t, "neo-go", "wallet", "sign", e.RunWithError(t, "neo-go", "wallet", "sign",
"--wallet", walletPath, "--address", validatorAddr, "--wallet", walletPath, "--address", testcli.ValidatorAddr,
"--in", txPath, "--out", txPath) "--in", txPath, "--out", txPath)
t.Run("sendtx", func(t *testing.T) { t.Run("sendtx", func(t *testing.T) {
// And it can't be sent. // And it can't be sent.
@ -710,22 +711,22 @@ func TestOfflineSigning(t *testing.T) {
// But it can be signed with a proper wallet. // But it can be signed with a proper wallet.
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "sign", e.Run(t, "neo-go", "wallet", "sign",
"--wallet", validatorWallet, "--address", validatorAddr, "--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
"--in", txPath, "--out", txPath) "--in", txPath, "--out", txPath)
// And then anyone can send (even via wallet sign). // And then anyone can send (even via wallet sign).
e.Run(t, "neo-go", "wallet", "sign", e.Run(t, "neo-go", "wallet", "sign",
"--rpc-endpoint", "http://"+e.RPC.Addr, "--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", walletPath, "--address", validatorAddr, "--wallet", walletPath, "--address", testcli.ValidatorAddr,
"--in", txPath) "--in", txPath)
}) })
e.checkTxPersisted(t) e.CheckTxPersisted(t)
t.Run("simple signature", func(t *testing.T) { t.Run("simple signature", func(t *testing.T) {
simpleAddr := w.Accounts[0].Address simpleAddr := w.Accounts[0].Address
args := []string{"neo-go", "wallet", "nep17", "transfer", args := []string{"neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,
"--wallet", walletPath, "--wallet", walletPath,
"--from", simpleAddr, "--from", simpleAddr,
"--to", validatorAddr, "--to", testcli.ValidatorAddr,
"--token", "NEO", "--token", "NEO",
"--amount", "1", "--amount", "1",
"--force", "--force",
@ -741,7 +742,7 @@ func TestOfflineSigning(t *testing.T) {
// But can be with a proper one. // But can be with a proper one.
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "sign", e.Run(t, "neo-go", "wallet", "sign",
"--wallet", validatorWallet, "--address", simpleAddr, "--wallet", testcli.ValidatorWallet, "--address", simpleAddr,
"--in", txPath, "--out", txPath) "--in", txPath, "--out", txPath)
// Sending without an RPC node is not likely to succeed. // Sending without an RPC node is not likely to succeed.
e.RunWithError(t, "neo-go", "util", "sendtx", txPath) e.RunWithError(t, "neo-go", "util", "sendtx", txPath)
@ -753,18 +754,18 @@ func TestOfflineSigning(t *testing.T) {
} }
func TestWalletDump(t *testing.T) { func TestWalletDump(t *testing.T) {
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
t.Run("missing wallet", func(t *testing.T) { t.Run("missing wallet", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "dump") e.RunWithError(t, "neo-go", "wallet", "dump")
}) })
cmd := []string{"neo-go", "wallet", "dump", "--wallet", testWalletPath} cmd := []string{"neo-go", "wallet", "dump", "--wallet", testcli.TestWalletPath}
e.Run(t, cmd...) e.Run(t, cmd...)
rawStr := strings.TrimSpace(e.Out.String()) rawStr := strings.TrimSpace(e.Out.String())
w := new(wallet.Wallet) w := new(wallet.Wallet)
require.NoError(t, json.Unmarshal([]byte(rawStr), w)) require.NoError(t, json.Unmarshal([]byte(rawStr), w))
require.Equal(t, 1, len(w.Accounts)) require.Equal(t, 1, len(w.Accounts))
require.Equal(t, testWalletAccount, w.Accounts[0].Address) require.Equal(t, testcli.TestWalletAccount, w.Accounts[0].Address)
t.Run("with decrypt", func(t *testing.T) { t.Run("with decrypt", func(t *testing.T) {
cmd = append(cmd, "--decrypt") cmd = append(cmd, "--decrypt")
@ -782,13 +783,13 @@ func TestWalletDump(t *testing.T) {
w := new(wallet.Wallet) w := new(wallet.Wallet)
require.NoError(t, json.Unmarshal([]byte(rawStr), w)) require.NoError(t, json.Unmarshal([]byte(rawStr), w))
require.Equal(t, 1, len(w.Accounts)) require.Equal(t, 1, len(w.Accounts))
require.Equal(t, testWalletAccount, w.Accounts[0].Address) require.Equal(t, testcli.TestWalletAccount, w.Accounts[0].Address)
}) })
t.Run("good, from wallet config", func(t *testing.T) { t.Run("good, from wallet config", func(t *testing.T) {
tmp := t.TempDir() tmp := t.TempDir()
configPath := filepath.Join(tmp, "config.yaml") configPath := filepath.Join(tmp, "config.yaml")
cfg := config.Wallet{ cfg := config.Wallet{
Path: testWalletPath, Path: testcli.TestWalletPath,
Password: "testpass", Password: "testpass",
} }
res, err := yaml.Marshal(cfg) res, err := yaml.Marshal(cfg)
@ -799,31 +800,31 @@ func TestWalletDump(t *testing.T) {
w := new(wallet.Wallet) w := new(wallet.Wallet)
require.NoError(t, json.Unmarshal([]byte(rawStr), w)) require.NoError(t, json.Unmarshal([]byte(rawStr), w))
require.Equal(t, 1, len(w.Accounts)) require.Equal(t, 1, len(w.Accounts))
require.Equal(t, testWalletAccount, w.Accounts[0].Address) require.Equal(t, testcli.TestWalletAccount, w.Accounts[0].Address)
}) })
}) })
} }
func TestWalletDumpKeys(t *testing.T) { func TestWalletDumpKeys(t *testing.T) {
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
t.Run("missing wallet", func(t *testing.T) { t.Run("missing wallet", func(t *testing.T) {
e.RunWithError(t, "neo-go", "wallet", "dump-keys") e.RunWithError(t, "neo-go", "wallet", "dump-keys")
}) })
cmd := []string{"neo-go", "wallet", "dump-keys", "--wallet", validatorWallet} cmd := []string{"neo-go", "wallet", "dump-keys", "--wallet", testcli.ValidatorWallet}
pubRegex := "^0[23][a-hA-H0-9]{64}$" pubRegex := "^0[23][a-hA-H0-9]{64}$"
t.Run("all", func(t *testing.T) { t.Run("all", func(t *testing.T) {
e.Run(t, cmd...) e.Run(t, cmd...)
e.checkNextLine(t, "Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn") e.CheckNextLine(t, "Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn")
e.checkNextLine(t, pubRegex) e.CheckNextLine(t, pubRegex)
e.checkNextLine(t, "^\\s*$") e.CheckNextLine(t, "^\\s*$")
e.checkNextLine(t, "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq") e.CheckNextLine(t, "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq")
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
e.checkNextLine(t, pubRegex) e.CheckNextLine(t, pubRegex)
} }
e.checkNextLine(t, "^\\s*$") e.CheckNextLine(t, "^\\s*$")
e.checkNextLine(t, "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP") e.CheckNextLine(t, "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP")
e.checkNextLine(t, pubRegex) e.CheckNextLine(t, pubRegex)
e.checkEOF(t) e.CheckEOF(t)
}) })
t.Run("unknown address", func(t *testing.T) { t.Run("unknown address", func(t *testing.T) {
cmd := append(cmd, "--address", util.Uint160{}.StringLE()) cmd := append(cmd, "--address", util.Uint160{}.StringLE())
@ -832,39 +833,39 @@ func TestWalletDumpKeys(t *testing.T) {
t.Run("simple signature", func(t *testing.T) { t.Run("simple signature", func(t *testing.T) {
cmd := append(cmd, "--address", "Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn") cmd := append(cmd, "--address", "Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn")
e.Run(t, cmd...) e.Run(t, cmd...)
e.checkNextLine(t, "simple signature contract") e.CheckNextLine(t, "simple signature contract")
e.checkNextLine(t, pubRegex) e.CheckNextLine(t, pubRegex)
e.checkEOF(t) e.CheckEOF(t)
}) })
t.Run("3/4 multisig", func(t *testing.T) { t.Run("3/4 multisig", func(t *testing.T) {
cmd := append(cmd, "-a", "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq") cmd := append(cmd, "-a", "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq")
e.Run(t, cmd...) e.Run(t, cmd...)
e.checkNextLine(t, "3 out of 4 multisig contract") e.CheckNextLine(t, "3 out of 4 multisig contract")
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
e.checkNextLine(t, pubRegex) e.CheckNextLine(t, pubRegex)
} }
e.checkEOF(t) e.CheckEOF(t)
}) })
t.Run("1/1 multisig", func(t *testing.T) { t.Run("1/1 multisig", func(t *testing.T) {
cmd := append(cmd, "--address", "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP") cmd := append(cmd, "--address", "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP")
e.Run(t, cmd...) e.Run(t, cmd...)
e.checkNextLine(t, "1 out of 1 multisig contract") e.CheckNextLine(t, "1 out of 1 multisig contract")
e.checkNextLine(t, pubRegex) e.CheckNextLine(t, pubRegex)
e.checkEOF(t) e.CheckEOF(t)
}) })
} }
// Testcase is the wallet of privnet validator. // Testcase is the wallet of privnet validator.
func TestWalletConvert(t *testing.T) { func TestWalletConvert(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
e := newExecutor(t, false) e := testcli.NewExecutor(t, false)
outPath := filepath.Join(tmpDir, "wallet.json") outPath := filepath.Join(tmpDir, "wallet.json")
cmd := []string{"neo-go", "wallet", "convert"} cmd := []string{"neo-go", "wallet", "convert"}
t.Run("missing wallet", func(t *testing.T) { t.Run("missing wallet", func(t *testing.T) {
e.RunWithError(t, cmd...) e.RunWithError(t, cmd...)
}) })
cmd = append(cmd, "--wallet", "testdata/wallets/testwallet_NEO2.json") cmd = append(cmd, "--wallet", "testdata/testwallet_NEO2.json")
t.Run("missing out path", func(t *testing.T) { t.Run("missing out path", func(t *testing.T) {
e.RunWithError(t, cmd...) e.RunWithError(t, cmd...)
}) })
@ -886,12 +887,12 @@ func TestWalletConvert(t *testing.T) {
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.In.WriteString("one\r") e.In.WriteString("one\r")
e.Run(t, "neo-go", "wallet", "convert", e.Run(t, "neo-go", "wallet", "convert",
"--wallet", "testdata/wallets/testwallet_NEO2.json", "--wallet", "testdata/testwallet_NEO2.json",
"--out", outPath) "--out", outPath)
actual, err := wallet.NewWalletFromFile(outPath) actual, err := wallet.NewWalletFromFile(outPath)
require.NoError(t, err) require.NoError(t, err)
expected, err := wallet.NewWalletFromFile("testdata/wallets/testwallet_NEO3.json") expected, err := wallet.NewWalletFromFile("testdata/testwallet_NEO3.json")
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, len(actual.Accounts), len(expected.Accounts)) require.Equal(t, len(actual.Accounts), len(expected.Accounts))
for _, exp := range expected.Accounts { for _, exp := range expected.Accounts {

View file

@ -45,7 +45,7 @@ ApplicationConfiguration:
MaxPeers: 10 MaxPeers: 10
AttemptConnPeers: 5 AttemptConnPeers: 5
UnlockWallet: UnlockWallet:
Path: "testdata/wallet1_solo.json" Path: "../testdata/wallet1_solo.json"
Password: "one" Password: "one"
P2PNotary: P2PNotary:
Enabled: false Enabled: false

View file

@ -1,4 +1,11 @@
package main /*
Package testcli contains auxiliary code to test CLI commands.
All testdata assets for it are contained in the cli directory and paths here
use `../` prefix to reference them because the package itself is used from
cli/* subpackages.
*/
package testcli
import ( import (
"bytes" "bytes"
@ -6,11 +13,13 @@ import (
"fmt" "fmt"
"io" "io"
"math" "math"
"path/filepath"
"strings" "strings"
"sync" "sync"
"testing" "testing"
"time" "time"
"github.com/nspcc-dev/neo-go/cli/app"
"github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/cli/input"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/consensus" "github.com/nspcc-dev/neo-go/pkg/consensus"
@ -32,25 +41,25 @@ import (
) )
const ( const (
validatorWIF = "KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY" ValidatorWIF = "KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY"
validatorAddr = "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP" ValidatorAddr = "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP"
multisigAddr = "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq" MultisigAddr = "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq"
testWalletPath = "testdata/testwallet.json" TestWalletPath = "../testdata/testwallet.json"
testWalletAccount = "Nfyz4KcsgYepRJw1W5C2uKCi6QWKf7v6gG" TestWalletAccount = "Nfyz4KcsgYepRJw1W5C2uKCi6QWKf7v6gG"
validatorWallet = "testdata/wallet1_solo.json" ValidatorWallet = "../testdata/wallet1_solo.json"
validatorPass = "one" ValidatorPass = "one"
) )
var ( var (
validatorHash, _ = address.StringToUint160(validatorAddr) ValidatorHash, _ = address.StringToUint160(ValidatorAddr)
validatorPriv, _ = keys.NewPrivateKeyFromWIF(validatorWIF) ValidatorPriv, _ = keys.NewPrivateKeyFromWIF(ValidatorWIF)
) )
// executor represents context for a test instance. // Executor represents context for a test instance.
// It can be safely used in multiple tests, but not in parallel. // It can be safely used in multiple tests, but not in parallel.
type executor struct { type Executor struct {
// CLI is a cli application to test. // CLI is a cli application to test.
CLI *cli.App CLI *cli.App
// Chain is a blockchain instance (can be empty). // Chain is a blockchain instance (can be empty).
@ -120,8 +129,8 @@ func (w *ConcurrentBuffer) Reset() {
w.buf.Reset() w.buf.Reset()
} }
func newTestChain(t *testing.T, f func(*config.Config), run bool) (*core.Blockchain, *rpcsrv.Server, *network.Server) { func NewTestChain(t *testing.T, f func(*config.Config), run bool) (*core.Blockchain, *rpcsrv.Server, *network.Server) {
configPath := "../config/protocol.unit_testnet.single.yml" configPath := "../../config/protocol.unit_testnet.single.yml"
cfg, err := config.LoadFile(configPath) cfg, err := config.LoadFile(configPath)
require.NoError(t, err, "could not load config") require.NoError(t, err, "could not load config")
if f != nil { if f != nil {
@ -160,17 +169,17 @@ func newTestChain(t *testing.T, f func(*config.Config), run bool) (*core.Blockch
return chain, &rpcServer, netSrv return chain, &rpcServer, netSrv
} }
func newExecutor(t *testing.T, needChain bool) *executor { func NewExecutor(t *testing.T, needChain bool) *Executor {
return newExecutorWithConfig(t, needChain, true, nil) return NewExecutorWithConfig(t, needChain, true, nil)
} }
func newExecutorSuspended(t *testing.T) *executor { func NewExecutorSuspended(t *testing.T) *Executor {
return newExecutorWithConfig(t, true, false, nil) return NewExecutorWithConfig(t, true, false, nil)
} }
func newExecutorWithConfig(t *testing.T, needChain, runChain bool, f func(*config.Config)) *executor { func NewExecutorWithConfig(t *testing.T, needChain, runChain bool, f func(*config.Config)) *Executor {
e := &executor{ e := &Executor{
CLI: newApp(), CLI: app.New(),
Out: NewConcurrentBuffer(), Out: NewConcurrentBuffer(),
Err: bytes.NewBuffer(nil), Err: bytes.NewBuffer(nil),
In: bytes.NewBuffer(nil), In: bytes.NewBuffer(nil),
@ -178,7 +187,7 @@ func newExecutorWithConfig(t *testing.T, needChain, runChain bool, f func(*confi
e.CLI.Writer = e.Out e.CLI.Writer = e.Out
e.CLI.ErrWriter = e.Err e.CLI.ErrWriter = e.Err
if needChain { if needChain {
e.Chain, e.RPC, e.NetSrv = newTestChain(t, f, runChain) e.Chain, e.RPC, e.NetSrv = NewTestChain(t, f, runChain)
} }
t.Cleanup(func() { t.Cleanup(func() {
e.Close(t) e.Close(t)
@ -186,7 +195,7 @@ func newExecutorWithConfig(t *testing.T, needChain, runChain bool, f func(*confi
return e return e
} }
func (e *executor) Close(t *testing.T) { func (e *Executor) Close(t *testing.T) {
input.Terminal = nil input.Terminal = nil
if e.RPC != nil { if e.RPC != nil {
e.RPC.Shutdown() e.RPC.Shutdown()
@ -202,7 +211,7 @@ func (e *executor) Close(t *testing.T) {
// GetTransaction returns tx with hash h after it has persisted. // GetTransaction returns tx with hash h after it has persisted.
// If it is in mempool, we can just wait for the next block, otherwise // If it is in mempool, we can just wait for the next block, otherwise
// it must be already in chain. 1 second is time per block in a unittest chain. // it must be already in chain. 1 second is time per block in a unittest chain.
func (e *executor) GetTransaction(t *testing.T, h util.Uint256) (*transaction.Transaction, uint32) { func (e *Executor) GetTransaction(t *testing.T, h util.Uint256) (*transaction.Transaction, uint32) {
var tx *transaction.Transaction var tx *transaction.Transaction
var height uint32 var height uint32
require.Eventually(t, func() bool { require.Eventually(t, func() bool {
@ -213,22 +222,22 @@ func (e *executor) GetTransaction(t *testing.T, h util.Uint256) (*transaction.Tr
return tx, height return tx, height
} }
func (e *executor) getNextLine(t *testing.T) string { func (e *Executor) GetNextLine(t *testing.T) string {
line, err := e.Out.ReadString('\n') line, err := e.Out.ReadString('\n')
require.NoError(t, err) require.NoError(t, err)
return strings.TrimSuffix(line, "\n") return strings.TrimSuffix(line, "\n")
} }
func (e *executor) checkNextLine(t *testing.T, expected string) { func (e *Executor) CheckNextLine(t *testing.T, expected string) {
line := e.getNextLine(t) line := e.GetNextLine(t)
e.checkLine(t, line, expected) e.CheckLine(t, line, expected)
} }
func (e *executor) checkLine(t *testing.T, line, expected string) { func (e *Executor) CheckLine(t *testing.T, line, expected string) {
require.Regexp(t, expected, line) require.Regexp(t, expected, line)
} }
func (e *executor) checkEOF(t *testing.T) { func (e *Executor) CheckEOF(t *testing.T) {
_, err := e.Out.ReadString('\n') _, err := e.Out.ReadString('\n')
require.True(t, errors.Is(err, io.EOF)) require.True(t, errors.Is(err, io.EOF))
} }
@ -253,19 +262,19 @@ func checkExit(t *testing.T, ch <-chan int, code int) {
} }
// RunWithError runs command and checks that is exits with error. // RunWithError runs command and checks that is exits with error.
func (e *executor) RunWithError(t *testing.T, args ...string) { func (e *Executor) RunWithError(t *testing.T, args ...string) {
ch := setExitFunc() ch := setExitFunc()
require.Error(t, e.run(args...)) require.Error(t, e.run(args...))
checkExit(t, ch, 1) checkExit(t, ch, 1)
} }
// Run runs command and checks that there were no errors. // Run runs command and checks that there were no errors.
func (e *executor) Run(t *testing.T, args ...string) { func (e *Executor) Run(t *testing.T, args ...string) {
ch := setExitFunc() ch := setExitFunc()
require.NoError(t, e.run(args...)) require.NoError(t, e.run(args...))
checkExit(t, ch, 0) checkExit(t, ch, 0)
} }
func (e *executor) run(args ...string) error { func (e *Executor) run(args ...string) error {
e.Out.Reset() e.Out.Reset()
e.Err.Reset() e.Err.Reset()
input.Terminal = term.NewTerminal(input.ReadWriter{ input.Terminal = term.NewTerminal(input.ReadWriter{
@ -278,7 +287,7 @@ func (e *executor) run(args ...string) error {
return err return err
} }
func (e *executor) checkTxPersisted(t *testing.T, prefix ...string) (*transaction.Transaction, uint32) { func (e *Executor) CheckTxPersisted(t *testing.T, prefix ...string) (*transaction.Transaction, uint32) {
line, err := e.Out.ReadString('\n') line, err := e.Out.ReadString('\n')
require.NoError(t, err) require.NoError(t, err)
@ -297,7 +306,7 @@ func (e *executor) checkTxPersisted(t *testing.T, prefix ...string) (*transactio
return tx, height return tx, height
} }
func generateKeys(t *testing.T, n int) ([]*keys.PrivateKey, keys.PublicKeys) { func GenerateKeys(t *testing.T, n int) ([]*keys.PrivateKey, keys.PublicKeys) {
privs := make([]*keys.PrivateKey, n) privs := make([]*keys.PrivateKey, n)
pubs := make(keys.PublicKeys, n) pubs := make(keys.PublicKeys, n)
for i := range privs { for i := range privs {
@ -308,3 +317,45 @@ func generateKeys(t *testing.T, n int) ([]*keys.PrivateKey, keys.PublicKeys) {
} }
return privs, pubs return privs, pubs
} }
func (e *Executor) CheckTxTestInvokeOutput(t *testing.T, scriptSize int) {
e.CheckNextLine(t, `Hash:\s+`)
e.CheckNextLine(t, `OnChain:\s+false`)
e.CheckNextLine(t, `ValidUntil:\s+\d+`)
e.CheckNextLine(t, `Signer:\s+\w+`)
e.CheckNextLine(t, `SystemFee:\s+(\d|\.)+`)
e.CheckNextLine(t, `NetworkFee:\s+(\d|\.)+`)
e.CheckNextLine(t, `Script:\s+\w+`)
e.CheckScriptDump(t, scriptSize)
}
func (e *Executor) CheckScriptDump(t *testing.T, scriptSize int) {
e.CheckNextLine(t, `INDEX\s+`)
for i := 0; i < scriptSize; i++ {
e.CheckNextLine(t, `\d+\s+\w+`)
}
}
func DeployContract(t *testing.T, e *Executor, inPath, configPath, wallet, address, pass string) util.Uint160 {
config.Version = "0.90.0-test" // Contracts are compiled and we want NEFs to not change from run to run.
tmpDir := t.TempDir()
nefName := filepath.Join(tmpDir, "contract.nef")
manifestName := filepath.Join(tmpDir, "contract.manifest.json")
e.Run(t, "neo-go", "contract", "compile",
"--in", inPath,
"--config", configPath,
"--out", nefName, "--manifest", manifestName)
e.In.WriteString(pass + "\r")
e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", wallet, "--address", address,
"--force",
"--in", nefName, "--manifest", manifestName)
e.CheckTxPersisted(t, "Sent invocation transaction ")
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)
return h
}

View file

@ -183,7 +183,7 @@ func TestRegenerateCLITestwallet_NEO3(t *testing.T) {
if !regenerate { if !regenerate {
return return
} }
const walletPath = "../../cli/testdata/wallets/testwallet_NEO3.json" const walletPath = "../../cli/wallet/testdata/testwallet_NEO3.json"
pubs := getKeys(t) pubs := getKeys(t)
acc1 := getAccount(t, privnetWIFs[0], passwords[0]) acc1 := getAccount(t, privnetWIFs[0], passwords[0])
@ -211,8 +211,8 @@ func TestRegenerateCLIWallet1_solo(t *testing.T) {
const ( const (
walletPath = "../../cli/testdata/wallet1_solo.json" walletPath = "../../cli/testdata/wallet1_solo.json"
verifyWIF = "L3W8gi36Y3KPqyR54VJaE1agH9yPvW2hALNZy1BerDwWce9P9xEy" verifyWIF = "L3W8gi36Y3KPqyR54VJaE1agH9yPvW2hALNZy1BerDwWce9P9xEy"
verifyNEFPath = "../../cli/testdata/verify.nef" verifyNEFPath = "../../cli/smartcontract/testdata/verify.nef"
verifyManifestPath = "../../cli/testdata/verify.manifest.json" verifyManifestPath = "../../cli/smartcontract/testdata/verify.manifest.json"
) )
scrypt := keys.ScryptParams{N: 2, R: 1, P: 1} scrypt := keys.ScryptParams{N: 2, R: 1, P: 1}