package cmdargs import ( "encoding/hex" "strings" "testing" "github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" ) func TestParseCosigner(t *testing.T) { acc := util.Uint160{1, 3, 5, 7} c1, c2 := random.Uint160(), random.Uint160() priv, err := keys.NewPrivateKey() require.NoError(t, err) testCases := map[string]transaction.Signer{ acc.StringLE(): { Account: acc, Scopes: transaction.CalledByEntry, }, "0x" + acc.StringLE(): { Account: acc, Scopes: transaction.CalledByEntry, }, acc.StringLE() + ":Global": { Account: acc, Scopes: transaction.Global, }, acc.StringLE() + ":CalledByEntry": { Account: acc, Scopes: transaction.CalledByEntry, }, acc.StringLE() + ":None": { Account: acc, Scopes: transaction.None, }, acc.StringLE() + ":CalledByEntry,CustomContracts:" + c1.StringLE() + ":0x" + c2.StringLE(): { Account: acc, Scopes: transaction.CalledByEntry | transaction.CustomContracts, AllowedContracts: []util.Uint160{c1, c2}, }, acc.StringLE() + ":CustomGroups:" + hex.EncodeToString(priv.PublicKey().Bytes()): { Account: acc, Scopes: transaction.CustomGroups, AllowedGroups: keys.PublicKeys{priv.PublicKey()}, }, } for s, expected := range testCases { actual, err := parseCosigner(s) require.NoError(t, err) require.Equal(t, expected, actual, s) } errorCases := []string{ acc.StringLE() + "0", acc.StringLE() + ":Unknown", acc.StringLE() + ":Global,CustomContracts", acc.StringLE() + ":Global,None", acc.StringLE() + ":CustomContracts:" + acc.StringLE() + ",Global", acc.StringLE() + ":CustomContracts", acc.StringLE() + ":CustomContracts:xxx", acc.StringLE() + ":CustomGroups", acc.StringLE() + ":CustomGroups:xxx", } for _, s := range errorCases { _, err := parseCosigner(s) require.Error(t, err, s) } } func TestParseParams_CalledFromItself(t *testing.T) { testCases := map[string]struct { WordsRead int Value []smartcontract.Parameter }{ "]": { WordsRead: 1, Value: []smartcontract.Parameter{}, }, "[ [ ] ] ]": { WordsRead: 5, Value: []smartcontract.Parameter{ { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{}, }, }, }, }, }, "a b c ]": { WordsRead: 4, Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "a", }, { Type: smartcontract.StringType, Value: "b", }, { Type: smartcontract.StringType, Value: "c", }, }, }, "a [ b [ [ c d ] e ] ] f ] extra items": { WordsRead: 13, // the method should return right after the last bracket, as calledFromMain == false Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "a", }, { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "b", }, { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "c", }, { Type: smartcontract.StringType, Value: "d", }, }, }, { Type: smartcontract.StringType, Value: "e", }, }, }, }, }, { Type: smartcontract.StringType, Value: "f", }, }, }, } for str, expected := range testCases { input := strings.Split(str, " ") offset, actual, err := ParseParams(input, false) require.NoError(t, err) require.Equal(t, expected.WordsRead, offset) require.Equal(t, expected.Value, actual) } errorCases := []string{ "[ ]", "[ a b [ c ] d ]", "[ ] --", "--", "not-int:integer ]", } for _, str := range errorCases { input := strings.Split(str, " ") _, _, err := ParseParams(input, false) require.Error(t, err) } } func TestParseParams_CalledFromOutside(t *testing.T) { testCases := map[string]struct { WordsRead int Parameters []smartcontract.Parameter }{ "-- cosigner1": { WordsRead: 1, // the `--` only Parameters: []smartcontract.Parameter{}, }, "a b c": { WordsRead: 3, Parameters: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "a", }, { Type: smartcontract.StringType, Value: "b", }, { Type: smartcontract.StringType, Value: "c", }, }, }, "a b c -- cosigner1": { WordsRead: 4, Parameters: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "a", }, { Type: smartcontract.StringType, Value: "b", }, { Type: smartcontract.StringType, Value: "c", }, }, }, "a [ b [ [ c d ] e ] ] f": { WordsRead: 12, Parameters: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "a", }, { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "b", }, { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "c", }, { Type: smartcontract.StringType, Value: "d", }, }, }, { Type: smartcontract.StringType, Value: "e", }, }, }, }, }, { Type: smartcontract.StringType, Value: "f", }, }, }, "a [ b ] -- cosigner1 cosigner2": { WordsRead: 5, Parameters: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "a", }, { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "b", }, }, }, }, }, "a [ b ]": { WordsRead: 4, Parameters: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "a", }, { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "b", }, }, }, }, }, "a [ b ] [ [ c ] ] [ [ [ d ] ] ]": { WordsRead: 16, Parameters: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "a", }, { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "b", }, }, }, { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "c", }, }, }, }, }, { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.ArrayType, Value: []smartcontract.Parameter{ { Type: smartcontract.StringType, Value: "d", }, }, }, }, }, }, }, }, }, } for str, expected := range testCases { input := strings.Split(str, " ") offset, arr, err := ParseParams(input, true) require.NoError(t, err) require.Equal(t, expected.WordsRead, offset) require.Equal(t, expected.Parameters, arr) } errorCases := []string{ "[", "]", "[ [ ]", "[ [ ] --", "[ -- ]", } for _, str := range errorCases { input := strings.Split(str, " ") _, _, err := ParseParams(input, true) require.Error(t, err) } }