def actual_test(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('\n') dut.expect_exact('Enter test for running.') dut.write('"start_and_stop"') dut.expect_unity_test_output() dut.expect_exact("Enter next test, or 'enter' to see menu") dut.write('"get_set_mac"') dut.expect_unity_test_output() dut.expect_exact("Enter next test, or 'enter' to see menu") with configure_eth_if() as so: so.settimeout(30) dut.write('"ethernet_broadcast_transmit"') eth_frame = Ether(so.recv(1024)) for i in range(0, 1010): if eth_frame.load[i] != i & 0xff: raise Exception('Packet content mismatch') dut.expect_unity_test_output() dut.expect_exact("Enter next test, or 'enter' to see menu") dut.write('"recv_pkt"') res = dut.expect( r'([\s\S]*)' r'DUT MAC: ([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})' ) send_eth_packet('ff:ff:ff:ff:ff:ff') # broadcast frame send_eth_packet('01:00:00:00:00:00') # multicast frame send_eth_packet(res.group(2)) # unicast frame dut.expect_unity_test_output(extra_before=res.group(1)) dut.expect_exact("Enter next test, or 'enter' to see menu") dut.write('"start_stop_stress_test"') res = dut.expect( r'([\s\S]*)' r'DUT MAC: ([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})' ) # Start/stop under heavy Tx traffic for tx_i in range(10): recv_resp_poke(tx_i) # Start/stop under heavy Rx traffic pipe_rcv, pipe_send = Pipe(False) tx_proc = Process(target=traffic_gen, args=( res.group(2), pipe_rcv, )) tx_proc.start() try: for rx_i in range(10): recv_resp_poke(rx_i) finally: pipe_send.send(0) tx_proc.join() dut.expect_unity_test_output()
def test_examples_protocol_https_x509_bundle_dynamic_buffer(dut: Dut) -> None: # test mbedtls dynamic resource # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin') bin_size = os.path.getsize(binary_file) logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024)) # start test num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode()) dut.expect(r'Connection established to ([\s\S]*)', timeout=30) dut.expect('Completed {} connections'.format(num_URLS), timeout=60)
def test_examples_protocol_simple_ota_example_ethernet_with_spiram_config( dut: Dut) -> None: """ steps: | 1. join AP 2. Fetch OTA image over HTTPS 3. Reboot with the new OTA image """ try: # start test host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, 8000)) thread1.daemon = True thread1.start() dut.expect('Loaded app from partition at offset 0x10000', timeout=30) try: ip_address = dut.expect(r' eth ip: ([^,]+),', timeout=30) print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') dut.expect('Starting OTA example', timeout=30) print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin')) dut.write('https://' + host_ip + ':8000/simple_ota.bin') dut.expect('Loaded app from partition at offset 0x110000', timeout=60) dut.expect('Starting OTA example', timeout=30) finally: thread1.terminate()
def test_examples_protocol_native_ota_example_chunked(dut: Dut) -> None: """ This is a positive test case, which downloads complete binary file multiple number of times. Number of iterations can be specified in variable iterations. steps: | 1. join AP 2. Fetch OTA image over HTTPS 3. Reboot with the new OTA image """ # File to be downloaded. This file is generated after compilation bin_name = 'native_ota.bin' # start test host_ip = get_my_ip() chunked_server = start_chunked_server(dut.app.binary_path, 8070) try: dut.expect('Loaded app from partition at offset', timeout=30) try: ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') dut.expect('Starting OTA example', timeout=30) print('writing to device: {}'.format('https://' + host_ip + ':8070/' + bin_name)) dut.write('https://' + host_ip + ':8070/' + bin_name) dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('Starting OTA example', timeout=30) os.remove(os.path.join(dut.app.binary_path, 'server_cert.pem')) os.remove(os.path.join(dut.app.binary_path, 'server_key.pem')) finally: chunked_server.kill()
def test_examples_cbor(dut: Dut) -> None: dut.expect(r'example: encoded buffer size \d+') dut.expect('example: convert CBOR to JSON') parsed_info = dut.expect( r'\[\{"chip":"(\w+)","unicore":(\w+),"ip":\[(\d+),(\d+),(\d+),(\d+)\]\},' r'3.1400001049041748' r',"simple\(99\)","2019-07-10 09:00:00\+0000","undefined"\]') dut.expect('example: decode CBOR manually') dut.expect( textwrap.dedent(r''' Array\[\s+ Map{{\s+ chip\s+ {}\s+ unicore\s+ {}\s+ ip\s+ Array\[\s+ {}\s+ {}\s+ {}\s+ {}\s+ \]\s+ }}\s+ 3.14\s+ simple\(99\)\s+ 2019-07-10 09:00:00\+0000\s+ undefined\s+ \]'''.format( parsed_info[1].decode(), parsed_info[2].decode(), parsed_info[3].decode(), parsed_info[4].decode(), parsed_info[5].decode(), parsed_info[6].decode())).replace('{', r'\{').replace('}', r'\}'))
def test_examples_protocol_advanced_https_ota_example_redirect_url( dut: Dut) -> None: """ This is a positive test case, which starts a server and a redirection server. Redirection server redirects http_request to different port Number of iterations can be specified in variable iterations. steps: | 1. join AP 2. Fetch OTA image over HTTPS 3. Reboot with the new OTA image """ try: server_port = 8001 # Port to which the request should be redirected redirection_server_port = 8081 redirection_server_port1 = 8082 # File to be downloaded. This file is generated after compilation bin_name = 'advanced_https_ota.bin' # start test host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) thread1.daemon = True thread1.start() thread2 = multiprocessing.Process(target=start_redirect_server, args=(dut.app.binary_path, host_ip, redirection_server_port, redirection_server_port1)) thread2.daemon = True thread2.start() thread3 = multiprocessing.Process(target=start_redirect_server, args=(dut.app.binary_path, host_ip, redirection_server_port1, server_port)) thread3.daemon = True thread3.start() dut.expect('Loaded app from partition at offset', timeout=30) try: ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: thread1.terminate() thread2.terminate() thread3.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') dut.expect('Starting Advanced OTA example', timeout=30) print('writing to device: {}'.format('https://' + host_ip + ':' + str(redirection_server_port) + '/' + bin_name)) dut.write('https://' + host_ip + ':' + str(redirection_server_port) + '/' + bin_name) dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('Starting Advanced OTA example', timeout=30) finally: thread1.terminate() thread2.terminate() thread3.terminate()
def test_himem(dut: Dut) -> None: mem = dut.expect( r'esp_himem: Initialized. Using last \d+ 32KB address blocks for bank ' r'switching on (\d+) KB of physical memory.').group(1).decode('utf8') dut.expect( r'Himem has {}KiB of memory, \d+KiB of which is free.'.format(mem), timeout=10) dut.expect_exact('Testing the free memory...') dut.expect_exact('Done!')
def deep_sleep_test(dut: Dut) -> None: def expect_enable_deep_sleep_touch() -> None: # different targets configure different wake pin(s) wake_pads = { 'esp32': [8, 9], 'esp32s2': [9], }[dut.target] logging.info('Expecting to see wakeup configured on pad(s): {}'.format( wake_pads)) expect_items = ['Enabling timer wakeup, 20s'] for pad in wake_pads: expect_items += [ r'Touch pad #{} average: \d+, wakeup threshold set to \d+.'. format(pad) ] expect_items += ['Enabling touch pad wakeup', 'Entering deep sleep'] for exp in expect_items: dut.expect(exp, timeout=10) def expect_enable_deep_sleep_no_touch() -> None: dut.expect_exact('Enabling timer wakeup, 20s', timeout=10) dut.expect_exact('Entering deep sleep', timeout=10) if dut.target in touch_wake_up_support: expect_enable_deep_sleep = expect_enable_deep_sleep_touch else: expect_enable_deep_sleep = expect_enable_deep_sleep_no_touch dut.expect_exact('Not a deep sleep reset') expect_enable_deep_sleep() start_sleep = time.time() logging.info('Waiting for wakeup...') dut.expect_exact( 'boot: ESP-IDF') # first output that's the same on all chips sleep_time = time.time() - start_sleep logging.info('Host measured sleep time at {:.2f}s'.format(sleep_time)) assert 18 < sleep_time < 22 # note: high tolerance as measuring time on the host may have some timing skew # This line indicates that the CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP option set in sdkconfig.defaults # has correctly allowed skipping verification on wakeup dut.expect_exact('boot: Fast booting app from partition', timeout=2) # Check that it measured 2xxxxms in deep sleep, i.e at least 20 seconds: dut.expect(r'Wake up from timer. Time spent in deep sleep: 2\d{4}ms', timeout=2) expect_enable_deep_sleep()
def test_examples_security_flash_encryption(dut: Dut) -> None: # Erase the nvs_key partition dut.serial.erase_partition('nvs_key') # calculate the expected ciphertext flash_addr = dut.app.partition_table['storage']['offset'] plain_hex_str = '00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f' plain_data = binascii.unhexlify(plain_hex_str.replace(' ', '')) # espsecure uses the cryptography package for encrypting # with aes-xts, but does not allow for a symmetric key # so the key for later chips are not all zeros if dut.target == 'esp32': key_bytes = b'\x00' * 32 aes_xts = False else: key_bytes = b'\xff' + b'\x00' * 31 aes_xts = True # Emulate espsecure encrypt_flash_data command EncryptFlashDataArgs = namedtuple('EncryptFlashDataArgs', [ 'output', 'plaintext_file', 'address', 'keyfile', 'flash_crypt_conf', 'aes_xts' ]) args = EncryptFlashDataArgs(BytesIO(), BytesIO(plain_data), flash_addr, BytesIO(key_bytes), 0xF, aes_xts) espsecure.encrypt_flash_data(args) expected_ciphertext = args.output.getvalue() hex_ciphertext = binascii.hexlify(expected_ciphertext).decode('ascii') expected_str = (' '.join(hex_ciphertext[i:i + 2] for i in range(0, 16, 2)) + ' ' + ' '.join(hex_ciphertext[i:i + 2] for i in range(16, 32, 2))) lines = [ 'FLASH_CRYPT_CNT eFuse value is 1', 'Flash encryption feature is enabled in DEVELOPMENT mode', 'with esp_partition_write', plain_hex_str, 'with esp_partition_read', plain_hex_str, 'with esp_flash_read', expected_str, # The status of NVS encryption for the "nvs" partition 'NVS partition "nvs" is encrypted.', # The status of NVS encryption for the "custom_nvs" partition 'NVS partition "custom_nvs" is encrypted.' ] for line in lines: dut.expect(line, timeout=20)
def test_examples_protocol_https_x509_bundle(dut: Dut) -> None: """ steps: | 1. join AP 2. connect to multiple URLs 3. send http request """ # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin') bin_size = os.path.getsize(binary_file) logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024)) # start test num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode()) dut.expect(r'Connection established to ([\s\S]*)', timeout=30) dut.expect('Completed {} connections'.format(num_URLS), timeout=60)
def actual_test(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('\n') dut.expect_exact('Enter test for running.') dut.write('"start_and_stop"') dut.expect_unity_test_output() dut.expect_exact("Enter next test, or 'enter' to see menu") dut.write('"get_set_mac"') dut.expect_unity_test_output() dut.expect_exact("Enter next test, or 'enter' to see menu") with configure_eth_if() as so: so.settimeout(30) dut.write('"ethernet_broadcast_transmit"') pkt = so.recv(1024) for i in range(128, 1024): if pkt[i] != i & 0xff: raise Exception('Packet content mismatch') dut.expect_unity_test_output() dut.expect_exact("Enter next test, or 'enter' to see menu") dut.write('"recv_pkt"') res = dut.expect( r'([\s\S]*)' r'DUT MAC: ([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})' ) send_eth_packet(bytes.fromhex('ffffffffffff')) # broadcast frame # pylint: disable=no-value-for-parameter send_eth_packet(bytes.fromhex('010000000000')) # multicast frame # pylint: disable=no-value-for-parameter send_eth_packet(bytes.fromhex(res.group(2).decode('utf-8').replace(':', ''))) # unicast fram # pylint: disable=no-value-for-parameter, line-too-long # noqa dut.expect_unity_test_output(extra_before=res.group(1))
def test_ulp_fsm_adc(dut: Dut) -> None: dut.expect_exact('Not ULP wakeup') dut.expect_exact('Entering deep sleep') for _ in range(5): dut.expect_exact('Deep sleep wakeup', timeout=60) measurements_str = dut.expect(r'ULP did (\d+) measurements', timeout=5).group(1) assert measurements_str is not None measurements = int(measurements_str) logging.info('ULP did {} measurements'.format(measurements)) dut.expect_exact('Thresholds: low=1500 high=2000', timeout=5) value_str = dut.expect(r'Value=(\d+) was (above|below) threshold', timeout=5).group(1) assert value_str is not None value = int(value_str) logging.info('Value {} was outside the boundaries'.format(value)) dut.expect_exact('Entering deep sleep', timeout=60)
def test_i2s_adc_dac_example(dut: Dut) -> None: dut.expect( 'partiton addr: 0x([0-9a-fA-F]+); size: ([0-9]+); label: storage', timeout=30) dut.expect_exact('Erasing flash', timeout=30) dut.expect( 'partiton addr: 0x([0-9a-fA-F]+); size: ([0-9]+); label: storage', timeout=30) dut.expect('Erase size: ([0-9]+) Bytes', timeout=30) dut.expect('I \\(([0-9]+)\\) ad/da: ([0-9]+) mV', timeout=30)
def test_examples_protocol_https_request_dynamic_buffers(dut: Dut) -> None: # Check for connection using crt bundle with mbedtls dynamic resource enabled # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'https_request.bin') bin_size = os.path.getsize(binary_file) logging.info('https_request_bin_size : {}KB'.format(bin_size // 1024)) dut.expect('Loaded app from partition at offset', timeout=30) try: ip_address = dut.expect(r' (sta|eth) ip: (\d+\.\d+\.\d+\.\d+)', timeout=60)[2].decode() print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') # only check if one connection is established logging.info( "Testing for \"https_request using crt bundle\" with mbedtls dynamic resource enabled" ) try: dut.expect('https_request using crt bundle', timeout=30) dut.expect([ 'Connection established...', 'Reading HTTP response...', 'HTTP/1.1 200 OK', 'connection closed' ], expect_all=True) except Exception: logging.info( "Failed the test for \"https_request using crt bundle\" when mbedtls dynamic resource was enabled" ) raise logging.info( "Passed the test for \"https_request using crt bundle\" when mbedtls dynamic resource was enabled" )
def test_examples_protocol_advanced_https_ota_example_openssl_aligned_bin( dut: Dut) -> None: """ This is a test case for esp_http_client_read with binary size multiple of 289 bytes steps: | 1. join AP 2. Fetch OTA image over HTTPS 3. Reboot with the new OTA image """ # Original binary file generated after compilation bin_name = 'advanced_https_ota.bin' # Binary file aligned to DEFAULT_OTA_BUF_SIZE(289 bytes) boundary aligned_bin_name = 'aligned.bin' # check and log bin size binary_file = os.path.join(dut.app.binary_path, bin_name) # Original binary size bin_size = os.path.getsize(binary_file) # Dummy data required to align binary size to 289 bytes boundary dummy_data_size = 289 - (bin_size % 289) with open(binary_file, 'rb+') as f: with open(os.path.join(dut.app.binary_path, aligned_bin_name), 'wb+') as fo: fo.write(f.read(bin_size)) for _ in range(dummy_data_size): fo.write(struct.pack('B', random.randrange(0, 255, 1))) # start test host_ip = get_my_ip() chunked_server = start_chunked_server(dut.app.binary_path, 8070) try: dut.expect('Loaded app from partition at offset', timeout=30) try: ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') dut.expect('Starting Advanced OTA example', timeout=30) print('writing to device: {}'.format('https://' + host_ip + ':8070/' + aligned_bin_name)) dut.write('https://' + host_ip + ':8070/' + aligned_bin_name) dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('Starting Advanced OTA example', timeout=30) try: os.remove(aligned_bin_name) except OSError: pass finally: chunked_server.kill()
def test_otatool_example(dut: Dut) -> None: # Verify factory firmware dut.expect('OTA Tool Example') dut.expect('Example end') # Close connection to DUT dut.serial.proc.close() script_path = os.path.join(str(os.getenv('IDF_PATH')), 'examples', 'system', 'ota', 'otatool', 'otatool_example.py') binary_path = '' for flash_file in dut.app.flash_files: if 'otatool.bin' in flash_file[1]: binary_path = flash_file[1] break subprocess.check_call( [sys.executable, script_path, '--binary', binary_path])
def test_examples_protocol_advanced_https_ota_example_invalid_chip_id( dut: Dut) -> None: """ Working of OTA if binary file have invalid chip id is validated in this test case. Chip id verification should fail in this case. steps: | 1. join AP 2. Generate binary image with invalid chip id 3. Fetch OTA image over HTTPS 4. Check working of code for random binary file """ try: server_port = 8001 bin_name = 'advanced_https_ota.bin' # Random binary file to be generated random_bin_name = 'random.bin' random_binary_file = os.path.join(dut.app.binary_path, random_bin_name) # Size of random binary file. 2000 is choosen, to reduce the time required to run the test-case random_bin_size = 2000 binary_file = os.path.join(dut.app.binary_path, bin_name) with open(binary_file, 'rb+') as f: data = list(f.read(random_bin_size)) # Changing Chip id data[13] = 0xfe with open(random_binary_file, 'wb+') as fo: fo.write(bytearray(data)) # start test host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) thread1.daemon = True thread1.start() dut.expect('Loaded app from partition at offset', timeout=30) try: ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') dut.expect('Starting Advanced OTA example', timeout=30) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name)) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name) dut.expect(r'esp_https_ota: Mismatch chip id, expected 0, found \d', timeout=10) try: os.remove(random_binary_file) except OSError: pass finally: thread1.terminate()
def test_examples_protocol_advanced_https_ota_example_truncated_header( dut: Dut) -> None: """ Working of OTA if headers of binary file are truncated is vaildated in this test case. Application should return with error message in this case. steps: | 1. join AP 2. Generate binary file with truncated headers 3. Fetch OTA image over HTTPS 4. Check working of code if headers are not sent completely """ try: server_port = 8001 # Original binary file generated after compilation bin_name = 'advanced_https_ota.bin' # Truncated binary file to be generated from original binary file truncated_bin_name = 'truncated_header.bin' # Size of truncated file to be generated. This value should be less than 288 bytes (Image header size) truncated_bin_size = 180 # check and log bin size binary_file = os.path.join(dut.app.binary_path, bin_name) with open(binary_file, 'rb+') as f: with open(os.path.join(dut.app.binary_path, truncated_bin_name), 'wb+') as fo: fo.write(f.read(truncated_bin_size)) binary_file = os.path.join(dut.app.binary_path, truncated_bin_name) # start test host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) thread1.daemon = True thread1.start() dut.expect('Loaded app from partition at offset', timeout=30) try: ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') dut.expect('Starting Advanced OTA example', timeout=30) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name)) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name) dut.expect( 'advanced_https_ota_example: esp_https_ota_read_img_desc failed', timeout=30) try: os.remove(binary_file) except OSError: pass finally: thread1.terminate()
def ulp_fsm_test_function(dut: Dut) -> None: dut.expect_exact('Not ULP wakeup') dut.expect_exact('Entering deep sleep') def generate_gpio0_events() -> None: for _ in range(5): dut.serial.proc.setDTR(True) # Pulling GPIO0 low using DTR time.sleep(0.25) dut.serial.proc.setDTR(False) time.sleep(0.25) nvs_value = None for _ in range(5): generate_gpio0_events() dut.expect_exact('ULP wakeup, saving pulse count', timeout=5) logging.info('Woke up...') init_count = int( dut.expect(r'Read pulse count from NVS:\s+(\d+)', timeout=5).group(1), 10) assert nvs_value in (init_count, None), ( 'Read count is {} and previously written value is {}' ''.format(init_count, nvs_value)) inc = int( dut.expect(r'Pulse count from ULP:\s+(\d+)', timeout=5).group(1), 10) assert inc in (5, 6), 'pulse count is {}'.format(inc) new_count = int( dut.expect(r'Wrote updated pulse count to NVS:\s+(\d+)', timeout=5).group(1), 10) assert init_count + inc == new_count, '{} + {} != {}'.format( init_count, inc, new_count) nvs_value = new_count logging.info( 'Pulse count written to NVS: {}. Entering deep sleep...'.format( nvs_value)) dut.expect_exact('Entering deep sleep', timeout=5)
def test_examples_protocol_native_ota_example_truncated_bin(dut: Dut) -> None: """ Working of OTA if binary file is truncated is validated in this test case. Application should return with error message in this case. steps: | 1. join AP 2. Generate truncated binary file 3. Fetch OTA image over HTTPS 4. Check working of code if bin is truncated """ try: server_port = 8002 # Original binary file generated after compilation bin_name = 'native_ota.bin' # Truncated binary file to be generated from original binary file truncated_bin_name = 'truncated.bin' # Size of truncated file to be grnerated. This value can range from 288 bytes (Image header size) to size of original binary file # truncated_bin_size is set to 64000 to reduce consumed by the test case truncated_bin_size = 64000 # check and log bin size binary_file = os.path.join(dut.app.binary_path, bin_name) f = open(binary_file, 'rb+') fo = open(os.path.join(dut.app.binary_path, truncated_bin_name), 'wb+') fo.write(f.read(truncated_bin_size)) fo.close() f.close() binary_file = os.path.join(dut.app.binary_path, truncated_bin_name) # start test host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) thread1.daemon = True thread1.start() dut.expect('Loaded app from partition at offset', timeout=30) try: ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') dut.expect('Starting OTA example', timeout=30) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name)) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name) dut.expect( 'native_ota_example: Image validation failed, image is corrupted', timeout=20) os.remove(binary_file) finally: thread1.terminate()
def test_examples_protocol_advanced_https_ota_example_random(dut: Dut) -> None: """ Working of OTA if random data is added in binary file are validated in this test case. Magic byte verification should fail in this case. steps: | 1. join AP 2. Generate random binary image 3. Fetch OTA image over HTTPS 4. Check working of code for random binary file """ try: server_port = 8001 # Random binary file to be generated random_bin_name = 'random.bin' # Size of random binary file. 32000 is choosen, to reduce the time required to run the test-case random_bin_size = 32000 # check and log bin size binary_file = os.path.join(dut.app.binary_path, random_bin_name) with open(binary_file, 'wb+') as fo: # First byte of binary file is always set to zero. If first byte is generated randomly, # in some cases it may generate 0xE9 which will result in failure of testcase. fo.write(struct.pack('B', 0)) for i in range(random_bin_size - 1): fo.write(struct.pack('B', random.randrange(0, 255, 1))) # start test host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) thread1.daemon = True thread1.start() dut.expect('Loaded app from partition at offset', timeout=30) try: ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') dut.expect('Starting Advanced OTA example', timeout=30) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name)) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name) dut.expect(r'esp_https_ota: Incorrect app descriptor magic', timeout=10) try: os.remove(binary_file) except OSError: pass finally: thread1.terminate()
def test_examples_protocol_native_ota_example(dut: Dut) -> None: """ This is a positive test case, which downloads complete binary file multiple number of times. Number of iterations can be specified in variable iterations. steps: | 1. join AP 2. Fetch OTA image over HTTPS 3. Reboot with the new OTA image """ try: server_port = 8002 # No. of times working of application to be validated iterations = 3 # File to be downloaded. This file is generated after compilation bin_name = 'native_ota.bin' # start test host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) thread1.daemon = True thread1.start() for i in range(iterations): dut.expect('Loaded app from partition at offset', timeout=60) try: ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') dut.expect('Starting OTA example', timeout=30) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name) finally: thread1.terminate()
def test_examples_protocol_advanced_https_ota_example_nimble_gatts( dut: Dut) -> None: """ Run an OTA image update while a BLE GATT Server is running in background. This GATT server will be using NimBLE Host stack. steps: | 1. join AP 2. Run BLE advertise and then GATT server. 3. Fetch OTA image over HTTPS 4. Reboot with the new OTA image """ try: server_port = 8001 # File to be downloaded. This file is generated after compilation bin_name = 'advanced_https_ota.bin' # start test host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) thread1.daemon = True thread1.start() dut.expect('Loaded app from partition at offset', timeout=30) try: ip_address = dut.expect(r' sta ip: ([^,]+),', timeout=30) print('Connected to AP with IP: {}'.format(ip_address)) except pexpect.exceptions.TIMEOUT: thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') dut.expect('Starting Advanced OTA example', timeout=30) print( 'writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)) print('Started GAP advertising.') dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name) dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('Starting Advanced OTA example', timeout=30) finally: thread1.terminate()
def test_unit_test(dut: Dut) -> None: def get_reg_nums(number: int) -> str: return r'\d{1,2}\s+' * number dut.expect_exact( 'In main application. Collecting 32 random numbers from 1 to 100:') dut.expect(get_reg_nums(10)) dut.expect(get_reg_nums(10)) dut.expect(get_reg_nums(10)) dut.expect(get_reg_nums(2))
def deepsleep_test(dut: Dut, case_name: str) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write(case_name) reset_reason = 'DEEPSLEEP_RESET' if dut.target == 'esp32' else 'DSLEEP' if dut.target == 'esp32c3': # Known issue: IDF-5003 dut.expect(r'rst:.*\(%s\)' % reset_reason, timeout=40) elif dut.target == 'esp32c2': # Known issue: IDF-5003 dut.expect(r'rst:.*\(%s\)' % reset_reason, timeout=60) else: dut.expect(r'rst:.*\(%s\)' % reset_reason, timeout=10)
def test_examples_protocol_http_ws_echo_server(dut: Dut) -> None: # Get binary file binary_file = os.path.join(dut.app.binary_path, 'ws_echo_server.bin') bin_size = os.path.getsize(binary_file) logging.info('http_ws_server_bin_size : {}KB'.format(bin_size // 1024)) logging.info('Starting ws-echo-server test app based on http_server') # Parse IP address of STA logging.info('Waiting to connect with AP') got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode() got_port = dut.expect(r"Starting server on port: '(\d+)'", timeout=30)[1].decode() logging.info('Got IP : {}'.format(got_ip)) logging.info('Got Port : {}'.format(got_port)) # Start ws server test with WsClient(got_ip, int(got_port)) as ws: DATA = 'Espressif' for expected_opcode in [OPCODE_TEXT, OPCODE_BIN, OPCODE_PING]: ws.write(data=DATA, opcode=expected_opcode) opcode, data = ws.read() logging.info( 'Testing opcode {}: Received opcode:{}, data:{}'.format( expected_opcode, opcode, data)) data = data.decode() if expected_opcode == OPCODE_PING: dut.expect('Got a WS PING frame, Replying PONG') if opcode != OPCODE_PONG or data != DATA: raise RuntimeError( 'Failed to receive correct opcode:{} or data:{}'. format(opcode, data)) continue dut_data = dut.expect( r'Got packet with message: ([A-Za-z0-9_]*)')[1] dut_opcode = dut.expect(r'Packet type: ([0-9]*)')[1].decode() if opcode != expected_opcode or data != DATA or opcode != int( dut_opcode) or (data not in str(dut_data)): raise RuntimeError( 'Failed to receive correct opcode:{} or data:{}'.format( opcode, data)) ws.write(data='Trigger async', opcode=OPCODE_TEXT) opcode, data = ws.read() logging.info('Testing async send: Received opcode:{}, data:{}'.format( opcode, data)) data = data.decode() if opcode != OPCODE_TEXT or data != 'Async data': raise RuntimeError( 'Failed to receive correct opcode:{} or data:{}'.format( opcode, data))
def test_timer_group_example(dut: Dut) -> None: dut.expect(r'Init timer with auto-reload', timeout=5) res = dut.expect(r'Timer auto reloaded, count value in ISR: (\d+)', timeout=5) reloaded_count = res.group(1).decode('utf8') assert 0 <= int(reloaded_count) < 10 alarm_increase_step = 500000 dut.expect(r'Init timer without auto-reload') for i in range(1, 5): res = dut.expect(r'Timer alarmed at (\d+)', timeout=3) alarm_count = res.group(1).decode('utf8') assert (i * alarm_increase_step - 10) < int(alarm_count) < (i * alarm_increase_step + 10)
def test_base_mac_address(dut: Dut) -> None: dut.expect_exact('BASE_MAC: Base MAC Address read from EFUSE BLK0') hex_r = r', '.join((r'0x([0-9a-f]{1,2})', ) * 6) mac_m = dut.expect(r'BASE_MAC: Using "' + hex_r + r'" as base MAC address', timeout=5).groups() def get_expected_mac_string(increment: int) -> str: ''' Return the string representation of the MAC address mac_m with the last octet incremented. mac_m is an array of strings in hexa-decimal format without the '0x' prefix. ''' return ', '.join(['0x{}'.format(m.decode('utf8')) for m in mac_m[:-1]] + [hex(int(mac_m[-1], 16) + increment)]) dut.expect_exact('WIFI_STA MAC: ' + get_expected_mac_string(0), timeout=2) dut.expect_exact('SoftAP MAC: ' + get_expected_mac_string(1)) if dut.target != 'esp32s2': dut.expect_exact('BT MAC: ' + get_expected_mac_string(2)) dut.expect_exact('Ethernet MAC: ' + get_expected_mac_string(3))
def actual_test(dut: Dut) -> None: # Get DUT's MAC address res = dut.expect( r'([\s\S]*)' r'Ethernet HW Addr ([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})' ) dut_mac = res.group(2) # Receive "ESP32 Hello frame" recv_eth_frame(ETH_TYPE_3) # Sent a message and receive its echo message = 'ESP32 test message with EthType ' + hex(ETH_TYPE_1) echoed = send_recv_eth_frame(message, ETH_TYPE_1, dut_mac) if echoed == message: logging.info('PASS') else: raise Exception('Echoed message does not match!') message = 'ESP32 test message with EthType ' + hex(ETH_TYPE_2) echoed = send_recv_eth_frame(message, ETH_TYPE_2, dut_mac) if echoed == message: logging.info('PASS') else: raise Exception('Echoed message does not match!')
def test_esp_event_user_event_loops(dut: Dut) -> None: dut.expect_exact('setting up') dut.expect_exact('starting event source') dut.expect_exact('starting application task') for iteration in range(1, TASK_ITERATION_LIMIT + 1): loop = None if (iteration % 2 == 0): loop = 'loop_with_task' else: loop = 'loop_without_task' dut.expect(TASK_ITERATION_POSTING.format(loop, iteration)) logging.info('Posted iteration {} to {}'.format(iteration, loop)) dut.expect(TASK_ITERATION_HANDLING.format(loop, iteration)) logging.info('Handled iteration {} from {}'.format(iteration, loop)) dut.expect('deleting task event source') logging.info('Deleted task event source')