Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

166 lines
6.1KB

  1. import asyncio
  2. import itertools
  3. from pico import start_server, send_json, recv_json
  4. import websockets
  5. class Script:
  6. def __init__(self):
  7. self.events = []
  8. def __add__(self, event):
  9. self.events.append(('send', event))
  10. return self
  11. def __sub__(self, event):
  12. self.events.append(('recv', event))
  13. return self
  14. async def _make_client(path, timeout, script):
  15. state = {}
  16. error = False
  17. await asyncio.sleep(timeout)
  18. async with websockets.connect(path) as websocket:
  19. for kind, message in script.events:
  20. if kind == 'recv':
  21. A, B = message, await recv_json(websocket)
  22. B.pop('ts')
  23. state.update(message)
  24. if A != B:
  25. error = True
  26. print('-', A)
  27. print('+', B)
  28. print()
  29. elif kind == 'send':
  30. await send_json(websocket, **message)
  31. while 'users' in state:
  32. if min(state['users']) == state['username']:
  33. break
  34. message = await recv_json(websocket)
  35. message.pop('ts')
  36. error = True
  37. print('+', message)
  38. print()
  39. state.update(message)
  40. if error:
  41. print('error')
  42. exit()
  43. async def _test(*clients):
  44. try:
  45. gather = asyncio.gather(
  46. start_server('localhost', 8642, 'TestServer'),
  47. *clients,
  48. )
  49. server, *results = await asyncio.wait_for(gather, timeout=2)
  50. server.close()
  51. except asyncio.TimeoutError:
  52. return
  53. return results
  54. def test_happy_path():
  55. client = _make_client('ws://localhost:8642/A', 0.1, Script()
  56. + {'action': 'login', 'username': 'TestUser'}
  57. - {'kind': 'update', 'users': ['TestUser'], 'info': 'Welcome to /A', 'username': 'TestUser'}
  58. + {'action': 'post', 'text': 'Hello World!'}
  59. - {'kind': 'post', 'source': 'TestUser', 'text': 'Hello World!'}
  60. )
  61. return _test(client)
  62. def test_name_taken():
  63. client1 = _make_client('ws://localhost:8642/', 0.10, Script()
  64. + {'action': 'login', 'username': 'A'}
  65. - {'kind': 'update', 'users': ['A'], 'info': 'Welcome to /', 'username': 'A'}
  66. - {'kind': 'update', 'users': ['A', 'B'], 'info': 'B joined'}
  67. )
  68. client2 = _make_client('ws://localhost:8642/', 0.11, Script()
  69. + {'action': 'login', 'username': 'A'}
  70. - {'kind': 'error', 'info': 'Username taken'}
  71. )
  72. client3 = _make_client('ws://localhost:8642/', 0.12, Script()
  73. + {'action': 'login', 'username': 'B'}
  74. - {'kind': 'update', 'users': ['A', 'B'], 'info': 'Welcome to /', 'username': 'B'}
  75. - {'kind': 'update', 'users': ['B'], 'info': 'A left'}
  76. )
  77. return _test(client1, client2, client3)
  78. def test_interact():
  79. client1 = _make_client('ws://localhost:8642/', 0.10, Script()
  80. + {'action': 'login', 'username': 'Alice'}
  81. - {'kind': 'update', 'users': ['Alice'], 'info': 'Welcome to /', 'username': 'Alice'}
  82. - {'kind': 'update', 'users': ['Alice', 'Bob'], 'info': 'Bob joined'}
  83. + {'action': 'post', 'text': 'Hey Bob!'}
  84. - {'kind': 'post', 'source': 'Alice', 'text': 'Hey Bob!'}
  85. - {'kind': 'post', 'source': 'Bob', 'text': 'Howdy!'}
  86. )
  87. client2 = _make_client('ws://localhost:8642/', 0.11, Script()
  88. + {'action': 'login', 'username': 'Bob'}
  89. - {'kind': 'update', 'users': ['Alice', 'Bob'], 'info': 'Welcome to /', 'username': 'Bob'}
  90. - {'kind': 'post', 'source': 'Alice', 'text': 'Hey Bob!'}
  91. + {'action': 'post', 'text': 'Howdy!'}
  92. - {'kind': 'post', 'source': 'Bob', 'text': 'Howdy!'}
  93. + {'action': 'post', 'text': ''}
  94. - {'kind': 'update', 'users': ['Bob'], 'info': 'Alice left'}
  95. )
  96. return _test(client1, client2)
  97. def test_party():
  98. client1 = _make_client('ws://localhost:8642/', 0.10, Script()
  99. + {'action': 'login', 'username': 'Norman'}
  100. - {'kind': 'update', 'users': ['Norman'], 'info': 'Welcome to /', 'username': 'Norman'}
  101. - {'kind': 'update', 'users': ['Norman', 'Ray'], 'info': 'Ray joined'}
  102. - {'kind': 'update', 'users': ['Emma', 'Norman', 'Ray'], 'info': 'Emma joined'}
  103. + {'action': 'post', 'text': 'なに?'}
  104. - {'kind': 'post', 'source': 'Norman', 'text': 'なに?'}
  105. - {'kind': 'update', 'users': ['Norman', 'Ray'], 'info': 'Emma left'}
  106. )
  107. client2 = _make_client('ws://localhost:8642/', 0.11, Script()
  108. + {'action': 'login', 'username': 'Ray'}
  109. - {'kind': 'update', 'users': ['Norman', 'Ray'], 'info': 'Welcome to /', 'username': 'Ray'}
  110. - {'kind': 'update', 'users': ['Emma', 'Norman', 'Ray'], 'info': 'Emma joined'}
  111. - {'kind': 'post', 'source': 'Norman', 'text': 'なに?'}
  112. - {'kind': 'update', 'users': ['Norman', 'Ray'], 'info': 'Emma left'}
  113. - {'kind': 'update', 'users': ['Ray'], 'info': 'Norman left'}
  114. )
  115. client3 = _make_client('ws://localhost:8642/', 0.12, Script()
  116. + {'action': 'login', 'username': 'Emma'}
  117. - {'kind': 'update', 'users': ['Emma', 'Norman', 'Ray'], 'info': 'Welcome to /', 'username': 'Emma'}
  118. - {'kind': 'post', 'source': 'Norman', 'text': 'なに?'}
  119. )
  120. return _test(client1, client2, client3)
  121. def test_rooms():
  122. client1 = _make_client('ws://localhost:8642/A', 0.10, Script()
  123. + {'action': 'login', 'username': 'Dandy'}
  124. - {'kind': 'update', 'users': ['Dandy'], 'info': 'Welcome to /A', 'username': 'Dandy'}
  125. + {'action': 'post', 'text': 'Hi'}
  126. - {'kind': 'post', 'source': 'Dandy', 'text': 'Hi'}
  127. )
  128. client2 = _make_client('ws://localhost:8642/B', 0.10, Script()
  129. + {'action': 'login', 'username': 'Dandy'}
  130. - {'kind': 'update', 'users': ['Dandy'], 'info': 'Welcome to /B', 'username': 'Dandy'}
  131. + {'action': 'post', 'text': 'Howdy'}
  132. - {'kind': 'post', 'source': 'Dandy', 'text': 'Howdy'}
  133. )
  134. return _test(client1, client2)
  135. if __name__ == '__main__':
  136. loop = asyncio.get_event_loop()
  137. for fn_name, fn in list(locals().items()):
  138. if fn_name.startswith('test_'):
  139. loop.run_until_complete(fn())