github.com/lbryio/lbcd@v0.22.119/database/internal/treap/treapiter_test.go (about)

     1  // Copyright (c) 2015-2016 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package treap
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/binary"
    10  	"testing"
    11  )
    12  
    13  // TestMutableIterator ensures that the general behavior of mutable treap
    14  // iterators is as expected including tests for first, last, ordered and reverse
    15  // ordered iteration, limiting the range, seeking, and initially unpositioned.
    16  func TestMutableIterator(t *testing.T) {
    17  	t.Parallel()
    18  
    19  	tests := []struct {
    20  		numKeys       int
    21  		step          int
    22  		startKey      []byte
    23  		limitKey      []byte
    24  		expectedFirst []byte
    25  		expectedLast  []byte
    26  		seekKey       []byte
    27  		expectedSeek  []byte
    28  	}{
    29  		// No range limits.  Values are the set (0, 1, 2, ..., 49).
    30  		// Seek existing value.
    31  		{
    32  			numKeys:       50,
    33  			step:          1,
    34  			expectedFirst: serializeUint32(0),
    35  			expectedLast:  serializeUint32(49),
    36  			seekKey:       serializeUint32(12),
    37  			expectedSeek:  serializeUint32(12),
    38  		},
    39  
    40  		// Limited to range [24, end].  Values are the set
    41  		// (0, 2, 4, ..., 48).  Seek value that doesn't exist and is
    42  		// greater than largest existing key.
    43  		{
    44  			numKeys:       50,
    45  			step:          2,
    46  			startKey:      serializeUint32(24),
    47  			expectedFirst: serializeUint32(24),
    48  			expectedLast:  serializeUint32(48),
    49  			seekKey:       serializeUint32(49),
    50  			expectedSeek:  nil,
    51  		},
    52  
    53  		// Limited to range [start, 25).  Values are the set
    54  		// (0, 3, 6, ..., 48).  Seek value that doesn't exist but is
    55  		// before an existing value within the range.
    56  		{
    57  			numKeys:       50,
    58  			step:          3,
    59  			limitKey:      serializeUint32(25),
    60  			expectedFirst: serializeUint32(0),
    61  			expectedLast:  serializeUint32(24),
    62  			seekKey:       serializeUint32(17),
    63  			expectedSeek:  serializeUint32(18),
    64  		},
    65  
    66  		// Limited to range [10, 21).  Values are the set
    67  		// (0, 4, ..., 48).  Seek value that exists, but is before the
    68  		// minimum allowed range.
    69  		{
    70  			numKeys:       50,
    71  			step:          4,
    72  			startKey:      serializeUint32(10),
    73  			limitKey:      serializeUint32(21),
    74  			expectedFirst: serializeUint32(12),
    75  			expectedLast:  serializeUint32(20),
    76  			seekKey:       serializeUint32(4),
    77  			expectedSeek:  nil,
    78  		},
    79  
    80  		// Limited by prefix {0,0,0}, range [{0,0,0}, {0,0,1}).
    81  		// Since it's a bytewise compare,  {0,0,0,...} < {0,0,1}.
    82  		// Seek existing value within the allowed range.
    83  		{
    84  			numKeys:       300,
    85  			step:          1,
    86  			startKey:      []byte{0x00, 0x00, 0x00},
    87  			limitKey:      []byte{0x00, 0x00, 0x01},
    88  			expectedFirst: serializeUint32(0),
    89  			expectedLast:  serializeUint32(255),
    90  			seekKey:       serializeUint32(100),
    91  			expectedSeek:  serializeUint32(100),
    92  		},
    93  	}
    94  
    95  testLoop:
    96  	for i, test := range tests {
    97  		// Insert a bunch of keys.
    98  		testTreap := NewMutable()
    99  		for i := 0; i < test.numKeys; i += test.step {
   100  			key := serializeUint32(uint32(i))
   101  			testTreap.Put(key, key)
   102  		}
   103  
   104  		// Create new iterator limited by the test params.
   105  		iter := testTreap.Iterator(test.startKey, test.limitKey)
   106  
   107  		// Ensure the first item is accurate.
   108  		hasFirst := iter.First()
   109  		if !hasFirst && test.expectedFirst != nil {
   110  			t.Errorf("First #%d: unexpected exhausted iterator", i)
   111  			continue
   112  		}
   113  		gotKey := iter.Key()
   114  		if !bytes.Equal(gotKey, test.expectedFirst) {
   115  			t.Errorf("First.Key #%d: unexpected key - got %x, "+
   116  				"want %x", i, gotKey, test.expectedFirst)
   117  			continue
   118  		}
   119  		gotVal := iter.Value()
   120  		if !bytes.Equal(gotVal, test.expectedFirst) {
   121  			t.Errorf("First.Value #%d: unexpected value - got %x, "+
   122  				"want %x", i, gotVal, test.expectedFirst)
   123  			continue
   124  		}
   125  
   126  		// Ensure the iterator gives the expected items in order.
   127  		curNum := binary.BigEndian.Uint32(test.expectedFirst)
   128  		for iter.Next() {
   129  			curNum += uint32(test.step)
   130  
   131  			// Ensure key is as expected.
   132  			gotKey := iter.Key()
   133  			expectedKey := serializeUint32(curNum)
   134  			if !bytes.Equal(gotKey, expectedKey) {
   135  				t.Errorf("iter.Key #%d (%d): unexpected key - "+
   136  					"got %x, want %x", i, curNum, gotKey,
   137  					expectedKey)
   138  				continue testLoop
   139  			}
   140  
   141  			// Ensure value is as expected.
   142  			gotVal := iter.Value()
   143  			if !bytes.Equal(gotVal, expectedKey) {
   144  				t.Errorf("iter.Value #%d (%d): unexpected "+
   145  					"value - got %x, want %x", i, curNum,
   146  					gotVal, expectedKey)
   147  				continue testLoop
   148  			}
   149  		}
   150  
   151  		// Ensure iterator is exhausted.
   152  		if iter.Valid() {
   153  			t.Errorf("Valid #%d: iterator should be exhausted", i)
   154  			continue
   155  		}
   156  
   157  		// Ensure the last item is accurate.
   158  		hasLast := iter.Last()
   159  		if !hasLast && test.expectedLast != nil {
   160  			t.Errorf("Last #%d: unexpected exhausted iterator", i)
   161  			continue
   162  		}
   163  		gotKey = iter.Key()
   164  		if !bytes.Equal(gotKey, test.expectedLast) {
   165  			t.Errorf("Last.Key #%d: unexpected key - got %x, "+
   166  				"want %x", i, gotKey, test.expectedLast)
   167  			continue
   168  		}
   169  		gotVal = iter.Value()
   170  		if !bytes.Equal(gotVal, test.expectedLast) {
   171  			t.Errorf("Last.Value #%d: unexpected value - got %x, "+
   172  				"want %x", i, gotVal, test.expectedLast)
   173  			continue
   174  		}
   175  
   176  		// Ensure the iterator gives the expected items in reverse
   177  		// order.
   178  		curNum = binary.BigEndian.Uint32(test.expectedLast)
   179  		for iter.Prev() {
   180  			curNum -= uint32(test.step)
   181  
   182  			// Ensure key is as expected.
   183  			gotKey := iter.Key()
   184  			expectedKey := serializeUint32(curNum)
   185  			if !bytes.Equal(gotKey, expectedKey) {
   186  				t.Errorf("iter.Key #%d (%d): unexpected key - "+
   187  					"got %x, want %x", i, curNum, gotKey,
   188  					expectedKey)
   189  				continue testLoop
   190  			}
   191  
   192  			// Ensure value is as expected.
   193  			gotVal := iter.Value()
   194  			if !bytes.Equal(gotVal, expectedKey) {
   195  				t.Errorf("iter.Value #%d (%d): unexpected "+
   196  					"value - got %x, want %x", i, curNum,
   197  					gotVal, expectedKey)
   198  				continue testLoop
   199  			}
   200  		}
   201  
   202  		// Ensure iterator is exhausted.
   203  		if iter.Valid() {
   204  			t.Errorf("Valid #%d: iterator should be exhausted", i)
   205  			continue
   206  		}
   207  
   208  		// Seek to the provided key.
   209  		seekValid := iter.Seek(test.seekKey)
   210  		if !seekValid && test.expectedSeek != nil {
   211  			t.Errorf("Seek #%d: unexpected exhausted iterator", i)
   212  			continue
   213  		}
   214  		gotKey = iter.Key()
   215  		if !bytes.Equal(gotKey, test.expectedSeek) {
   216  			t.Errorf("Seek.Key #%d: unexpected key - got %x, "+
   217  				"want %x", i, gotKey, test.expectedSeek)
   218  			continue
   219  		}
   220  		gotVal = iter.Value()
   221  		if !bytes.Equal(gotVal, test.expectedSeek) {
   222  			t.Errorf("Seek.Value #%d: unexpected value - got %x, "+
   223  				"want %x", i, gotVal, test.expectedSeek)
   224  			continue
   225  		}
   226  
   227  		// Recreate the iterator and ensure calling Next on it before it
   228  		// has been positioned gives the first element.
   229  		iter = testTreap.Iterator(test.startKey, test.limitKey)
   230  		hasNext := iter.Next()
   231  		if !hasNext && test.expectedFirst != nil {
   232  			t.Errorf("Next #%d: unexpected exhausted iterator", i)
   233  			continue
   234  		}
   235  		gotKey = iter.Key()
   236  		if !bytes.Equal(gotKey, test.expectedFirst) {
   237  			t.Errorf("Next.Key #%d: unexpected key - got %x, "+
   238  				"want %x", i, gotKey, test.expectedFirst)
   239  			continue
   240  		}
   241  		gotVal = iter.Value()
   242  		if !bytes.Equal(gotVal, test.expectedFirst) {
   243  			t.Errorf("Next.Value #%d: unexpected value - got %x, "+
   244  				"want %x", i, gotVal, test.expectedFirst)
   245  			continue
   246  		}
   247  
   248  		// Recreate the iterator and ensure calling Prev on it before it
   249  		// has been positioned gives the first element.
   250  		iter = testTreap.Iterator(test.startKey, test.limitKey)
   251  		hasPrev := iter.Prev()
   252  		if !hasPrev && test.expectedLast != nil {
   253  			t.Errorf("Prev #%d: unexpected exhausted iterator", i)
   254  			continue
   255  		}
   256  		gotKey = iter.Key()
   257  		if !bytes.Equal(gotKey, test.expectedLast) {
   258  			t.Errorf("Prev.Key #%d: unexpected key - got %x, "+
   259  				"want %x", i, gotKey, test.expectedLast)
   260  			continue
   261  		}
   262  		gotVal = iter.Value()
   263  		if !bytes.Equal(gotVal, test.expectedLast) {
   264  			t.Errorf("Next.Value #%d: unexpected value - got %x, "+
   265  				"want %x", i, gotVal, test.expectedLast)
   266  			continue
   267  		}
   268  	}
   269  }
   270  
   271  // TestMutableEmptyIterator ensures that the various functions behave as
   272  // expected when a mutable treap is empty.
   273  func TestMutableEmptyIterator(t *testing.T) {
   274  	t.Parallel()
   275  
   276  	// Create iterator against empty treap.
   277  	testTreap := NewMutable()
   278  	iter := testTreap.Iterator(nil, nil)
   279  
   280  	// Ensure Valid on empty iterator reports it as exhausted.
   281  	if iter.Valid() {
   282  		t.Fatal("Valid: iterator should be exhausted")
   283  	}
   284  
   285  	// Ensure First and Last on empty iterator report it as exhausted.
   286  	if iter.First() {
   287  		t.Fatal("First: iterator should be exhausted")
   288  	}
   289  	if iter.Last() {
   290  		t.Fatal("Last: iterator should be exhausted")
   291  	}
   292  
   293  	// Ensure Next and Prev on empty iterator report it as exhausted.
   294  	if iter.Next() {
   295  		t.Fatal("Next: iterator should be exhausted")
   296  	}
   297  	if iter.Prev() {
   298  		t.Fatal("Prev: iterator should be exhausted")
   299  	}
   300  
   301  	// Ensure Key and Value on empty iterator are nil.
   302  	if gotKey := iter.Key(); gotKey != nil {
   303  		t.Fatalf("Key: should be nil - got %q", gotKey)
   304  	}
   305  	if gotVal := iter.Value(); gotVal != nil {
   306  		t.Fatalf("Value: should be nil - got %q", gotVal)
   307  	}
   308  
   309  	// Ensure Next and Prev report exhausted after forcing a reseek on an
   310  	// empty iterator.
   311  	iter.ForceReseek()
   312  	if iter.Next() {
   313  		t.Fatal("Next: iterator should be exhausted")
   314  	}
   315  	iter.ForceReseek()
   316  	if iter.Prev() {
   317  		t.Fatal("Prev: iterator should be exhausted")
   318  	}
   319  }
   320  
   321  // TestIteratorUpdates ensures that issuing a call to ForceReseek on an iterator
   322  // that had the underlying mutable treap updated works as expected.
   323  func TestIteratorUpdates(t *testing.T) {
   324  	t.Parallel()
   325  
   326  	// Create a new treap with various values inserted in no particular
   327  	// order.  The resulting keys are the set (2, 4, 7, 11, 18, 25).
   328  	testTreap := NewMutable()
   329  	testTreap.Put(serializeUint32(7), nil)
   330  	testTreap.Put(serializeUint32(2), nil)
   331  	testTreap.Put(serializeUint32(18), nil)
   332  	testTreap.Put(serializeUint32(11), nil)
   333  	testTreap.Put(serializeUint32(25), nil)
   334  	testTreap.Put(serializeUint32(4), nil)
   335  
   336  	// Create an iterator against the treap with a range that excludes the
   337  	// lowest and highest entries.  The limited set is then (4, 7, 11, 18)
   338  	iter := testTreap.Iterator(serializeUint32(3), serializeUint32(25))
   339  
   340  	// Delete a key from the middle of the range and notify the iterator to
   341  	// force a reseek.
   342  	testTreap.Delete(serializeUint32(11))
   343  	iter.ForceReseek()
   344  
   345  	// Ensure that calling Next on the iterator after the forced reseek
   346  	// gives the expected key.  The limited set of keys at this point is
   347  	// (4, 7, 18) and the iterator has not yet been positioned.
   348  	if !iter.Next() {
   349  		t.Fatal("ForceReseek.Next: unexpected exhausted iterator")
   350  	}
   351  	wantKey := serializeUint32(4)
   352  	gotKey := iter.Key()
   353  	if !bytes.Equal(gotKey, wantKey) {
   354  		t.Fatalf("ForceReseek.Key: unexpected key - got %x, want %x",
   355  			gotKey, wantKey)
   356  	}
   357  
   358  	// Delete the key the iterator is currently position at and notify the
   359  	// iterator to force a reseek.
   360  	testTreap.Delete(serializeUint32(4))
   361  	iter.ForceReseek()
   362  
   363  	// Ensure that calling Next on the iterator after the forced reseek
   364  	// gives the expected key.  The limited set of keys at this point is
   365  	// (7, 18) and the iterator is positioned at a deleted entry before 7.
   366  	if !iter.Next() {
   367  		t.Fatal("ForceReseek.Next: unexpected exhausted iterator")
   368  	}
   369  	wantKey = serializeUint32(7)
   370  	gotKey = iter.Key()
   371  	if !bytes.Equal(gotKey, wantKey) {
   372  		t.Fatalf("ForceReseek.Key: unexpected key - got %x, want %x",
   373  			gotKey, wantKey)
   374  	}
   375  
   376  	// Add a key before the current key the iterator is position at and
   377  	// notify the iterator to force a reseek.
   378  	testTreap.Put(serializeUint32(4), nil)
   379  	iter.ForceReseek()
   380  
   381  	// Ensure that calling Prev on the iterator after the forced reseek
   382  	// gives the expected key.  The limited set of keys at this point is
   383  	// (4, 7, 18) and the iterator is positioned at 7.
   384  	if !iter.Prev() {
   385  		t.Fatal("ForceReseek.Prev: unexpected exhausted iterator")
   386  	}
   387  	wantKey = serializeUint32(4)
   388  	gotKey = iter.Key()
   389  	if !bytes.Equal(gotKey, wantKey) {
   390  		t.Fatalf("ForceReseek.Key: unexpected key - got %x, want %x",
   391  			gotKey, wantKey)
   392  	}
   393  
   394  	// Delete the next key the iterator would ordinarily move to then notify
   395  	// the iterator to force a reseek.
   396  	testTreap.Delete(serializeUint32(7))
   397  	iter.ForceReseek()
   398  
   399  	// Ensure that calling Next on the iterator after the forced reseek
   400  	// gives the expected key.  The limited set of keys at this point is
   401  	// (4, 18) and the iterator is positioned at 4.
   402  	if !iter.Next() {
   403  		t.Fatal("ForceReseek.Next: unexpected exhausted iterator")
   404  	}
   405  	wantKey = serializeUint32(18)
   406  	gotKey = iter.Key()
   407  	if !bytes.Equal(gotKey, wantKey) {
   408  		t.Fatalf("ForceReseek.Key: unexpected key - got %x, want %x",
   409  			gotKey, wantKey)
   410  	}
   411  }
   412  
   413  // TestImmutableIterator ensures that the general behavior of immutable treap
   414  // iterators is as expected including tests for first, last, ordered and reverse
   415  // ordered iteration, limiting the range, seeking, and initially unpositioned.
   416  func TestImmutableIterator(t *testing.T) {
   417  	t.Parallel()
   418  
   419  	tests := []struct {
   420  		numKeys       int
   421  		step          int
   422  		startKey      []byte
   423  		limitKey      []byte
   424  		expectedFirst []byte
   425  		expectedLast  []byte
   426  		seekKey       []byte
   427  		expectedSeek  []byte
   428  	}{
   429  		// No range limits.  Values are the set (0, 1, 2, ..., 49).
   430  		// Seek existing value.
   431  		{
   432  			numKeys:       50,
   433  			step:          1,
   434  			expectedFirst: serializeUint32(0),
   435  			expectedLast:  serializeUint32(49),
   436  			seekKey:       serializeUint32(12),
   437  			expectedSeek:  serializeUint32(12),
   438  		},
   439  
   440  		// Limited to range [24, end].  Values are the set
   441  		// (0, 2, 4, ..., 48).  Seek value that doesn't exist and is
   442  		// greater than largest existing key.
   443  		{
   444  			numKeys:       50,
   445  			step:          2,
   446  			startKey:      serializeUint32(24),
   447  			expectedFirst: serializeUint32(24),
   448  			expectedLast:  serializeUint32(48),
   449  			seekKey:       serializeUint32(49),
   450  			expectedSeek:  nil,
   451  		},
   452  
   453  		// Limited to range [start, 25).  Values are the set
   454  		// (0, 3, 6, ..., 48).  Seek value that doesn't exist but is
   455  		// before an existing value within the range.
   456  		{
   457  			numKeys:       50,
   458  			step:          3,
   459  			limitKey:      serializeUint32(25),
   460  			expectedFirst: serializeUint32(0),
   461  			expectedLast:  serializeUint32(24),
   462  			seekKey:       serializeUint32(17),
   463  			expectedSeek:  serializeUint32(18),
   464  		},
   465  
   466  		// Limited to range [10, 21).  Values are the set
   467  		// (0, 4, ..., 48).  Seek value that exists, but is before the
   468  		// minimum allowed range.
   469  		{
   470  			numKeys:       50,
   471  			step:          4,
   472  			startKey:      serializeUint32(10),
   473  			limitKey:      serializeUint32(21),
   474  			expectedFirst: serializeUint32(12),
   475  			expectedLast:  serializeUint32(20),
   476  			seekKey:       serializeUint32(4),
   477  			expectedSeek:  nil,
   478  		},
   479  
   480  		// Limited by prefix {0,0,0}, range [{0,0,0}, {0,0,1}).
   481  		// Since it's a bytewise compare,  {0,0,0,...} < {0,0,1}.
   482  		// Seek existing value within the allowed range.
   483  		{
   484  			numKeys:       300,
   485  			step:          1,
   486  			startKey:      []byte{0x00, 0x00, 0x00},
   487  			limitKey:      []byte{0x00, 0x00, 0x01},
   488  			expectedFirst: serializeUint32(0),
   489  			expectedLast:  serializeUint32(255),
   490  			seekKey:       serializeUint32(100),
   491  			expectedSeek:  serializeUint32(100),
   492  		},
   493  	}
   494  
   495  testLoop:
   496  	for i, test := range tests {
   497  		// Insert a bunch of keys.
   498  		testTreap := NewImmutable()
   499  		for i := 0; i < test.numKeys; i += test.step {
   500  			key := serializeUint32(uint32(i))
   501  			testTreap = testTreap.Put(key, key)
   502  		}
   503  
   504  		// Create new iterator limited by the test params.
   505  		iter := testTreap.Iterator(test.startKey, test.limitKey)
   506  
   507  		// Ensure the first item is accurate.
   508  		hasFirst := iter.First()
   509  		if !hasFirst && test.expectedFirst != nil {
   510  			t.Errorf("First #%d: unexpected exhausted iterator", i)
   511  			continue
   512  		}
   513  		gotKey := iter.Key()
   514  		if !bytes.Equal(gotKey, test.expectedFirst) {
   515  			t.Errorf("First.Key #%d: unexpected key - got %x, "+
   516  				"want %x", i, gotKey, test.expectedFirst)
   517  			continue
   518  		}
   519  		gotVal := iter.Value()
   520  		if !bytes.Equal(gotVal, test.expectedFirst) {
   521  			t.Errorf("First.Value #%d: unexpected value - got %x, "+
   522  				"want %x", i, gotVal, test.expectedFirst)
   523  			continue
   524  		}
   525  
   526  		// Ensure the iterator gives the expected items in order.
   527  		curNum := binary.BigEndian.Uint32(test.expectedFirst)
   528  		for iter.Next() {
   529  			curNum += uint32(test.step)
   530  
   531  			// Ensure key is as expected.
   532  			gotKey := iter.Key()
   533  			expectedKey := serializeUint32(curNum)
   534  			if !bytes.Equal(gotKey, expectedKey) {
   535  				t.Errorf("iter.Key #%d (%d): unexpected key - "+
   536  					"got %x, want %x", i, curNum, gotKey,
   537  					expectedKey)
   538  				continue testLoop
   539  			}
   540  
   541  			// Ensure value is as expected.
   542  			gotVal := iter.Value()
   543  			if !bytes.Equal(gotVal, expectedKey) {
   544  				t.Errorf("iter.Value #%d (%d): unexpected "+
   545  					"value - got %x, want %x", i, curNum,
   546  					gotVal, expectedKey)
   547  				continue testLoop
   548  			}
   549  		}
   550  
   551  		// Ensure iterator is exhausted.
   552  		if iter.Valid() {
   553  			t.Errorf("Valid #%d: iterator should be exhausted", i)
   554  			continue
   555  		}
   556  
   557  		// Ensure the last item is accurate.
   558  		hasLast := iter.Last()
   559  		if !hasLast && test.expectedLast != nil {
   560  			t.Errorf("Last #%d: unexpected exhausted iterator", i)
   561  			continue
   562  		}
   563  		gotKey = iter.Key()
   564  		if !bytes.Equal(gotKey, test.expectedLast) {
   565  			t.Errorf("Last.Key #%d: unexpected key - got %x, "+
   566  				"want %x", i, gotKey, test.expectedLast)
   567  			continue
   568  		}
   569  		gotVal = iter.Value()
   570  		if !bytes.Equal(gotVal, test.expectedLast) {
   571  			t.Errorf("Last.Value #%d: unexpected value - got %x, "+
   572  				"want %x", i, gotVal, test.expectedLast)
   573  			continue
   574  		}
   575  
   576  		// Ensure the iterator gives the expected items in reverse
   577  		// order.
   578  		curNum = binary.BigEndian.Uint32(test.expectedLast)
   579  		for iter.Prev() {
   580  			curNum -= uint32(test.step)
   581  
   582  			// Ensure key is as expected.
   583  			gotKey := iter.Key()
   584  			expectedKey := serializeUint32(curNum)
   585  			if !bytes.Equal(gotKey, expectedKey) {
   586  				t.Errorf("iter.Key #%d (%d): unexpected key - "+
   587  					"got %x, want %x", i, curNum, gotKey,
   588  					expectedKey)
   589  				continue testLoop
   590  			}
   591  
   592  			// Ensure value is as expected.
   593  			gotVal := iter.Value()
   594  			if !bytes.Equal(gotVal, expectedKey) {
   595  				t.Errorf("iter.Value #%d (%d): unexpected "+
   596  					"value - got %x, want %x", i, curNum,
   597  					gotVal, expectedKey)
   598  				continue testLoop
   599  			}
   600  		}
   601  
   602  		// Ensure iterator is exhausted.
   603  		if iter.Valid() {
   604  			t.Errorf("Valid #%d: iterator should be exhausted", i)
   605  			continue
   606  		}
   607  
   608  		// Seek to the provided key.
   609  		seekValid := iter.Seek(test.seekKey)
   610  		if !seekValid && test.expectedSeek != nil {
   611  			t.Errorf("Seek #%d: unexpected exhausted iterator", i)
   612  			continue
   613  		}
   614  		gotKey = iter.Key()
   615  		if !bytes.Equal(gotKey, test.expectedSeek) {
   616  			t.Errorf("Seek.Key #%d: unexpected key - got %x, "+
   617  				"want %x", i, gotKey, test.expectedSeek)
   618  			continue
   619  		}
   620  		gotVal = iter.Value()
   621  		if !bytes.Equal(gotVal, test.expectedSeek) {
   622  			t.Errorf("Seek.Value #%d: unexpected value - got %x, "+
   623  				"want %x", i, gotVal, test.expectedSeek)
   624  			continue
   625  		}
   626  
   627  		// Recreate the iterator and ensure calling Next on it before it
   628  		// has been positioned gives the first element.
   629  		iter = testTreap.Iterator(test.startKey, test.limitKey)
   630  		hasNext := iter.Next()
   631  		if !hasNext && test.expectedFirst != nil {
   632  			t.Errorf("Next #%d: unexpected exhausted iterator", i)
   633  			continue
   634  		}
   635  		gotKey = iter.Key()
   636  		if !bytes.Equal(gotKey, test.expectedFirst) {
   637  			t.Errorf("Next.Key #%d: unexpected key - got %x, "+
   638  				"want %x", i, gotKey, test.expectedFirst)
   639  			continue
   640  		}
   641  		gotVal = iter.Value()
   642  		if !bytes.Equal(gotVal, test.expectedFirst) {
   643  			t.Errorf("Next.Value #%d: unexpected value - got %x, "+
   644  				"want %x", i, gotVal, test.expectedFirst)
   645  			continue
   646  		}
   647  
   648  		// Recreate the iterator and ensure calling Prev on it before it
   649  		// has been positioned gives the first element.
   650  		iter = testTreap.Iterator(test.startKey, test.limitKey)
   651  		hasPrev := iter.Prev()
   652  		if !hasPrev && test.expectedLast != nil {
   653  			t.Errorf("Prev #%d: unexpected exhausted iterator", i)
   654  			continue
   655  		}
   656  		gotKey = iter.Key()
   657  		if !bytes.Equal(gotKey, test.expectedLast) {
   658  			t.Errorf("Prev.Key #%d: unexpected key - got %x, "+
   659  				"want %x", i, gotKey, test.expectedLast)
   660  			continue
   661  		}
   662  		gotVal = iter.Value()
   663  		if !bytes.Equal(gotVal, test.expectedLast) {
   664  			t.Errorf("Next.Value #%d: unexpected value - got %x, "+
   665  				"want %x", i, gotVal, test.expectedLast)
   666  			continue
   667  		}
   668  	}
   669  }
   670  
   671  // TestImmutableEmptyIterator ensures that the various functions behave as
   672  // expected when an immutable treap is empty.
   673  func TestImmutableEmptyIterator(t *testing.T) {
   674  	t.Parallel()
   675  
   676  	// Create iterator against empty treap.
   677  	testTreap := NewImmutable()
   678  	iter := testTreap.Iterator(nil, nil)
   679  
   680  	// Ensure Valid on empty iterator reports it as exhausted.
   681  	if iter.Valid() {
   682  		t.Fatal("Valid: iterator should be exhausted")
   683  	}
   684  
   685  	// Ensure First and Last on empty iterator report it as exhausted.
   686  	if iter.First() {
   687  		t.Fatal("First: iterator should be exhausted")
   688  	}
   689  	if iter.Last() {
   690  		t.Fatal("Last: iterator should be exhausted")
   691  	}
   692  
   693  	// Ensure Next and Prev on empty iterator report it as exhausted.
   694  	if iter.Next() {
   695  		t.Fatal("Next: iterator should be exhausted")
   696  	}
   697  	if iter.Prev() {
   698  		t.Fatal("Prev: iterator should be exhausted")
   699  	}
   700  
   701  	// Ensure Key and Value on empty iterator are nil.
   702  	if gotKey := iter.Key(); gotKey != nil {
   703  		t.Fatalf("Key: should be nil - got %q", gotKey)
   704  	}
   705  	if gotVal := iter.Value(); gotVal != nil {
   706  		t.Fatalf("Value: should be nil - got %q", gotVal)
   707  	}
   708  
   709  	// Ensure calling ForceReseek on an immutable treap iterator does not
   710  	// cause any issues since it only applies to mutable treap iterators.
   711  	iter.ForceReseek()
   712  	if iter.Next() {
   713  		t.Fatal("Next: iterator should be exhausted")
   714  	}
   715  	iter.ForceReseek()
   716  	if iter.Prev() {
   717  		t.Fatal("Prev: iterator should be exhausted")
   718  	}
   719  }