github.com/koko1123/flow-go-1@v0.29.6/storage/badger/operation/modifiers_test.go (about)

     1  // (c) 2019 Dapper Labs - ALL RIGHTS RESERVED
     2  
     3  package operation
     4  
     5  import (
     6  	"errors"
     7  	"fmt"
     8  	"testing"
     9  
    10  	"github.com/dgraph-io/badger/v3"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  	"github.com/vmihailenco/msgpack/v4"
    14  
    15  	"github.com/koko1123/flow-go-1/storage"
    16  	"github.com/koko1123/flow-go-1/utils/unittest"
    17  )
    18  
    19  func TestSkipDuplicates(t *testing.T) {
    20  	unittest.RunWithBadgerDB(t, func(db *badger.DB) {
    21  		e := Entity{ID: 1337}
    22  		key := []byte{0x01, 0x02, 0x03}
    23  		val, _ := msgpack.Marshal(e)
    24  
    25  		// persist first time
    26  		err := db.Update(insert(key, e))
    27  		require.NoError(t, err)
    28  
    29  		e2 := Entity{ID: 1338}
    30  
    31  		// persist again
    32  		err = db.Update(SkipDuplicates(insert(key, e2)))
    33  		require.NoError(t, err)
    34  
    35  		// ensure old value is still used
    36  		var act []byte
    37  		_ = db.View(func(tx *badger.Txn) error {
    38  			item, err := tx.Get(key)
    39  			require.NoError(t, err)
    40  			act, err = item.ValueCopy(nil)
    41  			require.NoError(t, err)
    42  			return nil
    43  		})
    44  
    45  		assert.Equal(t, val, act)
    46  	})
    47  }
    48  
    49  func TestRetryOnConflict(t *testing.T) {
    50  	unittest.RunWithBadgerDB(t, func(db *badger.DB) {
    51  		t.Run("good op", func(t *testing.T) {
    52  			goodOp := func(*badger.Txn) error {
    53  				return nil
    54  			}
    55  			err := RetryOnConflict(db.Update, goodOp)
    56  			require.NoError(t, err)
    57  		})
    58  
    59  		t.Run("conflict op should be retried", func(t *testing.T) {
    60  			n := 0
    61  			conflictOp := func(*badger.Txn) error {
    62  				n++
    63  				if n > 3 {
    64  					return nil
    65  				}
    66  				return badger.ErrConflict
    67  			}
    68  			err := RetryOnConflict(db.Update, conflictOp)
    69  			require.NoError(t, err)
    70  		})
    71  
    72  		t.Run("wrapped conflict op should be retried", func(t *testing.T) {
    73  			n := 0
    74  			conflictOp := func(*badger.Txn) error {
    75  				n++
    76  				if n > 3 {
    77  					return nil
    78  				}
    79  				return fmt.Errorf("wrap error: %w", badger.ErrConflict)
    80  			}
    81  			err := RetryOnConflict(db.Update, conflictOp)
    82  			require.NoError(t, err)
    83  		})
    84  
    85  		t.Run("other error should be returned", func(t *testing.T) {
    86  			otherError := errors.New("other error")
    87  			failOp := func(*badger.Txn) error {
    88  				return otherError
    89  			}
    90  
    91  			err := RetryOnConflict(db.Update, failOp)
    92  			require.Equal(t, otherError, err)
    93  		})
    94  	})
    95  }
    96  
    97  func TestSkipNonExists(t *testing.T) {
    98  	unittest.RunWithBadgerDB(t, func(db *badger.DB) {
    99  		t.Run("not found", func(t *testing.T) {
   100  			op := func(*badger.Txn) error {
   101  				return badger.ErrKeyNotFound
   102  			}
   103  
   104  			err := db.Update(SkipNonExist(op))
   105  			require.NoError(t, err)
   106  		})
   107  
   108  		t.Run("not exist", func(t *testing.T) {
   109  			op := func(*badger.Txn) error {
   110  				return storage.ErrNotFound
   111  			}
   112  
   113  			err := db.Update(SkipNonExist(op))
   114  			require.NoError(t, err)
   115  		})
   116  
   117  		t.Run("general error", func(t *testing.T) {
   118  			expectError := fmt.Errorf("random error")
   119  			op := func(*badger.Txn) error {
   120  				return expectError
   121  			}
   122  
   123  			err := db.Update(SkipNonExist(op))
   124  			require.Equal(t, expectError, err)
   125  		})
   126  	})
   127  }