Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Simple solution to deal with OracleStatementTimeoutException
Fixes #20
  • Loading branch information
pesse committed Mar 13, 2019
commit 65119ba4d684033e8ff09eaf650ea5087195e718
12 changes: 12 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>orai18n</artifactId>
<version>12.2.0.1</version>
<scope>compile</scope>
</dependency>

<!-- Test -->
<dependency>
Expand Down
39 changes: 31 additions & 8 deletions src/main/java/org/utplsql/cli/ReporterManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
class ReporterManager {

private List<ReporterOptions> reporterOptionsList;
private List<Throwable> reporterGatherErrors;
private ExecutorService executorService;

ReporterManager(List<String> reporterParams ) {
initReporterOptionsList(reporterParams);
Expand Down Expand Up @@ -49,14 +51,33 @@ private void initReporterOptionsList( List<String> reporterParams ) {
}
}

private void abortGathering(Throwable e) {
addGatherError(e);
executorService.shutdownNow();
}

private void addGatherError( Throwable e ) {
if ( reporterGatherErrors == null ) {
reporterGatherErrors = new ArrayList<>();
}
reporterGatherErrors.add(e);
}

boolean haveGatherErrorsOccured() {
return reporterGatherErrors != null && !reporterGatherErrors.isEmpty();
}

List<Throwable> getGatherErrors() {
return reporterGatherErrors;
}

/** Initializes the reporters so we can use the id to gather results
*
* @param conn Active Connection
* @return List of Reporters
* @throws SQLException
*/
public List<Reporter> initReporters(Connection conn, ReporterFactory reporterFactory, CompatibilityProxy compatibilityProxy) throws SQLException
List<Reporter> initReporters(Connection conn, ReporterFactory reporterFactory, CompatibilityProxy compatibilityProxy) throws SQLException
{
final List<Reporter> reporterList = new ArrayList<>();

Expand All @@ -79,10 +100,14 @@ public List<Reporter> initReporters(Connection conn, ReporterFactory reporterFac
*
* @param executorService
* @param dataSource
* @param returnCode
*/
public void startReporterGatherers(ExecutorService executorService, final DataSource dataSource, final int[] returnCode)
void startReporterGatherers(ExecutorService executorService, final DataSource dataSource)
{
if ( this.executorService != null && !this.executorService.isShutdown())
throw new IllegalStateException("There is already a running executor service!");

this.executorService = executorService;

// TODO: Implement Init-check
// Gather each reporter results on a separate thread.
for (ReporterOptions ro : reporterOptionsList) {
Expand All @@ -103,9 +128,7 @@ public void startReporterGatherers(ExecutorService executorService, final DataSo

ro.getReporterObj().getOutputBuffer().printAvailable(conn, printStreams);
} catch (SQLException | FileNotFoundException e) {
System.out.println(e.getMessage());
returnCode[0] = Cli.DEFAULT_ERROR_CODE;
executorService.shutdownNow();
abortGathering(e);
} finally {
if (fileOutStream != null)
fileOutStream.close();
Expand All @@ -114,9 +137,9 @@ public void startReporterGatherers(ExecutorService executorService, final DataSo
}
}

public List<ReporterOptions> getReporterOptionsList() {
List<ReporterOptions> getReporterOptionsList() {
return reporterOptionsList;
}

public int getNumberOfReporters() { return reporterOptionsList.size(); }
int getNumberOfReporters() { return reporterOptionsList.size(); }
}
96 changes: 69 additions & 27 deletions src/main/java/org/utplsql/cli/RunCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.pool.HikariProxyConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.utplsql.api.*;
import org.utplsql.api.compatibility.CompatibilityProxy;
import org.utplsql.api.db.DefaultDatabaseInformation;
import org.utplsql.api.exception.DatabaseNotCompatibleException;
import org.utplsql.api.exception.OracleCreateStatmenetStuckException;
import org.utplsql.api.exception.SomeTestsFailedException;
import org.utplsql.api.exception.UtPLSQLNotInstalledException;
import org.utplsql.api.reporter.Reporter;
Expand All @@ -25,6 +28,7 @@
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
Expand Down Expand Up @@ -139,7 +143,7 @@ else if ( logDebug ) {
LoggerConfiguration.configure(level);
}

public int run() {
public int doRun() {
init();
outputMainInformation();

Expand All @@ -148,18 +152,9 @@ public int run() {
final List<Reporter> reporterList;

final File baseDir = new File("").getAbsoluteFile();
final FileMapperOptions[] sourceMappingOptions = {null};
final FileMapperOptions[] testMappingOptions = {null};

final int[] returnCode = {0};

sourceMappingOptions[0] = getFileMapperOptionsByParamListItem(this.sourcePathParams, baseDir);
testMappingOptions[0] = getFileMapperOptionsByParamListItem(this.testPathParams, baseDir);

final List<String> finalIncludeObjectsList = getObjectList(includeObjects);
final List<String> finalExcludeObjectsList = getObjectList(excludeObjects);

final DataSource dataSource = DataSourceProvider.getDataSource(getConnectionInfo(), getReporterManager().getNumberOfReporters() + 1);
final DataSource dataSource = DataSourceProvider.getDataSource(getConnectionInfo(), getReporterManager().getNumberOfReporters() + 2);

initDatabase(dataSource);
reporterList = initReporters(dataSource);
Expand All @@ -173,33 +168,50 @@ public int run() {
ExecutorService executorService = Executors.newFixedThreadPool(1 + reporterList.size());

// Run tests.
executorService.submit(() -> {
try (Connection conn = dataSource.getConnection()) {
TestRunner testRunner = new TestRunner()
.addPathList(testPaths)
.addReporterList(reporterList)
.sourceMappingOptions(sourceMappingOptions[0])
.testMappingOptions(testMappingOptions[0])
.colorConsole(this.colorConsole)
.failOnErrors(true)
.skipCompatibilityCheck(skipCompatibilityCheck)
.includeObjects(finalIncludeObjectsList)
.excludeObjects(finalExcludeObjectsList);
Future<Integer> future = executorService.submit(() -> {
Connection conn = null;
try {
conn = dataSource.getConnection();
TestRunner testRunner = newTestRunner(reporterList);

logger.info("Running tests now.");
logger.info("--------------------------------------");
testRunner.run(conn);
} catch (SomeTestsFailedException e) {
returnCode[0] = this.failureExitCode;
} catch (SQLException e) {
}
catch (OracleCreateStatmenetStuckException e ) {
try {
conn.abort(Executors.newSingleThreadExecutor());
conn = null;
} catch (SQLException e1) {
logger.error(e1.getMessage(), e1);
}
executorService.shutdownNow();
return 3;
}
catch (SQLException e) {
System.out.println(e.getMessage());
returnCode[0] = Cli.DEFAULT_ERROR_CODE;
//returnCode[0] = Cli.DEFAULT_ERROR_CODE;
executorService.shutdownNow();
return Cli.DEFAULT_ERROR_CODE;
}
finally {
if ( conn != null ) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return 0;
});

// Gather each reporter results on a separate thread.
getReporterManager().startReporterGatherers(executorService, dataSource, returnCode);
getReporterManager().startReporterGatherers(executorService, dataSource);

Integer mainTestResult = future.get();

executorService.shutdown();
if ( !executorService.awaitTermination(timeoutInMinutes, TimeUnit.MINUTES) ) {
Expand All @@ -209,7 +221,9 @@ public int run() {
logger.info("--------------------------------------");
logger.info("All tests done.");

return returnCode[0];
((HikariDataSource)dataSource).close();

return mainTestResult;
}
catch ( DatabaseNotCompatibleException | UtPLSQLNotInstalledException | DatabaseConnectionFailed | ReporterTimeoutException e ) {
System.out.println(e.getMessage());
Expand All @@ -219,6 +233,34 @@ public int run() {
return Cli.DEFAULT_ERROR_CODE;
}

public int run() {
int i = 1;
int exitCode = doRun();
// Retry
while ( exitCode == 3 && i<10 ) {
logger.warn("Retry");
exitCode = doRun();
i++;
}
return exitCode;
}

private TestRunner newTestRunner( List<Reporter> reporterList) {

final File baseDir = new File("").getAbsoluteFile();

return new TestRunner()
.addPathList(testPaths)
.addReporterList(reporterList)
.sourceMappingOptions(getFileMapperOptionsByParamListItem(this.sourcePathParams, baseDir))
.testMappingOptions(getFileMapperOptionsByParamListItem(this.testPathParams, baseDir))
.colorConsole(this.colorConsole)
.failOnErrors(true)
.skipCompatibilityCheck(skipCompatibilityCheck)
.includeObjects(getObjectList(includeObjects))
.excludeObjects(getObjectList(excludeObjects));
}

private ArrayList<String> getObjectList(String includeObjects) {
ArrayList<String> includeObjectsList;
if (includeObjects != null && !includeObjects.isEmpty()) {
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/org/utplsql/cli/TestRunnerTask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.utplsql.cli;

import org.utplsql.api.TestRunner;

import java.sql.Connection;
import java.util.concurrent.ExecutorService;

class TestRunnerTask implements Runnable {

private Connection con;
private TestRunner testRunner;
private ExecutorService executorService;

TestRunnerTask(Connection con, TestRunner testRunner, ExecutorService executorService ) {
this.con = con;
this.testRunner = testRunner;
this.executorService = executorService;
}

@Override
public void run() {

}
}
46 changes: 46 additions & 0 deletions src/test/java/org/utplsql/cli/RunCommandIssue20Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.utplsql.cli;

import java.util.List;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.utplsql.api.reporter.CoreReporters;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* Unit test for run command.
*/
class RunCommandIssue20Test {

private static final Logger logger = LoggerFactory.getLogger(RunCommandIssue20Test.class);

@Test
void runLoop() {
RunCommand runCmd = TestHelper.createRunCommand(
TestHelper.getConnectionString(),
"-p=TEST_BETWNSTR.normal_case",
"-f=ut_documentation_reporter");
List<ReporterOptions> reporterOptionsList = runCmd.getReporterOptionsList();
ReporterOptions reporterOptions1 = reporterOptionsList.get(0);
assertEquals(CoreReporters.UT_DOCUMENTATION_REPORTER.name(), reporterOptions1.getReporterName());
assertTrue(reporterOptions1.outputToScreen());
// Loop in same JVM, uses a lot of new connections without closing existing ones, this might lead to
// "Could not establish connection to database. Reason: IO Error: Got minus one from a read call"
// before hitting the hanger at oracle.jdbc.driver.OracleStruct.getOracleAttributes(OracleStruct.java:347)
// You may increase processes and implicitly sessions by "alter system set processes=1024 scope=spfile;"
for (int i=0; i <= 120; i++) {
logger.info("=======================");
logger.info("Loop number " + i);
logger.info("=======================");
int result = runCmd.run();
if (result != 0) {
logger.error("Got an error during run. Return Code was " + result + "." );
break;
}
}
}

}