github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/unwrap/unwrap_test.go (about) 1 package unwrap 2 3 import ( 4 "encoding/json" 5 "errors" 6 "math" 7 "math/big" 8 "testing" 9 10 "github.com/google/uuid" 11 "github.com/nspcc-dev/neo-go/pkg/core/state" 12 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 13 "github.com/nspcc-dev/neo-go/pkg/neorpc/result" 14 "github.com/nspcc-dev/neo-go/pkg/util" 15 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 16 "github.com/stretchr/testify/require" 17 ) 18 19 func TestStdErrors(t *testing.T) { 20 funcs := []func(r *result.Invoke, err error) (any, error){ 21 func(r *result.Invoke, err error) (any, error) { 22 return BigInt(r, err) 23 }, 24 func(r *result.Invoke, err error) (any, error) { 25 return Bool(r, err) 26 }, 27 func(r *result.Invoke, err error) (any, error) { 28 return Int64(r, err) 29 }, 30 func(r *result.Invoke, err error) (any, error) { 31 return LimitedInt64(r, err, 0, 1) 32 }, 33 func(r *result.Invoke, err error) (any, error) { 34 return Bytes(r, err) 35 }, 36 func(r *result.Invoke, err error) (any, error) { 37 return UTF8String(r, err) 38 }, 39 func(r *result.Invoke, err error) (any, error) { 40 return PrintableASCIIString(r, err) 41 }, 42 func(r *result.Invoke, err error) (any, error) { 43 return Uint160(r, err) 44 }, 45 func(r *result.Invoke, err error) (any, error) { 46 return Uint256(r, err) 47 }, 48 func(r *result.Invoke, err error) (any, error) { 49 return PublicKey(r, err) 50 }, 51 func(r *result.Invoke, err error) (any, error) { 52 _, _, err = SessionIterator(r, err) 53 return nil, err 54 }, 55 func(r *result.Invoke, err error) (any, error) { 56 _, _, _, err = ArrayAndSessionIterator(r, err) 57 return nil, err 58 }, 59 func(r *result.Invoke, err error) (any, error) { 60 return Array(r, err) 61 }, 62 func(r *result.Invoke, err error) (any, error) { 63 return ArrayOfBools(r, err) 64 }, 65 func(r *result.Invoke, err error) (any, error) { 66 return ArrayOfBigInts(r, err) 67 }, 68 func(r *result.Invoke, err error) (any, error) { 69 return ArrayOfBytes(r, err) 70 }, 71 func(r *result.Invoke, err error) (any, error) { 72 return ArrayOfUTF8Strings(r, err) 73 }, 74 func(r *result.Invoke, err error) (any, error) { 75 return ArrayOfUint160(r, err) 76 }, 77 func(r *result.Invoke, err error) (any, error) { 78 return ArrayOfUint256(r, err) 79 }, 80 func(r *result.Invoke, err error) (any, error) { 81 return ArrayOfPublicKeys(r, err) 82 }, 83 func(r *result.Invoke, err error) (any, error) { 84 return Map(r, err) 85 }, 86 } 87 t.Run("error on input", func(t *testing.T) { 88 for _, f := range funcs { 89 _, err := f(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, errors.New("some")) 90 require.Error(t, err) 91 } 92 }) 93 94 t.Run("FAULT state", func(t *testing.T) { 95 for _, f := range funcs { 96 _, err := f(&result.Invoke{State: "FAULT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 97 require.Error(t, err) 98 99 var fault Exception 100 require.True(t, errors.As(err, &fault)) 101 require.Equal(t, "", string(fault)) 102 } 103 }) 104 t.Run("FAULT state with exception", func(t *testing.T) { 105 for _, f := range funcs { 106 _, err := f(&result.Invoke{State: "FAULT", FaultException: "something bad", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 107 require.Error(t, err) 108 109 var fault Exception 110 require.True(t, errors.As(err, &fault)) 111 require.Equal(t, "something bad", string(fault)) 112 } 113 }) 114 t.Run("nothing returned", func(t *testing.T) { 115 for _, f := range funcs { 116 _, err := f(&result.Invoke{State: "HALT"}, errors.New("some")) 117 require.Error(t, err) 118 } 119 }) 120 t.Run("HALT state with empty stack", func(t *testing.T) { 121 for _, f := range funcs { 122 _, err := f(&result.Invoke{State: "HALT"}, nil) 123 require.Error(t, err) 124 } 125 }) 126 t.Run("multiple return values", func(t *testing.T) { 127 for _, f := range funcs { 128 _, err := f(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42), stackitem.Make(42)}}, nil) 129 require.Error(t, err) 130 } 131 }) 132 } 133 134 func TestBigInt(t *testing.T) { 135 _, err := BigInt(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{})}}, nil) 136 require.Error(t, err) 137 138 i, err := BigInt(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 139 require.NoError(t, err) 140 require.Equal(t, big.NewInt(42), i) 141 } 142 143 func TestBool(t *testing.T) { 144 _, err := Bool(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make("0x03c564ed28ba3d50beb1a52dcb751b929e1d747281566bd510363470be186bc0")}}, nil) 145 require.Error(t, err) 146 147 b, err := Bool(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(true)}}, nil) 148 require.NoError(t, err) 149 require.True(t, b) 150 } 151 152 func TestNothing(t *testing.T) { 153 // Error on input. 154 err := Nothing(&result.Invoke{State: "HALT", Stack: []stackitem.Item{}}, errors.New("some")) 155 require.Error(t, err) 156 157 // Nonempty stack. 158 err = Nothing(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 159 require.Error(t, err) 160 161 // FAULT state. 162 err = Nothing(&result.Invoke{State: "FAULT", Stack: []stackitem.Item{}}, nil) 163 require.Error(t, err) 164 165 // Positive. 166 err = Nothing(&result.Invoke{State: "HALT", Stack: []stackitem.Item{}}, nil) 167 require.NoError(t, err) 168 } 169 170 func TestInt64(t *testing.T) { 171 _, err := Int64(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make("0x03c564ed28ba3d50beb1a52dcb751b929e1d747281566bd510363470be186bc0")}}, nil) 172 require.Error(t, err) 173 174 _, err = Int64(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(uint64(math.MaxUint64))}}, nil) 175 require.Error(t, err) 176 177 i, err := Int64(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 178 require.NoError(t, err) 179 require.Equal(t, int64(42), i) 180 } 181 182 func TestLimitedInt64(t *testing.T) { 183 _, err := LimitedInt64(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make("0x03c564ed28ba3d50beb1a52dcb751b929e1d747281566bd510363470be186bc0")}}, nil, math.MinInt64, math.MaxInt64) 184 require.Error(t, err) 185 186 _, err = LimitedInt64(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(uint64(math.MaxUint64))}}, nil, math.MinInt64, math.MaxInt64) 187 require.Error(t, err) 188 189 _, err = LimitedInt64(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil, 128, 256) 190 require.Error(t, err) 191 192 _, err = LimitedInt64(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil, 0, 40) 193 require.Error(t, err) 194 195 i, err := LimitedInt64(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil, 0, 128) 196 require.NoError(t, err) 197 require.Equal(t, int64(42), i) 198 } 199 200 func TestBytes(t *testing.T) { 201 _, err := Bytes(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{})}}, nil) 202 require.Error(t, err) 203 204 b, err := Bytes(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]byte{1, 2, 3})}}, nil) 205 require.NoError(t, err) 206 require.Equal(t, []byte{1, 2, 3}, b) 207 } 208 209 func TestItemJSONError(t *testing.T) { 210 bigValidSlice := stackitem.NewByteArray(make([]byte, stackitem.MaxSize-1)) 211 res := &result.Invoke{ 212 State: "HALT", 213 GasConsumed: 237626000, 214 Script: []byte{10}, 215 Stack: []stackitem.Item{bigValidSlice, bigValidSlice}, 216 FaultException: "", 217 Notifications: []state.NotificationEvent{}, 218 } 219 data, err := json.Marshal(res) 220 require.NoError(t, err) 221 222 var received result.Invoke 223 require.NoError(t, json.Unmarshal(data, &received)) 224 require.True(t, len(received.FaultException) != 0) 225 226 _, err = Item(&received, nil) 227 var fault Exception 228 require.True(t, errors.As(err, &fault)) 229 require.Equal(t, received.FaultException, string(fault)) 230 } 231 232 func TestUTF8String(t *testing.T) { 233 _, err := UTF8String(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{})}}, nil) 234 require.Error(t, err) 235 236 _, err = UTF8String(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make("\xff")}}, nil) 237 require.Error(t, err) 238 239 s, err := UTF8String(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make("value")}}, nil) 240 require.NoError(t, err) 241 require.Equal(t, "value", s) 242 } 243 244 func TestPrintableASCIIString(t *testing.T) { 245 _, err := PrintableASCIIString(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{})}}, nil) 246 require.Error(t, err) 247 248 _, err = PrintableASCIIString(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make("\xff")}}, nil) 249 require.Error(t, err) 250 251 _, err = PrintableASCIIString(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make("\n\r")}}, nil) 252 require.Error(t, err) 253 254 s, err := PrintableASCIIString(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make("value")}}, nil) 255 require.NoError(t, err) 256 require.Equal(t, "value", s) 257 } 258 259 func TestUint160(t *testing.T) { 260 _, err := Uint160(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(util.Uint256{1, 2, 3}.BytesBE())}}, nil) 261 require.Error(t, err) 262 263 u, err := Uint160(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(util.Uint160{1, 2, 3}.BytesBE())}}, nil) 264 require.NoError(t, err) 265 require.Equal(t, util.Uint160{1, 2, 3}, u) 266 } 267 268 func TestUint256(t *testing.T) { 269 _, err := Uint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(util.Uint160{1, 2, 3}.BytesBE())}}, nil) 270 require.Error(t, err) 271 272 u, err := Uint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(util.Uint256{1, 2, 3}.BytesBE())}}, nil) 273 require.NoError(t, err) 274 require.Equal(t, util.Uint256{1, 2, 3}, u) 275 } 276 277 func TestPublicKey(t *testing.T) { 278 k, err := keys.NewPrivateKey() 279 require.NoError(t, err) 280 281 _, err = PublicKey(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(util.Uint160{1, 2, 3}.BytesBE())}}, nil) 282 require.Error(t, err) 283 284 pk, err := PublicKey(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(k.PublicKey().Bytes())}}, nil) 285 require.NoError(t, err) 286 require.Equal(t, k.PublicKey(), pk) 287 } 288 289 func TestSessionIterator(t *testing.T) { 290 _, _, err := SessionIterator(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 291 require.Error(t, err) 292 293 _, _, err = SessionIterator(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.NewInterop(42)}}, nil) 294 require.Error(t, err) 295 296 iid := uuid.New() 297 iter := result.Iterator{ID: &iid} 298 _, _, err = SessionIterator(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.NewInterop(iter)}}, nil) 299 require.Error(t, err) 300 301 sid := uuid.New() 302 rs, ri, err := SessionIterator(&result.Invoke{Session: sid, State: "HALT", Stack: []stackitem.Item{stackitem.NewInterop(iter)}}, nil) 303 require.NoError(t, err) 304 require.Equal(t, sid, rs) 305 require.Equal(t, iter, ri) 306 } 307 308 func TestArraySessionIterator(t *testing.T) { 309 _, _, _, err := ArrayAndSessionIterator(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 310 require.Error(t, err) 311 312 _, _, _, err = ArrayAndSessionIterator(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.NewInterop(42)}}, nil) 313 require.Error(t, err) 314 315 arr := stackitem.NewArray([]stackitem.Item{stackitem.Make(42)}) 316 ra, rs, ri, err := ArrayAndSessionIterator(&result.Invoke{State: "HALT", Stack: []stackitem.Item{arr}}, nil) 317 require.NoError(t, err) 318 require.Equal(t, arr.Value(), ra) 319 require.Empty(t, rs) 320 require.Empty(t, ri) 321 322 _, _, _, err = ArrayAndSessionIterator(&result.Invoke{State: "HALT", Stack: []stackitem.Item{arr, stackitem.NewInterop(42)}}, nil) 323 require.Error(t, err) 324 325 iid := uuid.New() 326 iter := result.Iterator{ID: &iid} 327 _, _, _, err = ArrayAndSessionIterator(&result.Invoke{State: "HALT", Stack: []stackitem.Item{arr, stackitem.NewInterop(iter)}}, nil) 328 require.ErrorIs(t, err, ErrNoSessionID) 329 330 sid := uuid.New() 331 _, rs, ri, err = ArrayAndSessionIterator(&result.Invoke{Session: sid, State: "HALT", Stack: []stackitem.Item{arr, stackitem.NewInterop(iter)}}, nil) 332 require.NoError(t, err) 333 require.Equal(t, arr.Value(), ra) 334 require.Equal(t, sid, rs) 335 require.Equal(t, iter, ri) 336 337 _, _, _, err = ArrayAndSessionIterator(&result.Invoke{Session: sid, State: "HALT", Stack: []stackitem.Item{arr, stackitem.NewInterop(iter), stackitem.Make(42)}}, nil) 338 require.Error(t, err) 339 } 340 341 func TestArray(t *testing.T) { 342 _, err := Array(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 343 require.Error(t, err) 344 345 a, err := Array(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(42)})}}, nil) 346 require.NoError(t, err) 347 require.Equal(t, 1, len(a)) 348 require.Equal(t, stackitem.Make(42), a[0]) 349 } 350 351 func TestArrayOfBools(t *testing.T) { 352 _, err := ArrayOfBools(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 353 require.Error(t, err) 354 355 _, err = ArrayOfBools(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make("reallybigstringthatcantbeanumberandthuscantbeconvertedtobool")})}}, nil) 356 require.Error(t, err) 357 358 a, err := ArrayOfBools(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(true)})}}, nil) 359 require.NoError(t, err) 360 require.Equal(t, 1, len(a)) 361 require.Equal(t, true, a[0]) 362 } 363 364 func TestArrayOfBigInts(t *testing.T) { 365 _, err := ArrayOfBigInts(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 366 require.Error(t, err) 367 368 _, err = ArrayOfBigInts(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil) 369 require.Error(t, err) 370 371 a, err := ArrayOfBigInts(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(42)})}}, nil) 372 require.NoError(t, err) 373 require.Equal(t, 1, len(a)) 374 require.Equal(t, big.NewInt(42), a[0]) 375 } 376 377 func TestArrayOfBytes(t *testing.T) { 378 _, err := ArrayOfBytes(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 379 require.Error(t, err) 380 381 _, err = ArrayOfBytes(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil) 382 require.Error(t, err) 383 384 a, err := ArrayOfBytes(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]byte("some"))})}}, nil) 385 require.NoError(t, err) 386 require.Equal(t, 1, len(a)) 387 require.Equal(t, []byte("some"), a[0]) 388 } 389 390 func TestArrayOfUTF8Strings(t *testing.T) { 391 _, err := ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 392 require.Error(t, err) 393 394 _, err = ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil) 395 require.Error(t, err) 396 397 _, err = ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]byte{0, 0xff})})}}, nil) 398 require.Error(t, err) 399 400 a, err := ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make("some")})}}, nil) 401 require.NoError(t, err) 402 require.Equal(t, 1, len(a)) 403 require.Equal(t, "some", a[0]) 404 } 405 406 func TestArrayOfUint160(t *testing.T) { 407 _, err := ArrayOfUint160(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 408 require.Error(t, err) 409 410 _, err = ArrayOfUint160(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil) 411 require.Error(t, err) 412 413 _, err = ArrayOfUint160(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]byte("some"))})}}, nil) 414 require.Error(t, err) 415 416 u160 := util.Uint160{1, 2, 3} 417 uints, err := ArrayOfUint160(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(u160.BytesBE())})}}, nil) 418 require.NoError(t, err) 419 require.Equal(t, 1, len(uints)) 420 require.Equal(t, u160, uints[0]) 421 } 422 423 func TestArrayOfUint256(t *testing.T) { 424 _, err := ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 425 require.Error(t, err) 426 427 _, err = ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil) 428 require.Error(t, err) 429 430 _, err = ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]byte("some"))})}}, nil) 431 require.Error(t, err) 432 433 u256 := util.Uint256{1, 2, 3} 434 uints, err := ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(u256.BytesBE())})}}, nil) 435 require.NoError(t, err) 436 require.Equal(t, 1, len(uints)) 437 require.Equal(t, u256, uints[0]) 438 } 439 440 func TestArrayOfPublicKeys(t *testing.T) { 441 _, err := ArrayOfPublicKeys(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 442 require.Error(t, err) 443 444 _, err = ArrayOfPublicKeys(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil) 445 require.Error(t, err) 446 447 _, err = ArrayOfPublicKeys(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]byte("some"))})}}, nil) 448 require.Error(t, err) 449 450 k, err := keys.NewPrivateKey() 451 require.NoError(t, err) 452 453 pks, err := ArrayOfPublicKeys(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(k.PublicKey().Bytes())})}}, nil) 454 require.NoError(t, err) 455 require.Equal(t, 1, len(pks)) 456 require.Equal(t, k.PublicKey(), pks[0]) 457 } 458 459 func TestMap(t *testing.T) { 460 _, err := Map(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil) 461 require.Error(t, err) 462 463 m, err := Map(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.NewMapWithValue([]stackitem.MapElement{{Key: stackitem.Make(42), Value: stackitem.Make("string")}})}}, nil) 464 require.NoError(t, err) 465 require.Equal(t, 1, m.Len()) 466 require.Equal(t, 0, m.Index(stackitem.Make(42))) 467 }