diff --git a/pkg/acceptance/java/TestRunner.java b/pkg/acceptance/java/TestRunner.java new file mode 100644 index 000000000000..b8c37370c08c --- /dev/null +++ b/pkg/acceptance/java/TestRunner.java @@ -0,0 +1,179 @@ +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +/* +This class compiles and runs all java files under a directory. +Usage : java TestRunner [expected] [dir] + expected : can be 'SUCCESS' or 'FAIL' depicting the success/failing of a test case + dir : the directory containing all java test files + */ +public class TestRunner { + + private enum ExpectedOutcome { + SUCCESS, + FAIL; + + public static ExpectedOutcome parse(String s) { + try { + return ExpectedOutcome.valueOf(s); + } catch (Exception e) { + return null; + } + } + } + + public static void main(String[] args) throws Exception { + if (args.length < 2) { + throw new Exception("unexpected : missing arguments. usage : java TestRunner [SUCCESS/FAIL] [dir]"); + } + + String mode = args[0], testDirectory = args[1]; + ExpectedOutcome expectedOutcome = ExpectedOutcome.parse(mode); + if (expectedOutcome == null) { + throw new Exception("unexpected : missing arguments. usage : java TestRunner [SUCCESS/FAIL] [dir]"); + } + + Result result = runTests(expectedOutcome, testDirectory); + // Clean up all generated files before throwing the exception + cleanup(); + if (!result.isSuccess()) { + throw new Exception(result.getException().getMessage()); + } + } + + // Runs all test in the {testsDirectory} and checks that each test has the expected outcome + private static Result runTests(ExpectedOutcome expected, String testsDirectory) throws Exception { + List tests = listJavaFiles(testsDirectory); + for (File test : tests) { + Result testResult = runTest(test); + + switch (expected) { + case SUCCESS: + if (testResult.isSuccess()) { + break; + } + // This test should have "PASSED" but "FAILED + return failureResult( + String.format("\n\nTest [%s]\nResult : [FAILED]\nExcepted: [SUCCESS]\nCause: %s\n", + test.getName(), testResult.getException().getMessage())); + + case FAIL: + if (!testResult.isSuccess()) { + break; + } + // This test should have "FAILED" but "PASSED". + return failureResult + (String.format("\n\nTest [%s]\nResult: [PASSED]\nExcepted: [FAILURE].", + test.getName())); + } + } + return successResult(); + } + + // Lists all java files in a directory + private static List listJavaFiles(String path) { + List javaFiles = new ArrayList<>(); + + File directory = new File(path); + File[] files = directory.listFiles(); + if (files == null) { + return javaFiles; + } + + for (File file : files) { + if (!file.getName().contains(".java")) { + continue; + } + javaFiles.add(file); + } + return javaFiles; + } + + // Compiles and runs the test java file and returns the result + private static Result runTest(File test) { + String javaFile = test.getName(); + String javaFilePrefix = javaFile.substring(0, javaFile.lastIndexOf(".")); + File parent = test.getParentFile(); + String classPath = String.format("/postgres.jar:%s:.", parent.getAbsolutePath()); + + String[] compileCmds = new String[] {"javac", test.getAbsolutePath()}; + String[] runCmds = new String[] {"java", "-cp", classPath, javaFilePrefix}; + + try { + // Compiles the java code + Process compileTest = Runtime.getRuntime().exec(compileCmds); + String errorTrace = toString(compileTest.getErrorStream()); + compileTest.waitFor(); + if (compileTest.exitValue() != 0) { + return failureResult(errorTrace); + } + + // Runs the java code + Process runTest = Runtime.getRuntime().exec(runCmds); + errorTrace = toString(runTest.getErrorStream()); + runTest.waitFor(); + if (runTest.exitValue() != 0) { + return failureResult(errorTrace); + } + + return successResult(); + } catch (Exception e) { + return failureResult(e.getMessage()); + } + } + + // Runs the clean up script + private static void cleanup() { + try { + run(new String[]{"/bin/bash", "-c", "./run_cleanup.sh"}); + } catch (Exception e) { + } + } + + private static Process run(String[] cmds) throws Exception { + Process exec = Runtime.getRuntime().exec(cmds); + exec.waitFor(); + return exec; + } + + private static String toString(InputStream ins) throws Exception { + StringBuilder sb = new StringBuilder(); + String line; + BufferedReader in = new BufferedReader(new InputStreamReader(ins)); + while ((line = in.readLine()) != null) { + sb.append(line).append("\n"); + } + return sb.toString(); + } + + private static Result failureResult(String message) { + return new Result(false, new Exception(message)); + } + + private static Result successResult() { + return new Result(true, null); + } + + // A wrapper object containing test case execution result and the exception + private static class Result { + private final boolean success; + private final Exception exception; + + public Result(boolean success, Exception exception) { + this.success = success; + this.exception = exception; + } + + public boolean isSuccess() { + return success; + } + + public Exception getException() { + return exception; + } + } +} \ No newline at end of file diff --git a/pkg/acceptance/java/fail/JavaFailureTest.java b/pkg/acceptance/java/fail/JavaFailureTest.java new file mode 100644 index 000000000000..9d6b6b4e79e5 --- /dev/null +++ b/pkg/acceptance/java/fail/JavaFailureTest.java @@ -0,0 +1,78 @@ +import java.sql.*; + +public class JavaFailureTest { + + public static void main(String[] args) throws Exception { + Class.forName("org.postgresql.Driver"); + String DB_URL = "jdbc:postgresql://"; + DB_URL += System.getenv("PGHOST") + ":" + System.getenv("PGPORT"); + DB_URL += "/test?ssl=true"; + DB_URL += "&sslcert=" + System.getenv("PGSSLCERT"); + DB_URL += "&sslkey=key.pk8"; + DB_URL += "&sslrootcert=/certs/ca.crt"; + DB_URL += "&sslfactory=org.postgresql.ssl.jdbc4.LibPQFactory"; + Connection conn = DriverManager.getConnection(DB_URL); + PreparedStatement stmt = conn.prepareStatement("CREATE DATABASE test"); + int res = stmt.executeUpdate(); + if (res != 0) { + throw new Exception("unexpected: CREATE DATABASE reports " + res + " rows changed, expecting 0"); + } + stmt = conn.prepareStatement("CREATE TABLE test.f (x INT, ts TIMESTAMP)"); + res = stmt.executeUpdate(); + if (res != 0) { + throw new Exception("unexpected: CREATE TABLE reports " + res + " rows changed, expecting 0"); + } + stmt = conn.prepareStatement("INSERT INTO test.f VALUES (42, timestamp '2015-05-07 18:20:00')"); + res = stmt.executeUpdate(); + if (res != 1) { + throw new Exception("unexpected: INSERT reports " + res + " rows changed, expecting 1"); + } + stmt = conn.prepareStatement("SELECT * FROM test.f"); + ResultSet rs = stmt.executeQuery(); + rs.next(); + int a = rs.getInt(1); + if (a != 42) { + throw new Exception("unexpected: SELECT can't find inserted value: read " + a + ", expecting 42"); + } + String tsStr = rs.getTimestamp(2).toString(); + if (!tsStr.equals("2015-05-07 18:20:00.0")) { + throw new Exception("unexpected value for ts: "+tsStr); + } + stmt = conn.prepareStatement("DROP TABLE test.f"); + res = stmt.executeUpdate(); + if (res != 0) { + throw new Exception("unexpected: DROP TABLE reports " + res + " rows changed, expecting 0"); + } + stmt = conn.prepareStatement("SELECT 1, 2 > ?, ?::int, ?::string, ?::string, ?::string, ?::string, ?::string"); + stmt.setInt(1, 3); + stmt.setString(2, "a"); + stmt.setBoolean(3, true); + stmt.setLong(4, -4L); + stmt.setFloat(5, 5.31f); + stmt.setDouble(6, -6.21d); + stmt.setShort(7, (short)7); + rs = stmt.executeQuery(); + rs.next(); + a = rs.getInt(1); + boolean b = rs.getBoolean(2); + int c = rs.getInt(3); + String d = rs.getString(4); + String e = rs.getString(5); + String f = rs.getString(6); + String g = rs.getString(7); + String h = rs.getString(8); + if (a != 1 || b != false || c != 3 || !d.equals("true") || !e.equals("-4") || !f.startsWith("5.3") || !g.startsWith("-6.2") || !h.equals("7")) { + throw new Exception("unexpected"); + } + stmt = conn.prepareStatement("CREATE TABLE accounts (id INT PRIMARY KEY, balance INT, cdate DATE)"); + res = stmt.executeUpdate(); + if (res != 0) { + throw new Exception("unexpected: CREATE TABLE reports " + res + " rows changed, expecting 0"); + } + stmt = conn.prepareStatement("INSERT INTO accounts (id, balance, cdate) VALUES ( ?, ?, ? )"); + stmt.setObject(1, 1); + stmt.setObject(2, 1000); + stmt.setObject(3, new java.sql.Date(System.currentTimeMillis())); + stmt.executeUpdate(); + } +} diff --git a/pkg/acceptance/java/run_cleanup.sh b/pkg/acceptance/java/run_cleanup.sh new file mode 100755 index 000000000000..ac207adeb8a5 --- /dev/null +++ b/pkg/acceptance/java/run_cleanup.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +# cleans all {.class, .pk8} files in the current directory +find . -type f -name "*.class" -exec rm -f {} \; +find . -type f -name "*.pk8" -exec rm -f {} \; diff --git a/pkg/acceptance/java/run_java_test.sh b/pkg/acceptance/java/run_java_test.sh new file mode 100755 index 000000000000..f246cd66fce9 --- /dev/null +++ b/pkg/acceptance/java/run_java_test.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -e + +# set up environment +export PATH=$PATH:/usr/lib/jvm/java-1.8-openjdk/bin +export JAVA_ROOT=/go/src/github.com/cockroachdb/cockroach/acceptance/java +export CLASSPATH=$CLASSPATH:$JAVA_ROOT/success:$JAVA_ROOT/fail:$JAVA_ROOT + +cd $JAVA_ROOT + +# See: https://basildoncoder.com/blog/postgresql-jdbc-client-certificates.html +openssl pkcs8 -topk8 -inform PEM -outform DER -in /certs/node.key -out key.pk8 -nocrypt + +# compile and run java files +case $1 in +SUCCESS) + expected=SUCCESS + test_cases_dir=success + ;; +FAILURE) + expected=FAIL + test_cases_dir=fail + ;; +esac + +javac TestRunner.java +java TestRunner $expected $JAVA_ROOT/$test_cases_dir + +./run_cleanup.sh diff --git a/pkg/acceptance/java/success/JavaSuccessTest.java b/pkg/acceptance/java/success/JavaSuccessTest.java new file mode 100644 index 000000000000..cb6d1bd9f1f7 --- /dev/null +++ b/pkg/acceptance/java/success/JavaSuccessTest.java @@ -0,0 +1,80 @@ +import java.sql.*; + +public class JavaSuccessTest { + + public static void main(String[] args) throws Exception { + Class.forName("org.postgresql.Driver"); + + String DB_URL = "jdbc:postgresql://"; + DB_URL += System.getenv("PGHOST") + ":" + System.getenv("PGPORT"); + DB_URL += "/test?ssl=true"; + DB_URL += "&sslcert=" + System.getenv("PGSSLCERT"); + DB_URL += "&sslkey=key.pk8"; + DB_URL += "&sslrootcert=/certs/ca.crt"; + DB_URL += "&sslfactory=org.postgresql.ssl.jdbc4.LibPQFactory"; + Connection conn = DriverManager.getConnection(DB_URL); + + PreparedStatement stmt = conn.prepareStatement("CREATE DATABASE test"); + int res = stmt.executeUpdate(); + if (res != 0) { + throw new Exception("unexpected: CREATE DATABASE reports " + res + " rows changed, expecting 0"); + } + stmt = conn.prepareStatement("CREATE TABLE test.f (x INT, ts TIMESTAMP)"); + res = stmt.executeUpdate(); + if (res != 0) { + throw new Exception("unexpected: CREATE TABLE reports " + res + " rows changed, expecting 0"); + } + stmt = conn.prepareStatement("INSERT INTO test.f VALUES (42, timestamp '2015-05-07 18:20:00')"); + res = stmt.executeUpdate(); + if (res != 1) { + throw new Exception("unexpected: INSERT reports " + res + " rows changed, expecting 1"); + } + stmt = conn.prepareStatement("SELECT * FROM test.f"); + ResultSet rs = stmt.executeQuery(); + rs.next(); + int a = rs.getInt(1); + if (a != 42) { + throw new Exception("unexpected: SELECT can't find inserted value: read " + a + ", expecting 42"); + } + String tsStr = rs.getTimestamp(2).toString(); + if (!tsStr.equals("2015-05-07 18:20:00.0")) { + throw new Exception("unexpected value for ts: "+tsStr); + } + stmt = conn.prepareStatement("DROP TABLE test.f"); + res = stmt.executeUpdate(); + if (res != 0) { + throw new Exception("unexpected: DROP TABLE reports " + res + " rows changed, expecting 0"); + } + stmt = conn.prepareStatement("SELECT 1, 2 > ?, ?::int, ?::string, ?::string, ?::string, ?::string, ?::string"); + stmt.setInt(1, 3); + stmt.setInt(2, 3); + stmt.setBoolean(3, true); + stmt.setLong(4, -4L); + stmt.setFloat(5, 5.31f); + stmt.setDouble(6, -6.21d); + stmt.setShort(7, (short)7); + rs = stmt.executeQuery(); + rs.next(); + a = rs.getInt(1); + boolean b = rs.getBoolean(2); + int c = rs.getInt(3); + String d = rs.getString(4); + String e = rs.getString(5); + String f = rs.getString(6); + String g = rs.getString(7); + String h = rs.getString(8); + if (a != 1 || b != false || c != 3 || !d.equals("true") || !e.equals("-4") || !f.startsWith("5.3") || !g.startsWith("-6.2") || !h.equals("7")) { + throw new Exception("unexpected"); + } + stmt = conn.prepareStatement("CREATE TABLE accounts (id INT PRIMARY KEY, balance INT, cdate DATE)"); + res = stmt.executeUpdate(); + if (res != 0) { + throw new Exception("unexpected: CREATE TABLE reports " + res + " rows changed, expecting 0"); + } + stmt = conn.prepareStatement("INSERT INTO accounts (id, balance, cdate) VALUES ( ?, ?, ? )"); + stmt.setObject(1, 1); + stmt.setObject(2, 1000); + stmt.setObject(3, new java.sql.Date(System.currentTimeMillis())); + stmt.executeUpdate(); + } +} diff --git a/pkg/acceptance/java_test.go b/pkg/acceptance/java_test.go index 22dff3d10859..54e0458c7e8e 100644 --- a/pkg/acceptance/java_test.go +++ b/pkg/acceptance/java_test.go @@ -17,111 +17,11 @@ package acceptance import ( - "strings" "testing" ) func TestDockerJava(t *testing.T) { - testDockerSuccess(t, "java", []string{"/bin/sh", "-c", strings.Replace(java, "%v", "Int(2, 3)", 1)}) - testDockerFail(t, "java", []string{"/bin/sh", "-c", strings.Replace(java, "%v", `String(2, "a")`, 1)}) + testScript := "/go/src/github.com/cockroachdb/cockroach/acceptance/java/run_java_test.sh" + testDockerSuccess(t, "java", []string{"/bin/sh", "-c", testScript + " SUCCESS"}) + testDockerSuccess(t, "java", []string{"/bin/sh", "-c", testScript + " FAILURE"}) } - -const java = ` -set -e -cat > main.java << 'EOF' -import java.sql.*; - -public class main { - public static void main(String[] args) throws Exception { - Class.forName("org.postgresql.Driver"); - - String DB_URL = "jdbc:postgresql://"; - DB_URL += System.getenv("PGHOST") + ":" + System.getenv("PGPORT"); - DB_URL += "/test?ssl=true"; - DB_URL += "&sslcert=" + System.getenv("PGSSLCERT"); - DB_URL += "&sslkey=key.pk8"; - DB_URL += "&sslrootcert=/certs/ca.crt"; - DB_URL += "&sslfactory=org.postgresql.ssl.jdbc4.LibPQFactory"; - Connection conn = DriverManager.getConnection(DB_URL); - - PreparedStatement stmt = conn.prepareStatement("CREATE DATABASE test"); - int res = stmt.executeUpdate(); - if (res != 0) { - throw new Exception("unexpected: CREATE DATABASE reports " + res + " rows changed, expecting 0"); - } - - stmt = conn.prepareStatement("CREATE TABLE test.f (x INT, ts TIMESTAMP)"); - res = stmt.executeUpdate(); - if (res != 0) { - throw new Exception("unexpected: CREATE TABLE reports " + res + " rows changed, expecting 0"); - } - - stmt = conn.prepareStatement("INSERT INTO test.f VALUES (42, timestamp '2015-05-07 18:20:00')"); - res = stmt.executeUpdate(); - if (res != 1) { - throw new Exception("unexpected: INSERT reports " + res + " rows changed, expecting 1"); - } - - stmt = conn.prepareStatement("SELECT * FROM test.f"); - ResultSet rs = stmt.executeQuery(); - rs.next(); - int a = rs.getInt(1); - if (a != 42) { - throw new Exception("unexpected: SELECT can't find inserted value: read " + a + ", expecting 42"); - } - String tsStr = rs.getTimestamp(2).toString(); - if (!tsStr.equals("2015-05-07 18:20:00.0")) { - throw new Exception("unexpected value for ts: "+tsStr); - } - stmt = conn.prepareStatement("DROP TABLE test.f"); - res = stmt.executeUpdate(); - if (res != 0) { - throw new Exception("unexpected: DROP TABLE reports " + res + " rows changed, expecting 0"); - } - - stmt = conn.prepareStatement("SELECT 1, 2 > ?, ?::int, ?::string, ?::string, ?::string, ?::string, ?::string"); - stmt.setInt(1, 3); - stmt.set%v; - - stmt.setBoolean(3, true); - stmt.setLong(4, -4L); - stmt.setFloat(5, 5.31f); - stmt.setDouble(6, -6.21d); - stmt.setShort(7, (short)7); - - rs = stmt.executeQuery(); - rs.next(); - a = rs.getInt(1); - boolean b = rs.getBoolean(2); - int c = rs.getInt(3); - String d = rs.getString(4); - String e = rs.getString(5); - String f = rs.getString(6); - String g = rs.getString(7); - String h = rs.getString(8); - if (a != 1 || b != false || c != 3 || !d.equals("true") || !e.equals("-4") || !f.startsWith("5.3") || !g.startsWith("-6.2") || !h.equals("7")) { - throw new Exception("unexpected"); - } - - stmt = conn.prepareStatement("CREATE TABLE accounts (id INT PRIMARY KEY, balance INT, cdate DATE)"); - res = stmt.executeUpdate(); - if (res != 0) { - throw new Exception("unexpected: CREATE TABLE reports " + res + " rows changed, expecting 0"); - } - - stmt = conn.prepareStatement("INSERT INTO accounts (id, balance, cdate) VALUES ( ?, ?, ? )"); - stmt.setObject(1, 1); - stmt.setObject(2, 1000); - stmt.setObject(3, new java.sql.Date(System.currentTimeMillis())); - - stmt.executeUpdate(); - } -} -EOF -# See: https://basildoncoder.com/blog/postgresql-jdbc-client-certificates.html -openssl pkcs8 -topk8 -inform PEM -outform DER -in /certs/node.key -out key.pk8 -nocrypt - -export PATH=$PATH:/usr/lib/jvm/java-1.8-openjdk/bin -javac main.java -java -cp /postgres.jar:. main -`