github.com/ethersphere/bee/v2@v2.2.0/pkg/storer/mock/mockstorer_test.go (about)

     1  // Copyright 2023 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 mockstorer_test
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"fmt"
    11  	"os"
    12  	"testing"
    13  	"time"
    14  
    15  	storage "github.com/ethersphere/bee/v2/pkg/storage"
    16  	chunktesting "github.com/ethersphere/bee/v2/pkg/storage/testing"
    17  	storer "github.com/ethersphere/bee/v2/pkg/storer"
    18  	mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock"
    19  	"github.com/ethersphere/bee/v2/pkg/swarm"
    20  	"github.com/google/go-cmp/cmp"
    21  )
    22  
    23  var now = func() time.Time { return time.Unix(1234567890, 0) }
    24  
    25  // TestMain exists to adjust the time.Now function to a fixed value.
    26  func TestMain(m *testing.M) {
    27  	mockstorer.ReplaceTimeNow(now)
    28  	code := m.Run()
    29  	mockstorer.ReplaceTimeNow(time.Now)
    30  	os.Exit(code)
    31  }
    32  
    33  func TestMockStorer(t *testing.T) {
    34  	t.Parallel()
    35  
    36  	mockStorer := mockstorer.New()
    37  
    38  	t.Run("new session", func(t *testing.T) {
    39  		have, err := mockStorer.NewSession()
    40  		if err != nil {
    41  			t.Fatalf("NewSession(): unexpected error: %v", err)
    42  		}
    43  
    44  		want := storer.SessionInfo{TagID: 1, StartedAt: now().UnixNano()}
    45  
    46  		if diff := cmp.Diff(want, have); diff != "" {
    47  			t.Fatalf("unexpected session info: (-want +have):\n%s", diff)
    48  		}
    49  	})
    50  
    51  	t.Run("get session", func(t *testing.T) {
    52  		have, err := mockStorer.Session(1)
    53  		if err != nil {
    54  			t.Fatalf("Session(): unexpected error: %v", err)
    55  		}
    56  
    57  		want := storer.SessionInfo{TagID: 1, StartedAt: now().UnixNano()}
    58  
    59  		if diff := cmp.Diff(want, have); diff != "" {
    60  			t.Fatalf("unexpected session info: (-want +have):\n%s", diff)
    61  		}
    62  	})
    63  
    64  	t.Run("list sessions", func(t *testing.T) {
    65  		have, err := mockStorer.ListSessions(0, 1)
    66  		if err != nil {
    67  			t.Fatalf("ListSessions(): unexpected error: %v", err)
    68  		}
    69  
    70  		want := []storer.SessionInfo{
    71  			{TagID: 1, StartedAt: now().UnixNano()},
    72  		}
    73  
    74  		if diff := cmp.Diff(want, have); diff != "" {
    75  			t.Fatalf("unexpected session info: (-want +have):\n%s", diff)
    76  		}
    77  	})
    78  
    79  	t.Run("delete session", func(t *testing.T) {
    80  		if err := mockStorer.DeleteSession(1); err != nil {
    81  			t.Fatalf("DeleteSession(): unexpected error: %v", err)
    82  		}
    83  
    84  		want := storage.ErrNotFound
    85  		_, have := mockStorer.Session(1)
    86  		if !errors.Is(want, have) {
    87  			t.Fatalf("Session(): unexpected error: want %v have %v", want, have)
    88  		}
    89  	})
    90  
    91  	verifyChunksAndPin := func(t *testing.T, chunks []swarm.Chunk, root swarm.Address) {
    92  		t.Helper()
    93  
    94  		for _, ch := range chunks {
    95  			has, err := mockStorer.ChunkStore().Has(context.Background(), ch.Address())
    96  			if err != nil {
    97  				t.Fatalf("Has(...): unexpected error: %v", err)
    98  			}
    99  
   100  			if !has {
   101  				t.Fatalf("expected chunk to be found %s", ch.Address())
   102  			}
   103  		}
   104  
   105  		has, err := mockStorer.HasPin(root)
   106  		if err != nil {
   107  			t.Fatalf("HasPin(...): unexpected error: %v", err)
   108  		}
   109  
   110  		if !has {
   111  			t.Fatalf("expected to find root pin %s", root)
   112  		}
   113  
   114  		pins, err := mockStorer.Pins()
   115  		if err != nil {
   116  			t.Fatalf("Pins(): unexpected error: %v", err)
   117  		}
   118  
   119  		found := false
   120  		for _, p := range pins {
   121  			if p.Equal(root) {
   122  				found = true
   123  				break
   124  			}
   125  		}
   126  
   127  		if !found {
   128  			t.Fatalf("expected to find pin in list %s", root)
   129  		}
   130  	}
   131  
   132  	t.Run("upload", func(t *testing.T) {
   133  		session, err := mockStorer.NewSession()
   134  		if err != nil {
   135  			t.Fatalf("NewSession(): unexpected error: %v", err)
   136  		}
   137  
   138  		chunks := chunktesting.GenerateTestRandomChunks(5)
   139  		putter, err := mockStorer.Upload(context.Background(), true, session.TagID)
   140  		if err != nil {
   141  			t.Fatalf("Upload(...): unexpected error: %v", err)
   142  		}
   143  
   144  		for _, ch := range chunks {
   145  			err = putter.Put(context.Background(), ch)
   146  			if err != nil {
   147  				t.Fatalf("Put(...): unexpected error: %v", err)
   148  			}
   149  		}
   150  
   151  		err = putter.Done(chunks[0].Address())
   152  		if err != nil {
   153  			t.Fatalf("Done(...): unexpected error: %v", err)
   154  		}
   155  
   156  		have, err := mockStorer.Session(session.TagID)
   157  		if err != nil {
   158  			t.Fatalf("Session(...): unexpected error: %v", err)
   159  		}
   160  
   161  		want := storer.SessionInfo{
   162  			TagID:     session.TagID,
   163  			StartedAt: session.StartedAt,
   164  			Address:   chunks[0].Address(),
   165  		}
   166  
   167  		if diff := cmp.Diff(want, have); diff != "" {
   168  			t.Fatalf("unexpected session info: (-want +have):\n%s", diff)
   169  		}
   170  
   171  		verifyChunksAndPin(t, chunks, chunks[0].Address())
   172  	})
   173  
   174  	t.Run("pin", func(t *testing.T) {
   175  		putter, err := mockStorer.NewCollection(context.Background())
   176  		if err != nil {
   177  			t.Fatalf("NewCollection(): unexpected error: %v", err)
   178  		}
   179  
   180  		chunks := chunktesting.GenerateTestRandomChunks(5)
   181  		for _, ch := range chunks {
   182  			err = putter.Put(context.Background(), ch)
   183  			if err != nil {
   184  				t.Fatalf("Put(...): unexpected error: %v", err)
   185  			}
   186  		}
   187  
   188  		err = putter.Done(chunks[0].Address())
   189  		if err != nil {
   190  			t.Fatalf("Done(...): unexpected error: %v", err)
   191  		}
   192  
   193  		verifyChunksAndPin(t, chunks, chunks[0].Address())
   194  	})
   195  
   196  	t.Run("direct upload", func(t *testing.T) {
   197  		putter := mockStorer.DirectUpload()
   198  
   199  		chunks := chunktesting.GenerateTestRandomChunks(5)
   200  		done := make(chan struct{})
   201  		go func() {
   202  			defer close(done)
   203  
   204  			i := 0
   205  			for op := range mockStorer.PusherFeed() {
   206  				if !op.Chunk.Equal(chunks[i]) {
   207  					op.Err <- fmt.Errorf("invalid chunk %s", op.Chunk.Address())
   208  					break
   209  				}
   210  				op.Err <- nil
   211  				i++
   212  				if i == len(chunks) {
   213  					break
   214  				}
   215  			}
   216  		}()
   217  
   218  		for _, ch := range chunks {
   219  			err := putter.Put(context.Background(), ch)
   220  			if err != nil {
   221  				t.Fatalf("Put(...): unexpected error: %v", err)
   222  			}
   223  		}
   224  
   225  		err := putter.Done(swarm.ZeroAddress)
   226  		if err != nil {
   227  			t.Fatalf("Done(...): unexpected error: %v", err)
   228  		}
   229  
   230  		select {
   231  		case <-done:
   232  		case <-time.After(3 * time.Second):
   233  			t.Fatalf("expected to be done by now")
   234  		}
   235  	})
   236  
   237  	t.Run("delete pin", func(t *testing.T) {
   238  		pins, err := mockStorer.Pins()
   239  		if err != nil {
   240  			t.Fatalf("Pins(): unexpected error: %v", err)
   241  		}
   242  
   243  		for _, p := range pins {
   244  			err := mockStorer.DeletePin(context.Background(), p)
   245  			if err != nil {
   246  				t.Fatalf("DeletePin(...): unexpected error: %v", err)
   247  			}
   248  		}
   249  
   250  		for _, p := range pins {
   251  			has, err := mockStorer.HasPin(p)
   252  			if err != nil {
   253  				t.Fatalf("HasPin(...): unexpected error: %v", err)
   254  			}
   255  
   256  			if has {
   257  				t.Fatalf("expected pin to be deleted %s", p)
   258  			}
   259  		}
   260  
   261  		pins, err = mockStorer.Pins()
   262  		if err != nil {
   263  			t.Fatalf("Pins(): unexpected error: %v", err)
   264  		}
   265  		if len(pins) != 0 {
   266  			t.Fatalf("expected all pins to be deleted, found %d", len(pins))
   267  		}
   268  	})
   269  }