example_test.py 21 KB

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