diff --git a/tools/ci/python_packages/tiny_test_fw/bin/example.py b/tools/ci/python_packages/tiny_test_fw/bin/example.py index c4348bf34..238d3561c 100644 --- a/tools/ci/python_packages/tiny_test_fw/bin/example.py +++ b/tools/ci/python_packages/tiny_test_fw/bin/example.py @@ -14,24 +14,12 @@ """ example of writing test with TinyTestFW """ import re -import os -import sys -try: - import TinyFW -except ImportError: - # if we want to run test case outside `tiny-test-fw` folder, - # we need to insert tiny-test-fw path into sys path - test_fw_path = os.getenv("TEST_FW_PATH") - if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - import TinyFW - -import IDF -from IDF.IDFDUT import ESP32DUT +import ttfw_idf +from tiny_test_fw import TinyFW -@IDF.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_https_request(env, extra_data): """ steps: | @@ -39,7 +27,7 @@ def test_examples_protocol_https_request(env, extra_data): 2. connect to www.howsmyssl.com:443 3. send http request """ - dut1 = env.get_dut("https_request", "examples/protocols/https_request", dut_class=ESP32DUT) + dut1 = env.get_dut("https_request", "examples/protocols/https_request", dut_class=ttfw_idf.ESP32DUT) dut1.start_app() dut1.expect(re.compile(r"Connecting to www.howsmyssl.com:443"), timeout=30) dut1.expect("Performing the SSL/TLS handshake") @@ -51,5 +39,5 @@ def test_examples_protocol_https_request(env, extra_data): if __name__ == '__main__': - TinyFW.set_default_config(env_config_file="EnvConfigTemplate.yml", dut=IDF.IDFDUT) + TinyFW.set_default_config(env_config_file="EnvConfigTemplate.yml", dut=ttfw_idf.IDFDUT) test_examples_protocol_https_request() diff --git a/tools/ci/python_packages/ttfw_idf/IDFDUT.py b/tools/ci/python_packages/ttfw_idf/IDFDUT.py index 2665d1c36..bd4764853 100644 --- a/tools/ci/python_packages/ttfw_idf/IDFDUT.py +++ b/tools/ci/python_packages/ttfw_idf/IDFDUT.py @@ -21,6 +21,7 @@ import functools import tempfile import subprocess import time +import pexpect # python2 and python3 queue package name is different try: @@ -419,6 +420,7 @@ class IDFDUT(DUT.SerialDUT): class ESP32DUT(IDFDUT): TARGET = "esp32" TOOLCHAIN_PREFIX = "xtensa-esp32-elf-" + @classmethod def _get_rom(cls): return esptool.ESP32ROM @@ -427,6 +429,7 @@ class ESP32DUT(IDFDUT): class ESP32S2DUT(IDFDUT): TARGET = "esp32s2beta" TOOLCHAIN_PREFIX = "xtensa-esp32s2-elf-" + @classmethod def _get_rom(cls): return esptool.ESP32S2ROM @@ -435,19 +438,22 @@ class ESP32S2DUT(IDFDUT): class ESP8266DUT(IDFDUT): TARGET = "esp8266" TOOLCHAIN_PREFIX = "xtensa-lx106-elf-" + @classmethod def _get_rom(cls): return esptool.ESP8266ROM def get_target_by_rom_class(cls): - for c in [ESP32DUT, ESP32S2DUT, ESP8266DUT]: + for c in [ESP32DUT, ESP32S2DUT, ESP8266DUT, IDFQEMUDUT]: if c._get_rom() == cls: return c.TARGET return None class IDFQEMUDUT(IDFDUT): + TARGET = None + TOOLCHAIN_PREFIX = None ERASE_NVS = True DEFAULT_EXPECT_TIMEOUT = 30 # longer timeout, since app startup takes more time in QEMU (due to slow SHA emulation) QEMU_SERIAL_PORT = 3334 @@ -465,17 +471,15 @@ class IDFQEMUDUT(IDFDUT): "-drive", "file={},if=mtd,format=raw".format(self.flash_image.name), "-nic", "user,model=open_eth", "-serial", "tcp::{},server,nowait".format(self.QEMU_SERIAL_PORT), - # FIXME: generate a temporary efuse binary, pass it to QEMU - ] + "-S", + "-global driver=timer.esp32.timg,property=wdt_disable,value=true"] + # TODO(IDF-1242): generate a temporary efuse binary, pass it to QEMU if "QEMU_BIOS_PATH" in os.environ: - args += [ "-L", os.environ["QEMU_BIOS_PATH"] ] - - self.qemu = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=sys.stdout, stderr=subprocess.STDOUT) - - # FIXME: wait for QEMU to start up by interacting with its monitor - time.sleep(1) + args += ["-L", os.environ["QEMU_BIOS_PATH"]] + self.qemu = pexpect.spawn(" ".join(args), timeout=self.DEFAULT_EXPECT_TIMEOUT) + self.qemu.expect_exact(b"(qemu)") super(IDFQEMUDUT, self).__init__(name, port, log_file, app, allow_dut_exception=allow_dut_exception, **kwargs) def _write_flash_img(self): @@ -488,29 +492,34 @@ class IDFQEMUDUT(IDFDUT): self.flash_image.write(contents) self.flash_image.flush() + @classmethod + def _get_rom(cls): + return esptool.ESP32ROM + @classmethod def get_mac(cls, app, port): - # FIXME: get this from QEMU somehow(?) + # TODO(IDF-1242): get this from QEMU/efuse binary return "11:22:33:44:55:66" @classmethod - def confirm_dut(cls, port, app, **kwargs): + def confirm_dut(cls, port, **kwargs): return True, cls.TARGET def start_app(self, erase_nvs=ERASE_NVS): # TODO: implement erase_nvs # since the flash image is generated every time in the constructor, maybe this isn't needed... - self.reset() + self.qemu.sendline(b"cont\n") + self.qemu.expect_exact(b"(qemu)") def reset(self): - self.qemu.stdin.write("system_reset\n") - time.sleep(1) + self.qemu.sendline(b"system_reset\n") + self.qemu.expect_exact(b"(qemu)") def erase_partition(self, partition): - pass + raise NotImplementedError("method not erase_partition not implemented") def dump_flush(self, output_file, **kwargs): - pass + raise NotImplementedError("method not dump_flush not implemented") @classmethod def list_available_ports(cls): @@ -518,7 +527,16 @@ class IDFQEMUDUT(IDFDUT): def close(self): super(IDFQEMUDUT, self).close() - self.qemu.kill() + self.qemu.sendline(b"q\n") + self.qemu.expect_exact(b"(qemu)") + for _ in range(self.DEFAULT_EXPECT_TIMEOUT): + if not self.qemu.isalive(): + break + time.sleep(1) + else: + self.qemu.terminate(force=True) + class ESP32QEMUDUT(IDFQEMUDUT): TARGET = "esp32" + TOOLCHAIN_PREFIX = "xtensa-esp32-elf-" diff --git a/tools/ci/python_packages/ttfw_idf/__init__.py b/tools/ci/python_packages/ttfw_idf/__init__.py index 8c72047d5..8d7f4df63 100644 --- a/tools/ci/python_packages/ttfw_idf/__init__.py +++ b/tools/ci/python_packages/ttfw_idf/__init__.py @@ -16,7 +16,7 @@ import re from tiny_test_fw import TinyFW, Utility from IDFApp import IDFApp, Example, LoadableElfExample, UT # noqa: export all Apps for users -from IDFDUT import IDFDUT, ESP32DUT, ESP32S2DUT, ESP8266DUT # noqa: export DUTs for users +from IDFDUT import IDFDUT, ESP32DUT, ESP32S2DUT, ESP8266DUT, ESP32QEMUDUT # noqa: export DUTs for users def format_case_id(chip, case_name):