Skip to content

Feature/version check #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Nov 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
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
18 changes: 9 additions & 9 deletions .travis/install_utplsql.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@ set -ev
cd $(dirname $(readlink -f $0))

# Download the specified version of utPLSQL.
# UTPLSQL_VERSION="v3.0.0-beta"
# UTPLSQL_FILE="utPLSQLv3.0.0.562-beta"
# curl -L -O "https://github.com/utPLSQL/utPLSQL/releases/download/$UTPLSQL_VERSION/$UTPLSQL_FILE.tar.gz"
UTPLSQL_VERSION="v3.0.4"
UTPLSQL_FILE="utPLSQL"
curl -L -O "https://github.com/utPLSQL/utPLSQL/releases/download/$UTPLSQL_VERSION/$UTPLSQL_FILE.tar.gz"

# Download develop branch of utPLSQL.
UTPLSQL_VERSION="develop"
UTPLSQL_FILE="utPLSQL"
git clone -b develop --single-branch https://github.com/utPLSQL/utPLSQL.git
#UTPLSQL_VERSION="develop"
#UTPLSQL_FILE="utPLSQL"
#git clone -b develop --single-branch https://github.com/utPLSQL/utPLSQL.git
# tar -czf $UTPLSQL_FILE.tar.gz $UTPLSQL_FILE && rm -rf $UTPLSQL_FILE

# Create a temporary install script.
cat > install.sh.tmp <<EOF
# tar -xzf ${UTPLSQL_FILE}.tar.gz && rm ${UTPLSQL_FILE}.tar.gz
tar -xzf ${UTPLSQL_FILE}.tar.gz && rm ${UTPLSQL_FILE}.tar.gz
cd ${UTPLSQL_FILE}/source
sqlplus -S -L sys/oracle@//127.0.0.1:1521/xe AS SYSDBA @install_headless.sql ut3 ut3 users
EOF

# Copy utPLSQL files to the container and install it.
# docker cp ./$UTPLSQL_FILE.tar.gz $ORACLE_VERSION:/$UTPLSQL_FILE.tar.gz
docker cp ./$UTPLSQL_FILE $ORACLE_VERSION:/$UTPLSQL_FILE
docker cp ./$UTPLSQL_FILE.tar.gz $ORACLE_VERSION:/$UTPLSQL_FILE.tar.gz
# docker cp ./$UTPLSQL_FILE $ORACLE_VERSION:/$UTPLSQL_FILE
docker cp ./install.sh.tmp $ORACLE_VERSION:/install.sh
docker cp ./create_api_user.sh $ORACLE_VERSION:/create_api_user.sh

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>org.utplsql</groupId>
<artifactId>java-api</artifactId>
<version>1.0-SNAPSHOT</version>
<version>3.0.4-SNAPSHOT</version>
<packaging>jar</packaging>

<name>utPLSQL-java-api</name>
Expand Down
54 changes: 48 additions & 6 deletions src/main/java/org/utplsql/api/DBHelper.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package org.utplsql.api;

import oracle.jdbc.OracleTypes;
import org.utplsql.api.exception.DatabaseNotCompatibleException;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import java.sql.*;

/**
* Database utility functions.
*/
public final class DBHelper {

public static final String UTPLSQL_COMPATIBILITY_VERSION = "3.0.3";
public static final String UTPLSQL_COMPATIBILITY_VERSION = "3";

private DBHelper() {}

Expand Down Expand Up @@ -96,6 +94,51 @@ public static boolean versionCompatibilityCheck(Connection conn)
return versionCompatibilityCheck(conn, UTPLSQL_COMPATIBILITY_VERSION);
}


/** Checks if actual API-version is compatible with utPLSQL database version and throws a DatabaseNotCompatibleException if not
* Throws a DatabaseNotCompatibleException if version compatibility can not be checked.
*
* @param conn Active db connection
*/
public static void failOnVersionCompatibilityCheckFailed( Connection conn ) throws DatabaseNotCompatibleException
{
try {
if (!versionCompatibilityCheck(conn))
{
// Try to find out Framework Version
Version v = DBHelper.getDatabaseFrameworkVersion(conn);

throw new DatabaseNotCompatibleException( v );
}
}
catch ( SQLException e )
{
throw new DatabaseNotCompatibleException("Compatibility-check failed with error. Aborting. Reason: " + e.getMessage(), new Version(UTPLSQL_COMPATIBILITY_VERSION), new Version("Unknown"), e);
}
}

/** Returns the Frameworks version string of the given connection
*
* @param conn Active db connection
* @return
* @throws SQLException
*/
public static Version getDatabaseFrameworkVersion( Connection conn )
throws SQLException {
Version result = new Version("");
try (PreparedStatement stmt = conn.prepareStatement("select ut_runner.version() from dual"))
{
ResultSet rs = stmt.executeQuery();

if ( rs.next() )
result = new Version(rs.getString(1));

rs.close();
}

return result;
}

