pytest_http_server_simple.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #!/usr/bin/env python
  2. #
  3. # SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD
  4. # SPDX-License-Identifier: Apache-2.0
  5. from __future__ import division, print_function, unicode_literals
  6. import logging
  7. import os
  8. import random
  9. import socket
  10. import string
  11. import sys
  12. import threading
  13. import time
  14. from builtins import range
  15. import pytest
  16. try:
  17. from idf_http_server_test import client
  18. except ModuleNotFoundError:
  19. sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'tools', 'ci', 'python_packages'))
  20. from idf_http_server_test import client
  21. from common_test_methods import get_env_config_variable
  22. from pytest_embedded import Dut
  23. class http_client_thread(threading.Thread):
  24. def __init__(self, ip: str, port: int, delay: int) -> None:
  25. threading.Thread.__init__(self)
  26. self.ip = ip
  27. self.port = port
  28. self.delay = delay
  29. self.exc = 0
  30. # Thread function used to open a socket and wait for specific amount of time before returning
  31. def open_connection(self, ip: str, port: int, delay: int) -> None:
  32. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  33. s.settimeout(delay)
  34. s.connect((ip, port))
  35. time.sleep(delay)
  36. def run(self) -> None:
  37. try:
  38. self.open_connection(self.ip, self.port, self.delay)
  39. except socket.timeout:
  40. self.exc = 1
  41. def join(self, timeout=None): # type: ignore
  42. threading.Thread.join(self)
  43. if self.exc:
  44. raise socket.timeout
  45. # When running on local machine execute the following before running this script
  46. # > make app bootloader
  47. # > make print_flash_cmd | tail -n 1 > build/download.config
  48. @pytest.mark.esp32
  49. @pytest.mark.esp32c3
  50. @pytest.mark.esp32s2
  51. @pytest.mark.esp32s3
  52. @pytest.mark.wifi_router
  53. def test_examples_protocol_http_server_simple(dut: Dut) -> None:
  54. # Get binary file
  55. binary_file = os.path.join(dut.app.binary_path, 'simple.bin')
  56. bin_size = os.path.getsize(binary_file)
  57. logging.info('http_server_bin_size : {}KB'.format(bin_size // 1024))
  58. # Upload binary and start testing
  59. logging.info('Starting http_server simple test app')
  60. # Parse IP address of STA
  61. logging.info('Waiting to connect with AP')
  62. if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
  63. dut.expect('Please input ssid password:')
  64. env_name = 'wifi_router'
  65. ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
  66. ap_password = get_env_config_variable(env_name, 'ap_password')
  67. dut.write(' '.join([ap_ssid, ap_password]))
  68. got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
  69. got_port = dut.expect(r"(?:[\s\S]*)Starting server on port: '(\d+)'", timeout=30)[1].decode()
  70. logging.info('Got IP : {}'.format(got_ip))
  71. logging.info('Got Port : {}'.format(got_port))
  72. # Expected Logs
  73. dut.expect('Registering URI handlers', timeout=30)
  74. # Run test script
  75. # If failed raise appropriate exception
  76. logging.info('Test /hello GET handler')
  77. if not client.test_get_handler(got_ip, str(got_port)):
  78. raise RuntimeError
  79. # Acquire host IP. Need a way to check it
  80. dut.expect(r'(?:[\s\S]*)Found header => Host: (\d+.\d+.\d+.\d+)', timeout=30)
  81. # Match additional headers sent in the request
  82. dut.expect('Found header => Test-Header-2: Test-Value-2', timeout=30)
  83. dut.expect('Found header => Test-Header-1: Test-Value-1', timeout=30)
  84. dut.expect('Found URL query parameter => query1=value1', timeout=30)
  85. dut.expect('Found URL query parameter => query3=value3', timeout=30)
  86. dut.expect('Found URL query parameter => query2=value2', timeout=30)
  87. dut.expect('Request headers lost', timeout=30)
  88. logging.info('Test /ctrl PUT handler and realtime handler de/registration')
  89. if not client.test_put_handler(got_ip, got_port):
  90. raise RuntimeError
  91. dut.expect('Unregistering /hello and /echo URIs', timeout=30)
  92. dut.expect('Registering /hello and /echo URIs', timeout=30)
  93. # Generate random data of 10KB
  94. random_data = ''.join(string.printable[random.randint(0,len(string.printable)) - 1] for _ in range(10 * 1024))
  95. logging.info('Test /echo POST handler with random data')
  96. if not client.test_post_handler(got_ip, got_port, random_data):
  97. raise RuntimeError
  98. query = 'http://foobar'
  99. logging.info('Test /hello with custom query : {}'.format(query))
  100. if not client.test_custom_uri_query(got_ip, got_port, query):
  101. raise RuntimeError
  102. dut.expect('Found URL query => ' + query, timeout=30)
  103. query = 'abcd+1234%20xyz'
  104. logging.info('Test /hello with custom query : {}'.format(query))
  105. if not client.test_custom_uri_query(got_ip, got_port, query):
  106. raise RuntimeError
  107. dut.expect_exact('Found URL query => ' + query, timeout=30)
  108. @pytest.mark.esp32
  109. @pytest.mark.esp32c3
  110. @pytest.mark.esp32s2
  111. @pytest.mark.esp32s3
  112. @pytest.mark.wifi_router
  113. def test_examples_protocol_http_server_lru_purge_enable(dut: Dut) -> None:
  114. # Get binary file
  115. binary_file = os.path.join(dut.app.binary_path, 'simple.bin')
  116. bin_size = os.path.getsize(binary_file)
  117. logging.info('http_server_bin_size : {}KB'.format(bin_size // 1024))
  118. # Upload binary and start testing
  119. logging.info('Starting http_server simple test app')
  120. # Parse IP address of STA
  121. logging.info('Waiting to connect with AP')
  122. if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
  123. dut.expect('Please input ssid password:')
  124. env_name = 'wifi_router'
  125. ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
  126. ap_password = get_env_config_variable(env_name, 'ap_password')
  127. dut.write(f'{ap_ssid} {ap_password}')
  128. got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
  129. got_port = dut.expect(r"(?:[\s\S]*)Starting server on port: '(\d+)'", timeout=30)[1].decode()
  130. logging.info('Got IP : {}'.format(got_ip))
  131. logging.info('Got Port : {}'.format(got_port))
  132. # Expected Logs
  133. dut.expect('Registering URI handlers', timeout=30)
  134. threads = []
  135. # Open 20 sockets, one from each thread
  136. for _ in range(20):
  137. try:
  138. thread = http_client_thread(got_ip, (int(got_port)), 20)
  139. thread.start()
  140. threads.append(thread)
  141. except OSError as err:
  142. logging.info('Error: unable to start thread, {}'.format(err))
  143. for t in threads:
  144. t.join()