example_test.py 21 KB

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