def driver(): buf = GPS.EditorBuffer.get(GPS.File("hello.adb")) view = buf.current_view() expected_orig = buf.get_chars() # Select a bit buf.select(buf.at(5, 3), buf.at(6, 6)) yield timeout(200) # get the low-level textview v = pygps.get_widgets_by_type(Gtk.TextView, view.pywidget())[0] # simulate a click at coordinates 40, 5: regardless of the font, # this is somewhere on the first line, well past the last character win = v.get_window(Gtk.TextWindowType.TEXT) click_in_widget(window=win, x=40, y=5, button=2) yield timeout(200) # Verify that paste happend gps_assert(buf.get_chars(), expected_after_click, """Middle click paste didn't happen at the right place""") # Verify noncorruption after Undo buf.undo() gps_assert(buf.get_chars(), expected_orig, """Undo didn't restore the right contents""")
def driver(): # Execute build & run GPS.execute_action("Build & Run Number 1") window = None # Wait until the main is running in the output window while not window: yield timeout(100) window = GPS.MDI.get("Run: hello" + (".exe" if sys.platform == "win32" else "")) # Wait one second... yield timeout(1000) # Then wait until idle. # What we're trying to do here is verify that the main loop has cycles # to respond to the requests, ie it should become idle before we hit # a timeout, even if the process being launched is outputing characters # for 3 minutes # TODO: find a way to check that the main loop is responsive # Interrupt the task [t for t in GPS.Task.list() if t.name() == "Run Main"][0].interrupt()
def driver(): # Launch a program that will run forever GPS.execute_action("Build & Run Number 1") # Wait until the command appears while True: tasks = filter(lambda x: x.name() == "Run Main", GPS.Task.list()) if len(tasks) == 1: break yield timeout(100) # Wait a bit more yield timeout(100) # Interrupt the command tasks[0].interrupt() # Wait a bit and verify that the process interruption is showing in # the console yield timeout(100) if "linux" in sys.platform: console = GPS.Console("Run: main") else: console = GPS.Console("Run: main.exe") gps_assert( "process interrupted" in console.get_text(), True, "the console didn't see the process ending: {}".format( console.get_text())) # Now destroy the console: this shouldn't crash console.destroy() yield timeout(100)
def driver(): b = GPS.EditorBuffer.get(GPS.File("main.adb")) b.current_view().goto(b.at(4, 7)) yield wait_tasks(other_than=known_tasks) # First verify that the navigation does *not* work GPS.execute_action('goto declaration') # At this point "language_server_response_processed" shouldn't work, # timeout instead yield timeout(500) current_buf = GPS.EditorBuffer.get() gps_assert(current_buf.file(), GPS.File('main.adb'), "'goto declaration' should not have worked at this point") # Now set the project path and reload the project GPS.setenv("GPR_PROJECT_PATH", os.path.join(GPS.pwd(), "subdir")) # Restart the language server GPS.LanguageServer.get_by_language_name("Ada").restart() GPS.Project.load("p.gpr") yield timeout(1000) # Verify that the navigation works now b = GPS.EditorBuffer.get(GPS.File("main.adb")) b.current_view().goto(b.at(4, 7)) GPS.execute_action('goto declaration') yield timeout(500) gps_assert(GPS.EditorBuffer.get().file(), GPS.File('foo.ads'), "'goto declaration' did not open the right file")
def driver(): # type 'foo' in the omnisearch yield wait_tasks() w = pygps.get_widget_by_name('global_search') w.get_toplevel().grab_focus() yield wait_idle() w.grab_focus() yield wait_idle() w.set_text("foo") yield timeout(1000) popup = pygps.get_widget_by_name('global_search-results-list') results_tree = pygps.get_widgets_by_type(Gtk.TreeView, popup)[0] # select "foo.adb" file click_in_tree(results_tree, path="0", column=1) yield timeout(1000) if not GPS.EditorBuffer.get().file().name().endswith("foo.adb"): simple_error("foo.adb is not opened") # retype 'foo' in the omnisearch w.get_toplevel().grab_focus() yield wait_idle() w.grab_focus() yield wait_idle() w.set_text("foo") yield timeout(1000) # check whether we have result from the History provider popup = pygps.get_widget_by_name('global_search-results-list') results_tree = pygps.get_widgets_by_type(Gtk.TreeView, popup)[0] result = dump_tree_model(results_tree.get_model(), 3) gps_assert("History (1)" in result, True, "wrong omnisearch result")
def run_test(): ls_pid = get_language_server_pid() gps_assert(ls_pid is not None, True, "couldn't get the language server PID") # Kill the language server os.kill(ls_pid, signal.SIGKILL) # Wait for the language server to relaunch yield hook("language_server_started") # Give the language server the time to process all the events # (init, didChangeConfiguration, didOpenFile, etc) # because otherwise the call to "lanugage_server_response_processed" # below will catch one of those. yield timeout(1000) # Get the new language server PID new_ls_pid = get_language_server_pid() gps_assert(new_ls_pid is not None, True, "couldn't get the new language server PID after kill") gps_assert(ls_pid != new_ls_pid, True, "the language server wasn't killed") # Verify the functionality of the new language server buf = GPS.EditorBuffer.get(GPS.File('main.adb')) buf.current_view().goto(buf.at(5, 10)) # wait LSP responses has been processed to have folding information if GPS.LanguageServer.is_enabled_for_language_name("Ada"): yield wait_tasks(other_than=known_tasks) GPS.execute_action('goto declaration') yield hook("language_server_response_processed") current_buf = GPS.EditorBuffer.get() gps_assert(current_buf.file(), GPS.File('hello_world.ads'), "'goto declaration' did not open the right file") # Verify that there isn't the error message in the console gps_assert("had to be restarted more than" in GPS.Console().get_text(), False, "the error message about language server showed unexpectedly") # Now try to kill the language server too many times for j in range(5): ls_pid = get_language_server_pid() if ls_pid: os.kill(ls_pid, signal.SIGKILL) yield timeout(200) # Verify that there is the error message in the console gps_assert("had to be restarted more than" in GPS.Console().get_text(), True, "the error message about language server showed unexpectedly")
def driver(): GPS.EditorBuffer.get(GPS.File("p.ads")) GPS.execute_action("gnatfuzz analyze file workflow") messages = [] # Wait at most 2 seconds for messages to appear in the locations view time_waited = 0 while time_waited < 2000: yield timeout(100) time_waited += 100 messages = GPS.Message.list("Fuzzable Subprograms") if len(messages) > 0: break gps_assert(len(messages) > 0, True, "No messages found after analyze") m = messages[0] # We have one "Fuzzable program" message: click on the action yield idle_modal_dialog(lambda: m.execute_action()) dialog = get_window_by_title("gnatfuzz analyze") # The confirmation dialog to switch to the harness project should pop up yield idle_modal_dialog( lambda: get_button_from_label("Execute", dialog).clicked()) dialog = get_window_by_title("Confirmation") get_button_from_label("Yes", dialog).clicked() yield wait_tasks() # Check that we've switched to the harness project gps_assert(GPS.Project.root().name(), "Fuzz_Test", "wrong project name after generation")
def driver(): b = GPS.EditorBuffer.get(GPS.File("p.adb")) yield wait_tasks() v = b.current_view() v.goto(b.at(9, 8)) GPS.execute_action("Macro Start Keyboard") send_key_event(ord('o')) yield timeout(200) send_key_event(ord('o')) yield timeout(200) GPS.execute_action("Macro Stop") v.goto(b.at(9, 1)) GPS.execute_action("Macro Play") # Let the macro execute yield timeout(1000) gps_assert(b.get_chars(b.at(9, 1), b.at(9, 4)), "oo ", "Macro playback was hindered by completion")
def driver(): yield wait_tasks() b = GPS.EditorBuffer.get(GPS.File("t.cpp")) # Wait until the semantic tree is available, then move the cursor yield hook('semantic_tree_updated') # Move the cursor line by line and verify that GPS doesn't freeze for line in range(20, 40): b.current_view().goto(b.at(line, 1)) yield timeout(500)
def wf(task): """The task that does random edits on the buffer""" choices = [insert_random, delete_random] for j in range(N_OPERATIONS): # Do a random operation fun = random.choice(choices) fun(g) # timeout from time to time so the display and progress bar can # refresh if j % 10 == 0: yield timeout(50) task.set_progress(j, N_OPERATIONS)
def driver(): yield wait_tasks() b = GPS.EditorBuffer.get(GPS.File("p.ads")) # Execute a first "find all references" for Foo and check the result b.current_view().goto(b.at(2, 4)) GPS.execute_action("Find All References") yield wait_language_server("textDocument/references") gps_assert(len(GPS.Message.list(category="References for Foo (p.ads:2)")), 2, "There should be two references for Foo") # Simulate a file change on the filesystem for a file that has never # been opened shutil.copy("q.ads.lots", "q.ads") # Wait a bit for the filesystem + the ALS to catch up yield timeout(2000) # Re-execute the request and verify that we have updated results b.current_view().goto(b.at(2, 4)) GPS.execute_action("Find All References") yield wait_language_server("textDocument/references") gps_assert(len(GPS.Message.list(category="References for Foo (p.ads:2)")), 5, "There should now be five references for Foo") # Now do the same as above, after deleting the file os.remove("q.ads") yield timeout(2000) b.current_view().goto(b.at(2, 4)) GPS.execute_action("Find All References") yield wait_language_server("textDocument/references") gps_assert(len(GPS.Message.list(category="References for Foo (p.ads:2)")), 1, "There should now be one references for Foo")
def run_test(): buf = GPS.EditorBuffer.get(GPS.File('f.cpp')) buf.current_view().goto(buf.at(5, 4)) yield wait_tasks() GPS.execute_action('goto declaration') yield timeout(2000) buf = GPS.EditorBuffer.get() basename = os.path.basename(buf.file().name()) gps_assert(buf.get_lang().name, "c++", "wrong lang for hop.hpp") gps_assert(basename, "foo.hpp", "did not navigate to the foo.hpp file, but {}".format(basename)) buf.current_view().goto(buf.at(4, 24)) GPS.execute_action('goto declaration') yield timeout(2000) buf = GPS.EditorBuffer.get() basename = os.path.basename(buf.file().name()) gps_assert(buf.get_lang().name, "c++", "wrong lang for bar.hpp") gps_assert(basename, "bar.hpp", "did not navigate to the bar.hpp file, but {}".format(basename))
def driver(): # Execute build & run GPS.execute_action("Build & Run Number 1") window = None # Wait until the main is running in the output window while not window: yield timeout(100) window = GPS.MDI.get("Run: hello" + (".exe" if sys.platform == "win32" else "")) view = pygps.get_widgets_by_type(Gtk.TextView, window.pywidget())[0] # Interrupt the task [t for t in GPS.Task.list() if t.name() == "Run Main"][0].interrupt() # Send a couple of Enter keys view.grab_focus() yield timeout(100) send_key_event(GDK_RETURN) yield timeout(100) send_key_event(GDK_RETURN)
def driver(): b = GPS.EditorBuffer.get(GPS.File("hello.adb")) v = b.current_view() # wait LSP responses has been processed if GPS.LanguageServer.is_enabled_for_language_name("Ada"): yield wait_tasks(other_than=known_tasks) yield timeout(1000) b.blocks_fold() gps_assert(b.get_chars(include_hidden_chars=False), expected_1, "block folding didn't happen") b.insert(b.at(7, 19), "a") gps_assert(b.get_chars(include_hidden_chars=False), expected_2, "contents not right after inserting character")
def driver(): # Open an editor and go to a line where there's a code action b = GPS.EditorBuffer.get(GPS.File("main.c")) v = b.current_view() v.goto(b.at(5, 8)) # Wait until the language server has responded to the codeAction request yield wait_language_server("textDocument/codeAction", "C") # Verify that one codeAction message has been created m = GPS.Message.list() gps_assert(len(m), 1, "there should be one message at this point") gps_assert(m[0].get_category(), "_internal_code_actions", "we have a message, but not in the expected category") # Click on the side action b.click_on_side_icon(5, 1, "gps-codefix") # Allow a timeout for the asynchronous popup of the menu yield timeout(1000) menu = get_widget_by_name("gnatstudio_code_actions_menu") gps_assert(menu is not None, True, "no menu found") # Check that the menu contains the "Name parameters" action item = menu.get_children()[0] gps_assert(item.get_label(), "Expand macro 'FOO'", "the menu item doesn' have the right title") # Now activate the menu item and wait for the application of the edits item.activate() yield wait_language_server("workspace/executeCommand", "C") # Check that the edits have been received gps_assert( b.get_chars(b.at(5, 1), b.at(6, 1)).strip(), 'if (0 > 2)', "edits not received") yield wait_language_server("textDocument/codeAction", "C") m = GPS.Message.list(category="_internal_code_actions") gps_assert(len(m), 0, "there should be no code action message")
def driver(): # Launch a fuzzing session yield idle_modal_dialog( lambda: GPS.execute_action("gnatfuzz fuzz workflow")) yield wait_for_mdi_child("gnatfuzz fuzz") dialog = get_window_by_title("gnatfuzz fuzz") get_button_from_label("Execute", dialog).clicked() yield wait_for_mdi_child("Fuzz Crashes") view = get_widget_by_name("fuzz_crash_list_view") model = view.get_model() # Wait 20 seconds at most, until messages appear in the "Fuzz crashes" view time_waited = 0 while time_waited < MAX_TIME_MS: if len(model) > 0: break yield timeout(INCREMENTS_MS) time_waited += INCREMENTS_MS # Test the contents of the model: presence of the crash... gps_assert(model[0][0], "1 (Crash)", "wrong contents in the first row") # ... and the fact that the faulty parameter (causing integer overflow) # is properly found by the fuzzer and displayed in the view. gps_assert( int(model[0, 0][1]), 2**31 - 1, "wrong value for the parameter which causes the crash", ) # We can stop fuzzing now that we've had one crash GPS.execute_action("gnatfuzz fuzz workflow") # Click in the view to launch a debug workflow click_in_tree(view, path="0", events=double_click_events) # Wait 20 seconds at most, until we have the right data in the debugger view debugger_text = None time_waited = 0 expected_text = "Y := X + 1" while time_waited < MAX_TIME_MS: yield timeout(INCREMENTS_MS) time_waited += INCREMENTS_MS d = None try: d = GPS.Debugger.get() except GPS.Exception: pass if d is None: continue debugger_text = d.get_console().get_text() # The debugger console should contain this if expected_text in debugger_text: break gps_assert(expected_text in debugger_text, True, f"{expected_text} didn't appear in output:\n{debugger_text}") # Quit the debugger GPS.execute_action("terminate all debuggers") yield wait_idle() # Restart a fuzz session... yield idle_modal_dialog( lambda: GPS.execute_action("gnatfuzz fuzz workflow")) yield wait_for_mdi_child("gnatfuzz fuzz") dialog = get_window_by_title("gnatfuzz fuzz") get_button_from_label("Execute", dialog).clicked() # ... and kill it immediately yield timeout(100) GPS.execute_action("gnatfuzz fuzz workflow") # And verify that the Fuzz crashes view is empty gps_assert(len(model), 0, "The Fuzz crashes view should clear when starting a session")