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