github.com/insight-chain/inb-go@v1.1.3-0.20191221022159-da049980ae38/swarm/network/stream/common_test.go (about) 1 // Copyright 2018 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 MiningReward, 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 stream 18 19 import ( 20 "context" 21 "errors" 22 "flag" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "math/rand" 27 "os" 28 "strings" 29 "sync/atomic" 30 "testing" 31 "time" 32 33 "github.com/insight-chain/inb-go/log" 34 "github.com/insight-chain/inb-go/p2p/enode" 35 p2ptest "github.com/insight-chain/inb-go/p2p/testing" 36 "github.com/insight-chain/inb-go/swarm/network" 37 "github.com/insight-chain/inb-go/swarm/network/simulation" 38 "github.com/insight-chain/inb-go/swarm/pot" 39 "github.com/insight-chain/inb-go/swarm/state" 40 "github.com/insight-chain/inb-go/swarm/storage" 41 "github.com/insight-chain/inb-go/swarm/testutil" 42 colorable "github.com/mattn/go-colorable" 43 ) 44 45 var ( 46 loglevel = flag.Int("loglevel", 2, "verbosity of logs") 47 nodes = flag.Int("nodes", 0, "number of nodes") 48 chunks = flag.Int("chunks", 0, "number of chunks") 49 useMockStore = flag.Bool("mockstore", false, "disabled mock store (default: enabled)") 50 longrunning = flag.Bool("longrunning", false, "do run long-running tests") 51 52 bucketKeyDB = simulation.BucketKey("db") 53 bucketKeyStore = simulation.BucketKey("store") 54 bucketKeyFileStore = simulation.BucketKey("filestore") 55 bucketKeyNetStore = simulation.BucketKey("netstore") 56 bucketKeyDelivery = simulation.BucketKey("delivery") 57 bucketKeyRegistry = simulation.BucketKey("registry") 58 59 chunkSize = 4096 60 pof = pot.DefaultPof(256) 61 ) 62 63 func init() { 64 flag.Parse() 65 rand.Seed(time.Now().UnixNano()) 66 67 log.PrintOrigins(true) 68 log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true)))) 69 } 70 71 func newStreamerTester(t *testing.T, registryOptions *RegistryOptions) (*p2ptest.ProtocolTester, *Registry, *storage.LocalStore, func(), error) { 72 // setup 73 addr := network.RandomAddr() // tested peers peer address 74 to := network.NewKademlia(addr.OAddr, network.NewKadParams()) 75 76 // temp datadir 77 datadir, err := ioutil.TempDir("", "streamer") 78 if err != nil { 79 return nil, nil, nil, func() {}, err 80 } 81 removeDataDir := func() { 82 os.RemoveAll(datadir) 83 } 84 85 params := storage.NewDefaultLocalStoreParams() 86 params.Init(datadir) 87 params.BaseKey = addr.Over() 88 89 localStore, err := storage.NewTestLocalStoreForAddr(params) 90 if err != nil { 91 return nil, nil, nil, removeDataDir, err 92 } 93 94 netStore, err := storage.NewNetStore(localStore, nil) 95 if err != nil { 96 return nil, nil, nil, removeDataDir, err 97 } 98 99 delivery := NewDelivery(to, netStore) 100 netStore.NewNetFetcherFunc = network.NewFetcherFactory(delivery.RequestFromPeers, true).New 101 streamer := NewRegistry(addr.ID(), delivery, netStore, state.NewInmemoryStore(), registryOptions, nil) 102 teardown := func() { 103 streamer.Close() 104 removeDataDir() 105 } 106 protocolTester := p2ptest.NewProtocolTester(t, addr.ID(), 1, streamer.runProtocol) 107 108 err = waitForPeers(streamer, 1*time.Second, 1) 109 if err != nil { 110 return nil, nil, nil, nil, errors.New("timeout: peer is not created") 111 } 112 113 return protocolTester, streamer, localStore, teardown, nil 114 } 115 116 func waitForPeers(streamer *Registry, timeout time.Duration, expectedPeers int) error { 117 ticker := time.NewTicker(10 * time.Millisecond) 118 timeoutTimer := time.NewTimer(timeout) 119 for { 120 select { 121 case <-ticker.C: 122 if streamer.peersCount() >= expectedPeers { 123 return nil 124 } 125 case <-timeoutTimer.C: 126 return errors.New("timeout") 127 } 128 } 129 } 130 131 type roundRobinStore struct { 132 index uint32 133 stores []storage.ChunkStore 134 } 135 136 func newRoundRobinStore(stores ...storage.ChunkStore) *roundRobinStore { 137 return &roundRobinStore{ 138 stores: stores, 139 } 140 } 141 142 func (rrs *roundRobinStore) Get(ctx context.Context, addr storage.Address) (storage.Chunk, error) { 143 return nil, errors.New("get not well defined on round robin store") 144 } 145 146 func (rrs *roundRobinStore) Put(ctx context.Context, chunk storage.Chunk) error { 147 i := atomic.AddUint32(&rrs.index, 1) 148 idx := int(i) % len(rrs.stores) 149 return rrs.stores[idx].Put(ctx, chunk) 150 } 151 152 func (rrs *roundRobinStore) Close() { 153 for _, store := range rrs.stores { 154 store.Close() 155 } 156 } 157 158 func readAll(fileStore *storage.FileStore, hash []byte) (int64, error) { 159 r, _ := fileStore.Retrieve(context.TODO(), hash) 160 buf := make([]byte, 1024) 161 var n int 162 var total int64 163 var err error 164 for (total == 0 || n > 0) && err == nil { 165 n, err = r.ReadAt(buf, total) 166 total += int64(n) 167 } 168 if err != nil && err != io.EOF { 169 return total, err 170 } 171 return total, nil 172 } 173 174 func uploadFilesToNodes(sim *simulation.Simulation) ([]storage.Address, []string, error) { 175 nodes := sim.UpNodeIDs() 176 nodeCnt := len(nodes) 177 log.Debug(fmt.Sprintf("Uploading %d files to nodes", nodeCnt)) 178 //array holding generated files 179 rfiles := make([]string, nodeCnt) 180 //array holding the root hashes of the files 181 rootAddrs := make([]storage.Address, nodeCnt) 182 183 var err error 184 //for every node, generate a file and upload 185 for i, id := range nodes { 186 item, ok := sim.NodeItem(id, bucketKeyFileStore) 187 if !ok { 188 return nil, nil, fmt.Errorf("Error accessing localstore") 189 } 190 fileStore := item.(*storage.FileStore) 191 //generate a file 192 rfiles[i], err = generateRandomFile() 193 if err != nil { 194 return nil, nil, err 195 } 196 //store it (upload it) on the FileStore 197 ctx := context.TODO() 198 rk, wait, err := fileStore.Store(ctx, strings.NewReader(rfiles[i]), int64(len(rfiles[i])), false) 199 log.Debug("Uploaded random string file to node") 200 if err != nil { 201 return nil, nil, err 202 } 203 err = wait(ctx) 204 if err != nil { 205 return nil, nil, err 206 } 207 rootAddrs[i] = rk 208 } 209 return rootAddrs, rfiles, nil 210 } 211 212 //generate a random file (string) 213 func generateRandomFile() (string, error) { 214 //generate a random file size between minFileSize and maxFileSize 215 fileSize := rand.Intn(maxFileSize-minFileSize) + minFileSize 216 log.Debug(fmt.Sprintf("Generated file with filesize %d kB", fileSize)) 217 b := testutil.RandomBytes(1, fileSize*1024) 218 return string(b), nil 219 } 220 221 //create a local store for the given node 222 func createTestLocalStorageForID(id enode.ID, addr *network.BzzAddr) (storage.ChunkStore, string, error) { 223 var datadir string 224 var err error 225 datadir, err = ioutil.TempDir("", fmt.Sprintf("syncer-test-%s", id.TerminalString())) 226 if err != nil { 227 return nil, "", err 228 } 229 var store storage.ChunkStore 230 params := storage.NewDefaultLocalStoreParams() 231 params.ChunkDbPath = datadir 232 params.BaseKey = addr.Over() 233 store, err = storage.NewTestLocalStoreForAddr(params) 234 if err != nil { 235 os.RemoveAll(datadir) 236 return nil, "", err 237 } 238 return store, datadir, nil 239 }