Skip to content

Commit 21d6f96

Browse files
Merge pull request utPLSQL#108 from utPLSQL/bugfix/issue-107-nested-cdata
utPLSQL#107 - Crash of Realtime Report when server output contains <![CDATA[...]]>
2 parents c2b746d + e90a80e commit 21d6f96

File tree

7 files changed

+119
-77
lines changed

7 files changed

+119
-77
lines changed

sqldev/src/main/java/org/utplsql/sqldev/dal/RealtimeReporterDao.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/*
22
* Copyright 2018 Philipp Salvisberg <philipp.salvisberg@trivadis.com>
3-
*
3+
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
7-
*
7+
*
88
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
9+
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,
1212
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -28,7 +28,6 @@
2828
import org.springframework.jdbc.core.CallableStatementCallback;
2929
import org.springframework.jdbc.core.JdbcTemplate;
3030
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
31-
import org.utplsql.sqldev.exception.GenericRuntimeException;
3231
import org.utplsql.sqldev.model.StringTools;
3332
import org.utplsql.sqldev.model.XMLTools;
3433
import org.utplsql.sqldev.model.runner.Counter;
@@ -211,8 +210,8 @@ public String getHtmlCoverage(final String reporterId) {
211210
rs.close();
212211
return sb1.toString();
213212
});
214-
}
215-
213+
}
214+
216215
private RealtimeReporterEvent convert(final String itemType, final String text) {
217216
logger.fine(() -> "\n---- " + itemType + " ----\n" + text);
218217
try {
@@ -234,13 +233,15 @@ private RealtimeReporterEvent convert(final String itemType, final String text)
234233
}
235234
return event;
236235
} catch (SAXException e) {
236+
// continue processing, see https://github.com/utPLSQL/utPLSQL-SQLDeveloper/issues/107
237237
final String msg = "Parse error while processing " + itemType + " with content: " + text;
238238
logger.severe(() -> msg);
239-
throw new GenericRuntimeException(msg, e);
239+
return null;
240240
} catch (IOException e) {
241+
// continue processing, see https://github.com/utPLSQL/utPLSQL-SQLDeveloper/issues/107
241242
final String msg = "I/O error while processing " + itemType + " with content: " + text;
242243
logger.severe(() -> msg);
243-
throw new GenericRuntimeException(msg, e);
244+
return null;
244245
}
245246
}
246247

sqldev/src/main/java/org/utplsql/sqldev/runner/UtplsqlRunner.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ public static String getSysdate() {
173173
return df.format(dateTime);
174174
}
175175

176+
public boolean isRunning() {
177+
return run != null && run.getEndTime() == null;
178+
}
179+
176180
private void initRun() {
177181
run = new Run(realtimeReporterId, connectionName, pathList);
178182
run.setStartTime(getSysdate());

sqldev/src/main/java/org/utplsql/sqldev/ui/runner/RunnerPanel.java

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,52 @@ private void runCodeCoverage(boolean selectedOnly) {
709709
reporter.showParameterWindow();
710710
}
711711

712+
private void fixCountersAndUpdate() {
713+
// fix incompleteTests
714+
List<Test> incompleteTests = currentRun.getTests().values().stream()
715+
.filter(it -> it.getEndTime() == null && !it.isDisabled()).collect(Collectors.toList());
716+
if (!incompleteTests.isEmpty()) {
717+
final Double now = (double) System.currentTimeMillis();
718+
final String sysdate = UtplsqlRunner.getSysdate();
719+
for (Test test : incompleteTests) {
720+
// fix incomplete tests, see https://github.com/utPLSQL/utPLSQL-SQLDeveloper/issues/107
721+
test.setEndTime(sysdate);
722+
test.setExecutionTime((now - currentRun.getStart()) / 1000);
723+
test.setErrorStack(UtplsqlResources.getString("RUNNER_MISSING_TEST_RESULT_MESSAGE"));
724+
test.getCounter().setError(1);
725+
}
726+
}
727+
// recalculate counters and fix inconsistencies
728+
currentRun.getCounter().setSuccess(0);
729+
currentRun.getCounter().setFailure(0);
730+
currentRun.getCounter().setError(0);
731+
currentRun.getCounter().setDisabled(0);
732+
currentRun.getCounter().setWarning(0);
733+
for (Test test : currentRun.getTests().values()) {
734+
if (test.isDisabled() && test.getCounter().getDisabled() == 0) {
735+
test.getCounter().setDisabled(1);
736+
}
737+
if (test.getFailedExpectations() != null && !test.getFailedExpectations().isEmpty() && test.getCounter().getFailure() == 0) {
738+
test.getCounter().setFailure(1);
739+
}
740+
if (test.getErrorStack() != null && test.getCounter().getError() == 0) {
741+
test.getCounter().setError(1);
742+
}
743+
currentRun.getCounter().setSuccess(currentRun.getCounter().getSuccess() + test.getCounter().getSuccess());
744+
currentRun.getCounter().setFailure(currentRun.getCounter().getFailure() + test.getCounter().getFailure());
745+
currentRun.getCounter().setError(currentRun.getCounter().getError() + test.getCounter().getError());
746+
currentRun.getCounter().setDisabled(currentRun.getCounter().getDisabled() + test.getCounter().getDisabled());
747+
currentRun.getCounter().setWarning(currentRun.getCounter().getWarning() + test.getCounter().getWarning());
748+
}
749+
// terminate run
750+
currentRun.setEndTime(UtplsqlRunner.getSysdate());
751+
double now = (double) System.currentTimeMillis();
752+
currentRun.setExecutionTime((now - currentRun.getStart()) / 1000);
753+
currentRun.setCurrentTestNumber(0);
754+
// update run in GUI
755+
update(currentRun.getReporterId());
756+
}
757+
712758
@SuppressWarnings("DuplicatedCode")
713759
private void initializeGUI() {
714760
// Base panel containing all components
@@ -767,45 +813,18 @@ private void initializeGUI() {
767813
if (currentRun.getConsumerConn() != null) {
768814
// Aborts JDBC Connection. Connection might still run in the background. That's expected.
769815
DatabaseTools.abortConnection(currentRun.getConsumerConn());
770-
for (Test test : currentRun.getTests().values()) {
771-
if (test.getEndTime() == null && !test.isDisabled()) {
772-
test.setDisabled(true);
773-
test.getCounter().setDisabled(1);
774-
test.getCounter().setWarning(1);
775-
test.setWarnings(UtplsqlResources.getString("RUNNER_STOP_TEST_MESSAGE"));
776-
test.setStartTime(null);
777-
}
816+
List<Test> notCompletedTests = currentRun.getTests().values().stream()
817+
.filter(it -> it.getTestNumber() >= currentRun.getCurrentTestNumber() && it.getEndTime() == null && !it.isDisabled())
818+
.collect(Collectors.toList());
819+
for (Test test : notCompletedTests) {
820+
test.setDisabled(true);
821+
test.getCounter().setDisabled(1);
822+
test.getCounter().setWarning(1);
823+
test.setWarnings(UtplsqlResources.getString("RUNNER_STOP_TEST_MESSAGE"));
824+
test.setStartTime(null);
778825
}
779-
// recalculate counters and fix inconsistencies
780-
currentRun.getCounter().setSuccess(0);
781-
currentRun.getCounter().setFailure(0);
782-
currentRun.getCounter().setError(0);
783-
currentRun.getCounter().setDisabled(0);
784-
currentRun.getCounter().setWarning(0);
785-
for (Test test : currentRun.getTests().values()) {
786-
if (test.isDisabled() && test.getCounter().getDisabled() == 0) {
787-
test.getCounter().setDisabled(1);
788-
}
789-
if (test.getFailedExpectations() != null && !test.getFailedExpectations().isEmpty() && test.getCounter().getFailure() == 0) {
790-
test.getCounter().setFailure(1);
791-
}
792-
if (test.getErrorStack() != null && test.getCounter().getError() == 0) {
793-
test.getCounter().setError(1);
794-
}
795-
currentRun.getCounter().setSuccess(currentRun.getCounter().getSuccess() + test.getCounter().getSuccess());
796-
currentRun.getCounter().setFailure(currentRun.getCounter().getFailure() + test.getCounter().getFailure());
797-
currentRun.getCounter().setError(currentRun.getCounter().getError() + test.getCounter().getError());
798-
currentRun.getCounter().setDisabled(currentRun.getCounter().getDisabled() + test.getCounter().getDisabled());
799-
currentRun.getCounter().setWarning(currentRun.getCounter().getWarning() + test.getCounter().getWarning());
800-
}
801-
// terminate run
802-
currentRun.setEndTime(UtplsqlRunner.getSysdate());
803-
double now = (double) System.currentTimeMillis();
804-
currentRun.setExecutionTime((now - currentRun.getStart()) / 1000);
805-
currentRun.setCurrentTestNumber(0);
806826
currentRun.setStatus(UtplsqlResources.getString("RUNNER_STOP_RUN_MESSAGE"));
807-
// update run in GUI
808-
update(currentRun.getReporterId());
827+
fixCountersAndUpdate();
809828
}
810829
});
811830
stopButton.setEnabled(false);
@@ -871,6 +890,9 @@ private void initializeGUI() {
871890
if (currentRun.getExecutionTime() != null) {
872891
time.setSeconds(currentRun.getExecutionTime());
873892
elapsedTimeTimer.stop();
893+
if (!currentRun.getTotalNumberOfTests().equals(currentRun.getTotalNumberOfCompletedTests())) {
894+
fixCountersAndUpdate();
895+
}
874896
} else {
875897
final Double now = (double) System.currentTimeMillis();
876898
time.setSeconds((now - currentRun.getStart()) / 1000);

sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ RUNNER_CODE_COVERAGE_TOOLTIP=Rerun all tests with code coverage
9090
RUNNER_STOP_TOOLTIP=Stops the consumer session of the current test run immediately, the JDBC connection might be closed delayed
9191
RUNNER_STOP_TEST_MESSAGE=Test disabled due to abortion of the test run.
9292
RUNNER_STOP_RUN_MESSAGE=Test run aborted.
93+
RUNNER_MISSING_TEST_RESULT_MESSAGE=Missing test results.
9394
RUNNER_CLEAR_BUTTON=Clear run history
9495
RUNNER_TESTS_LABEL=Tests
9596
RUNNER_FAILURES_LABEL=Failures

sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ RUNNER_CODE_COVERAGE_TOOLTIP=Alle Tests mit Codeabdeckung ausf\u00fchren
6363
RUNNER_STOP_TOOLTIP=Stoppt die Verbrauchersitzung des aktuellen Testlaufs, die JDBC-Verbindung wird m\00f6glicherweise verz\00fgert geschlossen
6464
RUNNER_STOP_TEST_MESSAGE=Test wurde aufgrund eines Abbruchs des Testlaufs deaktiviert.
6565
RUNNER_STOP_RUN_MESSAGE=Testlauf abgebrochen.
66+
RUNNER_MISSING_TEST_RESULT_MESSAGE=Testergebnis fehlt.
6667
RUNNER_CLEAR_BUTTON=Run History l\u00f6schen
6768
RUNNER_TESTS_LABEL=Tests
6869
RUNNER_FAILURES_LABEL=Fehlschl\u00e4ge

sqldev/src/test/java/org/utplsql/sqldev/test/runner/UtplsqlRunnerTest.java

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
package org.utplsql.sqldev.test.runner;
1717

1818
import java.sql.Connection;
19-
import java.util.Arrays;
19+
import java.util.Collections;
2020

2121
import org.junit.After;
2222
import org.junit.Assert;
@@ -110,31 +110,45 @@ public void setup() {
110110
sb.append("END;");
111111
jdbcTemplate.execute(sb.toString());
112112
new CodeCoverageReporterTest().setup();
113+
sb.setLength(0);
114+
sb.append("CREATE OR REPLACE PACKAGE junit_utplsql_test2_pkg is\n");
115+
sb.append(" --%suite(JUnit testing)\n");
116+
sb.append(" --%suitepath(b)\n\n");
117+
118+
sb.append(" --%test(test XML with nested CDATA)\n");
119+
sb.append(" PROCEDURE test_nested_cdata;\n\n");
120+
sb.append("END;");
121+
jdbcTemplate.execute(sb.toString());
122+
sb.setLength(0);
123+
sb.append("CREATE OR REPLACE PACKAGE BODY junit_utplsql_test2_pkg IS\n");
124+
sb.append(" PROCEDURE test_nested_cdata IS\n");
125+
sb.append(" BEGIN\n");
126+
sb.append(" dbms_output.put_line('nested cdata block: <![CDATA[...]]>, to be handled.');\n");
127+
sb.append(" ut.expect(1).to_equal(1);\n");
128+
sb.append(" END;\n");
129+
sb.append("END;");
130+
jdbcTemplate.execute(sb.toString());
113131
}
114132

115133
@After
116134
public void teardown() {
117135
executeAndIgnore(jdbcTemplate, "DROP PACKAGE junit_utplsql_test1_pkg");
136+
executeAndIgnore(jdbcTemplate, "DROP PACKAGE junit_utplsql_test2_pkg");
118137
new CodeCoverageReporterTest().teardown();
119138
}
120139

140+
private Connection getNewConnection() {
141+
final SingleConnectionDataSource ds = new SingleConnectionDataSource();
142+
ds.setDriverClassName("oracle.jdbc.OracleDriver");
143+
ds.setUrl(dataSource.getUrl());
144+
ds.setUsername(dataSource.getUsername());
145+
ds.setPassword(dataSource.getPassword());
146+
return DatabaseTools.getConnection(ds);
147+
}
148+
121149
@Test
122150
public void runTestsWithMaxTime() {
123-
final SingleConnectionDataSource ds1 = new SingleConnectionDataSource();
124-
ds1.setDriverClassName("oracle.jdbc.OracleDriver");
125-
ds1.setUrl(dataSource.getUrl());
126-
ds1.setUsername(dataSource.getUsername());
127-
ds1.setPassword(dataSource.getPassword());
128-
final Connection producerConn = DatabaseTools.getConnection(ds1);
129-
130-
final SingleConnectionDataSource ds2 = new SingleConnectionDataSource();
131-
ds2.setDriverClassName("oracle.jdbc.OracleDriver");
132-
ds2.setUrl(dataSource.getUrl());
133-
ds2.setUsername(dataSource.getUsername());
134-
ds2.setPassword(dataSource.getPassword());
135-
final Connection consumerConn = DatabaseTools.getConnection(ds2);
136-
137-
UtplsqlRunner runner = new UtplsqlRunner(Arrays.asList(":a"), producerConn, consumerConn);
151+
UtplsqlRunner runner = new UtplsqlRunner(Collections.singletonList(":a"), getNewConnection(), getNewConnection());
138152
runner.runTestAsync();
139153

140154
SystemTools.waitForThread(runner.getProducerThread(), 200000);
@@ -146,27 +160,26 @@ public void runTestsWithMaxTime() {
146160

147161
@Test
148162
public void runTestsWithCodeCoverage() {
149-
final SingleConnectionDataSource ds1 = new SingleConnectionDataSource();
150-
ds1.setDriverClassName("oracle.jdbc.OracleDriver");
151-
ds1.setUrl(dataSource.getUrl());
152-
ds1.setUsername(dataSource.getUsername());
153-
ds1.setPassword(dataSource.getPassword());
154-
final Connection producerConn = DatabaseTools.getConnection(ds1);
155-
156-
final SingleConnectionDataSource ds2 = new SingleConnectionDataSource();
157-
ds2.setDriverClassName("oracle.jdbc.OracleDriver");
158-
ds2.setUrl(dataSource.getUrl());
159-
ds2.setUsername(dataSource.getUsername());
160-
ds2.setPassword(dataSource.getPassword());
161-
final Connection consumerConn = DatabaseTools.getConnection(ds2);
162-
163-
UtplsqlRunner runner = new UtplsqlRunner(Arrays.asList(":test_f"), null, null, null, producerConn, consumerConn);
163+
UtplsqlRunner runner = new UtplsqlRunner(Collections.singletonList(":test_f"), null, null, null, getNewConnection(), getNewConnection());
164+
runner.runTestAsync();
165+
166+
SystemTools.waitForThread(runner.getProducerThread(), 200000);
167+
SystemTools.waitForThread(runner.getConsumerThread(), 200000);
168+
SystemTools.sleep(4 * 1000);
169+
Assert.assertNotNull(runner);
170+
runner.dispose();
171+
}
172+
173+
@Test
174+
public void runTestWithNestedCdataSection() {
175+
UtplsqlRunner runner = new UtplsqlRunner(Collections.singletonList(":b"), getNewConnection(), getNewConnection());
164176
runner.runTestAsync();
165177

166178
SystemTools.waitForThread(runner.getProducerThread(), 200000);
167179
SystemTools.waitForThread(runner.getConsumerThread(), 200000);
168180
SystemTools.sleep(4 * 1000);
169181
Assert.assertNotNull(runner);
182+
Assert.assertFalse(runner.isRunning());
170183
runner.dispose();
171184
}
172185
}

sqldev/src/test/resources/logging.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ handlers=java.util.logging.ConsoleHandler
1212

1313
# Loggers
1414
#oracle.level=FINE
15-
org.utplsql.level=ALL
15+
org.utplsql.level=INFO
1616

1717
# --- ConsoleHandler ---
1818
java.util.logging.ConsoleHandler.level=ALL

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy