example_test.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. import re
  2. import os
  3. import socket
  4. import BaseHTTPServer
  5. import SimpleHTTPServer
  6. from threading import Thread
  7. import ssl
  8. from tiny_test_fw import DUT
  9. import ttfw_idf
  10. import random
  11. import subprocess
  12. server_cert = "-----BEGIN CERTIFICATE-----\n" \
  13. "MIIDXTCCAkWgAwIBAgIJAP4LF7E72HakMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV\n"\
  14. "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n"\
  15. "aWRnaXRzIFB0eSBMdGQwHhcNMTkwNjA3MDk1OTE2WhcNMjAwNjA2MDk1OTE2WjBF\n"\
  16. "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n"\
  17. "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"\
  18. "CgKCAQEAlzfCyv3mIv7TlLkObxunKfCdrJ/zgdANrsx0RBtpEPhV560hWJ0fEin0\n"\
  19. "nIOMpJSiF9E6QsPdr6Q+eogH4XnOMU9JE+iG743N1dPfGEzJvRlyct/Ck8SswKPC\n"\
  20. "9+VXsnOdZmUw9y/xtANbURA/TspvPzz3Avv382ffffrJGh7ooOmaZSCZFlSYHLZA\n"\
  21. "w/XlRr0sSRbLpFGY0gXjaAV8iHHiPDYLy4kZOepjV9U51xi+IGsL4w75zuMgsHyF\n"\
  22. "3nJeGYHgtGVBrkL0ZKG5udY0wcBjysjubDJC4iSlNiq2HD3fhs7j6CZddV2v845M\n"\
  23. "lVKNxP0kO4Uj4D8r+5USWC8JKfAwxQIDAQABo1AwTjAdBgNVHQ4EFgQU6OE7ssfY\n"\
  24. "IIPTDThiUoofUpsD5NwwHwYDVR0jBBgwFoAU6OE7ssfYIIPTDThiUoofUpsD5Nww\n"\
  25. "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAXIlHS/FJWfmcinUAxyBd\n"\
  26. "/xd5Lu8ykeru6oaUCci+Vk9lyoMMES7lQ+b/00d5x7AcTawkTil9EWpBTPTOTraA\n"\
  27. "lzJMQhNKmSLk0iIoTtAJtSZgUSpIIozqK6lenxQQDsHbXKU6h+u9H6KZE8YcjsFl\n"\
  28. "6vL7sw9BVotw/VxfgjQ5OSGLgoLrdVT0z5C2qOuwOgz1c7jNiJhtMdwN+cOtnJp2\n"\
  29. "fuBgEYyE3eeuWogvkWoDcIA8r17Ixzkpq2oJsdvZcHZPIZShPKW2SHUsl98KDemu\n"\
  30. "y0pQyExmQUbwKE4vbFb9XuWCcL9XaOHQytyszt2DeD67AipvoBwVU7/LBOvqnsmy\n"\
  31. "hA==\n"\
  32. "-----END CERTIFICATE-----\n"
  33. server_key = "-----BEGIN PRIVATE KEY-----\n"\
  34. "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCXN8LK/eYi/tOU\n"\
  35. "uQ5vG6cp8J2sn/OB0A2uzHREG2kQ+FXnrSFYnR8SKfScg4yklKIX0TpCw92vpD56\n"\
  36. "iAfhec4xT0kT6Ibvjc3V098YTMm9GXJy38KTxKzAo8L35Veyc51mZTD3L/G0A1tR\n"\
  37. "ED9Oym8/PPcC+/fzZ999+skaHuig6ZplIJkWVJgctkDD9eVGvSxJFsukUZjSBeNo\n"\
  38. "BXyIceI8NgvLiRk56mNX1TnXGL4gawvjDvnO4yCwfIXecl4ZgeC0ZUGuQvRkobm5\n"\
  39. "1jTBwGPKyO5sMkLiJKU2KrYcPd+GzuPoJl11Xa/zjkyVUo3E/SQ7hSPgPyv7lRJY\n"\
  40. "Lwkp8DDFAgMBAAECggEAfBhAfQE7mUByNbxgAgI5fot9eaqR1Nf+QpJ6X2H3KPwC\n"\
  41. "02sa0HOwieFwYfj6tB1doBoNq7i89mTc+QUlIn4pHgIowHO0OGawomeKz5BEhjCZ\n"\
  42. "4XeLYGSoODary2+kNkf2xY8JTfFEcyvGBpJEwc4S2VyYgRRx+IgnumTSH+N5mIKZ\n"\
  43. "SXWNdZIuHEmkwod+rPRXs6/r+PH0eVW6WfpINEbr4zVAGXJx2zXQwd2cuV1GTJWh\n"\
  44. "cPVOXLu+XJ9im9B370cYN6GqUnR3fui13urYbnWnEf3syvoH/zuZkyrVChauoFf8\n"\
  45. "8EGb74/HhXK7Q2s8NRakx2c7OxQifCbcy03liUMmyQKBgQDFAob5B/66N4Q2cq/N\n"\
  46. "MWPf98kYBYoLaeEOhEJhLQlKk0pIFCTmtpmUbpoEes2kCUbH7RwczpYko8tlKyoB\n"\
  47. "6Fn6RY4zQQ64KZJI6kQVsjkYpcP/ihnOY6rbds+3yyv+4uPX7Eh9sYZwZMggE19M\n"\
  48. "CkFHkwAjiwqhiiSlUxe20sWmowKBgQDEfx4lxuFzA1PBPeZKGVBTxYPQf+DSLCre\n"\
  49. "ZFg3ZmrxbCjRq1O7Lra4FXWD3dmRq7NDk79JofoW50yD8wD7I0B7opdDfXD2idO8\n"\
  50. "0dBnWUKDr2CAXyoLEINce9kJPbx4kFBQRN9PiGF7VkDQxeQ3kfS8CvcErpTKCOdy\n"\
  51. "5wOwBTwJdwKBgDiTFTeGeDv5nVoVbS67tDao7XKchJvqd9q3WGiXikeELJyuTDqE\n"\
  52. "zW22pTwMF+m3UEAxcxVCrhMvhkUzNAkANHaOatuFHzj7lyqhO5QPbh4J3FMR0X9X\n"\
  53. "V8VWRSg+jA/SECP9koOl6zlzd5Tee0tW1pA7QpryXscs6IEhb3ns5R2JAoGAIkzO\n"\
  54. "RmnhEOKTzDex611f2D+yMsMfy5BKK2f4vjLymBH5TiBKDXKqEpgsW0huoi8Gq9Uu\n"\
  55. "nvvXXAgkIyRYF36f0vUe0nkjLuYAQAWgC2pZYgNLJR13iVbol0xHJoXQUHtgiaJ8\n"\
  56. "GLYFzjHQPqFMpSalQe3oELko39uOC1CoJCHFySECgYBeycUnRBikCO2n8DNhY4Eg\n"\
  57. "9Y3oxcssRt6ea5BZwgW2eAYi7/XqKkmxoSoOykUt3MJx9+EkkrL17bxFSpkj1tvL\n"\
  58. "qvxn7egtsKjjgGNAxwXC4MwCvhveyUQQxtQb8AqGrGqo4jEEN0L15cnP38i2x1Uo\n"\
  59. "muhfskWf4MABV0yTUaKcGg==\n"\
  60. "-----END PRIVATE KEY-----\n"
  61. def get_my_ip():
  62. s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  63. s1.connect(("8.8.8.8", 80))
  64. my_ip = s1.getsockname()[0]
  65. s1.close()
  66. return my_ip
  67. def get_server_status(host_ip, port):
  68. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  69. server_status = sock.connect_ex((host_ip, port))
  70. sock.close()
  71. if server_status == 0:
  72. return True
  73. return False
  74. def create_file(server_file, file_data):
  75. with open(server_file, "w+") as file:
  76. file.write(file_data)
  77. def get_ca_cert(ota_image_dir):
  78. os.chdir(ota_image_dir)
  79. server_file = os.path.join(ota_image_dir, "server_cert.pem")
  80. create_file(server_file, server_cert)
  81. key_file = os.path.join(ota_image_dir, "server_key.pem")
  82. create_file(key_file, server_key)
  83. return server_file, key_file
  84. def start_https_server(ota_image_dir, server_ip, server_port):
  85. server_file, key_file = get_ca_cert(ota_image_dir)
  86. httpd = BaseHTTPServer.HTTPServer((server_ip, server_port),
  87. SimpleHTTPServer.SimpleHTTPRequestHandler)
  88. httpd.socket = ssl.wrap_socket(httpd.socket,
  89. keyfile=key_file,
  90. certfile=server_file, server_side=True)
  91. httpd.serve_forever()
  92. def start_chunked_server(ota_image_dir, server_port):
  93. server_file, key_file = get_ca_cert(ota_image_dir)
  94. chunked_server = subprocess.Popen(["openssl", "s_server", "-WWW", "-key", key_file, "-cert", server_file, "-port", str(server_port)])
  95. return chunked_server
  96. def redirect_handler_factory(url):
  97. """
  98. Returns a request handler class that redirects to supplied `url`
  99. """
  100. class RedirectHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
  101. def do_GET(self):
  102. print("Sending resp, URL: " + url)
  103. self.send_response(301)
  104. self.send_header('Location', url)
  105. self.end_headers()
  106. return RedirectHandler
  107. def start_redirect_server(ota_image_dir, server_ip, server_port, redirection_port):
  108. os.chdir(ota_image_dir)
  109. server_file, key_file = get_ca_cert(ota_image_dir)
  110. redirectHandler = redirect_handler_factory("https://" + server_ip + ":" + str(redirection_port) + "/advanced_https_ota.bin")
  111. httpd = BaseHTTPServer.HTTPServer((server_ip, server_port),
  112. redirectHandler)
  113. httpd.socket = ssl.wrap_socket(httpd.socket,
  114. keyfile=key_file,
  115. certfile=server_file, server_side=True)
  116. httpd.serve_forever()
  117. @ttfw_idf.idf_example_test(env_tag="Example_WIFI")
  118. def test_examples_protocol_advanced_https_ota_example(env, extra_data):
  119. """
  120. This is a positive test case, which downloads complete binary file multiple number of times.
  121. Number of iterations can be specified in variable iterations.
  122. steps: |
  123. 1. join AP
  124. 2. Fetch OTA image over HTTPS
  125. 3. Reboot with the new OTA image
  126. """
  127. dut1 = env.get_dut("advanced_https_ota_example", "examples/system/ota/advanced_https_ota", dut_class=ttfw_idf.ESP32DUT)
  128. # Number of iterations to validate OTA
  129. iterations = 3
  130. server_port = 8001
  131. # File to be downloaded. This file is generated after compilation
  132. bin_name = "advanced_https_ota.bin"
  133. # check and log bin size
  134. binary_file = os.path.join(dut1.app.binary_path, bin_name)
  135. bin_size = os.path.getsize(binary_file)
  136. ttfw_idf.log_performance("advanced_https_ota_bin_size", "{}KB".format(bin_size // 1024))
  137. ttfw_idf.check_performance("advanced_https_ota_bin_size", bin_size // 1024)
  138. # start test
  139. host_ip = get_my_ip()
  140. if (get_server_status(host_ip, server_port) is False):
  141. thread1 = Thread(target=start_https_server, args=(dut1.app.binary_path, host_ip, server_port))
  142. thread1.daemon = True
  143. thread1.start()
  144. dut1.start_app()
  145. for i in range(iterations):
  146. dut1.expect("Loaded app from partition at offset", timeout=30)
  147. try:
  148. ip_address = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)
  149. print("Connected to AP with IP: {}".format(ip_address))
  150. except DUT.ExpectTimeout:
  151. raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
  152. thread1.close()
  153. dut1.expect("Starting Advanced OTA example", timeout=30)
  154. print("writing to device: {}".format("https://" + host_ip + ":" + str(server_port) + "/" + bin_name))
  155. dut1.write("https://" + host_ip + ":" + str(server_port) + "/" + bin_name)
  156. dut1.expect("Loaded app from partition at offset", timeout=60)
  157. dut1.expect("Starting Advanced OTA example", timeout=30)
  158. dut1.reset()
  159. @ttfw_idf.idf_example_test(env_tag="Example_WIFI")
  160. def test_examples_protocol_advanced_https_ota_example_truncated_bin(env, extra_data):
  161. """
  162. Working of OTA if binary file is truncated is validated in this test case.
  163. Application should return with error message in this case.
  164. steps: |
  165. 1. join AP
  166. 2. Generate truncated binary file
  167. 3. Fetch OTA image over HTTPS
  168. 4. Check working of code if bin is truncated
  169. """
  170. dut1 = env.get_dut("advanced_https_ota_example", "examples/system/ota/advanced_https_ota", dut_class=ttfw_idf.ESP32DUT)
  171. server_port = 8001
  172. # Original binary file generated after compilation
  173. bin_name = "advanced_https_ota.bin"
  174. # Truncated binary file to be generated from original binary file
  175. truncated_bin_name = "truncated.bin"
  176. # Size of truncated file to be grnerated. This value can range from 288 bytes (Image header size) to size of original binary file
  177. # truncated_bin_size is set to 64000 to reduce consumed by the test case
  178. truncated_bin_size = 64000
  179. # check and log bin size
  180. binary_file = os.path.join(dut1.app.binary_path, bin_name)
  181. f = open(binary_file, "r+")
  182. fo = open(os.path.join(dut1.app.binary_path, truncated_bin_name), "w+")
  183. fo.write(f.read(truncated_bin_size))
  184. fo.close()
  185. f.close()
  186. binary_file = os.path.join(dut1.app.binary_path, truncated_bin_name)
  187. bin_size = os.path.getsize(binary_file)
  188. ttfw_idf.log_performance("advanced_https_ota_bin_size", "{}KB".format(bin_size // 1024))
  189. ttfw_idf.check_performance("advanced_https_ota_bin_size", bin_size // 1024)
  190. # start test
  191. host_ip = get_my_ip()
  192. if (get_server_status(host_ip, server_port) is False):
  193. thread1 = Thread(target=start_https_server, args=(dut1.app.binary_path, host_ip, server_port))
  194. thread1.daemon = True
  195. thread1.start()
  196. dut1.start_app()
  197. dut1.expect("Loaded app from partition at offset", timeout=30)
  198. try:
  199. ip_address = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)
  200. print("Connected to AP with IP: {}".format(ip_address))
  201. except DUT.ExpectTimeout:
  202. raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
  203. dut1.expect("Starting Advanced OTA example", timeout=30)
  204. print("writing to device: {}".format("https://" + host_ip + ":" + str(server_port) + "/" + truncated_bin_name))
  205. dut1.write("https://" + host_ip + ":" + str(server_port) + "/" + truncated_bin_name)
  206. dut1.expect("Image validation failed, image is corrupted", timeout=30)
  207. os.remove(binary_file)
  208. @ttfw_idf.idf_example_test(env_tag="Example_WIFI")
  209. def test_examples_protocol_advanced_https_ota_example_truncated_header(env, extra_data):
  210. """
  211. Working of OTA if headers of binary file are truncated is vaildated in this test case.
  212. Application should return with error message in this case.
  213. steps: |
  214. 1. join AP
  215. 2. Generate binary file with truncated headers
  216. 3. Fetch OTA image over HTTPS
  217. 4. Check working of code if headers are not sent completely
  218. """
  219. dut1 = env.get_dut("advanced_https_ota_example", "examples/system/ota/advanced_https_ota", dut_class=ttfw_idf.ESP32DUT)
  220. server_port = 8001
  221. # Original binary file generated after compilation
  222. bin_name = "advanced_https_ota.bin"
  223. # Truncated binary file to be generated from original binary file
  224. truncated_bin_name = "truncated_header.bin"
  225. # Size of truncated file to be grnerated. This value should be less than 288 bytes (Image header size)
  226. truncated_bin_size = 180
  227. # check and log bin size
  228. binary_file = os.path.join(dut1.app.binary_path, bin_name)
  229. f = open(binary_file, "r+")
  230. fo = open(os.path.join(dut1.app.binary_path, truncated_bin_name), "w+")
  231. fo.write(f.read(truncated_bin_size))
  232. fo.close()
  233. f.close()
  234. binary_file = os.path.join(dut1.app.binary_path, truncated_bin_name)
  235. bin_size = os.path.getsize(binary_file)
  236. ttfw_idf.log_performance("advanced_https_ota_bin_size", "{}KB".format(bin_size // 1024))
  237. ttfw_idf.check_performance("advanced_https_ota_bin_size", bin_size // 1024)
  238. # start test
  239. host_ip = get_my_ip()
  240. if (get_server_status(host_ip, server_port) is False):
  241. thread1 = Thread(target=start_https_server, args=(dut1.app.binary_path, host_ip, server_port))
  242. thread1.daemon = True
  243. thread1.start()
  244. dut1.start_app()
  245. dut1.expect("Loaded app from partition at offset", timeout=30)
  246. try:
  247. ip_address = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)
  248. print("Connected to AP with IP: {}".format(ip_address))
  249. except DUT.ExpectTimeout:
  250. raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
  251. dut1.expect("Starting Advanced OTA example", timeout=30)
  252. print("writing to device: {}".format("https://" + host_ip + ":" + str(server_port) + "/" + truncated_bin_name))
  253. dut1.write("https://" + host_ip + ":" + str(server_port) + "/" + truncated_bin_name)
  254. dut1.expect("advanced_https_ota_example: esp_https_ota_read_img_desc failed", timeout=30)
  255. os.remove(binary_file)
  256. @ttfw_idf.idf_example_test(env_tag="Example_WIFI")
  257. def test_examples_protocol_advanced_https_ota_example_random(env, extra_data):
  258. """
  259. Working of OTA if random data is added in binary file are validated in this test case.
  260. Magic byte verification should fail in this case.
  261. steps: |
  262. 1. join AP
  263. 2. Generate random binary image
  264. 3. Fetch OTA image over HTTPS
  265. 4. Check working of code for random binary file
  266. """
  267. dut1 = env.get_dut("advanced_https_ota_example", "examples/system/ota/advanced_https_ota", dut_class=ttfw_idf.ESP32DUT)
  268. server_port = 8001
  269. # Random binary file to be generated
  270. random_bin_name = "random.bin"
  271. # Size of random binary file. 32000 is choosen, to reduce the time required to run the test-case
  272. random_bin_size = 32000
  273. # check and log bin size
  274. binary_file = os.path.join(dut1.app.binary_path, random_bin_name)
  275. fo = open(binary_file, "w+")
  276. # First byte of binary file is always set to zero. If first byte is generated randomly,
  277. # in some cases it may generate 0xE9 which will result in failure of testcase.
  278. fo.write(str(0))
  279. for i in range(random_bin_size - 1):
  280. fo.write(str(random.randrange(0,255,1)))
  281. fo.close()
  282. bin_size = os.path.getsize(binary_file)
  283. ttfw_idf.log_performance("advanced_https_ota_bin_size", "{}KB".format(bin_size // 1024))
  284. ttfw_idf.check_performance("advanced_https_ota_bin_size", bin_size // 1024)
  285. # start test
  286. host_ip = get_my_ip()
  287. if (get_server_status(host_ip, server_port) is False):
  288. thread1 = Thread(target=start_https_server, args=(dut1.app.binary_path, host_ip, server_port))
  289. thread1.daemon = True
  290. thread1.start()
  291. dut1.start_app()
  292. dut1.expect("Loaded app from partition at offset", timeout=30)
  293. try:
  294. ip_address = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)
  295. print("Connected to AP with IP: {}".format(ip_address))
  296. except DUT.ExpectTimeout:
  297. raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
  298. dut1.expect("Starting Advanced OTA example", timeout=30)
  299. print("writing to device: {}".format("https://" + host_ip + ":" + str(server_port) + "/" + random_bin_name))
  300. dut1.write("https://" + host_ip + ":" + str(server_port) + "/" + random_bin_name)
  301. dut1.expect("esp_ota_ops: OTA image has invalid magic byte", timeout=10)
  302. os.remove(binary_file)
  303. @ttfw_idf.idf_example_test(env_tag="Example_WIFI")
  304. def test_examples_protocol_advanced_https_ota_example_chunked(env, extra_data):
  305. """
  306. This is a positive test case, which downloads complete binary file multiple number of times.
  307. Number of iterations can be specified in variable iterations.
  308. steps: |
  309. 1. join AP
  310. 2. Fetch OTA image over HTTPS
  311. 3. Reboot with the new OTA image
  312. """
  313. dut1 = env.get_dut("advanced_https_ota_example", "examples/system/ota/advanced_https_ota", dut_class=ttfw_idf.ESP32DUT)
  314. # File to be downloaded. This file is generated after compilation
  315. bin_name = "advanced_https_ota.bin"
  316. # check and log bin size
  317. binary_file = os.path.join(dut1.app.binary_path, bin_name)
  318. bin_size = os.path.getsize(binary_file)
  319. ttfw_idf.log_performance("advanced_https_ota_bin_size", "{}KB".format(bin_size // 1024))
  320. ttfw_idf.check_performance("advanced_https_ota_bin_size", bin_size // 1024)
  321. # start test
  322. host_ip = get_my_ip()
  323. chunked_server = start_chunked_server(dut1.app.binary_path, 8070)
  324. dut1.start_app()
  325. dut1.expect("Loaded app from partition at offset", timeout=30)
  326. try:
  327. ip_address = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)
  328. print("Connected to AP with IP: {}".format(ip_address))
  329. except DUT.ExpectTimeout:
  330. raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
  331. dut1.expect("Starting Advanced OTA example", timeout=30)
  332. print("writing to device: {}".format("https://" + host_ip + ":8070/" + bin_name))
  333. dut1.write("https://" + host_ip + ":8070/" + bin_name)
  334. dut1.expect("Loaded app from partition at offset", timeout=60)
  335. dut1.expect("Starting Advanced OTA example", timeout=30)
  336. chunked_server.kill()
  337. os.remove(os.path.join(dut1.app.binary_path, "server_cert.pem"))
  338. os.remove(os.path.join(dut1.app.binary_path, "server_key.pem"))
  339. @ttfw_idf.idf_example_test(env_tag="Example_WIFI")
  340. def test_examples_protocol_advanced_https_ota_example_redirect_url(env, extra_data):
  341. """
  342. This is a positive test case, which starts a server and a redirection server.
  343. Redirection server redirects http_request to different port
  344. Number of iterations can be specified in variable iterations.
  345. steps: |
  346. 1. join AP
  347. 2. Fetch OTA image over HTTPS
  348. 3. Reboot with the new OTA image
  349. """
  350. dut1 = env.get_dut("advanced_https_ota_example", "examples/system/ota/advanced_https_ota", dut_class=ttfw_idf.ESP32DUT)
  351. server_port = 8001
  352. # Port to which the request should be redirecetd
  353. redirection_server_port = 8081
  354. # File to be downloaded. This file is generated after compilation
  355. bin_name = "advanced_https_ota.bin"
  356. # check and log bin size
  357. binary_file = os.path.join(dut1.app.binary_path, bin_name)
  358. bin_size = os.path.getsize(binary_file)
  359. ttfw_idf.log_performance("advanced_https_ota_bin_size", "{}KB".format(bin_size // 1024))
  360. ttfw_idf.check_performance("advanced_https_ota_bin_size", bin_size // 1024)
  361. # start test
  362. host_ip = get_my_ip()
  363. if (get_server_status(host_ip, server_port) is False):
  364. thread1 = Thread(target=start_https_server, args=(dut1.app.binary_path, host_ip, server_port))
  365. thread1.daemon = True
  366. thread1.start()
  367. thread2 = Thread(target=start_redirect_server, args=(dut1.app.binary_path, host_ip, redirection_server_port, server_port))
  368. thread2.daemon = True
  369. thread2.start()
  370. dut1.start_app()
  371. dut1.expect("Loaded app from partition at offset", timeout=30)
  372. try:
  373. ip_address = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)
  374. print("Connected to AP with IP: {}".format(ip_address))
  375. except DUT.ExpectTimeout:
  376. raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
  377. thread1.close()
  378. thread2.close()
  379. dut1.expect("Starting Advanced OTA example", timeout=30)
  380. print("writing to device: {}".format("https://" + host_ip + ":" + str(redirection_server_port) + "/" + bin_name))
  381. dut1.write("https://" + host_ip + ":" + str(redirection_server_port) + "/" + bin_name)
  382. dut1.expect("Loaded app from partition at offset", timeout=60)
  383. dut1.expect("Starting Advanced OTA example", timeout=30)
  384. dut1.reset()
  385. if __name__ == '__main__':
  386. test_examples_protocol_advanced_https_ota_example()
  387. test_examples_protocol_advanced_https_ota_example_chunked()
  388. test_examples_protocol_advanced_https_ota_example_redirect_url()
  389. test_examples_protocol_advanced_https_ota_example_truncated_bin()
  390. test_examples_protocol_advanced_https_ota_example_truncated_header()
  391. test_examples_protocol_advanced_https_ota_example_random()