github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/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/intfoundation/intchain/event"
    31  	"github.com/intfoundation/intchain/node"
    32  	"github.com/intfoundation/intchain/p2p"
    33  	"github.com/intfoundation/intchain/p2p/discover"
    34  	"github.com/intfoundation/intchain/p2p/simulations/adapters"
    35  	"github.com/intfoundation/intchain/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  		node, err := client.CreateNode(nil)
   352  		if err != nil {
   353  			t.Fatalf("error creating node: %s", err)
   354  		}
   355  		nodeIDs[i] = node.ID
   356  	}
   357  
   358  	// check both nodes exist
   359  	nodes, err := client.GetNodes()
   360  	if err != nil {
   361  		t.Fatalf("error getting nodes: %s", err)
   362  	}
   363  	if len(nodes) != nodeCount {
   364  		t.Fatalf("expected %d nodes, got %d", nodeCount, len(nodes))
   365  	}
   366  	for i, nodeID := range nodeIDs {
   367  		if nodes[i].ID != nodeID {
   368  			t.Fatalf("expected node %d to have ID %q, got %q", i, nodeID, nodes[i].ID)
   369  		}
   370  		node, err := client.GetNode(nodeID)
   371  		if err != nil {
   372  			t.Fatalf("error getting node %d: %s", i, err)
   373  		}
   374  		if node.ID != nodeID {
   375  			t.Fatalf("expected node %d to have ID %q, got %q", i, nodeID, node.ID)
   376  		}
   377  	}
   378  
   379  	// start both nodes
   380  	for _, nodeID := range nodeIDs {
   381  		if err := client.StartNode(nodeID); err != nil {
   382  			t.Fatalf("error starting node %q: %s", nodeID, err)
   383  		}
   384  	}
   385  
   386  	// connect the nodes
   387  	for i := 0; i < nodeCount-1; i++ {
   388  		peerId := i + 1
   389  		if i == nodeCount-1 {
   390  			peerId = 0
   391  		}
   392  		if err := client.ConnectNode(nodeIDs[i], nodeIDs[peerId]); err != nil {
   393  			t.Fatalf("error connecting nodes: %s", err)
   394  		}
   395  	}
   396  
   397  	return nodeIDs
   398  }
   399  
   400  type expectEvents struct {
   401  	*testing.T
   402  
   403  	events chan *Event
   404  	sub    event.Subscription
   405  }
   406  
   407  func (t *expectEvents) nodeEvent(id string, up bool) *Event {
   408  	return &Event{
   409  		Type: EventTypeNode,
   410  		Node: &Node{
   411  			Config: &adapters.NodeConfig{
   412  				ID: discover.MustHexID(id),
   413  			},
   414  			Up: up,
   415  		},
   416  	}
   417  }
   418  
   419  func (t *expectEvents) connEvent(one, other string, up bool) *Event {
   420  	return &Event{
   421  		Type: EventTypeConn,
   422  		Conn: &Conn{
   423  			One:   discover.MustHexID(one),
   424  			Other: discover.MustHexID(other),
   425  			Up:    up,
   426  		},
   427  	}
   428  }
   429  
   430  func (t *expectEvents) expectMsgs(expected map[MsgFilter]int) {
   431  	actual := make(map[MsgFilter]int)
   432  	timeout := time.After(10 * time.Second)
   433  loop:
   434  	for {
   435  		select {
   436  		case event := <-t.events:
   437  			t.Logf("received %s event: %s", event.Type, event)
   438  
   439  			if event.Type != EventTypeMsg || event.Msg.Received {
   440  				continue loop
   441  			}
   442  			if event.Msg == nil {
   443  				t.Fatal("expected event.Msg to be set")
   444  			}
   445  			filter := MsgFilter{
   446  				Proto: event.Msg.Protocol,
   447  				Code:  int64(event.Msg.Code),
   448  			}
   449  			actual[filter]++
   450  			if actual[filter] > expected[filter] {
   451  				t.Fatalf("received too many msgs for filter: %v", filter)
   452  			}
   453  			if reflect.DeepEqual(actual, expected) {
   454  				return
   455  			}
   456  
   457  		case err := <-t.sub.Err():
   458  			t.Fatalf("network stream closed unexpectedly: %s", err)
   459  
   460  		case <-timeout:
   461  			t.Fatal("timed out waiting for expected events")
   462  		}
   463  	}
   464  }
   465  
   466  func (t *expectEvents) expect(events ...*Event) {
   467  	timeout := time.After(10 * time.Second)
   468  	i := 0
   469  	for {
   470  		select {
   471  		case event := <-t.events:
   472  			t.Logf("received %s event: %s", event.Type, event)
   473  
   474  			expected := events[i]
   475  			if event.Type != expected.Type {
   476  				t.Fatalf("expected event %d to have type %q, got %q", i, expected.Type, event.Type)
   477  			}
   478  
   479  			switch expected.Type {
   480  
   481  			case EventTypeNode:
   482  				if event.Node == nil {
   483  					t.Fatal("expected event.Node to be set")
   484  				}
   485  				if event.Node.ID() != expected.Node.ID() {
   486  					t.Fatalf("expected node event %d to have id %q, got %q", i, expected.Node.ID().TerminalString(), event.Node.ID().TerminalString())
   487  				}
   488  				if event.Node.Up != expected.Node.Up {
   489  					t.Fatalf("expected node event %d to have up=%t, got up=%t", i, expected.Node.Up, event.Node.Up)
   490  				}
   491  
   492  			case EventTypeConn:
   493  				if event.Conn == nil {
   494  					t.Fatal("expected event.Conn to be set")
   495  				}
   496  				if event.Conn.One != expected.Conn.One {
   497  					t.Fatalf("expected conn event %d to have one=%q, got one=%q", i, expected.Conn.One.TerminalString(), event.Conn.One.TerminalString())
   498  				}
   499  				if event.Conn.Other != expected.Conn.Other {
   500  					t.Fatalf("expected conn event %d to have other=%q, got other=%q", i, expected.Conn.Other.TerminalString(), event.Conn.Other.TerminalString())
   501  				}
   502  				if event.Conn.Up != expected.Conn.Up {
   503  					t.Fatalf("expected conn event %d to have up=%t, got up=%t", i, expected.Conn.Up, event.Conn.Up)
   504  				}
   505  
   506  			}
   507  
   508  			i++
   509  			if i == len(events) {
   510  				return
   511  			}
   512  
   513  		case err := <-t.sub.Err():
   514  			t.Fatalf("network stream closed unexpectedly: %s", err)
   515  
   516  		case <-timeout:
   517  			t.Fatal("timed out waiting for expected events")
   518  		}
   519  	}
   520  }
   521  
   522  // TestHTTPNodeRPC tests calling RPC methods on nodes via the HTTP API
   523  func TestHTTPNodeRPC(t *testing.T) {
   524  	// start the server
   525  	_, s := testHTTPServer(t)
   526  	defer s.Close()
   527  
   528  	// start a node in the network
   529  	client := NewClient(s.URL)
   530  	node, err := client.CreateNode(nil)
   531  	if err != nil {
   532  		t.Fatalf("error creating node: %s", err)
   533  	}
   534  	if err := client.StartNode(node.ID); err != nil {
   535  		t.Fatalf("error starting node: %s", err)
   536  	}
   537  
   538  	// create two RPC clients
   539  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   540  	defer cancel()
   541  	rpcClient1, err := client.RPCClient(ctx, node.ID)
   542  	if err != nil {
   543  		t.Fatalf("error getting node RPC client: %s", err)
   544  	}
   545  	rpcClient2, err := client.RPCClient(ctx, node.ID)
   546  	if err != nil {
   547  		t.Fatalf("error getting node RPC client: %s", err)
   548  	}
   549  
   550  	// subscribe to events using client 1
   551  	events := make(chan int64, 1)
   552  	sub, err := rpcClient1.Subscribe(ctx, "test", events, "events")
   553  	if err != nil {
   554  		t.Fatalf("error subscribing to events: %s", err)
   555  	}
   556  	defer sub.Unsubscribe()
   557  
   558  	// call some RPC methods using client 2
   559  	if err := rpcClient2.CallContext(ctx, nil, "test_add", 10); err != nil {
   560  		t.Fatalf("error calling RPC method: %s", err)
   561  	}
   562  	var result int64
   563  	if err := rpcClient2.CallContext(ctx, &result, "test_get"); err != nil {
   564  		t.Fatalf("error calling RPC method: %s", err)
   565  	}
   566  	if result != 10 {
   567  		t.Fatalf("expected result to be 10, got %d", result)
   568  	}
   569  
   570  	// check we got an event from client 1
   571  	select {
   572  	case event := <-events:
   573  		if event != 10 {
   574  			t.Fatalf("expected event to be 10, got %d", event)
   575  		}
   576  	case <-ctx.Done():
   577  		t.Fatal(ctx.Err())
   578  	}
   579  }
   580  
   581  // TestHTTPSnapshot tests creating and loading network snapshots
   582  func TestHTTPSnapshot(t *testing.T) {
   583  	// start the server
   584  	_, s := testHTTPServer(t)
   585  	defer s.Close()
   586  
   587  	// create a two-node network
   588  	client := NewClient(s.URL)
   589  	nodeCount := 2
   590  	nodes := make([]*p2p.NodeInfo, nodeCount)
   591  	for i := 0; i < nodeCount; i++ {
   592  		node, err := client.CreateNode(nil)
   593  		if err != nil {
   594  			t.Fatalf("error creating node: %s", err)
   595  		}
   596  		if err := client.StartNode(node.ID); err != nil {
   597  			t.Fatalf("error starting node: %s", err)
   598  		}
   599  		nodes[i] = node
   600  	}
   601  	if err := client.ConnectNode(nodes[0].ID, nodes[1].ID); err != nil {
   602  		t.Fatalf("error connecting nodes: %s", err)
   603  	}
   604  
   605  	// store some state in the test services
   606  	states := make([]string, nodeCount)
   607  	for i, node := range nodes {
   608  		rpc, err := client.RPCClient(context.Background(), node.ID)
   609  		if err != nil {
   610  			t.Fatalf("error getting RPC client: %s", err)
   611  		}
   612  		defer rpc.Close()
   613  		state := fmt.Sprintf("%x", rand.Int())
   614  		if err := rpc.Call(nil, "test_setState", []byte(state)); err != nil {
   615  			t.Fatalf("error setting service state: %s", err)
   616  		}
   617  		states[i] = state
   618  	}
   619  
   620  	// create a snapshot
   621  	snap, err := client.CreateSnapshot()
   622  	if err != nil {
   623  		t.Fatalf("error creating snapshot: %s", err)
   624  	}
   625  	for i, state := range states {
   626  		gotState := snap.Nodes[i].Snapshots["test"]
   627  		if string(gotState) != state {
   628  			t.Fatalf("expected snapshot state %q, got %q", state, gotState)
   629  		}
   630  	}
   631  
   632  	// create another network
   633  	_, s = testHTTPServer(t)
   634  	defer s.Close()
   635  	client = NewClient(s.URL)
   636  
   637  	// subscribe to events so we can check them later
   638  	events := make(chan *Event, 100)
   639  	var opts SubscribeOpts
   640  	sub, err := client.SubscribeNetwork(events, opts)
   641  	if err != nil {
   642  		t.Fatalf("error subscribing to network events: %s", err)
   643  	}
   644  	defer sub.Unsubscribe()
   645  
   646  	// load the snapshot
   647  	if err := client.LoadSnapshot(snap); err != nil {
   648  		t.Fatalf("error loading snapshot: %s", err)
   649  	}
   650  
   651  	// check the nodes and connection exists
   652  	net, err := client.GetNetwork()
   653  	if err != nil {
   654  		t.Fatalf("error getting network: %s", err)
   655  	}
   656  	if len(net.Nodes) != nodeCount {
   657  		t.Fatalf("expected network to have %d nodes, got %d", nodeCount, len(net.Nodes))
   658  	}
   659  	for i, node := range nodes {
   660  		id := net.Nodes[i].ID().String()
   661  		if id != node.ID {
   662  			t.Fatalf("expected node %d to have ID %s, got %s", i, node.ID, id)
   663  		}
   664  	}
   665  	if len(net.Conns) != 1 {
   666  		t.Fatalf("expected network to have 1 connection, got %d", len(net.Conns))
   667  	}
   668  	conn := net.Conns[0]
   669  	if conn.One.String() != nodes[0].ID {
   670  		t.Fatalf("expected connection to have one=%q, got one=%q", nodes[0].ID, conn.One)
   671  	}
   672  	if conn.Other.String() != nodes[1].ID {
   673  		t.Fatalf("expected connection to have other=%q, got other=%q", nodes[1].ID, conn.Other)
   674  	}
   675  
   676  	// check the node states were restored
   677  	for i, node := range nodes {
   678  		rpc, err := client.RPCClient(context.Background(), node.ID)
   679  		if err != nil {
   680  			t.Fatalf("error getting RPC client: %s", err)
   681  		}
   682  		defer rpc.Close()
   683  		var state []byte
   684  		if err := rpc.Call(&state, "test_getState"); err != nil {
   685  			t.Fatalf("error getting service state: %s", err)
   686  		}
   687  		if string(state) != states[i] {
   688  			t.Fatalf("expected snapshot state %q, got %q", states[i], state)
   689  		}
   690  	}
   691  
   692  	// check we got all the events
   693  	x := &expectEvents{t, events, sub}
   694  	x.expect(
   695  		x.nodeEvent(nodes[0].ID, false),
   696  		x.nodeEvent(nodes[0].ID, true),
   697  		x.nodeEvent(nodes[1].ID, false),
   698  		x.nodeEvent(nodes[1].ID, true),
   699  		x.connEvent(nodes[0].ID, nodes[1].ID, false),
   700  		x.connEvent(nodes[0].ID, nodes[1].ID, true),
   701  	)
   702  }
   703  
   704  // TestMsgFilterPassMultiple tests streaming message events using a filter
   705  // with multiple protocols
   706  func TestMsgFilterPassMultiple(t *testing.T) {
   707  	// start the server
   708  	_, s := testHTTPServer(t)
   709  	defer s.Close()
   710  
   711  	// subscribe to events with a message filter
   712  	client := NewClient(s.URL)
   713  	events := make(chan *Event, 10)
   714  	opts := SubscribeOpts{
   715  		Filter: "prb:0-test:0",
   716  	}
   717  	sub, err := client.SubscribeNetwork(events, opts)
   718  	if err != nil {
   719  		t.Fatalf("error subscribing to network events: %s", err)
   720  	}
   721  	defer sub.Unsubscribe()
   722  
   723  	// start a simulation network
   724  	startTestNetwork(t, client)
   725  
   726  	// check we got the expected events
   727  	x := &expectEvents{t, events, sub}
   728  	x.expectMsgs(map[MsgFilter]int{
   729  		{"test", 0}: 2,
   730  		{"prb", 0}:  2,
   731  	})
   732  }
   733  
   734  // TestMsgFilterPassWildcard tests streaming message events using a filter
   735  // with a code wildcard
   736  func TestMsgFilterPassWildcard(t *testing.T) {
   737  	// start the server
   738  	_, s := testHTTPServer(t)
   739  	defer s.Close()
   740  
   741  	// subscribe to events with a message filter
   742  	client := NewClient(s.URL)
   743  	events := make(chan *Event, 10)
   744  	opts := SubscribeOpts{
   745  		Filter: "prb:0,2-test:*",
   746  	}
   747  	sub, err := client.SubscribeNetwork(events, opts)
   748  	if err != nil {
   749  		t.Fatalf("error subscribing to network events: %s", err)
   750  	}
   751  	defer sub.Unsubscribe()
   752  
   753  	// start a simulation network
   754  	startTestNetwork(t, client)
   755  
   756  	// check we got the expected events
   757  	x := &expectEvents{t, events, sub}
   758  	x.expectMsgs(map[MsgFilter]int{
   759  		{"test", 2}: 2,
   760  		{"test", 1}: 2,
   761  		{"test", 0}: 2,
   762  		{"prb", 0}:  2,
   763  	})
   764  }
   765  
   766  // TestMsgFilterPassSingle tests streaming message events using a filter
   767  // with a single protocol and code
   768  func TestMsgFilterPassSingle(t *testing.T) {
   769  	// start the server
   770  	_, s := testHTTPServer(t)
   771  	defer s.Close()
   772  
   773  	// subscribe to events with a message filter
   774  	client := NewClient(s.URL)
   775  	events := make(chan *Event, 10)
   776  	opts := SubscribeOpts{
   777  		Filter: "dum:0",
   778  	}
   779  	sub, err := client.SubscribeNetwork(events, opts)
   780  	if err != nil {
   781  		t.Fatalf("error subscribing to network events: %s", err)
   782  	}
   783  	defer sub.Unsubscribe()
   784  
   785  	// start a simulation network
   786  	startTestNetwork(t, client)
   787  
   788  	// check we got the expected events
   789  	x := &expectEvents{t, events, sub}
   790  	x.expectMsgs(map[MsgFilter]int{
   791  		{"dum", 0}: 2,
   792  	})
   793  }
   794  
   795  // TestMsgFilterPassSingle tests streaming message events using an invalid
   796  // filter
   797  func TestMsgFilterFailBadParams(t *testing.T) {
   798  	// start the server
   799  	_, s := testHTTPServer(t)
   800  	defer s.Close()
   801  
   802  	client := NewClient(s.URL)
   803  	events := make(chan *Event, 10)
   804  	opts := SubscribeOpts{
   805  		Filter: "foo:",
   806  	}
   807  	_, err := client.SubscribeNetwork(events, opts)
   808  	if err == nil {
   809  		t.Fatalf("expected event subscription to fail but succeeded!")
   810  	}
   811  
   812  	opts.Filter = "bzz:aa"
   813  	_, err = client.SubscribeNetwork(events, opts)
   814  	if err == nil {
   815  		t.Fatalf("expected event subscription to fail but succeeded!")
   816  	}
   817  
   818  	opts.Filter = "invalid"
   819  	_, err = client.SubscribeNetwork(events, opts)
   820  	if err == nil {
   821  		t.Fatalf("expected event subscription to fail but succeeded!")
   822  	}
   823  }