def _open_and_yield(self, action_name, timeout_ms=300, retries=6): """ Compatible with run_test_driver, to be used in a yield statement editor = Project_Properties_Editor() yield editor.open_and_yield() ... :param action_name: the name of the action that will open window """ windows = Gtk.Window.list_toplevels() yield modal_dialog(lambda: GPS.execute_action(action_name), timeout_ms) self.dialogs = [] attempt = 0 while True: self.dialogs = [ w for w in Gtk.Window.list_toplevels() if w not in windows and w.get_mapped()] if self.dialogs: # Wait little bit more to allow dialog to be dispayed and # focus to be moved. yield timeout(timeout_ms) break attempt += 1 if attempt > retries: break yield timeout(timeout_ms)
def wait_until_not_busy(debugger, t=100): """ Wait until the given GPS.Debugger is not busy """ while debugger.is_busy(): yield timeout(t)
def cancel(self): """ Cancel the assistant. """ get_button_from_label("Cancel", self.__assistant).clicked() yield timeout(300)
def ok(self): """ Press the OK button. Use as:: yield dialog.ok() """ get_button_from_label("OK", self.dialog).clicked() yield timeout(300)
def cancel(self): """ Press the Cancel button. Use as:: yield dialog.cancel() """ get_button_from_label("Cancel", self.dialog).clicked() yield timeout(300)
def apply(self): """ Click on the 'Apply' button of the assistant to deploy the currently selected template. """ get_button_from_label("Apply", self.__assistant).clicked() yield timeout(300)
def open_and_yield(self): GPS.execute_action("open Learn") self.dialog = GPS.MDI.get('Learn').pywidget() self.paned_view = get_widgets_by_type(Gtk.Paned, self.dialog)[0] self.doc_label = get_widgets_by_type(Gtk.Label, self.paned_view.get_child2())[0] # wait for the Learn view to be fully realized before returning while self.dialog.get_allocation().width == -1: yield timeout(200)
def send_keys(*input_seq): """ Workflow Given an input sequence composed of strings and character codes, send them to the application, waiting a small amount of time between each keystroke, to simulate human keyboard input. Returns nothing """ for chunk in input_seq: if isinstance(chunk, int): send_key_event(chunk) yield timeout(10) elif isinstance(chunk, str): for c in chunk: if c == "\n": send_key_event(GDK_RETURN) else: send_key_event(ord(c)) yield timeout(10)
def wait_until_true(test_func, *args, **kwargs): """ Wait for the the :param func test_func: to return True, without blocking the UI. """ k = 0 n = 30 while not test_func(*args, **kwargs) and k < n: yield timeout(500) k += 1
def wait_for_mdi_child(name, step=500, n=10): """ Wait for the MDI child designated by :param str name: to be added to the MDI, waiting for the time specified in :param int step: n times. """ k = 0 while GPS.MDI.get(name) is None and k < n: yield timeout(step) k += 1
def save(self): """ Press the Save button, saving the modifications that have been made in the project file and closing the dialog. Use as:: yield dialog.save() """ save_button = get_widget_by_name("project properties edit source") save_button.clicked() yield timeout(300)
def driver(): yield timeout(1000) als = GPS.LanguageServer.get_by_language_name("Ada") b = GPS.EditorBuffer.get(GPS.File("main.adb")) b.current_view().goto(b.at(4, 5)) yield hook('language_server_response_processed') GPS.execute_action("Entity called by") yield hook('language_server_response_processed') yield wait_idle() call_tree = get_widget_by_name("Call Graph Tree") selection = call_tree.get_selection() selection.unselect_all() model = call_tree.get_model() selection.select_iter(model.iter_nth_child(model.get_iter_first(), 0)) GPS.execute_action("calltree expand selected") yield hook('language_server_response_processed') yield wait_idle() expected = [ 'Foo is called by ', [ 'Foo', ['Foo', ['computing...'], 'Main', ['computing...']], 'Main', ['computing...'] ] ] gps_assert(expected, dump_tree_model(model, 0), "The model didn't contain the expected text") # Now verify that double-clicking on the row that lists 'Main' # correctly open its editor. GPS.execute_action("close all editors") yield wait_tasks(other_than=known_tasks) click_in_tree(call_tree, path=Gtk.TreePath("0:0:1"), button=1, events=double_click_events) yield wait_idle() buffer = GPS.EditorBuffer.get() gps_assert( buffer.file(), GPS.File("main.adb"), "double-clicking on a Call Trees row should open an " + "editor for the clicked entity")
def driver(): GPS.Preference("Debugger-Execution-Window").set(False) # This test launches a debug session, and runs the program in the # debugger. The goal is to check against a memory corruption that # occurs after the process has terminated - the test itself might # not report an issue, but valgrind might. GPS.execute_action("Build & Debug Number 1") yield wait_tasks() GPS.Debugger.get().non_blocking_send("run") yield timeout(2000) yield wait_for_mdi_child("Debugger Execution") # sanity check that the test ran gps_assert("finished!" in GPS.Debugger.get().get_console().get_text(), True, "debug output not visible in console")
def workflow(): _ = yield hook("gps_started") yield timeout(10) try: action_gen = action_fn() if action_gen is not None: yield action_gen except: import traceback GPS.Logger('TESTSUITE').log( "Driver workflow received an exception %s %s\n%s" % (sys.exc_info()[0], sys.exc_info()[1], traceback.format_exc())) finally: if "GPS_PREVENT_EXIT" not in os.environ: GPS.exit(force=True)
def driver(): # Generate a giant file on disk and load it from disk with open("p.ads", "wb") as f: f.write("""package P is function Foo return Integer is (42); end P;""" + ("--" + "spam" * 100 + "\n") * 10000) # Reload the project so that p.ads is considered as a source GPS.execute_action("reload project") q_ads = GPS.File("q.ads") p_ads = GPS.File("p.ads") a = GPS.EditorBuffer.get(p_ads) yield timeout(1000) b = GPS.EditorBuffer.get(q_ads) # Now insert a huge amount of data in an already open editor b.insert(b.at(4, 7), ("-- " + "spam" * 100 + "\n") * 10000) als = GPS.LanguageServer.get_by_language_name("Ada") params = {"textDocument": {"uri": q_ads.uri}, "position": {"line": 2, "character": 27}, "context": {"includeDeclaration": True}} result = yield als.request_promise("textDocument/references", params) if not result.is_valid: simple_error("we were expecting a valid result") # The result we expect from find_all_references expected = [{"uri": p_ads.uri, "range": {"start": {"line": 1, "character": 12}, "end": {"line": 1, "character": 15}}, "alsKind": ["reference"]}, {"uri": q_ads.uri, "range": {"start": {"line": 2, "character": 27}, "end": {"line": 2, "character": 30}}, "alsKind": ["call"]}] gps_assert( result.data, expected, "result contents doesn't match expectations: {}".format(result))
def driver(): # Open bla.adb, goto declaration of "Create" b = GPS.EditorBuffer.get(GPS.File("bla.adb")) b.current_view().goto(b.at(6, 16)) GPS.execute_action("goto declaration") yield wait_tasks(other_than=known_tasks) # Sanity check that we're on the runtime file b2 = GPS.EditorBuffer.get() gps_assert(os.path.basename(b2.file().name()), "a-textio.ads", "goto declaration didn't work") # Run "is called by" GPS.execute_action("Entity called by") yield hook('language_server_response_processed') yield timeout(1000) # Verify that the call tree does show the call location in "Bla" call_tree = get_widget_by_name("Call Graph Tree") model = call_tree.get_model() gps_assert(dump_tree_model(model, 0), ['Create is called by ', ['Bla', ['computing...']]], "The model didn't contain the expected result")
def gnatfuzz_fuzz_workflow(self, task): """The 'gnatfuzz fuzz' workflow""" # Move away the previous fuzzing session dir fuzz_session_dir = os.path.join(self.output_dir, "fuzz_testing", "session") if os.path.exists(fuzz_session_dir): shutil.rmtree(fuzz_session_dir) # Generate the -X switches args = [] for variable, value in GPS.Project.scenario_variables().items(): # We pass all -X switches except the ones that are internal # to gnatfuzz. if not (variable.startswith("GNATFUZZ") or variable == "AFL_MODE"): args.append(f"-X{variable}={value}") args.extend([ f"--corpus-path={self.output_dir}/fuzz_testing/starting_corpus", f"--stop-criteria={self.output_dir}" "/fuzz_testing/user_configuration/stop_criteria.xml", ]) GPS.BuildTarget("gnatfuzz fuzz").execute( extra_args=args, synchronous=False, ) # Create a CodeAnalysis object to store the coverage data a = GPS.CodeAnalysis.get("gnatfuzz") xcov_files = {} # Keys: full path, values: timestamp # Launch the GNATfuzz view GPS.execute_action("open GNATfuzz view") # Clear the GNATfuzz view GPS.execute_action("clear GNATfuzz view") # Monitor the disk for the presence of xcov files while True: # This is interrupted by the user calling the menu again, # in which case the Task will be removed: see at the bottom # of the loop. yield promises.timeout(FUZZ_MONITOR_TIMEOUT) if not os.path.exists(fuzz_session_dir): self.error( f"fuzz session directory {fuzz_session_dir} not found") self.stop_fuzz() break # Monitor for coverage files found_xcov_files = glob.glob( os.path.join(fuzz_session_dir, "coverage_output", "*.xcov")) for xcov in found_xcov_files: (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(xcov) timestamp = time.ctime(mtime) if xcov not in xcov_files or xcov_files[xcov] != timestamp: xcov_files[xcov] = timestamp base = os.path.basename(xcov)[:-5] a.add_gcov_file_info(GPS.File(base), GPS.File(xcov), raise_window=False) a.show_file_coverage_info(GPS.File(base)) # Monitor for crashes view = get_gnatfuzz_view() if view is not None: view.refresh() # The end condition tasks = [t for t in GPS.Task.list() if t.name() == "gnatfuzz fuzz"] if len(tasks) == 0: break return
def yield_close(self): GPS.MDI.get("Search").close() yield timeout(500)