def _handle_source_code_dialog(self): logging.info("Waiting for the source code dialog.") def get_source_code_dialog(): return self.find_control(control_type="Window", name="main.c", parent=self.suite.top_window(), recurse=False) wait_for_condition(lambda: get_source_code_dialog().is_visible()) source_code_dialog = get_source_code_dialog() logging.info("Found source code dialog. Checking contents...") source_code_edit = self.find_control(control_type="Edit", name="", parent=source_code_dialog, recurse=False) self.expect_true( '#include <ggp_c/ggp.h>' in source_code_edit.get_line(0), "Source code dialog shows the correct file.") logging.info("All good. Closing the dialog...") close_button = self.find_control(control_type="Button", name="Close", parent=source_code_dialog, recurse=True) close_button.click_input()
def _execute(self, process_filter): # Finding FilterProcesses/ProcessList occationally throws from within pywinauto. This is not # understood. The while loop with the try/except block is a workaround for that. while True: try: filter_edit = self.find_control('Edit', 'FilterProcesses') break except KeyError: logging.info('Find FilterProcesses failed. Try again.') while True: try: process_list = self.find_control('Table', 'ProcessList') break except KeyError: logging.info('Find ProcessList failed. Try again.') logging.info('Waiting for process list to be populated') wait_for_condition(lambda: process_list.item_count() > 0, 30) logging.info('Setting filter text for process list') if process_filter: filter_edit.set_focus() filter_edit.set_edit_text('') send_keys(process_filter) # Wait for the process to show up - it may still be starting wait_for_condition(lambda: process_list.item_count() > 0, 30) logging.info('Process selected, continuing to main window...') process_list.children(control_type='DataItem')[0].double_click_input() _wait_for_main_window(self.suite.application) window = self.suite.top_window(True) self.expect_eq(window.class_name(), "OrbitMainWindow", 'Main window is visible') window.maximize()
def _execute(self): window = self.suite.top_window() logging.info('Start connecting to gamelet.') if flags.FLAGS.enable_ui_beta: connect_radio = self.find_control('RadioButton', 'ConnectToStadia') connect_radio.click_input() # Wait for the first data item in the instance list to exist # We're not using find_control here because magic lookup enables us to easily wait for the existence of a row window.InstanceList.click_input() window.InstanceList.DataItem0.wait('exists', timeout=100) instance_list = self.find_control('Table', 'InstanceList') logging.info('Found %s rows in the instance list', instance_list.item_count()) self.expect_true(instance_list.item_count() >= 1, 'Found at least one instance') window.InstanceList.DataItem0.double_click_input() logging.info('Connecting to Instance, waiting for the process list...') if flags.FLAGS.enable_ui_beta: # In the new UI, use small waits until the process list is active, and then some more for the # semi-transparent "loading" Overlay of the tables to disappear... wait_for_condition(lambda: self.find_control('Custom', 'ProcessesFrame').is_enabled() is True, 15) wait_for_condition(lambda: self.find_control('Table', 'ProcessList').is_active(), 10) # TODO(b/177037834): Get rid of this sleep and correctly wait for the overlay to be hidden time.sleep(2) else: wait_for_main_window(self.suite.application) window = self.suite.top_window(True) self.expect_eq(window.class_name(), "OrbitMainWindow", 'Main window is visible') logging.info('Process list ready')
def _execute(self, process_filter): if flags.FLAGS.enable_ui_beta: filter_edit = self.find_control('Edit', 'FilterProcesses') process_list = self.find_control('Table', 'ProcessList') else: process_data_view = DataViewPanel(self.find_control('Group', 'ProcessesDataView')) filter_edit = process_data_view.filter process_list = process_data_view.table logging.info('Waiting for process list to be populated') wait_for_condition(lambda: process_list.item_count() > 0, 30) logging.info('Setting filter text for process list') if process_filter: filter_edit.set_focus() filter_edit.set_edit_text('') send_keys(process_filter) # Wait for the process to show up - it may still be starting wait_for_condition(lambda: process_list.item_count() > 0, 30) if flags.FLAGS.enable_ui_beta: logging.info('Process selected, continuing to main window...') process_list.children(control_type='DataItem')[0].double_click_input() wait_for_main_window(self.suite.application) window = self.suite.top_window(True) self.expect_eq(window.class_name(), "OrbitMainWindow", 'Main window is visible') else: process_list.children(control_type='TreeItem')[0].click_input()
def _wait_and_verify_capture_interrupted(self): logging.info("Verifying that the capture was stopped by OrbitService") wait_for_condition(lambda: self.find_control( 'Window', 'Capture interrupted', recurse=False, raise_on_failure=False) is not None, max_seconds=300) dialog = self.find_control('Window', 'Capture interrupted') self.find_control('Button', 'OK', parent=dialog).click_input()
def _execute(self, filter_strings: str or Iterable[str]): if isinstance(filter_strings, str): filter_strings = [filter_strings] connect_radio = self.find_control('RadioButton', 'LoadCapture') connect_radio.click_input() filter_capture_files = self.find_control('Edit', 'FilterCaptureFiles') succeeded = False for filter_string in filter_strings: filter_capture_files.set_edit_text(filter_string) capture_file_list = self.find_control('Table', 'CaptureFileList') try: wait_for_condition(lambda: capture_file_list.item_count() > 0, 30) except OrbitE2EError: continue succeeded = True capture_file_list.children( control_type='DataItem')[0].double_click_input() # Unless the file does not exist, Orbit's main window will open and contain the "Loading capture" dialog. _wait_for_main_window(self.suite.application) # As there is a new top window (Orbit main window), we need to update the top window. self.suite.top_window(force_update=True) break if not succeeded: raise OrbitE2EError( f'Did not find any capture in filter strings: "{filter_strings}"' )
def _execute(self, function_name): cell, index = self.find_function_cell(function_name) cell.click_input(button='right') self.find_context_menu_item('Enable frame track(s)').click_input() tree_view = self.find_control('Tree', parent=self._live_tab) wait_for_condition( lambda: "F" in tree_view.children()[index - 1].window_text())
def _wait_for_capture_completion(self): logging.info("Waiting for capture to finalize...") wait_for_condition( lambda: self.find_control('Window', 'Finalizing capture', recurse=False, raise_on_failure=False) is None, max_seconds=120) logging.info("Capturing finished")
def _execute(self): time.sleep(1) app_menu = self.suite.top_window().descendants( control_type="MenuBar")[1] app_menu.item_by_path("File->End Session").click_input() wait_for_condition( lambda: self.suite.application.top_window().class_name() == "orbit_session_setup::SessionSetupDialog", 30) self.suite.top_window(force_update=True)
def _execute(self): _show_symbols_and_functions_tabs(self.suite.top_window()) self._load_presets() wait_for_condition(lambda: self._try_verify_functions_are_hooked) Capture().execute(self.suite) logging.info('Verifying function call counts') VerifyFunctionCallCount(function_name='DrawFrame', min_calls=30, max_calls=3000).execute(self.suite) VerifyFunctionCallCount(function_name='GgpIssueFrameToken', min_calls=30, max_calls=3000).execute(self.suite)
def _execute(self, module_search_string: str, expect_loaded: bool = True): _show_symbols_and_functions_tabs(self.suite.top_window()) logging.info('Start verifying module %s is %s.', module_search_string, "loaded" if expect_loaded else "not loaded") modules_dataview = DataViewPanel(self.find_control("Group", "ModulesDataView")) wait_for_condition(lambda: modules_dataview.get_row_count() > 0, 100) modules_dataview.filter.set_focus() modules_dataview.filter.set_edit_text('') send_keys(module_search_string) wait_for_condition(lambda: modules_dataview.get_row_count() > 0) self.expect_true('*' in modules_dataview.get_item_at(0, 0).texts()[0], 'Module is loaded.')
def _execute(self): logging.info('Select next project') project_combo_box = self.find_control(name='ProjectSelectionComboBox') # wait until loading is done wait_for_condition(lambda: project_combo_box.is_enabled() is True, 25) project_combo_box.click_input() logging.info('Found and opened project combo box, sending down arrow and enter') send_keys('{DOWN}{ENTER}') # After project changing, loading takes place. Wait until the overlay is hidden wait_for_condition( lambda: self.find_control('Group', 'InstanceListOverlay', raise_on_failure=False) is None, 100) logging.info('Successfully selected next project')
def _execute(self): _show_symbols_and_functions_tabs(self.suite.top_window()) functions_dataview = DataViewPanel(self.find_control("Group", "FunctionsDataView")) logging.info('Waiting for function list to be populated...') wait_for_condition(lambda: functions_dataview.get_row_count() > 0, 100) functions_dataview.filter.set_focus() functions_dataview.filter.set_edit_text('') functions_dataview.get_item_at(0, 0).click_input('left') # Hit Ctrl+a to select all functions. send_keys('^a') functions_dataview.get_item_at(0, 0).click_input('right') self.find_context_menu_item('Unhook').click_input()
def _execute(self, module_search_string: str): _show_symbols_and_functions_tabs(self.suite.top_window()) logging.info('Start loading symbols for module %s', module_search_string) modules_dataview = DataViewPanel( self.find_control("Group", "ModulesDataView")) logging.info('Waiting for module list to be populated...') wait_for_condition(lambda: modules_dataview.get_row_count() > 0, 100) logging.info('Filtering and loading') modules_dataview.filter.set_focus() modules_dataview.filter.set_edit_text('') send_keys(module_search_string) wait_for_condition(lambda: modules_dataview.get_row_count() == 1) modules_dataview.get_item_at(0, 0).click_input('right') self.find_context_menu_item('Load Symbols').click_input() logging.info('Waiting for * to indicate loaded modules') wait_for_condition( lambda: modules_dataview.get_item_at(0, 4).texts()[0] == "*", 100) functions_dataview = DataViewPanel( self.find_control("Group", "FunctionsDataView")) wait_for_condition(lambda: functions_dataview.get_row_count() > 0)
def _execute(self): instance_list = self.find_control('Table', 'InstanceList') refresh_button = self.find_control('Button', 'RefreshInstanceList') logging.info('Found instance list and refresh button, clicking refresh button') refresh_button.click_input() instance_list_overlay = self.find_control(None, 'InstanceListOverlay') self.expect_true(instance_list_overlay.is_visible(), "Instance overlay is visible") logging.info('Found InstanceListOverlay and its visible') wait_for_condition( lambda: self.find_control('Group', 'InstanceListOverlay', raise_on_failure=False) is None, 100) logging.info('Loading done, overlay is hidden') self.expect_true(_get_number_of_instances_in_list(self) >= 1, 'Found at least one instance')
def _execute(self): instance_list_overlay = self.find_control('Group', 'InstanceListOverlay') self.expect_true(instance_list_overlay.is_visible(), "Instance overlay is visible") disconnect_button = self.find_control('Button', 'Disconnect') logging.info( 'Instance overlay visible and Disconnect button was found; performing disconnect from the instance' ) disconnect_button.click_input() logging.info('Waiting for instance overlay to dissapear') wait_for_condition(lambda: self.find_control( 'Group', 'InstanceListOverlay', raise_on_failure=False) is None) logging.info('Loading done, overlay is hidden') self.expect_true(_get_number_of_instances_in_list(self) >= 1, 'Found at least one instance') wait_for_condition(lambda: self.find_control( 'Group', 'ProcessListOverlay', raise_on_failure=False) is None)
def _execute(self, filter_string: str = "", expected_track_count=None): """ :param filter_string: The string to be entered in the filter edit. Note that pywinauto's `keyboard.send_keys` is used, so certain special characters need to be escaped by enclosing them in {}. :param expected_track_count: If not None, this test will verify the amount of tracks after filtering """ toolbar = self.find_control("ToolBar", "CaptureToolBar") track_filter = self.find_control("Edit", "FilterTracks", parent=toolbar) logging.info("Setting track filter text: '{}'".format(filter_string)) track_filter.set_focus() track_filter.set_edit_text('') # Using send_keys instead of set_edit_text directly because set_edit_text ignores the wait timings... keyboard.send_keys(filter_string) if expected_track_count is not None: wait_for_condition(lambda: len(self._find_tracks()) == expected_track_count)
def _handle_file_not_found_message_box(self): logging.info('Waiting for message box') def get_message_box(): return self.find_control(control_type="Window", name="Source code file not found", parent=self.suite.top_window(), recurse=False) wait_for_condition(lambda: get_message_box().is_visible()) logging.info('Message box found - Clicking "Choose file..."') choose_file_button = self.find_control(control_type="Button", name="Choose file...", parent=get_message_box(), recurse=True) choose_file_button.click_input()
def _execute(self, function_name): cell, index = self.find_function_cell(function_name) cell.click_input(button='right') self.find_context_menu_item('Enable frame track(s)').click_input() tree_view = self.find_control('Tree', parent=self._live_tab) wait_for_condition( lambda: "F" in tree_view.children()[index - 1].window_text()) logging.info("Verifying existence of track in the Capture window") match_tracks = MatchTracks( expected_names=["Frame track based on %s" % function_name], allow_additional_tracks=True) match_tracks.execute(self.suite) check_timers = CheckTimers(track_name_contains=function_name) check_timers.execute(self.suite)
def _execute(self, project_name: str): logging.info('Select project with name ' + project_name) project_combo_box = self.find_control(name='ProjectSelectionComboBox') # wait until loading is done wait_for_condition(lambda: project_combo_box.is_enabled() is True, 25) project_combo_box.click_input() project = self.find_combo_box_item(text=project_name) logging.info('Expanded project combo box and found entry ' + project_name) project.click_input() # After project changing, loading takes place. Wait until the overlay is hidden wait_for_condition( lambda: self.find_control('Group', 'InstanceListOverlay', raise_on_failure=False) is None, 100) logging.info('Successfully selected project ' + project_name + 'and waited until loading is done') self.expect_true(_get_number_of_instances_in_list(self) >= 1, 'Found at least one instance')
def _provoke_goto_source_action(self, function_search_string: str): _show_symbols_and_functions_tabs(self.suite.top_window()) logging.info('Start showing source code for function {}'.format(function_search_string)) functions_dataview = DataViewPanel(self.find_control("Group", "FunctionsDataView")) logging.info('Waiting for function list to be populated...') wait_for_condition(lambda: functions_dataview.get_row_count() > 0, 100) logging.info('Filtering functions') functions_dataview.filter.set_focus() functions_dataview.filter.set_edit_text('') send_keys(function_search_string) wait_for_condition(lambda: functions_dataview.get_row_count() == 1) functions_dataview.get_item_at(0, 0).click_input('right') logging.info('Click on "Go to Source code"') self.find_context_menu_item('Go to Source code').click_input()
def _execute(self, capture_file_path: str, expect_fail=False): # Lets ensure that we are actually in the connection window, as this test might also be executed after the # main window has been opened. _wait_for_connection_window(self.suite.application) self.suite.top_window(force_update=True) logging.info('Starting to load a capture.') connect_radio = self.find_control('RadioButton', 'LoadCapture') connect_radio.click_input() others_button = self.find_control('Button', '...') others_button.click_input() file_name_edit = self.find_control('Edit', 'File name:') if not os.path.isabs(capture_file_path): automation_tests_dir = os.path.join(os.path.dirname(__file__), '..') capture_file_path = os.path.join(automation_tests_dir, capture_file_path) file_name_edit.set_edit_text(capture_file_path) logging.info(f'Trying to load capture file: {capture_file_path}') start_session_button = self.find_control('Button', 'Start Session') start_session_button.click_input() # Unless the file does not exist, Orbit's main window will open next and contain the "Loading capture" dialog. _wait_for_main_window(self.suite.application) # As there is a new top window (Orbit main window), we need to update the top window. self.suite.top_window(force_update=True) logging.info("Waiting for capture to load...") wait_for_condition(lambda: self.find_control( 'Window', 'Loading capture', raise_on_failure=False) is None, max_seconds=120) logging.info("Capture Loading finished") if expect_fail: self.find_control('Window', 'Error while loading capture') ok_button = self.find_control('Button', 'OK') ok_button.click_input()
def _execute(self): logging.info('Starting "All Instances" checkbox test.') # First wait until all loading is done. wait_for_condition( lambda: self.find_control('Group', 'InstanceListOverlay', raise_on_failure=False) is None, 100) check_box = self.find_control('CheckBox', 'AllInstancesCheckBox') logging.info('Found checkbox') instance_count = _get_number_of_instances_in_list(self) check_box.click_input() logging.info( 'Clicked All Instances check box, waiting until loading is done') wait_for_condition( lambda: self.find_control('Group', 'InstanceListOverlay', raise_on_failure=False) is None, 100) self.expect_true( instance_count <= _get_number_of_instances_in_list(self), 'Instance list contains at least same amount of instances as before.' ) logging.info('Loading successful, instance number increased') check_box.click_input() wait_for_condition( lambda: self.find_control('Group', 'InstanceListOverlay', raise_on_failure=False) is None, 100) self.expect_true( _get_number_of_instances_in_list(self) >= 1, 'Instance list contains at least one instance') logging.info('Second click on check box successful')
def _execute(self): window = self.suite.top_window() logging.info('Start connecting to gamelet.') connect_radio = self.find_control('RadioButton', 'ConnectToStadia') connect_radio.click_input() # Wait for the first data item in the instance list to exist # We're not using find_control here because magic lookup enables us to easily wait for the existence of a row window.InstanceList.click_input() window.InstanceList.DataItem0.wait('exists', timeout=100) self.expect_true( _get_number_of_instances_in_list(self) >= 1, 'Found at least one instance') window.InstanceList.DataItem0.double_click_input() logging.info('Connecting to Instance, waiting for the process list...') # In the new UI, use small waits until the process list is active, and then some more for the # semi-transparent "loading" Overlay of the tables to disappear wait_for_condition( lambda: self.find_control('Custom', 'ProcessesFrame').is_enabled() is True, 25) wait_for_condition( lambda: self.find_control('Table', 'ProcessList').is_active(), 10) # This is a bit annoying, but since the overlay is invisible when loading is done, we need to check for # absence of the overlay... not sure if there is a better way wait_for_condition(lambda: self.find_control( 'Group', 'ProcessListOverlay', raise_on_failure=False) is None) logging.info('Process list ready')
def _handle_file_open_dialog(self): logging.info("Waiting for File Open Dialog") def get_file_open_dialog(): return self.find_control(control_type="Window", name_contains="Choose ", parent=self.suite.top_window(), recurse=False) wait_for_condition(lambda: get_file_open_dialog().is_visible()) file_open_dialog = get_file_open_dialog() logging.info( "File Open Dialog is now visible. Looking for file edit...") logging.info("File Edit was found. Entering file path...") file_edit = self.find_control(control_type="Edit", name="File name:", parent=file_open_dialog, recurse=True) file_edit.set_focus() file_edit.set_edit_text('') # The test needs the source code file "main.c" from the hello_ggp example # to be available on the machine. On the E2E test infrastructure the example # project will be extracted to C:\build\scratch\test\hello_ggp. # # To run this test in developer machines, the patch can be overwritten by a # command line flag. Keep in mind, it needs to be an absolute path, which # is understood by the Windows file open dialog, when pasted into the filename # field. send_keys(flags.FLAGS.source_code_file) logging.info("Clicking the open button...") file_open_button = self.find_control(control_type="Button", name="Open", parent=file_open_dialog, recurse=False) file_open_button.click_input()
def _execute(self, module_search_string: str, expect_fail=False): """ :param module_search_string: String to enter in the module filter field, the first entry in the list of remaining modules will be loaded :param expect_fail: If True, the test will succeed if loading symbols results in an error message """ _show_symbols_and_functions_tabs(self.suite.top_window()) logging.info('Start loading symbols for module %s', module_search_string) modules_dataview = DataViewPanel( self.find_control("Group", "ModulesDataView")) logging.info('Waiting for module list to be populated...') wait_for_condition(lambda: modules_dataview.get_row_count() > 0, 100) logging.info('Filtering and loading') modules_dataview.filter.set_focus() modules_dataview.filter.set_edit_text('') send_keys(module_search_string) wait_for_condition(lambda: modules_dataview.get_row_count() == 1) modules_dataview.get_item_at(0, 0).click_input('right') self.find_context_menu_item('Load Symbols').click_input() logging.info('Waiting for * to indicate loaded modules') # The Loading column which should get filled with the "*" is the first column (0) if expect_fail: wait_for_condition(lambda: _find_and_close_error_dialog( self.suite.top_window()) is not None) else: wait_for_condition( lambda: modules_dataview.get_item_at(0, 0).texts()[0] == "*", 100) VerifySymbolsLoaded(symbol_search_string=module_search_string, expect_loaded=not expect_fail).execute(self.suite)
def _execute(self, function_search_string): _show_symbols_and_functions_tabs(self.suite.top_window()) logging.info('Hooking function based on search "%s"', function_search_string) functions_dataview = DataViewPanel(self.find_control("Group", "FunctionsDataView")) logging.info('Waiting for function list to be populated...') wait_for_condition(lambda: functions_dataview.get_row_count() > 0, 100) logging.info('Filtering and hooking') functions_dataview.filter.set_focus() functions_dataview.filter.set_edit_text('') send_keys(function_search_string) wait_for_condition(lambda: functions_dataview.get_row_count() == 1) functions_dataview.get_item_at(0, 0).click_input('right') self.find_context_menu_item('Hook').click_input() wait_for_condition(lambda: '✓' in functions_dataview.get_item_at(0, 0).texts()[0])
def _wait_for_connection_window(application: Application): wait_for_condition(lambda: application.top_window().class_name() == "orbit_session_setup::SessionSetupDialog", max_seconds=30)
def _wait_for_main_window(application: Application): wait_for_condition( lambda: application.top_window().class_name() == "OrbitMainWindow", max_seconds=30)