Merge pull request #170636 from Synthetica9/wait_before_entry

nixos/test-driver: add wait_before_entry

authored by Jacek Galowicz and committed by GitHub 9938dec6 58236ec8

+37 -8
+14
nixos/lib/test-driver/test_driver/driver.py
··· 220 res = driver.polling_conditions.pop() 221 assert res is self.condition 222 223 if fun_ is None: 224 return Poll 225 else:
··· 220 res = driver.polling_conditions.pop() 221 assert res is self.condition 222 223 + def wait(self, timeout: int = 900) -> None: 224 + def condition(last: bool) -> bool: 225 + if last: 226 + rootlog.info(f"Last chance for {self.condition.description}") 227 + ret = self.condition.check(force=True) 228 + if not ret and not last: 229 + rootlog.info( 230 + f"({self.condition.description} failure not fatal yet)" 231 + ) 232 + return ret 233 + 234 + with rootlog.nested(f"waiting for {self.condition.description}"): 235 + retry(condition, timeout=timeout) 236 + 237 if fun_ is None: 238 return Poll 239 else:
+22 -7
nixos/lib/test-driver/test_driver/polling_condition.py
··· 1 from typing import Callable, Optional 2 import time 3 4 from .logger import rootlog ··· 14 description: Optional[str] 15 16 last_called: float 17 - entered: bool 18 19 def __init__( 20 self, ··· 34 self.description = str(description) 35 36 self.last_called = float("-inf") 37 - self.entered = False 38 39 - def check(self) -> bool: 40 - if self.entered or not self.overdue: 41 return True 42 43 with self, rootlog.nested(self.nested_message): 44 - rootlog.info(f"Time since last: {time.monotonic() - self.last_called:.2f}s") 45 try: 46 res = self.condition() # type: ignore 47 except Exception: ··· 69 def overdue(self) -> bool: 70 return self.last_called + self.seconds_interval < time.monotonic() 71 72 def __enter__(self) -> None: 73 - self.entered = True 74 75 def __exit__(self, exc_type, exc_value, traceback) -> None: # type: ignore 76 - self.entered = False 77 self.last_called = time.monotonic()
··· 1 from typing import Callable, Optional 2 + from math import isfinite 3 import time 4 5 from .logger import rootlog ··· 15 description: Optional[str] 16 17 last_called: float 18 + entry_count: int 19 20 def __init__( 21 self, ··· 35 self.description = str(description) 36 37 self.last_called = float("-inf") 38 + self.entry_count = 0 39 40 + def check(self, force: bool = False) -> bool: 41 + if (self.entered or not self.overdue) and not force: 42 return True 43 44 with self, rootlog.nested(self.nested_message): 45 + time_since_last = time.monotonic() - self.last_called 46 + last_message = ( 47 + f"Time since last: {time_since_last:.2f}s" 48 + if isfinite(time_since_last) 49 + else "(not called yet)" 50 + ) 51 + 52 + rootlog.info(last_message) 53 try: 54 res = self.condition() # type: ignore 55 except Exception: ··· 77 def overdue(self) -> bool: 78 return self.last_called + self.seconds_interval < time.monotonic() 79 80 + @property 81 + def entered(self) -> bool: 82 + # entry_count should never dip *below* zero 83 + assert self.entry_count >= 0 84 + return self.entry_count > 0 85 + 86 def __enter__(self) -> None: 87 + self.entry_count += 1 88 89 def __exit__(self, exc_type, exc_value, traceback) -> None: # type: ignore 90 + assert self.entered 91 + self.entry_count -= 1 92 self.last_called = time.monotonic()
+1 -1
nixos/tests/vscodium.nix
··· 49 start_all() 50 51 machine.wait_for_unit('graphical.target') 52 - machine.wait_until_succeeds('pgrep -x codium') 53 54 with codium_running: 55 # Wait until vscodium is visible. "File" is in the menu bar. 56 machine.wait_for_text('Get Started')
··· 49 start_all() 50 51 machine.wait_for_unit('graphical.target') 52 53 + codium_running.wait() 54 with codium_running: 55 # Wait until vscodium is visible. "File" is in the menu bar. 56 machine.wait_for_text('Get Started')