github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/vm/stack_test.go (about) 1 package vm 2 3 import ( 4 "math/big" 5 "testing" 6 7 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestPushElement(t *testing.T) { 13 elems := makeElements(10) 14 s := NewStack("test") 15 for _, elem := range elems { 16 s.Push(elem) 17 } 18 19 assert.Equal(t, len(elems), s.Len()) 20 21 for i := 0; i < len(elems); i++ { 22 assert.Equal(t, elems[len(elems)-1-i], s.Peek(i)) 23 } 24 } 25 26 func TestStack_PushVal(t *testing.T) { 27 type ( 28 i32 int32 29 testByte uint8 30 ) 31 32 s := NewStack("test") 33 require.NotPanics(t, func() { s.PushVal(i32(123)) }) 34 require.NotPanics(t, func() { s.PushVal(testByte(42)) }) 35 require.Equal(t, 2, s.Len()) 36 require.Equal(t, big.NewInt(42), s.Pop().Value()) 37 require.Equal(t, big.NewInt(123), s.Pop().Value()) 38 } 39 40 func TestPopElement(t *testing.T) { 41 var ( 42 s = NewStack("test") 43 elems = makeElements(10) 44 ) 45 for _, elem := range elems { 46 s.Push(elem) 47 } 48 49 for i := len(elems) - 1; i >= 0; i-- { 50 assert.Equal(t, elems[i], s.Pop()) 51 assert.Equal(t, i, s.Len()) 52 } 53 } 54 55 func TestPeekElement(t *testing.T) { 56 var ( 57 s = NewStack("test") 58 elems = makeElements(10) 59 ) 60 for _, elem := range elems { 61 s.Push(elem) 62 } 63 for i := len(elems) - 1; i >= 0; i-- { 64 assert.Equal(t, elems[i], s.Peek(len(elems)-i-1)) 65 } 66 } 67 68 func TestRemoveAt(t *testing.T) { 69 var ( 70 s = NewStack("test") 71 elems = makeElements(10) 72 ) 73 for _, elem := range elems { 74 s.Push(elem) 75 } 76 77 elem := s.RemoveAt(8) 78 assert.Equal(t, elems[1], elem) 79 80 // Test if the pointers are moved. 81 assert.Equal(t, elems[0], s.Peek(8)) 82 assert.Equal(t, elems[2], s.Peek(7)) 83 } 84 85 func TestPushFromOtherStack(t *testing.T) { 86 var ( 87 s1 = NewStack("test") 88 s2 = NewStack("test2") 89 elems = makeElements(2) 90 ) 91 for _, elem := range elems { 92 s1.Push(elem) 93 } 94 s2.Push(NewElement(100)) 95 s2.Push(NewElement(101)) 96 97 s1.Push(s2.Pop()) 98 assert.Equal(t, len(elems)+1, s1.Len()) 99 assert.Equal(t, 1, s2.Len()) 100 } 101 102 func TestDupElement(t *testing.T) { 103 s := NewStack("test") 104 elemA := NewElement(101) 105 s.Push(elemA) 106 107 dupped := s.Dup(0) 108 s.Push(dupped) 109 assert.Equal(t, 2, s.Len()) 110 assert.Equal(t, dupped, s.Peek(0)) 111 } 112 113 func TestBack(t *testing.T) { 114 var ( 115 s = NewStack("test") 116 elems = makeElements(10) 117 ) 118 for _, elem := range elems { 119 s.Push(elem) 120 } 121 122 assert.Equal(t, elems[0], s.Back()) 123 } 124 125 func TestTop(t *testing.T) { 126 var ( 127 s = NewStack("test") 128 elems = makeElements(10) 129 ) 130 for _, elem := range elems { 131 s.Push(elem) 132 } 133 134 assert.Equal(t, elems[len(elems)-1], s.Top()) 135 } 136 137 func TestRemoveLastElement(t *testing.T) { 138 var ( 139 s = NewStack("test") 140 elems = makeElements(2) 141 ) 142 for _, elem := range elems { 143 s.Push(elem) 144 } 145 elem := s.RemoveAt(1) 146 assert.Equal(t, elems[0], elem) 147 assert.Equal(t, 1, s.Len()) 148 } 149 150 func TestIterAfterRemove(t *testing.T) { 151 var ( 152 s = NewStack("test") 153 elems = makeElements(10) 154 ) 155 for _, elem := range elems { 156 s.Push(elem) 157 } 158 s.RemoveAt(0) 159 160 i := 0 161 s.Iter(func(_ Element) { 162 i++ 163 }) 164 assert.Equal(t, len(elems)-1, i) 165 } 166 167 func TestIteration(t *testing.T) { 168 var ( 169 n = 10 170 s = NewStack("test") 171 elems = makeElements(n) 172 ) 173 for _, elem := range elems { 174 s.Push(elem) 175 } 176 assert.Equal(t, len(elems), s.Len()) 177 178 iteratedElems := make([]Element, 0) 179 180 s.Iter(func(elem Element) { 181 iteratedElems = append(iteratedElems, elem) 182 }) 183 184 // Top to bottom order of iteration. 185 poppedElems := make([]Element, 0) 186 for s.Len() != 0 { 187 poppedElems = append(poppedElems, s.Pop()) 188 } 189 assert.Equal(t, poppedElems, iteratedElems) 190 } 191 192 func TestBackIteration(t *testing.T) { 193 var ( 194 n = 10 195 s = NewStack("test") 196 elems = makeElements(n) 197 ) 198 for _, elem := range elems { 199 s.Push(elem) 200 } 201 assert.Equal(t, len(elems), s.Len()) 202 203 iteratedElems := make([]Element, 0) 204 205 s.IterBack(func(elem Element) { 206 iteratedElems = append(iteratedElems, elem) 207 }) 208 // Bottom to the top order of iteration. 209 assert.Equal(t, elems, iteratedElems) 210 } 211 212 func TestPushVal(t *testing.T) { 213 s := NewStack("test") 214 215 // integer 216 s.PushVal(2) 217 elem := s.Pop() 218 assert.Equal(t, int64(2), elem.BigInt().Int64()) 219 220 // byteArray 221 s.PushVal([]byte("foo")) 222 elem = s.Pop() 223 assert.Equal(t, "foo", string(elem.Bytes())) 224 225 // boolean 226 s.PushVal(true) 227 elem = s.Pop() 228 assert.Equal(t, true, elem.Bool()) 229 230 // array 231 s.PushVal([]stackitem.Item{stackitem.NewBool(true), stackitem.NewBool(false), stackitem.NewBool(true)}) 232 elem = s.Pop() 233 assert.IsType(t, elem.value, &stackitem.Array{}) 234 } 235 236 func TestStack_ToArray(t *testing.T) { 237 t.Run("Empty", func(t *testing.T) { 238 s := NewStack("test") 239 items := s.ToArray() 240 require.Equal(t, 0, len(items)) 241 }) 242 t.Run("NonEmpty", func(t *testing.T) { 243 s := NewStack("test") 244 expected := []stackitem.Item{stackitem.Make(1), stackitem.Make(true)} 245 for i := range expected { 246 s.PushVal(expected[i]) 247 } 248 require.Equal(t, expected, s.ToArray()) 249 }) 250 } 251 252 func TestSwapElemValues(t *testing.T) { 253 s := NewStack("test") 254 255 s.PushVal(2) 256 s.PushVal(4) 257 258 assert.NoError(t, s.Swap(0, 1)) 259 assert.Equal(t, int64(2), s.Pop().BigInt().Int64()) 260 assert.Equal(t, int64(4), s.Pop().BigInt().Int64()) 261 262 s.PushVal(1) 263 s.PushVal(2) 264 s.PushVal(3) 265 s.PushVal(4) 266 267 assert.NoError(t, s.Swap(1, 3)) 268 assert.Equal(t, int64(4), s.Pop().BigInt().Int64()) 269 assert.Equal(t, int64(1), s.Pop().BigInt().Int64()) 270 assert.Equal(t, int64(2), s.Pop().BigInt().Int64()) 271 assert.Equal(t, int64(3), s.Pop().BigInt().Int64()) 272 273 s.PushVal(1) 274 s.PushVal(2) 275 s.PushVal(3) 276 s.PushVal(4) 277 278 assert.Error(t, s.Swap(-1, 0)) 279 assert.Error(t, s.Swap(0, -3)) 280 assert.Error(t, s.Swap(0, 4)) 281 assert.Error(t, s.Swap(5, 0)) 282 283 assert.NoError(t, s.Swap(1, 1)) 284 assert.Equal(t, int64(4), s.Pop().BigInt().Int64()) 285 assert.Equal(t, int64(3), s.Pop().BigInt().Int64()) 286 assert.Equal(t, int64(2), s.Pop().BigInt().Int64()) 287 assert.Equal(t, int64(1), s.Pop().BigInt().Int64()) 288 } 289 290 func TestRoll(t *testing.T) { 291 s := NewStack("test") 292 293 s.PushVal(1) 294 s.PushVal(2) 295 s.PushVal(3) 296 s.PushVal(4) 297 298 assert.NoError(t, s.Roll(2)) 299 assert.Equal(t, int64(2), s.Pop().BigInt().Int64()) 300 assert.Equal(t, int64(4), s.Pop().BigInt().Int64()) 301 assert.Equal(t, int64(3), s.Pop().BigInt().Int64()) 302 assert.Equal(t, int64(1), s.Pop().BigInt().Int64()) 303 304 s.PushVal(1) 305 s.PushVal(2) 306 s.PushVal(3) 307 s.PushVal(4) 308 309 assert.NoError(t, s.Roll(3)) 310 assert.Equal(t, int64(1), s.Pop().BigInt().Int64()) 311 assert.Equal(t, int64(4), s.Pop().BigInt().Int64()) 312 assert.Equal(t, int64(3), s.Pop().BigInt().Int64()) 313 assert.Equal(t, int64(2), s.Pop().BigInt().Int64()) 314 315 s.PushVal(1) 316 s.PushVal(2) 317 s.PushVal(3) 318 s.PushVal(4) 319 320 assert.Error(t, s.Roll(-1)) 321 assert.Error(t, s.Roll(4)) 322 323 assert.NoError(t, s.Roll(0)) 324 assert.Equal(t, int64(4), s.Pop().BigInt().Int64()) 325 assert.Equal(t, int64(3), s.Pop().BigInt().Int64()) 326 assert.Equal(t, int64(2), s.Pop().BigInt().Int64()) 327 assert.Equal(t, int64(1), s.Pop().BigInt().Int64()) 328 } 329 330 func TestInsertAt(t *testing.T) { 331 s := NewStack("stack") 332 s.PushVal(1) 333 s.PushVal(2) 334 s.PushVal(3) 335 s.PushVal(4) 336 s.PushVal(5) 337 338 e := s.Dup(1) // it's `4` 339 s.InsertAt(e, 3) 340 341 assert.Equal(t, int64(5), s.Peek(0).BigInt().Int64()) 342 assert.Equal(t, int64(4), s.Peek(1).BigInt().Int64()) 343 assert.Equal(t, int64(3), s.Peek(2).BigInt().Int64()) 344 assert.Equal(t, int64(4), s.Peek(3).BigInt().Int64()) 345 assert.Equal(t, int64(2), s.Peek(4).BigInt().Int64()) 346 assert.Equal(t, int64(1), s.Peek(5).BigInt().Int64()) 347 } 348 349 func TestPopSigElements(t *testing.T) { 350 s := NewStack("test") 351 352 _, err := s.PopSigElements() 353 assert.NotNil(t, err) 354 355 s.PushVal([]stackitem.Item{}) 356 _, err = s.PopSigElements() 357 assert.NotNil(t, err) 358 359 s.PushVal([]stackitem.Item{stackitem.NewBool(false)}) 360 _, err = s.PopSigElements() 361 assert.NotNil(t, err) 362 363 b1 := []byte("smth") 364 b2 := []byte("strange") 365 s.PushVal([]stackitem.Item{stackitem.NewByteArray(b1), stackitem.NewByteArray(b2)}) 366 z, err := s.PopSigElements() 367 assert.Nil(t, err) 368 assert.Equal(t, z, [][]byte{b1, b2}) 369 370 s.PushVal(2) 371 _, err = s.PopSigElements() 372 assert.NotNil(t, err) 373 374 s.PushVal(b1) 375 s.PushVal(2) 376 _, err = s.PopSigElements() 377 assert.NotNil(t, err) 378 379 s.PushVal(b2) 380 s.PushVal(b1) 381 s.PushVal(2) 382 z, err = s.PopSigElements() 383 assert.Nil(t, err) 384 assert.Equal(t, z, [][]byte{b1, b2}) 385 } 386 387 func makeElements(n int) []Element { 388 elems := make([]Element, n) 389 for i := 0; i < n; i++ { 390 elems[i] = NewElement(i) 391 } 392 return elems 393 }