github.com/ethersphere/bee/v2@v2.2.0/pkg/storer/migration/step_06_test.go (about) 1 // Copyright 2024 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 migration_test 6 7 import ( 8 "context" 9 "testing" 10 11 "github.com/ethersphere/bee/v2/pkg/sharky" 12 "github.com/ethersphere/bee/v2/pkg/storage" 13 "github.com/ethersphere/bee/v2/pkg/storage/leveldbstore" 14 chunktest "github.com/ethersphere/bee/v2/pkg/storage/testing" 15 "github.com/ethersphere/bee/v2/pkg/storer/internal/chunkstamp" 16 "github.com/ethersphere/bee/v2/pkg/storer/internal/reserve" 17 "github.com/ethersphere/bee/v2/pkg/storer/internal/stampindex" 18 "github.com/ethersphere/bee/v2/pkg/storer/internal/transaction" 19 localmigration "github.com/ethersphere/bee/v2/pkg/storer/migration" 20 "github.com/ethersphere/bee/v2/pkg/swarm" 21 "github.com/stretchr/testify/assert" 22 "github.com/stretchr/testify/require" 23 ) 24 25 type oldAndNewItem[K storage.Item, V storage.Item] struct { 26 old K 27 new V 28 } 29 30 func Test_Step_06(t *testing.T) { 31 t.Parallel() 32 33 sharkyDir := t.TempDir() 34 sharkyStore, err := sharky.New(&dirFS{basedir: sharkyDir}, 1, swarm.SocMaxChunkSize) 35 require.NoError(t, err) 36 37 lstore, err := leveldbstore.New("", nil) 38 require.NoError(t, err) 39 40 store := transaction.NewStorage(sharkyStore, lstore) 41 t.Cleanup(func() { 42 err := store.Close() 43 require.NoError(t, err) 44 }) 45 46 chunks := chunktest.GenerateTestRandomChunks(100) 47 ctx := context.Background() 48 49 batchRadiusItems := make(map[string]oldAndNewItem[*reserve.BatchRadiusItemV1, *reserve.BatchRadiusItem]) 50 chunkBinItems := make(map[string]oldAndNewItem[*reserve.ChunkBinItemV1, *reserve.ChunkBinItem]) 51 stampIndexItems := make(map[string]oldAndNewItem[*stampindex.ItemV1, *stampindex.Item]) 52 53 for i, ch := range chunks { 54 err = store.Run(ctx, func(s transaction.Store) error { 55 b := &reserve.BatchRadiusItemV1{ 56 Bin: uint8(i), 57 BatchID: ch.Stamp().BatchID(), 58 Address: ch.Address(), 59 BinID: uint64(i), 60 } 61 err := s.IndexStore().Put(b) 62 if err != nil { 63 return err 64 } 65 batchRadiusItems[string(b.BatchID)+string(b.Bin)+b.Address.ByteString()] = oldAndNewItem[*reserve.BatchRadiusItemV1, *reserve.BatchRadiusItem]{old: b, new: nil} 66 67 c := &reserve.ChunkBinItemV1{ 68 Bin: uint8(i), 69 BinID: uint64(i), 70 Address: ch.Address(), 71 BatchID: ch.Stamp().BatchID(), 72 ChunkType: swarm.ChunkTypeSingleOwner, 73 } 74 err = s.IndexStore().Put(c) 75 if err != nil { 76 return err 77 } 78 chunkBinItems[c.ID()] = oldAndNewItem[*reserve.ChunkBinItemV1, *reserve.ChunkBinItem]{old: c, new: nil} 79 80 sIdxItem := &stampindex.ItemV1{ 81 BatchID: ch.Stamp().BatchID(), 82 StampIndex: ch.Stamp().Index(), 83 StampTimestamp: ch.Stamp().Timestamp(), 84 ChunkAddress: ch.Address(), 85 ChunkIsImmutable: true, 86 } 87 sIdxItem.SetNamespace([]byte("reserve")) 88 err = s.IndexStore().Put(sIdxItem) 89 if err != nil { 90 return err 91 } 92 93 stampIndexItems[sIdxItem.ID()] = oldAndNewItem[*stampindex.ItemV1, *stampindex.Item]{old: sIdxItem, new: nil} 94 95 return chunkstamp.Store(s.IndexStore(), "reserve", ch) 96 }) 97 require.NoError(t, err) 98 } 99 100 require.NoError(t, err) 101 err = localmigration.Step_06(store)() 102 require.NoError(t, err) 103 104 has, err := store.IndexStore().Has(&reserve.EpochItem{}) 105 if has { 106 t.Fatal("epoch item should be deleted") 107 } 108 require.NoError(t, err) 109 110 checkBatchRadiusItems(t, store.IndexStore(), len(chunks), batchRadiusItems) 111 checkChunkBinItems(t, store.IndexStore(), len(chunks), chunkBinItems) 112 checkStampIndex(t, store.IndexStore(), len(chunks), stampIndexItems) 113 } 114 115 func checkBatchRadiusItems(t *testing.T, s storage.Reader, wantCount int, m map[string]oldAndNewItem[*reserve.BatchRadiusItemV1, *reserve.BatchRadiusItem]) { 116 t.Helper() 117 count := 0 118 119 err := s.Iterate(storage.Query{ 120 Factory: func() storage.Item { return new(reserve.BatchRadiusItem) }, 121 }, func(result storage.Result) (bool, error) { 122 count++ 123 b := result.Entry.(*reserve.BatchRadiusItem) 124 id := string(b.BatchID) + string(b.Bin) + b.Address.ByteString() 125 found, ok := m[id] 126 require.True(t, ok) 127 found.new = b 128 m[id] = found 129 return false, nil 130 }) 131 require.NoError(t, err) 132 assert.Equal(t, wantCount, count) 133 134 for _, v := range m { 135 assert.Equal(t, v.old.Bin, v.new.Bin) 136 assert.Equal(t, v.old.BatchID, v.new.BatchID) 137 assert.Equal(t, v.old.Address, v.new.Address) 138 assert.Equal(t, v.old.BinID, v.new.BinID) 139 assert.NotEqual(t, swarm.EmptyAddress.Bytes(), v.new.StampHash) 140 } 141 } 142 143 func checkChunkBinItems(t *testing.T, s storage.Reader, wantCount int, m map[string]oldAndNewItem[*reserve.ChunkBinItemV1, *reserve.ChunkBinItem]) { 144 t.Helper() 145 count := 0 146 err := s.Iterate(storage.Query{ 147 Factory: func() storage.Item { return new(reserve.ChunkBinItem) }, 148 }, func(result storage.Result) (bool, error) { 149 count++ 150 b := result.Entry.(*reserve.ChunkBinItem) 151 found, ok := m[b.ID()] 152 require.True(t, ok) 153 found.new = b 154 m[b.ID()] = found 155 return false, nil 156 }) 157 require.NoError(t, err) 158 assert.Equal(t, wantCount, count) 159 for _, v := range m { 160 assert.Equal(t, v.old.Bin, v.new.Bin) 161 assert.Equal(t, v.old.BatchID, v.new.BatchID) 162 assert.Equal(t, v.old.Address, v.new.Address) 163 assert.Equal(t, v.old.BinID, v.new.BinID) 164 assert.Equal(t, v.old.ChunkType, v.new.ChunkType) 165 assert.NotEqual(t, swarm.EmptyAddress.Bytes(), v.new.StampHash) 166 } 167 } 168 169 func checkStampIndex(t *testing.T, s storage.Reader, wantCount int, m map[string]oldAndNewItem[*stampindex.ItemV1, *stampindex.Item]) { 170 t.Helper() 171 count := 0 172 err := s.Iterate(storage.Query{ 173 Factory: func() storage.Item { return new(stampindex.Item) }, 174 }, func(result storage.Result) (bool, error) { 175 count++ 176 b := result.Entry.(*stampindex.Item) 177 found, ok := m[b.ID()] 178 require.True(t, ok) 179 found.new = b 180 m[b.ID()] = found 181 return false, nil 182 }) 183 require.NoError(t, err) 184 assert.Equal(t, wantCount, count) 185 for _, v := range m { 186 assert.Equal(t, v.old.Namespace(), v.new.Namespace()) 187 assert.Equal(t, v.old.BatchID, v.new.BatchID) 188 assert.Equal(t, v.old.StampIndex, v.new.StampIndex) 189 assert.Equal(t, v.old.StampTimestamp, v.new.StampTimestamp) 190 assert.Equal(t, v.old.ChunkAddress, v.new.ChunkAddress) 191 assert.NotEqual(t, swarm.EmptyAddress.Bytes(), v.new.StampHash) 192 } 193 }