github.com/susy-go/susy-graviton@v0.0.0-20190614130430-36cddae42305/swarm/storage/mock/test/test.go (about) 1 // Copyleft 2018 The susy-graviton Authors 2 // This file is part of the susy-graviton library. 3 // 4 // The susy-graviton 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 susy-graviton library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MSRCHANTABILITY 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 susy-graviton 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 "fmt" 24 "io" 25 "strconv" 26 "testing" 27 28 "github.com/susy-go/susy-graviton/common" 29 "github.com/susy-go/susy-graviton/swarm/storage" 30 "github.com/susy-go/susy-graviton/swarm/storage/mock" 31 ) 32 33 // MockStore creates NodeStore instances from provided GlobalStorer, 34 // each one with a unique address, stores different chunks on them 35 // and checks if they are retrievable or not on all nodes. 36 // Attribute n defines the number of NodeStores that will be created. 37 func MockStore(t *testing.T, globalStore mock.GlobalStorer, n int) { 38 t.Run("GlobalStore", func(t *testing.T) { 39 addrs := make([]common.Address, n) 40 for i := 0; i < n; i++ { 41 addrs[i] = common.HexToAddress(strconv.FormatInt(int64(i)+1, 16)) 42 } 43 44 for i, addr := range addrs { 45 chunkAddr := storage.Address(append(addr[:], []byte(strconv.FormatInt(int64(i)+1, 16))...)) 46 data := []byte(strconv.FormatInt(int64(i)+1, 16)) 47 data = append(data, make([]byte, 4096-len(data))...) 48 globalStore.Put(addr, chunkAddr, data) 49 50 for _, cAddr := range addrs { 51 cData, err := globalStore.Get(cAddr, chunkAddr) 52 if cAddr == addr { 53 if err != nil { 54 t.Fatalf("get data from store %s key %s: %v", cAddr.Hex(), chunkAddr.Hex(), err) 55 } 56 if !bytes.Equal(data, cData) { 57 t.Fatalf("data on store %s: expected %x, got %x", cAddr.Hex(), data, cData) 58 } 59 if !globalStore.HasKey(cAddr, chunkAddr) { 60 t.Fatalf("expected key %s on global store for node %s, but it was not found", chunkAddr.Hex(), cAddr.Hex()) 61 } 62 } else { 63 if err != mock.ErrNotFound { 64 t.Fatalf("expected error from store %s: %v, got %v", cAddr.Hex(), mock.ErrNotFound, err) 65 } 66 if len(cData) > 0 { 67 t.Fatalf("data on store %s: expected nil, got %x", cAddr.Hex(), cData) 68 } 69 if globalStore.HasKey(cAddr, chunkAddr) { 70 t.Fatalf("not expected key %s on global store for node %s, but it was found", chunkAddr.Hex(), cAddr.Hex()) 71 } 72 } 73 } 74 } 75 t.Run("delete", func(t *testing.T) { 76 chunkAddr := storage.Address([]byte("1234567890abcd")) 77 for _, addr := range addrs { 78 err := globalStore.Put(addr, chunkAddr, []byte("data")) 79 if err != nil { 80 t.Fatalf("put data to store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err) 81 } 82 } 83 firstNodeAddr := addrs[0] 84 if err := globalStore.Delete(firstNodeAddr, chunkAddr); err != nil { 85 t.Fatalf("delete from store %s key %s: %v", firstNodeAddr.Hex(), chunkAddr.Hex(), err) 86 } 87 for i, addr := range addrs { 88 _, err := globalStore.Get(addr, chunkAddr) 89 if i == 0 { 90 if err != mock.ErrNotFound { 91 t.Errorf("get data from store %s key %s: expected mock.ErrNotFound error, got %v", addr.Hex(), chunkAddr.Hex(), err) 92 } 93 } else { 94 if err != nil { 95 t.Errorf("get data from store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err) 96 } 97 } 98 } 99 }) 100 }) 101 102 t.Run("NodeStore", func(t *testing.T) { 103 nodes := make(map[common.Address]*mock.NodeStore) 104 for i := 0; i < n; i++ { 105 addr := common.HexToAddress(strconv.FormatInt(int64(i)+1, 16)) 106 nodes[addr] = globalStore.NewNodeStore(addr) 107 } 108 109 i := 0 110 for addr, store := range nodes { 111 i++ 112 chunkAddr := storage.Address(append(addr[:], []byte(fmt.Sprintf("%x", i))...)) 113 data := []byte(strconv.FormatInt(int64(i)+1, 16)) 114 data = append(data, make([]byte, 4096-len(data))...) 115 store.Put(chunkAddr, data) 116 117 for cAddr, cStore := range nodes { 118 cData, err := cStore.Get(chunkAddr) 119 if cAddr == addr { 120 if err != nil { 121 t.Fatalf("get data from store %s key %s: %v", cAddr.Hex(), chunkAddr.Hex(), err) 122 } 123 if !bytes.Equal(data, cData) { 124 t.Fatalf("data on store %s: expected %x, got %x", cAddr.Hex(), data, cData) 125 } 126 if !globalStore.HasKey(cAddr, chunkAddr) { 127 t.Fatalf("expected key %s on global store for node %s, but it was not found", chunkAddr.Hex(), cAddr.Hex()) 128 } 129 } else { 130 if err != mock.ErrNotFound { 131 t.Fatalf("expected error from store %s: %v, got %v", cAddr.Hex(), mock.ErrNotFound, err) 132 } 133 if len(cData) > 0 { 134 t.Fatalf("data on store %s: expected nil, got %x", cAddr.Hex(), cData) 135 } 136 if globalStore.HasKey(cAddr, chunkAddr) { 137 t.Fatalf("not expected key %s on global store for node %s, but it was found", chunkAddr.Hex(), cAddr.Hex()) 138 } 139 } 140 } 141 } 142 t.Run("delete", func(t *testing.T) { 143 chunkAddr := storage.Address([]byte("1234567890abcd")) 144 var chosenStore *mock.NodeStore 145 for addr, store := range nodes { 146 if chosenStore == nil { 147 chosenStore = store 148 } 149 err := store.Put(chunkAddr, []byte("data")) 150 if err != nil { 151 t.Fatalf("put data to store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err) 152 } 153 } 154 if err := chosenStore.Delete(chunkAddr); err != nil { 155 t.Fatalf("delete key %s: %v", chunkAddr.Hex(), err) 156 } 157 for addr, store := range nodes { 158 _, err := store.Get(chunkAddr) 159 if store == chosenStore { 160 if err != mock.ErrNotFound { 161 t.Errorf("get data from store %s key %s: expected mock.ErrNotFound error, got %v", addr.Hex(), chunkAddr.Hex(), err) 162 } 163 } else { 164 if err != nil { 165 t.Errorf("get data from store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err) 166 } 167 } 168 } 169 }) 170 }) 171 } 172 173 // ImportExport saves chunks to the outStore, exports them to the tar archive, 174 // imports tar archive to the inStore and checks if all chunks are imported correctly. 175 func ImportExport(t *testing.T, outStore, inStore mock.GlobalStorer, n int) { 176 exporter, ok := outStore.(mock.Exporter) 177 if !ok { 178 t.Fatal("outStore does not implement mock.Exporter") 179 } 180 importer, ok := inStore.(mock.Importer) 181 if !ok { 182 t.Fatal("inStore does not implement mock.Importer") 183 } 184 addrs := make([]common.Address, n) 185 for i := 0; i < n; i++ { 186 addrs[i] = common.HexToAddress(strconv.FormatInt(int64(i)+1, 16)) 187 } 188 189 for i, addr := range addrs { 190 chunkAddr := storage.Address(append(addr[:], []byte(strconv.FormatInt(int64(i)+1, 16))...)) 191 data := []byte(strconv.FormatInt(int64(i)+1, 16)) 192 data = append(data, make([]byte, 4096-len(data))...) 193 outStore.Put(addr, chunkAddr, data) 194 } 195 196 r, w := io.Pipe() 197 defer r.Close() 198 199 exportErrChan := make(chan error) 200 go func() { 201 defer w.Close() 202 203 _, err := exporter.Export(w) 204 exportErrChan <- err 205 }() 206 207 if _, err := importer.Import(r); err != nil { 208 t.Fatalf("import: %v", err) 209 } 210 211 if err := <-exportErrChan; err != nil { 212 t.Fatalf("export: %v", err) 213 } 214 215 for i, addr := range addrs { 216 chunkAddr := storage.Address(append(addr[:], []byte(strconv.FormatInt(int64(i)+1, 16))...)) 217 data := []byte(strconv.FormatInt(int64(i)+1, 16)) 218 data = append(data, make([]byte, 4096-len(data))...) 219 for _, cAddr := range addrs { 220 cData, err := inStore.Get(cAddr, chunkAddr) 221 if cAddr == addr { 222 if err != nil { 223 t.Fatalf("get data from store %s key %s: %v", cAddr.Hex(), chunkAddr.Hex(), err) 224 } 225 if !bytes.Equal(data, cData) { 226 t.Fatalf("data on store %s: expected %x, got %x", cAddr.Hex(), data, cData) 227 } 228 if !inStore.HasKey(cAddr, chunkAddr) { 229 t.Fatalf("expected key %s on global store for node %s, but it was not found", chunkAddr.Hex(), cAddr.Hex()) 230 } 231 } else { 232 if err != mock.ErrNotFound { 233 t.Fatalf("expected error from store %s: %v, got %v", cAddr.Hex(), mock.ErrNotFound, err) 234 } 235 if len(cData) > 0 { 236 t.Fatalf("data on store %s: expected nil, got %x", cAddr.Hex(), cData) 237 } 238 if inStore.HasKey(cAddr, chunkAddr) { 239 t.Fatalf("not expected key %s on global store for node %s, but it was found", chunkAddr.Hex(), cAddr.Hex()) 240 } 241 } 242 } 243 } 244 }