github.com/murrekatt/go-ethereum@v1.5.8-0.20170123175102-fc52f2c007fb/swarm/network/syncdb_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 network 18 19 import ( 20 "bytes" 21 "io/ioutil" 22 "os" 23 "path/filepath" 24 "testing" 25 "time" 26 27 "github.com/ethereum/go-ethereum/crypto" 28 "github.com/ethereum/go-ethereum/logger" 29 "github.com/ethereum/go-ethereum/logger/glog" 30 "github.com/ethereum/go-ethereum/swarm/storage" 31 ) 32 33 func init() { 34 glog.SetV(0) 35 glog.SetToStderr(true) 36 } 37 38 type testSyncDb struct { 39 *syncDb 40 c int 41 t *testing.T 42 fromDb chan bool 43 delivered [][]byte 44 sent []int 45 dbdir string 46 at int 47 } 48 49 func newTestSyncDb(priority, bufferSize, batchSize int, dbdir string, t *testing.T) *testSyncDb { 50 if len(dbdir) == 0 { 51 tmp, err := ioutil.TempDir(os.TempDir(), "syncdb-test") 52 if err != nil { 53 t.Fatalf("unable to create temporary direcory %v: %v", tmp, err) 54 } 55 dbdir = tmp 56 } 57 db, err := storage.NewLDBDatabase(filepath.Join(dbdir, "requestdb")) 58 if err != nil { 59 t.Fatalf("unable to create db: %v", err) 60 } 61 self := &testSyncDb{ 62 fromDb: make(chan bool), 63 dbdir: dbdir, 64 t: t, 65 } 66 h := crypto.Keccak256Hash([]byte{0}) 67 key := storage.Key(h[:]) 68 self.syncDb = newSyncDb(db, key, uint(priority), uint(bufferSize), uint(batchSize), self.deliver) 69 // kick off db iterator right away, if no items on db this will allow 70 // reading from the buffer 71 return self 72 73 } 74 75 func (self *testSyncDb) close() { 76 self.db.Close() 77 os.RemoveAll(self.dbdir) 78 } 79 80 func (self *testSyncDb) push(n int) { 81 for i := 0; i < n; i++ { 82 self.buffer <- storage.Key(crypto.Keccak256([]byte{byte(self.c)})) 83 self.sent = append(self.sent, self.c) 84 self.c++ 85 } 86 glog.V(logger.Debug).Infof("pushed %v requests", n) 87 } 88 89 func (self *testSyncDb) draindb() { 90 it := self.db.NewIterator() 91 defer it.Release() 92 for { 93 it.Seek(self.start) 94 if !it.Valid() { 95 return 96 } 97 k := it.Key() 98 if len(k) == 0 || k[0] == 1 { 99 return 100 } 101 it.Release() 102 it = self.db.NewIterator() 103 } 104 } 105 106 func (self *testSyncDb) deliver(req interface{}, quit chan bool) bool { 107 _, db := req.(*syncDbEntry) 108 key, _, _, _, err := parseRequest(req) 109 if err != nil { 110 self.t.Fatalf("unexpected error of key %v: %v", key, err) 111 } 112 self.delivered = append(self.delivered, key) 113 select { 114 case self.fromDb <- db: 115 return true 116 case <-quit: 117 return false 118 } 119 } 120 121 func (self *testSyncDb) expect(n int, db bool) { 122 var ok bool 123 // for n items 124 for i := 0; i < n; i++ { 125 ok = <-self.fromDb 126 if self.at+1 > len(self.delivered) { 127 self.t.Fatalf("expected %v, got %v", self.at+1, len(self.delivered)) 128 } 129 if len(self.sent) > self.at && !bytes.Equal(crypto.Keccak256([]byte{byte(self.sent[self.at])}), self.delivered[self.at]) { 130 self.t.Fatalf("expected delivery %v/%v/%v to be hash of %v, from db: %v = %v", i, n, self.at, self.sent[self.at], ok, db) 131 glog.V(logger.Debug).Infof("%v/%v/%v to be hash of %v, from db: %v = %v", i, n, self.at, self.sent[self.at], ok, db) 132 } 133 if !ok && db { 134 self.t.Fatalf("expected delivery %v/%v/%v from db", i, n, self.at) 135 } 136 if ok && !db { 137 self.t.Fatalf("expected delivery %v/%v/%v from cache", i, n, self.at) 138 } 139 self.at++ 140 } 141 } 142 143 func TestSyncDb(t *testing.T) { 144 t.Skip("fails randomly on all platforms") 145 146 priority := High 147 bufferSize := 5 148 batchSize := 2 * bufferSize 149 s := newTestSyncDb(priority, bufferSize, batchSize, "", t) 150 defer s.close() 151 defer s.stop() 152 s.dbRead(false, 0, s.deliver) 153 s.draindb() 154 155 s.push(4) 156 s.expect(1, false) 157 // 3 in buffer 158 time.Sleep(100 * time.Millisecond) 159 s.push(3) 160 // push over limit 161 s.expect(1, false) 162 // one popped from the buffer, then contention detected 163 s.expect(4, true) 164 s.push(4) 165 s.expect(5, true) 166 // depleted db, switch back to buffer 167 s.draindb() 168 s.push(5) 169 s.expect(4, false) 170 s.push(3) 171 s.expect(4, false) 172 // buffer depleted 173 time.Sleep(100 * time.Millisecond) 174 s.push(6) 175 s.expect(1, false) 176 // push into buffer full, switch to db 177 s.expect(5, true) 178 s.draindb() 179 s.push(1) 180 s.expect(1, false) 181 } 182 183 func TestSaveSyncDb(t *testing.T) { 184 amount := 30 185 priority := High 186 bufferSize := amount 187 batchSize := 10 188 s := newTestSyncDb(priority, bufferSize, batchSize, "", t) 189 go s.dbRead(false, 0, s.deliver) 190 s.push(amount) 191 s.stop() 192 s.db.Close() 193 194 s = newTestSyncDb(priority, bufferSize, batchSize, s.dbdir, t) 195 go s.dbRead(false, 0, s.deliver) 196 s.expect(amount, true) 197 for i, key := range s.delivered { 198 expKey := crypto.Keccak256([]byte{byte(i)}) 199 if !bytes.Equal(key, expKey) { 200 t.Fatalf("delivery %v expected to be key %x, got %x", i, expKey, key) 201 } 202 } 203 s.push(amount) 204 s.expect(amount, false) 205 for i := amount; i < 2*amount; i++ { 206 key := s.delivered[i] 207 expKey := crypto.Keccak256([]byte{byte(i - amount)}) 208 if !bytes.Equal(key, expKey) { 209 t.Fatalf("delivery %v expected to be key %x, got %x", i, expKey, key) 210 } 211 } 212 s.stop() 213 s.db.Close() 214 215 s = newTestSyncDb(priority, bufferSize, batchSize, s.dbdir, t) 216 defer s.close() 217 defer s.stop() 218 219 go s.dbRead(false, 0, s.deliver) 220 s.push(1) 221 s.expect(1, false) 222 223 }