github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/network/stream/intervals_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 stream
    26  
    27  import (
    28  	"context"
    29  	crand "crypto/rand"
    30  	"encoding/binary"
    31  	"fmt"
    32  	"io"
    33  	"os"
    34  	"sync"
    35  	"testing"
    36  	"time"
    37  
    38  	"github.com/ethereum/go-ethereum/log"
    39  	"github.com/ethereum/go-ethereum/node"
    40  	"github.com/ethereum/go-ethereum/p2p"
    41  	"github.com/ethereum/go-ethereum/p2p/discover"
    42  	"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
    43  	"github.com/ethereum/go-ethereum/swarm/network"
    44  	"github.com/ethereum/go-ethereum/swarm/network/simulation"
    45  	"github.com/ethereum/go-ethereum/swarm/state"
    46  	"github.com/ethereum/go-ethereum/swarm/storage"
    47  )
    48  
    49  func TestIntervals(t *testing.T) {
    50  	testIntervals(t, true, nil, false)
    51  	testIntervals(t, false, NewRange(9, 26), false)
    52  	testIntervals(t, true, NewRange(9, 26), false)
    53  
    54  	testIntervals(t, true, nil, true)
    55  	testIntervals(t, false, NewRange(9, 26), true)
    56  	testIntervals(t, true, NewRange(9, 26), true)
    57  }
    58  
    59  func testIntervals(t *testing.T, live bool, history *Range, skipCheck bool) {
    60  	nodes := 2
    61  	chunkCount := dataChunkCount
    62  	externalStreamName := "externalStream"
    63  	externalStreamSessionAt := uint64(50)
    64  	externalStreamMaxKeys := uint64(100)
    65  
    66  	sim := simulation.New(map[string]simulation.ServiceFunc{
    67  		"intervalsStreamer": func(ctx *adapters.ServiceContext, bucket *sync.Map) (s node.Service, cleanup func(), err error) {
    68  
    69  			id := ctx.Config.ID
    70  			addr := network.NewAddrFromNodeID(id)
    71  			store, datadir, err := createTestLocalStorageForID(id, addr)
    72  			if err != nil {
    73  				return nil, nil, err
    74  			}
    75  			bucket.Store(bucketKeyStore, store)
    76  			cleanup = func() {
    77  				store.Close()
    78  				os.RemoveAll(datadir)
    79  			}
    80  			localStore := store.(*storage.LocalStore)
    81  			db := storage.NewDBAPI(localStore)
    82  			kad := network.NewKademlia(addr.Over(), network.NewKadParams())
    83  			delivery := NewDelivery(kad, db)
    84  
    85  			r := NewRegistry(addr, delivery, db, state.NewInmemoryStore(), &RegistryOptions{
    86  				SkipCheck: skipCheck,
    87  			})
    88  			bucket.Store(bucketKeyRegistry, r)
    89  
    90  			r.RegisterClientFunc(externalStreamName, func(p *Peer, t string, live bool) (Client, error) {
    91  				return newTestExternalClient(db), nil
    92  			})
    93  			r.RegisterServerFunc(externalStreamName, func(p *Peer, t string, live bool) (Server, error) {
    94  				return newTestExternalServer(t, externalStreamSessionAt, externalStreamMaxKeys, nil), nil
    95  			})
    96  
    97  			fileStore := storage.NewFileStore(localStore, storage.NewFileStoreParams())
    98  			bucket.Store(bucketKeyFileStore, fileStore)
    99  
   100  			return r, cleanup, nil
   101  
   102  		},
   103  	})
   104  	defer sim.Close()
   105  
   106  	log.Info("Adding nodes to simulation")
   107  	_, err := sim.AddNodesAndConnectChain(nodes)
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  
   112  	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
   113  	defer cancel()
   114  
   115  	result := sim.Run(ctx, func(ctx context.Context, sim *simulation.Simulation) error {
   116  		nodeIDs := sim.UpNodeIDs()
   117  		storer := nodeIDs[0]
   118  		checker := nodeIDs[1]
   119  
   120  		item, ok := sim.NodeItem(storer, bucketKeyFileStore)
   121  		if !ok {
   122  			return fmt.Errorf("No filestore")
   123  		}
   124  		fileStore := item.(*storage.FileStore)
   125  
   126  		size := chunkCount * chunkSize
   127  		_, wait, err := fileStore.Store(ctx, io.LimitReader(crand.Reader, int64(size)), int64(size), false)
   128  		if err != nil {
   129  			log.Error("Store error: %v", "err", err)
   130  			t.Fatal(err)
   131  		}
   132  		err = wait(ctx)
   133  		if err != nil {
   134  			log.Error("Wait error: %v", "err", err)
   135  			t.Fatal(err)
   136  		}
   137  
   138  		item, ok = sim.NodeItem(checker, bucketKeyRegistry)
   139  		if !ok {
   140  			return fmt.Errorf("No registry")
   141  		}
   142  		registry := item.(*Registry)
   143  
   144  		liveErrC := make(chan error)
   145  		historyErrC := make(chan error)
   146  
   147  		if _, err := sim.WaitTillHealthy(ctx, 2); err != nil {
   148  			log.Error("WaitKademlia error: %v", "err", err)
   149  			return err
   150  		}
   151  
   152  		log.Debug("Watching for disconnections")
   153  		disconnections := sim.PeerEvents(
   154  			context.Background(),
   155  			sim.NodeIDs(),
   156  			simulation.NewPeerEventsFilter().Type(p2p.PeerEventTypeDrop),
   157  		)
   158  
   159  		go func() {
   160  			for d := range disconnections {
   161  				if d.Error != nil {
   162  					log.Error("peer drop", "node", d.NodeID, "peer", d.Event.Peer)
   163  					t.Fatal(d.Error)
   164  				}
   165  			}
   166  		}()
   167  
   168  		go func() {
   169  			if !live {
   170  				close(liveErrC)
   171  				return
   172  			}
   173  
   174  			var err error
   175  			defer func() {
   176  				liveErrC <- err
   177  			}()
   178  
   179  //
   180  			var liveHashesChan chan []byte
   181  			liveHashesChan, err = getHashes(ctx, registry, storer, NewStream(externalStreamName, "", true))
   182  			if err != nil {
   183  				log.Error("Subscription error: %v", "err", err)
   184  				return
   185  			}
   186  			i := externalStreamSessionAt
   187  
   188  //
   189  			err = enableNotifications(registry, storer, NewStream(externalStreamName, "", true))
   190  			if err != nil {
   191  				return
   192  			}
   193  
   194  			for {
   195  				select {
   196  				case hash := <-liveHashesChan:
   197  					h := binary.BigEndian.Uint64(hash)
   198  					if h != i {
   199  						err = fmt.Errorf("expected live hash %d, got %d", i, h)
   200  						return
   201  					}
   202  					i++
   203  					if i > externalStreamMaxKeys {
   204  						return
   205  					}
   206  				case <-ctx.Done():
   207  					return
   208  				}
   209  			}
   210  		}()
   211  
   212  		go func() {
   213  			if live && history == nil {
   214  				close(historyErrC)
   215  				return
   216  			}
   217  
   218  			var err error
   219  			defer func() {
   220  				historyErrC <- err
   221  			}()
   222  
   223  //
   224  			var historyHashesChan chan []byte
   225  			historyHashesChan, err = getHashes(ctx, registry, storer, NewStream(externalStreamName, "", false))
   226  			if err != nil {
   227  				return
   228  			}
   229  
   230  			var i uint64
   231  			historyTo := externalStreamMaxKeys
   232  			if history != nil {
   233  				i = history.From
   234  				if history.To != 0 {
   235  					historyTo = history.To
   236  				}
   237  			}
   238  
   239  //
   240  			err = enableNotifications(registry, storer, NewStream(externalStreamName, "", false))
   241  			if err != nil {
   242  				return
   243  			}
   244  
   245  			for {
   246  				select {
   247  				case hash := <-historyHashesChan:
   248  					h := binary.BigEndian.Uint64(hash)
   249  					if h != i {
   250  						err = fmt.Errorf("expected history hash %d, got %d", i, h)
   251  						return
   252  					}
   253  					i++
   254  					if i > historyTo {
   255  						return
   256  					}
   257  				case <-ctx.Done():
   258  					return
   259  				}
   260  			}
   261  		}()
   262  
   263  		err = registry.Subscribe(storer, NewStream(externalStreamName, "", live), history, Top)
   264  		if err != nil {
   265  			return err
   266  		}
   267  		if err := <-liveErrC; err != nil {
   268  			return err
   269  		}
   270  		if err := <-historyErrC; err != nil {
   271  			return err
   272  		}
   273  
   274  		return nil
   275  	})
   276  
   277  	if result.Error != nil {
   278  		t.Fatal(result.Error)
   279  	}
   280  }
   281  
   282  func getHashes(ctx context.Context, r *Registry, peerID discover.NodeID, s Stream) (chan []byte, error) {
   283  	peer := r.getPeer(peerID)
   284  
   285  	client, err := peer.getClient(ctx, s)
   286  	if err != nil {
   287  		return nil, err
   288  	}
   289  
   290  	c := client.Client.(*testExternalClient)
   291  
   292  	return c.hashes, nil
   293  }
   294  
   295  func enableNotifications(r *Registry, peerID discover.NodeID, s Stream) error {
   296  	peer := r.getPeer(peerID)
   297  
   298  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   299  	defer cancel()
   300  
   301  	client, err := peer.getClient(ctx, s)
   302  	if err != nil {
   303  		return err
   304  	}
   305  
   306  	close(client.Client.(*testExternalClient).enableNotificationsC)
   307  
   308  	return nil
   309  }
   310  
   311  type testExternalClient struct {
   312  	hashes               chan []byte
   313  	db                   *storage.DBAPI
   314  	enableNotificationsC chan struct{}
   315  }
   316  
   317  func newTestExternalClient(db *storage.DBAPI) *testExternalClient {
   318  	return &testExternalClient{
   319  		hashes:               make(chan []byte),
   320  		db:                   db,
   321  		enableNotificationsC: make(chan struct{}),
   322  	}
   323  }
   324  
   325  func (c *testExternalClient) NeedData(ctx context.Context, hash []byte) func() {
   326  	chunk, _ := c.db.GetOrCreateRequest(ctx, hash)
   327  	if chunk.ReqC == nil {
   328  		return nil
   329  	}
   330  	c.hashes <- hash
   331  //
   332  //
   333  //
   334  //
   335   /*
   336    
   337     
   338    
   339   */
   340  
   341  	return nil
   342  }
   343  
   344  func (c *testExternalClient) BatchDone(Stream, uint64, []byte, []byte) func() (*TakeoverProof, error) {
   345  	return nil
   346  }
   347  
   348  func (c *testExternalClient) Close() {}
   349  
   350  const testExternalServerBatchSize = 10
   351  
   352  type testExternalServer struct {
   353  	t         string
   354  	keyFunc   func(key []byte, index uint64)
   355  	sessionAt uint64
   356  	maxKeys   uint64
   357  }
   358  
   359  func newTestExternalServer(t string, sessionAt, maxKeys uint64, keyFunc func(key []byte, index uint64)) *testExternalServer {
   360  	if keyFunc == nil {
   361  		keyFunc = binary.BigEndian.PutUint64
   362  	}
   363  	return &testExternalServer{
   364  		t:         t,
   365  		keyFunc:   keyFunc,
   366  		sessionAt: sessionAt,
   367  		maxKeys:   maxKeys,
   368  	}
   369  }
   370  
   371  func (s *testExternalServer) SetNextBatch(from uint64, to uint64) ([]byte, uint64, uint64, *HandoverProof, error) {
   372  	if from == 0 && to == 0 {
   373  		from = s.sessionAt
   374  		to = s.sessionAt + testExternalServerBatchSize
   375  	}
   376  	if to-from > testExternalServerBatchSize {
   377  		to = from + testExternalServerBatchSize - 1
   378  	}
   379  	if from >= s.maxKeys && to > s.maxKeys {
   380  		return nil, 0, 0, nil, io.EOF
   381  	}
   382  	if to > s.maxKeys {
   383  		to = s.maxKeys
   384  	}
   385  	b := make([]byte, HashSize*(to-from+1))
   386  	for i := from; i <= to; i++ {
   387  		s.keyFunc(b[(i-from)*HashSize:(i-from+1)*HashSize], i)
   388  	}
   389  	return b, from, to, nil, nil
   390  }
   391  
   392  func (s *testExternalServer) GetData(context.Context, []byte) ([]byte, error) {
   393  	return make([]byte, 4096), nil
   394  }
   395  
   396  func (s *testExternalServer) Close() {}