github.com/iotexproject/iotex-core@v1.14.1-rc1/db/range_index_test.go (about)

     1  // Copyright (c) 2019 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package db
     7  
     8  import (
     9  	"context"
    10  	"math/rand"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/iotexproject/iotex-core/testutil"
    16  )
    17  
    18  func TestRangeIndex(t *testing.T) {
    19  	require := require.New(t)
    20  
    21  	rangeTests := []struct {
    22  		k uint64
    23  		v []byte
    24  	}{
    25  		{1, []byte("beyond")},
    26  		{7, []byte("seven")},
    27  		{29, []byte("twenty-nine")},
    28  		{100, []byte("hundred")},
    29  		{999, []byte("nine-nine-nine")},
    30  	}
    31  
    32  	path := "test-indexer"
    33  	testPath, err := testutil.PathOfTempFile(path)
    34  	require.NoError(err)
    35  	cfg := DefaultConfig
    36  	cfg.DbPath = testPath
    37  	defer testutil.CleanupPath(testPath)
    38  
    39  	kv := NewBoltDB(cfg)
    40  	require.NotNil(kv)
    41  
    42  	require.NoError(kv.Start(context.Background()))
    43  	defer func() {
    44  		require.NoError(kv.Stop(context.Background()))
    45  	}()
    46  
    47  	index, err := NewRangeIndex(kv, []byte("test"), NotExist)
    48  	require.NoError(err)
    49  	v, err := index.Get(0)
    50  	require.NoError(err)
    51  	require.Equal(NotExist, v)
    52  	v, err = index.Get(1)
    53  	require.NoError(err)
    54  	require.Equal(NotExist, v)
    55  
    56  	// cannot insert 0
    57  	require.Error(index.Insert(0, NotExist))
    58  
    59  	for i, e := range rangeTests {
    60  		require.NoError(index.Insert(e.k, e.v))
    61  		if i == 0 {
    62  			v, err = index.Get(rangeTests[0].k)
    63  			require.NoError(err)
    64  			require.Equal(rangeTests[0].v, v)
    65  			continue
    66  		}
    67  		// test 5 random keys between the new and previous insertion
    68  		gap := e.k - rangeTests[i-1].k
    69  		for j := 0; j < 5; j++ {
    70  			k := rangeTests[i-1].k + uint64(rand.Intn(int(gap)))
    71  			v, err = index.Get(k)
    72  			require.NoError(err)
    73  			require.Equal(rangeTests[i-1].v, v)
    74  		}
    75  		v, err = index.Get(e.k - 1)
    76  		require.NoError(err)
    77  		require.Equal(rangeTests[i-1].v, v)
    78  		v, err = index.Get(e.k)
    79  		require.NoError(err)
    80  		require.Equal(e.v, v)
    81  
    82  		// test 5 random keys beyond new insertion
    83  		for j := 0; j < 5; j++ {
    84  			k := e.k + uint64(rand.Int())
    85  			v, err = index.Get(k)
    86  			require.NoError(err)
    87  			require.Equal(e.v, v)
    88  		}
    89  	}
    90  
    91  	// delete rangeTests[1].k
    92  	require.NoError(index.Delete(rangeTests[0].k))
    93  	require.NoError(index.Delete(rangeTests[1].k))
    94  	v, err = index.Get(rangeTests[1].k)
    95  	require.NoError(err)
    96  	require.Equal(NotExist, v)
    97  	for i := 2; i < len(rangeTests); i++ {
    98  		v, err = index.Get(rangeTests[i].k)
    99  		require.NoError(err)
   100  		require.Equal(rangeTests[i].v, v)
   101  		v, err = index.Get(rangeTests[i].k + 1)
   102  		require.NoError(err)
   103  		require.Equal(rangeTests[i].v, v)
   104  	}
   105  
   106  	// delete rangeTests[3].k
   107  	require.NoError(index.Delete(rangeTests[3].k))
   108  	for i := 2; i <= 3; i++ {
   109  		v, err = index.Get(rangeTests[i].k)
   110  		require.NoError(err)
   111  		require.Equal(rangeTests[2].v, v)
   112  		v, err = index.Get(rangeTests[i].k + 1)
   113  		require.NoError(err)
   114  		require.Equal(rangeTests[2].v, v)
   115  	}
   116  
   117  	// key 4 not affected
   118  	v, err = index.Get(rangeTests[4].k)
   119  	require.NoError(err)
   120  	require.Equal(rangeTests[4].v, v)
   121  	v, err = index.Get(rangeTests[4].k + 1)
   122  	require.NoError(err)
   123  	require.Equal(rangeTests[4].v, v)
   124  
   125  	// add rangeTests[3].k back with a diff value
   126  	rangeTests[3].v = []byte("not-hundred")
   127  	require.NoError(index.Insert(rangeTests[3].k, rangeTests[3].v))
   128  	for i := 2; i < len(rangeTests); i++ {
   129  		v, err = index.Get(rangeTests[i].k)
   130  		require.NoError(err)
   131  		require.Equal(rangeTests[i].v, v)
   132  		v, err = index.Get(rangeTests[i].k + 1)
   133  		require.NoError(err)
   134  		require.Equal(rangeTests[i].v, v)
   135  	}
   136  
   137  	// purge rangeTests[3].k
   138  	require.NoError(index.Purge(rangeTests[3].k))
   139  	for i := 1; i <= 3; i++ {
   140  		v, err = index.Get(rangeTests[i].k)
   141  		require.NoError(err)
   142  		require.Equal(NotExist, v)
   143  		v, err = index.Get(rangeTests[i].k + 1)
   144  		require.NoError(err)
   145  		require.Equal(NotExist, v)
   146  	}
   147  
   148  	// key 4 not affected
   149  	v, err = index.Get(rangeTests[4].k)
   150  	require.NoError(err)
   151  	require.Equal(rangeTests[4].v, v)
   152  	v, err = index.Get(rangeTests[4].k + 1)
   153  	require.NoError(err)
   154  	require.Equal(rangeTests[4].v, v)
   155  }
   156  
   157  func TestRangeIndex2(t *testing.T) {
   158  	require := require.New(t)
   159  
   160  	path := "test-ranger"
   161  	testPath, err := testutil.PathOfTempFile(path)
   162  	require.NoError(err)
   163  	cfg := DefaultConfig
   164  	cfg.DbPath = testPath
   165  	defer testutil.CleanupPath(testPath)
   166  
   167  	kv := NewBoltDB(cfg)
   168  	require.NotNil(kv)
   169  
   170  	require.NoError(kv.Start(context.Background()))
   171  	defer func() {
   172  		require.NoError(kv.Stop(context.Background()))
   173  	}()
   174  
   175  	testNS := []byte("test")
   176  	index, err := NewRangeIndex(kv, testNS, NotExist)
   177  	require.NoError(err)
   178  	// special case: insert 1
   179  	require.NoError(index.Insert(1, []byte("1")))
   180  	v, err := index.Get(5)
   181  	require.NoError(err)
   182  	require.Equal([]byte("1"), v)
   183  	// remove 1
   184  	require.NoError(index.Purge(1))
   185  	// insert 7
   186  	require.NoError(index.Insert(7, []byte("7")))
   187  	// Case I: key before 7
   188  	for i := uint64(1); i < 6; i++ {
   189  		v, err = index.Get(i)
   190  		require.NoError(err)
   191  		require.Equal(v, NotExist)
   192  	}
   193  	// Case II: key is 7 and greater than 7
   194  	for i := uint64(7); i < 10; i++ {
   195  		v, err = index.Get(i)
   196  		require.NoError(err)
   197  		require.Equal([]byte("7"), v)
   198  	}
   199  	// Case III: duplicate key
   200  	require.NoError(index.Insert(7, []byte("7777")))
   201  	for i := uint64(7); i < 10; i++ {
   202  		v, err = index.Get(i)
   203  		require.NoError(err)
   204  		require.Equal([]byte("7777"), v)
   205  	}
   206  	// Case IV: delete key less than 7
   207  	require.NoError(index.Insert(66, []byte("66")))
   208  	for i := uint64(1); i < 7; i++ {
   209  		err = index.Delete(i)
   210  		require.NoError(err)
   211  	}
   212  	v, err = index.Get(7)
   213  	require.NoError(err)
   214  	require.Equal([]byte("7777"), v)
   215  	// Case V: delete key 7
   216  	require.NoError(index.Purge(10))
   217  	for i := uint64(1); i < 66; i++ {
   218  		v, err = index.Get(i)
   219  		require.NoError(err)
   220  		require.Equal(v, NotExist)
   221  	}
   222  	for i := uint64(66); i < 70; i++ {
   223  		v, err = index.Get(i)
   224  		require.NoError(err)
   225  		require.Equal([]byte("66"), v)
   226  	}
   227  	// Case VI: delete key before 80,all keys deleted
   228  	require.NoError(index.Insert(70, []byte("70")))
   229  	require.NoError(index.Insert(80, []byte("80")))
   230  	require.NoError(index.Insert(91, []byte("91")))
   231  	require.NoError(index.Purge(79))
   232  	for i := uint64(1); i < 80; i++ {
   233  		v, err = index.Get(i)
   234  		require.NoError(err)
   235  		require.Equal(v, NotExist)
   236  	}
   237  	for i := uint64(80); i < 91; i++ {
   238  		v, err = index.Get(i)
   239  		require.NoError(err)
   240  		require.Equal([]byte("80"), v)
   241  	}
   242  	for i := uint64(91); i < 100; i++ {
   243  		v, err = index.Get(i)
   244  		require.NoError(err)
   245  		require.Equal([]byte("91"), v)
   246  	}
   247  }