| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """PyAuto: Python Interface to Chromium's Automation Proxy. | 7 """PyAuto: Python Interface to Chromium's Automation Proxy. |
| 8 | 8 |
| 9 PyAuto uses swig to expose Automation Proxy interfaces to Python. | 9 PyAuto uses swig to expose Automation Proxy interfaces to Python. |
| 10 For complete documentation on the functionality available, | 10 For complete documentation on the functionality available, |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 return ret | 241 return ret |
| 242 | 242 |
| 243 @staticmethod | 243 @staticmethod |
| 244 def Kill(pid): | 244 def Kill(pid): |
| 245 """Terminate the given pid.""" | 245 """Terminate the given pid.""" |
| 246 if PyUITest.IsWin(): | 246 if PyUITest.IsWin(): |
| 247 subprocess.call(['taskkill.exe', '/T', '/F', '/PID', str(pid)]) | 247 subprocess.call(['taskkill.exe', '/T', '/F', '/PID', str(pid)]) |
| 248 else: | 248 else: |
| 249 os.kill(pid, signal.SIGTERM) | 249 os.kill(pid, signal.SIGTERM) |
| 250 | 250 |
| 251 def WaitUntil(self, function, timeout=-1, retry_sleep=0.25, args=[]): | 251 def WaitUntil(self, function, timeout=-1, retry_sleep=0.25, args=[], |
| 252 expect_retval=None): |
| 252 """Poll on a condition until timeout. | 253 """Poll on a condition until timeout. |
| 253 | 254 |
| 254 Waits until the |function| evalues to True or until |timeout| secs, | 255 Waits until the |function| evalues to |expect_retval| or until |timeout| |
| 255 whichever occurs earlier. | 256 secs, whichever occurs earlier. |
| 256 | 257 |
| 257 This is better than using a sleep, since it waits (almost) only as much | 258 This is better than using a sleep, since it waits (almost) only as much |
| 258 as needed. | 259 as needed. |
| 259 | 260 |
| 260 WARNING: This method call should be avoided as far as possible in favor | 261 WARNING: This method call should be avoided as far as possible in favor |
| 261 of a real wait from chromium (like wait-until-page-loaded). | 262 of a real wait from chromium (like wait-until-page-loaded). |
| 262 Only use in case there's really no better option. | 263 Only use in case there's really no better option. |
| 263 | 264 |
| 264 EXAMPLES:- | 265 EXAMPLES:- |
| 265 Wait for "file.txt" to get created: | 266 Wait for "file.txt" to get created: |
| 266 WaitUntil(os.path.exists, args=["file.txt"]) | 267 WaitUntil(os.path.exists, args=["file.txt"]) |
| 267 | 268 |
| 268 Same as above, but using lambda: | 269 Same as above, but using lambda: |
| 269 WaitUntil(lambda: os.path.exists("file.txt")) | 270 WaitUntil(lambda: os.path.exists("file.txt")) |
| 270 | 271 |
| 271 Args: | 272 Args: |
| 272 function: the function whose truth value is to be evaluated | 273 function: the function whose truth value is to be evaluated |
| 273 timeout: the max timeout (in secs) for which to wait. The default | 274 timeout: the max timeout (in secs) for which to wait. The default |
| 274 action is to wait for kWaitForActionMaxMsec, as set in | 275 action is to wait for kWaitForActionMaxMsec, as set in |
| 275 ui_test.cc | 276 ui_test.cc |
| 276 Use None to wait indefinitely. | 277 Use None to wait indefinitely. |
| 277 retry_sleep: the sleep interval (in secs) before retrying |function|. | 278 retry_sleep: the sleep interval (in secs) before retrying |function|. |
| 278 Defaults to 0.25 secs. | 279 Defaults to 0.25 secs. |
| 279 args: the args to pass to |function| | 280 args: the args to pass to |function| |
| 281 expect_retval: the expected return value for |function|. This forms the |
| 282 exit criteria. In case this is None (the default), |
| 283 |function|'s return value is checked for truth, |
| 284 so 'non-empty-string' should match with True |
| 280 | 285 |
| 281 Returns: | 286 Returns: |
| 282 True, if returning when |function| evaluated to True | 287 True, if returning when |function| evaluated to True |
| 283 False, when returning due to timeout | 288 False, when returning due to timeout |
| 284 """ | 289 """ |
| 285 if timeout == -1: # Default | 290 if timeout == -1: # Default |
| 286 timeout = self.action_max_timeout_ms()/1000.0 | 291 timeout = self.action_max_timeout_ms() / 1000.0 |
| 287 assert callable(function), "function should be a callable" | 292 assert callable(function), "function should be a callable" |
| 288 begin = time.time() | 293 begin = time.time() |
| 289 while timeout is None or time.time() - begin <= timeout: | 294 while timeout is None or time.time() - begin <= timeout: |
| 290 if function(*args): | 295 retval = function(*args) |
| 296 if (expect_retval is None and retval) or expect_retval == retval: |
| 291 return True | 297 return True |
| 298 logging.debug('WaitUntil(%s) still waiting. ' |
| 299 'Expecting %s. Last returned %s.' % ( |
| 300 function, expect_retval, retval)) |
| 292 time.sleep(retry_sleep) | 301 time.sleep(retry_sleep) |
| 293 return False | 302 return False |
| 294 | 303 |
| 295 class CmdExecutionTimeoutChanger(object): | 304 class CmdExecutionTimeoutChanger(object): |
| 296 """Facilitate temporary changes to command_execution_timeout_ms. | 305 """Facilitate temporary changes to command_execution_timeout_ms. |
| 297 | 306 |
| 298 Automatically resets to original timeout when object is destroyed. | 307 Automatically resets to original timeout when object is destroyed. |
| 299 """ | 308 """ |
| 300 _saved_timeout = -1 # Saved value for command_execution_timeout_ms | 309 _saved_timeout = -1 # Saved value for command_execution_timeout_ms |
| 301 | 310 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 Note: Wait duration is capped by the automation timeout. | 715 Note: Wait duration is capped by the automation timeout. |
| 707 | 716 |
| 708 Args: | 717 Args: |
| 709 count: requested number of infobars | 718 count: requested number of infobars |
| 710 windex: window index. Defaults to 0 (first window) | 719 windex: window index. Defaults to 0 (first window) |
| 711 tab_index: tab index Defaults to 0 (first tab) | 720 tab_index: tab index Defaults to 0 (first tab) |
| 712 | 721 |
| 713 Raises: | 722 Raises: |
| 714 pyauto_errors.JSONInterfaceError if the automation call returns an error. | 723 pyauto_errors.JSONInterfaceError if the automation call returns an error. |
| 715 """ | 724 """ |
| 716 cmd_dict = { | |
| 717 'command': 'WaitForInfobarCount', | |
| 718 'count': count, | |
| 719 'tab_index': tab_index, | |
| 720 } | |
| 721 # TODO(phajdan.jr): We need a solid automation infrastructure to handle | 725 # TODO(phajdan.jr): We need a solid automation infrastructure to handle |
| 722 # these cases. See crbug.com/53647. | 726 # these cases. See crbug.com/53647. |
| 723 return self.WaitUntil( | 727 def _InfobarCount(): |
| 724 lambda(count): len(self.GetBrowserInfo()\ | 728 windows = self.GetBrowserInfo()['windows'] |
| 725 ['windows'][windex]['tabs'][tab_index]['infobars']) == count, | 729 if windex >= len(windows): # not enough windows |
| 726 args=[count]) | 730 return -1 |
| 731 tabs = windows[windex]['tabs'] |
| 732 if tab_index >= len(tabs): # not enough tabs |
| 733 return -1 |
| 734 return len(tabs[tab_index]['infobars']) |
| 735 |
| 736 return self.WaitUntil(_InfobarCount, expect_retval=count) |
| 727 | 737 |
| 728 def PerformActionOnInfobar( | 738 def PerformActionOnInfobar( |
| 729 self, action, infobar_index, windex=0, tab_index=0): | 739 self, action, infobar_index, windex=0, tab_index=0): |
| 730 """Perform actions on an infobar. | 740 """Perform actions on an infobar. |
| 731 | 741 |
| 732 Args: | 742 Args: |
| 733 action: the action to be performed. | 743 action: the action to be performed. |
| 734 Actions depend on the type of the infobar. The user needs to | 744 Actions depend on the type of the infobar. The user needs to |
| 735 call the right action for the right infobar. | 745 call the right action for the right infobar. |
| 736 Valid inputs are: | 746 Valid inputs are: |
| (...skipping 1055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1792 if self._options.verbose: | 1802 if self._options.verbose: |
| 1793 verbosity = 2 | 1803 verbosity = 2 |
| 1794 result = PyAutoTextTestRuner(verbosity=verbosity).run(pyauto_suite) | 1804 result = PyAutoTextTestRuner(verbosity=verbosity).run(pyauto_suite) |
| 1795 del loaded_tests # Need to destroy test cases before the suite | 1805 del loaded_tests # Need to destroy test cases before the suite |
| 1796 del pyauto_suite | 1806 del pyauto_suite |
| 1797 sys.exit(not result.wasSuccessful()) | 1807 sys.exit(not result.wasSuccessful()) |
| 1798 | 1808 |
| 1799 | 1809 |
| 1800 if __name__ == '__main__': | 1810 if __name__ == '__main__': |
| 1801 Main() | 1811 Main() |
| OLD | NEW |