github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/ldbstore_test.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 25 package storage 26 27 import ( 28 "bytes" 29 "context" 30 "fmt" 31 "io/ioutil" 32 "os" 33 "sync" 34 "testing" 35 "time" 36 37 "github.com/ethereum/go-ethereum/common" 38 "github.com/ethereum/go-ethereum/swarm/chunk" 39 "github.com/ethereum/go-ethereum/swarm/log" 40 "github.com/ethereum/go-ethereum/swarm/storage/mock/mem" 41 42 ldberrors "github.com/syndtr/goleveldb/leveldb/errors" 43 ) 44 45 type testDbStore struct { 46 *LDBStore 47 dir string 48 } 49 50 func newTestDbStore(mock bool, trusted bool) (*testDbStore, func(), error) { 51 dir, err := ioutil.TempDir("", "bzz-storage-test") 52 if err != nil { 53 return nil, func() {}, err 54 } 55 56 var db *LDBStore 57 storeparams := NewDefaultStoreParams() 58 params := NewLDBStoreParams(storeparams, dir) 59 params.Po = testPoFunc 60 61 if mock { 62 globalStore := mem.NewGlobalStore() 63 addr := common.HexToAddress("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed") 64 mockStore := globalStore.NewNodeStore(addr) 65 66 db, err = NewMockDbStore(params, mockStore) 67 } else { 68 db, err = NewLDBStore(params) 69 } 70 71 cleanup := func() { 72 if db != nil { 73 db.Close() 74 } 75 err = os.RemoveAll(dir) 76 if err != nil { 77 panic(fmt.Sprintf("db cleanup failed: %v", err)) 78 } 79 } 80 81 return &testDbStore{db, dir}, cleanup, err 82 } 83 84 func testPoFunc(k Address) (ret uint8) { 85 basekey := make([]byte, 32) 86 return uint8(Proximity(basekey[:], k[:])) 87 } 88 89 func (db *testDbStore) close() { 90 db.Close() 91 err := os.RemoveAll(db.dir) 92 if err != nil { 93 panic(err) 94 } 95 } 96 97 func testDbStoreRandom(n int, processors int, chunksize int64, mock bool, t *testing.T) { 98 db, cleanup, err := newTestDbStore(mock, true) 99 defer cleanup() 100 if err != nil { 101 t.Fatalf("init dbStore failed: %v", err) 102 } 103 testStoreRandom(db, processors, n, chunksize, t) 104 } 105 106 func testDbStoreCorrect(n int, processors int, chunksize int64, mock bool, t *testing.T) { 107 db, cleanup, err := newTestDbStore(mock, false) 108 defer cleanup() 109 if err != nil { 110 t.Fatalf("init dbStore failed: %v", err) 111 } 112 testStoreCorrect(db, processors, n, chunksize, t) 113 } 114 115 func TestDbStoreRandom_1(t *testing.T) { 116 testDbStoreRandom(1, 1, 0, false, t) 117 } 118 119 func TestDbStoreCorrect_1(t *testing.T) { 120 testDbStoreCorrect(1, 1, 4096, false, t) 121 } 122 123 func TestDbStoreRandom_1_5k(t *testing.T) { 124 testDbStoreRandom(8, 5000, 0, false, t) 125 } 126 127 func TestDbStoreRandom_8_5k(t *testing.T) { 128 testDbStoreRandom(8, 5000, 0, false, t) 129 } 130 131 func TestDbStoreCorrect_1_5k(t *testing.T) { 132 testDbStoreCorrect(1, 5000, 4096, false, t) 133 } 134 135 func TestDbStoreCorrect_8_5k(t *testing.T) { 136 testDbStoreCorrect(8, 5000, 4096, false, t) 137 } 138 139 func TestMockDbStoreRandom_1(t *testing.T) { 140 testDbStoreRandom(1, 1, 0, true, t) 141 } 142 143 func TestMockDbStoreCorrect_1(t *testing.T) { 144 testDbStoreCorrect(1, 1, 4096, true, t) 145 } 146 147 func TestMockDbStoreRandom_1_5k(t *testing.T) { 148 testDbStoreRandom(8, 5000, 0, true, t) 149 } 150 151 func TestMockDbStoreRandom_8_5k(t *testing.T) { 152 testDbStoreRandom(8, 5000, 0, true, t) 153 } 154 155 func TestMockDbStoreCorrect_1_5k(t *testing.T) { 156 testDbStoreCorrect(1, 5000, 4096, true, t) 157 } 158 159 func TestMockDbStoreCorrect_8_5k(t *testing.T) { 160 testDbStoreCorrect(8, 5000, 4096, true, t) 161 } 162 163 func testDbStoreNotFound(t *testing.T, mock bool) { 164 db, cleanup, err := newTestDbStore(mock, false) 165 defer cleanup() 166 if err != nil { 167 t.Fatalf("init dbStore failed: %v", err) 168 } 169 170 _, err = db.Get(context.TODO(), ZeroAddr) 171 if err != ErrChunkNotFound { 172 t.Errorf("Expected ErrChunkNotFound, got %v", err) 173 } 174 } 175 176 func TestDbStoreNotFound(t *testing.T) { 177 testDbStoreNotFound(t, false) 178 } 179 func TestMockDbStoreNotFound(t *testing.T) { 180 testDbStoreNotFound(t, true) 181 } 182 183 func testIterator(t *testing.T, mock bool) { 184 var chunkcount int = 32 185 var i int 186 var poc uint 187 chunkkeys := NewAddressCollection(chunkcount) 188 chunkkeys_results := NewAddressCollection(chunkcount) 189 190 db, cleanup, err := newTestDbStore(mock, false) 191 defer cleanup() 192 if err != nil { 193 t.Fatalf("init dbStore failed: %v", err) 194 } 195 196 chunks := GenerateRandomChunks(chunk.DefaultSize, chunkcount) 197 198 wg := &sync.WaitGroup{} 199 wg.Add(len(chunks)) 200 for i = 0; i < len(chunks); i++ { 201 db.Put(context.TODO(), chunks[i]) 202 chunkkeys[i] = chunks[i].Addr 203 j := i 204 go func() { 205 defer wg.Done() 206 <-chunks[j].dbStoredC 207 }() 208 } 209 210 // 211 212 for i = 0; i < len(chunkkeys); i++ { 213 log.Trace(fmt.Sprintf("Chunk array pos %d/%d: '%v'", i, chunkcount, chunkkeys[i])) 214 } 215 wg.Wait() 216 i = 0 217 for poc = 0; poc <= 255; poc++ { 218 err := db.SyncIterator(0, uint64(chunkkeys.Len()), uint8(poc), func(k Address, n uint64) bool { 219 log.Trace(fmt.Sprintf("Got key %v number %d poc %d", k, n, uint8(poc))) 220 chunkkeys_results[n-1] = k 221 i++ 222 return true 223 }) 224 if err != nil { 225 t.Fatalf("Iterator call failed: %v", err) 226 } 227 } 228 229 for i = 0; i < chunkcount; i++ { 230 if !bytes.Equal(chunkkeys[i], chunkkeys_results[i]) { 231 t.Fatalf("Chunk put #%d key '%v' does not match iterator's key '%v'", i, chunkkeys[i], chunkkeys_results[i]) 232 } 233 } 234 235 } 236 237 func TestIterator(t *testing.T) { 238 testIterator(t, false) 239 } 240 func TestMockIterator(t *testing.T) { 241 testIterator(t, true) 242 } 243 244 func benchmarkDbStorePut(n int, processors int, chunksize int64, mock bool, b *testing.B) { 245 db, cleanup, err := newTestDbStore(mock, true) 246 defer cleanup() 247 if err != nil { 248 b.Fatalf("init dbStore failed: %v", err) 249 } 250 benchmarkStorePut(db, processors, n, chunksize, b) 251 } 252 253 func benchmarkDbStoreGet(n int, processors int, chunksize int64, mock bool, b *testing.B) { 254 db, cleanup, err := newTestDbStore(mock, true) 255 defer cleanup() 256 if err != nil { 257 b.Fatalf("init dbStore failed: %v", err) 258 } 259 benchmarkStoreGet(db, processors, n, chunksize, b) 260 } 261 262 func BenchmarkDbStorePut_1_500(b *testing.B) { 263 benchmarkDbStorePut(500, 1, 4096, false, b) 264 } 265 266 func BenchmarkDbStorePut_8_500(b *testing.B) { 267 benchmarkDbStorePut(500, 8, 4096, false, b) 268 } 269 270 func BenchmarkDbStoreGet_1_500(b *testing.B) { 271 benchmarkDbStoreGet(500, 1, 4096, false, b) 272 } 273 274 func BenchmarkDbStoreGet_8_500(b *testing.B) { 275 benchmarkDbStoreGet(500, 8, 4096, false, b) 276 } 277 278 func BenchmarkMockDbStorePut_1_500(b *testing.B) { 279 benchmarkDbStorePut(500, 1, 4096, true, b) 280 } 281 282 func BenchmarkMockDbStorePut_8_500(b *testing.B) { 283 benchmarkDbStorePut(500, 8, 4096, true, b) 284 } 285 286 func BenchmarkMockDbStoreGet_1_500(b *testing.B) { 287 benchmarkDbStoreGet(500, 1, 4096, true, b) 288 } 289 290 func BenchmarkMockDbStoreGet_8_500(b *testing.B) { 291 benchmarkDbStoreGet(500, 8, 4096, true, b) 292 } 293 294 // 295 // 296 func TestLDBStoreWithoutCollectGarbage(t *testing.T) { 297 capacity := 50 298 n := 10 299 300 ldb, cleanup := newLDBStore(t) 301 ldb.setCapacity(uint64(capacity)) 302 defer cleanup() 303 304 chunks := []*Chunk{} 305 for i := 0; i < n; i++ { 306 c := GenerateRandomChunk(chunk.DefaultSize) 307 chunks = append(chunks, c) 308 log.Trace("generate random chunk", "idx", i, "chunk", c) 309 } 310 311 for i := 0; i < n; i++ { 312 go ldb.Put(context.TODO(), chunks[i]) 313 } 314 315 // 316 for i := 0; i < n; i++ { 317 <-chunks[i].dbStoredC 318 } 319 320 log.Info("ldbstore", "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt) 321 322 for i := 0; i < n; i++ { 323 ret, err := ldb.Get(context.TODO(), chunks[i].Addr) 324 if err != nil { 325 t.Fatal(err) 326 } 327 328 if !bytes.Equal(ret.SData, chunks[i].SData) { 329 t.Fatal("expected to get the same data back, but got smth else") 330 } 331 332 log.Info("got back chunk", "chunk", ret) 333 } 334 335 if ldb.entryCnt != uint64(n+1) { 336 t.Fatalf("expected entryCnt to be equal to %v, but got %v", n+1, ldb.entryCnt) 337 } 338 339 if ldb.accessCnt != uint64(2*n+1) { 340 t.Fatalf("expected accessCnt to be equal to %v, but got %v", n+1, ldb.accessCnt) 341 } 342 } 343 344 // 345 // 346 func TestLDBStoreCollectGarbage(t *testing.T) { 347 capacity := 500 348 n := 2000 349 350 ldb, cleanup := newLDBStore(t) 351 ldb.setCapacity(uint64(capacity)) 352 defer cleanup() 353 354 chunks := []*Chunk{} 355 for i := 0; i < n; i++ { 356 c := GenerateRandomChunk(chunk.DefaultSize) 357 chunks = append(chunks, c) 358 log.Trace("generate random chunk", "idx", i, "chunk", c) 359 } 360 361 for i := 0; i < n; i++ { 362 ldb.Put(context.TODO(), chunks[i]) 363 } 364 365 // 366 for i := 0; i < n; i++ { 367 <-chunks[i].dbStoredC 368 } 369 370 log.Info("ldbstore", "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt) 371 372 // 373 time.Sleep(5 * time.Second) 374 375 var missing int 376 for i := 0; i < n; i++ { 377 ret, err := ldb.Get(context.TODO(), chunks[i].Addr) 378 if err == ErrChunkNotFound || err == ldberrors.ErrNotFound { 379 missing++ 380 continue 381 } 382 if err != nil { 383 t.Fatal(err) 384 } 385 386 if !bytes.Equal(ret.SData, chunks[i].SData) { 387 t.Fatal("expected to get the same data back, but got smth else") 388 } 389 390 log.Trace("got back chunk", "chunk", ret) 391 } 392 393 if missing < n-capacity { 394 t.Fatalf("gc failure: expected to miss %v chunks, but only %v are actually missing", n-capacity, missing) 395 } 396 397 log.Info("ldbstore", "total", n, "missing", missing, "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt) 398 } 399 400 // 401 func TestLDBStoreAddRemove(t *testing.T) { 402 ldb, cleanup := newLDBStore(t) 403 ldb.setCapacity(200) 404 defer cleanup() 405 406 n := 100 407 408 chunks := []*Chunk{} 409 for i := 0; i < n; i++ { 410 c := GenerateRandomChunk(chunk.DefaultSize) 411 chunks = append(chunks, c) 412 log.Trace("generate random chunk", "idx", i, "chunk", c) 413 } 414 415 for i := 0; i < n; i++ { 416 go ldb.Put(context.TODO(), chunks[i]) 417 } 418 419 // 420 for i := 0; i < n; i++ { 421 <-chunks[i].dbStoredC 422 } 423 424 for i := 0; i < n; i++ { 425 // 426 if i%2 == 0 { 427 428 key := chunks[i].Addr 429 ikey := getIndexKey(key) 430 431 var indx dpaDBIndex 432 ldb.tryAccessIdx(ikey, &indx) 433 434 ldb.delete(indx.Idx, ikey, ldb.po(key)) 435 } 436 } 437 438 log.Info("ldbstore", "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt) 439 440 for i := 0; i < n; i++ { 441 ret, err := ldb.Get(context.TODO(), chunks[i].Addr) 442 443 if i%2 == 0 { 444 // 445 if err == nil || ret != nil { 446 t.Fatal("expected chunk to be missing, but got no error") 447 } 448 } else { 449 // 450 if err != nil { 451 t.Fatalf("expected no error, but got %s", err) 452 } 453 454 if !bytes.Equal(ret.SData, chunks[i].SData) { 455 t.Fatal("expected to get the same data back, but got smth else") 456 } 457 } 458 } 459 } 460 461 // 462 func TestLDBStoreRemoveThenCollectGarbage(t *testing.T) { 463 capacity := 10 464 465 ldb, cleanup := newLDBStore(t) 466 ldb.setCapacity(uint64(capacity)) 467 468 n := 7 469 470 chunks := []*Chunk{} 471 for i := 0; i < capacity; i++ { 472 c := GenerateRandomChunk(chunk.DefaultSize) 473 chunks = append(chunks, c) 474 log.Trace("generate random chunk", "idx", i, "chunk", c) 475 } 476 477 for i := 0; i < n; i++ { 478 ldb.Put(context.TODO(), chunks[i]) 479 } 480 481 // 482 for i := 0; i < n; i++ { 483 <-chunks[i].dbStoredC 484 } 485 486 // 487 for i := 0; i < n; i++ { 488 key := chunks[i].Addr 489 ikey := getIndexKey(key) 490 491 var indx dpaDBIndex 492 ldb.tryAccessIdx(ikey, &indx) 493 494 ldb.delete(indx.Idx, ikey, ldb.po(key)) 495 } 496 497 log.Info("ldbstore", "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt) 498 499 cleanup() 500 501 ldb, cleanup = newLDBStore(t) 502 ldb.setCapacity(uint64(capacity)) 503 504 n = 10 505 506 for i := 0; i < n; i++ { 507 ldb.Put(context.TODO(), chunks[i]) 508 } 509 510 // 511 for i := 0; i < n; i++ { 512 <-chunks[i].dbStoredC 513 } 514 515 // 516 idx := 0 517 ret, err := ldb.Get(context.TODO(), chunks[idx].Addr) 518 if err == nil || ret != nil { 519 t.Fatal("expected first chunk to be missing, but got no error") 520 } 521 522 // 523 idx = 9 524 ret, err = ldb.Get(context.TODO(), chunks[idx].Addr) 525 if err != nil { 526 t.Fatalf("expected no error, but got %s", err) 527 } 528 529 if !bytes.Equal(ret.SData, chunks[idx].SData) { 530 t.Fatal("expected to get the same data back, but got smth else") 531 } 532 }