esp-test-utils 0.2.1__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/CHANGELOG.md +13 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/PKG-INFO +1 -1
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esp_test_utils.egg-info/PKG-INFO +1 -1
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esp_test_utils.egg-info/SOURCES.txt +3 -1
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/dut/dut_base.py +8 -2
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/dut/esp_mixin.py +11 -4
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/port/base_port.py +22 -7
- esp_test_utils-0.2.3/esptest/adapter/port/shell_port.py +191 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/config/env_config.py +38 -11
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/devices/esp_serial.py +11 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/tools/download_bin.py +1 -1
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/utility/parse_bin_path.py +8 -0
- esp_test_utils-0.2.3/tests/adapter/test_shell_port.py +94 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/test_EnvConfig.py +24 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/.github/.gitkeep +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/.github/workflows/pypi-publish.yml +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/.gitignore +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/.gitlab-ci.yml +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/.pre-commit-config.yaml +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/CONTRIBUTING.md +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/LICENSE +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/README.md +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/docs/Makefile +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/docs/conf.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/docs/index.rst +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/docs/make.bat +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esp_test_utils.egg-info/dependency_links.txt +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esp_test_utils.egg-info/entry_points.txt +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esp_test_utils.egg-info/requires.txt +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esp_test_utils.egg-info/top_level.txt +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/__main__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/dut/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/dut/create_dut.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/dut/esp_dut.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/dut/esp_port.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/dut/mac_mixin.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/dut/wrapper.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/port/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/adapter/port/serial_port.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/all.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/common/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/common/compat_typing.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/common/data_monitor.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/common/decorators.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/common/encoding.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/common/generator.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/common/shell.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/common/timestamp.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/config/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/config/default_config.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/db/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/db/runners.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/devices/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/devices/attenuator.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/devices/serial_dut.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/devices/serial_tools.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/env/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/env/base_env.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/env/wifi_env.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/esp_console/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/esp_console/wifi_cmd.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/interface/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/interface/dut.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/interface/port.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/iperf_utility/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/iperf_utility/iperf_results.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/iperf_utility/iperf_test.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/iperf_utility/iperf_test.test.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/iperf_utility/line_chart.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/logger/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/logger/logger.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/network/__init__.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/network/mac.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/network/netif.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/network/nic.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/scripts/downbin.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/scripts/list_ports.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/scripts/monitor.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/scripts/set_att.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/tools/copy_bin.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/tools/http_download.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/tools/pip_check.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/esptest/utility/gen_esp32part.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/example/jap_test.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/example/restart_test.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/pyproject.toml +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/setup.cfg +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/__init__.py +0 -0
- {esp_test_utils-0.2.1/tests → esp_test_utils-0.2.3/tests/adapter}/test_Dut.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/basic/test_decorators.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/basic/test_network.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/conftest.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/db/test_db_runners.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/esp_console/_files/wifi_cmd_connected_1.log +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/esp_console/_files/wifi_cmd_connected_2.log +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/esp_console/conftest.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/esp_console/test_WifiCmd.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/iperf_utility/_files/dut_iperf_rx1.log +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/iperf_utility/_files/dut_iperf_rx2.log +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/iperf_utility/_files/pc_iperf_rx.log +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/iperf_utility/_files/pc_iperf_rx2.log +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/iperf_utility/test_chart.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/iperf_utility/test_iperf_results.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/iperf_utility/test_iperf_util.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/test_common.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/test_import.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/tools/test_download_file.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/tools/test_pip_check.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/utility/_files/test-bin.zip +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/utility/_files/test-get-baud/ESP32AT-V4.1.1.0/sdkconfig +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/utility/test_parse_bin_path.py +0 -0
- {esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tools/ci/check_dev_version.py +0 -0
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## v0.2.3 (2025-11-14)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
- feat: add shell port support
|
|
5
|
+
- fix: Fix esptool connect to given port
|
|
6
|
+
- fix: log of env config search dirs
|
|
7
|
+
|
|
8
|
+
## v0.2.2 (2025-10-29)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
- feat: get test variables from shell env
|
|
12
|
+
- fix: flash esp32 option no-stub
|
|
13
|
+
|
|
1
14
|
## v0.2.1 (2025-09-24)
|
|
2
15
|
|
|
3
16
|
|
|
@@ -33,6 +33,7 @@ esptest/adapter/dut/wrapper.py
|
|
|
33
33
|
esptest/adapter/port/__init__.py
|
|
34
34
|
esptest/adapter/port/base_port.py
|
|
35
35
|
esptest/adapter/port/serial_port.py
|
|
36
|
+
esptest/adapter/port/shell_port.py
|
|
36
37
|
esptest/common/__init__.py
|
|
37
38
|
esptest/common/compat_typing.py
|
|
38
39
|
esptest/common/data_monitor.py
|
|
@@ -84,10 +85,11 @@ example/jap_test.py
|
|
|
84
85
|
example/restart_test.py
|
|
85
86
|
tests/__init__.py
|
|
86
87
|
tests/conftest.py
|
|
87
|
-
tests/test_Dut.py
|
|
88
88
|
tests/test_EnvConfig.py
|
|
89
89
|
tests/test_common.py
|
|
90
90
|
tests/test_import.py
|
|
91
|
+
tests/adapter/test_Dut.py
|
|
92
|
+
tests/adapter/test_shell_port.py
|
|
91
93
|
tests/basic/test_decorators.py
|
|
92
94
|
tests/basic/test_network.py
|
|
93
95
|
tests/db/test_db_runners.py
|
|
@@ -11,7 +11,7 @@ from esptool.loader import ESPLoader
|
|
|
11
11
|
|
|
12
12
|
import esptest.common.compat_typing as t
|
|
13
13
|
|
|
14
|
-
from ...common.timestamp import
|
|
14
|
+
from ...common.timestamp import timestamp_slug
|
|
15
15
|
from ...interface.dut import DutInterface
|
|
16
16
|
from ...interface.port import PortInterface
|
|
17
17
|
from ...logger import get_logger
|
|
@@ -62,7 +62,7 @@ class DutConfig:
|
|
|
62
62
|
self._auto_gen_name()
|
|
63
63
|
if not self.log_file:
|
|
64
64
|
_log_path = self.log_path or './dut_logs'
|
|
65
|
-
_file_name = f'{self.name}_{
|
|
65
|
+
_file_name = f'{self.name}_{timestamp_slug()}.log'.replace(':', '-')
|
|
66
66
|
self.log_file = str(Path(_log_path) / _file_name)
|
|
67
67
|
# serial configs
|
|
68
68
|
_serial_configs = DEFAULT_SERIAL_CONFIGS.copy()
|
|
@@ -229,6 +229,12 @@ class DutBase(VariablesMixin, DutInterface): # pylint: disable=too-many-public-
|
|
|
229
229
|
return self._base_port_proxy.raw_port
|
|
230
230
|
raise NotImplementedError()
|
|
231
231
|
|
|
232
|
+
@property
|
|
233
|
+
def log_file(self) -> t.Any:
|
|
234
|
+
if self._base_port_proxy:
|
|
235
|
+
return self._base_port_proxy.log_file
|
|
236
|
+
return None
|
|
237
|
+
|
|
232
238
|
@property
|
|
233
239
|
def name(self) -> t.Any:
|
|
234
240
|
return self.dut_config.name
|
|
@@ -51,15 +51,17 @@ class EspSerial:
|
|
|
51
51
|
|
|
52
52
|
class EspMixin(BaseProtocol):
|
|
53
53
|
def _esptool_open_port(self, port: str, initial_baud: int, **kwargs: t.Any) -> esptool.ESPLoader:
|
|
54
|
-
ports = [p.device for p in get_all_serial_ports()]
|
|
55
54
|
port = compute_serial_port(port) if port else ''
|
|
55
|
+
serial_list = [port] if port else [p.device for p in get_all_serial_ports()]
|
|
56
|
+
# esptool.get_default_connected_device always detect_chip from serial_list
|
|
56
57
|
esp = esptool.get_default_connected_device(
|
|
57
|
-
|
|
58
|
-
port,
|
|
58
|
+
serial_list,
|
|
59
|
+
port=port or None, # type: ignore
|
|
59
60
|
connect_attempts=3,
|
|
60
61
|
initial_baud=initial_baud,
|
|
61
62
|
chip=kwargs.get('chip', 'auto'),
|
|
62
63
|
)
|
|
64
|
+
assert esp, f'Failed to connect to {port}'
|
|
63
65
|
return esp
|
|
64
66
|
|
|
65
67
|
def _esptool_path(self, use_esptool: str = '') -> str:
|
|
@@ -95,7 +97,7 @@ class EspMixin(BaseProtocol):
|
|
|
95
97
|
esptool=self.dut_config.use_esptool,
|
|
96
98
|
erase_nvs=erase_nvs,
|
|
97
99
|
)
|
|
98
|
-
if not self.esp.IS_STUB:
|
|
100
|
+
if not self.esp.IS_STUB and self.esp.CHIP_NAME not in ['ESP32']:
|
|
99
101
|
# preview or dev targets
|
|
100
102
|
down_bin_tool.force_no_stub = True
|
|
101
103
|
with self.disable_redirect_thread():
|
|
@@ -105,6 +107,11 @@ class EspMixin(BaseProtocol):
|
|
|
105
107
|
def start_redirect_thread(self) -> None:
|
|
106
108
|
if self.esp:
|
|
107
109
|
self.esp._port.open() # pylint: disable=protected-access
|
|
110
|
+
if self.log_file:
|
|
111
|
+
with open(self.log_file, 'a', encoding='utf-8') as log_f:
|
|
112
|
+
log_f.write(
|
|
113
|
+
f'------------ reopen port: {self.esp._port.port} {self.esp._port.baudrate} --------------- \n' # pylint: disable=protected-access
|
|
114
|
+
)
|
|
108
115
|
super().start_redirect_thread()
|
|
109
116
|
|
|
110
117
|
def stop_redirect_thread(self) -> bool:
|
|
@@ -31,9 +31,12 @@ class RawPort(metaclass=abc.ABCMeta):
|
|
|
31
31
|
"""Define a minimum Dut class, the dut objects should at least support these methods
|
|
32
32
|
|
|
33
33
|
the dut should at least support these attributes:
|
|
34
|
-
- attribute name with type str
|
|
35
34
|
- method: write_bytes() with parameters: data[bytes]
|
|
36
35
|
- method: read_bytes() with parameters: timeout[float]
|
|
36
|
+
|
|
37
|
+
optional attribute & method:
|
|
38
|
+
- attribute: name with type str
|
|
39
|
+
- attribute: read_timeout with type float
|
|
37
40
|
"""
|
|
38
41
|
|
|
39
42
|
@classmethod
|
|
@@ -243,7 +246,11 @@ class PortSpawn(pexpect.spawnbase.SpawnBase, t.Generic[T]):
|
|
|
243
246
|
self._log(ret_data, 'read') # type: ignore
|
|
244
247
|
return ret_data
|
|
245
248
|
|
|
249
|
+
@deprecated('Should use close() for Spawn')
|
|
246
250
|
def stop(self) -> None:
|
|
251
|
+
self.close()
|
|
252
|
+
|
|
253
|
+
def close(self) -> None:
|
|
247
254
|
"""Stop and clean up"""
|
|
248
255
|
self.logger.debug(f'Stopping SerialSpawn {self.name}')
|
|
249
256
|
self._read_thread_stop_event.set()
|
|
@@ -359,7 +366,7 @@ class BasePort(PortInterface, t.Generic[T]):
|
|
|
359
366
|
if new_log_file == self._log_file:
|
|
360
367
|
return
|
|
361
368
|
if self._pexpect_spawn:
|
|
362
|
-
self._pexpect_spawn.
|
|
369
|
+
self._pexpect_spawn.log_file = new_log_file
|
|
363
370
|
self._log_file = new_log_file
|
|
364
371
|
|
|
365
372
|
@property
|
|
@@ -381,7 +388,7 @@ class BasePort(PortInterface, t.Generic[T]):
|
|
|
381
388
|
if not self._pexpect_spawn:
|
|
382
389
|
return False
|
|
383
390
|
self._init_log_file()
|
|
384
|
-
self._pexpect_spawn.
|
|
391
|
+
self._pexpect_spawn.close()
|
|
385
392
|
self._pexpect_spawn = None
|
|
386
393
|
return True
|
|
387
394
|
|
|
@@ -486,9 +493,13 @@ class BasePort(PortInterface, t.Generic[T]):
|
|
|
486
493
|
"""
|
|
487
494
|
buffer = b''
|
|
488
495
|
if flush:
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
496
|
+
# pexpect may return empty bytes if b'(.*)' is used
|
|
497
|
+
try:
|
|
498
|
+
match = self.expect(re.compile(b'(.+)', re.DOTALL), timeout=0)
|
|
499
|
+
assert match
|
|
500
|
+
buffer = match.group(0)
|
|
501
|
+
except TimeoutError:
|
|
502
|
+
pass
|
|
492
503
|
else:
|
|
493
504
|
# flush spawn buffer
|
|
494
505
|
assert self._pexpect_spawn
|
|
@@ -499,7 +510,11 @@ class BasePort(PortInterface, t.Generic[T]):
|
|
|
499
510
|
|
|
500
511
|
def close(self) -> None:
|
|
501
512
|
if self._close_redirect_thread_when_exit and self._pexpect_spawn:
|
|
502
|
-
self._pexpect_spawn.
|
|
513
|
+
self._pexpect_spawn.close()
|
|
514
|
+
if self.raw_port:
|
|
515
|
+
if hasattr(self.raw_port, 'close'):
|
|
516
|
+
assert callable(self.raw_port.close) # type: ignore
|
|
517
|
+
self.raw_port.close() # type: ignore
|
|
503
518
|
|
|
504
519
|
def __enter__(self) -> 't.Self':
|
|
505
520
|
return self
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
import pexpect
|
|
6
|
+
import psutil
|
|
7
|
+
|
|
8
|
+
import esptest.common.compat_typing as t
|
|
9
|
+
|
|
10
|
+
from ...logger import get_logger
|
|
11
|
+
from .base_port import BasePort, RawPort
|
|
12
|
+
|
|
13
|
+
logger = get_logger('shell_port')
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ShellRaw(RawPort):
|
|
17
|
+
"""A subprocess Raw Port class that supports shell read, write
|
|
18
|
+
|
|
19
|
+
is a subclass of RawPort
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, cmd: str = '/bin/bash', env: t.Optional[t.Dict[str, str]] = None) -> None:
|
|
23
|
+
self.env = env or os.environ.copy()
|
|
24
|
+
self.env['PYTHONUNBUFFERED'] = 'true' # for python scripts, disable output buffering
|
|
25
|
+
self.cmd = cmd
|
|
26
|
+
self.proc: t.Optional[subprocess.Popen] = None
|
|
27
|
+
self.read_timeout = 0.002 # default read_timeout
|
|
28
|
+
self.open()
|
|
29
|
+
|
|
30
|
+
def open(self) -> None:
|
|
31
|
+
if not self.proc:
|
|
32
|
+
self.proc = subprocess.Popen( # pylint: disable=consider-using-with
|
|
33
|
+
self.cmd,
|
|
34
|
+
shell=True,
|
|
35
|
+
env=self.env,
|
|
36
|
+
stdin=subprocess.PIPE,
|
|
37
|
+
stdout=subprocess.PIPE,
|
|
38
|
+
stderr=subprocess.STDOUT,
|
|
39
|
+
)
|
|
40
|
+
# Set stdout to non-blocking
|
|
41
|
+
os.set_blocking(self.proc.stdout.fileno(), False) # type: ignore
|
|
42
|
+
|
|
43
|
+
def close(self) -> None:
|
|
44
|
+
"""Close subprocess."""
|
|
45
|
+
if self.proc:
|
|
46
|
+
if self.proc.pid:
|
|
47
|
+
try:
|
|
48
|
+
proc = psutil.Process(self.proc.pid)
|
|
49
|
+
for child in proc.children(recursive=True):
|
|
50
|
+
child.kill()
|
|
51
|
+
proc.kill()
|
|
52
|
+
time.sleep(0.01)
|
|
53
|
+
except psutil.Error:
|
|
54
|
+
pass
|
|
55
|
+
# # Unix / Linux - does not work
|
|
56
|
+
# try:
|
|
57
|
+
# os.killpg(self.proc.pid, signal.SIGTERM) # send SIGTERM to all in the group
|
|
58
|
+
# os.killpg(self.proc.pid, signal.SIGKILL) # send SIGTERM to all in the group
|
|
59
|
+
# except ProcessLookupError:
|
|
60
|
+
# pass
|
|
61
|
+
self.proc.terminate()
|
|
62
|
+
self.proc.kill()
|
|
63
|
+
self.proc.wait()
|
|
64
|
+
logger.info(f'shell command [{self.cmd}] was killed')
|
|
65
|
+
self.proc = None
|
|
66
|
+
|
|
67
|
+
def write_bytes(self, data: bytes) -> None:
|
|
68
|
+
"""Write bytes to subprocess stdin."""
|
|
69
|
+
if self.proc:
|
|
70
|
+
self.proc.stdin.write(data) # type: ignore
|
|
71
|
+
self.proc.stdin.flush() # type: ignore
|
|
72
|
+
return
|
|
73
|
+
raise ValueError('Subprocess not initialized.')
|
|
74
|
+
|
|
75
|
+
def read_bytes(self, timeout: float = 0) -> bytes:
|
|
76
|
+
"""blocking read bytes"""
|
|
77
|
+
data = self.read_bytes_nonblocking()
|
|
78
|
+
if not data and timeout > 0:
|
|
79
|
+
time.sleep(timeout) # blocking read
|
|
80
|
+
data = self.read_bytes_nonblocking()
|
|
81
|
+
if data:
|
|
82
|
+
logger.debug(f'[{self.cmd}] read_bytes timeout={timeout}, data={str(data)}')
|
|
83
|
+
return data
|
|
84
|
+
|
|
85
|
+
def read_bytes_nonblocking(self, size: int = -1) -> bytes:
|
|
86
|
+
"""non-blocking read bytes"""
|
|
87
|
+
if self.proc:
|
|
88
|
+
self.proc.stdout.flush() # type: ignore
|
|
89
|
+
return self.proc.stdout.read(size) # type: ignore
|
|
90
|
+
return b''
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class ShellPort(BasePort[ShellRaw]):
|
|
94
|
+
"""A combined port class that supports shell read, write, expect"""
|
|
95
|
+
|
|
96
|
+
def __init__(
|
|
97
|
+
self,
|
|
98
|
+
cmd: str = '/bin/bash',
|
|
99
|
+
env: t.Optional[dict[str, str]] = None,
|
|
100
|
+
name: str = '',
|
|
101
|
+
log_file: str = '',
|
|
102
|
+
**kwargs: t.Any,
|
|
103
|
+
) -> None:
|
|
104
|
+
raw_port = ShellRaw(cmd=cmd, env=env)
|
|
105
|
+
super().__init__(raw_port, name, log_file, **kwargs)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class InvalidRaw(RawPort):
|
|
109
|
+
"""A invalid Raw Port class that always raise NotImplementedError to pass type check"""
|
|
110
|
+
|
|
111
|
+
def write_bytes(self, data: bytes) -> None:
|
|
112
|
+
"""Write bytes to subprocess stdin."""
|
|
113
|
+
raise NotImplementedError('Invalid Raw Port.')
|
|
114
|
+
|
|
115
|
+
def read_bytes(self, timeout: float = 0) -> bytes:
|
|
116
|
+
"""blocking read bytes"""
|
|
117
|
+
raise NotImplementedError('Invalid Raw Port.')
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class PexpectPort(BasePort[InvalidRaw]):
|
|
121
|
+
"""A pexpect Port class that supports shell read, write, expect
|
|
122
|
+
|
|
123
|
+
based on pexpect.spawn but use different expect method
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
def __init__(
|
|
127
|
+
self,
|
|
128
|
+
cmd: str = '/bin/bash',
|
|
129
|
+
name: str = '',
|
|
130
|
+
log_file: str = '',
|
|
131
|
+
**kwargs: t.Any,
|
|
132
|
+
) -> None:
|
|
133
|
+
self._cmd = cmd
|
|
134
|
+
raw_port = InvalidRaw()
|
|
135
|
+
self._pexpect_spawn: t.Optional[pexpect.spawn] = None # change type
|
|
136
|
+
self.log_file_f = open(log_file, 'wb') if log_file else None # pylint: disable=consider-using-with
|
|
137
|
+
super().__init__(raw_port, name, log_file, **kwargs)
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def log_file(self) -> str:
|
|
141
|
+
"""Get Current dut log file."""
|
|
142
|
+
if not self._log_file:
|
|
143
|
+
return ''
|
|
144
|
+
return os.path.abspath(self._log_file)
|
|
145
|
+
|
|
146
|
+
@log_file.setter
|
|
147
|
+
def log_file(self, new_log_file: str) -> None:
|
|
148
|
+
"""Set Current dut log file."""
|
|
149
|
+
if new_log_file == self._log_file:
|
|
150
|
+
return
|
|
151
|
+
if self.log_file_f:
|
|
152
|
+
if self._pexpect_spawn:
|
|
153
|
+
self._pexpect_spawn.logfile = None # type: ignore
|
|
154
|
+
self.log_file_f.close()
|
|
155
|
+
if self._pexpect_spawn:
|
|
156
|
+
self.log_file_f = open(new_log_file, 'wb') if new_log_file else None # pylint: disable=consider-using-with
|
|
157
|
+
self._pexpect_spawn.logfile = self.log_file_f # type: ignore
|
|
158
|
+
self._log_file = new_log_file
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def spawn(self) -> t.Optional[pexpect.spawn]: # type: ignore
|
|
162
|
+
"""Allow the use of pexpect spawn enhancements, if pexpect process is available"""
|
|
163
|
+
return self._pexpect_spawn
|
|
164
|
+
|
|
165
|
+
def start_redirect_thread(self) -> None:
|
|
166
|
+
"""Start a new thread to read data from port and save to data cache."""
|
|
167
|
+
if self._pexpect_spawn:
|
|
168
|
+
return
|
|
169
|
+
self._init_log_file()
|
|
170
|
+
env = os.environ.copy()
|
|
171
|
+
env['PYTHONUNBUFFERED'] = 'true' # for python scripts, disable output buffering
|
|
172
|
+
self._pexpect_spawn = pexpect.spawn(self._cmd, maxread=8192, echo=False, env=env) # type: ignore
|
|
173
|
+
self._pexpect_spawn.logfile = self.log_file_f # type: ignore
|
|
174
|
+
# self._pexpect_spawn.delaybeforesend = 0.001
|
|
175
|
+
|
|
176
|
+
def stop_redirect_thread(self) -> bool:
|
|
177
|
+
"""Stop the redirect thread and pexpect process."""
|
|
178
|
+
if not self._pexpect_spawn:
|
|
179
|
+
return False
|
|
180
|
+
self._init_log_file()
|
|
181
|
+
self._pexpect_spawn.close()
|
|
182
|
+
self._pexpect_spawn = None # type: ignore
|
|
183
|
+
return True
|
|
184
|
+
|
|
185
|
+
def close(self) -> None:
|
|
186
|
+
"""Close pexpect process."""
|
|
187
|
+
super().close()
|
|
188
|
+
self.stop_redirect_thread()
|
|
189
|
+
if self.log_file_f:
|
|
190
|
+
self.log_file_f.close()
|
|
191
|
+
self.log_file_f = None
|
|
@@ -5,6 +5,30 @@ from typing import Any, List, Optional
|
|
|
5
5
|
|
|
6
6
|
import yaml
|
|
7
7
|
|
|
8
|
+
VAR_NAME_MAPPING = {
|
|
9
|
+
'ap_ssid': ['RUNNER_WIFI_SSID', 'RUNNER_AP_SSID'],
|
|
10
|
+
'ap_password': ['RUNNER_WIFI_PASSWORD', 'RUNNER_AP_PASSWORD'],
|
|
11
|
+
'pc_nic': ['RUNNER_PC_NIC'],
|
|
12
|
+
'dut1': ['ESPPORT1'],
|
|
13
|
+
'dut2': ['ESPPORT2'],
|
|
14
|
+
'dut3': ['ESPPORT3'],
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_variable_from_env(key: str) -> Any:
|
|
19
|
+
"""Get test variable from shell environment
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
key (str): which variable to get
|
|
23
|
+
"""
|
|
24
|
+
if key in VAR_NAME_MAPPING:
|
|
25
|
+
for var_name in VAR_NAME_MAPPING[key]:
|
|
26
|
+
var = os.getenv(var_name)
|
|
27
|
+
if var is not None:
|
|
28
|
+
logging.debug(f'Got env variable from shell env {var_name}: {var}')
|
|
29
|
+
return var
|
|
30
|
+
return None
|
|
31
|
+
|
|
8
32
|
|
|
9
33
|
class EnvConfig:
|
|
10
34
|
"""Get test environment variables from config file.
|
|
@@ -32,6 +56,8 @@ class EnvConfig:
|
|
|
32
56
|
# Find env config file from project root path
|
|
33
57
|
# CI_PROJECT_DIR was set by gitlab CI
|
|
34
58
|
PROJECT_ROOT_DIR = os.getenv('PROJECT_ROOT_DIR') or os.getenv('CI_PROJECT_DIR', '')
|
|
59
|
+
# allow EnvConfig load shell env variables, default enabled
|
|
60
|
+
DISABLE_LOAD_SHELL_ENV = os.getenv('ESPTEST_DISABLE_LOAD_SHELL_ENV', '').lower() in ('true', '1', 'yes', 'y')
|
|
35
61
|
|
|
36
62
|
# Allow input variables from terminal during local debugging
|
|
37
63
|
ALLOW_INPUT = not os.getenv('CI')
|
|
@@ -87,10 +113,7 @@ class EnvConfig:
|
|
|
87
113
|
continue
|
|
88
114
|
config_file = os.path.join(_dir, cls.ENV_CONFIG_FILE_BASE_NAME)
|
|
89
115
|
if not config_file:
|
|
90
|
-
_msg = (
|
|
91
|
-
'Can not find env config file from:\n ',
|
|
92
|
-
' \n'.join(cls._search_dirs()),
|
|
93
|
-
)
|
|
116
|
+
_msg = 'Can not find env config file from:\n ' + ' \n'.join(cls._search_dirs())
|
|
94
117
|
logging.warning(_msg)
|
|
95
118
|
if not cls.ALLOW_INPUT:
|
|
96
119
|
raise FileNotFoundError(f'Could not find config file: {cls.ENV_CONFIG_FILE_BASE_NAME}')
|
|
@@ -115,14 +138,18 @@ class EnvConfig:
|
|
|
115
138
|
# do not use dict.get because we can input the variable for local tests
|
|
116
139
|
if key in self.config_data:
|
|
117
140
|
var = self.config_data[key]
|
|
118
|
-
elif default:
|
|
141
|
+
elif default is not None:
|
|
119
142
|
var = default
|
|
120
143
|
else:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
144
|
+
if not self.DISABLE_LOAD_SHELL_ENV:
|
|
145
|
+
# Try to get from shell environment variables
|
|
146
|
+
var = get_variable_from_env(key)
|
|
147
|
+
if var is None:
|
|
148
|
+
logging.warning(f'Failed to get env variable {self.env_tag}/{key}.')
|
|
149
|
+
logging.info(self.__doc__)
|
|
150
|
+
if not self.ALLOW_INPUT:
|
|
151
|
+
raise ValueError(f'Env variable not found: {self.env_tag}/{key}')
|
|
152
|
+
# For local test, support input the variable from console
|
|
153
|
+
var = input('You can input the variable now:')
|
|
127
154
|
logging.debug(f'Got env variable {self.env_tag}/{key}: {var}')
|
|
128
155
|
return var
|
|
@@ -84,3 +84,14 @@ def list_all_esp_ports() -> t.List[EspPortInfo]:
|
|
|
84
84
|
for port in get_all_serial_ports():
|
|
85
85
|
esp_ports.append(detect_one_port(port))
|
|
86
86
|
return esp_ports
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def get_available_ports(target: str, max_num: int = 0) -> t.List[EspPortInfo]:
|
|
90
|
+
detect_ports = []
|
|
91
|
+
for port in get_all_serial_ports():
|
|
92
|
+
esp_port = detect_one_port(port)
|
|
93
|
+
if esp_port.target == target:
|
|
94
|
+
detect_ports.append(esp_port)
|
|
95
|
+
if max_num > 0 and len(detect_ports) >= max_num: # pylint: disable=chained-comparison
|
|
96
|
+
return detect_ports
|
|
97
|
+
return detect_ports
|
|
@@ -77,7 +77,7 @@ class DownBinTool:
|
|
|
77
77
|
parttool: str = '',
|
|
78
78
|
esptool: str = '',
|
|
79
79
|
erase_nvs: bool = True,
|
|
80
|
-
force_no_stub: bool =
|
|
80
|
+
force_no_stub: bool = False,
|
|
81
81
|
): # pylint: disable=too-many-positional-arguments,too-many-arguments
|
|
82
82
|
self.bin_path = bin_path
|
|
83
83
|
self.port = compute_serial_port(port, strict=True)
|
|
@@ -4,6 +4,7 @@ import os
|
|
|
4
4
|
import subprocess
|
|
5
5
|
import tempfile
|
|
6
6
|
from dataclasses import dataclass
|
|
7
|
+
from functools import lru_cache
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
|
|
9
10
|
import esptest.common.compat_typing as t
|
|
@@ -181,6 +182,7 @@ class ParseBinPath:
|
|
|
181
182
|
except subprocess.SubprocessError as e:
|
|
182
183
|
logger.error(f'Failed to gen partition-table.csv: {str(e)}')
|
|
183
184
|
|
|
185
|
+
@lru_cache()
|
|
184
186
|
def parse_partitions(self) -> t.List[PartitionInfo]:
|
|
185
187
|
"""Parse partitions from partition-table.csv"""
|
|
186
188
|
self._gen_partition_table()
|
|
@@ -293,3 +295,9 @@ class ParseBinPath:
|
|
|
293
295
|
# erase nvs
|
|
294
296
|
return args + list(self._gen_erase_nvs_bin())
|
|
295
297
|
raise ValueError('Can not find nvs partition info')
|
|
298
|
+
|
|
299
|
+
def get_partition_info(self, part_name: str) -> PartitionInfo:
|
|
300
|
+
for part in self.parse_partitions():
|
|
301
|
+
if part.name == part_name:
|
|
302
|
+
return part
|
|
303
|
+
raise ValueError('Can not find nvs partition info')
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import random
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
4
|
+
import time
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from esptest.adapter.port.shell_port import PexpectPort, ShellPort, ShellRaw
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_shell_raw_open_close() -> None:
|
|
13
|
+
ran_int = random.randint(12345678, 87654321)
|
|
14
|
+
raw_port = ShellRaw(cmd=f'sleep {ran_int}')
|
|
15
|
+
assert raw_port.proc is not None
|
|
16
|
+
output = subprocess.check_output(f'ps -ef | grep {ran_int}', shell=True).decode('utf-8')
|
|
17
|
+
assert f'sleep {ran_int}' in output
|
|
18
|
+
raw_port.close()
|
|
19
|
+
output = subprocess.check_output(f'ps -ef | grep {ran_int}', shell=True).decode('utf-8')
|
|
20
|
+
assert f'sleep {ran_int}' not in output
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_shell_port_open_close() -> None:
|
|
24
|
+
ran_int = random.randint(12345678, 87654321)
|
|
25
|
+
# close by close method
|
|
26
|
+
port = ShellPort(cmd=f'sleep {ran_int}')
|
|
27
|
+
assert isinstance(port.raw_port, ShellRaw)
|
|
28
|
+
output = subprocess.check_output(f'ps -ef | grep {ran_int}', shell=True).decode('utf-8')
|
|
29
|
+
assert f'sleep {ran_int}' in output
|
|
30
|
+
port.close()
|
|
31
|
+
output = subprocess.check_output(f'ps -ef | grep {ran_int}', shell=True).decode('utf-8')
|
|
32
|
+
assert f'sleep {ran_int}' not in output
|
|
33
|
+
# close by with statement
|
|
34
|
+
with ShellPort(cmd=f'sleep {ran_int}') as port:
|
|
35
|
+
assert isinstance(port.raw_port, ShellRaw)
|
|
36
|
+
output = subprocess.check_output(f'ps -ef | grep {ran_int}', shell=True).decode('utf-8')
|
|
37
|
+
assert f'sleep {ran_int}' in output
|
|
38
|
+
output = subprocess.check_output(f'ps -ef | grep {ran_int}', shell=True).decode('utf-8')
|
|
39
|
+
assert f'sleep {ran_int}' not in output
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_shell_port_read_write() -> None:
|
|
43
|
+
with ShellPort(cmd='/bin/bash') as port:
|
|
44
|
+
port.write_line('echo hello')
|
|
45
|
+
time.sleep(0.1) # wait for the receive thread
|
|
46
|
+
assert 'hello' in port.read_all_data()
|
|
47
|
+
port.write_line('sleep 0.1 && echo world')
|
|
48
|
+
assert 'world' not in port.read_all_data()
|
|
49
|
+
match = port.expect(re.compile('world'))
|
|
50
|
+
assert match.group(0) == 'world'
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_shell_port_logfile(tmp_path: Path) -> None:
|
|
54
|
+
log_file = tmp_path / 'shell_port1.log'
|
|
55
|
+
with ShellPort(cmd='/bin/bash', log_file=str(log_file)) as port:
|
|
56
|
+
port.write_line('echo hello')
|
|
57
|
+
time.sleep(0.1) # wait for the receive thread
|
|
58
|
+
with open(str(log_file), 'r') as f:
|
|
59
|
+
assert 'hello' in f.read()
|
|
60
|
+
port.log_file = str(tmp_path / 'shell_port2.log')
|
|
61
|
+
port.write_line('echo world')
|
|
62
|
+
time.sleep(0.1) # wait for the receive thread
|
|
63
|
+
with open(str(tmp_path / 'shell_port2.log'), 'r') as f:
|
|
64
|
+
assert 'world' in f.read()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_pexpect_spawn_port_read_write() -> None:
|
|
68
|
+
with PexpectPort(cmd='/bin/bash') as port:
|
|
69
|
+
port.write_line('echo hello')
|
|
70
|
+
time.sleep(0.5) # wait for the receive thread
|
|
71
|
+
assert 'hello' in port.read_all_data()
|
|
72
|
+
port.write_line('sleep 0.1 && echo world')
|
|
73
|
+
assert 'world' not in port.read_all_data()
|
|
74
|
+
match = port.expect(re.compile('world'))
|
|
75
|
+
assert match.group(0) == 'world'
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_pexpect_spawn_port_logfile(tmp_path: Path) -> None:
|
|
79
|
+
log_file = tmp_path / 'shell_port1.log'
|
|
80
|
+
with PexpectPort(cmd='/bin/bash', log_file=str(log_file)) as port:
|
|
81
|
+
port.write_line('echo hello')
|
|
82
|
+
time.sleep(0.5) # wait for the receive thread
|
|
83
|
+
with open(str(log_file), 'r') as f:
|
|
84
|
+
assert 'hello' in f.read()
|
|
85
|
+
port.log_file = str(tmp_path / 'shell_port2.log')
|
|
86
|
+
port.write_line('echo world')
|
|
87
|
+
time.sleep(0.1) # wait for the receive thread
|
|
88
|
+
with open(str(tmp_path / 'shell_port2.log'), 'r') as f:
|
|
89
|
+
assert 'world' in f.read()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == '__main__':
|
|
93
|
+
# Breakpoints do not work with coverage, disable coverage for debugging
|
|
94
|
+
pytest.main([__file__, '--no-cov', '--log-cli-level=DEBUG'])
|
|
@@ -65,6 +65,30 @@ def test_env_config_get_var(tmp_path: Path) -> None:
|
|
|
65
65
|
env_config.get_variable('dut_port')
|
|
66
66
|
|
|
67
67
|
|
|
68
|
+
def test_env_config_from_shell_env(tmp_path: Path) -> None:
|
|
69
|
+
# Test Get variable from console
|
|
70
|
+
config_file = tmp_path / 'not_exist_config.yml'
|
|
71
|
+
env = {
|
|
72
|
+
'TEST_ENV_CONFIG_FILE': str(config_file),
|
|
73
|
+
}
|
|
74
|
+
with reload_envconfig(env):
|
|
75
|
+
try:
|
|
76
|
+
os.environ.pop('RUNNER_WIFI_SSID')
|
|
77
|
+
except KeyError:
|
|
78
|
+
pass
|
|
79
|
+
try:
|
|
80
|
+
os.environ.pop('RUNNER_AP_SSID')
|
|
81
|
+
except KeyError:
|
|
82
|
+
pass
|
|
83
|
+
env_config = EnvConfig()
|
|
84
|
+
env_config.ALLOW_INPUT = False
|
|
85
|
+
with pytest.raises(ValueError):
|
|
86
|
+
var = env_config.get_variable('ap_ssid')
|
|
87
|
+
os.environ['RUNNER_AP_SSID'] = 'ssid_from_env'
|
|
88
|
+
var = env_config.get_variable('ap_ssid')
|
|
89
|
+
assert var == 'ssid_from_env'
|
|
90
|
+
|
|
91
|
+
|
|
68
92
|
def test_env_config_from_console(tmp_path, monkeypatch): # type: ignore
|
|
69
93
|
# Test Get variable from console
|
|
70
94
|
config_file = tmp_path / 'not_exist_config.yml'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/esp_console/_files/wifi_cmd_connected_1.log
RENAMED
|
File without changes
|
{esp_test_utils-0.2.1 → esp_test_utils-0.2.3}/tests/esp_console/_files/wifi_cmd_connected_2.log
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|