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 e5196306..beface0c 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java @@ -1,12 +1,12 @@ /* * Copyright 2018 Philipp Salvisberg - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,7 +28,6 @@ import org.springframework.jdbc.core.CallableStatementCallback; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.SingleConnectionDataSource; -import org.utplsql.sqldev.exception.GenericRuntimeException; import org.utplsql.sqldev.model.StringTools; import org.utplsql.sqldev.model.XMLTools; import org.utplsql.sqldev.model.runner.Counter; @@ -211,8 +210,8 @@ public String getHtmlCoverage(final String reporterId) { rs.close(); return sb1.toString(); }); - } - + } + private RealtimeReporterEvent convert(final String itemType, final String text) { logger.fine(() -> "\n---- " + itemType + " ----\n" + text); try { @@ -234,13 +233,15 @@ private RealtimeReporterEvent convert(final String itemType, final String text) } return event; } catch (SAXException e) { + // continue processing, see https://github.com/utPLSQL/utPLSQL-SQLDeveloper/issues/107 final String msg = "Parse error while processing " + itemType + " with content: " + text; logger.severe(() -> msg); - throw new GenericRuntimeException(msg, e); + return null; } catch (IOException e) { + // continue processing, see https://github.com/utPLSQL/utPLSQL-SQLDeveloper/issues/107 final String msg = "I/O error while processing " + itemType + " with content: " + text; logger.severe(() -> msg); - throw new GenericRuntimeException(msg, e); + return null; } } 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 053e467c..a4038bd4 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java +++ b/sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java @@ -173,6 +173,10 @@ public static String getSysdate() { return df.format(dateTime); } + public boolean isRunning() { + return run != null && run.getEndTime() == null; + } + private void initRun() { run = new Run(realtimeReporterId, connectionName, pathList); run.setStartTime(getSysdate()); 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 b9f2bdd3..9f760cd5 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 @@ -709,6 +709,52 @@ private void runCodeCoverage(boolean selectedOnly) { reporter.showParameterWindow(); } + private void fixCountersAndUpdate() { + // fix incompleteTests + List incompleteTests = currentRun.getTests().values().stream() + .filter(it -> it.getEndTime() == null && !it.isDisabled()).collect(Collectors.toList()); + if (!incompleteTests.isEmpty()) { + final Double now = (double) System.currentTimeMillis(); + final String sysdate = UtplsqlRunner.getSysdate(); + for (Test test : incompleteTests) { + // fix incomplete tests, see https://github.com/utPLSQL/utPLSQL-SQLDeveloper/issues/107 + test.setEndTime(sysdate); + test.setExecutionTime((now - currentRun.getStart()) / 1000); + test.setErrorStack(UtplsqlResources.getString("RUNNER_MISSING_TEST_RESULT_MESSAGE")); + test.getCounter().setError(1); + } + } + // 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); + // update run in GUI + update(currentRun.getReporterId()); + } + @SuppressWarnings("DuplicatedCode") private void initializeGUI() { // Base panel containing all components @@ -767,45 +813,18 @@ private void initializeGUI() { 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); - } + List notCompletedTests = currentRun.getTests().values().stream() + .filter(it -> it.getTestNumber() >= currentRun.getCurrentTestNumber() && it.getEndTime() == null && !it.isDisabled()) + .collect(Collectors.toList()); + for (Test test : notCompletedTests) { + 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()); + fixCountersAndUpdate(); } }); stopButton.setEnabled(false); @@ -871,6 +890,9 @@ private void initializeGUI() { if (currentRun.getExecutionTime() != null) { time.setSeconds(currentRun.getExecutionTime()); elapsedTimeTimer.stop(); + if (!currentRun.getTotalNumberOfTests().equals(currentRun.getTotalNumberOfCompletedTests())) { + fixCountersAndUpdate(); + } } else { final Double now = (double) System.currentTimeMillis(); time.setSeconds((now - currentRun.getStart()) / 1000); 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 71b79deb..ce1045cb 100644 --- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties +++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties @@ -90,6 +90,7 @@ 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_MISSING_TEST_RESULT_MESSAGE=Missing test results. RUNNER_CLEAR_BUTTON=Clear run history RUNNER_TESTS_LABEL=Tests RUNNER_FAILURES_LABEL=Failures 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 4da6a976..2a15b1c7 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 @@ -63,6 +63,7 @@ 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_MISSING_TEST_RESULT_MESSAGE=Testergebnis fehlt. RUNNER_CLEAR_BUTTON=Run History l\u00f6schen RUNNER_TESTS_LABEL=Tests RUNNER_FAILURES_LABEL=Fehlschl\u00e4ge diff --git a/sqldev/src/test/java/org/utplsql/sqldev/test/runner/UtplsqlRunnerTest.java b/sqldev/src/test/java/org/utplsql/sqldev/test/runner/UtplsqlRunnerTest.java index eba5aec7..e2a24001 100644 --- a/sqldev/src/test/java/org/utplsql/sqldev/test/runner/UtplsqlRunnerTest.java +++ b/sqldev/src/test/java/org/utplsql/sqldev/test/runner/UtplsqlRunnerTest.java @@ -16,7 +16,7 @@ package org.utplsql.sqldev.test.runner; import java.sql.Connection; -import java.util.Arrays; +import java.util.Collections; import org.junit.After; import org.junit.Assert; @@ -110,31 +110,45 @@ public void setup() { sb.append("END;"); jdbcTemplate.execute(sb.toString()); new CodeCoverageReporterTest().setup(); + sb.setLength(0); + sb.append("CREATE OR REPLACE PACKAGE junit_utplsql_test2_pkg is\n"); + sb.append(" --%suite(JUnit testing)\n"); + sb.append(" --%suitepath(b)\n\n"); + + sb.append(" --%test(test XML with nested CDATA)\n"); + sb.append(" PROCEDURE test_nested_cdata;\n\n"); + sb.append("END;"); + jdbcTemplate.execute(sb.toString()); + sb.setLength(0); + sb.append("CREATE OR REPLACE PACKAGE BODY junit_utplsql_test2_pkg IS\n"); + sb.append(" PROCEDURE test_nested_cdata IS\n"); + sb.append(" BEGIN\n"); + sb.append(" dbms_output.put_line('nested cdata block: , to be handled.');\n"); + sb.append(" ut.expect(1).to_equal(1);\n"); + sb.append(" END;\n"); + sb.append("END;"); + jdbcTemplate.execute(sb.toString()); } @After public void teardown() { executeAndIgnore(jdbcTemplate, "DROP PACKAGE junit_utplsql_test1_pkg"); + executeAndIgnore(jdbcTemplate, "DROP PACKAGE junit_utplsql_test2_pkg"); new CodeCoverageReporterTest().teardown(); } + private Connection getNewConnection() { + final SingleConnectionDataSource ds = new SingleConnectionDataSource(); + ds.setDriverClassName("oracle.jdbc.OracleDriver"); + ds.setUrl(dataSource.getUrl()); + ds.setUsername(dataSource.getUsername()); + ds.setPassword(dataSource.getPassword()); + return DatabaseTools.getConnection(ds); + } + @Test public void runTestsWithMaxTime() { - final SingleConnectionDataSource ds1 = new SingleConnectionDataSource(); - ds1.setDriverClassName("oracle.jdbc.OracleDriver"); - ds1.setUrl(dataSource.getUrl()); - ds1.setUsername(dataSource.getUsername()); - ds1.setPassword(dataSource.getPassword()); - final Connection producerConn = DatabaseTools.getConnection(ds1); - - final SingleConnectionDataSource ds2 = new SingleConnectionDataSource(); - ds2.setDriverClassName("oracle.jdbc.OracleDriver"); - ds2.setUrl(dataSource.getUrl()); - ds2.setUsername(dataSource.getUsername()); - ds2.setPassword(dataSource.getPassword()); - final Connection consumerConn = DatabaseTools.getConnection(ds2); - - UtplsqlRunner runner = new UtplsqlRunner(Arrays.asList(":a"), producerConn, consumerConn); + UtplsqlRunner runner = new UtplsqlRunner(Collections.singletonList(":a"), getNewConnection(), getNewConnection()); runner.runTestAsync(); SystemTools.waitForThread(runner.getProducerThread(), 200000); @@ -146,27 +160,26 @@ public void runTestsWithMaxTime() { @Test public void runTestsWithCodeCoverage() { - final SingleConnectionDataSource ds1 = new SingleConnectionDataSource(); - ds1.setDriverClassName("oracle.jdbc.OracleDriver"); - ds1.setUrl(dataSource.getUrl()); - ds1.setUsername(dataSource.getUsername()); - ds1.setPassword(dataSource.getPassword()); - final Connection producerConn = DatabaseTools.getConnection(ds1); - - final SingleConnectionDataSource ds2 = new SingleConnectionDataSource(); - ds2.setDriverClassName("oracle.jdbc.OracleDriver"); - ds2.setUrl(dataSource.getUrl()); - ds2.setUsername(dataSource.getUsername()); - ds2.setPassword(dataSource.getPassword()); - final Connection consumerConn = DatabaseTools.getConnection(ds2); - - UtplsqlRunner runner = new UtplsqlRunner(Arrays.asList(":test_f"), null, null, null, producerConn, consumerConn); + UtplsqlRunner runner = new UtplsqlRunner(Collections.singletonList(":test_f"), null, null, null, getNewConnection(), getNewConnection()); + runner.runTestAsync(); + + SystemTools.waitForThread(runner.getProducerThread(), 200000); + SystemTools.waitForThread(runner.getConsumerThread(), 200000); + SystemTools.sleep(4 * 1000); + Assert.assertNotNull(runner); + runner.dispose(); + } + + @Test + public void runTestWithNestedCdataSection() { + UtplsqlRunner runner = new UtplsqlRunner(Collections.singletonList(":b"), getNewConnection(), getNewConnection()); runner.runTestAsync(); SystemTools.waitForThread(runner.getProducerThread(), 200000); SystemTools.waitForThread(runner.getConsumerThread(), 200000); SystemTools.sleep(4 * 1000); Assert.assertNotNull(runner); + Assert.assertFalse(runner.isRunning()); runner.dispose(); } } diff --git a/sqldev/src/test/resources/logging.conf b/sqldev/src/test/resources/logging.conf index 957e74fc..dfb71d9b 100644 --- a/sqldev/src/test/resources/logging.conf +++ b/sqldev/src/test/resources/logging.conf @@ -12,7 +12,7 @@ handlers=java.util.logging.ConsoleHandler # Loggers #oracle.level=FINE -org.utplsql.level=ALL +org.utplsql.level=INFO # --- ConsoleHandler --- java.util.logging.ConsoleHandler.level=ALL