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