Exemple #1
0
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()
Exemple #5
0
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'\}'))
Exemple #6
0
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()
Exemple #7
0
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)
Exemple #11
0
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))
Exemple #12
0
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)
Exemple #14
0
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"
    )
Exemple #15
0
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()
Exemple #16
0
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])
Exemple #17
0
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()
Exemple #18
0
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()
Exemple #19
0
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)
Exemple #20
0
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()
Exemple #21
0
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()
Exemple #22
0
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()
Exemple #23
0
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()
Exemple #24
0
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))
Exemple #25
0
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)
Exemple #26
0
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))
Exemple #27
0
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')