github.com/MetalBlockchain/metalgo@v1.11.9/utils/buffer/unbounded_deque_test.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package buffer
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  func TestUnboundedDeque_InitialCapGreaterThanMin(t *testing.T) {
    13  	require := require.New(t)
    14  
    15  	bIntf := NewUnboundedDeque[int](10)
    16  	require.IsType(&unboundedSliceDeque[int]{}, bIntf)
    17  	b := bIntf.(*unboundedSliceDeque[int])
    18  	require.Empty(b.List())
    19  	require.Zero(b.Len())
    20  	_, ok := b.Index(0)
    21  	require.False(ok)
    22  
    23  	b.PushLeft(1)
    24  	require.Equal(1, b.Len())
    25  	require.Equal([]int{1}, b.List())
    26  	got, ok := b.Index(0)
    27  	require.True(ok)
    28  	require.Equal(1, got)
    29  	_, ok = b.Index(1)
    30  	require.False(ok)
    31  
    32  	got, ok = b.PopLeft()
    33  	require.Zero(b.Len())
    34  	require.True(ok)
    35  	require.Equal(1, got)
    36  	_, ok = b.Index(0)
    37  	require.False(ok)
    38  
    39  	b.PushLeft(1)
    40  	require.Equal(1, b.Len())
    41  	require.Equal([]int{1}, b.List())
    42  	got, ok = b.Index(0)
    43  	require.True(ok)
    44  	require.Equal(1, got)
    45  
    46  	got, ok = b.PopRight()
    47  	require.Zero(b.Len())
    48  	require.True(ok)
    49  	require.Equal(1, got)
    50  	require.Empty(b.List())
    51  	_, ok = b.Index(0)
    52  	require.False(ok)
    53  
    54  	b.PushRight(1)
    55  	require.Equal(1, b.Len())
    56  	require.Equal([]int{1}, b.List())
    57  	got, ok = b.Index(0)
    58  	require.True(ok)
    59  	require.Equal(1, got)
    60  
    61  	got, ok = b.PopRight()
    62  	require.Zero(b.Len())
    63  	require.True(ok)
    64  	require.Equal(1, got)
    65  	require.Empty(b.List())
    66  	_, ok = b.Index(0)
    67  	require.False(ok)
    68  
    69  	b.PushRight(1)
    70  	require.Equal(1, b.Len())
    71  	require.Equal([]int{1}, b.List())
    72  	got, ok = b.Index(0)
    73  	require.True(ok)
    74  	require.Equal(1, got)
    75  
    76  	got, ok = b.PopLeft()
    77  	require.Zero(b.Len())
    78  	require.True(ok)
    79  	require.Equal(1, got)
    80  	require.Empty(b.List())
    81  	_, ok = b.Index(0)
    82  	require.False(ok)
    83  
    84  	b.PushLeft(1)
    85  	require.Equal(1, b.Len())
    86  	require.Equal([]int{1}, b.List())
    87  	got, ok = b.Index(0)
    88  	require.True(ok)
    89  	require.Equal(1, got)
    90  
    91  	b.PushLeft(2)
    92  	require.Equal(2, b.Len())
    93  	require.Equal([]int{2, 1}, b.List())
    94  
    95  	got, ok = b.PopLeft()
    96  	require.Equal(1, b.Len())
    97  	require.True(ok)
    98  	require.Equal(2, got)
    99  	require.Equal([]int{1}, b.List())
   100  	got, ok = b.Index(0)
   101  	require.True(ok)
   102  	require.Equal(1, got)
   103  
   104  	got, ok = b.PopLeft()
   105  	require.Zero(b.Len())
   106  	require.True(ok)
   107  	require.Equal(1, got)
   108  	require.Empty(b.List())
   109  	_, ok = b.Index(0)
   110  	require.False(ok)
   111  
   112  	b.PushRight(1)
   113  	require.Equal(1, b.Len())
   114  	require.Equal([]int{1}, b.List())
   115  	got, ok = b.Index(0)
   116  	require.True(ok)
   117  	require.Equal(1, got)
   118  
   119  	b.PushRight(2)
   120  	require.Equal(2, b.Len())
   121  	require.Equal([]int{1, 2}, b.List())
   122  
   123  	got, ok = b.PopRight()
   124  	require.Equal(1, b.Len())
   125  	require.True(ok)
   126  	require.Equal(2, got)
   127  	require.Equal([]int{1}, b.List())
   128  	got, ok = b.Index(0)
   129  	require.True(ok)
   130  	require.Equal(1, got)
   131  
   132  	got, ok = b.PopRight()
   133  	require.Zero(b.Len())
   134  	require.True(ok)
   135  	require.Equal(1, got)
   136  	require.Empty(b.List())
   137  	_, ok = b.Index(0)
   138  	require.False(ok)
   139  
   140  	b.PushLeft(1)
   141  	require.Equal(1, b.Len())
   142  	require.Equal([]int{1}, b.List())
   143  	got, ok = b.Index(0)
   144  	require.True(ok)
   145  	require.Equal(1, got)
   146  
   147  	b.PushLeft(2)
   148  	require.Equal(2, b.Len())
   149  	require.Equal([]int{2, 1}, b.List())
   150  
   151  	got, ok = b.PopRight()
   152  	require.Equal(1, b.Len())
   153  	require.True(ok)
   154  	require.Equal(1, got)
   155  	require.Equal([]int{2}, b.List())
   156  	got, ok = b.Index(0)
   157  	require.True(ok)
   158  	require.Equal(2, got)
   159  
   160  	got, ok = b.PopLeft()
   161  	require.Zero(b.Len())
   162  	require.True(ok)
   163  	require.Equal(2, got)
   164  	require.Empty(b.List())
   165  	_, ok = b.Index(0)
   166  	require.False(ok)
   167  
   168  	b.PushRight(1)
   169  	require.Equal(1, b.Len())
   170  	require.Equal([]int{1}, b.List())
   171  	got, ok = b.Index(0)
   172  	require.True(ok)
   173  	require.Equal(1, got)
   174  
   175  	b.PushLeft(2)
   176  	require.Equal(2, b.Len())
   177  	require.Equal([]int{2, 1}, b.List())
   178  
   179  	got, ok = b.PopRight()
   180  	require.Equal(1, b.Len())
   181  	require.True(ok)
   182  	require.Equal(1, got)
   183  	require.Equal([]int{2}, b.List())
   184  	got, ok = b.Index(0)
   185  	require.True(ok)
   186  	require.Equal(2, got)
   187  
   188  	got, ok = b.PopLeft()
   189  	require.Zero(b.Len())
   190  	require.True(ok)
   191  	require.Equal(2, got)
   192  	require.Empty(b.List())
   193  	_, ok = b.Index(0)
   194  	require.False(ok)
   195  
   196  	b.PushLeft(1)
   197  	require.Equal(1, b.Len())
   198  	require.Equal([]int{1}, b.List())
   199  	got, ok = b.Index(0)
   200  	require.True(ok)
   201  	require.Equal(1, got)
   202  
   203  	b.PushRight(2)
   204  	require.Equal(2, b.Len())
   205  	require.Equal([]int{1, 2}, b.List())
   206  
   207  	got, ok = b.PopLeft()
   208  	require.Equal(1, b.Len())
   209  	require.True(ok)
   210  	require.Equal(1, got)
   211  	require.Equal([]int{2}, b.List())
   212  	got, ok = b.Index(0)
   213  	require.True(ok)
   214  	require.Equal(2, got)
   215  
   216  	got, ok = b.PopRight()
   217  	require.Zero(b.Len())
   218  	require.True(ok)
   219  	require.Equal(2, got)
   220  	require.Empty(b.List())
   221  	_, ok = b.Index(0)
   222  	require.False(ok)
   223  }
   224  
   225  // Cases we test:
   226  // 1. [left] moves to the left (no wrap around).
   227  // 2. [left] moves to the right (no wrap around).
   228  // 3. [left] wrapping around to the left side.
   229  // 4. [left] wrapping around to the right side.
   230  // 5. Resize.
   231  func TestUnboundedSliceDequePushLeftPopLeft(t *testing.T) {
   232  	require := require.New(t)
   233  
   234  	// Starts empty.
   235  	bIntf := NewUnboundedDeque[int](2)
   236  	require.IsType(&unboundedSliceDeque[int]{}, bIntf)
   237  	b := bIntf.(*unboundedSliceDeque[int])
   238  	require.Zero(bIntf.Len())
   239  	require.Len(b.data, 2)
   240  	require.Zero(b.left)
   241  	require.Equal(1, b.right)
   242  	require.Empty(b.List())
   243  	// slice is [EMPTY]
   244  
   245  	_, ok := b.PopLeft()
   246  	require.False(ok)
   247  	_, ok = b.PeekLeft()
   248  	require.False(ok)
   249  	_, ok = b.PeekRight()
   250  	require.False(ok)
   251  
   252  	b.PushLeft(1) // slice is [1,EMPTY]
   253  	require.Equal(1, b.Len())
   254  	require.Len(b.data, 2)
   255  	require.Equal(1, b.left)
   256  	require.Equal(1, b.right)
   257  	require.Equal([]int{1}, b.List())
   258  
   259  	got, ok := b.PeekLeft()
   260  	require.True(ok)
   261  	require.Equal(1, got)
   262  
   263  	got, ok = b.PeekRight()
   264  	require.True(ok)
   265  	require.Equal(1, got)
   266  
   267  	// This causes a resize
   268  	b.PushLeft(2) // slice is [2,1,EMPTY,EMPTY]
   269  	require.Equal(2, b.Len())
   270  	require.Len(b.data, 4)
   271  	require.Equal(3, b.left)
   272  	require.Equal(2, b.right)
   273  	require.Equal([]int{2, 1}, b.List())
   274  	got, ok = b.Index(0)
   275  	require.True(ok)
   276  	require.Equal(2, got)
   277  	got, ok = b.Index(1)
   278  	require.True(ok)
   279  	require.Equal(1, got)
   280  
   281  	got, ok = b.PeekLeft()
   282  	require.True(ok)
   283  	require.Equal(2, got)
   284  
   285  	got, ok = b.PeekRight()
   286  	require.True(ok)
   287  	require.Equal(1, got)
   288  
   289  	// Tests left moving left with no wrap around.
   290  	b.PushLeft(3) // slice is [2,1,EMPTY,3]
   291  	require.Equal(3, b.Len())
   292  	require.Len(b.data, 4)
   293  	require.Equal(2, b.left)
   294  	require.Equal(2, b.right)
   295  	require.Equal([]int{3, 2, 1}, b.List())
   296  	got, ok = b.Index(0)
   297  	require.True(ok)
   298  	require.Equal(3, got)
   299  	got, ok = b.Index(1)
   300  	require.True(ok)
   301  	require.Equal(2, got)
   302  	got, ok = b.Index(2)
   303  	require.True(ok)
   304  	require.Equal(1, got)
   305  	_, ok = b.Index(3)
   306  	require.False(ok)
   307  
   308  	got, ok = b.PeekLeft()
   309  	require.True(ok)
   310  	require.Equal(3, got)
   311  
   312  	got, ok = b.PeekRight()
   313  	require.True(ok)
   314  	require.Equal(1, got)
   315  
   316  	// Tests left moving right with no wrap around.
   317  	got, ok = b.PopLeft() // slice is [2,1,EMPTY,EMPTY]
   318  	require.True(ok)
   319  	require.Equal(3, got)
   320  	require.Equal(2, b.Len())
   321  	require.Len(b.data, 4)
   322  	require.Equal(3, b.left)
   323  	require.Equal(2, b.right)
   324  	require.Equal([]int{2, 1}, b.List())
   325  	got, ok = b.Index(0)
   326  	require.True(ok)
   327  	require.Equal(2, got)
   328  	got, ok = b.Index(1)
   329  	require.True(ok)
   330  	require.Equal(1, got)
   331  
   332  	got, ok = b.PeekLeft()
   333  	require.True(ok)
   334  	require.Equal(2, got)
   335  
   336  	got, ok = b.PeekRight()
   337  	require.True(ok)
   338  	require.Equal(1, got)
   339  
   340  	// Tests left wrapping around to the left side.
   341  	got, ok = b.PopLeft() // slice is [EMPTY,1,EMPTY,EMPTY]
   342  	require.True(ok)
   343  	require.Equal(2, got)
   344  	require.Equal(1, b.Len())
   345  	require.Len(b.data, 4)
   346  	require.Zero(b.left)
   347  	require.Equal(2, b.right)
   348  	require.Equal([]int{1}, b.List())
   349  	got, ok = b.Index(0)
   350  	require.True(ok)
   351  	require.Equal(1, got)
   352  
   353  	got, ok = b.PeekLeft()
   354  	require.True(ok)
   355  	require.Equal(1, got)
   356  
   357  	got, ok = b.PeekRight()
   358  	require.True(ok)
   359  	require.Equal(1, got)
   360  
   361  	// Test left wrapping around to the right side.
   362  	b.PushLeft(2) // slice is [2,1,EMPTY,EMPTY]
   363  	require.Equal(2, b.Len())
   364  	require.Len(b.data, 4)
   365  	require.Equal(3, b.left)
   366  	require.Equal(2, b.right)
   367  	require.Equal([]int{2, 1}, b.List())
   368  	got, ok = b.Index(0)
   369  	require.True(ok)
   370  	require.Equal(2, got)
   371  	got, ok = b.Index(1)
   372  	require.True(ok)
   373  	require.Equal(1, got)
   374  
   375  	got, ok = b.PeekLeft()
   376  	require.True(ok)
   377  	require.Equal(2, got)
   378  
   379  	got, ok = b.PeekRight()
   380  	require.True(ok)
   381  	require.Equal(1, got)
   382  
   383  	got, ok = b.PopLeft() // slice is [EMPTY,1,EMPTY,EMPTY]
   384  	require.True(ok)
   385  	require.Equal(2, got)
   386  	require.Equal(1, b.Len())
   387  	require.Len(b.data, 4)
   388  	require.Zero(b.left)
   389  	require.Equal(2, b.right)
   390  	require.Equal([]int{1}, b.List())
   391  	got, ok = b.Index(0)
   392  	require.True(ok)
   393  	require.Equal(1, got)
   394  
   395  	got, ok = b.PopLeft() // slice is [EMPTY,EMPTY,EMPTY,EMPTY]
   396  	require.True(ok)
   397  	require.Equal(1, got)
   398  	require.Zero(b.Len())
   399  	require.Len(b.data, 4)
   400  	require.Equal(1, b.left)
   401  	require.Equal(2, b.right)
   402  	require.Empty(b.List())
   403  	_, ok = b.Index(0)
   404  	require.False(ok)
   405  
   406  	_, ok = b.PopLeft()
   407  	require.False(ok)
   408  	_, ok = b.PeekLeft()
   409  	require.False(ok)
   410  	_, ok = b.PeekRight()
   411  	require.False(ok)
   412  }
   413  
   414  func TestUnboundedSliceDequePushRightPopRight(t *testing.T) {
   415  	require := require.New(t)
   416  
   417  	// Starts empty.
   418  	bIntf := NewUnboundedDeque[int](2)
   419  	require.IsType(&unboundedSliceDeque[int]{}, bIntf)
   420  	b := bIntf.(*unboundedSliceDeque[int])
   421  	require.Zero(bIntf.Len())
   422  	require.Len(b.data, 2)
   423  	require.Zero(b.left)
   424  	require.Equal(1, b.right)
   425  	require.Empty(b.List())
   426  	// slice is [EMPTY]
   427  
   428  	_, ok := b.PopRight()
   429  	require.False(ok)
   430  	_, ok = b.PeekLeft()
   431  	require.False(ok)
   432  	_, ok = b.PeekRight()
   433  	require.False(ok)
   434  
   435  	b.PushRight(1) // slice is [1,EMPTY]
   436  	require.Equal(1, b.Len())
   437  	require.Len(b.data, 2)
   438  	require.Zero(b.left)
   439  	require.Zero(b.right)
   440  	require.Equal([]int{1}, b.List())
   441  	got, ok := b.Index(0)
   442  	require.True(ok)
   443  	require.Equal(1, got)
   444  
   445  	got, ok = b.PeekLeft()
   446  	require.True(ok)
   447  	require.Equal(1, got)
   448  
   449  	got, ok = b.PeekRight()
   450  	require.True(ok)
   451  	require.Equal(1, got)
   452  
   453  	// This causes a resize
   454  	b.PushRight(2) // slice is [1,2,EMPTY,EMPTY]
   455  	require.Equal(2, b.Len())
   456  	require.Len(b.data, 4)
   457  	require.Equal(3, b.left)
   458  	require.Equal(2, b.right)
   459  	require.Equal([]int{1, 2}, b.List())
   460  	got, ok = b.Index(0)
   461  	require.True(ok)
   462  	require.Equal(1, got)
   463  	got, ok = b.Index(1)
   464  	require.True(ok)
   465  	require.Equal(2, got)
   466  
   467  	got, ok = b.PeekLeft()
   468  	require.True(ok)
   469  	require.Equal(1, got)
   470  
   471  	got, ok = b.PeekRight()
   472  	require.True(ok)
   473  	require.Equal(2, got)
   474  
   475  	// Tests right moving right with no wrap around
   476  	b.PushRight(3) // slice is [1,2,3,EMPTY]
   477  	require.Equal(3, b.Len())
   478  	require.Len(b.data, 4)
   479  	require.Equal(3, b.left)
   480  	require.Equal(3, b.right)
   481  	require.Equal([]int{1, 2, 3}, b.List())
   482  	got, ok = b.Index(0)
   483  	require.True(ok)
   484  	require.Equal(1, got)
   485  	got, ok = b.Index(1)
   486  	require.True(ok)
   487  	require.Equal(2, got)
   488  	got, ok = b.Index(2)
   489  	require.True(ok)
   490  	require.Equal(3, got)
   491  
   492  	got, ok = b.PeekLeft()
   493  	require.True(ok)
   494  	require.Equal(1, got)
   495  
   496  	got, ok = b.PeekRight()
   497  	require.True(ok)
   498  	require.Equal(3, got)
   499  
   500  	// Tests right moving left with no wrap around
   501  	got, ok = b.PopRight() // slice is [1,2,EMPTY,EMPTY]
   502  	require.True(ok)
   503  	require.Equal(3, got)
   504  	require.Equal(2, b.Len())
   505  	require.Len(b.data, 4)
   506  	require.Equal(3, b.left)
   507  	require.Equal(2, b.right)
   508  	require.Equal([]int{1, 2}, b.List())
   509  	got, ok = b.Index(0)
   510  	require.True(ok)
   511  	require.Equal(1, got)
   512  	got, ok = b.Index(1)
   513  	require.True(ok)
   514  	require.Equal(2, got)
   515  	_, ok = b.Index(2)
   516  	require.False(ok)
   517  
   518  	got, ok = b.PeekLeft()
   519  	require.True(ok)
   520  	require.Equal(1, got)
   521  
   522  	got, ok = b.PeekRight()
   523  	require.True(ok)
   524  	require.Equal(2, got)
   525  
   526  	got, ok = b.PopRight() // slice is [1,EMPTY,EMPTY,EMPTY]
   527  	require.True(ok)
   528  	require.Equal(2, got)
   529  	require.Equal(1, b.Len())
   530  	require.Len(b.data, 4)
   531  	require.Equal(3, b.left)
   532  	require.Equal(1, b.right)
   533  	require.Equal([]int{1}, b.List())
   534  	got, ok = b.Index(0)
   535  	require.True(ok)
   536  	require.Equal(1, got)
   537  	_, ok = b.Index(1)
   538  	require.False(ok)
   539  
   540  	got, ok = b.PeekLeft()
   541  	require.True(ok)
   542  	require.Equal(1, got)
   543  
   544  	got, ok = b.PeekRight()
   545  	require.True(ok)
   546  	require.Equal(1, got)
   547  
   548  	got, ok = b.PopRight() // slice is [EMPTY,EMPTY,EMPTY,EMPTY]
   549  	require.True(ok)
   550  	require.Equal(1, got)
   551  	require.Zero(b.Len())
   552  	require.Len(b.data, 4)
   553  	require.Equal(3, b.left)
   554  	require.Zero(b.right)
   555  	require.Empty(b.List())
   556  	require.Zero(b.Len())
   557  	_, ok = b.Index(0)
   558  	require.False(ok)
   559  
   560  	_, ok = b.PeekLeft()
   561  	require.False(ok)
   562  	_, ok = b.PeekRight()
   563  	require.False(ok)
   564  	_, ok = b.PopRight()
   565  	require.False(ok)
   566  
   567  	b.PushLeft(1) // slice is [EMPTY,EMPTY,EMPTY,1]
   568  	require.Equal(1, b.Len())
   569  	require.Len(b.data, 4)
   570  	require.Equal(2, b.left)
   571  	require.Zero(b.right)
   572  	require.Equal([]int{1}, b.List())
   573  	got, ok = b.Index(0)
   574  	require.True(ok)
   575  	require.Equal(1, got)
   576  
   577  	got, ok = b.PeekLeft()
   578  	require.True(ok)
   579  	require.Equal(1, got)
   580  
   581  	got, ok = b.PeekRight()
   582  	require.True(ok)
   583  	require.Equal(1, got)
   584  
   585  	// Test right wrapping around to the right
   586  	got, ok = b.PopRight() // slice is [EMPTY,EMPTY,EMPTY,EMPTY]
   587  	require.True(ok)
   588  	require.Equal(1, got)
   589  	require.Zero(b.Len())
   590  	require.Len(b.data, 4)
   591  	require.Equal(2, b.left)
   592  	require.Equal(3, b.right)
   593  	require.Empty(b.List())
   594  	require.Zero(b.Len())
   595  	_, ok = b.Index(0)
   596  	require.False(ok)
   597  
   598  	_, ok = b.PeekLeft()
   599  	require.False(ok)
   600  
   601  	_, ok = b.PeekRight()
   602  	require.False(ok)
   603  
   604  	// Tests right wrapping around to the left
   605  	b.PushRight(2) // slice is [EMPTY,EMPTY,EMPTY,2]
   606  	require.Equal(1, b.Len())
   607  	require.Len(b.data, 4)
   608  	require.Equal(2, b.left)
   609  	require.Zero(b.right)
   610  	require.Equal([]int{2}, b.List())
   611  	got, ok = b.Index(0)
   612  	require.True(ok)
   613  	require.Equal(2, got)
   614  
   615  	got, ok = b.PeekLeft()
   616  	require.True(ok)
   617  	require.Equal(2, got)
   618  
   619  	got, ok = b.PeekRight()
   620  	require.True(ok)
   621  	require.Equal(2, got)
   622  
   623  	got, ok = b.PopRight() // slice is [EMPTY,EMPTY,EMPTY,EMPTY]
   624  	require.True(ok)
   625  	require.Equal(2, got)
   626  	require.Empty(b.List())
   627  	_, ok = b.Index(0)
   628  	require.False(ok)
   629  
   630  	_, ok = b.PeekLeft()
   631  	require.False(ok)
   632  	_, ok = b.PeekRight()
   633  	require.False(ok)
   634  	_, ok = b.PopRight()
   635  	require.False(ok)
   636  }
   637  
   638  func FuzzUnboundedSliceDeque(f *testing.F) {
   639  	f.Fuzz(
   640  		func(t *testing.T, initSize uint, input []byte) {
   641  			require := require.New(t)
   642  			b := NewUnboundedDeque[byte](int(initSize))
   643  			for i, n := range input {
   644  				b.PushRight(n)
   645  				gotIndex, ok := b.Index(i)
   646  				require.True(ok)
   647  				require.Equal(n, gotIndex)
   648  			}
   649  
   650  			list := b.List()
   651  			require.Len(list, len(input))
   652  			for i, n := range input {
   653  				require.Equal(n, list[i])
   654  			}
   655  
   656  			for i := 0; i < len(input); i++ {
   657  				_, _ = b.PopLeft()
   658  				list = b.List()
   659  				if i == len(input)-1 {
   660  					require.Empty(list)
   661  					_, ok := b.Index(0)
   662  					require.False(ok)
   663  				} else {
   664  					require.Equal(input[i+1:], list)
   665  					got, ok := b.Index(0)
   666  					require.True(ok)
   667  					require.Equal(input[i+1], got)
   668  				}
   669  			}
   670  		},
   671  	)
   672  }