github.com/core-coin/go-core/v2@v2.1.9/p2p/simulations/http_test.go (about)

     1  // Copyright 2017 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package simulations
    18  
    19  import (
    20  	"context"
    21  	"flag"
    22  	"fmt"
    23  	"math/rand"
    24  	"net/http/httptest"
    25  	"os"
    26  	"reflect"
    27  	"sync"
    28  	"sync/atomic"
    29  	"testing"
    30  	"time"
    31  
    32  	"github.com/mattn/go-colorable"
    33  
    34  	"github.com/core-coin/go-core/v2/event"
    35  	"github.com/core-coin/go-core/v2/log"
    36  	"github.com/core-coin/go-core/v2/node"
    37  	"github.com/core-coin/go-core/v2/p2p"
    38  	"github.com/core-coin/go-core/v2/p2p/enode"
    39  	"github.com/core-coin/go-core/v2/p2p/simulations/adapters"
    40  	"github.com/core-coin/go-core/v2/rpc"
    41  )
    42  
    43  func TestMain(m *testing.M) {
    44  	loglevel := flag.Int("loglevel", 2, "verbosity of logs")
    45  
    46  	flag.Parse()
    47  	log.PrintOrigins(true)
    48  	log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true))))
    49  	os.Exit(m.Run())
    50  }
    51  
    52  // testService implements the node.Service interface and provides protocols
    53  // and APIs which are useful for testing nodes in a simulation network
    54  type testService struct {
    55  	id enode.ID
    56  
    57  	// peerCount is incremented once a peer handshake has been performed
    58  	peerCount int64
    59  
    60  	peers    map[enode.ID]*testPeer
    61  	peersMtx sync.Mutex
    62  
    63  	// state stores []byte which is used to test creating and loading
    64  	// snapshots
    65  	state atomic.Value
    66  }
    67  
    68  func newTestService(ctx *adapters.ServiceContext, stack *node.Node) (node.Lifecycle, error) {
    69  	svc := &testService{
    70  		id:    ctx.Config.ID,
    71  		peers: make(map[enode.ID]*testPeer),
    72  	}
    73  	svc.state.Store(ctx.Snapshot)
    74  
    75  	stack.RegisterProtocols(svc.Protocols())
    76  	stack.RegisterAPIs(svc.APIs())
    77  	return svc, nil
    78  }
    79  
    80  type testPeer struct {
    81  	testReady chan struct{}
    82  	dumReady  chan struct{}
    83  }
    84  
    85  func (t *testService) peer(id enode.ID) *testPeer {
    86  	t.peersMtx.Lock()
    87  	defer t.peersMtx.Unlock()
    88  	if peer, ok := t.peers[id]; ok {
    89  		return peer
    90  	}
    91  	peer := &testPeer{
    92  		testReady: make(chan struct{}),
    93  		dumReady:  make(chan struct{}),
    94  	}
    95  	t.peers[id] = peer
    96  	return peer
    97  }
    98  
    99  func (t *testService) Protocols() []p2p.Protocol {
   100  	return []p2p.Protocol{
   101  		{
   102  			Name:    "test",
   103  			Version: 1,
   104  			Length:  3,
   105  			Run:     t.RunTest,
   106  		},
   107  		{
   108  			Name:    "dum",
   109  			Version: 1,
   110  			Length:  1,
   111  			Run:     t.RunDum,
   112  		},
   113  		{
   114  			Name:    "prb",
   115  			Version: 1,
   116  			Length:  1,
   117  			Run:     t.RunPrb,
   118  		},
   119  	}
   120  }
   121  
   122  func (t *testService) APIs() []rpc.API {
   123  	return []rpc.API{{
   124  		Namespace: "test",
   125  		Version:   "1.0",
   126  		Service: &TestAPI{
   127  			state:     &t.state,
   128  			peerCount: &t.peerCount,
   129  		},
   130  	}}
   131  }
   132  
   133  func (t *testService) Start() error {
   134  	return nil
   135  }
   136  
   137  func (t *testService) Stop() error {
   138  	return nil
   139  }
   140  
   141  // handshake performs a peer handshake by sending and expecting an empty
   142  // message with the given code
   143  func (t *testService) handshake(rw p2p.MsgReadWriter, code uint64) error {
   144  	errc := make(chan error, 2)
   145  	go func() { errc <- p2p.Send(rw, code, struct{}{}) }()
   146  	go func() { errc <- p2p.ExpectMsg(rw, code, struct{}{}) }()
   147  	for i := 0; i < 2; i++ {
   148  		if err := <-errc; err != nil {
   149  			return err
   150  		}
   151  	}
   152  	return nil
   153  }
   154  
   155  func (t *testService) RunTest(p *p2p.Peer, rw p2p.MsgReadWriter) error {
   156  	peer := t.peer(p.ID())
   157  
   158  	// perform three handshakes with three different message codes,
   159  	// used to test message sending and filtering
   160  	if err := t.handshake(rw, 2); err != nil {
   161  		return err
   162  	}
   163  	if err := t.handshake(rw, 1); err != nil {
   164  		return err
   165  	}
   166  	if err := t.handshake(rw, 0); err != nil {
   167  		return err
   168  	}
   169  
   170  	// close the testReady channel so that other protocols can run
   171  	close(peer.testReady)
   172  
   173  	// track the peer
   174  	atomic.AddInt64(&t.peerCount, 1)
   175  	defer atomic.AddInt64(&t.peerCount, -1)
   176  
   177  	// block until the peer is dropped
   178  	for {
   179  		_, err := rw.ReadMsg()
   180  		if err != nil {
   181  			return err
   182  		}
   183  	}
   184  }
   185  
   186  func (t *testService) RunDum(p *p2p.Peer, rw p2p.MsgReadWriter) error {
   187  	peer := t.peer(p.ID())
   188  
   189  	// wait for the test protocol to perform its handshake
   190  	<-peer.testReady
   191  
   192  	// perform a handshake
   193  	if err := t.handshake(rw, 0); err != nil {
   194  		return err
   195  	}
   196  
   197  	// close the dumReady channel so that other protocols can run
   198  	close(peer.dumReady)
   199  
   200  	// block until the peer is dropped
   201  	for {
   202  		_, err := rw.ReadMsg()
   203  		if err != nil {
   204  			return err
   205  		}
   206  	}
   207  }
   208  func (t *testService) RunPrb(p *p2p.Peer, rw p2p.MsgReadWriter) error {
   209  	peer := t.peer(p.ID())
   210  
   211  	// wait for the dum protocol to perform its handshake
   212  	<-peer.dumReady
   213  
   214  	// perform a handshake
   215  	if err := t.handshake(rw, 0); err != nil {
   216  		return err
   217  	}
   218  
   219  	// block until the peer is dropped
   220  	for {
   221  		_, err := rw.ReadMsg()
   222  		if err != nil {
   223  			return err
   224  		}
   225  	}
   226  }
   227  
   228  func (t *testService) Snapshot() ([]byte, error) {
   229  	return t.state.Load().([]byte), nil
   230  }
   231  
   232  // TestAPI provides a test API to:
   233  // * get the peer count
   234  // * get and set an arbitrary state byte slice
   235  // * get and increment a counter
   236  // * subscribe to counter increment events
   237  type TestAPI struct {
   238  	state     *atomic.Value
   239  	peerCount *int64
   240  	counter   int64
   241  	feed      event.Feed
   242  }
   243  
   244  func (t *TestAPI) PeerCount() int64 {
   245  	return atomic.LoadInt64(t.peerCount)
   246  }
   247  
   248  func (t *TestAPI) Get() int64 {
   249  	return atomic.LoadInt64(&t.counter)
   250  }
   251  
   252  func (t *TestAPI) Add(delta int64) {
   253  	atomic.AddInt64(&t.counter, delta)
   254  	t.feed.Send(delta)
   255  }
   256  
   257  func (t *TestAPI) GetState() []byte {
   258  	return t.state.Load().([]byte)
   259  }
   260  
   261  func (t *TestAPI) SetState(state []byte) {
   262  	t.state.Store(state)
   263  }
   264  
   265  func (t *TestAPI) Events(ctx context.Context) (*rpc.Subscription, error) {
   266  	notifier, supported := rpc.NotifierFromContext(ctx)
   267  	if !supported {
   268  		return nil, rpc.ErrNotificationsUnsupported
   269  	}
   270  
   271  	rpcSub := notifier.CreateSubscription()
   272  
   273  	go func() {
   274  		events := make(chan int64)
   275  		sub := t.feed.Subscribe(events)
   276  		defer sub.Unsubscribe()
   277  
   278  		for {
   279  			select {
   280  			case event := <-events:
   281  				notifier.Notify(rpcSub.ID, event)
   282  			case <-sub.Err():
   283  				return
   284  			case <-rpcSub.Err():
   285  				return
   286  			case <-notifier.Closed():
   287  				return
   288  			}
   289  		}
   290  	}()
   291  
   292  	return rpcSub, nil
   293  }
   294  
   295  var testServices = adapters.LifecycleConstructors{
   296  	"test": newTestService,
   297  }
   298  
   299  func testHTTPServer(t *testing.T) (*Network, *httptest.Server) {
   300  	t.Helper()
   301  	adapter := adapters.NewSimAdapter(testServices)
   302  	network := NewNetwork(adapter, &NetworkConfig{
   303  		DefaultService: "test",
   304  	})
   305  	return network, httptest.NewServer(NewServer(network))
   306  }
   307  
   308  // TestHTTPNetwork tests interacting with a simulation network using the HTTP
   309  // API
   310  func TestHTTPNetwork(t *testing.T) {
   311  	// start the server
   312  	network, s := testHTTPServer(t)
   313  	defer s.Close()
   314  
   315  	// subscribe to events so we can check them later
   316  	client := NewClient(s.URL)
   317  	events := make(chan *Event, 100)
   318  	var opts SubscribeOpts
   319  	sub, err := client.SubscribeNetwork(events, opts)
   320  	if err != nil {
   321  		t.Fatalf("error subscribing to network events: %s", err)
   322  	}
   323  	defer sub.Unsubscribe()
   324  
   325  	// check we can retrieve details about the network
   326  	gotNetwork, err := client.GetNetwork()
   327  	if err != nil {
   328  		t.Fatalf("error getting network: %s", err)
   329  	}
   330  	if gotNetwork.ID != network.ID {
   331  		t.Fatalf("expected network to have ID %q, got %q", network.ID, gotNetwork.ID)
   332  	}
   333  
   334  	// start a simulation network
   335  	nodeIDs := startTestNetwork(t, client)
   336  
   337  	// check we got all the events
   338  	x := &expectEvents{t, events, sub}
   339  	x.expect(
   340  		x.nodeEvent(nodeIDs[0], false),
   341  		x.nodeEvent(nodeIDs[1], false),
   342  		x.nodeEvent(nodeIDs[0], true),
   343  		x.nodeEvent(nodeIDs[1], true),
   344  		x.connEvent(nodeIDs[0], nodeIDs[1], false),
   345  		x.connEvent(nodeIDs[0], nodeIDs[1], true),
   346  	)
   347  
   348  	// reconnect the stream and check we get the current nodes and conns
   349  	events = make(chan *Event, 100)
   350  	opts.Current = true
   351  	sub, err = client.SubscribeNetwork(events, opts)
   352  	if err != nil {
   353  		t.Fatalf("error subscribing to network events: %s", err)
   354  	}
   355  	defer sub.Unsubscribe()
   356  	x = &expectEvents{t, events, sub}
   357  	x.expect(
   358  		x.nodeEvent(nodeIDs[0], true),
   359  		x.nodeEvent(nodeIDs[1], true),
   360  		x.connEvent(nodeIDs[0], nodeIDs[1], true),
   361  	)
   362  }
   363  
   364  func startTestNetwork(t *testing.T, client *Client) []string {
   365  	// create two nodes
   366  	nodeCount := 2
   367  	nodeIDs := make([]string, nodeCount)
   368  	for i := 0; i < nodeCount; i++ {
   369  		config := adapters.RandomNodeConfig()
   370  		node, err := client.CreateNode(config)
   371  		if err != nil {
   372  			t.Fatalf("error creating node: %s", err)
   373  		}
   374  		nodeIDs[i] = node.ID
   375  	}
   376  
   377  	// check both nodes exist
   378  	nodes, err := client.GetNodes()
   379  	if err != nil {
   380  		t.Fatalf("error getting nodes: %s", err)
   381  	}
   382  	if len(nodes) != nodeCount {
   383  		t.Fatalf("expected %d nodes, got %d", nodeCount, len(nodes))
   384  	}
   385  	for i, nodeID := range nodeIDs {
   386  		if nodes[i].ID != nodeID {
   387  			t.Fatalf("expected node %d to have ID %q, got %q", i, nodeID, nodes[i].ID)
   388  		}
   389  		node, err := client.GetNode(nodeID)
   390  		if err != nil {
   391  			t.Fatalf("error getting node %d: %s", i, err)
   392  		}
   393  		if node.ID != nodeID {
   394  			t.Fatalf("expected node %d to have ID %q, got %q", i, nodeID, node.ID)
   395  		}
   396  	}
   397  
   398  	// start both nodes
   399  	for _, nodeID := range nodeIDs {
   400  		if err := client.StartNode(nodeID); err != nil {
   401  			t.Fatalf("error starting node %q: %s", nodeID, err)
   402  		}
   403  	}
   404  
   405  	// connect the nodes
   406  	for i := 0; i < nodeCount-1; i++ {
   407  		peerId := i + 1
   408  		if i == nodeCount-1 {
   409  			peerId = 0
   410  		}
   411  		if err := client.ConnectNode(nodeIDs[i], nodeIDs[peerId]); err != nil {
   412  			t.Fatalf("error connecting nodes: %s", err)
   413  		}
   414  	}
   415  
   416  	return nodeIDs
   417  }
   418  
   419  type expectEvents struct {
   420  	*testing.T
   421  
   422  	events chan *Event
   423  	sub    event.Subscription
   424  }
   425  
   426  func (t *expectEvents) nodeEvent(id string, up bool) *Event {
   427  	config := &adapters.NodeConfig{ID: enode.HexID(id)}
   428  	return &Event{Type: EventTypeNode, Node: newNode(nil, config, up)}
   429  }
   430  
   431  func (t *expectEvents) connEvent(one, other string, up bool) *Event {
   432  	return &Event{
   433  		Type: EventTypeConn,
   434  		Conn: &Conn{
   435  			One:   enode.HexID(one),
   436  			Other: enode.HexID(other),
   437  			Up:    up,
   438  		},
   439  	}
   440  }
   441  
   442  func (t *expectEvents) expectMsgs(expected map[MsgFilter]int) {
   443  	actual := make(map[MsgFilter]int)
   444  	timeout := time.After(10 * time.Second)
   445  loop:
   446  	for {
   447  		select {
   448  		case event := <-t.events:
   449  			t.Logf("received %s event: %v", event.Type, event)
   450  
   451  			if event.Type != EventTypeMsg || event.Msg.Received {
   452  				continue loop
   453  			}
   454  			if event.Msg == nil {
   455  				t.Fatal("expected event.Msg to be set")
   456  			}
   457  			filter := MsgFilter{
   458  				Proto: event.Msg.Protocol,
   459  				Code:  int64(event.Msg.Code),
   460  			}
   461  			actual[filter]++
   462  			if actual[filter] > expected[filter] {
   463  				t.Fatalf("received too many msgs for filter: %v", filter)
   464  			}
   465  			if reflect.DeepEqual(actual, expected) {
   466  				return
   467  			}
   468  
   469  		case err := <-t.sub.Err():
   470  			t.Fatalf("network stream closed unexpectedly: %s", err)
   471  
   472  		case <-timeout:
   473  			t.Fatal("timed out waiting for expected events")
   474  		}
   475  	}
   476  }
   477  
   478  func (t *expectEvents) expect(events ...*Event) {
   479  	t.Helper()
   480  	timeout := time.After(10 * time.Second)
   481  	i := 0
   482  	for {
   483  		select {
   484  		case event := <-t.events:
   485  			t.Logf("received %s event: %v", event.Type, event)
   486  
   487  			expected := events[i]
   488  			if event.Type != expected.Type {
   489  				t.Fatalf("expected event %d to have type %q, got %q", i, expected.Type, event.Type)
   490  			}
   491  
   492  			switch expected.Type {
   493  
   494  			case EventTypeNode:
   495  				if event.Node == nil {
   496  					t.Fatal("expected event.Node to be set")
   497  				}
   498  				if event.Node.ID() != expected.Node.ID() {
   499  					t.Fatalf("expected node event %d to have id %q, got %q", i, expected.Node.ID().TerminalString(), event.Node.ID().TerminalString())
   500  				}
   501  				if event.Node.Up() != expected.Node.Up() {
   502  					t.Fatalf("expected node event %d to have up=%t, got up=%t", i, expected.Node.Up(), event.Node.Up())
   503  				}
   504  
   505  			case EventTypeConn:
   506  				if event.Conn == nil {
   507  					t.Fatal("expected event.Conn to be set")
   508  				}
   509  				if event.Conn.One != expected.Conn.One {
   510  					t.Fatalf("expected conn event %d to have one=%q, got one=%q", i, expected.Conn.One.TerminalString(), event.Conn.One.TerminalString())
   511  				}
   512  				if event.Conn.Other != expected.Conn.Other {
   513  					t.Fatalf("expected conn event %d to have other=%q, got other=%q", i, expected.Conn.Other.TerminalString(), event.Conn.Other.TerminalString())
   514  				}
   515  				if event.Conn.Up != expected.Conn.Up {
   516  					t.Fatalf("expected conn event %d to have up=%t, got up=%t", i, expected.Conn.Up, event.Conn.Up)
   517  				}
   518  
   519  			}
   520  
   521  			i++
   522  			if i == len(events) {
   523  				return
   524  			}
   525  
   526  		case err := <-t.sub.Err():
   527  			t.Fatalf("network stream closed unexpectedly: %s", err)
   528  
   529  		case <-timeout:
   530  			t.Fatal("timed out waiting for expected events")
   531  		}
   532  	}
   533  }
   534  
   535  // TestHTTPNodeRPC tests calling RPC methods on nodes via the HTTP API
   536  func TestHTTPNodeRPC(t *testing.T) {
   537  	// start the server
   538  	_, s := testHTTPServer(t)
   539  	defer s.Close()
   540  
   541  	// start a node in the network
   542  	client := NewClient(s.URL)
   543  
   544  	config := adapters.RandomNodeConfig()
   545  	node, err := client.CreateNode(config)
   546  	if err != nil {
   547  		t.Fatalf("error creating node: %s", err)
   548  	}
   549  	if err := client.StartNode(node.ID); err != nil {
   550  		t.Fatalf("error starting node: %s", err)
   551  	}
   552  
   553  	// create two RPC clients
   554  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   555  	defer cancel()
   556  	rpcClient1, err := client.RPCClient(ctx, node.ID)
   557  	if err != nil {
   558  		t.Fatalf("error getting node RPC client: %s", err)
   559  	}
   560  	rpcClient2, err := client.RPCClient(ctx, node.ID)
   561  	if err != nil {
   562  		t.Fatalf("error getting node RPC client: %s", err)
   563  	}
   564  
   565  	// subscribe to events using client 1
   566  	events := make(chan int64, 1)
   567  	sub, err := rpcClient1.Subscribe(ctx, "test", events, "events")
   568  	if err != nil {
   569  		t.Fatalf("error subscribing to events: %s", err)
   570  	}
   571  	defer sub.Unsubscribe()
   572  
   573  	// call some RPC methods using client 2
   574  	if err := rpcClient2.CallContext(ctx, nil, "test_add", 10); err != nil {
   575  		t.Fatalf("error calling RPC method: %s", err)
   576  	}
   577  	var result int64
   578  	if err := rpcClient2.CallContext(ctx, &result, "test_get"); err != nil {
   579  		t.Fatalf("error calling RPC method: %s", err)
   580  	}
   581  	if result != 10 {
   582  		t.Fatalf("expected result to be 10, got %d", result)
   583  	}
   584  
   585  	// check we got an event from client 1
   586  	select {
   587  	case event := <-events:
   588  		if event != 10 {
   589  			t.Fatalf("expected event to be 10, got %d", event)
   590  		}
   591  	case <-ctx.Done():
   592  		t.Fatal(ctx.Err())
   593  	}
   594  }
   595  
   596  // TestHTTPSnapshot tests creating and loading network snapshots
   597  func TestHTTPSnapshot(t *testing.T) {
   598  	// start the server
   599  	network, s := testHTTPServer(t)
   600  	defer s.Close()
   601  
   602  	var eventsDone = make(chan struct{})
   603  	count := 1
   604  	eventsDoneChan := make(chan *Event)
   605  	eventSub := network.Events().Subscribe(eventsDoneChan)
   606  	go func() {
   607  		defer eventSub.Unsubscribe()
   608  		for event := range eventsDoneChan {
   609  			if event.Type == EventTypeConn && !event.Control {
   610  				count--
   611  				if count == 0 {
   612  					eventsDone <- struct{}{}
   613  					return
   614  				}
   615  			}
   616  		}
   617  	}()
   618  
   619  	// create a two-node network
   620  	client := NewClient(s.URL)
   621  	nodeCount := 2
   622  	nodes := make([]*p2p.NodeInfo, nodeCount)
   623  	for i := 0; i < nodeCount; i++ {
   624  		config := adapters.RandomNodeConfig()
   625  		node, err := client.CreateNode(config)
   626  		if err != nil {
   627  			t.Fatalf("error creating node: %s", err)
   628  		}
   629  		if err := client.StartNode(node.ID); err != nil {
   630  			t.Fatalf("error starting node: %s", err)
   631  		}
   632  		nodes[i] = node
   633  	}
   634  	if err := client.ConnectNode(nodes[0].ID, nodes[1].ID); err != nil {
   635  		t.Fatalf("error connecting nodes: %s", err)
   636  	}
   637  
   638  	// store some state in the test services
   639  	states := make([]string, nodeCount)
   640  	for i, node := range nodes {
   641  		rpc, err := client.RPCClient(context.Background(), node.ID)
   642  		if err != nil {
   643  			t.Fatalf("error getting RPC client: %s", err)
   644  		}
   645  		defer rpc.Close()
   646  		state := fmt.Sprintf("%x", rand.Int())
   647  		if err := rpc.Call(nil, "test_setState", []byte(state)); err != nil {
   648  			t.Fatalf("error setting service state: %s", err)
   649  		}
   650  		states[i] = state
   651  	}
   652  	<-eventsDone
   653  	// create a snapshot
   654  	snap, err := client.CreateSnapshot()
   655  	if err != nil {
   656  		t.Fatalf("error creating snapshot: %s", err)
   657  	}
   658  	for i, state := range states {
   659  		gotState := snap.Nodes[i].Snapshots["test"]
   660  		if string(gotState) != state {
   661  			t.Fatalf("expected snapshot state %q, got %q", state, gotState)
   662  		}
   663  	}
   664  
   665  	// create another network
   666  	network2, s := testHTTPServer(t)
   667  	defer s.Close()
   668  	client = NewClient(s.URL)
   669  	count = 1
   670  	eventSub = network2.Events().Subscribe(eventsDoneChan)
   671  	go func() {
   672  		defer eventSub.Unsubscribe()
   673  		for event := range eventsDoneChan {
   674  			if event.Type == EventTypeConn && !event.Control {
   675  				count--
   676  				if count == 0 {
   677  					eventsDone <- struct{}{}
   678  					return
   679  				}
   680  			}
   681  		}
   682  	}()
   683  
   684  	// subscribe to events so we can check them later
   685  	events := make(chan *Event, 100)
   686  	var opts SubscribeOpts
   687  	sub, err := client.SubscribeNetwork(events, opts)
   688  	if err != nil {
   689  		t.Fatalf("error subscribing to network events: %s", err)
   690  	}
   691  	defer sub.Unsubscribe()
   692  
   693  	// load the snapshot
   694  	if err := client.LoadSnapshot(snap); err != nil {
   695  		t.Fatalf("error loading snapshot: %s", err)
   696  	}
   697  	<-eventsDone
   698  
   699  	// check the nodes and connection exists
   700  	net, err := client.GetNetwork()
   701  	if err != nil {
   702  		t.Fatalf("error getting network: %s", err)
   703  	}
   704  	if len(net.Nodes) != nodeCount {
   705  		t.Fatalf("expected network to have %d nodes, got %d", nodeCount, len(net.Nodes))
   706  	}
   707  	for i, node := range nodes {
   708  		id := net.Nodes[i].ID().String()
   709  		if id != node.ID {
   710  			t.Fatalf("expected node %d to have ID %s, got %s", i, node.ID, id)
   711  		}
   712  	}
   713  	if len(net.Conns) != 1 {
   714  		t.Fatalf("expected network to have 1 connection, got %d", len(net.Conns))
   715  	}
   716  	conn := net.Conns[0]
   717  	if conn.One.String() != nodes[0].ID {
   718  		t.Fatalf("expected connection to have one=%q, got one=%q", nodes[0].ID, conn.One)
   719  	}
   720  	if conn.Other.String() != nodes[1].ID {
   721  		t.Fatalf("expected connection to have other=%q, got other=%q", nodes[1].ID, conn.Other)
   722  	}
   723  	if !conn.Up {
   724  		t.Fatal("should be up")
   725  	}
   726  
   727  	// check the node states were restored
   728  	for i, node := range nodes {
   729  		rpc, err := client.RPCClient(context.Background(), node.ID)
   730  		if err != nil {
   731  			t.Fatalf("error getting RPC client: %s", err)
   732  		}
   733  		defer rpc.Close()
   734  		var state []byte
   735  		if err := rpc.Call(&state, "test_getState"); err != nil {
   736  			t.Fatalf("error getting service state: %s", err)
   737  		}
   738  		if string(state) != states[i] {
   739  			t.Fatalf("expected snapshot state %q, got %q", states[i], state)
   740  		}
   741  	}
   742  
   743  	// check we got all the events
   744  	x := &expectEvents{t, events, sub}
   745  	x.expect(
   746  		x.nodeEvent(nodes[0].ID, false),
   747  		x.nodeEvent(nodes[0].ID, true),
   748  		x.nodeEvent(nodes[1].ID, false),
   749  		x.nodeEvent(nodes[1].ID, true),
   750  		x.connEvent(nodes[0].ID, nodes[1].ID, false),
   751  		x.connEvent(nodes[0].ID, nodes[1].ID, true),
   752  	)
   753  }
   754  
   755  // TestMsgFilterPassMultiple tests streaming message events using a filter
   756  // with multiple protocols
   757  func TestMsgFilterPassMultiple(t *testing.T) {
   758  	// start the server
   759  	_, s := testHTTPServer(t)
   760  	defer s.Close()
   761  
   762  	// subscribe to events with a message filter
   763  	client := NewClient(s.URL)
   764  	events := make(chan *Event, 10)
   765  	opts := SubscribeOpts{
   766  		Filter: "prb:0-test:0",
   767  	}
   768  	sub, err := client.SubscribeNetwork(events, opts)
   769  	if err != nil {
   770  		t.Fatalf("error subscribing to network events: %s", err)
   771  	}
   772  	defer sub.Unsubscribe()
   773  
   774  	// start a simulation network
   775  	startTestNetwork(t, client)
   776  
   777  	// check we got the expected events
   778  	x := &expectEvents{t, events, sub}
   779  	x.expectMsgs(map[MsgFilter]int{
   780  		{"test", 0}: 2,
   781  		{"prb", 0}:  2,
   782  	})
   783  }
   784  
   785  // TestMsgFilterPassWildcard tests streaming message events using a filter
   786  // with a code wildcard
   787  func TestMsgFilterPassWildcard(t *testing.T) {
   788  	// start the server
   789  	_, s := testHTTPServer(t)
   790  	defer s.Close()
   791  
   792  	// subscribe to events with a message filter
   793  	client := NewClient(s.URL)
   794  	events := make(chan *Event, 10)
   795  	opts := SubscribeOpts{
   796  		Filter: "prb:0,2-test:*",
   797  	}
   798  	sub, err := client.SubscribeNetwork(events, opts)
   799  	if err != nil {
   800  		t.Fatalf("error subscribing to network events: %s", err)
   801  	}
   802  	defer sub.Unsubscribe()
   803  
   804  	// start a simulation network
   805  	startTestNetwork(t, client)
   806  
   807  	// check we got the expected events
   808  	x := &expectEvents{t, events, sub}
   809  	x.expectMsgs(map[MsgFilter]int{
   810  		{"test", 2}: 2,
   811  		{"test", 1}: 2,
   812  		{"test", 0}: 2,
   813  		{"prb", 0}:  2,
   814  	})
   815  }
   816  
   817  // TestMsgFilterPassSingle tests streaming message events using a filter
   818  // with a single protocol and code
   819  func TestMsgFilterPassSingle(t *testing.T) {
   820  	// start the server
   821  	_, s := testHTTPServer(t)
   822  	defer s.Close()
   823  
   824  	// subscribe to events with a message filter
   825  	client := NewClient(s.URL)
   826  	events := make(chan *Event, 10)
   827  	opts := SubscribeOpts{
   828  		Filter: "dum:0",
   829  	}
   830  	sub, err := client.SubscribeNetwork(events, opts)
   831  	if err != nil {
   832  		t.Fatalf("error subscribing to network events: %s", err)
   833  	}
   834  	defer sub.Unsubscribe()
   835  
   836  	// start a simulation network
   837  	startTestNetwork(t, client)
   838  
   839  	// check we got the expected events
   840  	x := &expectEvents{t, events, sub}
   841  	x.expectMsgs(map[MsgFilter]int{
   842  		{"dum", 0}: 2,
   843  	})
   844  }
   845  
   846  // TestMsgFilterPassSingle tests streaming message events using an invalid
   847  // filter
   848  func TestMsgFilterFailBadParams(t *testing.T) {
   849  	// start the server
   850  	_, s := testHTTPServer(t)
   851  	defer s.Close()
   852  
   853  	client := NewClient(s.URL)
   854  	events := make(chan *Event, 10)
   855  	opts := SubscribeOpts{
   856  		Filter: "foo:",
   857  	}
   858  	_, err := client.SubscribeNetwork(events, opts)
   859  	if err == nil {
   860  		t.Fatalf("expected event subscription to fail but succeeded!")
   861  	}
   862  
   863  	opts.Filter = "bzz:aa"
   864  	_, err = client.SubscribeNetwork(events, opts)
   865  	if err == nil {
   866  		t.Fatalf("expected event subscription to fail but succeeded!")
   867  	}
   868  
   869  	opts.Filter = "invalid"
   870  	_, err = client.SubscribeNetwork(events, opts)
   871  	if err == nil {
   872  		t.Fatalf("expected event subscription to fail but succeeded!")
   873  	}
   874  }