github.com/gobitfly/go-ethereum@v1.8.12/swarm/storage/memstore_test.go (about) 1 // Copyright 2016 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 storage 18 19 import ( 20 "crypto/rand" 21 "encoding/binary" 22 "io/ioutil" 23 "os" 24 "sync" 25 "testing" 26 27 "github.com/ethereum/go-ethereum/swarm/log" 28 ) 29 30 func newTestMemStore() *MemStore { 31 storeparams := NewDefaultStoreParams() 32 return NewMemStore(storeparams, nil) 33 } 34 35 func testMemStoreRandom(n int, processors int, chunksize int64, t *testing.T) { 36 m := newTestMemStore() 37 defer m.Close() 38 testStoreRandom(m, processors, n, chunksize, t) 39 } 40 41 func testMemStoreCorrect(n int, processors int, chunksize int64, t *testing.T) { 42 m := newTestMemStore() 43 defer m.Close() 44 testStoreCorrect(m, processors, n, chunksize, t) 45 } 46 47 func TestMemStoreRandom_1(t *testing.T) { 48 testMemStoreRandom(1, 1, 0, t) 49 } 50 51 func TestMemStoreCorrect_1(t *testing.T) { 52 testMemStoreCorrect(1, 1, 4104, t) 53 } 54 55 func TestMemStoreRandom_1_1k(t *testing.T) { 56 testMemStoreRandom(1, 1000, 0, t) 57 } 58 59 func TestMemStoreCorrect_1_1k(t *testing.T) { 60 testMemStoreCorrect(1, 100, 4096, t) 61 } 62 63 func TestMemStoreRandom_8_1k(t *testing.T) { 64 testMemStoreRandom(8, 1000, 0, t) 65 } 66 67 func TestMemStoreCorrect_8_1k(t *testing.T) { 68 testMemStoreCorrect(8, 1000, 4096, t) 69 } 70 71 func TestMemStoreNotFound(t *testing.T) { 72 m := newTestMemStore() 73 defer m.Close() 74 75 _, err := m.Get(ZeroAddr) 76 if err != ErrChunkNotFound { 77 t.Errorf("Expected ErrChunkNotFound, got %v", err) 78 } 79 } 80 81 func benchmarkMemStorePut(n int, processors int, chunksize int64, b *testing.B) { 82 m := newTestMemStore() 83 defer m.Close() 84 benchmarkStorePut(m, processors, n, chunksize, b) 85 } 86 87 func benchmarkMemStoreGet(n int, processors int, chunksize int64, b *testing.B) { 88 m := newTestMemStore() 89 defer m.Close() 90 benchmarkStoreGet(m, processors, n, chunksize, b) 91 } 92 93 func BenchmarkMemStorePut_1_500(b *testing.B) { 94 benchmarkMemStorePut(500, 1, 4096, b) 95 } 96 97 func BenchmarkMemStorePut_8_500(b *testing.B) { 98 benchmarkMemStorePut(500, 8, 4096, b) 99 } 100 101 func BenchmarkMemStoreGet_1_500(b *testing.B) { 102 benchmarkMemStoreGet(500, 1, 4096, b) 103 } 104 105 func BenchmarkMemStoreGet_8_500(b *testing.B) { 106 benchmarkMemStoreGet(500, 8, 4096, b) 107 } 108 109 func newLDBStore(t *testing.T) (*LDBStore, func()) { 110 dir, err := ioutil.TempDir("", "bzz-storage-test") 111 if err != nil { 112 t.Fatal(err) 113 } 114 log.Trace("memstore.tempdir", "dir", dir) 115 116 ldbparams := NewLDBStoreParams(NewDefaultStoreParams(), dir) 117 db, err := NewLDBStore(ldbparams) 118 if err != nil { 119 t.Fatal(err) 120 } 121 122 cleanup := func() { 123 db.Close() 124 err := os.RemoveAll(dir) 125 if err != nil { 126 t.Fatal(err) 127 } 128 } 129 130 return db, cleanup 131 } 132 133 func TestMemStoreAndLDBStore(t *testing.T) { 134 ldb, cleanup := newLDBStore(t) 135 ldb.setCapacity(4000) 136 defer cleanup() 137 138 cacheCap := 200 139 requestsCap := 200 140 memStore := NewMemStore(NewStoreParams(4000, 200, 200, nil, nil), nil) 141 142 tests := []struct { 143 n int // number of chunks to push to memStore 144 chunkSize uint64 // size of chunk (by default in Swarm - 4096) 145 request bool // whether or not to set the ReqC channel on the random chunks 146 }{ 147 { 148 n: 1, 149 chunkSize: 4096, 150 request: false, 151 }, 152 { 153 n: 201, 154 chunkSize: 4096, 155 request: false, 156 }, 157 { 158 n: 501, 159 chunkSize: 4096, 160 request: false, 161 }, 162 { 163 n: 3100, 164 chunkSize: 4096, 165 request: false, 166 }, 167 { 168 n: 100, 169 chunkSize: 4096, 170 request: true, 171 }, 172 } 173 174 for i, tt := range tests { 175 log.Info("running test", "idx", i, "tt", tt) 176 var chunks []*Chunk 177 178 for i := 0; i < tt.n; i++ { 179 var c *Chunk 180 if tt.request { 181 c = NewRandomRequestChunk(tt.chunkSize) 182 } else { 183 c = NewRandomChunk(tt.chunkSize) 184 } 185 186 chunks = append(chunks, c) 187 } 188 189 for i := 0; i < tt.n; i++ { 190 go ldb.Put(chunks[i]) 191 memStore.Put(chunks[i]) 192 193 if got := memStore.cache.Len(); got > cacheCap { 194 t.Fatalf("expected to get cache capacity less than %v, but got %v", cacheCap, got) 195 } 196 197 if got := memStore.requests.Len(); got > requestsCap { 198 t.Fatalf("expected to get requests capacity less than %v, but got %v", requestsCap, got) 199 } 200 } 201 202 for i := 0; i < tt.n; i++ { 203 _, err := memStore.Get(chunks[i].Addr) 204 if err != nil { 205 if err == ErrChunkNotFound { 206 _, err := ldb.Get(chunks[i].Addr) 207 if err != nil { 208 t.Fatalf("couldn't get chunk %v from ldb, got error: %v", i, err) 209 } 210 } else { 211 t.Fatalf("got error from memstore: %v", err) 212 } 213 } 214 } 215 216 // wait for all chunks to be stored before ending the test are cleaning up 217 for i := 0; i < tt.n; i++ { 218 <-chunks[i].dbStoredC 219 } 220 } 221 } 222 223 func NewRandomChunk(chunkSize uint64) *Chunk { 224 c := &Chunk{ 225 Addr: make([]byte, 32), 226 ReqC: nil, 227 SData: make([]byte, chunkSize+8), // SData should be chunkSize + 8 bytes reserved for length 228 dbStoredC: make(chan bool), 229 dbStoredMu: &sync.Mutex{}, 230 } 231 232 rand.Read(c.SData) 233 234 binary.LittleEndian.PutUint64(c.SData[:8], chunkSize) 235 236 hasher := MakeHashFunc(SHA3Hash)() 237 hasher.Write(c.SData) 238 copy(c.Addr, hasher.Sum(nil)) 239 240 return c 241 } 242 243 func NewRandomRequestChunk(chunkSize uint64) *Chunk { 244 c := NewRandomChunk(chunkSize) 245 c.ReqC = make(chan bool) 246 247 return c 248 }