pytest_mqtt_ssl.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. # SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
  2. # SPDX-License-Identifier: Unlicense OR CC0-1.0
  3. import logging
  4. import os
  5. import re
  6. import ssl
  7. import sys
  8. from threading import Event, Thread
  9. import paho.mqtt.client as mqtt
  10. import pexpect
  11. import pytest
  12. from pytest_embedded import Dut
  13. event_client_connected = Event()
  14. event_stop_client = Event()
  15. event_client_received_correct = Event()
  16. event_client_received_binary = Event()
  17. message_log = ''
  18. # The callback for when the client receives a CONNACK response from the server.
  19. def on_connect(client, userdata, flags, rc): # type: (mqtt.Client, str, bool, str) -> None
  20. _ = (userdata, flags)
  21. print('Connected with result code ' + str(rc))
  22. event_client_connected.set()
  23. client.subscribe('/topic/qos0')
  24. def mqtt_client_task(client): # type: (mqtt.Client) -> None
  25. while not event_stop_client.is_set():
  26. client.loop()
  27. # The callback for when a PUBLISH message is received from the server.
  28. def on_message(client, userdata, msg): # type: (mqtt.Client, tuple, mqtt.client.MQTTMessage) -> None
  29. global message_log
  30. global event_client_received_correct
  31. global event_client_received_binary
  32. if msg.topic == '/topic/binary':
  33. binary, bin_size = userdata
  34. print('Receiving binary from esp and comparing with {}, size {}...'.format(binary, bin_size))
  35. with open(binary, 'rb') as f:
  36. bin = f.read()
  37. if bin[:bin_size] == msg.payload[:bin_size]:
  38. print('...matches!')
  39. event_client_received_binary.set()
  40. return
  41. recv_binary = binary + '.received'
  42. with open(recv_binary, 'w') as fw:
  43. fw.write(msg.payload)
  44. raise ValueError('Received binary (saved as: {}) does not match the original file: {}'.format(recv_binary, binary))
  45. payload = msg.payload.decode()
  46. if not event_client_received_correct.is_set() and payload == 'data':
  47. client.subscribe('/topic/binary')
  48. client.publish('/topic/qos0', 'send binary please')
  49. if msg.topic == '/topic/qos0' and payload == 'data':
  50. event_client_received_correct.set()
  51. message_log += 'Received data:' + msg.topic + ' ' + payload + '\n'
  52. @pytest.mark.esp32
  53. @pytest.mark.ethernet
  54. def test_examples_protocol_mqtt_ssl(dut): # type: (Dut) -> None
  55. broker_url = ''
  56. broker_port = 0
  57. """
  58. steps:
  59. 1. join AP and connects to ssl broker
  60. 2. Test connects a client to the same broker
  61. 3. Test evaluates python client received correct qos0 message
  62. 4. Test ESP32 client received correct qos0 message
  63. 5. Test python client receives binary data from running partition and compares it with the binary
  64. """
  65. binary_file = os.path.join(dut.app.binary_path, 'mqtt_ssl.bin')
  66. bin_size = os.path.getsize(binary_file)
  67. logging.info('[Performance][mqtt_ssl_bin_size]: %s KB', bin_size // 1024)
  68. # Look for host:port in sdkconfig
  69. try:
  70. value = re.search(r'\:\/\/([^:]+)\:([0-9]+)', dut.app.sdkconfig.get('BROKER_URI'))
  71. assert value is not None
  72. broker_url = value.group(1)
  73. broker_port = int(value.group(2))
  74. bin_size = min(int(dut.app.sdkconfig.get('BROKER_BIN_SIZE_TO_SEND')), bin_size)
  75. except Exception:
  76. print('ENV_TEST_FAILURE: Cannot find broker url in sdkconfig')
  77. raise
  78. client = None
  79. # 1. Test connects to a broker
  80. try:
  81. client = mqtt.Client()
  82. client.on_connect = on_connect
  83. client.on_message = on_message
  84. client.user_data_set((binary_file, bin_size))
  85. client.tls_set(None,
  86. None,
  87. None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)
  88. client.tls_insecure_set(True)
  89. print('Connecting...')
  90. client.connect(broker_url, broker_port, 60)
  91. except Exception:
  92. print('ENV_TEST_FAILURE: Unexpected error while connecting to broker {}: {}:'.format(broker_url, sys.exc_info()[0]))
  93. raise
  94. # Starting a py-client in a separate thread
  95. thread1 = Thread(target=mqtt_client_task, args=(client,))
  96. thread1.start()
  97. try:
  98. print('Connecting py-client to broker {}:{}...'.format(broker_url, broker_port))
  99. if not event_client_connected.wait(timeout=30):
  100. raise ValueError('ENV_TEST_FAILURE: Test script cannot connect to broker: {}'.format(broker_url))
  101. try:
  102. ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[0]
  103. print('Connected to AP with IP: {}'.format(ip_address))
  104. except pexpect.TIMEOUT:
  105. print('ENV_TEST_FAILURE: Cannot connect to AP')
  106. raise
  107. print('Checking py-client received msg published from esp...')
  108. if not event_client_received_correct.wait(timeout=30):
  109. raise ValueError('Wrong data received, msg log: {}'.format(message_log))
  110. print('Checking esp-client received msg published from py-client...')
  111. dut.expect(r'DATA=send binary please', timeout=30)
  112. print('Receiving binary data from running partition...')
  113. if not event_client_received_binary.wait(timeout=30):
  114. raise ValueError('Binary not received within timeout')
  115. finally:
  116. event_stop_client.set()
  117. thread1.join()