github.com/jincm/wesharechain@v0.0.0-20210122032815-1537409ce26a/chain/swarm/storage/mock/test/test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package test provides functions that are used for testing 18 // GlobalStorer implementations. 19 package test 20 21 import ( 22 "bytes" 23 "encoding/binary" 24 "fmt" 25 "io" 26 "strconv" 27 "testing" 28 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/swarm/storage" 31 "github.com/ethereum/go-ethereum/swarm/storage/mock" 32 ) 33 34 // MockStore creates NodeStore instances from provided GlobalStorer, 35 // each one with a unique address, stores different chunks on them 36 // and checks if they are retrievable or not on all nodes. 37 // Attribute n defines the number of NodeStores that will be created. 38 func MockStore(t *testing.T, globalStore mock.GlobalStorer, n int) { 39 t.Run("GlobalStore", func(t *testing.T) { 40 addrs := make([]common.Address, n) 41 for i := 0; i < n; i++ { 42 addrs[i] = common.HexToAddress(strconv.FormatInt(int64(i)+1, 16)) 43 } 44 45 for i, addr := range addrs { 46 chunkAddr := storage.Address(append(addr[:], []byte(strconv.FormatInt(int64(i)+1, 16))...)) 47 data := []byte(strconv.FormatInt(int64(i)+1, 16)) 48 data = append(data, make([]byte, 4096-len(data))...) 49 globalStore.Put(addr, chunkAddr, data) 50 51 for _, cAddr := range addrs { 52 cData, err := globalStore.Get(cAddr, chunkAddr) 53 if cAddr == addr { 54 if err != nil { 55 t.Fatalf("get data from store %s key %s: %v", cAddr.Hex(), chunkAddr.Hex(), err) 56 } 57 if !bytes.Equal(data, cData) { 58 t.Fatalf("data on store %s: expected %x, got %x", cAddr.Hex(), data, cData) 59 } 60 if !globalStore.HasKey(cAddr, chunkAddr) { 61 t.Fatalf("expected key %s on global store for node %s, but it was not found", chunkAddr.Hex(), cAddr.Hex()) 62 } 63 } else { 64 if err != mock.ErrNotFound { 65 t.Fatalf("expected error from store %s: %v, got %v", cAddr.Hex(), mock.ErrNotFound, err) 66 } 67 if len(cData) > 0 { 68 t.Fatalf("data on store %s: expected nil, got %x", cAddr.Hex(), cData) 69 } 70 if globalStore.HasKey(cAddr, chunkAddr) { 71 t.Fatalf("not expected key %s on global store for node %s, but it was found", chunkAddr.Hex(), cAddr.Hex()) 72 } 73 } 74 } 75 } 76 t.Run("delete", func(t *testing.T) { 77 chunkAddr := storage.Address([]byte("1234567890abcd")) 78 for _, addr := range addrs { 79 err := globalStore.Put(addr, chunkAddr, []byte("data")) 80 if err != nil { 81 t.Fatalf("put data to store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err) 82 } 83 } 84 firstNodeAddr := addrs[0] 85 if err := globalStore.Delete(firstNodeAddr, chunkAddr); err != nil { 86 t.Fatalf("delete from store %s key %s: %v", firstNodeAddr.Hex(), chunkAddr.Hex(), err) 87 } 88 for i, addr := range addrs { 89 _, err := globalStore.Get(addr, chunkAddr) 90 if i == 0 { 91 if err != mock.ErrNotFound { 92 t.Errorf("get data from store %s key %s: expected mock.ErrNotFound error, got %v", addr.Hex(), chunkAddr.Hex(), err) 93 } 94 } else { 95 if err != nil { 96 t.Errorf("get data from store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err) 97 } 98 } 99 } 100 }) 101 }) 102 103 t.Run("NodeStore", func(t *testing.T) { 104 nodes := make(map[common.Address]*mock.NodeStore) 105 for i := 0; i < n; i++ { 106 addr := common.HexToAddress(strconv.FormatInt(int64(i)+1, 16)) 107 nodes[addr] = globalStore.NewNodeStore(addr) 108 } 109 110 i := 0 111 for addr, store := range nodes { 112 i++ 113 chunkAddr := storage.Address(append(addr[:], []byte(fmt.Sprintf("%x", i))...)) 114 data := []byte(strconv.FormatInt(int64(i)+1, 16)) 115 data = append(data, make([]byte, 4096-len(data))...) 116 store.Put(chunkAddr, data) 117 118 for cAddr, cStore := range nodes { 119 cData, err := cStore.Get(chunkAddr) 120 if cAddr == addr { 121 if err != nil { 122 t.Fatalf("get data from store %s key %s: %v", cAddr.Hex(), chunkAddr.Hex(), err) 123 } 124 if !bytes.Equal(data, cData) { 125 t.Fatalf("data on store %s: expected %x, got %x", cAddr.Hex(), data, cData) 126 } 127 if !globalStore.HasKey(cAddr, chunkAddr) { 128 t.Fatalf("expected key %s on global store for node %s, but it was not found", chunkAddr.Hex(), cAddr.Hex()) 129 } 130 } else { 131 if err != mock.ErrNotFound { 132 t.Fatalf("expected error from store %s: %v, got %v", cAddr.Hex(), mock.ErrNotFound, err) 133 } 134 if len(cData) > 0 { 135 t.Fatalf("data on store %s: expected nil, got %x", cAddr.Hex(), cData) 136 } 137 if globalStore.HasKey(cAddr, chunkAddr) { 138 t.Fatalf("not expected key %s on global store for node %s, but it was found", chunkAddr.Hex(), cAddr.Hex()) 139 } 140 } 141 } 142 } 143 t.Run("delete", func(t *testing.T) { 144 chunkAddr := storage.Address([]byte("1234567890abcd")) 145 var chosenStore *mock.NodeStore 146 for addr, store := range nodes { 147 if chosenStore == nil { 148 chosenStore = store 149 } 150 err := store.Put(chunkAddr, []byte("data")) 151 if err != nil { 152 t.Fatalf("put data to store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err) 153 } 154 } 155 if err := chosenStore.Delete(chunkAddr); err != nil { 156 t.Fatalf("delete key %s: %v", chunkAddr.Hex(), err) 157 } 158 for addr, store := range nodes { 159 _, err := store.Get(chunkAddr) 160 if store == chosenStore { 161 if err != mock.ErrNotFound { 162 t.Errorf("get data from store %s key %s: expected mock.ErrNotFound error, got %v", addr.Hex(), chunkAddr.Hex(), err) 163 } 164 } else { 165 if err != nil { 166 t.Errorf("get data from store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err) 167 } 168 } 169 } 170 }) 171 }) 172 } 173 174 // MockStoreListings tests global store methods Keys, Nodes, NodeKeys and KeyNodes. 175 // It uses a provided globalstore to put chunks for n number of node addresses 176 // and to validate that methods are returning the right responses. 177 func MockStoreListings(t *testing.T, globalStore mock.GlobalStorer, n int) { 178 addrs := make([]common.Address, n) 179 for i := 0; i < n; i++ { 180 addrs[i] = common.HexToAddress(strconv.FormatInt(int64(i)+1, 16)) 181 } 182 type chunk struct { 183 key []byte 184 data []byte 185 } 186 const chunksPerNode = 5 187 keys := make([][]byte, n*chunksPerNode) 188 for i := 0; i < n*chunksPerNode; i++ { 189 b := make([]byte, 8) 190 binary.BigEndian.PutUint64(b, uint64(i)) 191 keys[i] = b 192 } 193 194 // keep track of keys on every node 195 nodeKeys := make(map[common.Address][][]byte) 196 // keep track of nodes that store particular key 197 keyNodes := make(map[string][]common.Address) 198 for i := 0; i < chunksPerNode; i++ { 199 // put chunks for every address 200 for j := 0; j < n; j++ { 201 addr := addrs[j] 202 key := keys[(i*n)+j] 203 err := globalStore.Put(addr, key, []byte("data")) 204 if err != nil { 205 t.Fatal(err) 206 } 207 nodeKeys[addr] = append(nodeKeys[addr], key) 208 keyNodes[string(key)] = append(keyNodes[string(key)], addr) 209 } 210 211 // test Keys method 212 var startKey []byte 213 var gotKeys [][]byte 214 for { 215 keys, err := globalStore.Keys(startKey, 0) 216 if err != nil { 217 t.Fatal(err) 218 } 219 gotKeys = append(gotKeys, keys.Keys...) 220 if keys.Next == nil { 221 break 222 } 223 startKey = keys.Next 224 } 225 wantKeys := keys[:(i+1)*n] 226 if fmt.Sprint(gotKeys) != fmt.Sprint(wantKeys) { 227 t.Fatalf("got #%v keys %v, want %v", i+1, gotKeys, wantKeys) 228 } 229 230 // test Nodes method 231 var startNode *common.Address 232 var gotNodes []common.Address 233 for { 234 nodes, err := globalStore.Nodes(startNode, 0) 235 if err != nil { 236 t.Fatal(err) 237 } 238 gotNodes = append(gotNodes, nodes.Addrs...) 239 if nodes.Next == nil { 240 break 241 } 242 startNode = nodes.Next 243 } 244 wantNodes := addrs 245 if fmt.Sprint(gotNodes) != fmt.Sprint(wantNodes) { 246 t.Fatalf("got #%v nodes %v, want %v", i+1, gotNodes, wantNodes) 247 } 248 249 // test NodeKeys method 250 for addr, wantKeys := range nodeKeys { 251 var startKey []byte 252 var gotKeys [][]byte 253 for { 254 keys, err := globalStore.NodeKeys(addr, startKey, 0) 255 if err != nil { 256 t.Fatal(err) 257 } 258 gotKeys = append(gotKeys, keys.Keys...) 259 if keys.Next == nil { 260 break 261 } 262 startKey = keys.Next 263 } 264 if fmt.Sprint(gotKeys) != fmt.Sprint(wantKeys) { 265 t.Fatalf("got #%v %s node keys %v, want %v", i+1, addr.Hex(), gotKeys, wantKeys) 266 } 267 } 268 269 // test KeyNodes method 270 for key, wantNodes := range keyNodes { 271 var startNode *common.Address 272 var gotNodes []common.Address 273 for { 274 nodes, err := globalStore.KeyNodes([]byte(key), startNode, 0) 275 if err != nil { 276 t.Fatal(err) 277 } 278 gotNodes = append(gotNodes, nodes.Addrs...) 279 if nodes.Next == nil { 280 break 281 } 282 startNode = nodes.Next 283 } 284 if fmt.Sprint(gotNodes) != fmt.Sprint(wantNodes) { 285 t.Fatalf("got #%v %x key nodes %v, want %v", i+1, []byte(key), gotNodes, wantNodes) 286 } 287 } 288 } 289 } 290 291 // ImportExport saves chunks to the outStore, exports them to the tar archive, 292 // imports tar archive to the inStore and checks if all chunks are imported correctly. 293 func ImportExport(t *testing.T, outStore, inStore mock.GlobalStorer, n int) { 294 exporter, ok := outStore.(mock.Exporter) 295 if !ok { 296 t.Fatal("outStore does not implement mock.Exporter") 297 } 298 importer, ok := inStore.(mock.Importer) 299 if !ok { 300 t.Fatal("inStore does not implement mock.Importer") 301 } 302 addrs := make([]common.Address, n) 303 for i := 0; i < n; i++ { 304 addrs[i] = common.HexToAddress(strconv.FormatInt(int64(i)+1, 16)) 305 } 306 307 for i, addr := range addrs { 308 chunkAddr := storage.Address(append(addr[:], []byte(strconv.FormatInt(int64(i)+1, 16))...)) 309 data := []byte(strconv.FormatInt(int64(i)+1, 16)) 310 data = append(data, make([]byte, 4096-len(data))...) 311 outStore.Put(addr, chunkAddr, data) 312 } 313 314 r, w := io.Pipe() 315 defer r.Close() 316 317 exportErrChan := make(chan error) 318 go func() { 319 defer w.Close() 320 321 _, err := exporter.Export(w) 322 exportErrChan <- err 323 }() 324 325 if _, err := importer.Import(r); err != nil { 326 t.Fatalf("import: %v", err) 327 } 328 329 if err := <-exportErrChan; err != nil { 330 t.Fatalf("export: %v", err) 331 } 332 333 for i, addr := range addrs { 334 chunkAddr := storage.Address(append(addr[:], []byte(strconv.FormatInt(int64(i)+1, 16))...)) 335 data := []byte(strconv.FormatInt(int64(i)+1, 16)) 336 data = append(data, make([]byte, 4096-len(data))...) 337 for _, cAddr := range addrs { 338 cData, err := inStore.Get(cAddr, chunkAddr) 339 if cAddr == addr { 340 if err != nil { 341 t.Fatalf("get data from store %s key %s: %v", cAddr.Hex(), chunkAddr.Hex(), err) 342 } 343 if !bytes.Equal(data, cData) { 344 t.Fatalf("data on store %s: expected %x, got %x", cAddr.Hex(), data, cData) 345 } 346 if !inStore.HasKey(cAddr, chunkAddr) { 347 t.Fatalf("expected key %s on global store for node %s, but it was not found", chunkAddr.Hex(), cAddr.Hex()) 348 } 349 } else { 350 if err != mock.ErrNotFound { 351 t.Fatalf("expected error from store %s: %v, got %v", cAddr.Hex(), mock.ErrNotFound, err) 352 } 353 if len(cData) > 0 { 354 t.Fatalf("data on store %s: expected nil, got %x", cAddr.Hex(), cData) 355 } 356 if inStore.HasKey(cAddr, chunkAddr) { 357 t.Fatalf("not expected key %s on global store for node %s, but it was found", chunkAddr.Hex(), cAddr.Hex()) 358 } 359 } 360 } 361 } 362 }