test_failures.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. from openleadr import OpenADRClient, OpenADRServer
  2. from openleadr.utils import generate_id
  3. from openleadr import messaging, errors
  4. import pytest
  5. from aiohttp import web
  6. import os
  7. import logging
  8. import asyncio
  9. from datetime import timedelta
  10. from base64 import b64encode
  11. import re
  12. @pytest.mark.asyncio
  13. async def test_http_level_error(start_server):
  14. client = OpenADRClient(vtn_url="http://this.is.an.error", ven_name=VEN_NAME)
  15. client.on_event = _client_on_event
  16. await client.run()
  17. await client.client_session.close()
  18. @pytest.mark.asyncio
  19. async def test_xml_schema_error(start_server, caplog):
  20. message = messaging.create_message("oadrQueryRegistration", request_id='req1234')
  21. message = message.replace('<requestID xmlns="http://docs.oasis-open.org/ns/energyinterop/201110/payloads">req1234</requestID>', '')
  22. client = OpenADRClient(ven_name='myven', vtn_url=f'http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b')
  23. result = await client._perform_request('EiRegisterParty', message)
  24. assert result == (None, {})
  25. logs = [rec.message for rec in caplog.records]
  26. for log in logs:
  27. if log.startswith("Non-OK status 400"):
  28. assert "XML failed validation" in log
  29. break
  30. else:
  31. assert False
  32. @pytest.mark.asyncio
  33. async def test_wrong_endpoint(start_server, caplog):
  34. message = messaging.create_message("oadrQueryRegistration", request_id='req1234')
  35. client = OpenADRClient(ven_name='myven', vtn_url=f'http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b')
  36. response_type, response_payload = await client._perform_request('OadrPoll', message)
  37. assert response_type == 'oadrResponse'
  38. assert response_payload['response']['response_code'] == 459
  39. @pytest.mark.asyncio
  40. async def test_vtn_no_create_party_registration_handler(caplog):
  41. caplog.set_level(logging.WARNING)
  42. server = OpenADRServer(vtn_id='myvtn')
  43. client = OpenADRClient(ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b')
  44. await server.run_async()
  45. await client.run()
  46. await asyncio.sleep(0.5)
  47. await server.stop()
  48. await client.stop()
  49. assert len(caplog.messages) == 2
  50. assert 'No VEN ID received from the VTN, aborting.' in caplog.messages
  51. assert ("You should implement and register your own on_create_party_registration "
  52. "handler if you want VENs to be able to connect to you. This handler will "
  53. "receive a registration request and should return either 'False' (if the "
  54. "registration is denied) or a (ven_id, registration_id) tuple if the "
  55. "registration is accepted.") in caplog.messages
  56. @pytest.mark.asyncio
  57. async def test_invalid_signature_error(start_server_with_signatures, caplog):
  58. client = OpenADRClient(ven_name='myven',
  59. vtn_url=f'https://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b',
  60. cert=VEN_CERT,
  61. key=VEN_KEY,
  62. vtn_fingerprint='EE:44:C5:78:7E:4B:B8:DC:84:1F')
  63. message = client._create_message('oadrPoll', ven_id='ven123')
  64. fake_sig = b64encode("HelloThere".encode('utf-8')).decode('utf-8')
  65. message = re.sub(r'<ds:SignatureValue>.*?</ds:SignatureValue>', f'<ds:SignatureValue>{fake_sig}</ds:SignatureValue>', message)
  66. result = await client._perform_request('OadrPoll', message)
  67. assert result == (None, {})
  68. logs = [rec.message for rec in caplog.records]
  69. for log in logs:
  70. if log.startswith("Non-OK status 403 when performing a request"):
  71. assert "Invalid Signature" in log
  72. break
  73. else:
  74. assert False
  75. def problematic_handler(*args, **kwargs):
  76. raise Exception("BOOM")
  77. @pytest.mark.asyncio
  78. async def test_server_handler_exception(caplog):
  79. server = OpenADRServer(vtn_id=VTN_ID,
  80. http_port=SERVER_PORT)
  81. server.add_handler('on_create_party_registration', problematic_handler)
  82. await server.run_async()
  83. client = OpenADRClient(ven_name='myven',
  84. vtn_url=f'http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b')
  85. await client.run()
  86. await asyncio.sleep(0.5)
  87. await client.stop()
  88. await server.stop()
  89. for message in caplog.messages:
  90. if message.startswith('Non-OK status 500 when performing a request'):
  91. break
  92. else:
  93. assert False
  94. def protocol_error_handler(*args, **kwargs):
  95. raise errors.OutOfSequenceError()
  96. @pytest.mark.asyncio
  97. async def test_throw_protocol_error(caplog):
  98. server = OpenADRServer(vtn_id=VTN_ID,
  99. http_port=SERVER_PORT)
  100. server.add_handler('on_create_party_registration', protocol_error_handler)
  101. await server.run_async()
  102. client = OpenADRClient(ven_name='myven',
  103. vtn_url=f'http://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b')
  104. await client.run()
  105. await asyncio.sleep(0.5)
  106. await client.stop()
  107. await server.stop()
  108. assert 'We got a non-OK OpenADR response from the server: 450: OUT OF SEQUENCE' in caplog.messages
  109. @pytest.mark.asyncio
  110. async def test_invalid_signature_error(start_server_with_signatures, caplog):
  111. client = OpenADRClient(ven_name='myven',
  112. vtn_url=f'https://localhost:{SERVER_PORT}/OpenADR2/Simple/2.0b',
  113. cert=VEN_CERT,
  114. key=VEN_KEY,
  115. vtn_fingerprint='EE:44:C5:78:7E:4B:B8:DC:84:1F')
  116. message = client._create_message('oadrPoll', ven_id='ven123')
  117. fake_sig = b64encode("HelloThere".encode('utf-8')).decode('utf-8')
  118. message = re.sub(r'<ds:SignatureValue>.*?</ds:SignatureValue>', f'<ds:SignatureValue>{fake_sig}</ds:SignatureValue>', message)
  119. result = await client._perform_request('OadrPoll', message)
  120. assert result == (None, {})
  121. logs = [rec.message for rec in caplog.records]
  122. for log in logs:
  123. if log.startswith("Non-OK status 403 when performing a request"):
  124. assert "Invalid Signature" in log
  125. break
  126. else:
  127. assert False
  128. ##########################################################################################
  129. SERVER_PORT = 8001
  130. VEN_NAME = 'myven'
  131. VEN_ID = '1234abcd'
  132. VTN_ID = "TestVTN"
  133. VEN_CERT = os.path.join(os.path.dirname(os.path.dirname(__file__)), "certificates", "dummy_ven.crt")
  134. VEN_KEY = os.path.join(os.path.dirname(os.path.dirname(__file__)), "certificates", "dummy_ven.key")
  135. VTN_CERT = os.path.join(os.path.dirname(os.path.dirname(__file__)), "certificates", "dummy_vtn.crt")
  136. VTN_KEY = os.path.join(os.path.dirname(os.path.dirname(__file__)), "certificates", "dummy_vtn.key")
  137. CA_FILE = os.path.join(os.path.dirname(os.path.dirname(__file__)), "certificates", "dummy_ca.crt")
  138. async def _on_create_party_registration(payload):
  139. registration_id = generate_id()
  140. payload = {'response': {'response_code': 200,
  141. 'response_description': 'OK',
  142. 'request_id': payload['request_id']},
  143. 'ven_id': VEN_ID,
  144. 'registration_id': registration_id,
  145. 'profiles': [{'profile_name': '2.0b',
  146. 'transports': {'transport_name': 'simpleHttp'}}],
  147. 'requested_oadr_poll_freq': timedelta(seconds=1)}
  148. return 'oadrCreatedPartyRegistration', payload
  149. async def _client_on_event(event):
  150. pass
  151. async def _client_on_report(report):
  152. pass
  153. def fingerprint_lookup(ven_id):
  154. return "6B:C8:4E:47:15:AA:30:EB:CE:0E"
  155. @pytest.fixture
  156. async def start_server():
  157. server = OpenADRServer(vtn_id=VTN_ID, http_port=SERVER_PORT)
  158. server.add_handler('on_create_party_registration', _on_create_party_registration)
  159. await server.run_async()
  160. yield
  161. await server.stop()
  162. @pytest.fixture
  163. async def start_server_with_signatures():
  164. server = OpenADRServer(vtn_id=VTN_ID,
  165. cert=VTN_CERT,
  166. key=VTN_KEY,
  167. http_cert=VTN_CERT,
  168. http_key=VTN_KEY,
  169. http_ca_file=CA_FILE,
  170. http_port=SERVER_PORT,
  171. fingerprint_lookup=fingerprint_lookup)
  172. server.add_handler('on_create_party_registration', _on_create_party_registration)
  173. await server.run_async()
  174. yield
  175. await server.stop()