Index: jdktools/modules/jdktools/make/exclude.linux.x86.drl =================================================================== --- jdktools/modules/jdktools/make/exclude.linux.x86.drl (revision 0) +++ jdktools/modules/jdktools/make/exclude.linux.x86.drl (revision 0) @@ -0,0 +1 @@ +org/apache/harmony/tests/tools/javaw/binary/JavawBinTest.java \ No newline at end of file Index: jdktools/modules/jdktools/make/exclude.linux.x86.ibm =================================================================== --- jdktools/modules/jdktools/make/exclude.linux.x86.ibm (revision 0) +++ jdktools/modules/jdktools/make/exclude.linux.x86.ibm (revision 0) @@ -0,0 +1 @@ +org/apache/harmony/tests/tools/javaw/binary/JavawBinTest.java \ No newline at end of file Index: jdktools/modules/jdktools/make/exclude.linux.x86_64.drl =================================================================== --- jdktools/modules/jdktools/make/exclude.linux.x86_64.drl (revision 0) +++ jdktools/modules/jdktools/make/exclude.linux.x86_64.drl (revision 0) @@ -0,0 +1 @@ +org/apache/harmony/tests/tools/javaw/binary/JavawBinTest.java \ No newline at end of file Index: jdktools/modules/jdktools/make/exclude.linux.x86_64.ibm =================================================================== --- jdktools/modules/jdktools/make/exclude.linux.x86_64.ibm (revision 0) +++ jdktools/modules/jdktools/make/exclude.linux.x86_64.ibm (revision 0) @@ -0,0 +1 @@ +org/apache/harmony/tests/tools/javaw/binary/JavawBinTest.java \ No newline at end of file Property changes on: jdktools\modules\jdktools\src\test\java ___________________________________________________________________ Added: svn:ignore + windows Property changes on: jdktools\modules\jdktools\src\test\java\org\apache\harmony\tests\tools ___________________________________________________________________ Added: svn:ignore + javaw Index: jdktools/modules/jdktools/src/test/java/org/apache/harmony/tests/tools/javac/binary/JavacBinTest.java =================================================================== --- jdktools/modules/jdktools/src/test/java/org/apache/harmony/tests/tools/javac/binary/JavacBinTest.java (revision 0) +++ jdktools/modules/jdktools/src/test/java/org/apache/harmony/tests/tools/javac/binary/JavacBinTest.java (revision 0) @@ -0,0 +1,281 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.tests.tools.javac.binary; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +public class JavacBinTest extends TestCase { + + private static final String RESOURCES = "resources/"; + + /** + * Method that takes in a non-existent file and checks the output for the + * appropriate Error message + * + */ + public void test_nonExists() throws IOException, InterruptedException { + + final String testStr = "no_this_test.java"; + + final Object[] output = runExe(new String[] { "javac", testStr }, null); + final Process proc = (Process) output[0]; + final String stdErr = (String) output[1]; + final String stdOut = getProcessOutput(proc, false); + + if (proc.exitValue() == 0) { + System.err.println("Error: " + stdErr); + System.err.println("Output: " + stdOut); + fail(" The javac process should have terminated abnormally due to a bad parameter"); + } + + assertTrue("The output should contain \"" + testStr + "\" Error - \"" + + stdErr + "\"", stdErr.contains(testStr)); + + assertTrue( + "The output should contain \"is missing\" Error - \"" + + stdErr + "\"", stdErr.contains("is missing")); + } + + /** + * Method that takes a valid (A program without any errors) file and tests + * for the proper return code + */ + public void test_exists() throws IOException, InterruptedException { + final String testStr = RESOURCES + "Simple.java"; + + final Object[] output = runExe(new String[] { "javac", testStr }, null); + final Process proc = (Process) output[0]; + final String stdErr = (String) output[1]; + final String stdOut = getProcessOutput(proc, false); + + if (proc.exitValue() != 0) { + System.err.println("Error: " + stdErr); + System.err.println("Output: " + stdOut); + fail(" The javac process terminated abnormally with Exit status " + + proc.exitValue()); + } + + final String classFile = RESOURCES + "Simple.class"; + final File clsFile = new File(classFile); + + assertTrue("The program " + testStr + + " should cleanly compile. Error - \"" + stdErr + "\"", + stdErr.trim().equals("")); + + assertTrue("The program output should generate " + classFile, clsFile + .exists()); + } + + /** + * Method that takes a valid (A program without any errors) file but with + * unresolved dependencies and tests for the proper return code + */ + public void test_existsWithUnresolvedDep() throws IOException, + InterruptedException { + + final String testStr = RESOURCES + "Sample.java"; + + final Object[] output = runExe(new String[] { "javac", testStr }, null); + final Process proc = (Process) output[0]; + final String stdErr = (String) output[1]; + final String stdOut = getProcessOutput(proc, false); + + if (proc.exitValue() == 0) { + System.err.println("Error: " + stdErr); + System.err.println("Output: " + stdOut); + fail(" The javac process should not terminate normally due to unresolved dependencies "); + } + + assertTrue( + "The program " + + testStr + + " shouldn't compile due to unresolved dependencies. Error - \"" + + stdErr + "\"", stdErr.contains("error")); + } + + /** + * Method that takes a valid (A program without any errors) file with + * Resolved dependencies and tests for the proper return code + */ + public void test_existsWithResolvedDep() throws IOException, + InterruptedException { + final String testStr = RESOURCES + "Sample.java"; + + final String option1 = "-classpath"; + + final String jarFile = RESOURCES + "Dependency.jar"; + + final Object[] output = runExe(new String[] { "javac", testStr, + option1, jarFile }, null); + final Process proc = (Process) output[0]; + final String stdErr = (String) output[1]; + final String stdOut = getProcessOutput(proc, false); + + if (proc.exitValue() != 0) { + System.err.println("Error: " + stdErr); + System.err.println("Output: " + stdOut); + fail(" The javac process terminated abnormally with Exit status " + + proc.exitValue()); + } + + final String classFile = RESOURCES + "Sample.class"; + final File clsFile = new File(classFile); + + assertTrue("The program " + testStr + " should compile as dependency " + + jarFile + " is resolved. Error - " + stdErr, stdErr.trim() + .equals("") + && clsFile.exists()); + } + + /** + * Method to extract information from a Process's Output + * + * @param proc + * Reference to the Process + * @param displayOutput + * A flag which can be set to true if we want to see outputs for + * debug - Used for dev purposes + * @return The Output content of the Process, returned as a String + * @throws IOException + * IOException thrown during a stream read + * @throws InterruptedException + * InterruptedException during a Thread interrupt + */ + private static String getProcessOutput(Process proc, boolean displayOutput) + throws IOException, InterruptedException { + StringBuilder output = new StringBuilder(); + InputStream in = proc.getInputStream(); + int result; + + synchronized (output) { + byte[] bytes = new byte[1024]; + while ((result = in.read(bytes)) != -1) { + output.append(new String(bytes, 0, result)); + + if (displayOutput) { + System.out.write(bytes, 0, result); + } + } + } + + in.close(); + proc.waitFor(); + proc.destroy(); + + return output.toString(); + } + + /** + * Method to execute a process + * + * @param args + * String array of arguments to run the executable + * @param envp + * Environment variables required to run the process + * @return An array holding the process reference and the Error output + * @throws IOException + * IOException thrown during a stream read + * @throws InterruptedException + * InterruptedException during a Thread interrupt + */ + private static Object[] runExe(String[] args, String[] envp) + throws IOException, InterruptedException { + + final Process proc = Runtime.getRuntime().exec(args, envp); + final StringBuilder errBuf = new StringBuilder(); + final byte[] bytes = new byte[1024]; + final Lock lock = new Lock(); + + Thread monitorStream = new Thread(new Runnable() { + public void run() { + synchronized (errBuf) { + int result; + final InputStream err = proc.getErrorStream(); + + synchronized (proc) { + proc.notifyAll(); + } + + try { + while ((result = err.read(bytes)) != -1) { + // System.err.write(bytes, 0, result); + errBuf.append(new String(bytes)); + } + err.close(); + } catch (IOException io) { + io.printStackTrace(); + } + + lock.setLockStat(true); + errBuf.notifyAll(); + } + + } + }); + + monitorStream.start(); + int count = 0; + synchronized (proc) { + boolean done = false; + while (!done) { + try { + proc.wait(); + done = true; + } catch (InterruptedException ie) { + if (++count == 2) { + throw ie; + } + } + } + if (count > 0) { + Thread.currentThread().interrupt(); + } + } + + // Have to make sure that the complete error String is read + synchronized (errBuf) { + while (!lock.getLockStat()) { + errBuf.wait(); + } + } + + return new Object[] { proc, errBuf.toString() }; + + } + +} + +/** + * Class that is used to track the status of the wait/notify signalling + * mechanism + */ +class Lock { + private boolean signalled = false; + + public void setLockStat(boolean stat) { + signalled = stat; + } + + public boolean getLockStat() { + return signalled; + } +} Index: jdktools/modules/jdktools/src/test/java/windows/org/apache/harmony/tests/tools/javaw/binary/JavawBinTest.java =================================================================== --- jdktools/modules/jdktools/src/test/java/windows/org/apache/harmony/tests/tools/javaw/binary/JavawBinTest.java (revision 0) +++ jdktools/modules/jdktools/src/test/java/windows/org/apache/harmony/tests/tools/javaw/binary/JavawBinTest.java (revision 0) @@ -0,0 +1,347 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.tests.tools.javaw.binary; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import junit.framework.TestCase; + +public class JavawBinTest extends TestCase { + + private static final String RESOURCES = "resources/"; + + /** + * Method that attempts a execution of a class file using javaw + * + * @throws IOException + * IOException thrown during a stream read + * @throws InterruptedException + * InterruptedException during a Thread interrupt + */ + public void testExecution() throws IOException, InterruptedException { + // Compile a file + final String testStr = RESOURCES + "Simple.java"; + + final Object[] compileOutput = runExe( + new String[] { "javac", testStr }, null); + + final Process proc = (Process) compileOutput[0]; + final String stdErr = (String) compileOutput[1]; + final String stdOut = getProcessOutput(proc, false); + + if (proc.exitValue() != 0) { + System.err.println("Error: " + stdErr); + System.err.println("Output: " + stdOut); + fail(" The javac process terminated abnormally with Exit status " + + proc.exitValue()); + } + + final String classFile = RESOURCES + "Simple.class"; + final File clsFile = new File(classFile); + + assertTrue("The program " + testStr + + " should cleanly compile. Error \"" + stdErr + "\"", stdErr + .trim().equals("")); + + assertTrue(" Class file " + classFile + " does not exist ", clsFile + .exists()); + + final Object[] execOutput = runExe(new String[] { "javaw", + "resources.Simple" }, null); + + final Process process = (Process) execOutput[0]; + final String errExecOutput = (String) execOutput[1]; + final String stdExecOut = getProcessOutput(process, false); + + if (proc.exitValue() != 0) { + System.err.println("Error: " + errExecOutput); + System.err.println("Output: " + stdExecOut); + fail(" The javaw process terminated abnormally with Exit status " + + proc.exitValue()); + } + + assertTrue("Class file " + classFile + + " executed with errors. Error - \"" + errExecOutput + "\"", + errExecOutput.trim().equals("")); + + assertTrue("Program output doesn't contain \"Hello World\"", stdExecOut + .contains("Hello World")); + + } + + /** + * Method to execute a Jar file + * + * @throws IOException + * IOException thrown during a stream read + * @throws InterruptedException + * InterruptedException during a Thread interrupt + */ + public void testJarExecution() throws IOException, InterruptedException { + final String jarFile = RESOURCES + "Simple.jar"; + + final Object[] jarOutput = runExe(new String[] { "javaw", "-jar", + jarFile }, null); + + final Process proc = (Process) jarOutput[0]; + final String stdErr = (String) jarOutput[1]; + final String stdOut = getProcessOutput(proc, false); + + if (proc.exitValue() != 0) { + System.err.println("Error: " + stdErr); + System.err.println("Output: " + stdOut); + fail(" The javaw process terminated abnormally with Exit status " + + proc.exitValue()); + } + + assertTrue("Jar file " + jarFile + + " was executed with errors. Error - \"" + stdErr + "\"", + stdErr.trim().equals("")); + + assertTrue("Program output doesn't contain \"Hello World\"", stdOut + .contains("Hello World")); + } + + /** + * Method to execute a jar which depends on another class and the class is + * not resolved in the classpath + * + * @throws IOException + * IOException thrown during a stream read + * @throws InterruptedException + * InterruptedException during a Thread interrupt + */ + public void testJarExecWithUnresolvedCP() throws IOException, + InterruptedException { + final String jarFile = RESOURCES + "Sample_unresolved.jar"; + + final Object[] jarOutput = runExe(new String[] { "javaw", "-jar", + jarFile }, null); + + final Process proc = (Process) jarOutput[0]; + final String stdErr = (String) jarOutput[1]; + final String stdOut = getProcessOutput(proc, true); + + if (proc.exitValue() == 0) { + System.err.println("Error: " + stdErr); + System.err.println("Output: " + stdOut); + fail(" The javaw process should not terminate normally due to unresolved dependencies"); + } + assertTrue("Jar file " + jarFile + " wasn't executed. Error - \"" + + stdErr + "\"", stdErr.contains("ClassNotFoundException")); + } + + /** + * Method to execute a jar which depends on another class and the class is + * resolved in the classpath + * + * @throws IOException + * @throws InterruptedException + */ + public void testJarExecWithResolvedCP() throws IOException, + InterruptedException { + final String jarFile = RESOURCES + "Sample_resolved.jar"; + + final Object[] jarOutput = runExe(new String[] { "javaw", "-jar", + jarFile }, null); + + final Process proc = (Process) jarOutput[0]; + final String stdErr = (String) jarOutput[1]; + final String stdOut = getProcessOutput(proc, false); + + if (proc.exitValue() != 0) { + System.err.println("Error: " + stdErr); + System.err.println("Output: " + stdOut); + fail(" The javaw process terminated abnormally with Exit status " + + proc.exitValue()); + } + + assertTrue("Jar file " + jarFile + " wasn't executed. Error - \"" + + stdErr + "\"", stdErr.trim().equals("")); + + assertTrue("Failure output doesn't contain \"Dependency\" StdOut - " + + stdOut, stdOut.contains("Dependency")); + } + + /** + * Method that attempts to launch the java executable with a wrong option + * + * @throws IOException + * IOException thrown during a stream read + * @throws InterruptedException + * InterruptedException during a Thread interrupt + */ + public void testLaunch() throws IOException, InterruptedException { + final Object[] execOutput = runExe(new String[] { "javaw", "-dummy" }, + null); + final Process proc = (Process) execOutput[0]; + final String stdErr = (String) execOutput[1]; + final String stdOut = getProcessOutput(proc, false); + + if (proc.exitValue() == 0) { + System.err.println("Error: " + stdErr); + System.err.println("Output: " + stdOut); + fail("VM should not get launched when a wrong option is given"); + } + + assertTrue("Failure message should contain \"-dummy\" Error \"" + + stdErr + "\"" + " Output \"" + stdOut + "\"", stdErr + .contains("-dummy")); + } + + /** + * Method to extract information from a Process's Output + * + * @param proc + * Reference to the Process + * + * @param displayOutput + * A flag which can be set to true if we want to see outputs for + * debug + * @return The stream content returned as a String + * @throws IOException + * IOException thrown during a stream read + * @throws InterruptedException + * InterruptedException during a Thread interrupt + */ + private static String getProcessOutput(Process proc, boolean displayOutput) + throws IOException, InterruptedException { + + StringBuilder output = new StringBuilder(); + InputStream in = proc.getInputStream(); + int result; + + synchronized (output) { + byte[] bytes = new byte[1024]; + while ((result = in.read(bytes)) != -1) { + output.append(new String(bytes, 0, result)); + + if (displayOutput) { + System.out.write(bytes, 0, result); + } + } + } + + in.close(); + proc.waitFor(); + proc.destroy(); + + return output.toString(); + } + + /** + * Method to execute a process + * + * @param args + * String array of arguments to run the executable + * @param envp + * Environment variables required to run the process + * @return An array holding the process reference and the Error output + * @throws IOException + * IOException thrown during a stream read + * @throws InterruptedException + * InterruptedException during a Thread interrupt + */ + private static Object[] runExe(String[] args, String[] envp) + throws IOException, InterruptedException { + + final Process proc = Runtime.getRuntime().exec(args, envp); + final StringBuilder errBuf = new StringBuilder(); + final byte[] bytes = new byte[1024]; + final Lock lock = new Lock(); + + Thread monitorStream = new Thread(new Runnable() { + public void run() { + synchronized (errBuf) { + int result; + final InputStream err = proc.getErrorStream(); + + synchronized (proc) { + proc.notifyAll(); + } + + try { + while ((result = err.read(bytes)) != -1) { + // System.err.write(bytes, 0, result); + errBuf.append(new String(bytes)); + } + err.close(); + } catch (IOException io) { + io.printStackTrace(); + } + + lock.setLockStat(true); + errBuf.notifyAll(); + } + + } + }); + + monitorStream.start(); + int count = 0; + synchronized (proc) { + boolean done = false; + while (!done) { + try { + proc.wait(); + done = true; + } catch (InterruptedException ie) { + if (++count == 2) { + throw ie; + } + } + } + if (count > 0) { + Thread.currentThread().interrupt(); + } + } + + // Have to make sure that the complete error String is read + synchronized (errBuf) { + while (!lock.getLockStat()) { + try { + errBuf.wait(5000); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + } + + return new Object[] { proc, errBuf.toString() }; + + } + +} + +/** + * Class that is used to track the status of the wait/notify signalling + * mechanism + */ + +class Lock { + private boolean signalled = false; + + public void setLockStat(boolean stat) { + signalled = stat; + } + + public boolean getLockStat() { + return signalled; + } +} Index: jdktools/modules/jdktools/src/test/resources/Dependency.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: jdktools/modules/jdktools/src/test/resources/Sample.java =================================================================== --- jdktools/modules/jdktools/src/test/resources/Sample.java (revision 988396) +++ jdktools/modules/jdktools/src/test/resources/Sample.java (working copy) @@ -20,12 +20,13 @@ public class Sample { - /** + /**Command line arguments * @param args */ public static void main(String[] args) { - // TODO Auto-generated method stub + Dependency d = new Dependency(10,20); + System.out.println(d.toString()); } } Index: jdktools/modules/jdktools/src/test/resources/Sample_resolved.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jdktools\modules\jdktools\src\test\resources\Sample_resolved.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: jdktools/modules/jdktools/src/test/resources/Sample_unresolved.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jdktools\modules\jdktools\src\test\resources\Sample_unresolved.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: jdktools/modules/jdktools/src/test/resources/Simple.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jdktools\modules\jdktools\src\test\resources\Simple.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream