github.com/luckypickle/go-ethereum-vet@v1.14.2/p2p/simulations/http_test.go (about)

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