github.com/ethersphere/bee/v2@v2.2.0/pkg/storer/pinstore_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 storer_test 6 7 import ( 8 "context" 9 "fmt" 10 "testing" 11 "time" 12 13 chunktesting "github.com/ethersphere/bee/v2/pkg/storage/testing" 14 storer "github.com/ethersphere/bee/v2/pkg/storer" 15 "github.com/ethersphere/bee/v2/pkg/swarm" 16 ) 17 18 func testPinStore(t *testing.T, newStorer func() (*storer.DB, error)) { 19 t.Helper() 20 21 testCases := []struct { 22 chunks []swarm.Chunk 23 fail bool 24 }{ 25 { 26 chunks: chunktesting.GenerateTestRandomChunks(10), 27 }, 28 { 29 chunks: chunktesting.GenerateTestRandomChunks(20), 30 fail: true, 31 }, 32 { 33 chunks: chunktesting.GenerateTestRandomChunks(30), 34 }, 35 } 36 37 lstore, err := newStorer() 38 if err != nil { 39 t.Fatal(err) 40 } 41 42 for _, tc := range testCases { 43 testName := fmt.Sprintf("pin_%d_chunks", len(tc.chunks)) 44 if tc.fail { 45 testName += "_rollback" 46 } 47 t.Run(testName, func(t *testing.T) { 48 session, err := lstore.NewCollection(context.TODO()) 49 if err != nil { 50 t.Fatalf("NewCollection(...): unexpected error: %v", err) 51 } 52 53 for _, ch := range tc.chunks { 54 err := session.Put(context.TODO(), ch) 55 if err != nil { 56 t.Fatalf("session.Put(...): unexpected error: %v", err) 57 t.Fatal(err) 58 } 59 } 60 61 if tc.fail { 62 err := session.Cleanup() 63 if err != nil { 64 t.Fatalf("session.Cleanup(): unexpected error: %v", err) 65 } 66 } else { 67 err := session.Done(tc.chunks[0].Address()) 68 if err != nil { 69 t.Fatalf("session.Done(...): unexpected error: %v", err) 70 } 71 } 72 verifyPinCollection(t, lstore.Storage(), tc.chunks[0], tc.chunks, !tc.fail) 73 }) 74 } 75 76 for _, tc := range testCases { 77 t.Run("has "+tc.chunks[0].Address().String(), func(t *testing.T) { 78 hasFound, err := lstore.HasPin(tc.chunks[0].Address()) 79 if err != nil { 80 t.Fatalf("HasPin(...): unexpected error: %v", err) 81 } 82 if hasFound != !tc.fail { 83 t.Fatalf("unexpected has chunk state: want %t have %t", !tc.fail, hasFound) 84 } 85 }) 86 } 87 88 t.Run("pins", func(t *testing.T) { 89 pins, err := lstore.Pins() 90 if err != nil { 91 t.Fatalf("Pins(): unexpected error: %v", err) 92 } 93 94 want := 2 95 if len(pins) != want { 96 t.Fatalf("unexpected no of pins: want %d have %d", want, len(pins)) 97 } 98 }) 99 100 t.Run("delete pin", func(t *testing.T) { 101 t.Run("commit", func(t *testing.T) { 102 err := lstore.DeletePin(context.TODO(), testCases[2].chunks[0].Address()) 103 if err != nil { 104 t.Fatalf("DeletePin(...): unexpected error: %v", err) 105 } 106 107 verifyPinCollection(t, lstore.Storage(), testCases[2].chunks[0], testCases[2].chunks, false) 108 }) 109 }) 110 111 t.Run("duplicate parallel upload does not leave orphaned chunks", func(t *testing.T) { 112 chunks := chunktesting.GenerateTestRandomChunks(4) 113 114 session1, err := lstore.NewCollection(context.TODO()) 115 if err != nil { 116 t.Fatalf("NewCollection(...): unexpected error: %v", err) 117 } 118 119 session2, err := lstore.NewCollection(context.TODO()) 120 if err != nil { 121 t.Fatalf("NewCollection2(...): unexpected error: %v", err) 122 } 123 124 for _, ch := range chunks { 125 err := session2.Put(context.TODO(), ch) 126 if err != nil { 127 t.Fatalf("session2.Put(...): unexpected error: %v", err) 128 t.Fatal(err) 129 } 130 131 err = session1.Put(context.TODO(), ch) 132 if err != nil { 133 t.Fatalf("session1.Put(...): unexpected error: %v", err) 134 t.Fatal(err) 135 } 136 } 137 138 err = session1.Done(chunks[0].Address()) 139 if err != nil { 140 t.Fatalf("session1.Done(...): unexpected error: %v", err) 141 } 142 143 err = session2.Done(chunks[0].Address()) 144 if err == nil { 145 t.Fatalf("session2.Done(...): expected error, got nil") 146 } 147 148 if err := session2.Cleanup(); err != nil { 149 t.Fatalf("session2.Done(...): unexpected error: %v", err) 150 } 151 152 verifyPinCollection(t, lstore.Storage(), chunks[0], chunks, true) 153 verifyChunkRefCount(t, lstore.Storage(), chunks) 154 }) 155 } 156 157 func TestPinStore(t *testing.T) { 158 t.Parallel() 159 160 t.Run("inmem", func(t *testing.T) { 161 t.Parallel() 162 163 testPinStore(t, func() (*storer.DB, error) { 164 return storer.New(context.Background(), "", dbTestOps(swarm.RandAddress(t), 0, nil, nil, time.Second)) 165 }) 166 }) 167 t.Run("disk", func(t *testing.T) { 168 t.Parallel() 169 170 testPinStore(t, diskStorer(t, dbTestOps(swarm.RandAddress(t), 0, nil, nil, time.Second))) 171 }) 172 }