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 }