#!/usr/bin/python # Copyright (c) 2011 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Pyauto powered ui action runner. Developed primarily to verify validity of the model based action generator. """ import time import sys import pyauto_functional import pyauto import ui_model class Runner(pyauto.PyUITest): def setUp(self): self.debug_mode = False pyauto.PyUITest.setUp(self) def RunActionList(self): """Runs actions from a file.""" f = open('list') actions = f.readlines() self.browser = ui_model.BrowserState(advanced_actions=True) count = 0 for action in actions: count += 1 sys.stdout.write('%d > ' % count) action = action.strip() self.ApplyAction(action) raw_input('Press key to continue.') def DebugUIActions(self): """Run testUIActions with debug mode on. Allows inspection of the browser after unexpected state is encountered. """ self.debug_mode = True self.testUIActions() def testUIActions(self): """Generates and runs actions forever.""" self.browser = ui_model.BrowserState(advanced_actions=True) count = 0 start_time = time.time() while True: count += 1 sys.stdout.write('%d:%.3f > ' % (count, time.time() - start_time)) action = ui_model.GetRandomAction(self.browser) self.ApplyAction(action) def ApplyAction(self, action): sys.stdout.write('%s, ' % action) if self._DoAction(action): ui_model.UpdateState(self.browser, action) self._CheckState() def Error(self, msg=''): """Called when an unexpected state is encountered.""" if msg: print 'Error: %s' % msg else: print 'Error' while self.debug_mode: raw_input('Press key to continue.') assertTrue(False, msg) def _CheckState(self): """Check some basic properties of the browser against expected state.""" active_window = self.browser.window_position active_tab = self.GetActiveTabIndex(active_window) expected_tab = self.browser.window.tab_position print 'win: %d tab: %d navs: %d backs: %d' % ( active_window, active_tab, self.browser.window.tab.navs, self.browser.window.tab.backs) if active_tab != expected_tab: self.Error('active index out of sync: expected %d' % expected_tab) tab_count = self.GetTabCount(active_window) expected_count = self.browser.window.num_tabs if tab_count != expected_count: self.Error('tab count out of sync: count: %d expected: %d' % ( tab_count, expected_count)) window_count = self.GetBrowserWindowCount() expected_count = self.browser.num_windows if window_count != expected_count: self.Error('window count out of sync: count: %d expected %d' % ( window_count, expected_count)) def _GrabTab(self): active_window = self.browser.window_position window = self.GetBrowserWindow(active_window) tab_count = self.GetTabCount(self.browser.window_position) active_tab = self.browser.window.tab_position if active_tab >= tab_count: self.Error('active tab out of bounds: count: %d expected active: %d' % ( (tab_count, active_tab))) return window.GetTab(self.browser.window.tab_position) def _RunInActiveWindow(self, command): active_window = self.browser.window_position self.RunCommand(command, active_window) def _RunAsyncInActiveWindow(self, command): active_window = self.browser.window_position self.ApplyAccelerator(command, active_window) def _Zoom(self, command): active_window = self.browser.window_position title = self.GetActiveTabTitle(active_window) model_active_tab = self.browser.window.tab_position active_tab = self.GetActiveTabIndex(active_window) num_tabs = self.GetTabCount(active_window) self._RunAsyncInActiveWindow(command) if title == 'New Tab': self.Error('zoom called on new tab') def _WaitFor(self, test): start = time.time() test_result, detail = test() while not test_result: if time.time() - start > self.action_max_timeout_ms(): self.Error('TIMEOUT: %s' % detail) time.sleep(.1) test_result, detail = test() def _DoAction(self, action): """Execute action in the browser. Attempts to simulate synchronous execution for most actions. Args: action: action string. """ a = action.split(';')[0] if a == 'showbookmarks': self._RunAsyncInActiveWindow(pyauto.IDC_SHOW_BOOKMARK_BAR) if a == 'openwindow' or a == 'goofftherecord': def NewWindowHasTab(): result = self.GetTabCount(self.browser.num_windows) == 1 return (result, 'NewWindowHasTab') def TabLoaded(): result = self.GetActiveTabTitle(self.browser.num_windows) == 'New Tab' return (result, 'TabLoaded') if a == 'openwindow': self.OpenNewBrowserWindow(True) elif a == 'goofftherecord': self._RunAsyncInActiveWindow(pyauto.IDC_NEW_INCOGNITO_WINDOW) self._WaitFor(NewWindowHasTab) self._WaitFor(TabLoaded) if a == 'newtab': active_window = self.browser.window_position target = pyauto.GURL('chrome://newtab') self.AppendTab(target, active_window) if a == 'downloads': active_window = self.browser.window_position def TabLoaded(): result = self.GetActiveTabTitle(active_window) == 'Downloads' return (result, 'TabLoaded') self._RunAsyncInActiveWindow(pyauto.IDC_SHOW_DOWNLOADS) self._WaitFor(TabLoaded) if a == 'star': self._RunAsyncInActiveWindow(pyauto.IDC_BOOKMARK_PAGE) if a == 'zoomplus': self._Zoom(pyauto.IDC_ZOOM_PLUS) if a == 'zoomminus': self._Zoom(pyauto.IDC_ZOOM_MINUS) if a == 'pagedown': return False if a == 'back' or a == 'forward' or a == 'navigate': tab = self._GrabTab() active_window = self.browser.window_position old_title = self.GetActiveTabTitle(active_window) retries = 0 nav_result = 0 while nav_result != 1: if retries == 1: break if retries == 1: sys.stdout.write('retry ') if retries > 0: time.sleep(.1) sys.stdout.write('%d, ' % retries) if a == 'navigate': target = pyauto.GURL(action.split(';')[1]) nav_result = tab.NavigateToURL(target) elif a == 'back': self.browser.Back() self.browser.Forward() nav_result = tab.GoBack() elif a == 'forward': self.browser.Forward() self.browser.Back() nav_result = tab.GoForward() retries += 1 if a == 'closetab': tab = self._GrabTab() ui_model.UpdateState(self.browser, action) active_window = self.browser.window_position window_count = self.browser.num_windows tab_count = self.browser.window.num_tabs def WindowCount(): actual = self.GetBrowserWindowCount() result = actual == window_count return (result, 'WindowCount (expected %d, actual %d)' % (window_count, actual)) def TabCount(): actual = self.GetTabCount(active_window) result = actual == tab_count return (result, 'TabCount (expected %d, actual %d)' % (tab_count, actual)) tab.Close(True) self._WaitFor(WindowCount) self._WaitFor(TabCount) return False if a == 'closewindow': window_count = self.browser.num_windows - 1 def WindowCount(): result = self.GetBrowserWindowCount() == window_count return (result, 'WindowCount (expected %d)' % window_count) self._RunInActiveWindow(pyauto.IDC_CLOSE_WINDOW) self._WaitFor(WindowCount) if a == 'dragtabout': return False if a == 'dragtableft': self._RunAsyncInActiveWindow(pyauto.IDC_MOVE_TAB_PREVIOUS) if a == 'dragtabright': self._RunAsyncInActiveWindow(pyauto.IDC_MOVE_TAB_NEXT) if a == 'lasttab': self._RunAsyncInActiveWindow(pyauto.IDC_SELECT_PREVIOUS_TAB) if a == 'nexttab': self._RunAsyncInActiveWindow(pyauto.IDC_SELECT_NEXT_TAB) if a == 'restoretab': active_window = self.browser.window_position self.ApplyAccelerator(pyauto.IDC_RESTORE_TAB, active_window) self._GrabTab().WaitForTabToBeRestored(self.action_max_timeout_ms()) ui_model.UpdateState(self.browser, action) return False return True if __name__ == '__main__': pyauto_functional.Main()