def test_examples_protocol_http2_request(dut: Dut) -> None: """ steps: | 1. join AP 2. connect to http2.github.io 3. send http2 request 4. send http2 put response """ # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'http2_request.bin') bin_size = os.path.getsize(binary_file) logging.info('http2_request_bin_size : {}KB'.format(bin_size // 1024)) # start the test # check if test server is avilable test_server_available = is_test_server_available() # Skip the test if the server test server (http2.github.io) is not available at the moment. if test_server_available: logging.info('test server \"{}\" is available'.format(TEST_SERVER)) # check for connection dut.expect('Connection done', timeout=30) # check for get response dut.expect('Frame fully received') else: logging.info( 'test server \"{0}\" is not available at the moment.\nSkipping the test with status = success.' .format(TEST_SERVER))
def test_examples_wifi_prov_mgr(dut: Dut) -> None: # Check if BT memory is released before provisioning starts dut.expect('wifi_prov_scheme_ble: BT memory released', timeout=60) # Parse BLE devname devname = dut.expect( b'Provisioning started with service name : PROV_(.{6})')[0].decode( 'utf-8').split(' : ')[1] logging.info('BLE Device Alias for DUT : {}'.format(devname)) logging.info('Starting Provisioning') verbose = False protover = 'v1.1' secver = 1 pop = 'abcd1234' provmode = 'ble' ap_ssid = 'myssid' ap_password = '******' logging.info('Getting security') security = esp_prov.get_security(secver, pop, verbose) if security is None: raise RuntimeError('Failed to get security') logging.info('Getting transport') transport = esp_prov.get_transport(provmode, devname) if transport is None: raise RuntimeError('Failed to get transport') logging.info('Verifying protocol version') if not esp_prov.version_match(transport, protover): raise RuntimeError('Mismatch in protocol version') logging.info('Verifying scan list capability') if not esp_prov.has_capability(transport, 'wifi_scan'): raise RuntimeError('Capability not present') logging.info('Starting Session') if not esp_prov.establish_session(transport, security): raise RuntimeError('Failed to start session') logging.info('Sending Custom Data') if not esp_prov.custom_data(transport, security, 'My Custom Data'): raise RuntimeError('Failed to send custom data') logging.info('Sending Wifi credential to DUT') if not esp_prov.send_wifi_config(transport, security, ap_ssid, ap_password): raise RuntimeError('Failed to send Wi-Fi config') logging.info('Applying config') if not esp_prov.apply_wifi_config(transport, security): raise RuntimeError('Failed to send apply config') if not esp_prov.wait_wifi_connected(transport, security): raise RuntimeError('Provisioning failed') # Check if BTDM memory is released after provisioning finishes dut.expect('wifi_prov_scheme_ble: BTDM memory released', timeout=30)
def test_examples_protocol_http_server_lru_purge_enable(dut: Dut) -> None: # Get binary file binary_file = os.path.join(dut.app.binary_path, 'simple.bin') bin_size = os.path.getsize(binary_file) logging.info('http_server_bin_size : {}KB'.format(bin_size // 1024)) # Upload binary and start testing logging.info('Starting http_server simple test app') # 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"(?:[\s\S]*)Starting server on port: '(\d+)'", timeout=30)[1].decode() logging.info('Got IP : {}'.format(got_ip)) logging.info('Got Port : {}'.format(got_port)) # Expected Logs dut.expect('Registering URI handlers', timeout=30) threads = [] # Open 20 sockets, one from each thread for _ in range(20): try: thread = http_client_thread(got_ip, (int(got_port)), 20) thread.start() threads.append(thread) except OSError as err: logging.info('Error: unable to start thread, {}'.format(err)) for t in threads: t.join()
def test_dshot_esc_example(dut: Dut) -> None: dut.expect_exact('example: Create RMT TX channel') dut.expect_exact('example: Install Dshot ESC encoder') dut.expect_exact('example: Enable RMT TX channel') dut.expect_exact( 'example: Start ESC by sending zero throttle for a while...') dut.expect_exact('example: Increase throttle, no telemetry')
def test_examples_protocol_https_server_simple_dynamic_buffers(dut: Dut) -> None: # Test with mbedTLS dynamic buffer feature # start test # Parse IP address and port of the server dut.expect(r'Starting server') got_port = int(dut.expect(r'Server listening on port (\d+)', timeout=30)[1].decode()) logging.info('Waiting to connect with AP') got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode() # Expected logs logging.info('Got IP : {}'.format(got_ip)) logging.info('Got Port : {}'.format(got_port)) logging.info('Performing GET request over an SSL connection with the server') CLIENT_CERT_FILE = 'client_cert.pem' CLIENT_KEY_FILE = 'client_key.pem' ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) ssl_context.verify_mode = ssl.CERT_REQUIRED ssl_context.check_hostname = False ssl_context.load_verify_locations(cadata=server_cert_pem) ssl_context.load_cert_chain(certfile=CLIENT_CERT_FILE, keyfile=CLIENT_KEY_FILE) os.remove(CLIENT_CERT_FILE) os.remove(CLIENT_KEY_FILE) conn = http.client.HTTPSConnection(got_ip, got_port, context=ssl_context) logging.info('Performing SSL handshake with the server') conn.request('GET','/') resp = conn.getresponse() dut.expect('performing session handshake') got_resp = resp.read().decode('utf-8') if got_resp != success_response: logging.info('Response obtained does not match with correct response') raise RuntimeError('Failed to test SSL connection') current_cipher = dut.expect(r'Current Ciphersuite(.*)', timeout=5)[0] logging.info('Current Ciphersuite {}'.format(current_cipher)) # Close the connection conn.close() logging.info('Checking user callback: Obtaining client certificate...') serial_number = dut.expect(r'serial number(.*)', timeout=5)[0] issuer_name = dut.expect(r'issuer name(.*)', timeout=5)[0] expiry = dut.expect(r'expires on ((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode() logging.info('Serial No. : {}'.format(serial_number)) logging.info('Issuer Name : {}'.format(issuer_name)) logging.info('Expires on : {}'.format(expiry)) logging.info('Correct response obtained') logging.info('SSL connection test successful\nClosing the connection')
def test_custom_bootloader_impl_example(app: IdfApp, dut: Dut) -> None: # Expect to read a message from the custom bootloader # This message is defined in the Kconfig file, retrieve it while deleting # leading and trailing quotes (") welcome_message = app.sdkconfig['EXAMPLE_BOOTLOADER_WELCOME_MESSAGE'] dut.expect_exact(welcome_message) # Expect to read a message from the user application dut.expect_exact('Application started!')
def test_pthread(dut: Dut) -> None: # Note: this test doesn't really confirm anything, except that threads are created # and stdout is not being corrupted by multiple threads printing ot it. dut.expect(r'Created thread 0x[\da-f]+') dut.expect(r'Created larger stack thread 0x[\da-f]+') dut.expect(r'Threads have exited') dut.expect(r'Created thread 0x[\da-f]+ with new default config') dut.expect('Thread has exited')
def test_i2s_basic_example(dut: Dut) -> None: dut.expect_exact( 'I2S tx and rx channels have been initialized to standard duplex mode', timeout=30) dut.expect_exact('I2S tx and rx channels enabled', timeout=30) dut.expect_exact('[i2s write] 1440 bytes are written successfully', timeout=30) dut.expect_exact('', timeout=30) dut.expect_exact('[i2s read] 8192 bytes are read successfully', timeout=30)
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_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_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 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_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 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_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_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 lightsleep_test(dut: Dut, case_name: str) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write(case_name) if dut.target == 'esp32c3': # Known issue: IDF-5003 dut.expect(r'Returned from light sleep, reason: timer', timeout=40) else: dut.expect(r'Returned from light sleep, reason: timer', timeout=10)
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 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 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_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 """ 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() if (get_server_status(host_ip, server_port) is False): 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) thread1.terminate()
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_plugins(dut: Dut) -> None: log_text = textwrap.dedent(r""" Nihao plugin performing self-registration... Successfully registered plugin 'Nihao' Hello plugin performing self-registration... Successfully registered plugin 'Hello' cpu_start: Starting scheduler List of plugins: - Plugin 'Hello' - Plugin 'Nihao' Calling greet function of plugin 'Hello'... Hello, World! Done with greet function of plugin 'Hello'. Calling greet function of plugin 'Nihao'... 你好 World! Done with greet function of plugin 'Nihao'. """).strip('\n') for line in log_text.split('\n'): dut.expect_exact(line.encode('utf-8'))
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_eventfd(dut: Dut) -> None: dut.expect_exact('cpu_start: Starting scheduler') exp_list_5seconds = [ 'eventfd_example: Select timeouted for 1 times', 'eventfd_example: Timer triggerred for 2 times', 'eventfd_example: Progress triggerred for 1 times', ] exp_list_10seconds = [ 'eventfd_example: Select timeouted for 2 times', 'eventfd_example: Timer triggerred for 4 times', 'eventfd_example: Progress triggerred for 2 times', ] logging.info('Expecting:{}{}'.format(os.linesep, os.linesep.join(exp_list_5seconds))) for exp in exp_list_5seconds: dut.expect_exact(exp) logging.info('Expecting:{}{}'.format(os.linesep, os.linesep.join(exp_list_10seconds))) for exp in exp_list_10seconds: dut.expect_exact(exp)
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 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_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 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!')