Skip to content

TC-SU-2.2: Interactive timeout extension for physical device testing#72628

Draft
khodya wants to merge 17 commits into
project-chip:masterfrom
khodya:extended_timeouts
Draft

TC-SU-2.2: Interactive timeout extension for physical device testing#72628
khodya wants to merge 17 commits into
project-chip:masterfrom
khodya:extended_timeouts

Conversation

@khodya

@khodya khodya commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

When TC_SU_2_2.py runs against a real device, OTA transfer, apply, and reboot durations are unpredictable. This PR replaces hardcoded waits with an extensible timeout system that prompts the operator in interactive sessions and fails fast in CI.

New: PromptCoordinator (matter/testing/prompt_coordinator.py)

  • Serializes concurrent timeout prompts via a threading lock so multiple timed-out steps don't race to stdin
  • Tracks total time spent waiting/prompting and subtracts it from the overall test wall clock (total_prompt_seconds)
  • In non-interactive (CI) environments returns False immediately without printing anything

Per-step timeout callbacks (event_attribute_reporting.py)

  • await_all_expected_report_matches and await_first_value_asserting_no_forbidden accept an optional on_timeout callback and extension_sec parameter
  • On timeout the callback is invoked; returning True extends the deadline, False fails the test

Overall test supervisor (decorators.py)

  • Background daemon thread tracks effective elapsed time (wall time minus prompt time)
  • On timeout, calls PromptCoordinator.ask_user; user can extend or abort
  • Abort cancels the asyncio task and converts CancelledError into a test failure

MatterBaseTest.make_timeout_callback() (matter_testing.py)

  • Convenience helper that wires a step label to the shared PromptCoordinator

TC_SU_2_2.py changes:

  • default_timeout = 3600 (CI uses --timeout 2100 explicitly)
  • Per-step timeouts configurable via --int-arg: step5_transfer_timeout_sec, step5_apply_timeout_sec, step5_reboot_timeout_sec, step6_query_timeout_sec, timeout_extension_sec
  • Reboot reconnect loop is extensible (prompts operator instead of hard-failing)

Testing

  • 17 unit tests in matter/testing/test_prompt_coordinator.py covering non-interactive mode, interactive yes/no/extend flows, concurrent serialization, per-step callback extension and abort, and the
    overall supervisor — all passing

@github-actions github-actions Bot added the tests label Jun 17, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an interactive timeout prompt coordinator (PromptCoordinator) to serialize timeout prompts and track paused time during interactive Matter testing, updating test decorators, subscription handlers, and test cases accordingly. The review feedback highlights several critical improvements: utilizing time.monotonic() instead of time.time() to ensure robust elapsed time calculations against system clock adjustments, checking for a None value on sys.stdin to prevent potential AttributeErrors, and optimizing the supervisor thread in decorators.py with a threading.Event to eliminate a redundant 2-second delay on successful test completions.

Comment on lines +252 to +302
async def _run_with_interactive_timeout(coro, timeout_sec: float, coordinator) -> object:
"""Run coro with an interactive overall-timeout supervisor.

A background thread counts down ``timeout_sec`` of *effective* elapsed time
(wall time minus time spent in prompts via the coordinator). When the deadline
is hit in non-interactive mode the task is cancelled immediately; in interactive
mode the user is asked whether to extend or abort.

``asyncio.CancelledError`` that results from an "abort" choice is caught here and
converted to a clean Mobly test-failure signal so the test runner never sees an
unhandled cancellation.
"""
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(coro)
current_timeout = [float(timeout_sec)]
wall_start = time.time()

def _supervisor():
while not task.done():
time.sleep(5.0)
if task.done():
break
wall_elapsed = time.time() - wall_start
effective = wall_elapsed - coordinator.total_prompt_seconds
if effective < current_timeout[0]:
continue

def still_needed(): return (time.time() - wall_start - coordinator.total_prompt_seconds) >= current_timeout[0]
extended = coordinator.ask_user(
description=f"Overall test timeout ({current_timeout[0]:.0f}s) reached",
elapsed_sec=effective,
extension_sec=current_timeout[0],
still_needed=still_needed,
)
if extended:
current_timeout[0] += current_timeout[0]
else:
loop.call_soon_threadsafe(task.cancel)
return