/**
* Enable the dbms_output buffer with unlimited size.
* @param conn the connection
Expand All @@ -119,5 +162,4 @@ public static void disableDBMSOutput(Connection conn) {
System.out.println("Failed to disable dbms_output.");
}
}

}
144 changes: 44 additions & 100 deletions src/main/java/org/utplsql/api/TestRunner.java
Original file line number Diff line number Diff line change
@@ -1,188 +1,132 @@
package org.utplsql.api;

import oracle.jdbc.OracleConnection;
import org.utplsql.api.compatibility.CompatibilityProvider;
import org.utplsql.api.exception.DatabaseNotCompatibleException;
import org.utplsql.api.exception.SomeTestsFailedException;
import org.utplsql.api.reporter.DocumentationReporter;
import org.utplsql.api.reporter.Reporter;
import oracle.jdbc.OracleConnection;
import org.utplsql.api.testRunner.TestRunnerStatement;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;

/**
* Created by Vinicius Avellar on 12/04/2017.
*
* @author Vinicius Avellar
* @author pesse
*/
public class TestRunner {

private List<String> pathList = new ArrayList<>();
private List<Reporter> reporterList = new ArrayList<>();
private boolean colorConsole = false;
private List<String> coverageSchemes = new ArrayList<>();
private List<String> sourceFiles = new ArrayList<>();
private List<String> testFiles = new ArrayList<>();
private List<String> includeObjects = new ArrayList<>();
private List<String> excludeObjects = new ArrayList<>();
private FileMapperOptions sourceMappingOptions;
private FileMapperOptions testMappingOptions;
private boolean failOnErrors = false;
private TestRunnerOptions options = new TestRunnerOptions();

public TestRunner addPath(String path) {
this.pathList.add(path);
options.pathList.add(path);
return this;
}

public TestRunner addPathList(List<String> paths) {
if (pathList != null) this.pathList.addAll(paths);
if (options.pathList != null) options.pathList.addAll(paths);
return this;
}

public TestRunner addReporter(Reporter reporter) {
this.reporterList.add(reporter);
options.reporterList.add(reporter);
return this;
}

public TestRunner colorConsole(boolean colorConsole) {
this.colorConsole = colorConsole;
options.colorConsole = colorConsole;
return this;
}

public TestRunner addReporterList(List<Reporter> reporterList) {
if (reporterList != null) this.reporterList.addAll(reporterList);
if (options.reporterList != null) options.reporterList.addAll(reporterList);
return this;
}

public TestRunner addCoverageScheme(String coverageScheme) {
this.coverageSchemes.add(coverageScheme);
options.coverageSchemes.add(coverageScheme);
return this;
}

public TestRunner includeObject(String obj) {
this.includeObjects.add(obj);
options.includeObjects.add(obj);
return this;
}

public TestRunner excludeObject(String obj) {
this.excludeObjects.add(obj);
options.excludeObjects.add(obj);
return this;
}

public TestRunner sourceMappingOptions(FileMapperOptions mapperOptions) {
this.sourceMappingOptions = mapperOptions;
options.sourceMappingOptions = mapperOptions;
return this;
}

public TestRunner testMappingOptions(FileMapperOptions mapperOptions) {
this.testMappingOptions = mapperOptions;
options.testMappingOptions = mapperOptions;
return this;
}

public TestRunner failOnErrors(boolean failOnErrors) {
this.failOnErrors = failOnErrors;
options.failOnErrors = failOnErrors;
return this;
}

public TestRunner skipCompatibilityCheck( boolean skipCompatibilityCheck )
{
options.skipCompatibilityCheck = skipCompatibilityCheck;
return this;
}

public void run(Connection conn) throws SomeTestsFailedException, SQLException {
for (Reporter r : this.reporterList)
public void run(Connection conn) throws SomeTestsFailedException, SQLException, DatabaseNotCompatibleException {

// First of all check version compatibility
if ( !options.skipCompatibilityCheck )
DBHelper.failOnVersionCompatibilityCheckFailed(conn);

for (Reporter r : options.reporterList)
validateReporter(conn, r);

if (this.pathList.isEmpty()) {
this.pathList.add(DBHelper.getCurrentSchema(conn));
if (options.pathList.isEmpty()) {
options.pathList.add(DBHelper.getCurrentSchema(conn));
}

if (this.reporterList.isEmpty()) {
this.reporterList.add(new DocumentationReporter().init(conn));
if (options.reporterList.isEmpty()) {
options.reporterList.add(new DocumentationReporter().init(conn));
}

// Workaround because Oracle JDBC doesn't support passing boolean to stored procedures.
String colorConsoleStr = Boolean.toString(this.colorConsole);
String failOnErrors = Boolean.toString(this.failOnErrors);
TestRunnerStatement testRunnerStatement = null;

OracleConnection oraConn = conn.unwrap(OracleConnection.class);
CallableStatement callableStatement = null;
try {
DBHelper.enableDBMSOutput(conn);

callableStatement = conn.prepareCall(
"BEGIN " +
"ut_runner.run(" +
"a_paths => ?, " +
"a_reporters => ?, " +
"a_color_console => " + colorConsoleStr + ", " +
"a_coverage_schemes => ?, " +
"a_source_file_mappings => ?, " +
"a_test_file_mappings => ?, " +
"a_include_objects => ?, " +
"a_exclude_objects => ?, " +
"a_fail_on_errors => " + failOnErrors + "); " +
"END;");

int paramIdx = 0;

callableStatement.setArray(
++paramIdx, oraConn.createOracleArray(CustomTypes.UT_VARCHAR2_LIST, this.pathList.toArray()));

callableStatement.setArray(
++paramIdx, oraConn.createOracleArray(CustomTypes.UT_REPORTERS, this.reporterList.toArray()));

if (this.coverageSchemes.isEmpty()) {
callableStatement.setNull(++paramIdx, Types.ARRAY, CustomTypes.UT_VARCHAR2_LIST);
} else {
callableStatement.setArray(
++paramIdx, oraConn.createOracleArray(CustomTypes.UT_VARCHAR2_LIST, this.coverageSchemes.toArray()));
}

if (this.sourceMappingOptions == null) {
callableStatement.setNull(++paramIdx, Types.ARRAY, CustomTypes.UT_FILE_MAPPINGS);
} else {
List<FileMapping> sourceMappings = FileMapper.buildFileMappingList(conn, this.sourceMappingOptions);

callableStatement.setArray(
++paramIdx, oraConn.createOracleArray(CustomTypes.UT_FILE_MAPPINGS, sourceMappings.toArray()));
}

if (this.testMappingOptions == null) {
callableStatement.setNull(++paramIdx, Types.ARRAY, CustomTypes.UT_FILE_MAPPINGS);
} else {
List<FileMapping> sourceMappings = FileMapper.buildFileMappingList(conn, this.testMappingOptions);

callableStatement.setArray(
++paramIdx, oraConn.createOracleArray(CustomTypes.UT_FILE_MAPPINGS, sourceMappings.toArray()));
}

if (this.includeObjects.isEmpty()) {
callableStatement.setNull(++paramIdx, Types.ARRAY, CustomTypes.UT_VARCHAR2_LIST);
} else {
callableStatement.setArray(
++paramIdx, oraConn.createOracleArray(CustomTypes.UT_VARCHAR2_LIST, this.includeObjects.toArray()));
}

if (this.excludeObjects.isEmpty()) {
callableStatement.setNull(++paramIdx, Types.ARRAY, CustomTypes.UT_VARCHAR2_LIST);
} else {
callableStatement.setArray(
++paramIdx, oraConn.createOracleArray(CustomTypes.UT_VARCHAR2_LIST, this.excludeObjects.toArray()));
}
testRunnerStatement = CompatibilityProvider.getTestRunnerStatement(options, conn);

callableStatement.execute();
testRunnerStatement.execute();
} catch (SQLException e) {
if (e.getErrorCode() == SomeTestsFailedException.ERROR_CODE) {
throw new SomeTestsFailedException(e.getMessage(), e);
} else {
// If the execution failed by unexpected reasons finishes all reporters,
// this way the users don't need to care about reporters' sessions hanging.
OracleConnection oraConn = conn.unwrap(OracleConnection.class);

try (CallableStatement closeBufferStmt = conn.prepareCall("BEGIN ut_output_buffer.close(?); END;")) {
closeBufferStmt.setArray(1, oraConn.createOracleArray(CustomTypes.UT_REPORTERS, this.reporterList.toArray()));
closeBufferStmt.setArray(1, oraConn.createOracleArray(CustomTypes.UT_REPORTERS, options.reporterList.toArray()));
closeBufferStmt.execute();
} catch (SQLException ignored) {}

throw e;
}
} finally {
if (callableStatement != null) {
callableStatement.close();
if (testRunnerStatement != null) {
testRunnerStatement.close();
}

DBHelper.disableDBMSOutput(conn);
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/org/utplsql/api/TestRunnerOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.utplsql.api;

import org.utplsql.api.reporter.Reporter;

import java.util.ArrayList;
import java.util.List;

/** Holds the various possible options of TestRunner
*
* @author pesse
*/
public class TestRunnerOptions {
public List<String> pathList = new ArrayList<>();
public List<Reporter> reporterList = new ArrayList<>();
public boolean colorConsole = false;
public List<String> coverageSchemes = new ArrayList<>();
public List<String> sourceFiles = new ArrayList<>();
public List<String> testFiles = new ArrayList<>();
public List<String> includeObjects = new ArrayList<>();
public List<String> excludeObjects = new ArrayList<>();
public FileMapperOptions sourceMappingOptions;
public FileMapperOptions testMappingOptions;
public boolean failOnErrors = false;
public boolean skipCompatibilityCheck = false;
}
Loading