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