neo-go/cli/util/util_test.go
Ekaterina Pavlova d80e14dcbb cli: fix TestAwaitUtilCancelTx failing
Occasionally the block is being accepted right after main transaction
submission. Added two branches into this TestAwaitUtilCancelTx. One
branch handles the case of original transaction acceptance, the
other branch handles the conflicting transaction acceptance.

Close #3365

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
2024-03-22 16:22:11 +03:00

191 lines
6.7 KiB
Go

package util_test
import (
"os"
"path/filepath"
"strings"
"testing"
"time"
"github.com/nspcc-dev/neo-go/internal/testcli"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/stretchr/testify/require"
)
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)
}
func TestUtilOps(t *testing.T) {
e := testcli.NewExecutor(t, false)
base64Str := "EUA="
hexStr := "1140"
check := func(t *testing.T) {
e.CheckNextLine(t, "INDEX.*OPCODE.*PARAMETER")
e.CheckNextLine(t, "PUSH1")
e.CheckNextLine(t, "RET")
e.CheckEOF(t)
}
e.Run(t, "neo-go", "util", "ops", base64Str) // base64
check(t)
e.Run(t, "neo-go", "util", "ops", hexStr) // base64 is checked firstly by default, but it's invalid script if decoded from base64
e.CheckNextLine(t, "INDEX.*OPCODE.*PARAMETER")
e.CheckNextLine(t, ".*ERROR: incorrect opcode")
e.CheckEOF(t)
e.Run(t, "neo-go", "util", "ops", "--hex", hexStr) // explicitly specify hex encoding
check(t)
e.RunWithError(t, "neo-go", "util", "ops", "%&~*") // unknown encoding
tmp := filepath.Join(t.TempDir(), "script_base64.txt")
require.NoError(t, os.WriteFile(tmp, []byte(base64Str), os.ModePerm))
e.Run(t, "neo-go", "util", "ops", "--in", tmp) // base64 from file
check(t)
tmp = filepath.Join(t.TempDir(), "script_hex.txt")
require.NoError(t, os.WriteFile(tmp, []byte(hexStr), os.ModePerm))
e.Run(t, "neo-go", "util", "ops", "--hex", "--in", tmp) // hex from file
check(t)
}
func TestUtilCancelTx(t *testing.T) {
e := testcli.NewExecutorSuspended(t)
w, err := wallet.NewWalletFromFile("../testdata/testwallet.json")
require.NoError(t, err)
transferArgs := []string{
"neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet,
"--to", w.Accounts[0].Address,
"--token", "NEO",
"--from", testcli.ValidatorAddr,
"--force",
}
args := []string{"neo-go", "util", "canceltx",
"-r", "http://" + e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet,
"--address", testcli.ValidatorAddr}
e.In.WriteString("one\r")
e.Run(t, append(transferArgs, "--amount", "1")...)
line := e.GetNextLine(t)
txHash, err := util.Uint256DecodeStringLE(line)
require.NoError(t, err)
_, ok := e.Chain.GetMemPool().TryGetValue(txHash)
require.True(t, ok)
t.Run("invalid", func(t *testing.T) {
t.Run("missing tx argument", func(t *testing.T) {
e.RunWithError(t, args...)
})
t.Run("excessive arguments", func(t *testing.T) {
e.RunWithError(t, append(args, txHash.StringLE(), txHash.StringLE())...)
})
t.Run("invalid hash", func(t *testing.T) {
e.RunWithError(t, append(args, "notahash")...)
})
t.Run("not signed by main signer", func(t *testing.T) {
e.In.WriteString("one\r")
e.RunWithError(t, "neo-go", "util", "canceltx",
"-r", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet,
"--address", testcli.MultisigAddr, txHash.StringLE())
})
t.Run("wrong rpc endpoint", func(t *testing.T) {
e.In.WriteString("one\r")
e.RunWithError(t, "neo-go", "util", "canceltx",
"-r", "http://localhost:20331",
"--wallet", testcli.ValidatorWallet, txHash.StringLE())
})
})
e.In.WriteString("one\r")
e.Run(t, append(args, txHash.StringLE())...)
resHash, err := util.Uint256DecodeStringLE(e.GetNextLine(t))
require.NoError(t, err)
_, _, err = e.Chain.GetTransaction(resHash)
require.NoError(t, err)
e.CheckEOF(t)
go e.Chain.Run()
require.Eventually(t, func() bool {
_, aerErr := e.Chain.GetAppExecResults(resHash, trigger.Application)
return aerErr == nil
}, time.Second*2, time.Millisecond*50)
}
func TestAwaitUtilCancelTx(t *testing.T) {
e := testcli.NewExecutor(t, true)
w, err := wallet.NewWalletFromFile("../testdata/testwallet.json")
require.NoError(t, err)
transferArgs := []string{
"neo-go", "wallet", "nep17", "transfer",
"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet,
"--to", w.Accounts[0].Address,
"--token", "NEO",
"--from", testcli.ValidatorAddr,
"--force",
}
args := []string{"neo-go", "util", "canceltx",
"-r", "http://" + e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet,
"--address", testcli.ValidatorAddr,
"--await"}
e.In.WriteString("one\r")
e.Run(t, append(transferArgs, "--amount", "1")...)
line := e.GetNextLine(t)
txHash, err := util.Uint256DecodeStringLE(line)
require.NoError(t, err)
_, ok := e.Chain.GetMemPool().TryGetValue(txHash)
require.True(t, ok)
e.In.WriteString("one\r")
e.Run(t, append(args, txHash.StringLE())...)
response := e.GetNextLine(t)
if strings.Contains(response, "Conflicting transaction accepted") {
resHash, _ := e.CheckAwaitableTxPersisted(t)
require.Eventually(t, func() bool {
_, aerErr := e.Chain.GetAppExecResults(resHash.Hash(), trigger.Application)
return aerErr == nil
}, time.Second*2, time.Millisecond*50)
} else if strings.Contains(response, "Target transaction accepted") {
require.Eventually(t, func() bool {
_, _, err := e.Chain.GetTransaction(txHash)
require.NoError(t, err, "original transaction should be on chain")
_, aerErr := e.Chain.GetAppExecResults(txHash, trigger.Application)
return aerErr == nil
}, time.Second*2, time.Millisecond*50)
} else {
t.Fatalf("unexpected response: %s", response)
}
}