sv_thread = threading.Thread(target=_supervisor, daemon=True, name="timeout-supervisor")
sv_thread.start()

try:
return await task
except asyncio.CancelledError:
asserts.fail(
f"Test aborted by user after overall timeout ({timeout_sec:.0f}s)."
)
finally:
sv_thread.join(timeout=2.0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Efficiency & Correctness Issues

  1. Efficiency (2.0s delay on every test): The supervisor thread uses time.sleep(5.0) in a loop. When a test finishes successfully, the thread is likely still sleeping. The main thread's finally block calls sv_thread.join(timeout=2.0), which blocks the main thread for up to 2.0 seconds on every single successful test run. We can eliminate this delay entirely by using a threading.Event to interrupt the sleep immediately.
  2. Correctness (Clock adjustments): Using time.time() for measuring elapsed time is vulnerable to system clock changes (e.g., NTP sync). We should use time.monotonic() instead.
  3. Correctness (Redundant prompts): The still_needed lambda should check not task.done() to avoid prompting the user if the task has already completed while waiting for the lock.
async def _run_with_interactive_timeout(coro, timeout_sec: float, coordinator) -> object:
    """Run coro with an interactive overall-timeout supervisor.

    A background thread counts down ``timeout_sec`` of *effective* elapsed time
    (wall time minus time spent in prompts via the coordinator).  When the deadline
    is hit in non-interactive mode the task is cancelled immediately; in interactive
    mode the user is asked whether to extend or abort.

    ``asyncio.CancelledError`` that results from an "abort" choice is caught here and
    converted to a clean Mobly test-failure signal so the test runner never sees an
    unhandled cancellation.
    """
    loop = asyncio.get_event_loop()
    task = asyncio.ensure_future(coro)
    current_timeout = [float(timeout_sec)]
    wall_start = time.monotonic()
    exit_event = threading.Event()

    def _supervisor():
        while not exit_event.wait(timeout=5.0):
            if task.done():
                break
            wall_elapsed = time.monotonic() - wall_start
            effective = wall_elapsed - coordinator.total_prompt_seconds
            if effective < current_timeout[0]:
                continue

            still_needed = lambda: not task.done() and (time.monotonic() - wall_start - coordinator.total_prompt_seconds) >= current_timeout[0]
            extended = coordinator.ask_user(
                description=f"Overall test timeout ({current_timeout[0]:.0f}s) reached",
                elapsed_sec=effective,
                extension_sec=current_timeout[0],
                still_needed=still_needed,
            )
            if extended:
                current_timeout[0] += current_timeout[0]
            else:
                loop.call_soon_threadsafe(task.cancel)
                return

    sv_thread = threading.Thread(target=_supervisor, daemon=True, name="timeout-supervisor")
    sv_thread.start()

    try:
        return await task
    except asyncio.CancelledError:
        asserts.fail(
            f"Test aborted by user after overall timeout ({timeout_sec:.0f}s)."
        )
    finally:
        exit_event.set()
        sv_thread.join(timeout=2.0)

Comment on lines +50 to +52
@property
def is_interactive(self) -> bool:
return sys.stdin.isatty()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Defensive programming: sys.stdin can be None in certain environments (e.g., when run under some daemon managers or GUI wrappers). We should check if sys.stdin is not None before calling isatty() to prevent an AttributeError.

Suggested change
@property
def is_interactive(self) -> bool:
return sys.stdin.isatty()
@property
def is_interactive(self) -> bool:
return sys.stdin is not None and sys.stdin.isatty()

Comment on lines +88 to +107
t_wait_start = time.time()
self._lock.acquire()
wait_time = time.time() - t_wait_start
self._add_prompt_time(wait_time)

try:
if still_needed is not None and not still_needed():
# The timeout was resolved while we were waiting for the lock.
return True

prompt_start = time.time()
print(
f"\n⏱ Timeout: {description}\n"
f" Elapsed: {elapsed_sec:.0f}s — extend by {extension_sec:.0f}s? "
f"[y]es / [n]o (abort): ",
end="",
flush=True,
)
answer = sys.stdin.readline().strip().lower()
self._add_prompt_time(time.time() - prompt_start)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use time.monotonic() instead of time.time() for measuring elapsed time and intervals. time.time() is subject to system clock adjustments (e.g., NTP sync), which can cause incorrect calculations or flaky behavior.

Suggested change
t_wait_start = time.time()
self._lock.acquire()
wait_time = time.time() - t_wait_start
self._add_prompt_time(wait_time)
try:
if still_needed is not None and not still_needed():
# The timeout was resolved while we were waiting for the lock.
return True
prompt_start = time.time()
print(
f"\n⏱ Timeout: {description}\n"
f" Elapsed: {elapsed_sec:.0f}s — extend by {extension_sec:.0f}s? "
f"[y]es / [n]o (abort): ",
end="",
flush=True,
)
answer = sys.stdin.readline().strip().lower()
self._add_prompt_time(time.time() - prompt_start)
t_wait_start = time.monotonic()
self._lock.acquire()
wait_time = time.monotonic() - t_wait_start
self._add_prompt_time(wait_time)
try:
if still_needed is not None and not still_needed():
# The timeout was resolved while we were waiting for the lock.
return True
prompt_start = time.monotonic()
print(
f"\n⏱ Timeout: {description}\n"
f" Elapsed: {elapsed_sec:.0f}s — extend by {extension_sec:.0f}s? "
f"[y]es / [n]o (abort): ",
end="",
flush=True,
)
answer = sys.stdin.readline().strip().lower()
self._add_prompt_time(time.monotonic() - prompt_start)

Comment on lines +924 to +938
reboot_deadline_sec = s5_reboot_timeout_sec
reboot_start = time.time()
attempt = 0

while True:
await asyncio.sleep(poll_interval_sec)
attempt += 1
try:
await controller.GetConnectedDevice(
requestor_node_id, allowPASE=False, timeoutMs=reconnect_timeout_ms)
reconnected = True
logger.info('%s: Step #5.6 - DUT reconnected after OTA reboot (attempt %s).', step_number_s5, attempt + 1)
logger.info(f'{step_number_s5}: Step #5.6 - DUT reconnected after OTA reboot (attempt {attempt}).')
break
except (TimeoutError, ChipDeviceCtrl.ChipStackError):
logger.info('%s: Step #5.6 - Waiting for DUT to come back online (attempt %s/%s)...',
step_number_s5, attempt + 1, reboot_timeout_sec // poll_interval_sec)
elapsed = time.time() - reboot_start

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use time.monotonic() instead of time.time() for measuring elapsed time and intervals. time.time() is subject to system clock adjustments (e.g., NTP sync), which can cause incorrect calculations or flaky behavior.

Suggested change
reboot_deadline_sec = s5_reboot_timeout_sec
reboot_start = time.time()
attempt = 0
while True:
await asyncio.sleep(poll_interval_sec)
attempt += 1
try:
await controller.GetConnectedDevice(
requestor_node_id, allowPASE=False, timeoutMs=reconnect_timeout_ms)
reconnected = True
logger.info('%s: Step #5.6 - DUT reconnected after OTA reboot (attempt %s).', step_number_s5, attempt + 1)
logger.info(f'{step_number_s5}: Step #5.6 - DUT reconnected after OTA reboot (attempt {attempt}).')
break
except (TimeoutError, ChipDeviceCtrl.ChipStackError):
logger.info('%s: Step #5.6 - Waiting for DUT to come back online (attempt %s/%s)...',
step_number_s5, attempt + 1, reboot_timeout_sec // poll_interval_sec)
elapsed = time.time() - reboot_start
reboot_deadline_sec = s5_reboot_timeout_sec
reboot_start = time.monotonic()
attempt = 0
while True:
await asyncio.sleep(poll_interval_sec)
attempt += 1
try:
await controller.GetConnectedDevice(
requestor_node_id, allowPASE=False, timeoutMs=reconnect_timeout_ms)
reconnected = True
logger.info(f'{step_number_s5}: Step #5.6 - DUT reconnected after OTA reboot (attempt {attempt}).')
break
except (TimeoutError, ChipDeviceCtrl.ChipStackError):
elapsed = time.monotonic() - reboot_start

Comment on lines +475 to +485
matchers_list = list(expected_matchers)
start_time = time.time()
elapsed = 0.0
time_remaining = timeout_sec

report_matches: dict[int, bool] = {idx: False for idx, _ in enumerate(expected_matchers)}

for matcher in expected_matchers:
LOGGER.info("--> Matcher waiting: %s", matcher.description)
LOGGER.info("Waiting for %.1f seconds for all reports.", timeout_sec)

while time_remaining > 0:
while True:
elapsed = time.time() - start_time
time_remaining = timeout_sec - elapsed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use time.monotonic() instead of time.time() for measuring elapsed time and intervals. time.time() is subject to system clock adjustments (e.g., NTP sync), which can cause incorrect calculations or flaky behavior.

Suggested change
matchers_list = list(expected_matchers)
start_time = time.time()
elapsed = 0.0
time_remaining = timeout_sec
report_matches: dict[int, bool] = {idx: False for idx, _ in enumerate(expected_matchers)}
for matcher in expected_matchers:
LOGGER.info("--> Matcher waiting: %s", matcher.description)
LOGGER.info("Waiting for %.1f seconds for all reports.", timeout_sec)
while time_remaining > 0:
while True:
elapsed = time.time() - start_time
time_remaining = timeout_sec - elapsed
matchers_list = list(expected_matchers)
start_time = time.monotonic()
report_matches: dict[int, bool] = {idx: False for idx, _ in enumerate(expected_matchers)}
for matcher in expected_matchers:
LOGGER.info("--> Matcher waiting: %s", matcher.description)
LOGGER.info("Waiting for %.1f seconds for all reports.", timeout_sec)
while True:
elapsed = time.monotonic() - start_time
time_remaining = timeout_sec - elapsed

@github-actions

Copy link
Copy Markdown

PR #72628: Size comparison from ff91326 to 8e99fac

Full report (21 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, nrfconnect, psoc6, qpg, realtek, stm32)
platform target config section ff91326 8e99fac change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094776 1094776 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1106092 1106092 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593880 1593880 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057750 1057750 0 0.0
RAM 108525 108525 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896424 896424 0 0.0
RAM 105908 105908 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 777280 777280 0 0.0
RAM 103404 103404 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 790024 790024 0 0.0
RAM 108684 108684 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 739272 739272 0 0.0
RAM 97612 97612 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719444 719444 0 0.0
RAM 97644 97644 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 569574 569574 0 0.0
RAM 205112 205112 0 0.0
lock CC3235SF_LAUNCHXL FLASH 597126 597126 0 0.0
RAM 205272 205272 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 835024 835024 0 0.0
RAM 157693 157693 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1737772 1737772 0 0.0
RAM 215412 215412 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1626452 1626452 0 0.0
RAM 211604 211604 0 0.0
light cy8ckit_062s2_43012 FLASH 1470764 1470764 0 0.0
RAM 197436 197436 0 0.0
lock cy8ckit_062s2_43012 FLASH 1504212 1504212 0 0.0
RAM 225268 225268 0 0.0
qpg lighting-app qpg6200+debug FLASH 842996 842996 0 0.0
RAM 127908 127908 0 0.0
lock-app qpg6200+debug FLASH 782896 782896 0 0.0
RAM 118840 118840 0 0.0
realtek light-switch-app rtl8777g FLASH 689240 689240 0 0.0
RAM 101780 101780 0 0.0
lighting-app rtl8777g FLASH 730184 730184 0 0.0
RAM 102052 102052 0 0.0
stm32 light STM32WB5MM-DK FLASH 478892 478892 0 0.0
RAM 141492 141492 0 0.0

@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.06%. Comparing base (ff91326) to head (e64c89b).

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #72628   +/-   ##
=======================================
  Coverage   56.06%   56.06%           
=======================================
  Files        1640     1640           
  Lines      112575   112575           
  Branches    13353    13353           
=======================================
  Hits        63110    63110           
  Misses      49465    49465           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown

PR #72628: Size comparison from ff91326 to f20b2fb

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section ff91326 f20b2fb change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094776 1094776 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1106092 1106092 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593880 1593880 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057750 1057750 0 0.0
RAM 108525 108525 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896424 896424 0 0.0
RAM 105908 105908 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 777280 777280 0 0.0
RAM 103404 103404 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 790024 790024 0 0.0
RAM 108684 108684 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 739272 739272 0 0.0
RAM 97612 97612 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719444 719444 0 0.0
RAM 97644 97644 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 569574 569574 0 0.0
RAM 205112 205112 0 0.0
lock CC3235SF_LAUNCHXL FLASH 597126 597126 0 0.0
RAM 205272 205272 0 0.0
efr32 lighting-app BRD4187C FLASH 1094828 1094828 0 0.0
RAM 135256 135256 0 0.0
lock-app BRD4187C FLASH 994752 994752 0 0.0
RAM 131292 131292 0 0.0
BRD4338a FLASH 799713 799713 0 0.0
RAM 243432 243432 0 0.0
esp32 all-clusters-app c3devkit DRAM 99876 99876 0 0.0
FLASH 1624426 1624426 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 835024 835024 0 0.0
RAM 157693 157693 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1737772 1737772 0 0.0
RAM 215412 215412 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1626452 1626452 0 0.0
RAM 211604 211604 0 0.0
light cy8ckit_062s2_43012 FLASH 1470764 1470764 0 0.0
RAM 197436 197436 0 0.0
lock cy8ckit_062s2_43012 FLASH 1504212 1504212 0 0.0
RAM 225268 225268 0 0.0
qpg lighting-app qpg6200+debug FLASH 842996 842996 0 0.0
RAM 127908 127908 0 0.0
lock-app qpg6200+debug FLASH 782896 782896 0 0.0
RAM 118840 118840 0 0.0
realtek light-switch-app rtl8777g FLASH 689240 689240 0 0.0
RAM 101780 101780 0 0.0
lighting-app rtl8777g FLASH 730184 730184 0 0.0
RAM 102052 102052 0 0.0
stm32 light STM32WB5MM-DK FLASH 478892 478892 0 0.0
RAM 141492 141492 0 0.0
telink all-devices-app tl7218x FLASH 843192 843192 0 0.0
RAM 99092 99092 0 0.0
tlsr9118bdk40d FLASH 634558 634558 0 0.0
RAM 120224 120224 0 0.0
bridge-app tl7218x FLASH 734030 734030 0 0.0
RAM 97700 97700 0 0.0
light-app-ota-compress-lzma-factory-data tl3218x FLASH 800560 800560 0 0.0
RAM 42380 42380 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl7218x FLASH 845700 845700 0 0.0
RAM 101492 101492 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 734520 734520 0 0.0
RAM 57816 57816 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795582 795582 0 0.0
RAM 75176 75176 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 734436 734436 0 0.0
RAM 34472 34472 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 615092 615092 0 0.0
RAM 118508 118508 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841648 841652 4 0.0
RAM 97376 97376 0 0.0

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown

PR #72628: Size comparison from ff91326 to e64c89b

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section ff91326 e64c89b change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094776 1094776 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1106092 1106092 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593880 1593880 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057750 1057750 0 0.0
RAM 108525 108525 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896424 896424 0 0.0
RAM 105908 105908 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 777280 777280 0 0.0
RAM 103404 103404 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 790024 790024 0 0.0
RAM 108684 108684 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 739272 739272 0 0.0
RAM 97612 97612 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719444 719444 0 0.0
RAM 97644 97644 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 569574 569574 0 0.0
RAM 205112 205112 0 0.0
lock CC3235SF_LAUNCHXL FLASH 597126 597126 0 0.0
RAM 205272 205272 0 0.0
efr32 lighting-app BRD4187C FLASH 1094828 1094828 0 0.0
RAM 135256 135256 0 0.0
lock-app BRD4187C FLASH 994752 994752 0 0.0
RAM 131292 131292 0 0.0
BRD4338a FLASH 799713 799713 0 0.0
RAM 243432 243432 0 0.0
esp32 all-clusters-app c3devkit DRAM 99876 99876 0 0.0
FLASH 1624426 1624426 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 835024 835024 0 0.0
RAM 157693 157693 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1737772 1737772 0 0.0
RAM 215412 215412 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1626452 1626452 0 0.0
RAM 211604 211604 0 0.0
light cy8ckit_062s2_43012 FLASH 1470764 1470764 0 0.0
RAM 197436 197436 0 0.0
lock cy8ckit_062s2_43012 FLASH 1504212 1504212 0 0.0
RAM 225268 225268 0 0.0
qpg lighting-app qpg6200+debug FLASH 842996 842996 0 0.0
RAM 127908 127908 0 0.0
lock-app qpg6200+debug FLASH 782896 782896 0 0.0
RAM 118840 118840 0 0.0
realtek light-switch-app rtl8777g FLASH 689240 689240 0 0.0
RAM 101780 101780 0 0.0
lighting-app rtl8777g FLASH 730184 730184 0 0.0
RAM 102052 102052 0 0.0
stm32 light STM32WB5MM-DK FLASH 478892 478892 0 0.0
RAM 141492 141492 0 0.0
telink all-devices-app tl7218x FLASH 843192 843192 0 0.0
RAM 99092 99092 0 0.0
tlsr9118bdk40d FLASH 634558 634558 0 0.0
RAM 120224 120224 0 0.0
bridge-app tl7218x FLASH 734030 734030 0 0.0
RAM 97700 97700 0 0.0
light-app-ota-compress-lzma-factory-data tl3218x FLASH 800560 800560 0 0.0
RAM 42380 42380 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl7218x FLASH 845700 845700 0 0.0
RAM 101492 101492 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 734520 734520 0 0.0
RAM 57816 57816 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795582 795582 0 0.0
RAM 75176 75176 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 734436 734436 0 0.0
RAM 34472 34472 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 615092 615092 0 0.0
RAM 118508 118508 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841648 841652 4 0.0
RAM 97376 97376 0 0.0

@jtrejoespinoza-grid jtrejoespinoza-grid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. I think the implementation could be improved a bit but overall looks good.

print(
f"\n⏱ Timeout: {description}\n"
f" Elapsed: {elapsed_sec:.0f}s — extend by {extension_sec:.0f}s? "
f"[y]es / [n]o (abort): ",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks a bit hard to read, using Mayus [Y]es/[N]o is easier to read also it does not matter as the code already strips and lower the text.


prompt_start = time.time()
print(
f"\n⏱ Timeout: {description}\n"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: not sure is we should use these Symbols like "Clock".

self._prompt_coordinator = PromptCoordinator()
return self._prompt_coordinator

def make_timeout_callback(self, description: str, extension_sec: float = 600.0) -> Callable:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I see this method is here because it uses self.prompt_coordinator.ask_user but this methods looks like it should be in the file: event_attribute_reporting.py as is especific to be used only with the methods in that file.

# --int-arg ota_provider_port:5541
# --timeout 2100
# factory-reset: true
# quiet: false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to quiet: true. This to be able to see the real status in the Nigthly job and not just logs from the tests. If you open the logs Nightly at the test TC_SU_2_2 you will notice is not possible to verify without difficulty the real status of the test.

# --int-arg ota_provider_port:5541
# --timeout 2100
# factory-reset: true
# quiet: false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# quiet: true

Update this to true to avoid having a lot of logs in the execution report that not allow us to see the real reason of what caused the test to fail.

)

subscription_attr_applying.await_all_expected_report_matches([matcher_applying_obj], timeout_sec=800.0)
subscription_attr_applying.await_all_expected_report_matches(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a comment here about the implementation: In this scenario the Download is on Progress and if the method reaches the end of the timeout it ask for more time to wait for the kApplying state as many times the tester think is needed. But the problem I notice is the test just informs the kApplying State has not been reached and wait more time but we do not know if the download was stuck at 10% or 20% or at 98%. Would not be better to check for the download to reach maybe 98% or 99% (UpdateProgess) and then wait for the kApplying State. In that way the descriptor will tell the user where the Download was when the timeout was reached. Probably in that way the test can also decrease also the extension_sec as it can be repeated multiple times if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants