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 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 @@
- + +
diff --git a/sqldev/pom.xml b/sqldev/pom.xml index 86c63539..7d3f85b4 100644 --- a/sqldev/pom.xml +++ b/sqldev/pom.xml @@ -1,3 +1,4 @@ + 4.0.0 @@ -142,6 +143,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 @@ -172,6 +187,12 @@ spring-jdbc 5.2.6.RELEASE + + + org.springframework + spring-core + 5.2.6.RELEASE + org.springframework @@ -191,7 +212,13 @@ 4.12 test - + + org.jetbrains + annotations + 13.0 + compile + + @@ -370,6 +397,13 @@ + + + + + + + org.apache.felix maven-bundle-plugin 4.2.1 @@ -405,9 +439,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, 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..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; @@ -54,12 +52,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; @@ -72,12 +71,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 +98,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); } @@ -135,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); @@ -179,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(); }); } @@ -231,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"); @@ -238,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); @@ -311,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")); 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..a4f59ba0 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(); + } 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(); + } runner.runTestAsync(); } else { final UtplsqlWorksheetRunner worksheet = new UtplsqlWorksheetRunner(pathList, connectionName); + if (withDebug) { + worksheet.enableDebugging(); + } worksheet.runTestAsync(); } } 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) { 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) 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) 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..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,12 +15,14 @@ */ package org.utplsql.sqldev.model.runner; +import java.sql.Connection; import java.util.LinkedHashMap; import java.util.List; import org.springframework.core.style.ToStringCreator; import org.utplsql.sqldev.model.JsonToStringStyler; +@SuppressWarnings("unused") public class Run { private String reporterId; private String connectionName; @@ -38,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() { @@ -79,18 +83,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()); @@ -107,7 +106,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() { @@ -233,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; + } } 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; } 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..053e467c 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; @@ -27,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; @@ -48,12 +52,14 @@ 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; private final List schemaList; private final List includeObjectList; private final List excludeObjectList; + private Context context; private String connectionName; private Connection producerConn; private Connection consumerConn; @@ -64,6 +70,7 @@ public class UtplsqlRunner implements RealtimeReporterEventConsumer { private JFrame frame; // for testing purposes only (outside of SQL Developer) private Thread producerThread; private Thread consumerThread; + private boolean debug = false; public UtplsqlRunner(final List pathList, final String connectionName) { this.withCodeCoverage = false; @@ -72,6 +79,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, @@ -82,6 +90,7 @@ public UtplsqlRunner(final List pathList, final List schemaList, this.includeObjectList = includeObjectList; this.excludeObjectList = excludeObjectList; setConnection(connectionName); + this.context = Context.newIdeContext(); } /** @@ -122,6 +131,10 @@ private void setConnection(final String connectionName) { this.connectionName = connectionName; } + public void enableDebugging() { + this.debug = true; + } + public void dispose() { // running in SQL Developer DatabaseTools.closeConnection(producerConn); @@ -129,11 +142,13 @@ public void dispose() { if (frame != null) { frame.setVisible(false); } + run.setConsumerConn(null); } + @SuppressWarnings("StatementWithEmptyBody") @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,15 +159,15 @@ 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()); } } - 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); @@ -170,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); } @@ -187,14 +203,10 @@ 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); } - 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, @@ -280,6 +292,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 + "..."); @@ -287,38 +312,47 @@ private void produce() { if (withCodeCoverage) { dao.produceReportWithCoverage(realtimeReporterId, coverageReporterId, pathList, schemaList, includeObjectList, excludeObjectList); } else { - dao.produceReport(realtimeReporterId, pathList); + if (!debug) { + dao.produceReport(realtimeReporterId, pathList); + } else { + produceReportWithDebugger(dao.getProduceReportPlsql(realtimeReporterId, pathList)); + } } 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() + "."); } } 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 != null ? 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.setEndTime(getSysdate()); - run.setTotalNumberOfTests(0); - panel.update(realtimeReporterId); - } - if (isRunningInSqlDeveloper()) { - dispose(); } } @@ -332,9 +366,10 @@ 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(); + context.setView(dockable); } else { frame = new JFrame("utPLSQL Runner Panel"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); @@ -356,13 +391,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(); } 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(); } 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..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 @@ -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; @@ -100,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; @@ -117,6 +117,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; @@ -139,7 +140,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 @@ -168,8 +169,8 @@ public Component getTableCellRendererComponent(final JTable table, final Object } } - // used in mulitple components, therefore an inner class - private class FailuresTableHeaderRenderer extends DefaultTableCellRenderer { + // used in multiple components, therefore an inner class + private static class FailuresTableHeaderRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 5059401447983514596L; @Override @@ -201,6 +202,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); @@ -214,6 +216,7 @@ private void resetDerived() { testErrorStackTextPane.setText(null); testWarningsTextPane.setText(null); testServerOutputTextPane.setText(null); + enableOrDisableStopButton(); } private void refreshRunsComboBox() { @@ -262,8 +265,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 +279,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 +344,7 @@ private void openSelectedFailure() { } } + @SuppressWarnings("StringBufferReplaceableByString") private String getHtml(final String text) { StringBuilder sb = new StringBuilder(); sb.append("\n"); @@ -384,6 +381,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 +415,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() { @@ -483,7 +479,23 @@ private void setCurrentRun(final Run run) { } } + private void showDockable() { + try { + if (!RunnerFactory.getDockable().isVisible()) { + RunnerFactory.showDockable(); + } + } catch (Throwable t) { + // ignore + } + } + + 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(); @@ -568,9 +580,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); + } } } } @@ -695,6 +709,7 @@ private void runCodeCoverage(boolean selectedOnly) { reporter.showParameterWindow(); } + @SuppressWarnings("DuplicatedCode") private void initializeGUI() { // Base panel containing all components basePanel = new JPanel(); @@ -731,11 +746,70 @@ 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); 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); @@ -798,8 +872,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 { @@ -925,6 +999,7 @@ private void initializeGUI() { syncDetailTab(); testOverviewRunMenuItem.setEnabled(true); testOverviewRunWorksheetMenuItem.setEnabled(true); + testOverviewDebugMenuItem.setEnabled(true); testOverviewCodeCoverageMenuItem.setEnabled(true); } }); @@ -982,8 +1057,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); @@ -994,6 +1068,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); @@ -1262,7 +1343,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); @@ -1344,7 +1425,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; 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..71b79deb 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,118 @@ -# 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 +# 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 +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 +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 +# 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 +# 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. +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_DEBUG_TEST_LABEL=Debug 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_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 +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_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 +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..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 @@ -1,84 +1,91 @@ -# 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 +# 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. +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_DEBUG_TEST_LABEL=utPLSQL Test debuggen... +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_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 +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_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 +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 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 00000000..1a27adf8 Binary files /dev/null and b/sqldev/src/main/resources/org/utplsql/sqldev/resources/images/debug.png differ 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 00000000..015b8bd4 Binary files /dev/null and b/sqldev/src/main/resources/org/utplsql/sqldev/resources/images/stop.png differ 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); } } 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 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);