From 76f40dd54bbfa760a748c3e1661246b0bad4a5a5 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Sun, 31 May 2020 13:24:53 +0200 Subject: [PATCH 01/36] comment to integrate in IntelliJ and handle OSGi errors --- sqldev/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sqldev/pom.xml b/sqldev/pom.xml index 86c63539..8d2d6a30 100644 --- a/sqldev/pom.xml +++ b/sqldev/pom.xml @@ -370,6 +370,13 @@ + + + + + + + org.apache.felix maven-bundle-plugin 4.2.1 From a26d6f4e748e78aa34eab3848082cc9eded42fa9 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Sun, 31 May 2020 14:08:30 +0200 Subject: [PATCH 02/36] extend .gitignore regarding IntelliJ, SonarQube and more --- .gitignore | 50 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 410561c1..ba2ce844 100644 --- a/.gitignore +++ b/.gitignore @@ -1,27 +1,47 @@ +# Compiled class file *.class -*._trace -*.xtendbin -*.DS_Store + +# Log file *.log -**/target -**/bin -**/test-output -**/xtend-gen -**/.sonar -**/.project -**/.classpath -**/.settings -**/.idea -# Mobile Tools for Java (J2ME) -.mtj.tmp/ -# Package Files # + +# Package Files *.jar *.war +*.nar *.ear +*.zip +*.tar.gz +*.rar # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* +# Xtend +*._trace +*.xtendbin +**/xtend-gen + +# SonarQube +**/.sonar +**/.scannerwork + +# Eclipse / Visual Studio Code +.project +.classpath +**/.settings + +# IntelliJ +**/.idea +*.iml + +# macOS +*.DS_Store + +# Windows Thumbs.db + +# Targets +**/target +**/bin From cd109b2e3ae094f2dee57102950cf6812c1a6cd6 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Sun, 31 May 2020 19:36:35 +0200 Subject: [PATCH 03/36] change resource files to UTF-8 and escape umlauts --- .../resources/UtplsqlResources.properties | 216 +++++++++--------- .../resources/UtplsqlResources_de.properties | 169 +++++++------- 2 files changed, 193 insertions(+), 192 deletions(-) diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties index 141984bf..0165c608 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties @@ -1,108 +1,108 @@ -# English (default) resources for extension org.utplsql.sqldev - -# Externally used constants (pom.xml, bundle.xml, extension.xml, sqldeveloper.xml) -EXTENSION_NAME=utPLSQL for SQL Developer -EXTENSION_DESCRIPTION=Extension for running unit tests in SQL Developer. -EXTENSION_OWNER=Philipp Salvisberg -MIN_SQLDEV_VERSION=12.2.0.19.0.7 - -# Icons -UTPLSQL_ICON=/org/utplsql/sqldev/resources/images/utPLSQL.png -SUCCESS_ICON=/org/utplsql/sqldev/resources/images/success.png -ERROR_ICON=/org/utplsql/sqldev/resources/images/error.png -FAILURE_ICON=/org/utplsql/sqldev/resources/images/failure.png -DISABLED_ICON=/org/utplsql/sqldev/resources/images/disabled.png -WARNING_ICON=/org/utplsql/sqldev/resources/images/warning.png -INFO_ICON=/org/utplsql/sqldev/resources/images/info.png -REFRESH_ICON=/org/utplsql/sqldev/resources/images/refresh.png -RUN_ICON=/org/utplsql/sqldev/resources/images/run.png -RUN_WORKSHEET_ICON=/org/utplsql/sqldev/resources/images/run_worksheet.png -CLEAR_ICON=/org/utplsql/sqldev/resources/images/clear.png -CHECKMARK_ICON=/org/utplsql/sqldev/resources/images/checkmark.png -STATUS_ICON=/org/utplsql/sqldev/resources/images/status.png -# progress.gif - the animated version - does not work -PROGRESS_ICON=/org/utplsql/sqldev/resources/images/progress.png -CODE_COVERAGE_ICON=/org/utplsql/sqldev/resources/images/coverage.png - -# Translatable text -PREF_LABEL=utPLSQL -PREF_USE_REALTIME_REPORTER_LABEL=Use realtime reporter? -PREF_USE_REALTIME_REPORTER_HINT=Requires utPLSQL v3.1.4 or later. Opens a worksheet for older versions. -PREF_UNSHARED_WORKSHEET_LABEL=Open an unshared worksheet? -PREF_RESET_PACKAGE_LABEL=Reset package before running utPLSQL? -PREF_CLEAR_SCREEN_LABEL=Clear script output panel before running utPLSQL? -PREF_AUTO_EXECUTE_LABEL=Execute unit test automatically? -PREF_CHECK_RUN_UTPLSQL_TEST_LABEL=Check availability of menu option? -PREF_USE_SMART_TIMES_LABEL=Use smart times? -PREF_IMPORT_SNIPPETS_BUTTON_LABEL=Import Snippets -MENU_REALTIME_REPORTER_LABEL=Realtime Reporter -PREF_NUMBER_OF_RUNS_IN_HISTORY_LABEL=Number of runs in history -PREF_SHOW_DISABLED_COUNTER_LABEL=Show disabled counter? -PREF_SHOW_WARNINGS_COUNTER_LABEL=Show warnings counter? -PREF_SHOW_INFO_COUNTER_LABEL=Show info counter? -PREF_SHOW_WARNING_INDICATOR_LABEL=Show warning indicator? -PREF_SHOW_INFO_INDICATOR_LABEL=Show info indicator? -PREF_SHOW_SUCCESSFUL_TESTS_LABEL=Show successful tests? -PREF_SHOW_DISABLED_TESTS_LABEL=Show disabled tests? -PREF_SHOW_TEST_DESCRIPTION_LABEL=Show description (if present)? -PREF_SYNC_DETAIL_TAB_LABEL=Synchronize detail tab based on test status? -PREF_TEST_PACKAGE_PREFIX_LABEL=Test package prefix -PREF_TEST_PACKAGE_SUFFIX_LABEL=Test package suffix -PREF_TEST_UNIT_PREFIX_LABEL=Test unit prefix -PREF_TEST_UNIT_SUFFIX_LABEL=Test unit suffix -PREF_NUMBER_OF_TESTS_PER_UNIT_LABEL=Number of tests to generate per unit -PREF_GENERATE_COMMENTS_LABEL=Generate comments? -PREF_DISABLE_TESTS_LABEL=Disable tests? -PREF_SUITE_PATH_LABEL=Suite path -PREF_INDENT_SPACES_LABEL=Indent spaces -PREF_CHECK_GENERATE_UTPLSQL_TEST_LABEL=Check availability of menu option? -PREF_CREATE_CODE_TEMPLATES_BUTTON_LABEL=Create code templates -PREF_ROOT_FOLDER_IN_ODDGEN_VIEW_LABEL=Root folder in Generators view -PREF_GENERATE_FILES_LABEL=Generate files? -PREF_OUTPUT_DIRECTORY_LABEL=Output directory -PREF_OUTPUT_DIRECTORY_BUTTON_LABEL=Browse -PREF_DELETE_EXISTING_FILES_LABEL=Delete existing files in output directory? -PREF_CONFIRM_IMPORT_TITLE=Snippets imported -PREF_CONFIRM_IMPORT_MESSAGE=Snippets imported into %s. Please restart SQL Developer for this change to take effect. -MENU_RUN_TEST_LABEL=Run utPLSQL test -MENU_CODE_COVERAGE_LABEL=Code coverage... -MENU_GENERATE_TEST_LABEL=Generate utPLSQL test -WINDOW_CODE_COVERAGE_REPORT_LABEL=Code coverage report -WINDOW_PATHS_LABEL=utPLSQL paths -WINDOW_SCHEMAS_LABEL=Schemas under test -WINDOW_INCLUDE_OBJECS_LABEL=Include objects -WINDOW_EXCLUDE_OBJECS_LABEL=Exclude objects -WINDOW_RUN_BUTTON=Run -WINDOW_CANCEL_BUTTON=Cancel -WORKSHEET_TITLE=utPLSQL -RUNNER_VIEW_TITLE=utPLSQL -RUNNER_REFRESH_TOOLTIP=Reset ordering and refresh -RUNNER_RERUN_TOOLTIP=Rerun all tests -RUNNER_CLEAR_BUTTON=Clear run history -RUNNER_RERUN_WORKSHEET_TOOLTIP=Rerun all tests in a new worksheet -RUNNER_CODE_COVERAGE_TOOLTIP=Rerun all tests with code coverage -RUNNER_TESTS_LABEL=Tests -RUNNER_FAILURES_LABEL=Failures -RUNNER_ERRORS_LABEL=Errors -RUNNER_DISABLED_LABEL=Disabled -RUNNER_WARNINGS_LABEL=Warnings -RUNNER_INFO_LABEL=Info -RUNNER_INITIALIZING_TEXT=Initializing... -RUNNER_RUNNING_TEXT=Running tests... -RUNNER_FINNISHED_TEXT=Finished. -RUNNER_NO_TESTS_FOUND_TEXT=No tests found. -RUNNER_RUN_MENUITEM=Run test -RUNNER_RUN_WORKSHEET_MENUITEM=Run test in new worksheet -RUNNER_TEST_ID_COLUMN=Suitepath -RUNNER_TEST_EXECUTION_TIME_COLUMN=Time -RUNNER_OWNER_LABEL=Owner -RUNNER_PACKAGE_LABEL=Package -RUNNER_PROCEDURE_LABEL=Procedure -RUNNER_DESCRIPTION_LABEL=Description -RUNNER_START_LABEL=Start -RUNNER_ASSERT_DESCRIPTION_COLUMN=Assert description (failed line) -RUNNER_TEST_TAB_LABEL=Test -RUNNER_FAILURES_TAB_LABEL=Failures -RUNNER_ERRORS_TAB_LABEL=Errors -RUNNER_WARNINGS_TAB_LABEL=Warnings -RUNNER_INFO_TAB_LABEL=Info +# English (default) resources for extension org.utplsql.sqldev + +# Externally used constants (pom.xml, bundle.xml, extension.xml, sqldeveloper.xml) +EXTENSION_NAME=utPLSQL for SQL Developer +EXTENSION_DESCRIPTION=Extension for running unit tests in SQL Developer. +EXTENSION_OWNER=Philipp Salvisberg +MIN_SQLDEV_VERSION=12.2.0.19.0.7 + +# Icons +UTPLSQL_ICON=/org/utplsql/sqldev/resources/images/utPLSQL.png +SUCCESS_ICON=/org/utplsql/sqldev/resources/images/success.png +ERROR_ICON=/org/utplsql/sqldev/resources/images/error.png +FAILURE_ICON=/org/utplsql/sqldev/resources/images/failure.png +DISABLED_ICON=/org/utplsql/sqldev/resources/images/disabled.png +WARNING_ICON=/org/utplsql/sqldev/resources/images/warning.png +INFO_ICON=/org/utplsql/sqldev/resources/images/info.png +REFRESH_ICON=/org/utplsql/sqldev/resources/images/refresh.png +RUN_ICON=/org/utplsql/sqldev/resources/images/run.png +RUN_WORKSHEET_ICON=/org/utplsql/sqldev/resources/images/run_worksheet.png +CLEAR_ICON=/org/utplsql/sqldev/resources/images/clear.png +CHECKMARK_ICON=/org/utplsql/sqldev/resources/images/checkmark.png +STATUS_ICON=/org/utplsql/sqldev/resources/images/status.png +# progress.gif - the animated version - does not work +PROGRESS_ICON=/org/utplsql/sqldev/resources/images/progress.png +CODE_COVERAGE_ICON=/org/utplsql/sqldev/resources/images/coverage.png + +# Translatable text +PREF_LABEL=utPLSQL +PREF_USE_REALTIME_REPORTER_LABEL=Use realtime reporter? +PREF_USE_REALTIME_REPORTER_HINT=Requires utPLSQL v3.1.4 or later. Opens a worksheet for older versions. +PREF_UNSHARED_WORKSHEET_LABEL=Open an unshared worksheet? +PREF_RESET_PACKAGE_LABEL=Reset package before running utPLSQL? +PREF_CLEAR_SCREEN_LABEL=Clear script output panel before running utPLSQL? +PREF_AUTO_EXECUTE_LABEL=Execute unit test automatically? +PREF_CHECK_RUN_UTPLSQL_TEST_LABEL=Check availability of menu option? +PREF_USE_SMART_TIMES_LABEL=Use smart times? +PREF_IMPORT_SNIPPETS_BUTTON_LABEL=Import Snippets +MENU_REALTIME_REPORTER_LABEL=Realtime Reporter +PREF_NUMBER_OF_RUNS_IN_HISTORY_LABEL=Number of runs in history +PREF_SHOW_DISABLED_COUNTER_LABEL=Show disabled counter? +PREF_SHOW_WARNINGS_COUNTER_LABEL=Show warnings counter? +PREF_SHOW_INFO_COUNTER_LABEL=Show info counter? +PREF_SHOW_WARNING_INDICATOR_LABEL=Show warning indicator? +PREF_SHOW_INFO_INDICATOR_LABEL=Show info indicator? +PREF_SHOW_SUCCESSFUL_TESTS_LABEL=Show successful tests? +PREF_SHOW_DISABLED_TESTS_LABEL=Show disabled tests? +PREF_SHOW_TEST_DESCRIPTION_LABEL=Show description (if present)? +PREF_SYNC_DETAIL_TAB_LABEL=Synchronize detail tab based on test status? +PREF_TEST_PACKAGE_PREFIX_LABEL=Test package prefix +PREF_TEST_PACKAGE_SUFFIX_LABEL=Test package suffix +PREF_TEST_UNIT_PREFIX_LABEL=Test unit prefix +PREF_TEST_UNIT_SUFFIX_LABEL=Test unit suffix +PREF_NUMBER_OF_TESTS_PER_UNIT_LABEL=Number of tests to generate per unit +PREF_GENERATE_COMMENTS_LABEL=Generate comments? +PREF_DISABLE_TESTS_LABEL=Disable tests? +PREF_SUITE_PATH_LABEL=Suite path +PREF_INDENT_SPACES_LABEL=Indent spaces +PREF_CHECK_GENERATE_UTPLSQL_TEST_LABEL=Check availability of menu option? +PREF_CREATE_CODE_TEMPLATES_BUTTON_LABEL=Create code templates +PREF_ROOT_FOLDER_IN_ODDGEN_VIEW_LABEL=Root folder in Generators view +PREF_GENERATE_FILES_LABEL=Generate files? +PREF_OUTPUT_DIRECTORY_LABEL=Output directory +PREF_OUTPUT_DIRECTORY_BUTTON_LABEL=Browse +PREF_DELETE_EXISTING_FILES_LABEL=Delete existing files in output directory? +PREF_CONFIRM_IMPORT_TITLE=Snippets imported +PREF_CONFIRM_IMPORT_MESSAGE=Snippets imported into %s. Please restart SQL Developer for this change to take effect. +MENU_RUN_TEST_LABEL=Run utPLSQL test +MENU_CODE_COVERAGE_LABEL=Code coverage... +MENU_GENERATE_TEST_LABEL=Generate utPLSQL test +WINDOW_CODE_COVERAGE_REPORT_LABEL=Code coverage report +WINDOW_PATHS_LABEL=utPLSQL paths +WINDOW_SCHEMAS_LABEL=Schemas under test +WINDOW_INCLUDE_OBJECS_LABEL=Include objects +WINDOW_EXCLUDE_OBJECS_LABEL=Exclude objects +WINDOW_RUN_BUTTON=Run +WINDOW_CANCEL_BUTTON=Cancel +WORKSHEET_TITLE=utPLSQL +RUNNER_VIEW_TITLE=utPLSQL +RUNNER_REFRESH_TOOLTIP=Reset ordering and refresh +RUNNER_RERUN_TOOLTIP=Rerun all tests +RUNNER_CLEAR_BUTTON=Clear run history +RUNNER_RERUN_WORKSHEET_TOOLTIP=Rerun all tests in a new worksheet +RUNNER_CODE_COVERAGE_TOOLTIP=Rerun all tests with code coverage +RUNNER_TESTS_LABEL=Tests +RUNNER_FAILURES_LABEL=Failures +RUNNER_ERRORS_LABEL=Errors +RUNNER_DISABLED_LABEL=Disabled +RUNNER_WARNINGS_LABEL=Warnings +RUNNER_INFO_LABEL=Info +RUNNER_INITIALIZING_TEXT=Initializing... +RUNNER_RUNNING_TEXT=Running tests... +RUNNER_FINNISHED_TEXT=Finished. +RUNNER_NO_TESTS_FOUND_TEXT=No tests found. +RUNNER_RUN_MENUITEM=Run test +RUNNER_RUN_WORKSHEET_MENUITEM=Run test in new worksheet +RUNNER_TEST_ID_COLUMN=Suitepath +RUNNER_TEST_EXECUTION_TIME_COLUMN=Time +RUNNER_OWNER_LABEL=Owner +RUNNER_PACKAGE_LABEL=Package +RUNNER_PROCEDURE_LABEL=Procedure +RUNNER_DESCRIPTION_LABEL=Description +RUNNER_START_LABEL=Start +RUNNER_ASSERT_DESCRIPTION_COLUMN=Assert description (failed line) +RUNNER_TEST_TAB_LABEL=Test +RUNNER_FAILURES_TAB_LABEL=Failures +RUNNER_ERRORS_TAB_LABEL=Errors +RUNNER_WARNINGS_TAB_LABEL=Warnings +RUNNER_INFO_TAB_LABEL=Info diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties index 44bcbdcf..4d348012 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties @@ -1,84 +1,85 @@ -# German resources for extension org.utplsql.sqldev - -# Translatable text -PREF_LABEL=utPLSQL -PREF_USE_REALTIME_REPORTER_LABEL=Realtime Reporter verwenden? -PREF_USE_REALTIME_REPORTER_HINT=Benötigt utPLSQL v3.1.4 oder neuer. Öffnet ein Arbeitsblatt für ältere Versionen. -PREF_UNSHARED_WORKSHEET_LABEL=Arbeitsblatt mit eigener Verbindung öffnen? -PREF_RESET_PACKAGE_LABEL=Package vor der Ausführung von utPLSQL zurücksetzen? -PREF_CLEAR_SCREEN_LABEL=Skriptausgabe-Fenster vor der Ausführung von utPLSQL leeren? -PREF_AUTO_EXECUTE_LABEL=Unit Test automatisch ausführen? -PREF_CHECK_RUN_UTPLSQL_TEST_LABEL=Verfügbarkeit der Menüoption prüfen? -PREF_USE_SMART_TIMES_LABEL=Smarte Zeitangaben verwenden? -PREF_IMPORT_SNIPPETS_BUTTON_LABEL=Code-Schnipsel importieren -MENU_REALTIME_REPORTER_LABEL=Realtime Reporter -PREF_NUMBER_OF_RUNS_IN_HISTORY_LABEL=Anzahl Ausführungen in der Historie -PREF_SHOW_DISABLED_COUNTER_LABEL=Deaktiviert-Zähler anzeigen? -PREF_SHOW_WARNINGS_COUNTER_LABEL=Warnungen-Zähler anzeigen? -PREF_SHOW_INFO_COUNTER_LABEL=Info-Zähler anzeigen? -PREF_SHOW_WARNING_INDICATOR_LABEL=Warnung-Indikator anzeigen? -PREF_SHOW_INFO_INDICATOR_LABEL=Info-Indikator anzeigen? -PREF_SHOW_SUCCESSFUL_TESTS_LABEL=Erfolgreiche Tests anzeigen? -PREF_SHOW_DISABLED_TESTS_LABEL=Deaktivierte Tests anzeigen? -PREF_SHOW_TEST_DESCRIPTION_LABEL=Beschreibung anzeigen (falls vorhanden)? -PREF_SYNC_DETAIL_TAB_LABEL=Detailansicht basierend auf dem Teststatus synchronisieren? -PREF_TEST_PACKAGE_PREFIX_LABEL=Test Package Präfix -PREF_TEST_PACKAGE_SUFFIX_LABEL=Test Package Suffix -PREF_TEST_UNIT_PREFIX_LABEL=Test Unit Präfix -PREF_TEST_UNIT_SUFFIX_LABEL=Test Unit Suffix -PREF_NUMBER_OF_TESTS_PER_UNIT_LABEL=Anzahl zu generierende Tests pro Unit -PREF_GENERATE_COMMENTS_LABEL=Kommentare generieren? -PREF_DISABLE_TESTS_LABEL=Tests deaktivieren? -PREF_SUITE_PATH_LABEL=Suite-Pfad -PREF_INDENT_SPACES_LABEL=Einrückungsleerzeichen -PREF_CHECK_GENERATE_UTPLSQL_TEST_LABEL=Verfügbarkeit der Menüoption prüfen? -PREF_CREATE_CODE_TEMPLATES_BUTTON_LABEL=Codevorlagen erstellen -PREF_ROOT_FOLDER_IN_ODDGEN_VIEW_LABEL=Hauptverzeichnis in Generatoren Ansicht -PREF_GENERATE_FILES_LABEL=Dateien generieren? -PREF_OUTPUT_DIRECTORY_LABEL=Ausgabeverzeichnis -PREF_OUTPUT_DIRECTORY_BUTTON_LABEL=Auswählen -PREF_DELETE_EXISTING_FILES_LABEL=Bestehende Dateien im Ausgabeverzeichnis löschen? -PREF_CONFIRM_IMPORT_TITLE=Code-Schnipsel importiert -PREF_CONFIRM_IMPORT_MESSAGE=Code-Schnipsel in %s importiert. Bitte starten Sie den SQL Developer neu, um diese Änderung zu aktivieren. -MENU_RUN_TEST_LABEL=utPLSQL Test ausführen -MENU_CODE_COVERAGE_LABEL=Codeabdeckung... -MENU_GENERATE_TEST_LABEL=utPLSQL Test generieren -WINDOW_CODE_COVERAGE_REPORT_LABEL=Codeabdeckungs-Bericht -WINDOW_PATHS_LABEL=utPLSQL Pfade -WINDOW_SCHEMAS_LABEL=Schemata unter Test -WINDOW_INCLUDE_OBJECS_LABEL=Inkludierte Objekte -WINDOW_EXCLUDE_OBJECS_LABEL=Exkludierte Objekte -WINDOW_RUN_BUTTON=Start -WINDOW_CANCEL_BUTTON=Abbrechen -WORKSHEET_TITLE=utPLSQL -RUNNER_VIEW_TITLE=utPLSQL -RUNNER_REFRESH_TOOLTIP=Sortierung zurücksetzen und aktualisieren -RUNNER_RERUN_TOOLTIP=Alle Tests erneut ausführen -RUNNER_RERUN_WORKSHEET_TOOLTIP=Alle Tests in einem neuen Arbeitsblatt erneut ausführen -RUNNER_CODE_COVERAGE_TOOLTIP=Alle Tests mit Codeabdeckung ausführen -RUNNER_CLEAR_BUTTON=Run History löschen -RUNNER_TESTS_LABEL=Tests -RUNNER_FAILURES_LABEL=Fehlschläge -RUNNER_ERRORS_LABEL=Fehler -RUNNER_DISABLED_LABEL=Deaktiviert -RUNNER_WARNINGS_LABEL=Warnungen -RUNNER_INFO_LABEL=Info -RUNNER_INITIALIZING_TEXT=Initialisierung... -RUNNER_RUNNING_TEXT=Starte Tests... -RUNNER_FINNISHED_TEXT=Beendet. -RUNNER_NO_TESTS_FOUND_TEXT=Keine Tests gefunden. -RUNNER_RUN_MENUITEM=Run testTest ausführen -RUNNER_RUN_WORKSHEET_MENUITEM=Test in neuem Arbeitsblatt ausführuen -RUNNER_TEST_ID_COLUMN_NAME=Suitepath -RUNNER_TEST_EXECUTION_TIME_COLUMN_NAME=Zeit -RUNNER_OWNER_LABEL=Besitzer -RUNNER_PACKAGE_LABEL=Paket -RUNNER_PROCEDURE_LABEL=Prozedur -RUNNER_DESCRIPTION_LABEL=Beschreibung -RUNNER_START_LABEL=Start -RUNNER_ASSERT_DESCRIPTION_COLUMN_NAME=Assert Beschreibung (gescheiterte Zeile) -RUNNER_TEST_TAB_LABEL=Test -RUNNER_FAILURES_TAB_LABEL=Misserfolge -RUNNER_ERRORS_TAB_LABEL=Fehler -RUNNER_WARNINGS_TAB_LABEL=Warnungen -RUNNER_INFO_TAB_LABEL=Info +# German resources for extension org.utplsql.sqldev +# UTF-8 file works, as long as Umlaut are escaped, see https://www.utf8-chartable.de/ + +# Translatable text +PREF_LABEL=utPLSQL +PREF_USE_REALTIME_REPORTER_LABEL=Realtime Reporter verwenden? +PREF_USE_REALTIME_REPORTER_HINT=Ben\u00f6tigt utPLSQL v3.1.4 oder neuer. \u00d6ffnet ein Arbeitsblatt f\u00fcr \u00e4ltere Versionen. +PREF_UNSHARED_WORKSHEET_LABEL=Arbeitsblatt mit eigener Verbindung \u00f6ffnen? +PREF_RESET_PACKAGE_LABEL=Package vor der Ausf\u00fchrung von utPLSQL zur\u00fccksetzen? +PREF_CLEAR_SCREEN_LABEL=Skriptausgabe-Fenster vor der Ausf\u00fchrung von utPLSQL leeren? +PREF_AUTO_EXECUTE_LABEL=Unit Test automatisch ausf\u00fchren? +PREF_CHECK_RUN_UTPLSQL_TEST_LABEL=Verf\u00fcgbarkeit der Men\u00fcoption pr\u00fcfen? +PREF_USE_SMART_TIMES_LABEL=Smarte Zeitangaben verwenden? +PREF_IMPORT_SNIPPETS_BUTTON_LABEL=Code-Schnipsel importieren +MENU_REALTIME_REPORTER_LABEL=Realtime Reporter +PREF_NUMBER_OF_RUNS_IN_HISTORY_LABEL=Anzahl Ausf\u00fchrungen in der Historie +PREF_SHOW_DISABLED_COUNTER_LABEL=Deaktiviert-Z\u00e4hler anzeigen? +PREF_SHOW_WARNINGS_COUNTER_LABEL=Warnungen-Z\u00e4hler anzeigen? +PREF_SHOW_INFO_COUNTER_LABEL=Info-Z\u00e4hler anzeigen? +PREF_SHOW_WARNING_INDICATOR_LABEL=Warnung-Indikator anzeigen? +PREF_SHOW_INFO_INDICATOR_LABEL=Info-Indikator anzeigen? +PREF_SHOW_SUCCESSFUL_TESTS_LABEL=Erfolgreiche Tests anzeigen? +PREF_SHOW_DISABLED_TESTS_LABEL=Deaktivierte Tests anzeigen? +PREF_SHOW_TEST_DESCRIPTION_LABEL=Beschreibung anzeigen (falls vorhanden)? +PREF_SYNC_DETAIL_TAB_LABEL=Detailansicht basierend auf dem Teststatus synchronisieren? +PREF_TEST_PACKAGE_PREFIX_LABEL=Test Package Pr\u00e4fix +PREF_TEST_PACKAGE_SUFFIX_LABEL=Test Package Suffix +PREF_TEST_UNIT_PREFIX_LABEL=Test Unit Pr\u00e4fix +PREF_TEST_UNIT_SUFFIX_LABEL=Test Unit Suffix +PREF_NUMBER_OF_TESTS_PER_UNIT_LABEL=Anzahl zu generierende Tests pro Unit +PREF_GENERATE_COMMENTS_LABEL=Kommentare generieren? +PREF_DISABLE_TESTS_LABEL=Tests deaktivieren? +PREF_SUITE_PATH_LABEL=Suite-Pfad +PREF_INDENT_SPACES_LABEL=Einr\u00fcckungsleerzeichen +PREF_CHECK_GENERATE_UTPLSQL_TEST_LABEL=Verf\u00fcgbarkeit der Men\u00fcoption pr\u00fcfen? +PREF_CREATE_CODE_TEMPLATES_BUTTON_LABEL=Codevorlagen erstellen +PREF_ROOT_FOLDER_IN_ODDGEN_VIEW_LABEL=Hauptverzeichnis in Generatoren Ansicht +PREF_GENERATE_FILES_LABEL=Dateien generieren? +PREF_OUTPUT_DIRECTORY_LABEL=Ausgabeverzeichnis +PREF_OUTPUT_DIRECTORY_BUTTON_LABEL=Ausw\u00e4hlen +PREF_DELETE_EXISTING_FILES_LABEL=Bestehende Dateien im Ausgabeverzeichnis l\u00f6schen? +PREF_CONFIRM_IMPORT_TITLE=Code-Schnipsel importiert +PREF_CONFIRM_IMPORT_MESSAGE=Code-Schnipsel in %s importiert. Bitte starten Sie den SQL Developer neu, um diese \u00c4nderung zu aktivieren. +MENU_RUN_TEST_LABEL=utPLSQL Test ausf\u00fchren +MENU_CODE_COVERAGE_LABEL=Codeabdeckung... +MENU_GENERATE_TEST_LABEL=utPLSQL Test generieren +WINDOW_CODE_COVERAGE_REPORT_LABEL=Codeabdeckungs-Bericht +WINDOW_PATHS_LABEL=utPLSQL Pfade +WINDOW_SCHEMAS_LABEL=Schemata unter Test +WINDOW_INCLUDE_OBJECS_LABEL=Inkludierte Objekte +WINDOW_EXCLUDE_OBJECS_LABEL=Exkludierte Objekte +WINDOW_RUN_BUTTON=Start +WINDOW_CANCEL_BUTTON=Abbrechen +WORKSHEET_TITLE=utPLSQL +RUNNER_VIEW_TITLE=utPLSQL +RUNNER_REFRESH_TOOLTIP=Sortierung zur\u00fccksetzen und aktualisieren +RUNNER_RERUN_TOOLTIP=Alle Tests erneut ausf\u00fchren +RUNNER_RERUN_WORKSHEET_TOOLTIP=Alle Tests in einem neuen Arbeitsblatt erneut ausf\u00fchren +RUNNER_CODE_COVERAGE_TOOLTIP=Alle Tests mit Codeabdeckung ausf\u00fchren +RUNNER_CLEAR_BUTTON=Run History l\u00f6schen +RUNNER_TESTS_LABEL=Tests +RUNNER_FAILURES_LABEL=Fehlschl\u00e4ge +RUNNER_ERRORS_LABEL=Fehler +RUNNER_DISABLED_LABEL=Deaktiviert +RUNNER_WARNINGS_LABEL=Warnungen +RUNNER_INFO_LABEL=Info +RUNNER_INITIALIZING_TEXT=Initialisierung... +RUNNER_RUNNING_TEXT=Starte Tests... +RUNNER_FINNISHED_TEXT=Beendet. +RUNNER_NO_TESTS_FOUND_TEXT=Keine Tests gefunden. +RUNNER_RUN_MENUITEM=Run testTest ausf\u00fchren +RUNNER_RUN_WORKSHEET_MENUITEM=Test in neuem Arbeitsblatt ausf\u00fchren +RUNNER_TEST_ID_COLUMN=Suitepath +RUNNER_TEST_EXECUTION_TIME_COLUMN=Zeit +RUNNER_OWNER_LABEL=Besitzer +RUNNER_PACKAGE_LABEL=Paket +RUNNER_PROCEDURE_LABEL=Prozedur +RUNNER_DESCRIPTION_LABEL=Beschreibung +RUNNER_START_LABEL=Start +RUNNER_ASSERT_DESCRIPTION_COLUMN=Assert Beschreibung (gescheiterte Zeile) +RUNNER_TEST_TAB_LABEL=Test +RUNNER_FAILURES_TAB_LABEL=Misserfolge +RUNNER_ERRORS_TAB_LABEL=Fehler +RUNNER_WARNINGS_TAB_LABEL=Warnungen +RUNNER_INFO_TAB_LABEL=Info From b3b53c77432cbfb728e3d9c3aafa3b096988150f Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Sun, 31 May 2020 20:57:04 +0200 Subject: [PATCH 04/36] simplify test, compare length instead of content --- sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.java b/sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.java index b3ebeb49..6922386f 100644 --- a/sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.java +++ b/sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.java @@ -30,11 +30,13 @@ public class SnippetTest { @Test public void mergeAsCopy() { USER_SNIPPETS_FILE.delete(); + Assert.assertFalse(USER_SNIPPETS_FILE.exists()); final SnippetMerger merger = new SnippetMerger(USER_SNIPPETS_FILE); + final String template = merger.getTemplate(); merger.merge(); Assert.assertTrue(USER_SNIPPETS_FILE.exists()); final String userSnippetsXml = new String(FileTools.readFile(USER_SNIPPETS_FILE.toPath())); - Assert.assertEquals(merger.getTemplate(), userSnippetsXml); + Assert.assertEquals(template.length(), userSnippetsXml.length()); } @Test From b21f2bf768a9a119b81f96de4d0a4a2ee60633b2 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Mon, 1 Jun 2020 22:11:56 +0200 Subject: [PATCH 05/36] add debug icon --- .../org/utplsql/sqldev/resources/images/debug.png | Bin 0 -> 622 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 sqldev/src/main/resources/org/utplsql/sqldev/resources/images/debug.png diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/images/debug.png b/sqldev/src/main/resources/org/utplsql/sqldev/resources/images/debug.png new file mode 100644 index 0000000000000000000000000000000000000000..1a27adf880fa3d7699c5d5a3ebfb32db532434b7 GIT binary patch literal 622 zcmV-!0+IcRP)Lg9g&&*_!neTP+O=uRTD-XOJUO4yMdoGv%#wko- ztI4PK(Cvu{uYVd4n*19cc~HRz$bjyHuPHv(&@mWvj|3fqL7}(d;r{oV+DuaqQfR|v zysP(cPNDOn!*3QHKg-$zCqAOsn^0aF)ly6=m#*MRe20}Cqk?RHUjJy#d(+{KYax7i zBLpv=3vHJ|aG@HEeG&8>t;yzR@dAz@nQR(t=zaP}!zZ)KC0~C3yHW*hoe~M$`h?0d zL$73Y49=mBUl8pWkjjo4c#eD*n`@>^NT!s_WkS49eaC1i4B;*!NaJsiOm^uW_R`3s zB21MaL5O(vG*N@u+{89U(s&0$(zy#llpdcanV?cBlWUI)Lv;V8a}9iq3J#@l z6%R>e-nKk5usQWrJnl26X(SuVdW{HTdC$U25eU@ zD)dAu%lp;VTcxrjQ&d;@^9FO{_pHo*ZRz%Tbm9-(N$fi3J}f#o_LfBIj7;kR$xOS( z)~c=b8LNxmn*aG5%%FsQSlDf_8|`=;T_|E5OZaOi`~QZ20eFeg679~{V*mgE07*qo IM6N<$f{Gj=egFUf literal 0 HcmV?d00001 From 3088dda3311da2ac09382b3a59ffa18747852da1 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Mon, 1 Jun 2020 22:12:23 +0200 Subject: [PATCH 06/36] add debug test label to resource bundle --- .../org/utplsql/sqldev/resources/UtplsqlResources.properties | 1 + .../org/utplsql/sqldev/resources/UtplsqlResources_de.properties | 1 + 2 files changed, 2 insertions(+) diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties index 0165c608..ebd799b0 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties @@ -66,6 +66,7 @@ PREF_CONFIRM_IMPORT_TITLE=Snippets imported PREF_CONFIRM_IMPORT_MESSAGE=Snippets imported into %s. Please restart SQL Developer for this change to take effect. MENU_RUN_TEST_LABEL=Run utPLSQL test MENU_CODE_COVERAGE_LABEL=Code coverage... +MENU_DEBUG_TEST_LABEL=Debug utPLSQL test MENU_GENERATE_TEST_LABEL=Generate utPLSQL test WINDOW_CODE_COVERAGE_REPORT_LABEL=Code coverage report WINDOW_PATHS_LABEL=utPLSQL paths diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties index 4d348012..038a1724 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties @@ -43,6 +43,7 @@ PREF_CONFIRM_IMPORT_TITLE=Code-Schnipsel importiert PREF_CONFIRM_IMPORT_MESSAGE=Code-Schnipsel in %s importiert. Bitte starten Sie den SQL Developer neu, um diese \u00c4nderung zu aktivieren. MENU_RUN_TEST_LABEL=utPLSQL Test ausf\u00fchren MENU_CODE_COVERAGE_LABEL=Codeabdeckung... +MENU_DEBUG_TEST_LABEL=utPLSQL Test debuggen MENU_GENERATE_TEST_LABEL=utPLSQL Test generieren WINDOW_CODE_COVERAGE_REPORT_LABEL=Codeabdeckungs-Bericht WINDOW_PATHS_LABEL=utPLSQL Pfade From 39cb25d63addb2e6bc16f07a83d0bbeaf0550d3c Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Mon, 1 Jun 2020 22:13:08 +0200 Subject: [PATCH 07/36] add dependencies to run debugger to pom.xml --- sqldev/pom.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sqldev/pom.xml b/sqldev/pom.xml index 8d2d6a30..c6854a1a 100644 --- a/sqldev/pom.xml +++ b/sqldev/pom.xml @@ -142,6 +142,20 @@ system ${sqldev.basedir}/jdev/extensions/oracle.jdeveloper.java.core.jar + + oracle + oracle.jdeveloper.runner.jar + 13.0.0 + system + ${sqldev.basedir}/jdev/extensions/oracle.jdeveloper.runner.jar + + + oracle + oracle.ide.runner + 19.3.0 + system + ${sqldev.basedir}/ide/extensions/oracle.ide.runner.jar + oracle @@ -412,9 +426,11 @@ oracle.javatools, oracle.javatools-nodeps, oracle.jdeveloper.db.connection, + oracle.jdeveloper.runner, oracle.idert, oracle.ide, oracle.ide.db, + oracle.ide.runner, oracle.sqldeveloper, oracle.sqldeveloper.utils, oracle.sqldeveloper.worksheet, From 3bf3fe8bc986b4a721ec377457a60cee5dcbd242 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Mon, 1 Jun 2020 22:17:23 +0200 Subject: [PATCH 08/36] add getProduceReportPlsql to be passed to the PL/SQL debugger --- .../sqldev/dal/RealtimeReporterDao.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java b/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java index 042d6810..2790af86 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java @@ -72,12 +72,23 @@ public boolean isSupported() { .normalizedUtPlsqlVersionNumber() >= RealtimeReporterDao.FIRST_VERSION_WITH_REALTIME_REPORTER; } - public void produceReport(final String reporterId, final List pathList) { + // used for execution via PL/SQL Debugger + public String getProduceReportPlsql(final String reporterId, final List pathList) { + return getProduceReportPlsql(reporterId, pathList, false); + } + + private String getProduceReportPlsql(final String reporterId, final List pathList, boolean useBindVariable) { StringBuilder sb = new StringBuilder(); sb.append("DECLARE\n"); sb.append(" l_reporter ut_realtime_reporter := ut_realtime_reporter();\n"); sb.append("BEGIN\n"); - sb.append(" l_reporter.set_reporter_id(?);\n"); + if (useBindVariable) { + sb.append(" l_reporter.set_reporter_id(?);\n"); + } else { + sb.append(" l_reporter.set_reporter_id('"); + sb.append(reporterId); + sb.append("');\n"); + } sb.append(" l_reporter.output_buffer.init();\n"); sb.append(" sys.dbms_output.enable(NULL);\n"); sb.append(" ut_runner.run(\n"); @@ -88,7 +99,11 @@ public void produceReport(final String reporterId, final List pathList) sb.append(" );\n"); sb.append(" sys.dbms_output.disable;\n"); sb.append("END;"); - final String plsql = sb.toString(); + return sb.toString(); + } + + public void produceReport(final String reporterId, final List pathList) { + final String plsql = getProduceReportPlsql(reporterId, pathList, true); final Object[] binds = { reporterId }; jdbcTemplate.update(plsql, binds); } From 2cd156cc435a9aa904dc9479a3dae35ce5041ba7 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Mon, 1 Jun 2020 22:19:24 +0200 Subject: [PATCH 09/36] add "Debug utPLSQL test" to context menu of Connects window and editor --- sqldev/extension.xml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sqldev/extension.xml b/sqldev/extension.xml index 835e262c..88d49292 100644 --- a/sqldev/extension.xml +++ b/sqldev/extension.xml @@ -106,6 +106,13 @@ Code-Editor + + + ${MENU_DEBUG_TEST_LABEL} + res:/org/utplsql/sqldev/resources/images/debug.png + Code-Editor + + ${MENU_GENERATE_TEST_LABEL} @@ -120,6 +127,7 @@ + @@ -132,7 +140,8 @@ id="UTPLSQL_MENU" weight="2.0"> - + + @@ -142,7 +151,8 @@
- + +
From 56e28afca59aaffceb785a0bcae55690d26c3e63 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Mon, 1 Jun 2020 22:20:27 +0200 Subject: [PATCH 10/36] ensure that realtime reporter is/stays visible during a test run --- .../org/utplsql/sqldev/ui/runner/RunnerPanel.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java b/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java index a7650ea1..3e36e128 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java @@ -483,7 +483,18 @@ private void setCurrentRun(final Run run) { } } + private void showDockable() { + try { + if (!RunnerFactory.getDockable().isVisible()) { + RunnerFactory.showDockable(); + } + } catch (Throwable t) { + // ignore + } + } + public synchronized void update(final String reporterId) { + showDockable(); setCurrentRun(runs.get(reporterId)); final int row = currentRun.getCurrentTestNumber() - 1; final CharSequence header = testOverviewTableModel.getTestIdColumnName(); From 22c2898c58f9ef79082a4f39e3a0feb71937129d Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Mon, 1 Jun 2020 22:25:44 +0200 Subject: [PATCH 11/36] simplify code --- .../utplsql/sqldev/runner/UtplsqlRunner.java | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java index dbc62cb4..ffef8ab6 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java @@ -19,7 +19,6 @@ import java.awt.Toolkit; import java.sql.Connection; import java.text.SimpleDateFormat; -import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.UUID; @@ -133,7 +132,7 @@ public void dispose() { @Override public void process(final RealtimeReporterEvent event) { - logger.fine(() -> event.toString()); + logger.fine(event::toString); // dynamic dispatching code originally generated by Xtend if (event instanceof PostRunEvent) { doProcess((PostRunEvent) event); @@ -144,11 +143,11 @@ public void process(final RealtimeReporterEvent event) { } else if (event instanceof PreRunEvent) { doProcess((PreRunEvent) event); } else if (event instanceof PreSuiteEvent) { - doProcess((PreSuiteEvent) event); + // not processed } else if (event instanceof PreTestEvent) { doProcess((PreTestEvent) event); } else { - throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.asList(event).toString()); + throw new IllegalArgumentException("Unhandled event: " + event.toString()); } } @@ -191,10 +190,6 @@ private void doProcess(final PostRunEvent event) { panel.update(realtimeReporterId); } - private void doProcess(final PreSuiteEvent event) { - // ignore - } - private void doProcess(final PostSuiteEvent event) { final Test test = run.getCurrentTest(); // Errors on suite levels are reported as warnings by the utPLSQL framework, @@ -291,8 +286,7 @@ private void produce() { } logger.fine(() -> "All events produced for reporter id " + realtimeReporterId + "."); } catch (Exception e) { - logger.severe(() -> "Error while producing events for reporter id " + realtimeReporterId + ": " - + (e != null ? e.getMessage() : "???")); + logger.severe(() -> "Error while producing events for reporter id " + realtimeReporterId + ": " + e.getMessage() + "."); } } @@ -307,12 +301,11 @@ private void consume() { CodeCoverageReporter.openInBrowser(html); } } catch (Exception e) { - logger.severe(() -> "Error while consuming events for reporter id " + realtimeReporterId + ": " - + (e != null ? e.getMessage() : "???")); + logger.severe(() -> "Error while consuming events for reporter id " + realtimeReporterId + ": " + e.getMessage() + "."); } if (run.getTotalNumberOfTests() < 0) { run.setStatus(UtplsqlResources.getString("RUNNER_NO_TESTS_FOUND_TEXT")); - run.setExecutionTime(Double.valueOf(System.currentTimeMillis() - Double.valueOf(run.getStart())) / 1000); + run.setExecutionTime((System.currentTimeMillis() - Double.valueOf(run.getStart())) / 1000); run.setEndTime(getSysdate()); run.setTotalNumberOfTests(0); panel.update(realtimeReporterId); @@ -332,7 +325,7 @@ private boolean initGUI() { logger.severe(() -> "Error getting utPLSQL dockable. Cannot run utPLSQL test."); return false; } else { - if (isRunningInSqlDeveloper() && dockable != null) { + if (isRunningInSqlDeveloper()) { RunnerFactory.showDockable(); panel = dockable.getRunnerPanel(); } else { @@ -356,13 +349,13 @@ public void runTestAsync() { // start tests when the GUI has been successfully initialized. if (initGUI()) { // the consumer - consumerThread = new Thread(() -> consume()); + consumerThread = new Thread(this::consume); consumerThread.setName("realtime consumer"); consumerThread.start(); // avoid concurrency on output header table to fix issue #80 SystemTools.sleep(100); // the producer - producerThread = new Thread(() -> produce()); + producerThread = new Thread(this::produce); producerThread.setName("realtime producer"); producerThread.start(); } From 8ed6eb1460d16885de9dc13d6e394d004ee4851a Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Mon, 1 Jun 2020 22:28:03 +0200 Subject: [PATCH 12/36] call the PL/SQL debugger when testing via realtime reporter --- .../utplsql/sqldev/runner/UtplsqlRunner.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java index ffef8ab6..60ea3b78 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java @@ -26,9 +26,14 @@ import javax.swing.JFrame; +import oracle.dbtools.raptor.runner.DBStarterFactory; +import oracle.ide.Context; +import oracle.jdevimpl.runner.debug.DebuggingProcess; +import oracle.jdevimpl.runner.run.JRunner; import org.utplsql.sqldev.coverage.CodeCoverageReporter; import org.utplsql.sqldev.dal.RealtimeReporterDao; import org.utplsql.sqldev.dal.RealtimeReporterEventConsumer; +import org.utplsql.sqldev.exception.GenericRuntimeException; import org.utplsql.sqldev.model.DatabaseTools; import org.utplsql.sqldev.model.SystemTools; import org.utplsql.sqldev.model.runner.PostRunEvent; @@ -63,6 +68,7 @@ public class UtplsqlRunner implements RealtimeReporterEventConsumer { private JFrame frame; // for testing purposes only (outside of SQL Developer) private Thread producerThread; private Thread consumerThread; + private Context context; // required for debugging public UtplsqlRunner(final List pathList, final String connectionName) { this.withCodeCoverage = false; @@ -121,6 +127,10 @@ private void setConnection(final String connectionName) { this.connectionName = connectionName; } + public void enableDebugging(Context context) { + this.context = context; + } + public void dispose() { // running in SQL Developer DatabaseTools.closeConnection(producerConn); @@ -275,6 +285,19 @@ private void doProcess(final PostTestEvent event) { panel.update(realtimeReporterId); } + private void produceReportWithDebugger(String anonymousPlsqlBlock) { + try { + Context processContext = JRunner.prepareProcessContext(context, false); + DebuggingProcess process = new DebuggingProcess(processContext); + DBStarterFactory.PlSqlStarter starter = new DBStarterFactory.PlSqlStarter(process, anonymousPlsqlBlock, connectionName, context); + starter.start(); + } catch (Throwable t) { + String msg = t.getClass().getName() + " while debugging utPLSQL test."; + logger.severe(() -> msg); + throw new GenericRuntimeException(msg); + } + } + private void produce() { try { logger.fine(() -> "Running utPLSQL tests and producing events via reporter id " + realtimeReporterId + "..."); @@ -282,7 +305,11 @@ private void produce() { if (withCodeCoverage) { dao.produceReportWithCoverage(realtimeReporterId, coverageReporterId, pathList, schemaList, includeObjectList, excludeObjectList); } else { - dao.produceReport(realtimeReporterId, pathList); + if (context == null) { + dao.produceReport(realtimeReporterId, pathList); + } else { + produceReportWithDebugger(dao.getProduceReportPlsql(realtimeReporterId, pathList)); + } } logger.fine(() -> "All events produced for reporter id " + realtimeReporterId + "."); } catch (Exception e) { From a6cea12dbba3915b72616c58b88621867e17c525 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Mon, 1 Jun 2020 22:30:46 +0200 Subject: [PATCH 13/36] call the PL/SQL debugger when testing via worksheet --- .../sqldev/runner/UtplsqlWorksheetRunner.java | 91 +++++++++++++------ 1 file changed, 65 insertions(+), 26 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlWorksheetRunner.java b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlWorksheetRunner.java index b56b06fa..ebc0e7cc 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlWorksheetRunner.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlWorksheetRunner.java @@ -21,7 +21,12 @@ import javax.swing.JSplitPane; +import oracle.dbtools.raptor.runner.DBStarterFactory; +import oracle.ide.Context; +import oracle.jdevimpl.runner.debug.DebuggingProcess; +import oracle.jdevimpl.runner.run.JRunner; import org.utplsql.sqldev.exception.GenericDatabaseAccessException; +import org.utplsql.sqldev.exception.GenericRuntimeException; import org.utplsql.sqldev.model.DatabaseTools; import org.utplsql.sqldev.model.StringTools; import org.utplsql.sqldev.model.SystemTools; @@ -39,9 +44,10 @@ public class UtplsqlWorksheetRunner { private static final Logger logger = Logger.getLogger(UtplsqlWorksheetRunner.class.getName()); - private PreferenceModel preferences; + private final PreferenceModel preferences; + private final List pathList; private String connectionName; - private List pathList; + private boolean debug = false; public UtplsqlWorksheetRunner(final List pathList, final String connectionName) { this.pathList = pathList; @@ -49,6 +55,10 @@ public UtplsqlWorksheetRunner(final List pathList, final String connecti setConnection(connectionName); } + public void enableDebugging() { + this.debug = true; + } + private void setConnection(final String connectionName) { if (connectionName != null && preferences.isUnsharedWorksheet()) { try { @@ -65,23 +75,32 @@ private void setConnection(final String connectionName) { private CharSequence getCode() { StringBuilder sb = new StringBuilder(); - if (preferences.isResetPackage()) { - sb.append("EXECUTE dbms_session.reset_package;\n"); - } - sb.append("SET SERVEROUTPUT ON SIZE UNLIMITED\n"); - if (preferences.isClearScreen()) { - sb.append("CLEAR SCREEN\n"); - } - final List paths = pathList; - if (paths.size() == 1) { - sb.append("EXECUTE ut.run('"); - sb.append(paths.get(0)); - sb.append("');\n"); + if (!debug) { + if (preferences.isResetPackage()) { + sb.append("EXECUTE dbms_session.reset_package;\n"); + } + sb.append("SET SERVEROUTPUT ON SIZE UNLIMITED\n"); + if (preferences.isClearScreen()) { + sb.append("CLEAR SCREEN\n"); + } + if (pathList.size() == 1) { + sb.append("EXECUTE ut.run('"); + sb.append(pathList.get(0)); + sb.append("');\n"); + } else { + // we want a horizontal dense output because we resize the worksheet to fit the command in common cases + sb.append("EXECUTE ut.run(ut_varchar2_list("); + sb.append(StringTools.getCSV(pathList, "").replace("\n", "")); + sb.append("));\n"); + } } else { - // we want a horizontal dense output because we resize the worksheet to fit the command in common cases - sb.append("EXECUTE ut.run(ut_varchar2_list("); - sb.append(StringTools.getCSV(pathList, "").replace("\n","")); - sb.append("));\n"); + sb.append("BEGIN\n"); + sb.append(" ut.run(\n"); + sb.append(" ut_varchar2_list(\n"); + sb.append(StringTools.getCSV(pathList, 9)); + sb.append(" )\n"); + sb.append(" );\n"); + sb.append("END;\n"); } return sb; } @@ -115,17 +134,37 @@ private void resizeResultPanel(final Worksheet worksheet) { } } + // cannot use IdeAction to run debugger, because text has to be set in inaccessible PLSQLController.updateAction + private void runDebugger(final Worksheet worksheet, final String anonymousPlsqlBlock) { + try { + Context processContext = JRunner.prepareProcessContext(worksheet.getContext(), false); + DebuggingProcess process = new DebuggingProcess(processContext); + DBStarterFactory.PlSqlStarter starter = new DBStarterFactory.PlSqlStarter(process, anonymousPlsqlBlock, connectionName, worksheet.getContext()); + starter.start(); + } catch (Throwable t) { + String msg = t.getClass().getName() + " while debugging utPLSQL test."; + logger.severe(() -> msg); + throw new GenericRuntimeException(msg); + } + } + private void runScript(final Worksheet worksheet) { if (preferences.isAutoExecute()) { SystemTools.sleep(100); - final IdeAction action = ((IdeAction) Ide.getIdeActionMap().get(Ide.findCmdID("Worksheet.RunScript"))); - if (action != null) { - try { - action.performAction(worksheet.getContext()); - } catch (Exception e) { - logger.severe(() -> "Could not run script in worksheet due to " + (e != null ? e.getMessage() : "???") + "."); + if (debug) { + runDebugger(worksheet, worksheet.getFocusedEditorPane().getText()); + } else { + final IdeAction action = ((IdeAction) Ide.getIdeActionMap().get(Ide.findCmdID("Worksheet.RunScript"))); + if (action != null) { + try { + action.performAction(worksheet.getContext()); + } catch (Exception e) { + logger.severe(() -> "Could not run script in worksheet due to " + e.getMessage() + "."); + } + if (!debug) { + resizeResultPanel(worksheet); + } } - resizeResultPanel(worksheet); } } } @@ -137,7 +176,7 @@ private void runTest() { } public void runTestAsync() { - final Thread thread = new Thread(() -> runTest()); + final Thread thread = new Thread(this::runTest); thread.setName("utPLSQL run test"); thread.start(); } From 5006b7c782f10d9a2595690f594b3db1fcc6b310 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Mon, 1 Jun 2020 22:32:09 +0200 Subject: [PATCH 14/36] extend controller to handle debug action in the Connections window and editor --- .../sqldev/menu/UtplsqlController.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/menu/UtplsqlController.java b/sqldev/src/main/java/org/utplsql/sqldev/menu/UtplsqlController.java index a7e74654..43f91196 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/menu/UtplsqlController.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/menu/UtplsqlController.java @@ -67,9 +67,11 @@ public class UtplsqlController implements Controller { public static int UTPLSQL_TEST_CMD_ID = (Ide.findCmdID("utplsql.test")).intValue(); public static int UTPLSQL_COVERAGE_CMD_ID = (Ide.findCmdID("utplsql.coverage")).intValue(); + public static int UTPLSQL_DEBUG_CMD_ID = (Ide.findCmdID("utplsql.debug")).intValue(); public static int UTPLSQL_GENERATE_CMD_ID = (Ide.findCmdID("utplsql.generate")).intValue(); public static final IdeAction UTPLSQL_TEST_ACTION = IdeAction.get(UTPLSQL_TEST_CMD_ID); public static final IdeAction UTPLSQL_COVERAGE_ACTION = IdeAction.get(UTPLSQL_COVERAGE_CMD_ID); + public static final IdeAction UTPLSQL_DEBUG_ACTION = IdeAction.get(UTPLSQL_DEBUG_CMD_ID); public static final IdeAction UTPLSQL_GENERATE_ACTION = IdeAction.get(UTPLSQL_GENERATE_CMD_ID); @Override @@ -77,12 +79,16 @@ public boolean handleEvent(final IdeAction action, final Context context) { try { if (action.getCommandId() == UTPLSQL_TEST_CMD_ID) { logger.finer(() -> "handle utplsql.test"); - runTest(context); + runTest(context, false); return true; } else if (action.getCommandId() == UTPLSQL_COVERAGE_CMD_ID) { logger.finer(() -> "handle utplsql.coverage"); codeCoverage(context); return true; + } else if (action.getCommandId() == UTPLSQL_DEBUG_CMD_ID) { + logger.finer(() -> "handle utplsql.debug"); + runTest(context, true); + return true; } else if (action.getCommandId() == UTPLSQL_GENERATE_CMD_ID) { logger.finer(() -> "handle utplsql.generate"); generateTest(context); @@ -98,7 +104,8 @@ public boolean handleEvent(final IdeAction action, final Context context) { @Override public boolean update(final IdeAction action, final Context context) { - if (action.getCommandId() == UTPLSQL_TEST_CMD_ID || action.getCommandId() == UTPLSQL_COVERAGE_CMD_ID) { + if (action.getCommandId() == UTPLSQL_TEST_CMD_ID || action.getCommandId() == UTPLSQL_COVERAGE_CMD_ID || + action.getCommandId() == UTPLSQL_DEBUG_CMD_ID) { final PreferenceModel preferences = PreferenceModel.getInstance(Preferences.getPreferences()); action.setEnabled(false); final View view = context.getView(); @@ -315,7 +322,7 @@ private GenContext getGenContext(final Context context) { return genContext; } - public void runTest(final Context context) { + public void runTest(final Context context, boolean withDebug) { final View view = context.getView(); final Node node = context.getNode(); final PreferenceModel preferences = PreferenceModel.getInstance(Preferences.getPreferences()); @@ -348,9 +355,15 @@ public void runTest(final Context context) { final RealtimeReporterDao rrDao = new RealtimeReporterDao(conn); if (preferences.isUseRealtimeReporter() && rrDao.isSupported()) { final UtplsqlRunner runner = new UtplsqlRunner(getPathList(path), connectionName); + if (withDebug) { + runner.enableDebugging(context); + } runner.runTestAsync(); } else { final UtplsqlWorksheetRunner worksheet = new UtplsqlWorksheetRunner(getPathList(path), connectionName); + if (withDebug) { + worksheet.enableDebugging(); + } worksheet.runTestAsync(); } } @@ -364,9 +377,15 @@ public void runTest(final Context context) { final ArrayList pathList = dedupPathList(getPathList(context)); if (preferences.isUseRealtimeReporter() && rrDao.isSupported()) { final UtplsqlRunner runner = new UtplsqlRunner(pathList, connectionName); + if (withDebug) { + runner.enableDebugging(context); + } runner.runTestAsync(); } else { final UtplsqlWorksheetRunner worksheet = new UtplsqlWorksheetRunner(pathList, connectionName); + if (withDebug) { + worksheet.enableDebugging(); + } worksheet.runTestAsync(); } } From 4734c4032b59ecac0a83734c22f46d5e9dd43787 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 09:00:22 +0200 Subject: [PATCH 15/36] refactor, simplify --- .../utplsql/sqldev/ui/runner/RunnerPanel.java | 51 +++++++++---------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java b/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java index 3e36e128..d5756d49 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java @@ -54,7 +54,6 @@ import javax.swing.LookAndFeel; import javax.swing.RepaintManager; import javax.swing.RowFilter; -import javax.swing.SwingConstants; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.border.Border; @@ -139,7 +138,7 @@ public class RunnerPanel { private JTabbedPane testDetailTabbedPane; // used in multiple components, therefore an inner class - private class TestTableHeaderRenderer extends DefaultTableCellRenderer { + private static class TestTableHeaderRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 6295858563570577027L; @Override @@ -169,7 +168,7 @@ public Component getTableCellRendererComponent(final JTable table, final Object } // used in mulitple components, therefore an inner class - private class FailuresTableHeaderRenderer extends DefaultTableCellRenderer { + private static class FailuresTableHeaderRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 5059401447983514596L; @Override @@ -262,8 +261,7 @@ private void applyShowTestDescription() { testOverviewTable.getTableHeader().repaint(); } - private void applyShowWarningIndicator(final boolean show) { - final TableColumn col = testOverviewTable.getColumnModel().getColumn(1); + private void showColumn(final boolean show, TableColumn col) { if (show) { col.setWidth(INDICATOR_WIDTH); col.setMinWidth(INDICATOR_WIDTH); @@ -277,25 +275,19 @@ private void applyShowWarningIndicator(final boolean show) { } } + private void applyShowWarningIndicator(final boolean show) { + showColumn(show, testOverviewTable.getColumnModel().getColumn(1)); + } + private void applyShowInfoIndicator(final boolean show) { - final TableColumn col = testOverviewTable.getColumnModel().getColumn(2); - if (show) { - col.setWidth(INDICATOR_WIDTH); - col.setMinWidth(INDICATOR_WIDTH); - col.setMaxWidth(INDICATOR_WIDTH); - col.setPreferredWidth(INDICATOR_WIDTH); - } else { - col.setWidth(0); - col.setMinWidth(0); - col.setMaxWidth(0); - col.setPreferredWidth(0); - } + showColumn(show, testOverviewTable.getColumnModel().getColumn(2)); } private void applyFilter(final boolean showSuccessfulTests, final boolean showDisabledTests) { @SuppressWarnings("unchecked") final TableRowSorter sorter = ((TableRowSorter) testOverviewTable.getRowSorter()); final RowFilter filter = new RowFilter() { + @SuppressWarnings("RedundantIfStatement") @Override public boolean include(final RowFilter.Entry entry) { final Test test = entry.getModel().getTest((entry.getIdentifier()).intValue()); @@ -348,6 +340,7 @@ private void openSelectedFailure() { } } + @SuppressWarnings("StringBufferReplaceableByString") private String getHtml(final String text) { StringBuilder sb = new StringBuilder(); sb.append("\n"); @@ -384,6 +377,7 @@ private void openLink(final String link) { openEditor(ownerName, objectType, objectName.toUpperCase(), line, 1); } + @SuppressWarnings("SameParameterValue") private void openEditor(final String owner, final String type, final String name, final int line, final int col) { DefaultDrillLink drillLink = new DefaultDrillLink(); drillLink.setConnName(currentRun.getConnectionName()); @@ -417,14 +411,12 @@ private void syncDetailTab() { } private PreferenceModel getPreferenceModel() { - PreferenceModel preferences = null; try { - preferences = PreferenceModel.getInstance(Preferences.getPreferences()); + return PreferenceModel.getInstance(Preferences.getPreferences()); } catch (NoClassDefFoundError e) { // running outside of SQL Developer - preferences = PreferenceModel.getInstance(null); + return PreferenceModel.getInstance(null); } - return preferences; } private void applyPreferences() { @@ -579,9 +571,11 @@ private void comboBoxAction() { @SuppressWarnings("unchecked") final ComboBoxItem comboBoxItem = (ComboBoxItem) runComboBox .getSelectedItem(); - if (currentRun.getReporterId() != null && !currentRun.getReporterId().equals(comboBoxItem.getKey())) { - update(comboBoxItem.getKey()); - testDetailTabbedPane.setSelectedIndex(0); + if (currentRun.getReporterId() != null && comboBoxItem != null) { + if (!currentRun.getReporterId().equals(comboBoxItem.getKey())) { + update(comboBoxItem.getKey()); + testDetailTabbedPane.setSelectedIndex(0); + } } } } @@ -706,6 +700,7 @@ private void runCodeCoverage(boolean selectedOnly) { reporter.showParameterWindow(); } + @SuppressWarnings("DuplicatedCode") private void initializeGUI() { // Base panel containing all components basePanel = new JPanel(); @@ -809,8 +804,8 @@ private void initializeGUI() { time.setSeconds(currentRun.getExecutionTime()); elapsedTimeTimer.stop(); } else { - final Double now = Double.valueOf(System.currentTimeMillis()); - time.setSeconds(Double.valueOf(now - currentRun.getStart()) / 1000); + final Double now = (double) System.currentTimeMillis(); + time.setSeconds((now - currentRun.getStart()) / 1000); } elapsedTimeLabel.setText(time.toString() + (!useSmartTimes ? " s" : "")); } else { @@ -1273,7 +1268,7 @@ public void mouseClicked(final MouseEvent e) { c.weighty = 6; // - split pane - final JSplitPane failuresSplitPane = new JSplitPane(SwingConstants.HORIZONTAL, failuresTableScrollPane, + final JSplitPane failuresSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, failuresTableScrollPane, testFailureMessageScrollPane); failuresSplitPane.setResizeWeight(0.2); @@ -1355,7 +1350,7 @@ public void mouseClicked(final MouseEvent e) { testDetailTabbedPane.add(UtplsqlResources.getString("RUNNER_ERRORS_TAB_LABEL"), testErrorStackPanel); testDetailTabbedPane.add(UtplsqlResources.getString("RUNNER_WARNINGS_TAB_LABEL"), testWarningsPanel); testDetailTabbedPane.add(UtplsqlResources.getString("RUNNER_INFO_TAB_LABEL"), testServerOutputPanel); - final JSplitPane horizontalSplitPane = new JSplitPane(SwingConstants.HORIZONTAL, testOverviewScrollPane, + final JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, testOverviewScrollPane, testDetailTabbedPane); horizontalSplitPane.setResizeWeight(0.5); c.gridx = 0; From 372fe3be95dd883830114e32534fc417184234ce Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 11:39:20 +0200 Subject: [PATCH 16/36] add debug icon and debug utPLSQL test context menu for realtime reporter --- .../utplsql/sqldev/resources/UtplsqlResources.properties | 6 ++++-- .../utplsql/sqldev/resources/UtplsqlResources_de.properties | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties index ebd799b0..2accd08e 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties @@ -17,6 +17,7 @@ INFO_ICON=/org/utplsql/sqldev/resources/images/info.png REFRESH_ICON=/org/utplsql/sqldev/resources/images/refresh.png RUN_ICON=/org/utplsql/sqldev/resources/images/run.png RUN_WORKSHEET_ICON=/org/utplsql/sqldev/resources/images/run_worksheet.png +DEBUG_ICON=/org/utplsql/sqldev/resources/images/debug.png CLEAR_ICON=/org/utplsql/sqldev/resources/images/clear.png CHECKMARK_ICON=/org/utplsql/sqldev/resources/images/checkmark.png STATUS_ICON=/org/utplsql/sqldev/resources/images/status.png @@ -65,8 +66,8 @@ PREF_DELETE_EXISTING_FILES_LABEL=Delete existing files in output directory? PREF_CONFIRM_IMPORT_TITLE=Snippets imported PREF_CONFIRM_IMPORT_MESSAGE=Snippets imported into %s. Please restart SQL Developer for this change to take effect. MENU_RUN_TEST_LABEL=Run utPLSQL test +MENU_DEBUG_TEST_LABEL=Debug utPLSQL test... MENU_CODE_COVERAGE_LABEL=Code coverage... -MENU_DEBUG_TEST_LABEL=Debug utPLSQL test MENU_GENERATE_TEST_LABEL=Generate utPLSQL test WINDOW_CODE_COVERAGE_REPORT_LABEL=Code coverage report WINDOW_PATHS_LABEL=utPLSQL paths @@ -79,9 +80,10 @@ WORKSHEET_TITLE=utPLSQL RUNNER_VIEW_TITLE=utPLSQL RUNNER_REFRESH_TOOLTIP=Reset ordering and refresh RUNNER_RERUN_TOOLTIP=Rerun all tests -RUNNER_CLEAR_BUTTON=Clear run history RUNNER_RERUN_WORKSHEET_TOOLTIP=Rerun all tests in a new worksheet +RUNNER_DEBUG_TOOLTIP=Rerun all tests with PL/SQL Debugger RUNNER_CODE_COVERAGE_TOOLTIP=Rerun all tests with code coverage +RUNNER_CLEAR_BUTTON=Clear run history RUNNER_TESTS_LABEL=Tests RUNNER_FAILURES_LABEL=Failures RUNNER_ERRORS_LABEL=Errors diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties index 038a1724..55d328b3 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties @@ -42,8 +42,8 @@ PREF_DELETE_EXISTING_FILES_LABEL=Bestehende Dateien im Ausgabeverzeichnis l\u00f PREF_CONFIRM_IMPORT_TITLE=Code-Schnipsel importiert PREF_CONFIRM_IMPORT_MESSAGE=Code-Schnipsel in %s importiert. Bitte starten Sie den SQL Developer neu, um diese \u00c4nderung zu aktivieren. MENU_RUN_TEST_LABEL=utPLSQL Test ausf\u00fchren +MENU_DEBUG_TEST_LABEL=utPLSQL Test debuggen... MENU_CODE_COVERAGE_LABEL=Codeabdeckung... -MENU_DEBUG_TEST_LABEL=utPLSQL Test debuggen MENU_GENERATE_TEST_LABEL=utPLSQL Test generieren WINDOW_CODE_COVERAGE_REPORT_LABEL=Codeabdeckungs-Bericht WINDOW_PATHS_LABEL=utPLSQL Pfade @@ -57,6 +57,7 @@ RUNNER_VIEW_TITLE=utPLSQL RUNNER_REFRESH_TOOLTIP=Sortierung zur\u00fccksetzen und aktualisieren RUNNER_RERUN_TOOLTIP=Alle Tests erneut ausf\u00fchren RUNNER_RERUN_WORKSHEET_TOOLTIP=Alle Tests in einem neuen Arbeitsblatt erneut ausf\u00fchren +RUNNER_DEBUG_TOOLTIP=Alle Tests erneut mit dem PL/SQL Debugger ausf\u00fchren RUNNER_CODE_COVERAGE_TOOLTIP=Alle Tests mit Codeabdeckung ausf\u00fchren RUNNER_CLEAR_BUTTON=Run History l\u00f6schen RUNNER_TESTS_LABEL=Tests From 402d1b48d1a7372ff6be79d376d489df130e3c4a Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 11:41:27 +0200 Subject: [PATCH 17/36] create own context, add debugging flag, change enableDebugging signature --- .../org/utplsql/sqldev/runner/UtplsqlRunner.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java index 60ea3b78..f3637279 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java @@ -58,6 +58,7 @@ public class UtplsqlRunner implements RealtimeReporterEventConsumer { private final List schemaList; private final List includeObjectList; private final List excludeObjectList; + private Context context; private String connectionName; private Connection producerConn; private Connection consumerConn; @@ -68,7 +69,7 @@ public class UtplsqlRunner implements RealtimeReporterEventConsumer { private JFrame frame; // for testing purposes only (outside of SQL Developer) private Thread producerThread; private Thread consumerThread; - private Context context; // required for debugging + private boolean debug = false; public UtplsqlRunner(final List pathList, final String connectionName) { this.withCodeCoverage = false; @@ -77,6 +78,7 @@ public UtplsqlRunner(final List pathList, final String connectionName) { this.includeObjectList = null; this.excludeObjectList = null; setConnection(connectionName); + this.context = Context.newIdeContext(); } public UtplsqlRunner(final List pathList, final List schemaList, @@ -87,6 +89,7 @@ public UtplsqlRunner(final List pathList, final List schemaList, this.includeObjectList = includeObjectList; this.excludeObjectList = excludeObjectList; setConnection(connectionName); + this.context = Context.newIdeContext(); } /** @@ -127,8 +130,8 @@ private void setConnection(final String connectionName) { this.connectionName = connectionName; } - public void enableDebugging(Context context) { - this.context = context; + public void enableDebugging() { + this.debug = true; } public void dispose() { @@ -140,6 +143,7 @@ public void dispose() { } } + @SuppressWarnings("StatementWithEmptyBody") @Override public void process(final RealtimeReporterEvent event) { logger.fine(event::toString); @@ -305,7 +309,7 @@ private void produce() { if (withCodeCoverage) { dao.produceReportWithCoverage(realtimeReporterId, coverageReporterId, pathList, schemaList, includeObjectList, excludeObjectList); } else { - if (context == null) { + if (!debug) { dao.produceReport(realtimeReporterId, pathList); } else { produceReportWithDebugger(dao.getProduceReportPlsql(realtimeReporterId, pathList)); @@ -355,6 +359,7 @@ private boolean initGUI() { if (isRunningInSqlDeveloper()) { RunnerFactory.showDockable(); panel = dockable.getRunnerPanel(); + context.setView(dockable); } else { frame = new JFrame("utPLSQL Runner Panel"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); From 4a39c8db057494423bc25e22ad374e05e674cbcc Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 11:41:48 +0200 Subject: [PATCH 18/36] use new enableDebugging signature --- .../main/java/org/utplsql/sqldev/menu/UtplsqlController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/menu/UtplsqlController.java b/sqldev/src/main/java/org/utplsql/sqldev/menu/UtplsqlController.java index 43f91196..a4f59ba0 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/menu/UtplsqlController.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/menu/UtplsqlController.java @@ -356,7 +356,7 @@ public void runTest(final Context context, boolean withDebug) { if (preferences.isUseRealtimeReporter() && rrDao.isSupported()) { final UtplsqlRunner runner = new UtplsqlRunner(getPathList(path), connectionName); if (withDebug) { - runner.enableDebugging(context); + runner.enableDebugging(); } runner.runTestAsync(); } else { @@ -378,7 +378,7 @@ public void runTest(final Context context, boolean withDebug) { if (preferences.isUseRealtimeReporter() && rrDao.isSupported()) { final UtplsqlRunner runner = new UtplsqlRunner(pathList, connectionName); if (withDebug) { - runner.enableDebugging(context); + runner.enableDebugging(); } runner.runTestAsync(); } else { From 7a5a94587a2228b076d10924792e625fbb736af0 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 11:42:31 +0200 Subject: [PATCH 19/36] add toolbar button and context menu to debug utPLSQL tests --- .../utplsql/sqldev/ui/runner/RunnerPanel.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java b/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java index d5756d49..dce76c45 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java @@ -116,6 +116,7 @@ public class RunnerPanel { private JTable testOverviewTable; private JMenuItem testOverviewRunMenuItem; private JMenuItem testOverviewRunWorksheetMenuItem; + private JMenuItem testOverviewDebugMenuItem; private JMenuItem testOverviewCodeCoverageMenuItem; private JCheckBoxMenuItem showTestDescriptionCheckBoxMenuItem; private JCheckBoxMenuItem showWarningIndicatorCheckBoxMenuItem; @@ -200,6 +201,7 @@ private void resetDerived() { testOverviewTable.getRowSorter().setSortKeys(null); testOverviewRunMenuItem.setEnabled(false); testOverviewRunWorksheetMenuItem.setEnabled(false); + testOverviewDebugMenuItem.setEnabled(false); testOverviewCodeCoverageMenuItem.setEnabled(false); testIdTextArea.setText(null); testOwnerTextField.setText(null); @@ -737,6 +739,15 @@ private void initializeGUI() { worksheet.runTestAsync(); }); toolbar.add(rerunWorksheetButton); + final ToolbarButton debugButton = new ToolbarButton(UtplsqlResources.getIcon("DEBUG_ICON")); + debugButton.setToolTipText(UtplsqlResources.getString("RUNNER_DEBUG_TOOLTIP")); + debugButton.setBorder(buttonBorder); + debugButton.addActionListener(event -> { + final UtplsqlRunner runner = new UtplsqlRunner(currentRun.getPathList(), currentRun.getConnectionName()); + runner.enableDebugging(); + runner.runTestAsync(); + }); + toolbar.add(debugButton); final ToolbarButton codeCoverageButton = new ToolbarButton(UtplsqlResources.getIcon("CODE_COVERAGE_ICON")); codeCoverageButton.setToolTipText(UtplsqlResources.getString("RUNNER_CODE_COVERAGE_TOOLTIP")); codeCoverageButton.setBorder(buttonBorder); @@ -931,6 +942,7 @@ private void initializeGUI() { syncDetailTab(); testOverviewRunMenuItem.setEnabled(true); testOverviewRunWorksheetMenuItem.setEnabled(true); + testOverviewDebugMenuItem.setEnabled(true); testOverviewCodeCoverageMenuItem.setEnabled(true); } }); @@ -988,8 +1000,7 @@ public Component getTableCellRendererComponent(final JTable table, final Object final JPopupMenu testOverviewPopupMenu = new JPopupMenu(); testOverviewRunMenuItem = new JMenuItem(UtplsqlResources.getString("RUNNER_RUN_MENUITEM"), UtplsqlResources.getIcon("RUN_ICON")); testOverviewRunMenuItem.addActionListener(event -> { - final UtplsqlRunner runner = new UtplsqlRunner(getPathListFromSelectedTests(), - currentRun.getConnectionName()); + final UtplsqlRunner runner = new UtplsqlRunner(getPathListFromSelectedTests(), currentRun.getConnectionName()); runner.runTestAsync(); }); testOverviewPopupMenu.add(testOverviewRunMenuItem); @@ -1000,6 +1011,13 @@ public Component getTableCellRendererComponent(final JTable table, final Object worksheet.runTestAsync(); }); testOverviewPopupMenu.add(testOverviewRunWorksheetMenuItem); + testOverviewDebugMenuItem = new JMenuItem(UtplsqlResources.getString("MENU_DEBUG_TEST_LABEL"), UtplsqlResources.getIcon("DEBUG_ICON")); + testOverviewDebugMenuItem.addActionListener(event -> { + final UtplsqlRunner runner = new UtplsqlRunner(getPathListFromSelectedTests(), currentRun.getConnectionName()); + runner.enableDebugging(); + runner.runTestAsync(); + }); + testOverviewPopupMenu.add(testOverviewDebugMenuItem); testOverviewCodeCoverageMenuItem = new JMenuItem(UtplsqlResources.getString("MENU_CODE_COVERAGE_LABEL"), UtplsqlResources.getIcon("CODE_COVERAGE_ICON")); testOverviewCodeCoverageMenuItem.addActionListener(event -> runCodeCoverage(true)); testOverviewPopupMenu.add(testOverviewCodeCoverageMenuItem); From 2e8cf80cd61aeec15192c47def46e094b0266039 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:46:25 +0200 Subject: [PATCH 20/36] add stop icon --- .../utplsql/sqldev/resources/images/stop.png | Bin 0 -> 22864 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 sqldev/src/main/resources/org/utplsql/sqldev/resources/images/stop.png diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/images/stop.png b/sqldev/src/main/resources/org/utplsql/sqldev/resources/images/stop.png new file mode 100755 index 0000000000000000000000000000000000000000..015b8bd4b28601f96d22b2b031c9ee443c0c6044 GIT binary patch literal 22864 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 literal 0 HcmV?d00001 From b25cdc94cdd3e207fe868ad7be426a789ecc5b01 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:47:12 +0200 Subject: [PATCH 21/36] add stop icon and text regarding stop utPLSQL run in realtime reporter --- .../utplsql/sqldev/resources/UtplsqlResources.properties | 9 ++++++++- .../sqldev/resources/UtplsqlResources_de.properties | 6 +++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties index 2accd08e..71b79deb 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties @@ -2,8 +2,10 @@ # Externally used constants (pom.xml, bundle.xml, extension.xml, sqldeveloper.xml) EXTENSION_NAME=utPLSQL for SQL Developer +# suppress inspection "UnusedProperty" EXTENSION_DESCRIPTION=Extension for running unit tests in SQL Developer. EXTENSION_OWNER=Philipp Salvisberg +# suppress inspection "UnusedProperty" MIN_SQLDEV_VERSION=12.2.0.19.0.7 # Icons @@ -18,6 +20,7 @@ REFRESH_ICON=/org/utplsql/sqldev/resources/images/refresh.png RUN_ICON=/org/utplsql/sqldev/resources/images/run.png RUN_WORKSHEET_ICON=/org/utplsql/sqldev/resources/images/run_worksheet.png DEBUG_ICON=/org/utplsql/sqldev/resources/images/debug.png +STOP_ICON=/org/utplsql/sqldev/resources/images/stop.png CLEAR_ICON=/org/utplsql/sqldev/resources/images/clear.png CHECKMARK_ICON=/org/utplsql/sqldev/resources/images/checkmark.png STATUS_ICON=/org/utplsql/sqldev/resources/images/status.png @@ -26,6 +29,7 @@ PROGRESS_ICON=/org/utplsql/sqldev/resources/images/progress.png CODE_COVERAGE_ICON=/org/utplsql/sqldev/resources/images/coverage.png # Translatable text +# suppress inspection "UnusedProperty" PREF_LABEL=utPLSQL PREF_USE_REALTIME_REPORTER_LABEL=Use realtime reporter? PREF_USE_REALTIME_REPORTER_HINT=Requires utPLSQL v3.1.4 or later. Opens a worksheet for older versions. @@ -83,6 +87,9 @@ RUNNER_RERUN_TOOLTIP=Rerun all tests RUNNER_RERUN_WORKSHEET_TOOLTIP=Rerun all tests in a new worksheet RUNNER_DEBUG_TOOLTIP=Rerun all tests with PL/SQL Debugger RUNNER_CODE_COVERAGE_TOOLTIP=Rerun all tests with code coverage +RUNNER_STOP_TOOLTIP=Stops the consumer session of the current test run immediately, the JDBC connection might be closed delayed +RUNNER_STOP_TEST_MESSAGE=Test disabled due to abortion of the test run. +RUNNER_STOP_RUN_MESSAGE=Test run aborted. RUNNER_CLEAR_BUTTON=Clear run history RUNNER_TESTS_LABEL=Tests RUNNER_FAILURES_LABEL=Failures @@ -92,7 +99,7 @@ RUNNER_WARNINGS_LABEL=Warnings RUNNER_INFO_LABEL=Info RUNNER_INITIALIZING_TEXT=Initializing... RUNNER_RUNNING_TEXT=Running tests... -RUNNER_FINNISHED_TEXT=Finished. +RUNNER_FINISHED_TEXT=Finished. RUNNER_NO_TESTS_FOUND_TEXT=No tests found. RUNNER_RUN_MENUITEM=Run test RUNNER_RUN_WORKSHEET_MENUITEM=Run test in new worksheet diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties index 55d328b3..4da6a976 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties @@ -2,6 +2,7 @@ # UTF-8 file works, as long as Umlaut are escaped, see https://www.utf8-chartable.de/ # Translatable text +# suppress inspection "UnusedProperty" PREF_LABEL=utPLSQL PREF_USE_REALTIME_REPORTER_LABEL=Realtime Reporter verwenden? PREF_USE_REALTIME_REPORTER_HINT=Ben\u00f6tigt utPLSQL v3.1.4 oder neuer. \u00d6ffnet ein Arbeitsblatt f\u00fcr \u00e4ltere Versionen. @@ -59,6 +60,9 @@ RUNNER_RERUN_TOOLTIP=Alle Tests erneut ausf\u00fchren RUNNER_RERUN_WORKSHEET_TOOLTIP=Alle Tests in einem neuen Arbeitsblatt erneut ausf\u00fchren RUNNER_DEBUG_TOOLTIP=Alle Tests erneut mit dem PL/SQL Debugger ausf\u00fchren RUNNER_CODE_COVERAGE_TOOLTIP=Alle Tests mit Codeabdeckung ausf\u00fchren +RUNNER_STOP_TOOLTIP=Stoppt die Verbrauchersitzung des aktuellen Testlaufs, die JDBC-Verbindung wird m\00f6glicherweise verz\00fgert geschlossen +RUNNER_STOP_TEST_MESSAGE=Test wurde aufgrund eines Abbruchs des Testlaufs deaktiviert. +RUNNER_STOP_RUN_MESSAGE=Testlauf abgebrochen. RUNNER_CLEAR_BUTTON=Run History l\u00f6schen RUNNER_TESTS_LABEL=Tests RUNNER_FAILURES_LABEL=Fehlschl\u00e4ge @@ -68,7 +72,7 @@ RUNNER_WARNINGS_LABEL=Warnungen RUNNER_INFO_LABEL=Info RUNNER_INITIALIZING_TEXT=Initialisierung... RUNNER_RUNNING_TEXT=Starte Tests... -RUNNER_FINNISHED_TEXT=Beendet. +RUNNER_FINISHED_TEXT=Beendet. RUNNER_NO_TESTS_FOUND_TEXT=Keine Tests gefunden. RUNNER_RUN_MENUITEM=Run testTest ausf\u00fchren RUNNER_RUN_WORKSHEET_MENUITEM=Test in neuem Arbeitsblatt ausf\u00fchren From 08b3efa7d6011d3bd4d92d214d1a199d61d510f4 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:48:55 +0200 Subject: [PATCH 22/36] add jetbrains annotations --- sqldev/pom.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sqldev/pom.xml b/sqldev/pom.xml index c6854a1a..3d90e0af 100644 --- a/sqldev/pom.xml +++ b/sqldev/pom.xml @@ -1,3 +1,4 @@ + 4.0.0 @@ -205,7 +206,13 @@ 4.12 test
- + + org.jetbrains + annotations + 13.0 + compile + + From 45c9a431f39e9f05c9101ea34290ffe5a391a66b Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:49:37 +0200 Subject: [PATCH 23/36] add explicit spring-core dependency --- sqldev/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sqldev/pom.xml b/sqldev/pom.xml index 3d90e0af..7d3f85b4 100644 --- a/sqldev/pom.xml +++ b/sqldev/pom.xml @@ -187,6 +187,12 @@ spring-jdbc 5.2.6.RELEASE + + + org.springframework + spring-core + 5.2.6.RELEASE + org.springframework From ee5eb1c7440ae969edcfb07cf2de1ebc42f363b3 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:50:15 +0200 Subject: [PATCH 24/36] intitialize counter with zero values --- .../java/org/utplsql/sqldev/model/runner/Counter.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Counter.java b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Counter.java index 77ffceb9..e14dc387 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Counter.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Counter.java @@ -25,6 +25,14 @@ public class Counter { private Integer error; private Integer warning; + public Counter() { + disabled = 0; + success = 0; + failure = 0; + error = 0; + warning = 0; + } + @Override public String toString() { return new ToStringCreator(this, JsonToStringStyler.INSTANCE) From 7dd053e43638363136ac8d8102cb3f4e18f141c4 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:50:35 +0200 Subject: [PATCH 25/36] initialize counter --- .../src/main/java/org/utplsql/sqldev/model/runner/Item.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Item.java b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Item.java index 70bcef0c..059102c5 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Item.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Item.java @@ -28,6 +28,10 @@ public abstract class Item { private String serverOutput; private String warnings; + public Item() { + counter = new Counter(); + } + @Override public String toString() { return new ToStringCreator(this, JsonToStringStyler.INSTANCE) From 94d8a3ecb64dd7fab333bce6dc997973dcfcb484 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:51:02 +0200 Subject: [PATCH 26/36] rename getDisabled to isDisabled --- sqldev/src/main/java/org/utplsql/sqldev/model/runner/Test.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Test.java b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Test.java index 9e7d78ad..69338662 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Test.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Test.java @@ -23,6 +23,7 @@ import org.utplsql.sqldev.model.JsonToStringStyler; import org.utplsql.sqldev.resources.UtplsqlResources; +@SuppressWarnings("unused") public class Test extends Item { private String executableType; private String ownerName; @@ -130,7 +131,7 @@ public void setProcedureName(final String procedureName) { this.procedureName = procedureName; } - public Boolean getDisabled() { + public Boolean isDisabled() { return disabled; } From 5ca644e159af66e9ec650474df47e7bcbff01851 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:52:17 +0200 Subject: [PATCH 27/36] refactor, simplify --- .../main/java/org/utplsql/sqldev/model/runner/Run.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java index ed775d36..4fe63c35 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java @@ -21,6 +21,7 @@ import org.springframework.core.style.ToStringCreator; import org.utplsql.sqldev.model.JsonToStringStyler; +@SuppressWarnings("unused") public class Run { private String reporterId; private String connectionName; @@ -79,18 +80,13 @@ public void setStartTime(final String startTime) { public String getName() { final String time = startTime.substring(11, 19); final String conn = connectionName != null ? connectionName.substring(15) : "n/a"; - final StringBuilder sb = new StringBuilder(); - sb.append(time); - sb.append(" ("); - sb.append(conn); - sb.append(")"); - return sb.toString(); + return time + " (" + conn + ")"; } public void put(final List items) { for (final Item item : items) { if (item instanceof Test) { - tests.put(((Test) item).getId(), (Test) item); + tests.put(item.getId(), (Test) item); } if (item instanceof Suite) { put(((Suite) item).getItems()); From bfe8f1957ddd28807c3caf59f1eecd66461a0201 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:53:30 +0200 Subject: [PATCH 28/36] make getTotalNumberOfCompletedTests more robust --- .../main/java/org/utplsql/sqldev/model/runner/Run.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java index 4fe63c35..379750bd 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java @@ -103,7 +103,13 @@ public int getTotalNumberOfCompletedTests() { || counter.getError() == null) { return -1; } - return counter.getDisabled() + counter.getSuccess() + counter.getFailure() + counter.getError(); + int total = counter.getDisabled() + counter.getSuccess() + counter.getFailure() + counter.getError(); + if (totalNumberOfTests != null && total > totalNumberOfTests) { + // can happen when run is cancelled and two processes are updating the run in parallel + // not worth to ensure consistency for this case, using synchronized will not be enough + total = totalNumberOfTests; + } + return total; } public String getReporterId() { From d0d6ef1cf5813b38c5187b67c178f76808705839 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:54:25 +0200 Subject: [PATCH 29/36] always abort connections do not ask if connection is closed --- .../org/utplsql/sqldev/model/DatabaseTools.java | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/DatabaseTools.java b/sqldev/src/main/java/org/utplsql/sqldev/model/DatabaseTools.java index 9c2365ea..df12153b 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/model/DatabaseTools.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/model/DatabaseTools.java @@ -104,22 +104,8 @@ public static String createTemporaryOrPrivateConnection(String connectionName) { } } - public static boolean isConnectionClosed(Connection conn) { - try { - return conn.isClosed(); - } catch (SQLException e) { - throw new GenericDatabaseAccessException("Error getting status of connection.", e); - } - } - public static void closeConnection(Connection conn) { - if (!isConnectionClosed(conn)) { - try { - conn.close(); - } catch (SQLException e) { - throw new GenericDatabaseAccessException("Could not close connection."); - } - } + abortConnection(conn); } public static void abortConnection(Connection conn) { From 175f821e889c942ab233b2585e119da9ed61d704 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:55:13 +0200 Subject: [PATCH 30/36] add consumer connection of a run, to be closed in realtime reporter --- .../java/org/utplsql/sqldev/model/runner/Run.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java index 379750bd..9d6b3358 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/model/runner/Run.java @@ -15,6 +15,7 @@ */ package org.utplsql.sqldev.model.runner; +import java.sql.Connection; import java.util.LinkedHashMap; import java.util.List; @@ -39,6 +40,8 @@ public class Run { private LinkedHashMap tests; private String status; private Long start; + // to abort connections, producerConn is handled by UtplsqlRunner + private Connection consumerConn; @Override public String toString() { @@ -235,4 +238,12 @@ public Long getStart() { public void setStart(final Long start) { this.start = start; } + + public Connection getConsumerConn() { + return consumerConn; + } + + public void setConsumerConn(Connection consumerConn) { + this.consumerConn = consumerConn; + } } From cd16c052266d7752a1187adef312488567e7b9ed Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:56:55 +0200 Subject: [PATCH 31/36] refactor, simplify --- .../sqldev/dal/RealtimeReporterDao.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java b/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java index 2790af86..f115b045 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java @@ -54,12 +54,13 @@ import oracle.jdbc.OracleTypes; +@SuppressWarnings("StringBufferReplaceableByString") public class RealtimeReporterDao { private static final Logger logger = Logger.getLogger(RealtimeReporterDao.class.getName()); private static final int FIRST_VERSION_WITH_REALTIME_REPORTER = 3001004; private final XMLTools xmlTools = new XMLTools(); - private Connection conn; - private JdbcTemplate jdbcTemplate; + private final Connection conn; + private final JdbcTemplate jdbcTemplate; public RealtimeReporterDao(final Connection conn) { this.conn = conn; @@ -194,24 +195,21 @@ public String getHtmlCoverage(final String reporterId) { sb.append(" ? := l_reporter.get_lines_cursor();\n"); sb.append("END;"); final String plsql = sb.toString(); - return jdbcTemplate.execute(plsql, new CallableStatementCallback() { - @Override - public String doInCallableStatement(final CallableStatement cs) throws SQLException { - cs.setString(1, reporterId); - cs.registerOutParameter(2, OracleTypes.CURSOR); - cs.execute(); - final StringBuilder sb = new StringBuilder(); - final ResultSet rs = (ResultSet) cs.getObject(2); - while (rs.next()) { - final String text = rs.getString("text"); - if (text != null) { - sb.append(text); - sb.append('\n'); - } + return jdbcTemplate.execute(plsql, (CallableStatementCallback) cs -> { + cs.setString(1, reporterId); + cs.registerOutParameter(2, OracleTypes.CURSOR); + cs.execute(); + final StringBuilder sb1 = new StringBuilder(); + final ResultSet rs = (ResultSet) cs.getObject(2); + while (rs.next()) { + final String text = rs.getString("text"); + if (text != null) { + sb1.append(text); + sb1.append('\n'); } - rs.close(); - return sb.toString(); } + rs.close(); + return sb1.toString(); }); } @@ -246,6 +244,7 @@ private RealtimeReporterEvent convert(final String itemType, final String text) } } + @SuppressWarnings("DuplicatedCode") private RealtimeReporterEvent convertToPreRunEvent(final Document doc) { final PreRunEvent event = new PreRunEvent(); final Node totalNumberOfTestsNode = xmlTools.getNode(doc, "/event/totalNumberOfTests"); @@ -253,7 +252,7 @@ private RealtimeReporterEvent convertToPreRunEvent(final Document doc) { if (totalNumberOfTestsNode != null) { totalNumberOfTestsTextContent = totalNumberOfTestsNode.getTextContent(); } - event.setTotalNumberOfTests(Integer.valueOf(totalNumberOfTestsTextContent)); + event.setTotalNumberOfTests(Integer.valueOf(totalNumberOfTestsTextContent != null ? totalNumberOfTestsTextContent : "0")); final NodeList nodes = xmlTools.getNodeList(doc, "/event/items/*"); for (int i = 0; i < nodes.getLength(); i++) { final Node node = nodes.item(i); @@ -326,6 +325,7 @@ private RealtimeReporterEvent convertToPostTestEvent(final Document doc) { return event; } + @SuppressWarnings("DuplicatedCode") private void populate(final Suite suite, final Node node) { if (node instanceof Element) { suite.setId(xmlTools.getAttributeValue(node, "id")); From 6d69770fa9dd8df17983c59ffe6154ec3a6f360e Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:58:43 +0200 Subject: [PATCH 32/36] add signature to pass timeout in consumeReport a debugging session might require more, especially when debugging the utPLSQL framework --- .../sqldev/dal/RealtimeReporterDao.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java b/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java index f115b045..e5196306 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java @@ -17,11 +17,9 @@ import java.io.IOException; import java.io.StringReader; -import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Connection; import java.sql.ResultSet; -import java.sql.SQLException; import java.util.List; import java.util.logging.Logger; @@ -151,35 +149,37 @@ public void produceReportWithCoverage(final String realtimeReporterId, final Str } public void consumeReport(final String reporterId, final RealtimeReporterEventConsumer consumer) { + consumeReport(reporterId, consumer, 60); + } + + public void consumeReport(final String reporterId, final RealtimeReporterEventConsumer consumer, final int timeoutSeconds) { StringBuilder sb = new StringBuilder(); sb.append("DECLARE\n"); sb.append(" l_reporter ut_realtime_reporter := ut_realtime_reporter();\n"); sb.append("BEGIN\n"); sb.append(" l_reporter.set_reporter_id(?);\n"); - sb.append(" ? := l_reporter.get_lines_cursor();\n"); + sb.append(" ? := l_reporter.get_lines_cursor(a_initial_timeout => ?);\n"); sb.append("END;"); final String plsql = sb.toString(); jdbcTemplate.setFetchSize(1); try { - jdbcTemplate.execute(plsql, new CallableStatementCallback() { - @Override - public Void doInCallableStatement(final CallableStatement cs) throws SQLException { - cs.setString(1, reporterId); - cs.registerOutParameter(2, OracleTypes.CURSOR); - cs.execute(); - final ResultSet rs = (ResultSet) cs.getObject(2); - while (rs.next()) { - final String itemType = rs.getString("item_type"); - final Clob textClob = rs.getClob("text"); - final String textString = textClob.getSubString(1, ((int) textClob.length())); - final RealtimeReporterEvent event = convert(itemType, textString); - if (event != null) { - consumer.process(event); - } + jdbcTemplate.execute(plsql, (CallableStatementCallback) cs -> { + cs.setString(1, reporterId); + cs.setInt(3, timeoutSeconds); + cs.registerOutParameter(2, OracleTypes.CURSOR); + cs.execute(); + final ResultSet rs = (ResultSet) cs.getObject(2); + while (rs.next()) { + final String itemType = rs.getString("item_type"); + final Clob textClob = rs.getClob("text"); + final String textString = textClob.getSubString(1, ((int) textClob.length())); + final RealtimeReporterEvent event = convert(itemType, textString); + if (event != null) { + consumer.process(event); } - rs.close(); - return null; } + rs.close(); + return null; }); } finally { jdbcTemplate.setFetchSize(UtplsqlDao.FETCH_ROWS); From c3393b50557f9353aca80f9fd23b8e7bf94cda75 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 19:59:09 +0200 Subject: [PATCH 33/36] adapt test cases to match new counter default values --- .../sqldev/test/JsonToStringStylerTest.java | 54 ++++++++++++------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/sqldev/src/test/java/org/utplsql/sqldev/test/JsonToStringStylerTest.java b/sqldev/src/test/java/org/utplsql/sqldev/test/JsonToStringStylerTest.java index 2a0433cb..bbeb735d 100644 --- a/sqldev/src/test/java/org/utplsql/sqldev/test/JsonToStringStylerTest.java +++ b/sqldev/src/test/java/org/utplsql/sqldev/test/JsonToStringStylerTest.java @@ -15,13 +15,14 @@ */ package org.utplsql.sqldev.test; -import java.util.Arrays; +import java.util.Collections; import org.junit.Assert; import org.junit.Test; import org.utplsql.sqldev.model.runner.Run; import org.utplsql.sqldev.model.ut.OutputLines; +@SuppressWarnings("StringBufferReplaceableByString") public class JsonToStringStylerTest { @Test @@ -64,7 +65,7 @@ public void outputLinesWithoutLines() { @Test public void emptyRun() { - final Run r = new Run("1", "MyConnection", Arrays.asList()); + final Run r = new Run("1", "MyConnection", Collections.emptyList()); final String actual = r.toString(); @@ -82,11 +83,11 @@ public void emptyRun() { sb.append(" \"executionTime\": null,\n"); sb.append(" \"counter\": {\n"); sb.append(" \"className\": \"Counter\",\n"); - sb.append(" \"disabled\": null,\n"); - sb.append(" \"success\": null,\n"); - sb.append(" \"failure\": null,\n"); - sb.append(" \"error\": null,\n"); - sb.append(" \"warning\": null\n"); + sb.append(" \"disabled\": 0,\n"); + sb.append(" \"success\": 0,\n"); + sb.append(" \"failure\": 0,\n"); + sb.append(" \"error\": 0,\n"); + sb.append(" \"warning\": 0\n"); sb.append(" },\n"); sb.append(" \"infoCount\": null,\n"); sb.append(" \"errorStack\": null,\n"); @@ -95,15 +96,14 @@ public void emptyRun() { sb.append(" \"status\": null,\n"); sb.append(" \"start\": null,\n"); sb.append(" \"endTime\": null,\n"); - sb.append(" \"totalNumberOfCompletedTests\": -1\n"); + sb.append(" \"totalNumberOfCompletedTests\": 0\n"); sb.append("}"); - Assert.assertEquals(sb.toString(), actual.toString()); + Assert.assertEquals(sb.toString(), actual); } - @Test public void runWithTests() { - final Run r = new Run("1", "MyConnection", Arrays.asList()); + final Run r = new Run("1", "MyConnection", Collections.emptyList()); final org.utplsql.sqldev.model.runner.Test t1 = new org.utplsql.sqldev.model.runner.Test(); t1.setId("1"); t1.setName("Test One"); @@ -129,11 +129,11 @@ public void runWithTests() { sb.append(" \"executionTime\": null,\n"); sb.append(" \"counter\": {\n"); sb.append(" \"className\": \"Counter\",\n"); - sb.append(" \"disabled\": null,\n"); - sb.append(" \"success\": null,\n"); - sb.append(" \"failure\": null,\n"); - sb.append(" \"error\": null,\n"); - sb.append(" \"warning\": null\n"); + sb.append(" \"disabled\": 0,\n"); + sb.append(" \"success\": 0,\n"); + sb.append(" \"failure\": 0,\n"); + sb.append(" \"error\": 0,\n"); + sb.append(" \"warning\": 0\n"); sb.append(" },\n"); sb.append(" \"infoCount\": null,\n"); sb.append(" \"errorStack\": null,\n"); @@ -145,7 +145,14 @@ public void runWithTests() { sb.append(" \"startTime\": null,\n"); sb.append(" \"endTime\": null,\n"); sb.append(" \"executionTime\": null,\n"); - sb.append(" \"counter\": null,\n"); + sb.append(" \"counter\": {\n"); + sb.append(" \"className\": \"Counter\",\n"); + sb.append(" \"disabled\": 0,\n"); + sb.append(" \"success\": 0,\n"); + sb.append(" \"failure\": 0,\n"); + sb.append(" \"error\": 0,\n"); + sb.append(" \"warning\": 0\n"); + sb.append(" },\n"); sb.append(" \"errorStack\": null,\n"); sb.append(" \"serverOutput\": null,\n"); sb.append(" \"warnings\": null,\n"); @@ -168,7 +175,14 @@ public void runWithTests() { sb.append(" \"startTime\": null,\n"); sb.append(" \"endTime\": null,\n"); sb.append(" \"executionTime\": null,\n"); - sb.append(" \"counter\": null,\n"); + sb.append(" \"counter\": {\n"); + sb.append(" \"className\": \"Counter\",\n"); + sb.append(" \"disabled\": 0,\n"); + sb.append(" \"success\": 0,\n"); + sb.append(" \"failure\": 0,\n"); + sb.append(" \"error\": 0,\n"); + sb.append(" \"warning\": 0\n"); + sb.append(" },\n"); sb.append(" \"errorStack\": null,\n"); sb.append(" \"serverOutput\": null,\n"); sb.append(" \"warnings\": null,\n"); @@ -189,8 +203,8 @@ public void runWithTests() { sb.append(" \"status\": null,\n"); sb.append(" \"start\": null,\n"); sb.append(" \"endTime\": null,\n"); - sb.append(" \"totalNumberOfCompletedTests\": -1\n"); + sb.append(" \"totalNumberOfCompletedTests\": 0\n"); sb.append("}"); - Assert.assertEquals(sb.toString(), actual.toString()); + Assert.assertEquals(sb.toString(), actual); } } From 6f90c828ad6bb712a21d62ddd369bac6f85e7cfd Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 20:02:14 +0200 Subject: [PATCH 34/36] change timeout to 1h for debugging sessions, close session on abort properly --- .../utplsql/sqldev/runner/UtplsqlRunner.java | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java index f3637279..053e467c 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java @@ -52,6 +52,7 @@ public class UtplsqlRunner implements RealtimeReporterEventConsumer { private static final Logger logger = Logger.getLogger(UtplsqlRunner.class.getName()); + private static final int DEBUG_TIMEOUT_SECONDS = 60*60; private final boolean withCodeCoverage; private final List pathList; @@ -141,6 +142,7 @@ public void dispose() { if (frame != null) { frame.setVisible(false); } + run.setConsumerConn(null); } @SuppressWarnings("StatementWithEmptyBody") @@ -165,7 +167,7 @@ public void process(final RealtimeReporterEvent event) { } } - private String getSysdate() { + public static String getSysdate() { final Date dateTime = new Date(System.currentTimeMillis()); final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'000'"); return df.format(dateTime); @@ -183,6 +185,7 @@ private void initRun() { run.setTotalNumberOfTests(-1); run.setCurrentTestNumber(0); run.setStatus(UtplsqlResources.getString("RUNNER_INITIALIZING_TEXT")); + run.setConsumerConn(consumerConn); panel.setModel(run); panel.update(realtimeReporterId); } @@ -200,7 +203,7 @@ private void doProcess(final PostRunEvent event) { run.setExecutionTime(event.getExecutionTime()); run.setErrorStack(event.getErrorStack()); run.setServerOutput(event.getServerOutput()); - run.setStatus(UtplsqlResources.getString("RUNNER_FINNISHED_TEXT")); + run.setStatus(UtplsqlResources.getString("RUNNER_FINISHED_TEXT")); panel.update(realtimeReporterId); } @@ -323,26 +326,33 @@ private void produce() { private void consume() { try { - logger.fine(() -> "Consuming events from reporter id " + realtimeReporterId + " in realtime..."); - final RealtimeReporterDao dao = new RealtimeReporterDao(consumerConn); - dao.consumeReport(realtimeReporterId, this); - logger.fine(() -> "All events consumed."); - if (withCodeCoverage) { - String html = dao.getHtmlCoverage(coverageReporterId); - CodeCoverageReporter.openInBrowser(html); + try { + logger.fine(() -> "Consuming events from reporter id " + realtimeReporterId + " in realtime..."); + final RealtimeReporterDao dao = new RealtimeReporterDao(consumerConn); + if (!debug) { + dao.consumeReport(realtimeReporterId, this); + } else { + dao.consumeReport(realtimeReporterId, this, DEBUG_TIMEOUT_SECONDS); + } + logger.fine(() -> "All events consumed."); + if (withCodeCoverage) { + String html = dao.getHtmlCoverage(coverageReporterId); + CodeCoverageReporter.openInBrowser(html); + } + } catch (Exception e) { + logger.severe(() -> "Error while consuming events for reporter id " + realtimeReporterId + ": " + e.getMessage() + "."); + } + } finally { + if (run.getTotalNumberOfTests() < 0) { + run.setStatus(UtplsqlResources.getString("RUNNER_NO_TESTS_FOUND_TEXT")); + run.setExecutionTime((System.currentTimeMillis() - Double.valueOf(run.getStart())) / 1000); + run.setEndTime(getSysdate()); + run.setTotalNumberOfTests(0); + panel.update(realtimeReporterId); + } + if (isRunningInSqlDeveloper()) { + dispose(); } - } catch (Exception e) { - logger.severe(() -> "Error while consuming events for reporter id " + realtimeReporterId + ": " + e.getMessage() + "."); - } - if (run.getTotalNumberOfTests() < 0) { - run.setStatus(UtplsqlResources.getString("RUNNER_NO_TESTS_FOUND_TEXT")); - run.setExecutionTime((System.currentTimeMillis() - Double.valueOf(run.getStart())) / 1000); - run.setEndTime(getSysdate()); - run.setTotalNumberOfTests(0); - panel.update(realtimeReporterId); - } - if (isRunningInSqlDeveloper()) { - dispose(); } } From 1ac611fa7758ebde60fd344cff8cebbca179b69d Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 20:02:39 +0200 Subject: [PATCH 35/36] refactor, simplify --- .../sqldev/test/runner/UtplsqlRunnerPanelTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sqldev/src/test/java/org/utplsql/sqldev/test/runner/UtplsqlRunnerPanelTest.java b/sqldev/src/test/java/org/utplsql/sqldev/test/runner/UtplsqlRunnerPanelTest.java index 59776833..b4da9385 100644 --- a/sqldev/src/test/java/org/utplsql/sqldev/test/runner/UtplsqlRunnerPanelTest.java +++ b/sqldev/src/test/java/org/utplsql/sqldev/test/runner/UtplsqlRunnerPanelTest.java @@ -18,7 +18,7 @@ import java.awt.Component; import java.awt.Dimension; import java.awt.Toolkit; -import java.util.Arrays; +import java.util.Collections; import java.util.UUID; import javax.swing.JFrame; @@ -38,7 +38,7 @@ public class UtplsqlRunnerPanelTest { @Before public void setup() { final String reporterId = UUID.randomUUID().toString().replace("-", ""); - run = new Run(null, reporterId, Arrays.asList()); + run = new Run(null, reporterId, Collections.emptyList()); run.setStartTime("2019-06-09T13:42:42.123456"); run.getCounter().setDisabled(0); run.getCounter().setSuccess(0); @@ -94,8 +94,8 @@ public void showGUI() { run.getCounter().setSuccess(run.getCounter().getSuccess() + 1); run.setStatus("utplsql.test.e"); final long end = System.currentTimeMillis(); - run.setExecutionTime(Double.valueOf(end - start) / 1000); - run.setStatus(UtplsqlResources.getString("RUNNER_FINNISHED_TEXT")); + run.setExecutionTime((double) (end - start) / 1000); + run.setStatus(UtplsqlResources.getString("RUNNER_FINISHED_TEXT")); panel.update(run.getReporterId()); SystemTools.sleep(2000); Assert.assertNotNull(frame); From 7867223bcf8c8348e6040a01c480de4bbe8d7940 Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Tue, 2 Jun 2020 20:03:07 +0200 Subject: [PATCH 36/36] add stop button to toolbar in realtime reporter --- .../utplsql/sqldev/ui/runner/RunnerPanel.java | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java b/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java index dce76c45..b9f2bdd3 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java @@ -99,6 +99,7 @@ public class RunnerPanel { private Run currentRun; private JPanel basePanel; private DefaultComboBoxModel> runComboBoxModel; + private ToolbarButton stopButton; private JComboBox> runComboBox; private JLabel statusLabel; private Timer elapsedTimeTimer; @@ -168,7 +169,7 @@ public Component getTableCellRendererComponent(final JTable table, final Object } } - // used in mulitple components, therefore an inner class + // used in multiple components, therefore an inner class private static class FailuresTableHeaderRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 5059401447983514596L; @@ -215,6 +216,7 @@ private void resetDerived() { testErrorStackTextPane.setText(null); testWarningsTextPane.setText(null); testServerOutputTextPane.setText(null); + enableOrDisableStopButton(); } private void refreshRunsComboBox() { @@ -487,8 +489,13 @@ private void showDockable() { } } + private void enableOrDisableStopButton() { + stopButton.setEnabled(currentRun.getEndTime() == null); + } + public synchronized void update(final String reporterId) { showDockable(); + enableOrDisableStopButton(); setCurrentRun(runs.get(reporterId)); final int row = currentRun.getCurrentTestNumber() - 1; final CharSequence header = testOverviewTableModel.getTestIdColumnName(); @@ -753,6 +760,56 @@ private void initializeGUI() { codeCoverageButton.setBorder(buttonBorder); codeCoverageButton.addActionListener(event -> runCodeCoverage(false)); toolbar.add(codeCoverageButton); + stopButton = new ToolbarButton(UtplsqlResources.getIcon("STOP_ICON")); + stopButton.setToolTipText(UtplsqlResources.getString("RUNNER_STOP_TOOLTIP")); + stopButton.setBorder(buttonBorder); + stopButton.addActionListener(event -> { + if (currentRun.getConsumerConn() != null) { + // Aborts JDBC Connection. Connection might still run in the background. That's expected. + DatabaseTools.abortConnection(currentRun.getConsumerConn()); + for (Test test : currentRun.getTests().values()) { + if (test.getEndTime() == null && !test.isDisabled()) { + test.setDisabled(true); + test.getCounter().setDisabled(1); + test.getCounter().setWarning(1); + test.setWarnings(UtplsqlResources.getString("RUNNER_STOP_TEST_MESSAGE")); + test.setStartTime(null); + } + } + // recalculate counters and fix inconsistencies + currentRun.getCounter().setSuccess(0); + currentRun.getCounter().setFailure(0); + currentRun.getCounter().setError(0); + currentRun.getCounter().setDisabled(0); + currentRun.getCounter().setWarning(0); + for (Test test : currentRun.getTests().values()) { + if (test.isDisabled() && test.getCounter().getDisabled() == 0) { + test.getCounter().setDisabled(1); + } + if (test.getFailedExpectations() != null && !test.getFailedExpectations().isEmpty() && test.getCounter().getFailure() == 0) { + test.getCounter().setFailure(1); + } + if (test.getErrorStack() != null && test.getCounter().getError() == 0) { + test.getCounter().setError(1); + } + currentRun.getCounter().setSuccess(currentRun.getCounter().getSuccess() + test.getCounter().getSuccess()); + currentRun.getCounter().setFailure(currentRun.getCounter().getFailure() + test.getCounter().getFailure()); + currentRun.getCounter().setError(currentRun.getCounter().getError() + test.getCounter().getError()); + currentRun.getCounter().setDisabled(currentRun.getCounter().getDisabled() + test.getCounter().getDisabled()); + currentRun.getCounter().setWarning(currentRun.getCounter().getWarning() + test.getCounter().getWarning()); + } + // terminate run + currentRun.setEndTime(UtplsqlRunner.getSysdate()); + double now = (double) System.currentTimeMillis(); + currentRun.setExecutionTime((now - currentRun.getStart()) / 1000); + currentRun.setCurrentTestNumber(0); + currentRun.setStatus(UtplsqlResources.getString("RUNNER_STOP_RUN_MESSAGE")); + // update run in GUI + update(currentRun.getReporterId()); + } + }); + stopButton.setEnabled(false); + toolbar.add(stopButton); toolbar.add(Box.createHorizontalGlue()); runComboBoxModel = new DefaultComboBoxModel<>(); runComboBox = new JComboBox<>(runComboBoxModel);