github.com/ethersphere/bee/v2@v2.2.0/pkg/storage/storagetest/batch.go (about)

     1  // Copyright 2022 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package storagetest
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"testing"
    11  
    12  	"github.com/ethersphere/bee/v2/pkg/storage"
    13  	"github.com/google/go-cmp/cmp"
    14  )
    15  
    16  func TestBatchedStore(t *testing.T, bs storage.BatchStore) {
    17  	item := &obj1{Id: "id", SomeInt: 1, Buf: []byte("data")}
    18  
    19  	t.Run("duplicates are rejected", func(t *testing.T) {
    20  		batch := bs.Batch(context.Background())
    21  
    22  		if err := batch.Put(item); err != nil {
    23  			t.Fatalf("Put(...): unexpected error: %v", err)
    24  		}
    25  
    26  		if err := batch.Put(item); err != nil {
    27  			t.Fatalf("Put(...): unexpected error: %v", err)
    28  		}
    29  		if err := batch.Commit(); err != nil {
    30  			t.Fatalf("Commit(): unexpected error: %v", err)
    31  		}
    32  
    33  		var cnt int
    34  		err := bs.Iterate(storage.Query{
    35  			Factory:      func() storage.Item { return new(obj1) },
    36  			ItemProperty: storage.QueryItem,
    37  		}, func(r storage.Result) (bool, error) {
    38  			if cnt++; cnt > 1 {
    39  				t.Fatalf("Iterate(...): duplicate detected: %v", r.Entry)
    40  			}
    41  
    42  			want, have := item, r.Entry
    43  			if diff := cmp.Diff(want, have); diff != "" {
    44  				t.Errorf("Iterate(...): unexpected result: (-want +have):\n%s", diff)
    45  			}
    46  			return false, nil
    47  		})
    48  		if err != nil {
    49  			t.Fatalf("Iterate(...): unexpected error: %v", err)
    50  		}
    51  	})
    52  
    53  	t.Run("only last ops are of interest", func(t *testing.T) {
    54  		if err := bs.Put(item); err != nil {
    55  			t.Fatalf("Put(...): unexpected error: %v", err)
    56  		}
    57  
    58  		batch := bs.Batch(context.Background())
    59  
    60  		if err := batch.Put(item); err != nil {
    61  			t.Fatalf("Put(...): unexpected error: %v", err)
    62  		}
    63  		if err := batch.Delete(item); err != nil {
    64  			t.Fatalf("Delete(...): unexpected error: %v", err)
    65  		}
    66  
    67  		if err := batch.Commit(); err != nil {
    68  			t.Fatalf("Commit(): unexpected error: %v", err)
    69  		}
    70  
    71  		err := bs.Iterate(storage.Query{
    72  			Factory:      func() storage.Item { return new(obj1) },
    73  			ItemProperty: storage.QueryItem,
    74  		}, func(r storage.Result) (bool, error) {
    75  			t.Fatalf("expected empty store, got %v", r.Entry)
    76  			return true, nil
    77  		})
    78  		if err != nil {
    79  			t.Fatal("iterate", err)
    80  		}
    81  	})
    82  
    83  	t.Run("batch not reusable after commit", func(t *testing.T) {
    84  		batch := bs.Batch(context.Background())
    85  		if err := batch.Commit(); err != nil {
    86  			t.Fatalf("Commit(): unexpected error: %v", err)
    87  		}
    88  		if err := batch.Commit(); err == nil {
    89  			t.Fatal("Commit(): expected error; have none")
    90  		}
    91  	})
    92  
    93  	t.Run("batch not usable with expired context", func(t *testing.T) {
    94  		ctx, cancel := context.WithCancel(context.Background())
    95  
    96  		batch := bs.Batch(ctx)
    97  
    98  		if err := batch.Put(item); err != nil {
    99  			t.Fatalf("Put(...): unexpected error: %v", err)
   100  		}
   101  
   102  		cancel()
   103  		have := batch.Commit()
   104  		want := context.Canceled
   105  		if !errors.Is(have, want) {
   106  			t.Fatalf("Commit(): want error: %v; have error: %v", want, have)
   107  		}
   108  	})
   109  
   110  	t.Run("close", func(t *testing.T) {
   111  		err := bs.Close()
   112  		if err != nil {
   113  			t.Fatalf("failed closing: %v", err)
   114  		}
   115  	})
   116  }