github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/cli/cmdargs/parser_test.go (about) 1 package cmdargs 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/nspcc-dev/neo-go/internal/random" 8 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 9 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 10 "github.com/nspcc-dev/neo-go/pkg/smartcontract" 11 "github.com/nspcc-dev/neo-go/pkg/util" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func TestParseCosigner(t *testing.T) { 16 acc := util.Uint160{1, 3, 5, 7} 17 c1, c2 := random.Uint160(), random.Uint160() 18 priv, err := keys.NewPrivateKey() 19 require.NoError(t, err) 20 21 testCases := map[string]transaction.Signer{ 22 acc.StringLE(): { 23 Account: acc, 24 Scopes: transaction.CalledByEntry, 25 }, 26 "0x" + acc.StringLE(): { 27 Account: acc, 28 Scopes: transaction.CalledByEntry, 29 }, 30 acc.StringLE() + ":Global": { 31 Account: acc, 32 Scopes: transaction.Global, 33 }, 34 acc.StringLE() + ":CalledByEntry": { 35 Account: acc, 36 Scopes: transaction.CalledByEntry, 37 }, 38 acc.StringLE() + ":None": { 39 Account: acc, 40 Scopes: transaction.None, 41 }, 42 acc.StringLE() + ":CalledByEntry,CustomContracts:" + c1.StringLE() + ":0x" + c2.StringLE(): { 43 Account: acc, 44 Scopes: transaction.CalledByEntry | transaction.CustomContracts, 45 AllowedContracts: []util.Uint160{c1, c2}, 46 }, 47 acc.StringLE() + ":CustomGroups:" + priv.PublicKey().StringCompressed(): { 48 Account: acc, 49 Scopes: transaction.CustomGroups, 50 AllowedGroups: keys.PublicKeys{priv.PublicKey()}, 51 }, 52 } 53 for s, expected := range testCases { 54 actual, err := parseCosigner(s) 55 require.NoError(t, err) 56 require.Equal(t, expected, actual, s) 57 } 58 errorCases := []string{ 59 acc.StringLE() + "0", 60 acc.StringLE() + ":Unknown", 61 acc.StringLE() + ":Global,CustomContracts", 62 acc.StringLE() + ":Global,None", 63 acc.StringLE() + ":CustomContracts:" + acc.StringLE() + ",Global", 64 acc.StringLE() + ":CustomContracts", 65 acc.StringLE() + ":CustomContracts:xxx", 66 acc.StringLE() + ":CustomGroups", 67 acc.StringLE() + ":CustomGroups:xxx", 68 } 69 for _, s := range errorCases { 70 _, err := parseCosigner(s) 71 require.Error(t, err, s) 72 } 73 } 74 75 func TestParseParams_CalledFromItself(t *testing.T) { 76 testCases := map[string]struct { 77 WordsRead int 78 Value []smartcontract.Parameter 79 }{ 80 "]": { 81 WordsRead: 1, 82 Value: []smartcontract.Parameter{}, 83 }, 84 "[ [ ] ] ]": { 85 WordsRead: 5, 86 Value: []smartcontract.Parameter{ 87 { 88 Type: smartcontract.ArrayType, 89 Value: []smartcontract.Parameter{ 90 { 91 Type: smartcontract.ArrayType, 92 Value: []smartcontract.Parameter{}, 93 }, 94 }, 95 }, 96 }, 97 }, 98 "a b c ]": { 99 WordsRead: 4, 100 Value: []smartcontract.Parameter{ 101 { 102 Type: smartcontract.StringType, 103 Value: "a", 104 }, 105 { 106 Type: smartcontract.StringType, 107 Value: "b", 108 }, 109 { 110 Type: smartcontract.StringType, 111 Value: "c", 112 }, 113 }, 114 }, 115 "a [ b [ [ c d ] e ] ] f ] extra items": { 116 WordsRead: 13, // the method should return right after the last bracket, as calledFromMain == false 117 Value: []smartcontract.Parameter{ 118 { 119 Type: smartcontract.StringType, 120 Value: "a", 121 }, 122 { 123 Type: smartcontract.ArrayType, 124 Value: []smartcontract.Parameter{ 125 { 126 Type: smartcontract.StringType, 127 Value: "b", 128 }, 129 { 130 Type: smartcontract.ArrayType, 131 Value: []smartcontract.Parameter{ 132 { 133 Type: smartcontract.ArrayType, 134 Value: []smartcontract.Parameter{ 135 { 136 Type: smartcontract.StringType, 137 Value: "c", 138 }, 139 { 140 Type: smartcontract.StringType, 141 Value: "d", 142 }, 143 }, 144 }, 145 { 146 Type: smartcontract.StringType, 147 Value: "e", 148 }, 149 }, 150 }, 151 }, 152 }, 153 { 154 Type: smartcontract.StringType, 155 Value: "f", 156 }, 157 }, 158 }, 159 } 160 161 for str, expected := range testCases { 162 input := strings.Split(str, " ") 163 offset, actual, err := ParseParams(input, false) 164 require.NoError(t, err) 165 require.Equal(t, expected.WordsRead, offset) 166 require.Equal(t, expected.Value, actual) 167 } 168 169 errorCases := []string{ 170 "[ ]", 171 "[ a b [ c ] d ]", 172 "[ ] --", 173 "--", 174 "not-int:integer ]", 175 } 176 177 for _, str := range errorCases { 178 input := strings.Split(str, " ") 179 _, _, err := ParseParams(input, false) 180 require.Error(t, err) 181 } 182 } 183 184 func TestParseParams_CalledFromOutside(t *testing.T) { 185 testCases := map[string]struct { 186 WordsRead int 187 Parameters []smartcontract.Parameter 188 }{ 189 "-- cosigner1": { 190 WordsRead: 1, // the `--` only 191 Parameters: []smartcontract.Parameter{}, 192 }, 193 "a b c": { 194 WordsRead: 3, 195 Parameters: []smartcontract.Parameter{ 196 { 197 Type: smartcontract.StringType, 198 Value: "a", 199 }, 200 { 201 Type: smartcontract.StringType, 202 Value: "b", 203 }, 204 { 205 Type: smartcontract.StringType, 206 Value: "c", 207 }, 208 }, 209 }, 210 "a b c -- cosigner1": { 211 WordsRead: 4, 212 Parameters: []smartcontract.Parameter{ 213 { 214 Type: smartcontract.StringType, 215 Value: "a", 216 }, 217 { 218 Type: smartcontract.StringType, 219 Value: "b", 220 }, 221 { 222 Type: smartcontract.StringType, 223 Value: "c", 224 }, 225 }, 226 }, 227 "a [ b [ [ c d ] e ] ] f": { 228 WordsRead: 12, 229 Parameters: []smartcontract.Parameter{ 230 { 231 Type: smartcontract.StringType, 232 Value: "a", 233 }, 234 { 235 Type: smartcontract.ArrayType, 236 Value: []smartcontract.Parameter{ 237 { 238 Type: smartcontract.StringType, 239 Value: "b", 240 }, 241 { 242 Type: smartcontract.ArrayType, 243 Value: []smartcontract.Parameter{ 244 { 245 Type: smartcontract.ArrayType, 246 Value: []smartcontract.Parameter{ 247 { 248 Type: smartcontract.StringType, 249 Value: "c", 250 }, 251 { 252 Type: smartcontract.StringType, 253 Value: "d", 254 }, 255 }, 256 }, 257 { 258 Type: smartcontract.StringType, 259 Value: "e", 260 }, 261 }, 262 }, 263 }, 264 }, 265 { 266 Type: smartcontract.StringType, 267 Value: "f", 268 }, 269 }, 270 }, 271 "a [ b ] -- cosigner1 cosigner2": { 272 WordsRead: 5, 273 Parameters: []smartcontract.Parameter{ 274 { 275 Type: smartcontract.StringType, 276 Value: "a", 277 }, 278 { 279 Type: smartcontract.ArrayType, 280 Value: []smartcontract.Parameter{ 281 { 282 Type: smartcontract.StringType, 283 Value: "b", 284 }, 285 }, 286 }, 287 }, 288 }, 289 "a [ b ]": { 290 WordsRead: 4, 291 Parameters: []smartcontract.Parameter{ 292 { 293 Type: smartcontract.StringType, 294 Value: "a", 295 }, 296 { 297 Type: smartcontract.ArrayType, 298 Value: []smartcontract.Parameter{ 299 { 300 Type: smartcontract.StringType, 301 Value: "b", 302 }, 303 }, 304 }, 305 }, 306 }, 307 "a [ b ] [ [ c ] ] [ [ [ d ] ] ]": { 308 WordsRead: 16, 309 Parameters: []smartcontract.Parameter{ 310 { 311 Type: smartcontract.StringType, 312 Value: "a", 313 }, 314 { 315 Type: smartcontract.ArrayType, 316 Value: []smartcontract.Parameter{ 317 { 318 Type: smartcontract.StringType, 319 Value: "b", 320 }, 321 }, 322 }, 323 { 324 Type: smartcontract.ArrayType, 325 Value: []smartcontract.Parameter{ 326 { 327 Type: smartcontract.ArrayType, 328 Value: []smartcontract.Parameter{ 329 { 330 Type: smartcontract.StringType, 331 Value: "c", 332 }, 333 }, 334 }, 335 }, 336 }, 337 { 338 Type: smartcontract.ArrayType, 339 Value: []smartcontract.Parameter{ 340 { 341 Type: smartcontract.ArrayType, 342 Value: []smartcontract.Parameter{ 343 { 344 Type: smartcontract.ArrayType, 345 Value: []smartcontract.Parameter{ 346 { 347 Type: smartcontract.StringType, 348 Value: "d", 349 }, 350 }, 351 }, 352 }, 353 }, 354 }, 355 }, 356 }, 357 }, 358 } 359 for str, expected := range testCases { 360 input := strings.Split(str, " ") 361 offset, arr, err := ParseParams(input, true) 362 require.NoError(t, err) 363 require.Equal(t, expected.WordsRead, offset) 364 require.Equal(t, expected.Parameters, arr) 365 } 366 367 errorCases := []string{ 368 "[", 369 "]", 370 "[ [ ]", 371 "[ [ ] --", 372 "[ -- ]", 373 } 374 for _, str := range errorCases { 375 input := strings.Split(str, " ") 376 _, _, err := ParseParams(input, true) 377 require.Error(t, err) 378 } 379 }