github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/network/stream/common_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:43</date>
    10  //</624450115121188864>
    11  
    12  
    13  package stream
    14  
    15  import (
    16  	"context"
    17  	"errors"
    18  	"flag"
    19  	"fmt"
    20  	"io"
    21  	"io/ioutil"
    22  	"math/rand"
    23  	"os"
    24  	"strings"
    25  	"sync/atomic"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/ethereum/go-ethereum/log"
    30  	"github.com/ethereum/go-ethereum/p2p/enode"
    31  	p2ptest "github.com/ethereum/go-ethereum/p2p/testing"
    32  	"github.com/ethereum/go-ethereum/swarm/network"
    33  	"github.com/ethereum/go-ethereum/swarm/network/simulation"
    34  	"github.com/ethereum/go-ethereum/swarm/state"
    35  	"github.com/ethereum/go-ethereum/swarm/storage"
    36  	"github.com/ethereum/go-ethereum/swarm/testutil"
    37  	colorable "github.com/mattn/go-colorable"
    38  )
    39  
    40  var (
    41  	loglevel     = flag.Int("loglevel", 2, "verbosity of logs")
    42  	nodes        = flag.Int("nodes", 0, "number of nodes")
    43  	chunks       = flag.Int("chunks", 0, "number of chunks")
    44  	useMockStore = flag.Bool("mockstore", false, "disabled mock store (default: enabled)")
    45  	longrunning  = flag.Bool("longrunning", false, "do run long-running tests")
    46  
    47  	bucketKeyDB        = simulation.BucketKey("db")
    48  	bucketKeyStore     = simulation.BucketKey("store")
    49  	bucketKeyFileStore = simulation.BucketKey("filestore")
    50  	bucketKeyNetStore  = simulation.BucketKey("netstore")
    51  	bucketKeyDelivery  = simulation.BucketKey("delivery")
    52  	bucketKeyRegistry  = simulation.BucketKey("registry")
    53  
    54  	chunkSize = 4096
    55  	pof       = network.Pof
    56  )
    57  
    58  func init() {
    59  	flag.Parse()
    60  	rand.Seed(time.Now().UnixNano())
    61  
    62  	log.PrintOrigins(true)
    63  	log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true))))
    64  }
    65  
    66  func newStreamerTester(t *testing.T, registryOptions *RegistryOptions) (*p2ptest.ProtocolTester, *Registry, *storage.LocalStore, func(), error) {
    67  //设置
    68  addr := network.RandomAddr() //测试的对等地址
    69  	to := network.NewKademlia(addr.OAddr, network.NewKadParams())
    70  
    71  //临时数据
    72  	datadir, err := ioutil.TempDir("", "streamer")
    73  	if err != nil {
    74  		return nil, nil, nil, func() {}, err
    75  	}
    76  	removeDataDir := func() {
    77  		os.RemoveAll(datadir)
    78  	}
    79  
    80  	params := storage.NewDefaultLocalStoreParams()
    81  	params.Init(datadir)
    82  	params.BaseKey = addr.Over()
    83  
    84  	localStore, err := storage.NewTestLocalStoreForAddr(params)
    85  	if err != nil {
    86  		return nil, nil, nil, removeDataDir, err
    87  	}
    88  
    89  	netStore, err := storage.NewNetStore(localStore, nil)
    90  	if err != nil {
    91  		return nil, nil, nil, removeDataDir, err
    92  	}
    93  
    94  	delivery := NewDelivery(to, netStore)
    95  	netStore.NewNetFetcherFunc = network.NewFetcherFactory(delivery.RequestFromPeers, true).New
    96  	streamer := NewRegistry(addr.ID(), delivery, netStore, state.NewInmemoryStore(), registryOptions, nil)
    97  	teardown := func() {
    98  		streamer.Close()
    99  		removeDataDir()
   100  	}
   101  	protocolTester := p2ptest.NewProtocolTester(t, addr.ID(), 1, streamer.runProtocol)
   102  
   103  	err = waitForPeers(streamer, 1*time.Second, 1)
   104  	if err != nil {
   105  		return nil, nil, nil, nil, errors.New("timeout: peer is not created")
   106  	}
   107  
   108  	return protocolTester, streamer, localStore, teardown, nil
   109  }
   110  
   111  func waitForPeers(streamer *Registry, timeout time.Duration, expectedPeers int) error {
   112  	ticker := time.NewTicker(10 * time.Millisecond)
   113  	timeoutTimer := time.NewTimer(timeout)
   114  	for {
   115  		select {
   116  		case <-ticker.C:
   117  			if streamer.peersCount() >= expectedPeers {
   118  				return nil
   119  			}
   120  		case <-timeoutTimer.C:
   121  			return errors.New("timeout")
   122  		}
   123  	}
   124  }
   125  
   126  type roundRobinStore struct {
   127  	index  uint32
   128  	stores []storage.ChunkStore
   129  }
   130  
   131  func newRoundRobinStore(stores ...storage.ChunkStore) *roundRobinStore {
   132  	return &roundRobinStore{
   133  		stores: stores,
   134  	}
   135  }
   136  
   137  func (rrs *roundRobinStore) Get(ctx context.Context, addr storage.Address) (storage.Chunk, error) {
   138  	return nil, errors.New("get not well defined on round robin store")
   139  }
   140  
   141  func (rrs *roundRobinStore) Put(ctx context.Context, chunk storage.Chunk) error {
   142  	i := atomic.AddUint32(&rrs.index, 1)
   143  	idx := int(i) % len(rrs.stores)
   144  	return rrs.stores[idx].Put(ctx, chunk)
   145  }
   146  
   147  func (rrs *roundRobinStore) Close() {
   148  	for _, store := range rrs.stores {
   149  		store.Close()
   150  	}
   151  }
   152  
   153  func readAll(fileStore *storage.FileStore, hash []byte) (int64, error) {
   154  	r, _ := fileStore.Retrieve(context.TODO(), hash)
   155  	buf := make([]byte, 1024)
   156  	var n int
   157  	var total int64
   158  	var err error
   159  	for (total == 0 || n > 0) && err == nil {
   160  		n, err = r.ReadAt(buf, total)
   161  		total += int64(n)
   162  	}
   163  	if err != nil && err != io.EOF {
   164  		return total, err
   165  	}
   166  	return total, nil
   167  }
   168  
   169  func uploadFilesToNodes(sim *simulation.Simulation) ([]storage.Address, []string, error) {
   170  	nodes := sim.UpNodeIDs()
   171  	nodeCnt := len(nodes)
   172  	log.Debug(fmt.Sprintf("Uploading %d files to nodes", nodeCnt))
   173  //保存生成文件的数组
   174  	rfiles := make([]string, nodeCnt)
   175  //保存文件根哈希的数组
   176  	rootAddrs := make([]storage.Address, nodeCnt)
   177  
   178  	var err error
   179  //对于每个节点,生成一个文件并上载
   180  	for i, id := range nodes {
   181  		item, ok := sim.NodeItem(id, bucketKeyFileStore)
   182  		if !ok {
   183  			return nil, nil, fmt.Errorf("Error accessing localstore")
   184  		}
   185  		fileStore := item.(*storage.FileStore)
   186  //生成文件
   187  		rfiles[i], err = generateRandomFile()
   188  		if err != nil {
   189  			return nil, nil, err
   190  		}
   191  //将其存储(上载)到文件存储区
   192  		ctx := context.TODO()
   193  		rk, wait, err := fileStore.Store(ctx, strings.NewReader(rfiles[i]), int64(len(rfiles[i])), false)
   194  		log.Debug("Uploaded random string file to node")
   195  		if err != nil {
   196  			return nil, nil, err
   197  		}
   198  		err = wait(ctx)
   199  		if err != nil {
   200  			return nil, nil, err
   201  		}
   202  		rootAddrs[i] = rk
   203  	}
   204  	return rootAddrs, rfiles, nil
   205  }
   206  
   207  //生成随机文件(字符串)
   208  func generateRandomFile() (string, error) {
   209  //在minfileSize和maxfileSize之间生成随机文件大小
   210  	fileSize := rand.Intn(maxFileSize-minFileSize) + minFileSize
   211  	log.Debug(fmt.Sprintf("Generated file with filesize %d kB", fileSize))
   212  	b := testutil.RandomBytes(1, fileSize*1024)
   213  	return string(b), nil
   214  }
   215  
   216  //为给定节点创建本地存储
   217  func createTestLocalStorageForID(id enode.ID, addr *network.BzzAddr) (storage.ChunkStore, string, error) {
   218  	var datadir string
   219  	var err error
   220  	datadir, err = ioutil.TempDir("", fmt.Sprintf("syncer-test-%s", id.TerminalString()))
   221  	if err != nil {
   222  		return nil, "", err
   223  	}
   224  	var store storage.ChunkStore
   225  	params := storage.NewDefaultLocalStoreParams()
   226  	params.ChunkDbPath = datadir
   227  	params.BaseKey = addr.Over()
   228  	store, err = storage.NewTestLocalStoreForAddr(params)
   229  	if err != nil {
   230  		os.RemoveAll(datadir)
   231  		return nil, "", err
   232  	}
   233  	return store, datadir, nil
   234  }
   235