From b71b0f710f441cbfa2cb792320c1ecebafba7484 Mon Sep 17 00:00:00 2001 From: Artem Iglikov Date: Sun, 21 May 2017 18:24:42 +0100 Subject: [PATCH] Make start timeout work properly. self.alive is an RPC call, which can take a long time (e.g. 45s) if there are problems with communicating to server. Previously the loop was being executed exactly timeout * 10 times befor timing out, resulting in 450s timeout instead of the requested value. Now it is executed only until current timestamp is larger or equal the pre-calculated expiration time. --- test/test_server.py | 27 +++++++++++++++++++++++++-- uiautomator/__init__.py | 11 +++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/test/test_server.py b/test/test_server.py index e5e7169..0cd6d6e 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -59,9 +59,32 @@ def test_start_error(self): server.ping = MagicMock() server.ping.return_value = None server.adb = MagicMock() - with patch("time.sleep"): + with patch("time.sleep") as time_sleep_mock, patch("time.time") as time_time_mock: + self._current_time = 0 + time_sleep_mock.side_effect = self._time_sleep + time_time_mock.side_effect = lambda: self._current_time with self.assertRaises(IOError): - server.start() + server.start(timeout=1) + + def _time_sleep(self, timeout): + self._current_time += timeout + + # Tests that start() timeout works correctly even in case communication + # with device takes too long. + def test_start_timeout_works_properly(self): + server = AutomatorServer() + server.push = MagicMock() + server.push.return_value = ["bundle.jar", "uiautomator-stub.jar"] + server.ping = MagicMock() + server.ping.side_effect = lambda: self._time_sleep(100) + server.adb = MagicMock() + with patch("time.sleep") as time_sleep_mock, patch("time.time") as time_time_mock: + self._current_time = 0 + time_sleep_mock.side_effect = self._time_sleep + time_time_mock.side_effect = lambda: self._current_time + with self.assertRaises(IOError): + server.start(timeout=1) + self.assertGreater(100.2, self._current_time) def test_auto_start(self): try: diff --git a/uiautomator/__init__.py b/uiautomator/__init__.py index 677b0b7..85f1e49 100644 --- a/uiautomator/__init__.py +++ b/uiautomator/__init__.py @@ -474,10 +474,13 @@ def start(self, timeout=5): self.uiautomator_process = self.adb.cmd(*cmd) self.adb.forward(self.local_port, self.device_port) - while not self.alive and timeout > 0: - time.sleep(0.1) - timeout -= 0.1 - if not self.alive: + step_secs = 0.1 + expiration_time = time.time() + timeout + while time.time() < expiration_time: + if self.alive: + break + time.sleep(step_secs) + else: raise IOError("RPC server not started!") def ping(self):