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