/tests/pubsub/newHeads_test.py

https://github.com/Conflux-Chain/conflux-rust · Python · 91 lines · 54 code · 24 blank · 13 comment · 4 complexity · b14f8ebf63e326c8bc06ab7511524895 MD5 · raw file

  1. #!/usr/bin/env python3
  2. # allow imports from parent directory
  3. # source: https://stackoverflow.com/a/11158224
  4. import os, sys
  5. sys.path.insert(1, os.path.join(sys.path[0], '..'))
  6. import asyncio
  7. from conflux.rpc import RpcClient
  8. from conflux.pubsub import PubSubClient
  9. from test_framework.test_framework import ConfluxTestFramework
  10. from test_framework.util import assert_equal, connect_nodes
  11. FULLNODE0 = 0
  12. FULLNODE1 = 1
  13. LIGHTNODE = 2
  14. NUM_BLOCKS = 100
  15. class PubSubTest(ConfluxTestFramework):
  16. def set_test_params(self):
  17. self.num_nodes = 3
  18. def setup_network(self):
  19. self.add_nodes(self.num_nodes)
  20. self.start_node(FULLNODE0, ["--archive"])
  21. self.start_node(FULLNODE1, ["--archive"])
  22. self.start_node(LIGHTNODE, ["--light"], phase_to_wait=None)
  23. # set up RPC clients
  24. self.rpc = [None] * self.num_nodes
  25. self.rpc[FULLNODE0] = RpcClient(self.nodes[FULLNODE0])
  26. self.rpc[FULLNODE1] = RpcClient(self.nodes[FULLNODE1])
  27. self.rpc[LIGHTNODE] = RpcClient(self.nodes[LIGHTNODE])
  28. # set up PubSub clients
  29. self.pubsub = [None] * self.num_nodes
  30. self.pubsub[FULLNODE0] = PubSubClient(self.nodes[FULLNODE0])
  31. self.pubsub[FULLNODE1] = PubSubClient(self.nodes[FULLNODE1])
  32. self.pubsub[LIGHTNODE] = PubSubClient(self.nodes[LIGHTNODE])
  33. # connect nodes
  34. connect_nodes(self.nodes, FULLNODE0, FULLNODE1)
  35. connect_nodes(self.nodes, LIGHTNODE, FULLNODE0)
  36. connect_nodes(self.nodes, LIGHTNODE, FULLNODE1)
  37. # wait for phase changes to complete
  38. self.nodes[FULLNODE0].wait_for_phase(["NormalSyncPhase"])
  39. self.nodes[FULLNODE1].wait_for_phase(["NormalSyncPhase"])
  40. async def run_async(self):
  41. # subscribe
  42. sub_full = await self.pubsub[FULLNODE1].subscribe("newHeads")
  43. sub_light = await self.pubsub[LIGHTNODE].subscribe("newHeads")
  44. # -------- 1. receive headers one-by-one --------
  45. for _ in range(NUM_BLOCKS):
  46. hash = self.rpc[FULLNODE0].generate_block()
  47. # check archive node pub-sub
  48. block = await sub_full.next()
  49. assert_equal(block["hash"], hash)
  50. # check light node pub-sub
  51. block = await sub_light.next()
  52. assert_equal(block["hash"], hash)
  53. self.log.info("Pass -- 1")
  54. # -------- 2. receive headers concurrently --------
  55. hashes = self.rpc[FULLNODE0].generate_blocks(NUM_BLOCKS)
  56. # NOTE: headers might be received out-of-order
  57. full_hashes = [h["hash"] async for h in sub_full.iter()]
  58. assert_equal(sorted(hashes), sorted(full_hashes))
  59. light_hashes = [h["hash"] async for h in sub_light.iter()]
  60. assert_equal(sorted(hashes), sorted(light_hashes))
  61. self.log.info("Pass -- 2")
  62. await sub_full.unsubscribe()
  63. await sub_light.unsubscribe()
  64. def run_test(self):
  65. asyncio.get_event_loop().run_until_complete(self.run_async())
  66. if __name__ == "__main__":
  67. PubSubTest().main()