Merge branch 'feature/system_tests_pytest_embedded' into 'master'

CI: migrated system example tests to pytest-embedded framework

Closes IDFCI-1134

See merge request espressif/esp-idf!17401
This commit is contained in:
Marius Vikhammer 2022-03-15 09:08:31 +08:00
commit 8a9ab63ecb
36 changed files with 551 additions and 623 deletions

View File

@ -1,35 +0,0 @@
from __future__ import unicode_literals
import re
import ttfw_idf
from tiny_test_fw import Utility
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32c3'])
def test_examples_base_mac_address(env, extra_data):
dut = env.get_dut('base_mac_address', 'examples/system/base_mac_address')
dut.start_app()
dut.expect('BASE_MAC: Base MAC Address read from EFUSE BLK0', timeout=30)
hex_r = r', '.join((r'0x([0-9a-f]{1,2})',) * 6)
mac_m = dut.expect(re.compile(r'BASE_MAC: Using "' + hex_r + r'" as base MAC address'), timeout=5)
Utility.console_log('BASE_MAC detected: {}'.format(':'.join(mac_m)))
def get_expected_mac_string(increment):
'''
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) for m in mac_m[:-1]] + [hex(int(mac_m[-1], 16) + increment)])
dut.expect_all('WIFI_STA MAC: ' + get_expected_mac_string(0),
'SoftAP MAC: ' + get_expected_mac_string(1),
'BT MAC: ' + get_expected_mac_string(2),
'Ethernet MAC: ' + get_expected_mac_string(3),
timeout=10)
if __name__ == '__main__':
test_examples_base_mac_address()

View File

@ -94,11 +94,13 @@ void app_main(void)
derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2], derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2],
derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]); derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]);
#if CONFIG_ESP_MAC_ADDR_UNIVERSE_BT
//Get MAC address for Bluetooth //Get MAC address for Bluetooth
ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_BT)); ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_BT));
ESP_LOGI("BT MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", ESP_LOGI("BT MAC", "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2], derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2],
derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]); derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]);
#endif //SOC_BT_SUPPORTED
//Get MAC address for Ethernet //Get MAC address for Ethernet
ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_ETH)); ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_ETH));

View File

@ -0,0 +1,27 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.supported_targets
@pytest.mark.generic
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))

View File

@ -1,65 +0,0 @@
from __future__ import unicode_literals
import re
import time
import ttfw_idf
touch_wake_up_support = ['esp32', 'esp32s2']
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32s2', 'esp32c3'])
def test_examples_deep_sleep(env, extra_data):
dut = env.get_dut('deep_sleep', 'examples/system/deep_sleep')
dut.start_app()
def expect_enable_deep_sleep_touch():
# different targets configure different wake pin(s)
wake_pads = {
'esp32': [8,9],
'esp32s2': [9],
}[dut.TARGET]
print('Expecting to see wakeup configured on pad(s): {}'.format(wake_pads))
expect_items = ['Enabling timer wakeup, 20s']
for pad in wake_pads:
expect_items += [re.compile(r'Touch pad #{} average: \d+, wakeup threshold set to \d+.'.format(pad))]
expect_items += ['Enabling touch pad wakeup',
'Entering deep sleep']
dut.expect_all(*expect_items, timeout=10)
def expect_enable_deep_sleep_no_touch():
dut.expect_all('Enabling timer wakeup, 20s',
'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('Not a deep sleep reset', timeout=30)
expect_enable_deep_sleep()
start_sleep = time.time()
print('Waiting for wakeup...')
dut.expect('boot: ESP-IDF', timeout=30) # first output that's the same on all chips
sleep_time = time.time() - start_sleep
print('Host measured sleep time at {:.2f}s'.format(sleep_time))
assert 19 < 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('boot: Fast booting app from partition', timeout=2)
# Check that it measured 2xxxxms in deep sleep, i.e at least 20 seconds:
dut.expect(re.compile(r'Wake up from timer. Time spent in deep sleep: 2\d{4}ms'), timeout=2)
expect_enable_deep_sleep()
if __name__ == '__main__':
test_examples_deep_sleep()

View File

@ -0,0 +1,66 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import time
import pytest
from pytest_embedded import Dut
touch_wake_up_support = ['esp32', 'esp32s2']
CONFIGS = [
pytest.param('esp32_singlecore', marks=[pytest.mark.esp32]),
pytest.param('generic', marks=[pytest.mark.supported_targets]),
]
@pytest.mark.parametrize('config', CONFIGS, indirect=True)
@pytest.mark.generic
def test_deep_sleep(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 19 < 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()

View File

@ -1,40 +0,0 @@
from __future__ import print_function
import ttfw_idf
TASK_ITERATION_LIMIT = 10
TASK_ITERATION_POSTING = 'posting TASK_EVENTS:TASK_ITERATION_EVENT to {}, iteration {} out of ' + str(TASK_ITERATION_LIMIT)
TASK_ITERATION_HANDLING = 'handling TASK_EVENTS:TASK_ITERATION_EVENT from {}, iteration {}'
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32c3'])
def test_user_event_loops_example(env, extra_data):
dut = env.get_dut('user_event_loops', 'examples/system/esp_event/user_event_loops')
dut.start_app()
dut.expect('setting up')
dut.expect('starting event source')
dut.expect('starting application task')
print('Finished setup')
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))
print('Posted iteration {} to {}'.format(iteration, loop))
dut.expect(TASK_ITERATION_HANDLING.format(loop, iteration))
print('Handled iteration {} from {}'.format(iteration, loop))
dut.expect('deleting task event source')
print('Deleted task event source')
if __name__ == '__main__':
test_user_event_loops_example()

View File

@ -94,7 +94,7 @@ void app_main(void)
.queue_size = 5, .queue_size = 5,
.task_name = "loop_task", // task will be created .task_name = "loop_task", // task will be created
.task_priority = uxTaskPriorityGet(NULL), .task_priority = uxTaskPriorityGet(NULL),
.task_stack_size = 2048, .task_stack_size = 3072,
.task_core_id = tskNO_AFFINITY .task_core_id = tskNO_AFFINITY
}; };
@ -115,9 +115,9 @@ void app_main(void)
ESP_LOGI(TAG, "starting event source"); ESP_LOGI(TAG, "starting event source");
// Create the event source task with the same priority as the current task // Create the event source task with the same priority as the current task
xTaskCreate(task_event_source, "task_event_source", 2048, NULL, uxTaskPriorityGet(NULL), NULL); xTaskCreate(task_event_source, "task_event_source", 3072, NULL, uxTaskPriorityGet(NULL), NULL);
ESP_LOGI(TAG, "starting application task"); ESP_LOGI(TAG, "starting application task");
// Create the application task with the same priority as the current task // Create the application task with the same priority as the current task
xTaskCreate(application_task, "application_task", 2048, NULL, uxTaskPriorityGet(NULL), NULL); xTaskCreate(application_task, "application_task", 3072, NULL, uxTaskPriorityGet(NULL), NULL);
} }

View File

@ -0,0 +1,37 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import pytest
from pytest_embedded import Dut
TASK_ITERATION_LIMIT = 10
TASK_ITERATION_POSTING = 'posting TASK_EVENTS:TASK_ITERATION_EVENT to {}, iteration {} out of ' + str(TASK_ITERATION_LIMIT)
TASK_ITERATION_HANDLING = 'handling TASK_EVENTS:TASK_ITERATION_EVENT from {}, iteration {}'
@pytest.mark.supported_targets
@pytest.mark.generic
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')

View File

@ -1,89 +0,0 @@
from __future__ import print_function
import re
import ttfw_idf
STARTING_TIMERS_REGEX = re.compile(r'Started timers, time since boot: (\d+) us')
# name, period, next_alarm, times_started, times_fired, times_skipped, cb_exec_time
TIMER_DUMP_LINE_REGEX = re.compile(r'([\w-]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)')
PERIODIC_TIMER_REGEX = re.compile(r'Periodic timer called, time since boot: (\d+) us')
LIGHT_SLEEP_ENTER_REGEX = re.compile(r'Entering light sleep for 0\.5s, time since boot: (\d+) us')
LIGHT_SLEEP_EXIT_REGEX = re.compile(r'Woke up from light sleep, time since boot: (\d+) us')
ONE_SHOT_REGEX = re.compile(r'One\-shot timer called, time since boot: (\d+) us')
RESTART_REGEX = re.compile(r'Restarted periodic timer with 1s period, time since boot: (\d+) us')
STOP_REGEX = re.compile(r'Stopped and deleted timers')
INITIAL_TIMER_PERIOD = 500000
FINAL_TIMER_PERIOD = 1000000
LIGHT_SLEEP_TIME = 500000
ONE_SHOT_TIMER_PERIOD = 5000000
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32','esp32s2','esp32c3','esp32s3'])
def test_examples_system_esp_timer(env, extra_data):
dut = env.get_dut('esp_timer_example', 'examples/system/esp_timer')
# start test
dut.start_app()
groups = dut.expect(STARTING_TIMERS_REGEX, timeout=30)
start_time = int(groups[0])
print('Start time: {} us'.format(start_time))
groups = dut.expect(TIMER_DUMP_LINE_REGEX, timeout=2)
assert(groups[0] == 'periodic' and int(groups[1]) == INITIAL_TIMER_PERIOD)
groups = dut.expect(TIMER_DUMP_LINE_REGEX, timeout=2)
assert(groups[0] == 'one-shot' and int(groups[1]) == 0)
for i in range(0, 5):
groups = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(groups[0])
diff = start_time + (i + 1) * INITIAL_TIMER_PERIOD - cur_time
print('Callback #{}, time: {} us, diff: {} us'.format(i, cur_time, diff))
assert(abs(diff) < 100)
groups = dut.expect(ONE_SHOT_REGEX, timeout=3)
one_shot_timer_time = int(groups[0])
diff = start_time + ONE_SHOT_TIMER_PERIOD - one_shot_timer_time
print('One-shot timer, time: {} us, diff: {}'.format(one_shot_timer_time, diff))
assert(abs(diff) < 220)
groups = dut.expect(RESTART_REGEX, timeout=3)
start_time = int(groups[0])
print('Timer restarted, time: {} us'.format(start_time))
for i in range(0, 5):
groups = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(groups[0])
diff = start_time + (i + 1) * FINAL_TIMER_PERIOD - cur_time
print('Callback #{}, time: {} us, diff: {} us'.format(i, cur_time, diff))
assert(abs(diff) < 100)
groups = dut.expect(LIGHT_SLEEP_ENTER_REGEX, timeout=2)
sleep_enter_time = int(groups[0])
groups = dut.expect(LIGHT_SLEEP_EXIT_REGEX, timeout=2)
sleep_exit_time = int(groups[0])
sleep_time = sleep_exit_time - sleep_enter_time
print('Enter sleep: {}, exit sleep: {}, slept: {}'.format(
sleep_enter_time, sleep_exit_time, sleep_time))
assert(abs(sleep_time - LIGHT_SLEEP_TIME) < 1000)
for i in range(5, 7):
groups = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(groups[0])
diff = abs(start_time + (i + 1) * FINAL_TIMER_PERIOD - cur_time)
print('Callback #{}, time: {} us, diff: {} us'.format(i, cur_time, diff))
assert(diff < 100)
dut.expect(STOP_REGEX, timeout=2)
if __name__ == '__main__':
test_examples_system_esp_timer()

View File

@ -0,0 +1,86 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import pytest
from pytest_embedded import Dut
STARTING_TIMERS_REGEX = r'Started timers, time since boot: (\d+) us'
# name, period, next_alarm, times_started, times_fired, times_skipped, cb_exec_time
TIMER_DUMP_LINE_REGEX = r'([\w-]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)'
PERIODIC_TIMER_REGEX = r'Periodic timer called, time since boot: (\d+) us'
LIGHT_SLEEP_ENTER_REGEX = r'Entering light sleep for 0\.5s, time since boot: (\d+) us'
LIGHT_SLEEP_EXIT_REGEX = r'Woke up from light sleep, time since boot: (\d+) us'
ONE_SHOT_REGEX = r'One\-shot timer called, time since boot: (\d+) us'
RESTART_REGEX = r'Restarted periodic timer with 1s period, time since boot: (\d+) us'
STOP_REGEX = r'Stopped and deleted timers'
INITIAL_TIMER_PERIOD = 500000
FINAL_TIMER_PERIOD = 1000000
LIGHT_SLEEP_TIME = 500000
ONE_SHOT_TIMER_PERIOD = 5000000
@pytest.mark.supported_targets
@pytest.mark.generic
def test_esp_timer(dut: Dut) -> None:
match = dut.expect(STARTING_TIMERS_REGEX)
start_time = int(match.group(1))
logging.info('Start time: {} us'.format(start_time))
match = dut.expect(TIMER_DUMP_LINE_REGEX, timeout=2)
assert(match.group(1).decode('utf8') == 'periodic' and int(match.group(2)) == INITIAL_TIMER_PERIOD)
match = dut.expect(TIMER_DUMP_LINE_REGEX, timeout=2)
assert(match.group(1).decode('utf8') == 'one-shot' and int(match.group(2)) == 0)
for i in range(0, 5):
match = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(match.group(1))
diff = start_time + (i + 1) * INITIAL_TIMER_PERIOD - cur_time
logging.info('Callback #{}, time: {} us, diff: {} us'.format(i, cur_time, diff))
assert(abs(diff) < 100)
match = dut.expect(ONE_SHOT_REGEX, timeout=3)
one_shot_timer_time = int(match.group(1))
diff = start_time + ONE_SHOT_TIMER_PERIOD - one_shot_timer_time
logging.info('One-shot timer, time: {} us, diff: {}'.format(one_shot_timer_time, diff))
assert(abs(diff) < 220)
match = dut.expect(RESTART_REGEX, timeout=3)
start_time = int(match.group(1))
logging.info('Timer restarted, time: {} us'.format(start_time))
for i in range(0, 5):
match = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(match.group(1))
diff = start_time + (i + 1) * FINAL_TIMER_PERIOD - cur_time
logging.info('Callback #{}, time: {} us, diff: {} us'.format(i, cur_time, diff))
assert(abs(diff) < 100)
match = dut.expect(LIGHT_SLEEP_ENTER_REGEX, timeout=2)
sleep_enter_time = int(match.group(1))
match = dut.expect(LIGHT_SLEEP_EXIT_REGEX, timeout=2)
sleep_exit_time = int(match.group(1))
sleep_time = sleep_exit_time - sleep_enter_time
logging.info('Enter sleep: {}, exit sleep: {}, slept: {}'.format(
sleep_enter_time, sleep_exit_time, sleep_time))
assert(abs(sleep_time - LIGHT_SLEEP_TIME) < 1000)
for i in range(5, 7):
match = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(match.group(1))
diff = abs(start_time + (i + 1) * FINAL_TIMER_PERIOD - cur_time)
logging.info('Callback #{}, time: {} us, diff: {} us'.format(i, cur_time, diff))
assert(diff < 100)
dut.expect(STOP_REGEX, timeout=2)

View File

@ -1,38 +0,0 @@
from __future__ import unicode_literals
import os
import ttfw_idf
from tiny_test_fw import Env, Utility
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC')
def test_examples_eventfd(env, extra_data):
# type: (Env, None) -> None
dut = env.get_dut('eventfd', 'examples/system/eventfd')
dut.start_app()
dut.expect('cpu_start: Starting scheduler', timeout=30)
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',
]
Utility.console_log('Expecting:{}{}'.format(os.linesep, os.linesep.join(exp_list_5seconds)))
dut.expect_all(*exp_list_5seconds, timeout=60)
Utility.console_log('Expecting:{}{}'.format(os.linesep, os.linesep.join(exp_list_10seconds)))
dut.expect_all(*exp_list_10seconds, timeout=60)
if __name__ == '__main__':
test_examples_eventfd()

View File

@ -0,0 +1,35 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import os
import pytest
from pytest_embedded import Dut
@pytest.mark.supported_targets
@pytest.mark.generic
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)

View File

@ -1,19 +0,0 @@
from __future__ import print_function
import ttfw_idf
STATS_TASK_ITERS = 3
STATS_TASK_EXPECT = 'Real time stats obtained'
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32c3'])
def test_real_time_stats_example(env, extra_data):
dut = env.get_dut('real_time_stats', 'examples/system/freertos/real_time_stats')
dut.start_app()
for iteration in range(0, STATS_TASK_ITERS):
dut.expect(STATS_TASK_EXPECT)
if __name__ == '__main__':
test_real_time_stats_example()

View File

@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.supported_targets
@pytest.mark.generic
def test_freertos_real_time_stats(dut: Dut) -> None:
for _ in range(0, 3):
dut.expect_exact('Real time stats obtained')

View File

@ -1,24 +0,0 @@
from __future__ import unicode_literals
import re
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='8Mpsram')
def test_examples_himem(env, extra_data):
dut = env.get_dut('himem', 'examples/system/himem')
dut.start_app()
mem = dut.expect(re.compile(r'esp_himem: Initialized. Using last \d+ 32KB address blocks for bank '
r'switching on (\d+) KB of physical memory.'), timeout=30)[0]
dut.expect_all(re.compile(r'Himem has {}KiB of memory, \d+KiB of which is free. '
r'Testing the free memory...'.format(mem)),
'Done!',
timeout=10)
if __name__ == '__main__':
test_examples_himem()

View File

@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.generic
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!')

View File

@ -1,28 +0,0 @@
from __future__ import unicode_literals
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32'])
def test_examples_ipc_isr(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None
dut = env.get_dut('ipc_isr', 'examples/system/ipc/ipc_isr')
dut.start_app()
dut.expect_all('example: Start',
'example: PS_INTLEVEL = 0x5',
'example: PS_EXCM = 0x0',
'example: PS_UM = 0x1',
'example: in[0] = 0x1',
'example: in[1] = 0x2',
'example: in[2] = 0x3',
'example: out[0] = (in[0] | in[1] | in[2]) = 0x3',
'example: out[1] = (in[0] & in[1] & in[2]) = 0x6',
'example: out[2] = in[2] = 0x3',
'example: out[3] = PS of other cpu = 0x25',
'example: End',
timeout=10)
if __name__ == '__main__':
test_examples_ipc_isr()

View File

@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s3
@pytest.mark.generic
def test_ipc_isr(dut: Dut) -> None:
dut.expect_exact('example: Start')
dut.expect_exact('example: PS_INTLEVEL = 0x5')
dut.expect_exact('example: PS_EXCM = 0x0')
dut.expect_exact('example: PS_UM = 0x1')
dut.expect_exact('example: in[0] = 0x1')
dut.expect_exact('example: in[1] = 0x2')
dut.expect_exact('example: in[2] = 0x3')
dut.expect_exact('example: out[0] = (in[0] | in[1] | in[2]) = 0x3')
dut.expect_exact('example: out[1] = (in[0] & in[1] & in[2]) = 0x6')
dut.expect_exact('example: out[2] = in[2] = 0x3')
dut.expect_exact('example: out[3] = PS of other cpu = 0x25')
dut.expect_exact('example: End')

View File

@ -1,67 +0,0 @@
from __future__ import print_function
import re
import time
import ttfw_idf
ENTERING_SLEEP_STR = 'Entering light sleep'
EXIT_SLEEP_REGEX = re.compile(r'Returned from light sleep, reason: (\w+), t=(\d+) ms, slept for (\d+) ms')
WAITING_FOR_GPIO_STR = re.compile(r'Waiting for GPIO\d to go high...')
WAKEUP_INTERVAL_MS = 2000
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32s2', 'esp32c3', 'esp32s3'])
def test_examples_system_light_sleep(env, extra_data):
dut = env.get_dut('light_sleep_example', 'examples/system/light_sleep')
dut.start_app()
# Ensure DTR and RTS are de-asserted for proper control of GPIO0
dut.port_inst.setDTR(False)
dut.port_inst.setRTS(False)
# enter sleep first time
dut.expect(ENTERING_SLEEP_STR, timeout=30)
# don't check timing here, might be cache dependent
dut.expect(EXIT_SLEEP_REGEX)
print('Got first sleep period')
# enter sleep second time
dut.expect(ENTERING_SLEEP_STR)
groups = dut.expect(EXIT_SLEEP_REGEX)
print('Got second sleep period, wakeup from {}, slept for {}'.format(groups[0], groups[2]))
# sleep time error should be less than 1ms
assert(groups[0] == 'timer' and int(groups[2]) >= WAKEUP_INTERVAL_MS - 1 and int(groups[2]) <= WAKEUP_INTERVAL_MS + 1)
# this time we'll test gpio wakeup
dut.expect(ENTERING_SLEEP_STR)
print('Pulling GPIO0 low using DTR')
dut.port_inst.setDTR(True)
time.sleep(1)
groups = dut.expect(EXIT_SLEEP_REGEX)
print('Got third sleep period, wakeup from {}, slept for {}'.format(groups[0], groups[2]))
assert(groups[0] == 'pin' and int(groups[2]) < WAKEUP_INTERVAL_MS)
dut.expect(WAITING_FOR_GPIO_STR)
print('Is waiting for GPIO...')
dut.port_inst.setDTR(False)
dut.expect(ENTERING_SLEEP_STR)
print('Went to sleep again')
# Write 'U' to uart, 'U' in ascii is 0x55 which contains 8 edges in total
dut.write('U')
time.sleep(1)
groups = dut.expect(EXIT_SLEEP_REGEX)
print('Got third sleep period, wakeup from {}, slept for {}'.format(groups[0], groups[2]))
assert(groups[0] == 'uart' and int(groups[2]) < WAKEUP_INTERVAL_MS)
print('Went to sleep again')
groups = dut.expect(EXIT_SLEEP_REGEX)
assert(groups[0] == 'timer' and int(groups[2]) >= WAKEUP_INTERVAL_MS - 1 and int(groups[2]) <= WAKEUP_INTERVAL_MS + 1)
print('Woke up from timer again')
if __name__ == '__main__':
test_examples_system_light_sleep()

View File

@ -0,0 +1,64 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import time
import pytest
from pytest_embedded import Dut
@pytest.mark.supported_targets
@pytest.mark.generic
def test_light_sleep(dut: Dut) -> None:
ENTERING_SLEEP_STR = 'Entering light sleep'
EXIT_SLEEP_REGEX = r'Returned from light sleep, reason: (\w+), t=(\d+) ms, slept for (\d+) ms'
WAITING_FOR_GPIO_STR = r'Waiting for GPIO\d to go high...'
WAKEUP_INTERVAL_MS = 2000
# Ensure DTR and RTS are de-asserted for proper control of GPIO0
dut.serial.proc.setDTR(False)
dut.serial.proc.setRTS(False)
# enter sleep first time
dut.expect_exact(ENTERING_SLEEP_STR, timeout=30)
# don't check timing here, might be cache dependent
dut.expect(EXIT_SLEEP_REGEX)
logging.info('Got first sleep period')
# enter sleep second time
dut.expect_exact(ENTERING_SLEEP_STR)
match = dut.expect(EXIT_SLEEP_REGEX)
logging.info('Got second sleep period, wakeup from {}, slept for {}'.format(match.group(1), match.group(3)))
# sleep time error should be less than 1ms
assert(match.group(1).decode('utf8') == 'timer' and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 1 and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1)
# this time we'll test gpio wakeup
dut.expect_exact(ENTERING_SLEEP_STR)
logging.info('Pulling GPIO0 low using DTR')
dut.serial.proc.setDTR(True)
time.sleep(1)
match = dut.expect(EXIT_SLEEP_REGEX)
logging.info('Got third sleep period, wakeup from {}, slept for {}'.format(match.group(1), match.group(3)))
assert(match.group(1).decode('utf8') == 'pin' and int(match.group(3)) < WAKEUP_INTERVAL_MS)
dut.expect(WAITING_FOR_GPIO_STR)
logging.info('Is waiting for GPIO...')
dut.serial.proc.setDTR(False)
dut.expect_exact(ENTERING_SLEEP_STR)
logging.info('Went to sleep again')
# Write 'U' to uart, 'U' in ascii is 0x55 which contains 8 edges in total
dut.write('U')
time.sleep(1)
match = dut.expect(EXIT_SLEEP_REGEX)
logging.info('Got third sleep period, wakeup from {}, slept for {}'.format(match.group(1), match.group(3)))
assert(match.group(1).decode('utf8') == 'uart' and int(match.group(3)) < WAKEUP_INTERVAL_MS)
logging.info('Went to sleep again')
match = dut.expect(EXIT_SLEEP_REGEX)
assert(match.group(1).decode('utf8') == 'timer' and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 1 and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1)
logging.info('Woke up from timer again')

View File

@ -1,20 +0,0 @@
from __future__ import unicode_literals
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32'])
def test_examples_perfmon(env, extra_data):
dut = env.get_dut('perfmon', 'examples/system/perfmon')
dut.start_app()
dut.expect_all('example: Start',
'example: Start test with printing all available statistic',
'example: Start test with user defined statistic',
'example: The End',
timeout=60)
if __name__ == '__main__':
test_examples_perfmon()

View File

@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.generic
def test_perfmon(dut: Dut) -> None:
dut.expect('example: Start')
dut.expect('example: Start test with printing all available statistic')
dut.expect('example: Start test with user defined statistic')
dut.expect('example: The End')

View File

@ -1,27 +0,0 @@
#!/usr/bin/env python
from __future__ import division, print_function, unicode_literals
import re
from typing import Any
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32s2', 'esp32c3'])
def test_examples_pthread(env, _): # type: (Any, Any) -> None
app_name = 'pthread'
dut = env.get_dut(app_name, 'examples/system/pthread')
dut.start_app()
# 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(re.compile(r'Created thread 0x[\da-f]+'))
dut.expect(re.compile(r'Created larger stack thread 0x[\da-f]+'))
dut.expect(r'Threads have exited')
dut.expect(re.compile(r'Created thread 0x[\da-f]+ with new default config'))
dut.expect('Thread has exited')
if __name__ == '__main__':
test_examples_pthread()

View File

@ -0,0 +1,18 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.supported_targets
@pytest.mark.generic
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')

View File

@ -1,19 +0,0 @@
from __future__ import unicode_literals
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32c3'])
def test_examples_task_watchdog(env, extra_data):
dut = env.get_dut('task_watchdog', 'examples/system/task_watchdog')
dut.start_app()
dut.expect_all('Initialize TWDT',
'Delay for 10 seconds', timeout=30)
dut.expect_all('Unsubscribing and deleting tasks',
'Complete', timeout=20)
if __name__ == '__main__':
test_examples_task_watchdog()

View File

@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.supported_targets
@pytest.mark.generic
def test_task_watchdog(dut: Dut) -> None:
dut.expect_exact('Initialize TWDT')
dut.expect_exact('Delay for 10 seconds')
dut.expect_exact('Unsubscribing and deleting tasks')
dut.expect_exact('Complete')

View File

@ -1,45 +0,0 @@
from __future__ import unicode_literals
import re
import time
import ttfw_idf
from tiny_test_fw import Utility
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32'])
def test_examples_ulp(env, extra_data):
dut = env.get_dut('ulp', 'examples/system/ulp_fsm/ulp')
dut.start_app()
dut.expect_all('Not ULP wakeup, initializing ULP',
'Entering deep sleep',
timeout=30)
def generate_gpio0_events():
for _ in range(5):
dut.port_inst.setDTR(True) # Pulling GPIO0 low using DTR
time.sleep(0.25)
dut.port_inst.setDTR(False)
time.sleep(0.25)
nvs_value = None
for _ in range(5):
generate_gpio0_events()
dut.expect('ULP wakeup, saving pulse count', timeout=5)
Utility.console_log('Woke up...')
init_count = int(dut.expect(re.compile(r'Read pulse count from NVS:\s+(\d+)'), timeout=5)[0], 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(re.compile(r'Pulse count from ULP:\s+(\d+)'), timeout=5)[0], 10)
assert inc in (5, 6), 'pulse count is {}'.format(inc)
new_count = int(dut.expect(re.compile(r'Wrote updated pulse count to NVS:\s+(\d+)'), timeout=5)[0], 10)
assert init_count + inc == new_count, '{} + {} != {}'.format(init_count, inc, new_count)
nvs_value = new_count
Utility.console_log('Pulse count written to NVS: {}. Entering deep sleep...'.format(nvs_value))
dut.expect('Entering deep sleep', timeout=5)
if __name__ == '__main__':
test_examples_ulp()

View File

@ -0,0 +1,43 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import time
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.generic
def test_ulp_fsm(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)

View File

@ -1,34 +0,0 @@
from __future__ import unicode_literals
import re
import ttfw_idf
from tiny_test_fw import Utility
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32'])
def test_examples_ulp_adc(env, extra_data):
dut = env.get_dut('ulp_adc', 'examples/system/ulp_fsm/ulp_adc')
dut.start_app()
dut.expect_all('Not ULP wakeup',
'Entering deep sleep',
timeout=30)
for _ in range(5):
dut.expect('Deep sleep wakeup', timeout=60)
measurements_str = dut.expect(re.compile(r'ULP did (\d+) measurements'), timeout=5)[0]
assert measurements_str is not None
measurements = int(measurements_str)
Utility.console_log('ULP did {} measurements'.format(measurements))
dut.expect('Thresholds: low=1500 high=2000', timeout=5)
value_str = dut.expect(re.compile(r'Value=(\d+) was (above|below) threshold'), timeout=5)[0]
assert value_str is not None
value = int(value_str)
Utility.console_log('Value {} was outside the boundaries'.format(value))
dut.expect('Entering deep sleep', timeout=60)
if __name__ == '__main__':
test_examples_ulp_adc()

View File

@ -0,0 +1,28 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.generic
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)

View File

@ -1,44 +0,0 @@
from __future__ import unicode_literals
import re
import tiny_test_fw
import ttfw_idf
from tiny_test_fw import DUT
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32s2'])
def test_examples_ulp_riscv(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument
dut = env.get_dut('ulp_riscv', 'examples/system/ulp_riscv/gpio')
dut.start_app()
dut.expect_all('Not a ULP-RISC-V wakeup, initializing it!',
'Entering in deep sleep',
timeout=30)
# Run two times to make sure device sleep
# and wake up properly
for i in range(0, 2):
# Set GPIO0 using DTR
dut.port_inst.setDTR(i % 2 == 0)
dut.expect('ULP-RISC-V woke up the main CPU!', timeout=5)
# Check GPIO state
state = 'Low' if i % 2 == 0 else 'High'
dut.expect(re.compile(r'ULP-RISC-V read changes in GPIO_0 current is: %s' % state), timeout=5)
# Go back to sleep
dut.expect('Entering in deep sleep', timeout=5)
try:
# We expect a timeout here, otherwise it means that
# the main CPU woke up unexpectedly!
dut.expect('ULP-RISC-V woke up the main CPU!', timeout=20)
raise Exception('Main CPU woke up unexpectedly!')
except DUT.ExpectTimeout:
pass
if __name__ == '__main__':
test_examples_ulp_riscv()

View File

@ -0,0 +1,37 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pexpect
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32s2
@pytest.mark.generic
def test_ulp_riscv_gpio(dut: Dut) -> None:
dut.expect_exact('Not a ULP-RISC-V wakeup, initializing it!')
dut.expect_exact('Entering in deep sleep')
# Run two times to make sure device sleep
# and wake up properly
for i in range(0, 2):
# Set GPIO0 using DTR
dut.serial.proc.setDTR(i % 2 == 0)
dut.expect_exact('ULP-RISC-V woke up the main CPU!', timeout=5)
# Check GPIO state
state = 'Low' if i % 2 == 0 else 'High'
dut.expect(r'ULP-RISC-V read changes in GPIO_0 current is: %s' % state, timeout=5)
# Go back to sleep
dut.expect_exact('Entering in deep sleep', timeout=5)
try:
# We expect a timeout here, otherwise it means that
# the main CPU woke up unexpectedly!
dut.expect('ULP-RISC-V woke up the main CPU!', timeout=20)
raise Exception('Main CPU woke up unexpectedly!')
except pexpect.exceptions.TIMEOUT:
pass

View File

@ -1,26 +0,0 @@
from __future__ import unicode_literals
import re
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32c3'])
def test_examples_unit_test(env, extra_data):
dut = env.get_dut('unit_test', 'examples/system/unit_test')
dut.start_app()
def get_reg_nums(number):
return re.compile(r'\d{1,2}\s+' * number)
dut.expect_all('In main application. Collecting 32 random numbers from 1 to 100:',
get_reg_nums(10),
get_reg_nums(10),
get_reg_nums(10),
get_reg_nums(2),
timeout=30)
if __name__ == '__main__':
test_examples_unit_test()

View File

@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.supported_targets
@pytest.mark.generic
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))