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