diff --git a/drjava/build.xml b/drjava/build.xml
index 15c8ff541..c0ef01e8c 100644
--- a/drjava/build.xml
+++ b/drjava/build.xml
@@ -61,13 +61,17 @@
-
+
+
+
+
-
-
+
+
-
+
@@ -345,7 +349,19 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -425,8 +441,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -454,7 +512,7 @@
-
+
@@ -463,6 +521,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drjava/src/edu/rice/cs/drjava/CommandLineTest.java b/drjava/src/edu/rice/cs/drjava/CommandLineTest.java
index 189befb74..6182d11df 100644
--- a/drjava/src/edu/rice/cs/drjava/CommandLineTest.java
+++ b/drjava/src/edu/rice/cs/drjava/CommandLineTest.java
@@ -435,4 +435,4 @@ private void checkFile(File relativeFile, String funnyName)
// Close this doc to clean up after ourselves for the next check.
_mf.getModel().closeFile(doc);
}
-}
+}
\ No newline at end of file
diff --git a/drjava/src/edu/rice/cs/drjava/DrJavaTestCase.java b/drjava/src/edu/rice/cs/drjava/DrJavaTestCase.java
index 72d4deb95..34a9d326a 100644
--- a/drjava/src/edu/rice/cs/drjava/DrJavaTestCase.java
+++ b/drjava/src/edu/rice/cs/drjava/DrJavaTestCase.java
@@ -114,4 +114,4 @@ public void run() {
});
Utilities.clearEventQueue(); // ensure that all listener actions triggered by this document update have completed
}
-}
+}
\ No newline at end of file
diff --git a/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java b/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java
index bcb8ae1f3..0a9f13ad2 100644
--- a/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java
+++ b/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java
@@ -431,10 +431,16 @@ public static Vector vector(KeyStroke... ks) {
public static final VectorOption KEY_COMPILE_PROJECT =
new VectorOption("key.compile.project", new KeyStrokeOption("",null), to.vector());
+ /** The key binding for testing a project in parallel. */
+ public static final VectorOption KEY_JUNIT_PROJECT_PARALLEL =
+ new VectorOption("key.junit.project", new KeyStrokeOption("",null), to.vector());
+
+
/** The key binding for testing a project. */
public static final VectorOption KEY_JUNIT_PROJECT =
new VectorOption("key.junit.project", new KeyStrokeOption("",null), to.vector());
+
/** The key binding for running a project. */
public static final VectorOption KEY_RUN_PROJECT =
new VectorOption("key.run.project", new KeyStrokeOption("",null), to.vector());
@@ -764,12 +770,20 @@ public static Vector vector(KeyStroke... ks) {
new VectorOption("key.test",
new KeyStrokeOption("",null),
to.vector(KeyStroke.getKeyStroke(KeyEvent.VK_T, MASK|SHIFT_MASK)));
+ /** The key binding for testing the current document in parallel. */
+ public static final VectorOption KEY_TEST_PARALLEL =
+ new VectorOption("key.reset.interactions", new KeyStrokeOption("",null), to.vector());
+
/** The key binding for testing all open JUnit test cases. */
public static final VectorOption KEY_TEST_ALL =
new VectorOption("key.test.all",
new KeyStrokeOption("",null),
to.vector(KeyStroke.getKeyStroke(KeyEvent.VK_T, MASK)));
+ /** The key binding for testing all open JUnit test cases in parallel. */
+ public static final VectorOption KEY_TEST_ALL_PARALLEL =
+ new VectorOption("key.reset.interactions", new KeyStrokeOption("",null), to.vector());
+
/** The key binding for generating javadoc for all documents */
public static final VectorOption KEY_JAVADOC_ALL =
@@ -807,6 +821,8 @@ public static Vector vector(KeyStroke... ks) {
public static final VectorOption KEY_RESET_INTERACTIONS =
new VectorOption("key.reset.interactions", new KeyStrokeOption("",null), to.vector());
+
+
/** The key binding for viewing the interactions classpath. */
public static final VectorOption KEY_VIEW_INTERACTIONS_CLASSPATH =
new VectorOption("key.view.interactions.classpath", new KeyStrokeOption("",null), to.vector());
diff --git a/drjava/src/edu/rice/cs/drjava/model/DJError.java b/drjava/src/edu/rice/cs/drjava/model/DJError.java
index 06f5964c6..b78c4cabb 100644
--- a/drjava/src/edu/rice/cs/drjava/model/DJError.java
+++ b/drjava/src/edu/rice/cs/drjava/model/DJError.java
@@ -40,6 +40,7 @@
import java.io.Serializable;
import edu.rice.cs.util.FileOps;
+import edu.rice.cs.util.Log;
import edu.rice.cs.util.UnexpectedException;
@@ -48,6 +49,10 @@
* @version $Id$
*/
public class DJError implements Comparable, Serializable {
+
+ /** Debugging log. */
+ public static Log _log = new Log("DJError.txt", false);
+
private volatile File _file;
/** zero-based line number. */
@@ -78,6 +83,9 @@ public DJError(File file, int lineNumber, int startColumn, String message, boole
_startColumn = startColumn;
_message = message;
_isWarning = isWarning;
+ //TODO
+ _log.log("_lineNumber= "+_lineNumber);
+ _log.log("_file= "+_file);
if (lineNumber < 0) _noLocation = true;
}
@@ -127,7 +135,11 @@ public String fileName() {
/** Sets the line number.
* @param ln line number
*/
- public void setLineNumber(int ln) { _lineNumber = ln; }
+ public void setLineNumber(int ln) {
+ //TODO
+ _log.log("in setLineNumber _lineNumber= "+_lineNumber);
+ _lineNumber = ln;
+ }
/** Gets the column where the error begins.
* @return the starting column
diff --git a/drjava/src/edu/rice/cs/drjava/model/GlobalModelJUnitParallelTest.java b/drjava/src/edu/rice/cs/drjava/model/GlobalModelJUnitParallelTest.java
new file mode 100644
index 000000000..6a134f8d5
--- /dev/null
+++ b/drjava/src/edu/rice/cs/drjava/model/GlobalModelJUnitParallelTest.java
@@ -0,0 +1,186 @@
+/*BEGIN_COPYRIGHT_BLOCK
+ *
+ * Copyright (c) 2001-2017, JavaPLT group at Rice University (drjava@rice.edu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+ * following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+ * disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other materials provided with the distribution.
+ * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software is Open Source Initiative approved Open Source Software. Open Source Initative Approved is a trademark
+ * of the Open Source Initiative.
+ *
+ * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/ or
+ * http://sourceforge.net/projects/drjava/
+ *
+ * END_COPYRIGHT_BLOCK*/
+
+package edu.rice.cs.drjava.model;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import edu.rice.cs.drjava.model.compiler.CompilerListener;
+import edu.rice.cs.drjava.model.junit.*;
+import edu.rice.cs.util.Log;
+import edu.rice.cs.util.UnexpectedException;
+import edu.rice.cs.util.swing.Utilities;
+
+/** This is the parallel version of GlobalModelJUnitTest, we add _model.getJUnitModel().setRunTestParallel(true);
+ * before each call to Junit to make sure that test case can be tested in parallel.
+ * testJUnit4MultiTest_NOJOIN's assertNonTestCaseCount() and listener.assertJUnitStartCount(1) are comment out because multi test are run
+ * in multiple thread and can't run wait in Global Junit model
+ * testRealError_NOJOIN is discarded because JunitCore doesn't separate error and failure
+ * @version $Id$
+ */
+public final class GlobalModelJUnitParallelTest extends GlobalModelJunitTestCase {
+
+ private static Log _log = new Log("GlobalModelJUnitParallelTest.txt", true);
+
+
+
+ /** Tests that a JUnit file with no errors is reported to have no errors.
+ * @throws Exception if something goes wrong
+ */
+ public void testNoJUnitErrors_NOJOIN() throws Exception {
+ testNoJUnitErrors_NOJOIN(true);
+ }
+
+ /** Tests that a JUnit file with an error is reported to have an error.
+ * @throws Exception if something goes wrong
+ */
+ public void testOneJUnitError_NOJOIN() throws Exception {
+ testOneJUnitError_NOJOIN(true);
+ }
+
+ /** Tests that a JUnit file with an error is reported to have an error.
+ * @throws Exception if something goes wrong
+ */
+ public void testElspethOneJUnitError_NOJOIN() throws Exception {
+ testElspethOneJUnitError_NOJOIN(true);
+ }
+
+
+ /** Tests that the ui is notified to put up an error dialog if JUnit is run on a non-TestCase.
+ * @throws Exception if something goes wrong
+ */
+ public void testNonTestCaseError_NOJOIN() throws Exception {
+ testNonTestCaseError_NOJOIN(true);
+ }
+
+ /** Tests that the UI is notified to put up an error dialog if JUnit is run on a non-public TestCase.
+ * @throws Exception if something goes wrong
+ */
+ public void testResultOfNonPublicTestCase_NOJOIN() throws Exception {
+ testResultOfNonPublicTestCase_NOJOIN(true);
+ }
+
+
+
+ /** Tests a document that has no corresponding class file.
+ * @throws Exception if something goes wrong
+ */
+ public void testNoClassFile() throws Exception {
+ testNoClassFile(true);
+ }
+
+ // Commented out because MultiThreadedTestCase objects to the RemoteException thrown by auxiliary unit testing thread
+ // after resetInteractions kills the slave JVM.
+ /** Tests that an infinite loop in a test case can be aborted by clicking the Reset button.
+ * @throws Exception if something goes wrong
+ */
+ public void testInfiniteLoop_NOJOIN() throws Exception {
+ testInfiniteLoop_NOJOIN(true);
+ }
+
+ /** Tests that when a JUnit file with no errors, after being saved and compiled,
+ * has it's contents replaced by a test that should fail, will pass all tests.
+ * @throws Exception if something goes wrong
+ */
+ public void testUnsavedAndUnCompiledChanges() throws Exception {
+ testUnsavedAndUnCompiledChanges(true);
+ }
+
+ /** Verifies that we get a nonTestCase event and that opening a single test file enables testing.
+ * @throws Exception if something goes wrong
+ */
+ public void safeJUnitAllWithNoValidTests() throws Exception {
+ safeJUnitAllWithNoValidTests(true);
+ }
+
+ /** Tests that junit all works with one or two test cases that should pass.
+ * @throws Exception if something goes wrong
+ */
+ public void safeJUnitAllWithNoErrors() throws Exception {
+ safeJUnitAllWithNoErrors(true);
+ }
+
+ /** Tests that junit all works with test cases that do not pass.
+ * @throws Exception if something goes wrong
+ */
+ public void safeJUnitAllWithErrors() throws Exception {
+
+ safeJUnitAllWithErrors(true);
+ }
+
+ /** Tests that junit all works with one or two test cases that should pass.
+ * @throws Exception if something goes wrong
+ */
+ public void safeJUnitStaticInnerClass() throws Exception {
+ safeJUnitStaticInnerClass(true);
+ }
+
+
+
+ /** Tests that when a JUnit file with no errors is compiled and then modified to contain
+ * an error does not pass unit testing (by running correct class files).
+ * @throws Exception if something goes wrong
+ */
+ public void testCorrectFilesAfterIncorrectChanges_NOJOIN() throws Exception {
+ testCorrectFilesAfterIncorrectChanges_NOJOIN(true);
+ }
+
+
+ /** Tests if a JUnit4 style unit test works.
+ * @throws Exception if something goes wrong
+ */
+ public void testJUnit4StyleTestWorks_NOJOIN() throws Exception {
+ testJUnit4StyleTestWorks_NOJOIN(true);
+ }
+
+ /** Tests to see if a JUnit4 style test with multiple test cases passes.
+ * @throws Exception if something goes wrong
+ */
+ public void testJUnit4MultiTest_NOJOIN() throws Exception {
+ testJUnit4MultiTest_NOJOIN(true);
+ }
+
+
+ /** Tests to see if a JUnit4 style test with no test cases will not run.
+ * @throws Exception if something goes wrong
+ */
+ public void testJUnit4NoTest_NOJOIN() throws Exception {
+ testJUnit4NoTest_NOJOIN(true);
+ }
+
+ /** Tests to see if a JUnit4 style test with a test method and multiple nonTest methods will run.
+ * @throws Exception if something goes wrong
+ */
+ public void testJUnit4TwoMethod1Test_NOJOIN() throws Exception {
+ testJUnit4TwoMethod1Test_NOJOIN(true);
+ }
+}
diff --git a/drjava/src/edu/rice/cs/drjava/model/GlobalModelJUnitTest.java b/drjava/src/edu/rice/cs/drjava/model/GlobalModelJUnitTest.java
index 4dc11b328..27df61310 100644
--- a/drjava/src/edu/rice/cs/drjava/model/GlobalModelJUnitTest.java
+++ b/drjava/src/edu/rice/cs/drjava/model/GlobalModelJUnitTest.java
@@ -34,6 +34,8 @@
import java.util.Arrays;
import java.util.List;
+import edu.rice.cs.drjava.model.GlobalModelTestCase.FileSelector;
+import edu.rice.cs.drjava.model.GlobalModelTestCase.JUnitTestListener;
import edu.rice.cs.drjava.model.compiler.CompilerListener;
import edu.rice.cs.drjava.model.junit.*;
import edu.rice.cs.util.Log;
@@ -43,9 +45,9 @@
/** A test of Junit testing support in the GlobalModel.
* @version $Id$
*/
-public final class GlobalModelJUnitTest extends GlobalModelTestCase {
+public final class GlobalModelJUnitTest extends GlobalModelJunitTestCase {
- private static Log _log = new Log("GlobalModel.txt", false);
+ private static Log _log = new Log("GlobalModelJUnitTest.txt", false);
/** Whether or not to print debugging output. */
static final boolean printMessages = true;
@@ -179,89 +181,26 @@ public final class GlobalModelJUnitTest extends GlobalModelTestCase {
" public void testAB() { assertTrue(\"this is true\", true); } " +
" }";
-
/** Tests that a JUnit file with no errors is reported to have no errors.
- * @throws Exception if something goes wrong
- */
- public void testNoJUnitErrors_NOJOIN() throws Exception {
- _log.log("----testNoJUnitErrors-----");
-// Utilities.show("Running testNoJUnitErrors");
-
- final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_PASS_TEXT);
- final File file = new File(_tempDir, "MonkeyTestPass.java");
- saveFile(doc, new FileSelector(file));
- JUnitTestListener listener = new JUnitTestListener();
- _model.addListener(listener);
-
- listener.compile(doc); // synchronously compiles doc
- listener.checkCompileOccurred();
-
- listener.runJUnit(doc);
- // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
-
- listener.assertJUnitStartCount(1);
-
- _log.log("errors: " + _model.getJUnitModel().getJUnitErrorModel());
-
- listener.assertNonTestCaseCount(0);
- assertEquals("test case should have no errors reported", 0,
- _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
-
- _model.removeListener(listener);
- _log.log("testNoJUnitErrors completed");
- }
-
- /** Tests that a JUnit file with an error is reported to have an error.
* @throws Exception if something goes wrong
*/
- public void testOneJUnitError_NOJOIN() throws Exception {
- _log.log("----testOneJUnitError-----");
-// Utilities.show("Running testOneJUnitError");
-
- final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_FAIL_TEXT);
- final File file = new File(_tempDir, "MonkeyTestFail.java");
- saveFile(doc, new FileSelector(file));
- JUnitTestListener listener = new JUnitTestListener();
- _model.addListener(listener);
-
- listener.compile(doc);
- listener.checkCompileOccurred();
-
- listener.runJUnit(_model.getJUnitModel());
- // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
-
- assertEquals("test case has one error reported", 1, _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
- _model.removeListener(listener);
-
- _log.log("testOneJUnitError completed");
- }
-
- /** Tests that a JUnit file with an error is reported to have an error.
- * @throws Exception if something goes wrong
- */
- public void testElspethOneJUnitError_NOJOIN() throws Exception {
- _log.log("----testElspethOneJUnitError-----");
-// Utilities.show("Running testElspethOneJunitError");
-
- OpenDefinitionsDocument doc = setupDocument(ELSPETH_ERROR_TEXT);
- final File file = new File(_tempDir, "Elspeth.java");
- saveFile(doc, new FileSelector(file));
- JUnitTestListener listener = new JUnitTestListener();
- _model.addListener(listener);
-
- listener.compile(doc);
- listener.checkCompileOccurred();
-
- listener.runJUnit(doc);
-
- JUnitErrorModel junitErrorModel = _model.getJUnitModel().getJUnitErrorModel();
- assertEquals("test case has one error reported", 1, junitErrorModel.getNumErrors());
- assertTrue("first error should be an error not a warning", !junitErrorModel.getError(0).isWarning());
- _model.removeListener(listener);
-
- _log.log("testElspethOneJUnitError completed");
- }
-
+ public void testNoJUnitErrors_NOJOIN() throws Exception {
+ testNoJUnitErrors_NOJOIN(true);
+ }
+
+ /** Tests that a JUnit file with an error is reported to have an error.
+ * @throws Exception if something goes wrong
+ */
+ public void testOneJUnitError_NOJOIN() throws Exception {
+ testOneJUnitError_NOJOIN(true);
+ }
+
+ /** Tests that a JUnit file with an error is reported to have an error.
+ * @throws Exception if something goes wrong
+ */
+ public void testElspethOneJUnitError_NOJOIN() throws Exception {
+ testElspethOneJUnitError_NOJOIN(true);
+ }
/** Tests that a test class which throws a *real* Error (not an Exception) is handled correctly.
* @throws Exception if something goes wrong
*/
@@ -277,7 +216,7 @@ public void testRealError_NOJOIN() throws Exception {
listener.compile(doc);
listener.checkCompileOccurred();
-
+ _model.getJUnitModel().setRunTestParallel(false);
listener.runJUnit(doc);
// runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
@@ -292,649 +231,168 @@ public void testRealError_NOJOIN() throws Exception {
* @throws Exception if something goes wrong
*/
public void testNonTestCaseError_NOJOIN() throws Exception {
- _log.log("+++Starting testNonTestCaseError");
-// Utilities.show("Running testNonTestCaseError");
-
- final OpenDefinitionsDocument doc = setupDocument(NON_TESTCASE_TEXT);
- final File file = new File(_tempDir, "NonTestCase.java");
- saveFile(doc, new FileSelector(file));
-
- JUnitTestListener listener = new JUnitNonTestListener();
-
- _model.addListener(listener);
-
- listener.compile(doc);
- listener.checkCompileOccurred();
-
- listener.runJUnit(doc);
- // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
-
- _log.log("after test");
-
- // Check events fired
- listener.assertJUnitStartCount(0); // JUnit is never started
- listener.assertJUnitEndCount(0); // JUnit never started and hence never ended
- listener.assertNonTestCaseCount(1);
- listener.assertJUnitSuiteStartedCount(0);
- listener.assertJUnitTestStartedCount(0);
- listener.assertJUnitTestEndedCount(0);
- _model.removeListener(listener);
-
- _log.log("testNonTestCaseError completed");
+ testNonTestCaseError_NOJOIN(true);
}
/** Tests that the UI is notified to put up an error dialog if JUnit is run on a non-public TestCase.
* @throws Exception if something goes wrong
*/
public void testResultOfNonPublicTestCase_NOJOIN() throws Exception {
- _log.log("----testResultOfNonPublicTestCase-----");
-// Utilities.show("Running testResultOfNonPublicTestCase");
-
- final OpenDefinitionsDocument doc = setupDocument(NONPUBLIC_TEXT);
- final File file = new File(_tempDir, "NonPublic.java");
- saveFile(doc, new FileSelector(file));
-
- JUnitTestListener listener = new JUnitTestListener();
-
- _model.addListener(listener);
-
- listener.compile(doc);
- listener.checkCompileOccurred();
-
- listener.runJUnit(doc);
- // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
-
- _log.log("After test");
-
- // Check events fired
- listener.assertJUnitStartCount(1);
- listener.assertJUnitEndCount(1);
-
- assertEquals("test case has one error reported", 1, _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
- _model.removeListener(listener);
-
- _log.log("testResultOfNonPublicTestCase completed");
- }
-
- /* This test has become inconsistent with DrJava behavior. If a document's file no longer exists and no class file
- * exists, DrJava will detect that there is no valid class file for the document and ask the user to compile the
- * file
- */
-// public void testDoNotRunJUnitIfFileHasBeenMoved() throws Exception {
-// if (printMessages) System.err.println("----testDoNotRunJUnitIfFileHasBeenMoved-----");
-//// Utilities.show("Running testDoNotRunJUnitIfFileHasBeenMoved");
-//
-// final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_PASS_TEXT);
-// final File file = new File(_tempDir, "MonkeyTestPass.java");
-// doc.saveFile(new FileSelector(file));
-//
-// JUnitTestListener listener = new JUnitTestListener();
-//
-// _model.addListener(listener);
-// file.delete();
-//
-// listener.runJUnit(doc);
-//
-// listener.assertJUnitStartCount(0);
-// listener.assertJUnitTestStartedCount(0);
-//
-// _model.removeListener(listener);
-// _log.log("testDoNotRunJUnitIfFileHasBeenMoved completed");
-// }
-
- /** Tests a document that has no corresponding class file.
- * @throws Exception if something goes wrong
- */
- public void testNoClassFile() throws Exception {
- _log.log("----testNoClassFile-----");
-// Utilities.show("Running testNoClassFile");
-
- final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_PASS_TEXT);
- final File file = new File(_tempDir, "MonkeyTestPass.java");
- saveFile(doc, new FileSelector(file));
-
- JUnitTestListener listener = new JUnitCompileBeforeTestListener();
-
- _model.addListener(listener);
-
-// Utilities.show("calling _runJunit in testNoClassFile");
-
- listener.runJUnit(doc);
-// Utilities.showDebug("Junit run completed");
-
- _log.log("after test");
- listener.assertCompileBeforeJUnitCount(1);
- listener.assertNonTestCaseCount(0);
- listener.assertJUnitStartCount(1);
- listener.assertJUnitEndCount(1);
- listener.assertJUnitSuiteStartedCount(1);
- listener.assertJUnitTestStartedCount(1);
- listener.assertJUnitTestEndedCount(1);
- _model.removeListener(listener);
- _log.log("testNoClassFile completed");
- }
-
- // Commented out because MultiThreadedTestCase objects to the RemoteException thrown by auxiliary unit testing thread
- // after resetInteractions kills the slave JVM.
- /** Tests that an infinite loop in a test case can be aborted by clicking the Reset button.
- * @throws Exception if something goes wrong
- */
- public void testInfiniteLoop_NOJOIN() throws Exception {
- _log.log("----testInfiniteLoop-----");
-// Utilities.show("Running testInfiniteLoop");
-
- final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_INFINITE_TEXT);
- final File file = new File(_tempDir, "MonkeyTestInfinite.java");
- saveFile(doc, new FileSelector(file));
-
- JUnitTestListener listener = new JUnitTestListener(false) {
- public void junitSuiteStarted(int numTests) {
- assertEquals("should run 1 test", 1, numTests);
- synchronized(this) { junitSuiteStartedCount++; }
- // kill the infinite test once testSuiteProcessing starts
- _model.resetInteractions(new File(System.getProperty("user.dir")));
- }
- };
-
- _model.addListener(listener);
- listener.compile(doc);
-
- _log.log("Compilation of infinite loop completed");
-
- if (_model.getCompilerModel().getNumErrors() > 0) {
- fail("compile failed: " + getCompilerErrorString());
- }
- listener.checkCompileOccurred();
-
- _log.log("CheckCompile completed");
-// _model.removeListener(listener);
-//
-// _model.addListener(listener2);
-
- listener.logJUnitStart();
- try {
- _log.log("Starting JUnit");
- doc.startJUnit();
- listener.waitJUnitDone();
- // this waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
- // auxiliary thread silently swallows the exception and terminates.
- }
- catch (Exception e) { fail("Aborting unit testing runs recovery code in testing thread; no exception is thrown"); }
-
- listener.waitResetDone(); // reset should occur when test suite is started
-
- _log.log("ResetDone");
-
- _log.log("after test");
- listener.assertJUnitStartCount(1);
- _model.removeListener(listener);
- listener.assertJUnitEndCount(1); // Testing was aborted after junitStarted(); junitEnded called in recovery code
- _log.log("Reached Test End");
- _log.log("testInfiniteLoop completed");
- }
-
- /** Tests that when a JUnit file with no errors, after being saved and compiled,
- * has it's contents replaced by a test that should fail, will pass all tests.
- * @throws Exception if something goes wrong
- */
- public void testUnsavedAndUnCompiledChanges() throws Exception {
- _log.log("-----testUnsavedAndUnCompiledChanges-----");
-
- OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_PASS_TEXT);
- final File file = new File(_tempDir, "MonkeyTestPass.java");
- saveFile(doc, new FileSelector(file));
-
- List docs = _model.getSortedOpenDefinitionsDocuments();
-
- final OpenDefinitionsDocument untitled = docs.get(0);
-
- _log.log("Untitled file is named: " + untitled.getName());
-
- Utilities.invokeAndWait(new Runnable() {
- public void run() {
- untitled.quitFile();
- _model.closeFileWithoutPrompt(untitled);
- }
- });
-
- // set up test listener for compile command; automatically checks that compilation is performed
- JUnitTestListener listener = new JUnitCompileBeforeTestListener();
- _model.addListener(listener);
-
- testStartCompile(doc);
-
- _log.log("Ordinary compile completed");
- listener.waitCompileDone();
-
- listener.resetCompileCounts();
-
- changeDocumentText(MONKEYTEST_PASS_ALT_TEXT, doc);
- _log.log("document changed; modifiedSinceSave = " + doc.isModifiedSinceSave());
-
- listener.runJUnit(doc);
- _log.log("JUnit completed");
-
- /* Unsaved document forces both saveBeforeCompile and compileBeforeTest */
-
- listener.assertSaveBeforeCompileCount(1);
- listener.assertCompileBeforeJUnitCount(1);
- listener.assertNonTestCaseCount(0);
- listener.assertJUnitStartCount(1);
- listener.assertJUnitEndCount(1);
- listener.assertJUnitSuiteStartedCount(1);
- listener.assertJUnitTestStartedCount(1);
- listener.assertJUnitTestEndedCount(1);
-
- _log.log("after test");
- _model.removeListener(listener);
-
- assertEquals("test case should have no errors reported after modifying", 0,
- _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
-
- saveFile(doc, new FileSelector(file));
-
- listener = new JUnitTestListener();
- _model.addListener(listener);
-
-
- assertEquals("test case should have no errors reported after saving", 0,
- _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
- _model.removeListener(listener);
-
- _log.log("testUnsavedAndUnCompiledChanges completed");
- }
-
- /** Verifies that we get a nonTestCase event and that opening a single test file enables testing.
- * @throws Exception if something goes wrong
- */
- public void safeJUnitAllWithNoValidTests() throws Exception {
-
- _log.log("-----testJUnitAllWithNoValidTests-----");
-
- JUnitNonTestListener listener = new JUnitNonTestListener(true);
- _model.addListener(listener);
-
- listener.runJUnit(_model.getJUnitModel());
-
- listener.assertNonTestCaseCount(1);
- listener.assertJUnitSuiteStartedCount(0);
- listener.assertJUnitTestStartedCount(0);
- listener.assertJUnitTestEndedCount(0);
- _model.removeListener(listener);
-
- JUnitCompileBeforeTestListener listener2 = new JUnitCompileBeforeTestListener();
- _model.addListener(listener2);
- OpenDefinitionsDocument doc = setupDocument(NON_TESTCASE_TEXT);
- File file = new File(_tempDir, "NonTestCase.java");
- _log.log("-----> file = " + file + " -- canWrite() = " + file.canWrite() + " -- exists() = " + file.exists());
- saveFile(doc, new FileSelector(file));
-
- listener2.compile(doc);
- listener2.checkCompileOccurred();
-
- listener2.resetCompileCounts();
-
- // Opending Test
- File file2 = new File(_tempDir, "MonkeyTestPass.java");
- OpenDefinitionsDocument doc2 = setupDocument(MONKEYTEST_PASS_TEXT);
- saveFile(doc2, new FileSelector(file2));
- listener2.runJUnit(_model.getJUnitModel());
-
- listener2.assertNonTestCaseCount(0);
- listener2.assertJUnitSuiteStartedCount(1);
- listener2.assertJUnitTestStartedCount(1);
- listener2.assertJUnitTestEndedCount(1);
- _model.removeListener(listener2);
-
- _log.log("testJUnitAllWithNoValidTests completed");
- }
-
- /** Tests that junit all works with one or two test cases that should pass.
- * @throws Exception if something goes wrong
- */
- public void safeJUnitAllWithNoErrors() throws Exception {
-// _log.log("Starting testJUnitAllWithNoErrors");
-
-// final OpenDefinitionsDocument doc = setupDocument(NON_TESTCASE_TEXT);
-// final File file = new File(_tempDir, "NonTestCase.java");
-// saveFile(doc, new FileSelector(file));
-//
-// JUnitTestListener listener = new JUnitNonTestListener(true);
-//
-// _model.addListener(listener);
-//
-// listener.compile(doc);
-// listener.checkCompileOccurred();
-//
-// _log.log("Compiled first doc");
-//
- OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_PASS_TEXT);
- File file = new File(_tempDir, "MonkeyTestPass.java");
- saveFile(doc, new FileSelector(file));
- JUnitTestListener listener = new JUnitNonTestListener(true);
- _model.addListener(listener);
- listener.compile(doc);
- listener.checkCompileOccurred();
-
- listener.runJUnit(_model.getJUnitModel());
-
- listener.assertNonTestCaseCount(0);
- listener.assertJUnitSuiteStartedCount(1);
- listener.assertJUnitTestStartedCount(1);
- listener.assertJUnitTestEndedCount(1);
- _model.removeListener(listener);
-
- doc = setupDocument(HAS_MULTIPLE_TESTS_PASS_TEXT);
- file = new File(_tempDir, "HasMultipleTestsPass.java");
- saveFile(doc, new FileSelector(file));
-
- listener = new JUnitNonTestListener(true);
- _model.addListener(listener);
-
- listener.compile(doc);
-
- listener.runJUnit(_model.getJUnitModel());
- // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
-
- listener.assertNonTestCaseCount(0);
- listener.assertJUnitSuiteStartedCount(1);
- listener.assertJUnitTestStartedCount(3);
- listener.assertJUnitTestEndedCount(3);
- _model.removeListener(listener);
-
- _log.log("testJUnitAllWithNoErrors completed");
- }
-
- /** Tests that junit all works with test cases that do not pass.
- * @throws Exception if something goes wrong
- */
- public void safeJUnitAllWithErrors() throws Exception {
-
- _log.log("-----testJUnitAllWithErrors-----");
-
- OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_ERROR_TEXT);
- OpenDefinitionsDocument doc2 = setupDocument(MONKEYTEST_FAIL_TEXT);
- File file = new File(_tempDir, "MonkeyTestError.java");
- File file2 = new File(_tempDir, "MonkeyTestFail.java");
- saveFile(doc, new FileSelector(file));
- saveFile(doc2, new FileSelector(file2));
- JUnitNonTestListener listener = new JUnitNonTestListener(true);
- _model.addListener(listener);
- listener.compile(doc);
- listener.checkCompileOccurred();
- listener.resetCompileCounts();
- listener.compile(doc2);
- listener.checkCompileOccurred();
-
- listener.runJUnit(_model.getJUnitModel());
-
- listener.assertNonTestCaseCount(0);
- listener.assertJUnitSuiteStartedCount(1);
- listener.assertJUnitTestStartedCount(2);
- listener.assertJUnitTestEndedCount(2);
- _model.removeListener(listener);
-
- JUnitErrorModel junitErrorModel = _model.getJUnitModel().getJUnitErrorModel();
- assertEquals("test case has one error reported", 2, junitErrorModel.getNumErrors());
-
- assertTrue("first error should be an error", junitErrorModel.getError(0).isWarning());
- assertFalse("second error should be a failure", junitErrorModel.getError(1).isWarning());
-
- _log.log("testJUnitAllWithErrors completed");
- }
-
- /** Tests that junit all works with one or two test cases that should pass.
- * @throws Exception if something goes wrong
- */
- public void safeJUnitStaticInnerClass() throws Exception {
- _log.log("-----testJUnitAllWithStaticInnerClass-----");
-
- OpenDefinitionsDocument doc = setupDocument(NON_TESTCASE_TEXT);
- OpenDefinitionsDocument doc2 = setupDocument(STATIC_INNER_TEST_TEXT);
- File file = new File(_tempDir, "NonTestCase.java");
- File file2 = new File(_tempDir, "StaticInnerTestCase.java");
- saveFile(doc, new FileSelector(file));
- saveFile(doc2, new FileSelector(file2));
-
- JUnitNonTestListener listener = new JUnitNonTestListener(true);
- _model.addListener(listener);
- listener.compile(doc);
- listener.checkCompileOccurred();
- listener.resetCompileCounts();
- listener.compile(doc2);
- listener.checkCompileOccurred();
-
- listener.runJUnit(_model.getJUnitModel());
-
- listener.assertNonTestCaseCount(0);
- listener.assertJUnitSuiteStartedCount(1);
- listener.assertJUnitTestStartedCount(2);
- listener.assertJUnitTestEndedCount(2);
- _model.removeListener(listener);
- _log.log("----testJUnitAllWithNoErrors-----");
-
- _log.log("testJUnitStaticInnerClass completed");
- }
-
- /** Tests that testing an uncompiled but correct group of files will first compile and then run test. */
- public class JUnitCompileBeforeTestListener extends JUnitTestListener {
-
- /* Method copied by _mainListener in MainFrame. */
- public void compileBeforeJUnit(final CompilerListener testAfterCompile, List outOfSync) {
- _log.log("compileBeforeJUnit called in listener " + this);
- synchronized(this) { compileBeforeJUnitCount++; }
- // Compile all open source files
- _model.getCompilerModel().addListener(testAfterCompile); // listener removes itself
- _log.log("Calling _compileAll()");
- try { _model.getCompilerModel().compileAll(); /* instead of invoking MainFrame._compileAll() */ }
- catch(IOException e) { fail("Compile step generated IOException"); }
-
- _log.log("Compilation finished");
- }
-
- public void saveBeforeCompile() {
- _log.log("saveBeforeCompile called in " + this);
- synchronized(this) { saveBeforeCompileCount++; }
- /** Assumes that DrJava is in flat file mode! */
- saveAllFiles(_model, new FileSaveSelector() {
- public File getFile() { throw new UnexpectedException ("Test should not ask for save file name"); }
- public boolean warnFileOpen(File f) { return false; }
- public boolean verifyOverwrite(File f) { return true; }
- public boolean shouldSaveAfterFileMoved(OpenDefinitionsDocument doc, File oldFile) { return false; }
- public boolean shouldUpdateDocumentState() { return true; }
- });
- }
- public void fileSaved(OpenDefinitionsDocument doc) { }
+ testResultOfNonPublicTestCase_NOJOIN(true);
}
- /** Tests that when a JUnit file with no errors is compiled and then modified to contain
- * an error does not pass unit testing (by running correct class files).
- * @throws Exception if something goes wrong
- */
- public void testCorrectFilesAfterIncorrectChanges_NOJOIN() throws Exception {
- _log.log("----testCorrectFilesAfterIncorrectChanges-----");
-
-// OpenDefinitionsDocument doc0 = setupDocument(NON_TESTCASE_TEXT);
-// JUnitNonTestListener listener0 = new JUnitNonTestListener(true);
-// File file = new File(_tempDir, "NonTestCase.java");
-// saveFile(doc0, new FileSelector(file));
-// _model.addListener(listener0);
-//
-// listener0.compile(doc0);
-// listener0.checkCompileOccurred();
-// _model.removeListener(listener0);
-//// What is the preceding code segment supposed to test; it has already been done!
-
- final OpenDefinitionsDocument doc1 = setupDocument(MULTI_CLASSES_IN_FILE_TEXT);
- final File file = new File(_tempDir, "DJTest.java");
- saveFile(doc1, new FileSelector(file));
- _log.log("In testCorrectFilesAfterIncorrectChanges, DJTest.java = \n" + doc1.getText());
-
- final JUnitNonTestListener listener1 = new JUnitNonTestListener(true);
- _model.addListener(listener1);
- listener1.compile(doc1);
- listener1.checkCompileOccurred();
- assertCompileErrorsPresent(false);
- listener1.runJUnit(_model.getJUnitModel());
- listener1.assertJUnitSuiteStartedCount(1);
- listener1.assertJUnitTestStartedCount(1);
- listener1.assertJUnitTestEndedCount(1);
- listener1.assertNonTestCaseCount(0);
- _model.removeListener(listener1);
- doc1.remove(87,4);
-
- JUnitTestListener listener2 = new JUnitCompileBeforeTestListener();
- _model.addListener(listener2);
- listener2.runJUnit(doc1);
- // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
-
- _log.log("after test");
- listener2.assertCompileBeforeJUnitCount(1);
- listener2.assertNonTestCaseCount(1);
- listener2.assertJUnitStartCount(0);
- listener2.assertJUnitEndCount(0);
- listener2.assertJUnitSuiteStartedCount(0);
- listener2.assertJUnitTestStartedCount(0);
- listener2.assertJUnitTestEndedCount(0);
- _model.removeListener(listener2);
- _log.log("testCorrectFilesAfterIncorrectChanges completed");
- }
-
- /** Tests if a JUnit4 style unit test works.
- * @throws Exception if something goes wrong
- */
- public void testJUnit4StyleTestWorks_NOJOIN() throws Exception {
-
- _log.log("----testJUnit4StyleTestWorks-----");
-
- File file0 = new File("testFiles/GlobalModelJUnitTestFiles/JUnit4StyleTest.java");
- final OpenDefinitionsDocument doc = setupDocument((_model._createOpenDefinitionsDocument(file0)).getText());
-
- final File file = new File(_tempDir, "JUnit4StyleTest.java");
- saveFile(doc, new FileSelector(file));
- JUnitTestListener listener = new JUnitTestListener();
- _model.addListener(listener);
-
- listener.compile(doc); // synchronously compiles doc
- listener.checkCompileOccurred();
-
- listener.runJUnit(doc);
- _log.log("errors: " + Arrays.toString(_model.getJUnitModel().getJUnitErrorModel().getErrors()));
-
- // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
-
- listener.assertJUnitStartCount(1);
-
+ /**
+ * Tests a document that has no corresponding class file.
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void testNoClassFile() throws Exception {
+ testNoClassFile(true);
+ }
- listener.assertNonTestCaseCount(0);
- assertEquals("test case should have no errors reported", 0,
- _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
-
- _model.removeListener(listener);
- _log.log("----testJUnit4StyleTestWorks completed");
- }
-
- /** Tests to see if a JUnit4 style test with multiple test cases passes.
- * @throws Exception if something goes wrong
- */
- public void testJUnit4MultiTest_NOJOIN() throws Exception {
-
- _log.log("----testJUnit4MultiTest-----");
-
- File file0 = new File("testFiles/GlobalModelJUnitTestFiles/JUnit4MultiTest.java");
- final OpenDefinitionsDocument doc = setupDocument((_model._createOpenDefinitionsDocument(file0)).getText());
-
- final File file = new File(_tempDir, "JUnit4MultiTest.java");
- saveFile(doc, new FileSelector(file));
- JUnitTestListener listener = new JUnitTestListener();
- _model.addListener(listener);
-
- listener.compile(doc); // synchronously compiles doc
- listener.checkCompileOccurred();
-
- listener.runJUnit(doc);
- // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
-
- _log.log("errors: " + Arrays.toString(_model.getJUnitModel().getJUnitErrorModel().getErrors()));
-
- listener.assertJUnitStartCount(1);
-
- listener.assertNonTestCaseCount(0);
- assertEquals("test case should have no errors reported", 0,
- _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
-
- _model.removeListener(listener);
- _log.log("testJUnit4SMultiTest completed");
- }
-
-
- /** Tests to see if a JUnit4 style test with no test cases will not run.
- * @throws Exception if something goes wrong
- */
- public void testJUnit4NoTest_NOJOIN() throws Exception {
- _log.log("----testJUnit4NoTest-----");
-
- File file0 = new File("testFiles/GlobalModelJUnitTestFiles/JUnit4NoTest.java");
- final OpenDefinitionsDocument doc = setupDocument((_model._createOpenDefinitionsDocument(file0)).getText());
- final File file = new File(_tempDir, "JUnit4NoTest.java");
- saveFile(doc, new FileSelector(file));
-
- JUnitTestListener listener = new JUnitNonTestListener();
-
- _model.addListener(listener);
-
- listener.compile(doc);
- listener.checkCompileOccurred();
-
- listener.runJUnit(doc);
- // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
-
- _log.log("after test");
-
- // Check events fired
- listener.assertJUnitStartCount(0); // JUnit is never started
- listener.assertJUnitEndCount(0); // JUnit never started and hence never ended
- listener.assertNonTestCaseCount(1);
- listener.assertJUnitSuiteStartedCount(0);
- listener.assertJUnitTestStartedCount(0);
- listener.assertJUnitTestEndedCount(0);
- _model.removeListener(listener);
-
- _log.log("testJUnit4NoTest completed");
- }
-
- /** Tests to see if a JUnit4 style test with a test method and multiple nonTest methods will run.
- * @throws Exception if something goes wrong
- */
- public void testJUnit4TwoMethod1Test_NOJOIN() throws Exception {
-
- _log.log("----testJUnit4TwoMethod1Test-----");
-
- File file0 = new File("testFiles/GlobalModelJUnitTestFiles/JUnit4TwoMethod1Test.java");
- final OpenDefinitionsDocument doc = setupDocument((_model._createOpenDefinitionsDocument(file0)).getText());
-
- final File file = new File(_tempDir, "JUnit4TwoMethod1Test.java");
- saveFile(doc, new FileSelector(file));
- JUnitTestListener listener = new JUnitTestListener();
- _model.addListener(listener);
-
- listener.compile(doc); // synchronously compiles doc
- listener.checkCompileOccurred();
-
- listener.runJUnit(doc);
- // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
-
- _log.log("errors: " + Arrays.toString(_model.getJUnitModel().getJUnitErrorModel().getErrors()));
-
- listener.assertJUnitStartCount(1);
- listener.assertNonTestCaseCount(0);
- assertEquals("test case should have no errors reported", 0,
- _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
-
- _model.removeListener(listener);
- _log.log("testJUnit4TwoMethod1Test completed");
- }
-}
+ // Commented out because MultiThreadedTestCase objects to the RemoteException
+ // thrown by auxiliary unit testing thread
+ // after resetInteractions kills the slave JVM.
+ /**
+ * Tests that an infinite loop in a test case can be aborted by clicking the
+ * Reset button.
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void testInfiniteLoop_NOJOIN() throws Exception {
+ testInfiniteLoop_NOJOIN(true);
+ }
+
+ /**
+ * Tests that when a JUnit file with no errors, after being saved and compiled,
+ * has it's contents replaced by a test that should fail, will pass all tests.
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void testUnsavedAndUnCompiledChanges() throws Exception {
+ testUnsavedAndUnCompiledChanges(true);
+ }
+ /**
+ * Verifies that we get a nonTestCase event and that opening a single test file
+ * enables testing.
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void safeJUnitAllWithNoValidTests() throws Exception {
+ safeJUnitAllWithNoValidTests(true);
+ }
+
+ /**
+ * Tests that junit all works with one or two test cases that should pass.
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void safeJUnitAllWithNoErrors() throws Exception {
+ safeJUnitAllWithNoErrors(true);
+ }
+
+ /**
+ * Tests that junit all works with test cases that do not pass.
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void safeJUnitAllWithErrors() throws Exception {
+
+ safeJUnitAllWithErrors(true);
+ }
+
+ /**
+ * Tests that junit all works with one or two test cases that should pass.
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void safeJUnitStaticInnerClass() throws Exception {
+ safeJUnitStaticInnerClass(true);
+ }
+
+ /**
+ * Tests that when a JUnit file with no errors is compiled and then modified to
+ * contain an error does not pass unit testing (by running correct class files).
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void testCorrectFilesAfterIncorrectChanges_NOJOIN() throws Exception {
+ testCorrectFilesAfterIncorrectChanges_NOJOIN(true);
+ }
+
+ /**
+ * Tests if a JUnit4 style unit test works.
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void testJUnit4StyleTestWorks_NOJOIN() throws Exception {
+ testJUnit4StyleTestWorks_NOJOIN(true);
+ }
+
+
+ /** Tests to see if a JUnit4 style test with multiple test cases passes.
+ * @throws Exception if something goes wrong
+ */
+ public void testJUnit4MultiTest_NOJOIN() throws Exception {
+
+ _log.log("----testJUnit4MultiTest-----");
+
+ File file0 = new File("testFiles/GlobalModelJUnitTestFiles/JUnit4MultiTest.java");
+ final OpenDefinitionsDocument doc = setupDocument((_model._createOpenDefinitionsDocument(file0)).getText());
+
+ final File file = new File(_tempDir, "JUnit4MultiTest.java");
+ saveFile(doc, new FileSelector(file));
+ JUnitTestListener listener = new JUnitTestListener();
+ _model.addListener(listener);
+
+ listener.compile(doc); // synchronously compiles doc
+ listener.checkCompileOccurred();
+
+ listener.runJUnit(doc);
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ _log.log("errors: " + Arrays.toString(_model.getJUnitModel().getJUnitErrorModel().getErrors()));
+
+ listener.assertJUnitStartCount(1);
+
+ listener.assertNonTestCaseCount(0);
+ assertEquals("test case should have no errors reported", 0,
+ _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
+
+ _model.removeListener(listener);
+ _log.log("testJUnit4SMultiTest completed");
+ }
+
+ /**
+ * Tests to see if a JUnit4 style test with no test cases will not run.
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void testJUnit4NoTest_NOJOIN() throws Exception {
+ testJUnit4NoTest_NOJOIN(true);
+ }
+
+ /**
+ * Tests to see if a JUnit4 style test with a test method and multiple nonTest
+ * methods will run.
+ *
+ * @throws Exception
+ * if something goes wrong
+ */
+ public void testJUnit4TwoMethod1Test_NOJOIN() throws Exception {
+ testJUnit4TwoMethod1Test_NOJOIN(true);
+ }
+}
diff --git a/drjava/src/edu/rice/cs/drjava/model/GlobalModelJunitTestCase.java b/drjava/src/edu/rice/cs/drjava/model/GlobalModelJunitTestCase.java
new file mode 100644
index 000000000..9b78eafdb
--- /dev/null
+++ b/drjava/src/edu/rice/cs/drjava/model/GlobalModelJunitTestCase.java
@@ -0,0 +1,918 @@
+
+/*BEGIN_COPYRIGHT_BLOCK
+*
+* Copyright (c) 2001-2017, JavaPLT group at Rice University (drjava@rice.edu). All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+* following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+* disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+* following disclaimer in the documentation and/or other materials provided with the distribution.
+* * Neither the names of DrJava, the JavaPLT group, Rice University, nor the names of its contributors may be used
+* to endorse or promote products derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* This software is Open Source Initiative approved Open Source Software. Open Source Initative Approved is a trademark
+* of the Open Source Initiative.
+*
+* This file is part of DrJava. Download the current version of this project from http://www.drjava.org/ or
+* http://sourceforge.net/projects/drjava/
+*
+* END_COPYRIGHT_BLOCK*/
+
+package edu.rice.cs.drjava.model;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import edu.rice.cs.drjava.model.compiler.CompilerListener;
+import edu.rice.cs.drjava.model.junit.*;
+import edu.rice.cs.util.Log;
+import edu.rice.cs.util.UnexpectedException;
+import edu.rice.cs.util.swing.Utilities;
+
+/** To reuse the code, we add this class to contain the method that both GlobalModelJunitTest and GlobalModelParallelJunitTest will use
+ * @version $Id$
+ */
+public abstract class GlobalModelJunitTestCase extends GlobalModelTestCase {
+
+ private static Log _log = new Log("GlobalModelJunitTestCase.txt", true);
+
+ /** Whether or not to print debugging output. */
+ static final boolean printMessages = true;
+
+ private static final String ELSPETH_ERROR_TEXT =
+ "import junit.framework.TestCase;" +
+ "public class Elspeth extends TestCase {" +
+ " public void testMe() {" +
+ " String s = \"elspeth\";" +
+ " assertEquals(\"they match\", s, \"elspeth4\");" +
+ " }" +
+ " public Elspeth() {" +
+ " super();" +
+ " }" +
+ " public java.lang.String toString() {" +
+ " return \"Elspeth(\" + \")\";" +
+ " }" +
+ " public boolean equals(java.lang.Object o) {" +
+ " if ((o == null) || getClass() != o.getClass()) return false;" +
+ " return true;" +
+ " }" +
+ " public int hashCode() {" +
+ " return getClass().hashCode();" +
+ " }" +
+ "}";
+
+ private static final String MONKEYTEST_PASS_TEXT =
+ "import junit.framework.*; \n" +
+ "import java.io.*; \n" +
+ "public class MonkeyTestPass extends TestCase { \n" +
+ " public MonkeyTestPass(String name) { super(name); } \n" +
+ " public void testShouldPass() { \n" +
+ " assertEquals(\"monkey\", \"monkey\"); \n" +
+ " } \n" +
+ "}\n";
+
+ private static final String MONKEYTEST_PASS_ALT_TEXT =
+ "import junit.framework.*; \n" +
+ "import java.io.*; \n" +
+ "public class MonkeyTestPass extends TestCase { \n" +
+ " public MonkeyTestPass(String name) { super(name); } \n" +
+ " public void testShouldPass() { \n" +
+ " assertEquals(\"monkeys\", \"monkeys\"); \n" +
+ " } \n" +
+ "}\n";
+
+ private static final String MONKEYTEST_FAIL_TEXT =
+ "import junit.framework.*; " +
+ "public class MonkeyTestFail extends TestCase { " +
+ " public MonkeyTestFail(String name) { super(name); } " +
+ " public void testShouldFail() { " +
+ " assertEquals(\"monkey\", \"baboon\"); " +
+ " } " +
+ "}";
+
+ private static final String MONKEYTEST_ERROR_TEXT =
+ "import junit.framework.*; " +
+ "public class MonkeyTestError extends TestCase { " +
+ " public MonkeyTestError(String name) { super(name); } " +
+ " public void testThrowsError() { " +
+ " throw new Error(\"This is an error.\"); " +
+ " } " +
+ "}";
+
+// private static final String MONKEYTEST_COMPILEERROR_TEXT =
+// "import junit.framework.*; " +
+// "public class MonkeyTestCompileError extends TestCase { " +
+// " Object MonkeyTestFail(String name) { super(name); } " +
+// " public void testShouldFail() { " +
+// " assertEquals(\"monkey\", \"baboon\"); " +
+// " } " +
+// "}";
+
+ private static final String NONPUBLIC_TEXT =
+ "import junit.framework.*; " +
+ "class NonPublic extends TestCase { " +
+ " NonPublic(String name) { super(name); } " +
+ " void testShouldFail() { " +
+ " assertEquals(\"monkey\", \"baboon\"); " +
+ " } " +
+ "}";
+
+ private static final String NON_TESTCASE_TEXT =
+ "public class NonTestCase {}";
+
+ private static final String MONKEYTEST_INFINITE_TEXT =
+ "import junit.framework.*; " +
+ "public class MonkeyTestInfinite extends TestCase { " +
+ " public MonkeyTestInfinite(String name) { super(name); } " +
+ " public void testInfinite() { " +
+ " while(true) {}" +
+ " } " +
+ "}";
+
+ private static final String HAS_MULTIPLE_TESTS_PASS_TEXT =
+ "import junit.framework.*; " +
+ "public class HasMultipleTestsPass extends TestCase { " +
+ " public HasMultipleTestsPass(String name) { super(name); } " +
+ " public void testShouldPass() { " +
+ " assertEquals(\"monkey\", \"monkey\"); " +
+ " } " +
+ " public void testShouldAlsoPass() { " +
+ " assertTrue(true); " +
+ " } " +
+ "}";
+
+ private static final String STATIC_INNER_TEST_TEXT =
+ "import junit.framework.TestCase;" +
+ " public class StaticInnerTestCase{" +
+ " public static class Sadf extends TestCase {" +
+ " public Sadf() {" +
+ " super();" +
+ " }" +
+ " public Sadf(String name) {" +
+ " super(name);" +
+ " }" +
+ " public void testX() {" +
+ " assertTrue(\"this is true\", true);" +
+ " }" +
+ " public void testY() {" +
+ " assertFalse(\"this is false\", false);" +
+ " }" +
+ " }" +
+ "}";
+
+ private static final String MULTI_CLASSES_IN_FILE_TEXT =
+ "import junit.framework.TestCase;" +
+ " class A { } " +
+ " class B /* with syntax error */ { public void foo(int x) { } } " +
+ " public class DJTest extends TestCase { " +
+ " public void testAB() { assertTrue(\"this is true\", true); } " +
+ " }";
+
+
+ /** Tests that a JUnit file with no errors is reported to have no errors.
+ * @throws Exception if something goes wrong
+ */
+ protected void testNoJUnitErrors_NOJOIN(boolean testInParallel) throws Exception {
+ _log.log("----testNoJUnitErrors-----");
+// Utilities.show("Running testNoJUnitErrors");
+
+ final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_PASS_TEXT);
+ final File file = new File(_tempDir, "MonkeyTestPass.java");
+ saveFile(doc, new FileSelector(file));
+ JUnitTestListener listener = new JUnitTestListener();
+ _model.addListener(listener);
+
+ listener.compile(doc); // synchronously compiles doc
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel( testInParallel);
+ listener.runJUnit(doc);
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ listener.assertJUnitStartCount(1);
+
+ _log.log("errors: " + _model.getJUnitModel().getJUnitErrorModel());
+
+ listener.assertNonTestCaseCount(0);
+ assertEquals("test case should have no errors reported", 0,
+ _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
+
+ _model.removeListener(listener);
+ _log.log("testNoJUnitErrors completed");
+ }
+
+ /** Tests that a JUnit file with an error is reported to have an error.
+ * @throws Exception if something goes wrong
+ */
+ protected void testOneJUnitError_NOJOIN(boolean testInParallel) throws Exception {
+ _log.log("----testOneJUnitError-----");
+// Utilities.show("Running testOneJUnitError");
+
+ final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_FAIL_TEXT);
+ final File file = new File(_tempDir, "MonkeyTestFail.java");
+ saveFile(doc, new FileSelector(file));
+ JUnitTestListener listener = new JUnitTestListener();
+ _model.addListener(listener);
+
+ listener.compile(doc);
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel( testInParallel);
+ listener.runJUnit(_model.getJUnitModel());
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ assertEquals("test case has one error reported", 1, _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
+ _model.removeListener(listener);
+
+ _log.log("testOneJUnitError completed");
+ }
+
+ /** Tests that a JUnit file with an error is reported to have an error.
+ * @throws Exception if something goes wrong
+ */
+ protected void testElspethOneJUnitError_NOJOIN(boolean testInParallel) throws Exception {
+ _log.log("----testElspethOneJUnitError-----");
+// Utilities.show("Running testElspethOneJunitError");
+
+ OpenDefinitionsDocument doc = setupDocument(ELSPETH_ERROR_TEXT);
+ final File file = new File(_tempDir, "Elspeth.java");
+ saveFile(doc, new FileSelector(file));
+ JUnitTestListener listener = new JUnitTestListener();
+ _model.addListener(listener);
+
+ listener.compile(doc);
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel( testInParallel);
+ listener.runJUnit(doc);
+
+ JUnitErrorModel junitErrorModel = _model.getJUnitModel().getJUnitErrorModel();
+ assertEquals("test case has one error reported", 1, junitErrorModel.getNumErrors());
+ assertTrue("first error should be an error not a warning", !junitErrorModel.getError(0).isWarning());
+ _model.removeListener(listener);
+
+ _log.log("testElspethOneJUnitError completed");
+ }
+
+
+ /** Tests that the ui is notified to put up an error dialog if JUnit is run on a non-TestCase.
+ * @throws Exception if something goes wrong
+ */
+ protected void testNonTestCaseError_NOJOIN(boolean testInParallel) throws Exception {
+ _log.log("+++Starting testNonTestCaseError");
+// Utilities.show("Running testNonTestCaseError");
+
+ final OpenDefinitionsDocument doc = setupDocument(NON_TESTCASE_TEXT);
+ final File file = new File(_tempDir, "NonTestCase.java");
+ saveFile(doc, new FileSelector(file));
+
+ JUnitTestListener listener = new JUnitNonTestListener();
+
+ _model.addListener(listener);
+
+ listener.compile(doc);
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel( testInParallel);
+ listener.runJUnit(doc);
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ _log.log("after test");
+
+ // Check events fired
+ listener.assertJUnitStartCount(0); // JUnit is never started
+ listener.assertJUnitEndCount(0); // JUnit never started and hence never ended
+ listener.assertNonTestCaseCount(1);
+ listener.assertJUnitSuiteStartedCount(0);
+ listener.assertJUnitTestStartedCount(0);
+ listener.assertJUnitTestEndedCount(0);
+ _model.removeListener(listener);
+
+ _log.log("testNonTestCaseError completed");
+ }
+
+ /** Tests that the UI is notified to put up an error dialog if JUnit is run on a non-public TestCase.
+ * @throws Exception if something goes wrong
+ */
+ protected void testResultOfNonPublicTestCase_NOJOIN(boolean testInParallel) throws Exception {
+ _log.log("----testResultOfNonPublicTestCase-----");
+// Utilities.show("Running testResultOfNonPublicTestCase");
+
+ final OpenDefinitionsDocument doc = setupDocument(NONPUBLIC_TEXT);
+ final File file = new File(_tempDir, "NonPublic.java");
+ saveFile(doc, new FileSelector(file));
+
+ JUnitTestListener listener = new JUnitTestListener();
+
+ _model.addListener(listener);
+
+ listener.compile(doc);
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel( testInParallel);
+ listener.runJUnit(doc);
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ _log.log("After test");
+
+ // Check events fired
+ listener.assertJUnitStartCount(1);
+ listener.assertJUnitEndCount(1);
+
+ assertEquals("test case has one error reported", 1, _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
+ _model.removeListener(listener);
+
+ _log.log("testResultOfNonPublicTestCase completed");
+ }
+
+ /* This test has become inconsistent with DrJava behavior. If a document's file no longer exists and no class file
+ * exists, DrJava will detect that there is no valid class file for the document and ask the user to compile the
+ * file
+ */
+// public void testDoNotRunJUnitIfFileHasBeenMoved() throws Exception {
+// if (printMessages) System.err.println("----testDoNotRunJUnitIfFileHasBeenMoved-----");
+//// Utilities.show("Running testDoNotRunJUnitIfFileHasBeenMoved");
+//
+// final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_PASS_TEXT);
+// final File file = new File(_tempDir, "MonkeyTestPass.java");
+// doc.saveFile(new FileSelector(file));
+//
+// JUnitTestListener listener = new JUnitTestListener();
+//
+// _model.addListener(listener);
+// file.delete();
+//
+// listener.runJUnit(doc);
+//
+// listener.assertJUnitStartCount(0);
+// listener.assertJUnitTestStartedCount(0);
+//
+// _model.removeListener(listener);
+// _log.log("testDoNotRunJUnitIfFileHasBeenMoved completed");
+// }
+
+ /** Tests a document that has no corresponding class file.
+ * @throws Exception if something goes wrong
+ */
+ protected void testNoClassFile(boolean testInParallel) throws Exception {
+ _log.log("----testNoClassFile-----");
+// Utilities.show("Running testNoClassFile");
+
+ final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_PASS_TEXT);
+ final File file = new File(_tempDir, "MonkeyTestPass.java");
+ saveFile(doc, new FileSelector(file));
+
+ JUnitTestListener listener = new JUnitCompileBeforeTestListener();
+
+ _model.addListener(listener);
+
+// Utilities.show("calling _runJunit in testNoClassFile");
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.runJUnit(doc);
+// Utilities.showDebug("Junit run completed");
+
+ _log.log("after test");
+ listener.assertCompileBeforeJUnitCount(1);
+ listener.assertNonTestCaseCount(0);
+ listener.assertJUnitStartCount(1);
+ listener.assertJUnitEndCount(1);
+ listener.assertJUnitSuiteStartedCount(1);
+ listener.assertJUnitTestStartedCount(1);
+ listener.assertJUnitTestEndedCount(1);
+ _model.removeListener(listener);
+ _log.log("testNoClassFile completed");
+ }
+
+ // Commented out because MultiThreadedTestCase objects to the RemoteException thrown by auxiliary unit testing thread
+ // after resetInteractions kills the slave JVM.
+ /** Tests that an infinite loop in a test case can be aborted by clicking the Reset button.
+ * @throws Exception if something goes wrong
+ */
+ protected void testInfiniteLoop_NOJOIN(boolean testInParallel) throws Exception {
+ _log.log("----testInfiniteLoop-----");
+// Utilities.show("Running testInfiniteLoop");
+
+ final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_INFINITE_TEXT);
+ final File file = new File(_tempDir, "MonkeyTestInfinite.java");
+ saveFile(doc, new FileSelector(file));
+
+ JUnitTestListener listener = new JUnitTestListener(false) {
+ public void junitSuiteStarted(int numTests) {
+ assertEquals("should run 1 test", 1, numTests);
+ synchronized(this) { junitSuiteStartedCount++; }
+ // kill the infinite test once testSuiteProcessing starts
+ _model.resetInteractions(new File(System.getProperty("user.dir")));
+ }
+ };
+
+ _model.addListener(listener);
+ listener.compile(doc);
+
+ _log.log("Compilation of infinite loop completed");
+
+ if (_model.getCompilerModel().getNumErrors() > 0) {
+ fail("compile failed: " + getCompilerErrorString());
+ }
+ listener.checkCompileOccurred();
+
+ _log.log("CheckCompile completed");
+// _model.removeListener(listener);
+//
+// _model.addListener(listener2);
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.logJUnitStart();
+ try {
+ _log.log("Starting JUnit");
+ doc.startJUnit();
+ listener.waitJUnitDone();
+ // this waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+ // auxiliary thread silently swallows the exception and terminates.
+ }
+ catch (Exception e) { fail("Aborting unit testing runs recovery code in testing thread; no exception is thrown"); }
+
+ listener.waitResetDone(); // reset should occur when test suite is started
+
+ _log.log("ResetDone");
+
+ _log.log("after test");
+ listener.assertJUnitStartCount(1);
+ _model.removeListener(listener);
+ listener.assertJUnitEndCount(1); // Testing was aborted after junitStarted(); junitEnded called in recovery code
+ _log.log("Reached Test End");
+ _log.log("testInfiniteLoop completed");
+ }
+
+ /** Tests that when a JUnit file with no errors, after being saved and compiled,
+ * has it's contents replaced by a test that should fail, will pass all tests.
+ * @throws Exception if something goes wrong
+ */
+ protected void testUnsavedAndUnCompiledChanges(boolean testInParallel) throws Exception {
+ _log.log("-----testUnsavedAndUnCompiledChanges-----");
+
+ OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_PASS_TEXT);
+ final File file = new File(_tempDir, "MonkeyTestPass.java");
+ saveFile(doc, new FileSelector(file));
+
+ List docs = _model.getSortedOpenDefinitionsDocuments();
+
+ final OpenDefinitionsDocument untitled = docs.get(0);
+
+ _log.log("Untitled file is named: " + untitled.getName());
+
+ Utilities.invokeAndWait(new Runnable() {
+ public void run() {
+ untitled.quitFile();
+ _model.closeFileWithoutPrompt(untitled);
+ }
+ });
+
+ // set up test listener for compile command; automatically checks that compilation is performed
+ JUnitTestListener listener = new JUnitCompileBeforeTestListener();
+ _model.addListener(listener);
+
+ testStartCompile(doc);
+
+ _log.log("Ordinary compile completed");
+ listener.waitCompileDone();
+
+ listener.resetCompileCounts();
+
+ changeDocumentText(MONKEYTEST_PASS_ALT_TEXT, doc);
+ _log.log("document changed; modifiedSinceSave = " + doc.isModifiedSinceSave());
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.runJUnit(doc);
+ _log.log("JUnit completed");
+
+ /* Unsaved document forces both saveBeforeCompile and compileBeforeTest */
+
+ listener.assertSaveBeforeCompileCount(1);
+ listener.assertCompileBeforeJUnitCount(1);
+ listener.assertNonTestCaseCount(0);
+ listener.assertJUnitStartCount(1);
+ listener.assertJUnitEndCount(1);
+ listener.assertJUnitSuiteStartedCount(1);
+ listener.assertJUnitTestStartedCount(1);
+ listener.assertJUnitTestEndedCount(1);
+
+ _log.log("after test");
+ _model.removeListener(listener);
+
+ assertEquals("test case should have no errors reported after modifying", 0,
+ _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
+
+ saveFile(doc, new FileSelector(file));
+
+ listener = new JUnitTestListener();
+ _model.addListener(listener);
+
+
+ assertEquals("test case should have no errors reported after saving", 0,
+ _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
+ _model.removeListener(listener);
+
+ _log.log("testUnsavedAndUnCompiledChanges completed");
+ }
+
+ /** Verifies that we get a nonTestCase event and that opening a single test file enables testing.
+ * @throws Exception if something goes wrong
+ */
+ protected void safeJUnitAllWithNoValidTests(boolean testInParallel) throws Exception {
+
+ _log.log("-----testJUnitAllWithNoValidTests-----");
+
+ JUnitNonTestListener listener = new JUnitNonTestListener(true);
+ _model.addListener(listener);
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+
+ listener.runJUnit(_model.getJUnitModel());
+
+ listener.assertNonTestCaseCount(1);
+ listener.assertJUnitSuiteStartedCount(0);
+ listener.assertJUnitTestStartedCount(0);
+ listener.assertJUnitTestEndedCount(0);
+ _model.removeListener(listener);
+
+ JUnitCompileBeforeTestListener listener2 = new JUnitCompileBeforeTestListener();
+ _model.addListener(listener2);
+ OpenDefinitionsDocument doc = setupDocument(NON_TESTCASE_TEXT);
+ File file = new File(_tempDir, "NonTestCase.java");
+ _log.log("-----> file = " + file + " -- canWrite() = " + file.canWrite() + " -- exists() = " + file.exists());
+ saveFile(doc, new FileSelector(file));
+
+ listener2.compile(doc);
+ listener2.checkCompileOccurred();
+
+ listener2.resetCompileCounts();
+
+ // Opending Test
+ File file2 = new File(_tempDir, "MonkeyTestPass.java");
+ OpenDefinitionsDocument doc2 = setupDocument(MONKEYTEST_PASS_TEXT);
+ saveFile(doc2, new FileSelector(file2));
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener2.runJUnit(_model.getJUnitModel());
+
+ listener2.assertNonTestCaseCount(0);
+ listener2.assertJUnitSuiteStartedCount(1);
+ listener2.assertJUnitTestStartedCount(1);
+ listener2.assertJUnitTestEndedCount(1);
+ _model.removeListener(listener2);
+
+ _log.log("testJUnitAllWithNoValidTests completed");
+ }
+
+ /** Tests that junit all works with one or two test cases that should pass.
+ * @throws Exception if something goes wrong
+ */
+ protected void safeJUnitAllWithNoErrors(boolean testInParallel) throws Exception {
+// _log.log("Starting testJUnitAllWithNoErrors");
+
+// final OpenDefinitionsDocument doc = setupDocument(NON_TESTCASE_TEXT);
+// final File file = new File(_tempDir, "NonTestCase.java");
+// saveFile(doc, new FileSelector(file));
+//
+// JUnitTestListener listener = new JUnitNonTestListener(true);
+//
+// _model.addListener(listener);
+//
+// listener.compile(doc);
+// listener.checkCompileOccurred();
+//
+// _log.log("Compiled first doc");
+//
+ OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_PASS_TEXT);
+ File file = new File(_tempDir, "MonkeyTestPass.java");
+ saveFile(doc, new FileSelector(file));
+ JUnitTestListener listener = new JUnitNonTestListener(true);
+ _model.addListener(listener);
+ listener.compile(doc);
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.runJUnit(_model.getJUnitModel());
+
+ listener.assertNonTestCaseCount(0);
+ listener.assertJUnitSuiteStartedCount(1);
+ listener.assertJUnitTestStartedCount(1);
+ listener.assertJUnitTestEndedCount(1);
+ _model.removeListener(listener);
+
+ doc = setupDocument(HAS_MULTIPLE_TESTS_PASS_TEXT);
+ file = new File(_tempDir, "HasMultipleTestsPass.java");
+ saveFile(doc, new FileSelector(file));
+
+ listener = new JUnitNonTestListener(true);
+ _model.addListener(listener);
+
+ listener.compile(doc);
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.runJUnit(_model.getJUnitModel());
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ listener.assertNonTestCaseCount(0);
+ listener.assertJUnitSuiteStartedCount(1);
+ listener.assertJUnitTestStartedCount(3);
+ listener.assertJUnitTestEndedCount(3);
+ _model.removeListener(listener);
+
+ _log.log("testJUnitAllWithNoErrors completed");
+ }
+
+ /** Tests that junit all works with test cases that do not pass.
+ * @throws Exception if something goes wrong
+ */
+ protected void safeJUnitAllWithErrors(boolean testInParallel) throws Exception {
+
+ _log.log("-----testJUnitAllWithErrors-----");
+
+ OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_ERROR_TEXT);
+ OpenDefinitionsDocument doc2 = setupDocument(MONKEYTEST_FAIL_TEXT);
+ File file = new File(_tempDir, "MonkeyTestError.java");
+ File file2 = new File(_tempDir, "MonkeyTestFail.java");
+ saveFile(doc, new FileSelector(file));
+ saveFile(doc2, new FileSelector(file2));
+ JUnitNonTestListener listener = new JUnitNonTestListener(true);
+ _model.addListener(listener);
+ listener.compile(doc);
+ listener.checkCompileOccurred();
+ listener.resetCompileCounts();
+ listener.compile(doc2);
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.runJUnit(_model.getJUnitModel());
+
+ listener.assertNonTestCaseCount(0);
+ listener.assertJUnitSuiteStartedCount(1);
+ listener.assertJUnitTestStartedCount(2);
+ listener.assertJUnitTestEndedCount(2);
+ _model.removeListener(listener);
+
+ JUnitErrorModel junitErrorModel = _model.getJUnitModel().getJUnitErrorModel();
+ assertEquals("test case has one error reported", 2, junitErrorModel.getNumErrors());
+
+ assertTrue("first error should be an error", junitErrorModel.getError(0).isWarning());
+ assertFalse("second error should be a failure", junitErrorModel.getError(1).isWarning());
+
+ _log.log("testJUnitAllWithErrors completed");
+ }
+
+ /** Tests that junit all works with one or two test cases that should pass.
+ * @throws Exception if something goes wrong
+ */
+ protected void safeJUnitStaticInnerClass(boolean testInParallel) throws Exception {
+ _log.log("-----testJUnitAllWithStaticInnerClass-----");
+
+ OpenDefinitionsDocument doc = setupDocument(NON_TESTCASE_TEXT);
+ OpenDefinitionsDocument doc2 = setupDocument(STATIC_INNER_TEST_TEXT);
+ File file = new File(_tempDir, "NonTestCase.java");
+ File file2 = new File(_tempDir, "StaticInnerTestCase.java");
+ saveFile(doc, new FileSelector(file));
+ saveFile(doc2, new FileSelector(file2));
+
+ JUnitNonTestListener listener = new JUnitNonTestListener(true);
+ _model.addListener(listener);
+ listener.compile(doc);
+ listener.checkCompileOccurred();
+ listener.resetCompileCounts();
+ listener.compile(doc2);
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.runJUnit(_model.getJUnitModel());
+
+ listener.assertNonTestCaseCount(0);
+ listener.assertJUnitSuiteStartedCount(1);
+ listener.assertJUnitTestStartedCount(2);
+ listener.assertJUnitTestEndedCount(2);
+ _model.removeListener(listener);
+ _log.log("----testJUnitAllWithNoErrors-----");
+
+ _log.log("testJUnitStaticInnerClass completed");
+ }
+
+ /** Tests that testing an uncompiled but correct group of files will first compile and then run test. */
+ public class JUnitCompileBeforeTestListener extends JUnitTestListener {
+
+ /* Method copied by _mainListener in MainFrame. */
+ public void compileBeforeJUnit(final CompilerListener testAfterCompile, List outOfSync) {
+ _log.log("compileBeforeJUnit called in listener " + this);
+ synchronized(this) { compileBeforeJUnitCount++; }
+ // Compile all open source files
+ _model.getCompilerModel().addListener(testAfterCompile); // listener removes itself
+ _log.log("Calling _compileAll()");
+ try { _model.getCompilerModel().compileAll(); /* instead of invoking MainFrame._compileAll() */ }
+ catch(IOException e) { fail("Compile step generated IOException"); }
+
+ _log.log("Compilation finished");
+ }
+
+ public void saveBeforeCompile() {
+ _log.log("saveBeforeCompile called in " + this);
+ synchronized(this) { saveBeforeCompileCount++; }
+ /** Assumes that DrJava is in flat file mode! */
+ saveAllFiles(_model, new FileSaveSelector() {
+ public File getFile() { throw new UnexpectedException ("Test should not ask for save file name"); }
+ public boolean warnFileOpen(File f) { return false; }
+ public boolean verifyOverwrite(File f) { return true; }
+ public boolean shouldSaveAfterFileMoved(OpenDefinitionsDocument doc, File oldFile) { return false; }
+ public boolean shouldUpdateDocumentState() { return true; }
+ });
+ }
+ public void fileSaved(OpenDefinitionsDocument doc) { }
+ }
+
+ /** Tests that when a JUnit file with no errors is compiled and then modified to contain
+ * an error does not pass unit testing (by running correct class files).
+ * @throws Exception if something goes wrong
+ */
+ protected void testCorrectFilesAfterIncorrectChanges_NOJOIN(boolean testInParallel) throws Exception {
+ _log.log("----testCorrectFilesAfterIncorrectChanges-----");
+
+// OpenDefinitionsDocument doc0 = setupDocument(NON_TESTCASE_TEXT);
+// JUnitNonTestListener listener0 = new JUnitNonTestListener(true);
+// File file = new File(_tempDir, "NonTestCase.java");
+// saveFile(doc0, new FileSelector(file));
+// _model.addListener(listener0);
+//
+// listener0.compile(doc0);
+// listener0.checkCompileOccurred();
+// _model.removeListener(listener0);
+////What is the preceding code segment supposed to test; it has already been done!
+
+ final OpenDefinitionsDocument doc1 = setupDocument(MULTI_CLASSES_IN_FILE_TEXT);
+ final File file = new File(_tempDir, "DJTest.java");
+ saveFile(doc1, new FileSelector(file));
+ _log.log("In testCorrectFilesAfterIncorrectChanges, DJTest.java = \n" + doc1.getText());
+
+ final JUnitNonTestListener listener1 = new JUnitNonTestListener(true);
+ _model.addListener(listener1);
+ listener1.compile(doc1);
+ listener1.checkCompileOccurred();
+ assertCompileErrorsPresent(false);
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener1.runJUnit(_model.getJUnitModel());
+ listener1.assertJUnitSuiteStartedCount(1);
+ listener1.assertJUnitTestStartedCount(1);
+ listener1.assertJUnitTestEndedCount(1);
+ listener1.assertNonTestCaseCount(0);
+ _model.removeListener(listener1);
+ doc1.remove(87,4);
+
+ JUnitTestListener listener2 = new JUnitCompileBeforeTestListener();
+ _model.addListener(listener2);
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener2.runJUnit(doc1);
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ _log.log("after test");
+ listener2.assertCompileBeforeJUnitCount(1);
+ listener2.assertNonTestCaseCount(1);
+ listener2.assertJUnitStartCount(0);
+ listener2.assertJUnitEndCount(0);
+ listener2.assertJUnitSuiteStartedCount(0);
+ listener2.assertJUnitTestStartedCount(0);
+ listener2.assertJUnitTestEndedCount(0);
+ _model.removeListener(listener2);
+ _log.log("testCorrectFilesAfterIncorrectChanges completed");
+ }
+
+
+ /** Tests if a JUnit4 style unit test works.
+ * @throws Exception if something goes wrong
+ */
+ protected void testJUnit4StyleTestWorks_NOJOIN(boolean testInParallel) throws Exception {
+
+ _log.log("----testJUnit4StyleTestWorks-----");
+
+ File file0 = new File("testFiles/GlobalModelJUnitTestFiles/JUnit4StyleTest.java");
+ final OpenDefinitionsDocument doc = setupDocument((_model._createOpenDefinitionsDocument(file0)).getText());
+
+ final File file = new File(_tempDir, "JUnit4StyleTest.java");
+ saveFile(doc, new FileSelector(file));
+ JUnitTestListener listener = new JUnitTestListener();
+ _model.addListener(listener);
+
+ listener.compile(doc); // synchronously compiles doc
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.runJUnit(doc);
+ _log.log("errors: " + Arrays.toString(_model.getJUnitModel().getJUnitErrorModel().getErrors()));
+
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ listener.assertJUnitStartCount(1);
+
+
+ listener.assertNonTestCaseCount(0);
+ assertEquals("test case should have no errors reported", 0,
+ _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
+
+ _model.removeListener(listener);
+ _log.log("----testJUnit4StyleTestWorks completed");
+ }
+
+ /** Tests to see if a JUnit4 style test with multiple test cases passes.
+ * @throws Exception if something goes wrong
+ */
+ protected void testJUnit4MultiTest_NOJOIN(boolean testInParallel) throws Exception {
+
+ _log.log("----testJUnit4MultiTest-----");
+
+ File file0 = new File("testFiles/GlobalModelJUnitTestFiles/JUnit4MultiTest.java");
+ final OpenDefinitionsDocument doc = setupDocument((_model._createOpenDefinitionsDocument(file0)).getText());
+
+ final File file = new File(_tempDir, "JUnit4MultiTest.java");
+ saveFile(doc, new FileSelector(file));
+ JUnitTestListener listener = new JUnitTestListener();
+ _model.addListener(listener);
+
+ listener.compile(doc); // synchronously compiles doc
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.runJUnitWithoutWait(doc);
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ _log.log("errors: " + Arrays.toString(_model.getJUnitModel().getJUnitErrorModel().getErrors()));
+
+ //listener.assertJUnitStartCount(1);
+
+ //listener.assertNonTestCaseCount(0);
+ assertEquals("test case should have no errors reported", 0,
+ _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
+
+ _model.removeListener(listener);
+ _log.log("testJUnit4SMultiTest completed");
+ }
+
+
+ /** Tests to see if a JUnit4 style test with no test cases will not run.
+ * @throws Exception if something goes wrong
+ */
+ protected void testJUnit4NoTest_NOJOIN(boolean testInParallel) throws Exception {
+ _log.log("----testJUnit4NoTest-----");
+
+ File file0 = new File("testFiles/GlobalModelJUnitTestFiles/JUnit4NoTest.java");
+ final OpenDefinitionsDocument doc = setupDocument((_model._createOpenDefinitionsDocument(file0)).getText());
+ final File file = new File(_tempDir, "JUnit4NoTest.java");
+ saveFile(doc, new FileSelector(file));
+
+ JUnitTestListener listener = new JUnitNonTestListener();
+
+ _model.addListener(listener);
+
+ listener.compile(doc);
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.runJUnit(doc);
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ _log.log("after test");
+
+ // Check events fired
+ listener.assertJUnitStartCount(0); // JUnit is never started
+ listener.assertJUnitEndCount(0); // JUnit never started and hence never ended
+ listener.assertNonTestCaseCount(1);
+ listener.assertJUnitSuiteStartedCount(0);
+ listener.assertJUnitTestStartedCount(0);
+ listener.assertJUnitTestEndedCount(0);
+ _model.removeListener(listener);
+
+ _log.log("testJUnit4NoTest completed");
+ }
+
+ /** Tests to see if a JUnit4 style test with a test method and multiple nonTest methods will run.
+ * @throws Exception if something goes wrong
+ */
+ protected void testJUnit4TwoMethod1Test_NOJOIN(boolean testInParallel) throws Exception {
+
+ _log.log("----testJUnit4TwoMethod1Test-----");
+
+ File file0 = new File("testFiles/GlobalModelJUnitTestFiles/JUnit4TwoMethod1Test.java");
+ final OpenDefinitionsDocument doc = setupDocument((_model._createOpenDefinitionsDocument(file0)).getText());
+
+ final File file = new File(_tempDir, "JUnit4TwoMethod1Test.java");
+ saveFile(doc, new FileSelector(file));
+ JUnitTestListener listener = new JUnitTestListener();
+ _model.addListener(listener);
+
+ listener.compile(doc); // synchronously compiles doc
+ listener.checkCompileOccurred();
+ _model.getJUnitModel().setRunTestParallel(testInParallel);
+ listener.runJUnit(doc);
+ // runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
+
+ _log.log("errors: " + Arrays.toString(_model.getJUnitModel().getJUnitErrorModel().getErrors()));
+
+ listener.assertJUnitStartCount(1);
+ listener.assertNonTestCaseCount(0);
+ assertEquals("test case should have no errors reported", 0,
+ _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
+
+ _model.removeListener(listener);
+ _log.log("testJUnit4TwoMethod1Test completed");
+ }
+}
diff --git a/drjava/src/edu/rice/cs/drjava/model/GlobalModelTestCase.java b/drjava/src/edu/rice/cs/drjava/model/GlobalModelTestCase.java
index bb02366fc..cb1d155fa 100644
--- a/drjava/src/edu/rice/cs/drjava/model/GlobalModelTestCase.java
+++ b/drjava/src/edu/rice/cs/drjava/model/GlobalModelTestCase.java
@@ -1288,6 +1288,13 @@ public void runJUnit(JUnitModel jm) throws IOException, ClassNotFoundException,
waitJUnitDone();
}
+ public void runJUnitWithoutWait(JUnitModel jm) throws IOException, ClassNotFoundException, InterruptedException {
+ logJUnitStart();
+// _log.log("Starting JUnit");
+ jm.junitAll();
+
+ }
+
public void waitJUnitDone() throws InterruptedException {
synchronized(_junitLock) { while (! _junitDone) { _junitLock.wait(); } }
}
@@ -1352,6 +1359,13 @@ public synchronized void resetJUnitCounts() {
_log.log("junitEnded() called; notifying JUnitDone");
_notifyJUnitDone();
}
+ public void runJUnitWithoutWait(OpenDefinitionsDocument doc) throws ClassNotFoundException, IOException {
+ logJUnitStart();
+ // System.err.println("Starting JUnit on " + doc);
+ doc.startJUnit();
+ // System.err.println("JUnit Started on " + doc);
+
+ }
}
/** Listener class for failing JUnit invocation. */
diff --git a/drjava/src/edu/rice/cs/drjava/model/junit/DefaultJUnitModel.java b/drjava/src/edu/rice/cs/drjava/model/junit/DefaultJUnitModel.java
index c39dfc762..443dedbb0 100644
--- a/drjava/src/edu/rice/cs/drjava/model/junit/DefaultJUnitModel.java
+++ b/drjava/src/edu/rice/cs/drjava/model/junit/DefaultJUnitModel.java
@@ -84,11 +84,15 @@
* @version $Id$
*/
public class DefaultJUnitModel implements JUnitModel, JUnitModelCallback {
+
+ /**Set whether we should run the test in parallel, whenever use it, set it back to false*/
+ public static boolean runTestParallel=false;
private CoverageMetadata coverageMetadata = new CoverageMetadata(false, "");
/** log for use in debugging */
- private static Log _log = new Log("GlobalModel.txt", false);
+ //needtodo
+ private static Log _log = new Log("DefaultJUnitModel.txt", false);
/** Manages listeners to this model. */
private final JUnitEventNotifier _notifier = new JUnitEventNotifier();
@@ -136,6 +140,11 @@ public DefaultJUnitModel(MainJVM jvm, CompilerModel compilerModel, SingleDisplay
//-------------------------- Field Setters --------------------------------//
+ public void setRunTestParallel(boolean testParallel) {
+ _log.log("setRunTestParallel= "+testParallel);
+ runTestParallel=testParallel;
+ }
+
public void setCoverage(boolean coverage, String outdirPath) {
this.coverageMetadata = new CoverageMetadata(coverage, outdirPath);
}
@@ -344,7 +353,8 @@ private void _rawJUnitOpenDefDocs(List lod, final boole
File sourceDir =
(buildDir == FileOps.NULL_FILE) ? classFileDir :
new File(IOUtil.attemptCanonicalFile(sourceRoot), packagePath);
-
+ _log.log("classFileDir= " + classFileDir + " sourceDir= " + sourceDir + " sourceRoot= "+sourceRoot);
+ _log.log("classDirsAndRoots= " + classDirsAndRoots);
if (! classDirsAndRoots.containsKey(classFileDir)) {
classDirsAndRoots.put(classFileDir, sourceDir);
_log.log("Adding " + classFileDir + " with source root " + sourceRoot + " to list of class directories");
@@ -429,7 +439,7 @@ public void visitEnd() { }
/** The canonical pathname for the file (including the file name) */
String javaSourceFileName = getCanonicalPath(rootDir) + File.separator + sourceName.value();
-
+ _log.log("javaSourceFileName= " + javaSourceFileName);
// System.err.println("Full java source fileName = " + javaSourceFileName);
/* The index in fileName of the dot preceding the extension ".java", ".dj", ".dj0*, ".dj1", or ".dj2" */
@@ -500,7 +510,9 @@ public void run() {
try {
_notifyJUnitStarted();
// The false return value could be changed to an exception.
- boolean testsPresent = _jvm.runTestSuite();
+ _log.log("runTestParallel= "+runTestParallel);
+ boolean testsPresent = _jvm.runTestSuite(runTestParallel);
+ runTestParallel=false;
if (!testsPresent) {
throw new RemoteException("No unit test classes were passed to the slave JVM");
}
diff --git a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitErrorModelTest.java b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitErrorModelTest.java
index 781fd7e09..7c087706f 100644
--- a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitErrorModelTest.java
+++ b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitErrorModelTest.java
@@ -426,5 +426,4 @@ public void run() {
debug.logEnd();
_log.log("testErrorInSuperClass_NOJOIN complete");
}
-}
-
+}
\ No newline at end of file
diff --git a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitModel.java b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitModel.java
index dc4387266..dc7028003 100644
--- a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitModel.java
+++ b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitModel.java
@@ -43,8 +43,13 @@
public interface JUnitModel {
+
//-------------------------- Field Setters --------------------------------//
+ /** @param runTestParallel true if we run the test in parallel
+ */
+ public void setRunTestParallel(boolean testParallel);
+
/** @param c true if a coverage report is desired; false otherwise
* @param p value to set the outdir path to
*/
diff --git a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitParallelTestManager.java b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitParallelTestManager.java
new file mode 100644
index 000000000..be0036b99
--- /dev/null
+++ b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitParallelTestManager.java
@@ -0,0 +1,533 @@
+/*BEGIN_COPYRIGHT_BLOCK
+ *
+ * Copyright (c) 2001-2017, JavaPLT group at Rice University (drjava@rice.edu)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software is Open Source Initiative approved Open Source Software.
+ * Open Source Initative Approved is a trademark of the Open Source Initiative.
+ *
+ * This file is part of DrJava. Download the current version of this project
+ * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
+ *
+ * END_COPYRIGHT_BLOCK*/
+
+package edu.rice.cs.drjava.model.junit;
+
+import java.io.File;
+import java.io.InputStream;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.concurrent.TimeUnit;
+import java.util.Enumeration;
+import java.util.Arrays;
+
+import edu.rice.cs.drjava.model.coverage.CoverageMetadata;
+import edu.rice.cs.drjava.model.coverage.ReportGenerator;
+
+import edu.rice.cs.drjava.model.repl.newjvm.ClassPathManager;
+
+import edu.rice.cs.util.Log;
+import edu.rice.cs.util.UnexpectedException;
+import edu.rice.cs.util.classloader.ClassFileError;
+
+import edu.rice.cs.plt.io.IOUtil;
+import edu.rice.cs.plt.tuple.Pair;
+import edu.rice.cs.plt.iter.IterUtil;
+
+import edu.rice.cs.drjava.model.coverage.JacocoClassLoader;
+import edu.rice.cs.plt.reflect.EmptyClassLoader;
+
+import static edu.rice.cs.plt.debug.DebugUtil.error;
+
+import junit.framework.JUnit4TestAdapter;
+
+import junit.framework.AssertionFailedError;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+import junit.framework.TestFailure;
+import junit.framework.JUnit4TestCaseFacade;
+
+import org.jacoco.core.analysis.Analyzer;
+import org.jacoco.core.analysis.CoverageBuilder;
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.data.ExecutionDataStore;
+import org.jacoco.core.data.SessionInfoStore;
+
+import org.jacoco.core.instr.Instrumenter;
+import org.jacoco.core.runtime.IRuntime;
+import org.jacoco.core.runtime.LoggerRuntime;
+import org.jacoco.core.runtime.RuntimeData;
+import org.junit.experimental.ParallelComputer;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+/** Runs in the InterpreterJVM. Runs tests given a classname and formats the results into a (serializable) array of
+ * JUnitError that can be passed back to the MainJVM.
+ * @version $Id$
+ */
+public class JUnitParallelTestManager extends JUnitTestManager{
+ public static Log _log = new Log("JUnitParallelTestManager.txt", false);
+
+
+
+ /** The current testRunner; initially null. Each test suite requires a new runner. */
+ private JUnitParallelTestRunner _testRunner;
+ /** class of of test cases, used to run test case in parallel*/
+ private Vector> cls=null;
+
+
+
+ /** Standard constructor
+ * @param jmc a JUnitModelCallback
+ * @param loaderFactory factory to create class loaders
+ */
+ public JUnitParallelTestManager(JUnitModelCallback jmc, ClassPathManager loaderFactory) {
+ super(jmc,loaderFactory);
+ }
+
+ /** Find the test classes among the given classNames and accumulate them in
+ * TestSuite for junit. Returns null if a test suite is already pending.
+ * @param classNames the (fully qualified) class names that are test class candidates
+ * @param files Java File objects for the source files corresponding to classNames
+ * @param coverageMetadata metadata to be used to generate the coverage report
+ * @return list of test class names
+ */
+ @SuppressWarnings({"unchecked","rawtypes"})
+ public List findTestClasses(final List classNames, final List files,
+ final CoverageMetadata coverageMetadata) {
+
+ _log.log("findTestClasses(" + classNames + ", " + files + ", " + coverageMetadata + ") called");
+ boolean doCoverage = coverageMetadata.getFlag();
+
+ // Set up the loader
+ final ClassLoader defaultLoader = JUnitParallelTestManager.class.getClassLoader();
+ final ClassLoader loader;
+ if (! doCoverage) loader = _classPathManager.value(defaultLoader);
+ else {
+ // create a Jacoco runtime, output directory, report descriptors, and loader
+ _coverageOutdir = coverageMetadata.getOutdirPath();
+ _runtime = new LoggerRuntime();
+ _myData = new RuntimeData();
+ loader = new JacocoClassLoader(_classPathManager.getClassPath(), new Instrumenter(_runtime), defaultLoader);
+ _nonTestClassNames = new ArrayList(classNames.size());
+ try { _runtime.startup(_myData); }
+ catch (Exception e) {
+ _log.log("In code coverage startup, throwing the wrapped exception " + e);
+ throw new UnexpectedException(e);
+ }
+ }
+
+ if (_testClassNames != null && ! _testClassNames.isEmpty())
+ throw new IllegalStateException("Test suite is still pending!");
+
+ _log.log("Preparing to run test cases");
+ _testRunner = makeRunner(loader);
+
+ _testClassNames = new ArrayList();
+ _testFiles = new ArrayList();
+ _nonTestClassNames = new ArrayList(classNames.size());
+ _suite = new TestSuite();
+ cls=new Vector>();
+ // Assemble test suite (as _suite) and return list of test class names
+ for (Pair pair : IterUtil.zip(classNames, files)) {
+ String cName = pair.first();
+ try {
+ Class> possibleTest = _testRunner.loadPossibleTest(cName);
+ _log.log("Exploring possibleTest " + possibleTest);
+ if (_isJUnitTest(possibleTest)) {
+ _testClassNames.add(cName);
+ _testFiles.add(pair.second());
+ Test test = new JUnit4TestAdapter(possibleTest);
+ cls.add(possibleTest);
+ _suite.addTest(test);
+ _log.log("Adding test " + test + " to test suite");
+ } else { // cName is a program class that is not a test class
+ _nonTestClassNames.add(cName);
+ _log.log("adding " + cName + " to nonTestClassNames");
+ }
+ }
+ catch (ClassNotFoundException e) { error.log(e); }
+ catch(LinkageError e) {
+ //debug.log(e);
+ String path = IOUtil.attemptAbsoluteFile(pair.second()).getPath();
+ _jmc.classFileError(new ClassFileError(cName, path, e));
+ }
+ }
+
+// debug.logEnd("result", _testClassNames);
+ _log.log("accumulated non test class names: " + _nonTestClassNames);
+ _log.log("returning: " + _testClassNames);
+
+ return _testClassNames;
+ }
+
+ /** Runs the pending test suite set up by the preceding call to findTestClasses. Runs in a single auxiliary thread,
+ * so no need for explicit synchronization.
+ * @param runTestParallel set whether we should run the test in parallel
+ * @return false if no test suite (even an empty one) has been set up
+ */
+ public boolean runTestSuite(Boolean runTestParallel) {
+
+ _log.log("runTestSuite() called");
+
+ if (_testClassNames == null || _testClassNames.isEmpty()) {
+ _finalResult = new JUnitResultTuple(false, null);
+ return false;
+ }
+ Map> lineColors = null;
+ _finalResult = new JUnitResultTuple(true, null);
+
+// _log.log("runTestSuite() in SlaveJVM called");
+
+ /* Declare fault array for amalgamating errors and failures */
+ JUnitError[] faults = new JUnitError[0];
+ try {
+ _log.log("Calling _testRunner.runSuite(" + _suite + ")");
+
+
+ //This is the result of runSuite
+ Result result=null;
+ int faultCount=0;
+ long startTime = System.nanoTime();
+ long estimatedTime = System.nanoTime() - startTime;
+ _log.log("isParallel= "+runTestParallel);
+ if (runTestParallel == true) {
+ @SuppressWarnings("rawtypes")
+ Class[] clsArray = new Class[cls.size()];
+ cls.copyInto(clsArray);
+ _testRunner.setCountTestCases(_suite);
+ startTime = System.nanoTime();
+ result = _testRunner.runClass(clsArray);
+ estimatedTime = System.nanoTime() - startTime;
+ long Second=TimeUnit.SECONDS.convert(estimatedTime, TimeUnit.NANOSECONDS);
+ _log.log("when testing in parallel, testing time is :" + estimatedTime +" in nanoseconds");
+ _log.log("when testing in parallel, testing time is :" + Second +" in second");
+
+ faultCount = result.getFailureCount();
+ _log.log("faultCount= " + faultCount);
+ if (faultCount > 0) {
+
+ faults = new JUnitError[faultCount];
+ List failure = result.getFailures();
+ int i = 0;
+ for (Failure failureIterator : failure) {
+ // TestFailure error = failure.
+ _log.log("failureIterator.getDescription() is " + failureIterator.getDescription());
+ String testMethodName = failureIterator.getDescription().getMethodName();
+ _log.log("failureIterator.getDescription().getTestClass() is "
+ + failureIterator.getDescription().getTestClass());
+ Test test = new JUnit4TestAdapter(failureIterator.getDescription().getTestClass());
+ _log.log("test is " + test);
+ _log.log("testName is " + testMethodName);
+ TestFailure testFailure = new TestFailure(test, failureIterator.getException());
+ faults[i] = _makeJUnitError(testFailure, _testClassNames, true, _testFiles, testMethodName);
+ i++;
+ }
+
+ }
+
+ }
+ else {
+
+ startTime = System.nanoTime();
+ TestResult testResult = _testRunner.runSuite(_suite);
+ estimatedTime = System.nanoTime() - startTime;
+ long Second=TimeUnit.SECONDS.convert(estimatedTime, TimeUnit.NANOSECONDS);
+ _log.log("when testing in sequential, testing time is :" + estimatedTime +" in nanoseconds");
+ _log.log("when testing in sequential, testing time is :" + Second +" in second");
+ /* A fault is either an error or a failure. */
+ faultCount = testResult.errorCount() + testResult.failureCount();
+ if (faultCount > 0) {
+
+ /*
+ * NOTE: TestFailure, a JUnit class, is misnamed; it should have been called
+ * TestFault with TestFailure and TestError as disjoint subtypes (e.g., classes)
+ */
+ faults = new JUnitError[faultCount];
+ Enumeration failures = testResult.failures();
+ Enumeration errors = testResult.errors();
+
+ int i = 0;
+
+ // faults should be called faults! and makeJUnitError should be makeJUnitFault!
+ while (errors.hasMoreElements()) {
+ TestFailure error = errors.nextElement();
+ faults[i] = _makeJUnitError(error, _testClassNames, true, _testFiles);
+ i++;
+ }
+
+ while (failures.hasMoreElements()) {
+ TestFailure failure = failures.nextElement();
+ faults[i] = _makeJUnitError(failure, _testClassNames, false, _testFiles);
+ i++;
+ }
+ }
+ }
+
+
+ _log.log("Testing doCoverage");
+
+ if (_runtime != null) { /* doCoverage was true */
+ _log.log("Analyzing coverage data for " + _nonTestClassNames);
+
+ /* Collect session info (including which code was executed) */
+ final ExecutionDataStore _executionDataStore = new ExecutionDataStore();
+ final SessionInfoStore sessionInfos = new SessionInfoStore();
+ _myData.collect(_executionDataStore, sessionInfos, false);
+ _log.log("Collected coverage information");
+ _runtime.shutdown();
+
+ /** Together with the original class definitions we can calculate coverage information. */
+ final CoverageBuilder coverageBuilder = new CoverageBuilder();
+ final Analyzer analyzer = new Analyzer(_executionDataStore, coverageBuilder);
+ URLClassLoader urlCL = newURLLoader();
+
+ String cName = null;
+ try {
+ for (int j = 0; j < _nonTestClassNames.size(); j++) {
+ cName = _nonTestClassNames.get(j);
+ InputStream is = urlCL.getResource(cName + ".class").openStream();
+ _log.log("Constructed InputStream " + is + " for class " + cName);
+ analyzer.analyzeClass(is, cName);
+ }
+ } catch(Exception e) {
+ throw new UnexpectedException(e, "Coverage analysis threw this exception while processing class " + cName);
+ }
+
+ /* Run the structure analyzer on the project source folder to build up the coverage model. In flat file
+ * mode, only the first source directory (if there are multiple source directories) is analyzed. TODO:
+ * extend this analysis to all source directories for the open classes in flat file mode.
+ */
+
+ _log.log("Generating test coverage");
+ IBundleCoverage bundleCoverage = coverageBuilder.getBundle("Coverage Summary");
+ ReportGenerator rg = new ReportGenerator(_coverageOutdir, coverageBuilder);
+ _log.log("Determining project root");
+ _log.log("getProjectCP() = " + _classPathManager.getProjectFilesCP());
+ File f = _classPathManager.getProjectFilesCP().iterator().next();
+ if (! f.exists()) _log.log("****** Project root does not exist!");
+ _log.log("Creating coverage report for code base rooted at " + f);
+ rg.createReport(bundleCoverage, _executionDataStore, sessionInfos, f);
+ lineColors = rg.getAllLineColors();
+ _finalResult = new JUnitResultTuple(true, lineColors);
+
+ } else {
+ _log.log("runtime was null");
+ }
+ /* Reset the runtime */
+ _runtime = null;
+ _reset();
+ _jmc.testSuiteEnded(faults);
+ }
+ //TODO change error of line
+ catch (Exception e) {
+ faults = new JUnitError[] {
+ new JUnitError(null, -1, -1, e.getMessage(), false, "", "", e.toString(), e.getStackTrace())
+ };
+ _log.log("Slave JVM: testSuite ended with faults:" + Arrays.toString(faults));
+ _reset();
+ _jmc.testSuiteEnded(faults);
+ }
+
+ _log.log("Exiting runTestSuite()");
+ return _finalResult.getRetval();
+ }
+
+ private void _reset() {
+ _suite = null;
+ _testClassNames = null;
+ _testFiles = null;
+ _log.log("test manager state reset");
+ }
+
+
+ /** Constructs a new JUnitError from a TestFailure
+ * @param failure A given TestFailure
+ * @param classNames The classes that were used for this test suite
+ * @param isError The passed TestFailure may signify either an error or a failure
+ * @param files The files that were used for this test suite
+ * @param testMethodName name of tested method
+ * @return JUnitError
+ */
+ private JUnitError _makeJUnitError(TestFailure failure, List classNames, boolean isError, List files,String testMethodName) {
+
+ _log.log("_makeJUnitError called with failure " + failure + " failedTest = " + failure.failedTest());
+ Test failedTest = failure.failedTest();
+ _log.log("failedTest " + failedTest);
+ _log.log("failure.exceptionMessage " + failure.exceptionMessage());
+ _log.log("failure.toString " + failure.toString());
+
+ String testString = failure.toString();
+
+ /** junit can return a string in two different formats; we parse both formats, and then decide which one to use. */
+
+ //needtodo
+ String className=failedTest.toString();
+ String testName=testMethodName;
+ _log.log("className " + className +" testName "+testName);
+
+ String classNameAndTest = className + "." + testName;
+// _log.log("classNameAndTest = " + classNameAndTest);
+ String exception = failure.thrownException().toString();
+ StackTraceElement[] stackTrace = failure.thrownException().getStackTrace();
+
+ /* Check to see if the class and test name appear directly in the stack trace. If
+ * they don't, then we'll have to do additional work to find the line number. Additionally,
+ * if the exception occured in a subclass of the test class, we'll need to adjust our conception
+ * of the class name.
+ */
+ StringBuilder sb = new StringBuilder();
+ sb.append(exception);
+ sb.append('\n');
+ for(StackTraceElement s: stackTrace) {
+ sb.append("\tat ");
+ sb.append(s);
+ }
+ String combined = sb.toString();
+ int lineNum = -1;
+ _log.log("start to cal lineNum");
+
+ if (combined.indexOf(classNameAndTest) == -1) {
+ /* get the stack trace of the junit error */
+ String trace = failure.trace();
+ _log.log("failure.trace is " +trace);
+ /* knock off the first line of the stack trace.
+ * now the string will look like
+ * at my.package.class(file.java:line)
+ * at other.package.class(anotherfile.java:line)
+ * etc...
+ */
+ trace = trace.substring(trace.indexOf('\n')+1);
+ if (trace.trim().length()>0) {
+ while (trace.indexOf("junit.framework") != -1 &&
+ trace.indexOf("junit.framework") < trace.indexOf("(")) {
+ /* the format of the trace will have "at junit.framework.Assert..."
+ * and "junit.framework.TestCase..."
+ * on each line until the line of the actual source file.
+ * if the exception was thrown from the test case (so the test failed
+ * without going through assert), then the source file will be on
+ * the first line of the stack trace
+ */
+ trace = trace.substring(trace.indexOf('\n') + 1);
+ }
+
+ _log.log("trace after junit.framework.Assert is " +trace);
+ _log.log("testName is " +testName);
+ trace = trace.substring(trace.indexOf(testName)+2);
+ trace = trace.substring(0, trace.indexOf(')'));
+
+ _log.log("trace after substring " +trace);
+ // If the exception occurred in a subclass of the test class, then update our
+ // concept of the class and test name. Otherwise, we're only here to pick up the
+ // line number.
+ if (combined.indexOf(className) == -1) {
+ int dotPos = trace.lastIndexOf('.');
+ if (dotPos!=-1) {
+ className = trace.substring(0,dotPos);
+ classNameAndTest = className + "." + testName;
+ }
+ }
+
+ try {
+ _log.log("trace is " +trace);
+ lineNum = Integer.parseInt(trace.substring(trace.indexOf(':') + 1)) - 1;
+ }
+ catch (NumberFormatException e) { lineNum = 0; } // may be native method
+ }
+ }
+ _log.log("lineNum is " +lineNum);
+ if (lineNum < 0) {
+ lineNum = _lineNumber(combined, classNameAndTest);
+ }
+
+// if (lineNum > -1) _faultsWithPos++;
+
+ String message = (isError) ? failure.thrownException().toString():
+ failure.thrownException().getMessage();
+
+ boolean isFailure = (failure.thrownException() instanceof AssertionError ||
+ failure.thrownException() instanceof AssertionFailedError) &&
+ !classNameAndTest.equals("junit.framework.TestSuite$1.warning");
+
+// for debugging
+// try {
+// File temp = File.createTempFile("asdf", "java", new File("/home/awulf"));
+// FileWriter writer = new FileWriter(temp);
+// writer.write("testString: " + testString + "\n");
+// writer.write("old className: " + className1 + "\n");
+// writer.write("new className: " + className2 + "\n");
+// writer.write("file: " + file + "\n");
+// writer.write("lineNum: " + lineNum + "\n");
+// writer.write("exception: " + exception + "\n");
+// writer.write("!isFailure: " + !isFailure + "\n");
+// writer.write("testName: " + testName + "\n");
+// writer.write("className: " + className + "\n");
+// writer.write("stackTrace: " + stackTrace + "\n");
+// writer.close();
+// } catch(IOException e) {
+//
+// }
+
+ int indexOfClass = classNames.indexOf(className);
+ File file;
+ if (indexOfClass != -1) file = files.get(indexOfClass);
+ else file = _jmc.getFileForClassName(className);
+
+ // if testClass contains no
+
+ // a test didn't fail, we couldn't even open the test.
+ if (file == null) {
+ return new JUnitError(new File("nofile"), 0, 0, message, !isFailure, testName, className, exception, stackTrace);
+ }
+
+ return new JUnitError(file, lineNum, 0, message, !isFailure, testName, className, exception, stackTrace);
+ }
+
+
+
+
+
+ /** @param loader current template for the runner's class loader
+ * @return a fresh JUnitTestRunner with its own class loader instance.
+ */
+ protected JUnitParallelTestRunner makeRunner(ClassLoader loader) {
+ return new JUnitParallelTestRunner(_jmc, loader);
+ }
+}
diff --git a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitParallelTestRunner.java b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitParallelTestRunner.java
new file mode 100644
index 000000000..5aa6ec45a
--- /dev/null
+++ b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitParallelTestRunner.java
@@ -0,0 +1,142 @@
+/*BEGIN_COPYRIGHT_BLOCK
+ *
+ * Copyright (c) 2001-2017, JavaPLT group at Rice University (drjava@rice.edu)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software is Open Source Initiative approved Open Source Software.
+ * Open Source Initative Approved is a trademark of the Open Source Initiative.
+ *
+ * This file is part of DrJava. Download the current version of this project
+ * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
+ *
+ * END_COPYRIGHT_BLOCK*/
+
+package edu.rice.cs.drjava.model.junit;
+
+import junit.runner.*;
+import junit.framework.*;
+
+import java.util.Vector;
+
+import org.junit.experimental.ParallelComputer;
+import org.junit.runner.Description;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.AllTests;
+import org.junit.runners.Suite.SuiteClasses;
+
+import edu.rice.cs.util.Log;
+import edu.rice.cs.util.UnexpectedException;
+
+/** DrJava's own testrunner. It updates the document in the JUnit pane as error and failure events are fired.
+ * These methods run inan auxiliary thread.
+ * @version $Id$
+ */
+public class JUnitParallelTestRunner extends JUnitTestRunner {
+
+ protected static final Log _log = new Log("JUnitParallelTestRunner.txt", false);
+
+ protected Vector failedTest=new Vector();
+
+
+
+ /** Standard constructor.
+ * @param jmc a JUnitModelCallback
+ * @param loader class loader to use during testing
+ */
+ public JUnitParallelTestRunner(JUnitModelCallback jmc, ClassLoader loader) {
+ super(jmc,loader);
+ }
+
+
+ //Result result= JUnitCore.runClasses(new ParallelComputer(true, true), clsArray);
+ //Result result = _testRunner.runSuite(_suite);
+
+ //how many test cases will run
+ private int countTestCases=0;
+ /**
+ * This method will manually set the number of test cases(number of method)
+ * @param suite testSuite that contain all test cases
+ */
+ public void setCountTestCases(TestSuite suite)
+ {
+ _log.log("getCountTestCases");
+
+ countTestCases=suite.countTestCases();
+ //suite.run(_result);
+ }
+
+ /**
+ * method to run class
+ *
+ * @param classes
+ * @return
+ */
+ public synchronized Result runClass(Class>... classes) {
+ _log.log("start run in runclass,countTestCases= " + countTestCases);
+
+ // Reset all bookkeeping
+ _errorCount = 0;
+ _failureCount = 0;
+
+ // Run the test
+ _result = new TestResult();
+ _result.addListener(this);
+ _jmc.testSuiteStarted(countTestCases);
+ MyJUnitCore myJunitCore = new MyJUnitCore();
+ return myJunitCore.parallelRunClasses(new RunListener() {
+ public void testStarted(Description description) {
+ _log.log(" in testStarted " + description.getMethodName());
+ // The parameter testName of testStarted is the form of testMethod(testClass)
+ _jmc.testStarted(description.getMethodName() + "(" + description.getClassName() + ")");
+ }
+
+ public void testFinished(Description description) {
+ _log.log(" in testEnded " + description.getMethodName());
+ String testName = description.getClassName() + ":" + description.getMethodName();
+ boolean success;
+ if (failedTest.indexOf(testName) == -1)
+ success = true;
+ else
+ success = false;
+ // The parameter testName of testStarted is the form of testMethod(testClass)
+ _jmc.testEnded(description.getMethodName() + "(" + description.getClassName() + ")", success, false);
+ }
+
+ public void testFailure(Failure failure) {
+ _log.log(" in testFailed " + failure.getMessage());
+ String testName = failure.getDescription().getClassName() + ":"
+ + failure.getDescription().getMethodName();
+ failedTest.add(testName);
+ }
+
+ }, classes);
+ }
+
+}
diff --git a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestManager.java b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestManager.java
index 297d1bbbb..edb9a5ff1 100644
--- a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestManager.java
+++ b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestManager.java
@@ -98,32 +98,33 @@
*/
public class JUnitTestManager {
- protected static final Log _log = new Log("GlobalModel.txt", false);
+ /** log for use in debugging */
+ protected static final Log _log = new Log("JUnitTestManager.txt", false);
/** The interface to the master JVM via RMI. */
- private final JUnitModelCallback _jmc;
+ protected final JUnitModelCallback _jmc;
/** A factory producing a ClassLoader for tests with the given parent */
- private final ClassPathManager _classPathManager;
+ protected final ClassPathManager _classPathManager;
/** The current testRunner; initially null. Each test suite requires a new runner. */
- private JUnitTestRunner _testRunner;
+ protected JUnitTestRunner _testRunner;
/** The accumulated test suite; null if no test is pending. */
- private TestSuite _suite = null;
+ protected TestSuite _suite = null;
/** The accumulated list of names of TestCase classes; null if no test is pending. */
- private List _testClassNames = null;
+ protected List _testClassNames = null;
/** The list of files corresponding to testClassNames; null if no test is pending. */
- private List _testFiles = null;
+ protected List _testFiles = null;
// Create and initialize fields for JaCoCo
- private String _coverageOutdir = null;
- private IRuntime _runtime = null;
- private RuntimeData _myData = null;
- private List _nonTestClassNames = null;
- private JUnitResultTuple _finalResult = new JUnitResultTuple(false, null);
+ protected String _coverageOutdir = null;
+ protected IRuntime _runtime = null;
+ protected RuntimeData _myData = null;
+ protected List _nonTestClassNames = null;
+ protected JUnitResultTuple _finalResult = new JUnitResultTuple(false, null);
/** Standard constructor
* @param jmc a JUnitModelCallback
@@ -140,7 +141,7 @@ public JUnitTestManager(JUnitModelCallback jmc, ClassPathManager loaderFactory)
/** Used to load class files in the analysis phase of code coverage
* @return URLClassLoader with DrJava classpath
*/
- private URLClassLoader newURLLoader() {
+ protected URLClassLoader newURLLoader() {
List urls = new LinkedList();
for (File f : _classPathManager.getClassPath()) {
try { urls.add(f.toURI().toURL()); }
@@ -357,7 +358,7 @@ private void _reset() {
* @param c the class to check
* @return true iff the given class is an instance of junit.framework.Test
*/
- private boolean _isJUnitTest(Class> c) {
+ protected boolean _isJUnitTest(Class> c) {
_log.log("Testing class " + c + " to determine if it is a JUnit test class");
// test first for JUnit 4 annotated test methods
@@ -378,10 +379,11 @@ private boolean _isJUnitTest(Class> c) {
* @param files The files that were used for this test suite
* @return JUnitError
*/
- private JUnitError _makeJUnitError(TestFailure failure, List classNames, boolean isError, List files) {
+ protected JUnitError _makeJUnitError(TestFailure failure, List classNames, boolean isError, List files) {
// _log.log("_makeJUnitError called with failure " + failure + " failedTest = " + failure.failedTest());
Test failedTest = failure.failedTest();
+ _log.log("failedTest " + failedTest);
String testName;
if (failedTest instanceof JUnit4TestCaseFacade) {
testName = ((JUnit4TestCaseFacade) failedTest).toString();
@@ -394,7 +396,7 @@ private JUnitError _makeJUnitError(TestFailure failure, List classNames,
int secondIndex = testString.indexOf(')');
/** junit can return a string in two different formats; we parse both formats, and then decide which one to use. */
-
+ _log.log("testString " + testString +" testName "+testName);
String className;
if (firstIndex != secondIndex)
className = testString.substring(firstIndex, secondIndex);
@@ -515,7 +517,7 @@ private JUnitError _makeJUnitError(TestFailure failure, List classNames,
* @param classname class in which stack trace was generated
* @return the line number
*/
- private int _lineNumber(String sw, String classname) {
+ protected int _lineNumber(String sw, String classname) {
// TODO: use stack trace elements to find line number
int lineNum;
int idxClassname = sw.indexOf(classname);
@@ -539,7 +541,7 @@ private int _lineNumber(String sw, String classname) {
/** @param loader current template for the runner's class loader
* @return a fresh JUnitTestRunner with its own class loader instance.
*/
- private JUnitTestRunner makeRunner(ClassLoader loader) {
+ protected JUnitTestRunner makeRunner(ClassLoader loader) {
return new JUnitTestRunner(_jmc, loader);
}
}
diff --git a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestRunner.java b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestRunner.java
index d6ca49fe2..6cbf7c258 100644
--- a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestRunner.java
+++ b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestRunner.java
@@ -51,19 +51,19 @@ public class JUnitTestRunner extends BaseTestRunner {
protected static final Log _log = new Log("JUnitTestManager.txt", false);
/** Receives updates on the test suite's progress. */
- private JUnitModelCallback _jmc;
+ protected JUnitModelCallback _jmc;
/** Class loader that uses DrJava's classpath. */
- private ClassLoader _loader;
+ protected ClassLoader _loader;
/** The JUnit TestResult being accumulated. */
- private TestResult _result;
+ protected TestResult _result;
/** The current number of errors in the result. */
- private int _errorCount;
+ protected int _errorCount;
/** The current number of failures in the result. */
- private int _failureCount;
+ protected int _failureCount;
diff --git a/drjava/src/edu/rice/cs/drjava/model/junit/MyJUnitCore.java b/drjava/src/edu/rice/cs/drjava/model/junit/MyJUnitCore.java
new file mode 100644
index 000000000..23c2575a9
--- /dev/null
+++ b/drjava/src/edu/rice/cs/drjava/model/junit/MyJUnitCore.java
@@ -0,0 +1,50 @@
+package edu.rice.cs.drjava.model.junit;
+
+import org.junit.experimental.ParallelComputer;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+
+import edu.rice.cs.util.Log;
+
+/**
+ * This class is used to run test in parallel.
+ * It uses ParallelComputer to parallel test method and test class
+ * @author zhexin
+ *
+ */
+public class MyJUnitCore extends JUnitCore {
+ public static Log _log = new Log("MyJUnitCore.txt", false);
+
+ private final RunNotifier runNotifier = new RunNotifier();
+
+ /**
+ * method to run test classes in parallel
+ * @param listener listener for these test case
+ * @param classes test cases
+ * @return result of running these test case
+ */
+ public Result parallelRunClasses(RunListener listener, Class>[] classes) {
+ _log.log("start parallelRunClasses");
+ Runner runner = Request.classes(new ParallelComputer(true, true), classes).getRunner();
+ Result result = new Result();
+ RunListener resultListener = result.createListener();
+ runNotifier.addFirstListener(resultListener);
+ runNotifier.addListener(listener);
+ try {
+ runNotifier.fireTestRunStarted(runner.getDescription());
+ runner.run(runNotifier);
+ runNotifier.fireTestRunFinished(result);
+ } finally {
+ removeListener(listener);
+ removeListener(resultListener);
+
+ }
+ return result;
+
+ }
+
+}
diff --git a/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVM.java b/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVM.java
index a2c987e6f..562c69c2c 100644
--- a/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVM.java
+++ b/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVM.java
@@ -59,6 +59,7 @@
import edu.rice.cs.drjava.platform.PlatformFactory;
import edu.rice.cs.drjava.model.junit.JUnitModelCallback;
+import edu.rice.cs.drjava.model.junit.JUnitParallelTestManager;
import edu.rice.cs.drjava.model.junit.JUnitTestManager;
import edu.rice.cs.drjava.model.junit.JUnitError;
import edu.rice.cs.drjava.model.junit.JUnitResultTuple;
@@ -86,8 +87,8 @@
* @version $Id$
*/
public class InterpreterJVM extends AbstractSlaveJVM implements InterpreterJVMRemoteI, JUnitModelCallback {
-
- public static final Log _log = new Log("GlobalModel.txt", false);
+ /** log for use in debugging */
+ public static final Log _log = new Log("InterpreterJVM.txt", false);
/** Singleton instance of this class. */
public static final InterpreterJVM ONLY = new InterpreterJVM();
@@ -110,7 +111,8 @@ public class InterpreterJVM extends AbstractSlaveJVM implements InterpreterJVMRe
private final Object _stateLock = new Object();
/** Responsible for running JUnit tests in this JVM. */
- private final JUnitTestManager _junitTestManager;
+ private final JUnitParallelTestManager _junitTestManager;
+
/** Remote reference to the MainJVM class in DrJava's primary JVM. Assigned ONLY once. */
private volatile MainJVMRemoteI _mainJVM;
@@ -122,7 +124,7 @@ private InterpreterJVM() {
/* Important singleton objects embedded in an InterpreterJVM */
_classPathManager = new ClassPathManager(ReflectUtil.SYSTEM_CLASS_PATH);
_interpreterLoader = _classPathManager.makeClassLoader(InterpreterJVM.class.getClassLoader());
- _junitTestManager = new JUnitTestManager(this, _classPathManager);
+ _junitTestManager = new JUnitParallelTestManager(this, _classPathManager);
// set the thread context class loader, this way NextGen and Mint can use the interpreter's class loader
Thread.currentThread().setContextClassLoader(_interpreterLoader);
@@ -541,7 +543,10 @@ public List findTestClasses(List classNames,
* and does not involve mutable local state.
* @return false if no test suite is cached; true otherwise
*/
- public boolean runTestSuite() throws RemoteException { return _junitTestManager.runTestSuite(); }
+ public boolean runTestSuite(Boolean runTestParallel) throws RemoteException {
+ _log.log("runTestSuite with runTestParallel= "+runTestParallel);
+ return _junitTestManager.runTestSuite(runTestParallel);
+ }
/** Notifies Main JVM that JUnit has been invoked on a non TestCase class. Unsynchronized because it contains a
* remote call and does not involve mutable local state.
diff --git a/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVMRemoteI.java b/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVMRemoteI.java
index 89cec0507..ce6059743 100644
--- a/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVMRemoteI.java
+++ b/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVMRemoteI.java
@@ -53,7 +53,7 @@ public interface InterpreterJVMRemoteI extends SlaveRemote {
public List findTestClasses(List classNames,
List files, CoverageMetadata coverageMetadata) throws RemoteException;
- public boolean runTestSuite() throws RemoteException;
+ public boolean runTestSuite(Boolean runTestParallel) throws RemoteException;
//public JUnitResultTuple getLastJUnitResult();
diff --git a/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/MainJVM.java b/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/MainJVM.java
index f48c5f899..23b50fb91 100644
--- a/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/MainJVM.java
+++ b/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/MainJVM.java
@@ -58,6 +58,7 @@
import edu.rice.cs.util.ArgumentTokenizer;
import edu.rice.cs.util.FileOps;
+import edu.rice.cs.util.Log;
import edu.rice.cs.util.UnexpectedException;
import edu.rice.cs.plt.io.IOUtil;
import edu.rice.cs.plt.iter.IterUtil;
@@ -94,6 +95,9 @@
*/
public class MainJVM extends AbstractMasterJVM implements MainJVMRemoteI {
+ /** Debugging log. */
+ public static Log _log = new Log("MainJVM.txt", false);
+
/** Number of slave startup failures allowed before aborting the startup process. */
private static final int MAX_STARTUP_FAILURES = 3;
@@ -479,13 +483,17 @@ public Option> findTestClasses(List classNames,
/** Runs the JUnit test suite already cached in the Interpreter JVM.
* Blocks until the remote JVM is available.
+ * @param runTestParallel Set whether we should run the test in parallel
* @return {@code false} if no test suite is cached, the remote JVM is
* unavailable, or an error occurs; true otherwise.
*/
- public boolean runTestSuite() {
+ public boolean runTestSuite(boolean runTestParallel) {
InterpreterJVMRemoteI remote = _state.value().interpreter(true);
if (remote == null) { return false; }
- try { return remote.runTestSuite(); }
+ try {
+ _log.log("runTestParallel= "+runTestParallel);
+ return remote.runTestSuite(runTestParallel);
+ }
catch (RemoteException e) { _handleRemoteException(e); return false; }
}
diff --git a/drjava/src/edu/rice/cs/drjava/ui/ErrorPanel.java b/drjava/src/edu/rice/cs/drjava/ui/ErrorPanel.java
index a6c8386ea..c13907ebd 100644
--- a/drjava/src/edu/rice/cs/drjava/ui/ErrorPanel.java
+++ b/drjava/src/edu/rice/cs/drjava/ui/ErrorPanel.java
@@ -45,6 +45,7 @@
import edu.rice.cs.drjava.model.DJError;
import edu.rice.cs.drjava.model.compiler.CompilerErrorModel;
import edu.rice.cs.drjava.model.ClipboardHistoryModel;
+import edu.rice.cs.util.Log;
import edu.rice.cs.util.UnexpectedException;
import edu.rice.cs.util.swing.HighlightManager;
import edu.rice.cs.util.swing.BorderlessScrollPane;
@@ -77,6 +78,8 @@
*/
public abstract class ErrorPanel extends TabbedPanel implements OptionConstants {
+ /** Debugging log. */
+ public static Log _log = new Log("ErrorPanel.txt", false);
protected static final SimpleAttributeSet NORMAL_ATTRIBUTES = _getNormalAttributes();
protected static final SimpleAttributeSet BOLD_ATTRIBUTES = _getBoldAttributes();
@@ -668,6 +671,7 @@ protected void _insertErrors(ErrorDocument doc) throws BadLocationException {
protected void _insertErrorText(DJError error, ErrorDocument doc) throws BadLocationException {
// Show file and line number
doc.append("File: ", BOLD_ATTRIBUTES);
+ //TODO
String fileAndLineNumber = error.getFileMessage() + " [line: " + error.getLineMessage() + "]";
doc.append(fileAndLineNumber + "\n", NORMAL_ATTRIBUTES);
diff --git a/drjava/src/edu/rice/cs/drjava/ui/JUnitPanel.java b/drjava/src/edu/rice/cs/drjava/ui/JUnitPanel.java
index 77b0df183..237298b12 100644
--- a/drjava/src/edu/rice/cs/drjava/ui/JUnitPanel.java
+++ b/drjava/src/edu/rice/cs/drjava/ui/JUnitPanel.java
@@ -40,6 +40,7 @@
import edu.rice.cs.drjava.model.DJError;
import edu.rice.cs.drjava.model.junit.JUnitError;
import edu.rice.cs.drjava.model.junit.JUnitErrorModel;
+import edu.rice.cs.util.Log;
import edu.rice.cs.util.UnexpectedException;
import edu.rice.cs.util.swing.BorderlessScrollPane;
import edu.rice.cs.util.swing.RightClickMouseAdapter;
@@ -59,6 +60,10 @@
* @version $Id$
*/
public class JUnitPanel extends ErrorPanel {
+
+ /** Debugging log. */
+ public static Log _log = new Log("JUnitPanel.txt", false);
+
private static final String START_JUNIT_MSG = "Testing in progress. Please wait ...\n";
private static final String JUNIT_FINISHED_MSG = "All tests completed successfully.\n";
private static final String NO_TESTS_MSG = "";
@@ -254,11 +259,15 @@ private String _getClassFromName(String name) {
* @param name the name of the test being run
*/
public void testStarted(String name) {
+ _log.log("testStarted name= " + name );
+
if (name.indexOf('(') < 0) return;
String testName = _getTestFromName(name);
String className = _getClassFromName(name);
String fullName = className + "." + testName;
+ _log.log(" fullName= " + fullName );
+
if (fullName.equals(JUNIT_WARNING)) return;
ErrorDocument doc = getErrorDocument();
try {
@@ -290,6 +299,7 @@ public void testStarted(String name) {
* @param causedError whether the test caused an error
*/
public void testEnded(String name, boolean wasSuccessful, boolean causedError) {
+ _log.log("testEnded(" + name + ", " + wasSuccessful + ", " + causedError + ")");
if (name.indexOf('(')<0) return;
String testName = _getTestFromName(name);
@@ -327,10 +337,14 @@ public void setJUnitInProgress() {
/** Used to show that testing was unsuccessful. */
protected void _updateWithErrors() throws BadLocationException {
+
//DefaultStyledDocument doc = new DefaultStyledDocument();
ErrorDocument doc = getErrorDocument();
+ _log.log("doc is "+doc.getText());
// _checkSync(doc);
_updateWithErrors("test", "failed", doc);
+ _log.log("doc is "+doc.getText());
+
}
/** Gets the message indicating the number of errors and warnings.*/
diff --git a/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java b/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java
index b8447e118..2890a20d7 100644
--- a/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java
+++ b/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java
@@ -91,6 +91,7 @@
import edu.rice.cs.drjava.model.definitions.NoSuchDocumentException;
import edu.rice.cs.drjava.model.debug.*;
import edu.rice.cs.drjava.model.repl.*;
+import edu.rice.cs.drjava.model.repl.newjvm.MainJVM;
import edu.rice.cs.drjava.model.javadoc.JavadocModel;
import edu.rice.cs.drjava.ui.config.ConfigFrame;
import edu.rice.cs.drjava.ui.coverage.CoverageFrame;
@@ -131,6 +132,7 @@
import static edu.rice.cs.util.XMLConfig.XMLConfigException;
import static edu.rice.cs.drjava.ui.MainFrameStatics.*;
+import edu.rice.cs.drjava.model.junit.JUnitParallelTestManager;
import edu.rice.cs.drjava.model.junit.JUnitResultTuple;
/** DrJava's main window. */
@@ -779,9 +781,20 @@ public void actionPerformed(ActionEvent ae) {
GUIAvailabilityListener.ComponentType.JUNIT,
GUIAvailabilityListener.ComponentType.COMPILER,
GUIAvailabilityListener.ComponentType.INTERACTIONS); }
- public final void actionPerformed(ActionEvent ae) { _junitFolder(); }
+ public final void actionPerformed(ActionEvent ae) { _junitFolder(false); }
};
+
+ /** Tests all the files in a folder in parallel. */
+ private volatile AbstractAction _junitPararrelFolderAction = new AbstractAction("Test Folder in parallel") {
+ { _addGUIAvailabilityListener(this,
+ GUIAvailabilityListener.ComponentType.JUNIT,
+ GUIAvailabilityListener.ComponentType.COMPILER,
+ GUIAvailabilityListener.ComponentType.INTERACTIONS); }
+ public final void actionPerformed(ActionEvent ae) { _junitFolder(true); }
+ };
+
+
/** Saves the current document. */
private final Action _saveAction = new AbstractAction("Save") {
public final void actionPerformed(ActionEvent ae) { _save(); }
@@ -1021,7 +1034,19 @@ public void actionPerformed(ActionEvent ae) {
GUIAvailabilityListener.ComponentType.INTERACTIONS); }
public void actionPerformed(ActionEvent ae) {
if (_mainSplit.getDividerLocation() > _mainSplit.getMaximumDividerLocation()) _mainSplit.resetToPreferredSizes();
- _junit();
+ _junit(false);
+ }
+ };
+
+ /** Runs JUnit on the document in the definitions pane in parallel. */
+ private volatile AbstractAction _junitActionParallel = new AbstractAction("Test Current Document in parallel") {
+ { _addGUIAvailabilityListener(this, // init
+ GUIAvailabilityListener.ComponentType.JUNIT,
+ GUIAvailabilityListener.ComponentType.COMPILER,
+ GUIAvailabilityListener.ComponentType.INTERACTIONS); }
+ public void actionPerformed(ActionEvent ae) {
+ if (_mainSplit.getDividerLocation() > _mainSplit.getMaximumDividerLocation()) _mainSplit.resetToPreferredSizes();
+ _junit(true);
}
};
@@ -1033,12 +1058,28 @@ public void actionPerformed(ActionEvent ae) {
GUIAvailabilityListener.ComponentType.INTERACTIONS); }
public void actionPerformed(ActionEvent e) {
if (_mainSplit.getDividerLocation() > _mainSplit.getMaximumDividerLocation()) _mainSplit.resetToPreferredSizes();
- _junitAll();
+ _junitAll(false);
_findReplace.updateFirstDocInSearch();
}
};
+ /** Runs JUnit over all open JUnit tests. */
+ private volatile AbstractAction _junitAllActionParallel = new AbstractAction("Test All Documents in Parallel") {
+ { _addGUIAvailabilityListener(this, // init
+ GUIAvailabilityListener.ComponentType.JUNIT,
+ GUIAvailabilityListener.ComponentType.COMPILER,
+ GUIAvailabilityListener.ComponentType.INTERACTIONS); }
+ public void actionPerformed(ActionEvent e) {
+ if (_mainSplit.getDividerLocation() > _mainSplit.getMaximumDividerLocation()) _mainSplit.resetToPreferredSizes();
+ _junitAll(true);
+ _findReplace.updateFirstDocInSearch();
+ }
+
+ };
+
+
+
/** Runs JUnit over all open JUnit tests in the project directory. */
private volatile AbstractAction _junitProjectAction = new AbstractAction("Test Project") {
{ _addGUIAvailabilityListener(this, // init
@@ -1048,7 +1089,21 @@ public void actionPerformed(ActionEvent e) {
GUIAvailabilityListener.ComponentType.INTERACTIONS); }
public void actionPerformed(ActionEvent e) {
if (_mainSplit.getDividerLocation() > _mainSplit.getMaximumDividerLocation()) _mainSplit.resetToPreferredSizes();
- _junitProject();
+ _junitProject(false);
+ _findReplace.updateFirstDocInSearch();
+ }
+ };
+
+ /** Runs JUnit over all open JUnit tests in the project directory. */
+ private volatile AbstractAction _junitProjectActionParallel = new AbstractAction("Test Project in Parallel") {
+ { _addGUIAvailabilityListener(this, // init
+ GUIAvailabilityListener.ComponentType.PROJECT,
+ GUIAvailabilityListener.ComponentType.JUNIT,
+ GUIAvailabilityListener.ComponentType.COMPILER,
+ GUIAvailabilityListener.ComponentType.INTERACTIONS); }
+ public void actionPerformed(ActionEvent e) {
+ if (_mainSplit.getDividerLocation() > _mainSplit.getMaximumDividerLocation()) _mainSplit.resetToPreferredSizes();
+ _junitProject(true);
_findReplace.updateFirstDocInSearch();
}
};
@@ -5933,7 +5988,7 @@ private void _runApplet() {
catch (IOException ioe) { MainFrameStatics.showIOError(MainFrame.this, ioe); }
}
- private void _junit() {
+ private void _junit(Boolean runTestParallel) {
/* */ assert Utilities.TEST_MODE || EventQueue.isDispatchThread();
hourglassOn(); // turned off in junitStarted/nonTestCase/_junitInterrupted
@@ -5944,12 +5999,16 @@ private void _junit() {
// now also works with multiple documents
// hourglassOn(); // moved into the prelude before this thread start
- try { _model.getJUnitModel().junitDocs(_model.getDocumentNavigator().getSelectedDocuments()); }
+ try {
+ if(runTestParallel==true)
+ _model.getJUnitModel().setRunTestParallel(true);
+ _model.getJUnitModel().junitDocs(_model.getDocumentNavigator().getSelectedDocuments());
+ }
catch(UnexpectedException e) { _junitInterrupted(e); }
catch(Exception e) { _junitInterrupted(new UnexpectedException(e)); }
}
- private void _junitFolder() {
+ private void _junitFolder(Boolean runTestParallel) {
updateStatusField("Running Unit Tests in Current Folder");
hourglassOn(); // turned off in junitStarted/nonTestCase/_junitInterrupted
// moved this back into the event thread to fix bug 2848696
@@ -5964,28 +6023,39 @@ private void _junitFolder() {
for (OpenDefinitionsDocument doc: docs) {
if (_model.getDocumentNavigator().isSelectedInGroup(doc)) l.add(doc);
}
- try { _model.getJUnitModel().junitDocs(l); } // hourglassOn executed by junitStarted()
+ try {
+ if(runTestParallel==true)
+ _model.getJUnitModel().setRunTestParallel(true);
+ _model.getJUnitModel().junitDocs(l); } // hourglassOn executed by junitStarted()
catch(UnexpectedException e) { _junitInterrupted(e); }
catch(Exception e) { _junitInterrupted(new UnexpectedException(e)); }
}
}
/** Tests the documents in the project source tree. Assumes that DrJava is in project mode. */
- private void _junitProject() {
+ private void _junitProject(boolean runTestParallel) {
updateStatusField("Running JUnit Tests in Project");
hourglassOn(); // turned off in junitStarted/nonTestCase/_junitInterrupted
_guiAvailabilityNotifier.junitStarted(); // JUNIT and COMPILER
- try { _model.getJUnitModel().junitProject(); }
+ try {
+ if(runTestParallel==true)
+ _model.getJUnitModel().setRunTestParallel(true);
+ _model.getJUnitModel().junitProject();
+ }
catch(UnexpectedException e) { _junitInterrupted(e); }
catch(Exception e) { _junitInterrupted(new UnexpectedException(e)); }
}
/** Tests all open documents. */
- public void _junitAll() {
+ public void _junitAll(boolean runTestParallel) {
updateStatusField("Running All Open Unit Tests");
hourglassOn(); // turned off in junitStarted/nonTestCase/_junitInterrupted
_guiAvailabilityNotifier.junitStarted(); // JUNIT and COMPILER
- try { _model.getJUnitModel().junitAll(); }
+ try {
+ if(runTestParallel==true)
+ _model.getJUnitModel().setRunTestParallel(true);
+ _model.getJUnitModel().junitAll();
+ }
catch(UnexpectedException e) { _junitInterrupted(e); }
catch(Exception e) { _junitInterrupted(new UnexpectedException(e)); }
}
@@ -6531,7 +6601,7 @@ private void _setUpActions() {
_setUpAction(_junitAction, "Test Current", "Run JUnit over the current document");
_setUpAction(_junitAllAction, "Test", "Run JUnit over all open JUnit tests");
-
+ _setUpAction(_junitAllActionParallel, "Test in Parallel", "Run JUnit over all open JUnit tests in Parallel");
_setUpAction(_coverageAction, "Code Coverage", "Generate code coverage reports");
if (_model.getJavadocModel().isAvailable()) {
@@ -6959,6 +7029,8 @@ private JMenu _setUpToolsMenu(int mask, boolean updateKeyboardManager) {
_addMenuItem(toolsMenu, _compileAction, KEY_COMPILE, updateKeyboardManager);
_addMenuItem(toolsMenu, _junitAllAction, KEY_TEST_ALL, updateKeyboardManager);
_addMenuItem(toolsMenu, _junitAction, KEY_TEST, updateKeyboardManager);
+ _addMenuItem(toolsMenu, _junitAllActionParallel, KEY_TEST_ALL_PARALLEL, updateKeyboardManager);
+ _addMenuItem(toolsMenu, _junitActionParallel, KEY_TEST_PARALLEL, updateKeyboardManager);
toolsMenu.addSeparator();
// Run
@@ -7129,6 +7201,7 @@ private JMenu _setUpProjectMenu(int mask, boolean updateKeyboardManager) {
// run project
_addMenuItem(projectMenu, _compileProjectAction, KEY_COMPILE_PROJECT, updateKeyboardManager);
_addMenuItem(projectMenu, _junitProjectAction, KEY_JUNIT_PROJECT, updateKeyboardManager);
+ _addMenuItem(projectMenu, _junitProjectActionParallel, KEY_JUNIT_PROJECT_PARALLEL, updateKeyboardManager);
_addMenuItem(projectMenu, _runProjectAction, KEY_RUN_PROJECT, updateKeyboardManager);
_addMenuItem(projectMenu, _cleanAction, KEY_CLEAN_PROJECT, updateKeyboardManager);
_addMenuItem(projectMenu, _autoRefreshAction, KEY_AUTO_REFRESH_PROJECT, updateKeyboardManager);
@@ -7472,6 +7545,7 @@ private void _setUpToolBar() {
_toolBar.add(_runButton = _createToolBarButton(_runAction));
_toolBar.add(_junitButton = _createToolBarButton(_junitAllAction));
+ _toolBar.add(_junitButton = _createToolBarButton(_junitAllActionParallel));
_toolBar.add(_createToolBarButton(_javadocAllAction));
_toolBar.add(_coverageButton = _createToolBarButton(_coverageAction));
@@ -7991,6 +8065,7 @@ protected void _popupAction(MouseEvent e) {
m.add(_compileProjectAction);
m.add(_runProjectAction);
m.add(_junitProjectAction);
+ m.add(_junitProjectActionParallel);
m.add(_projectPropertiesAction);
}
if (folderSelected) {
@@ -8007,6 +8082,7 @@ protected void _popupAction(MouseEvent e) {
m.add(_closeFolderAction);
m.add(_compileFolderAction);
m.add(_junitFolderAction);
+ m.add(_junitPararrelFolderAction);
}
else if (groupSelectedCount>1) {
if (!externalBinSelected && !auxiliaryBinSelected) {
@@ -8021,6 +8097,8 @@ else if (groupSelectedCount>1) {
createDelegateAction("Compile All Folders ("+groupSelectedCount+")", _compileFolderAction));
m.add(Utilities.
createDelegateAction("Test All Folders ("+groupSelectedCount+")", _junitFolderAction));
+ m.add(Utilities.
+ createDelegateAction("Test All Folders in parallel ("+groupSelectedCount+")", _junitPararrelFolderAction));
}
}
@@ -8038,6 +8116,7 @@ else if (groupSelectedCount>1) {
m.add(Utilities.createDelegateAction("Print File Preview...", _printDefDocPreviewAction));
m.add(Utilities.createDelegateAction("Compile File", _compileAction));
m.add(Utilities.createDelegateAction("Test File", _junitAction));
+ m.add(Utilities.createDelegateAction("Test File in Parallel", _junitActionParallel));
m.add(Utilities.createDelegateAction("Preview Javadoc for File", _javadocCurrentAction));
m.add(Utilities.createDelegateAction("Run File", _runAction));
m.add(Utilities.createDelegateAction("Run File as Applet", _runAppletAction));
@@ -8080,6 +8159,9 @@ else if (docSelectedCount>1) {
m.add(Utilities.createDelegateAction("Close All Files", _closeFolderAction));
m.add(Utilities.createDelegateAction("Compile All Files", _compileFolderAction));
m.add(Utilities.createDelegateAction("Test All Files", _junitFolderAction));
+ m.add(Utilities.createDelegateAction("Test All Files in parallel", _junitPararrelFolderAction));
+
+
}
if (externalBinSelected && !auxiliaryBinSelected) {
// external bin selected
diff --git a/drjava/src/edu/rice/cs/drjava/ui/coverage/CoverageFrame.java b/drjava/src/edu/rice/cs/drjava/ui/coverage/CoverageFrame.java
index 4f4744582..aba8abbda 100644
--- a/drjava/src/edu/rice/cs/drjava/ui/coverage/CoverageFrame.java
+++ b/drjava/src/edu/rice/cs/drjava/ui/coverage/CoverageFrame.java
@@ -305,7 +305,7 @@ private void cancel() {
private void startJUnit(){
_model.getJUnitModel().setCoverage(true,
this._outputDirSelector.getFileFromField().getPath());
- _mainFrame._junitAll();
+ _mainFrame._junitAll(false);
CoverageFrame.this.setVisible(false);
}
diff --git a/drjava/src/edu/rice/cs/util/LogTest.java b/drjava/src/edu/rice/cs/util/LogTest.java
index 6c59135db..e52f2cb6d 100644
--- a/drjava/src/edu/rice/cs/util/LogTest.java
+++ b/drjava/src/edu/rice/cs/util/LogTest.java
@@ -50,7 +50,6 @@
* @version $Id$
*/
public class LogTest extends MultiThreadedTestCase {
-
public static final int TOL = 2000;
// Relying on default constructor
@@ -218,7 +217,9 @@ public void testExceptionPrinting() throws IOException {
private static final int NUM_THREADS = 50;
private static final int DELAY = 100;
- // private static final Log ltl = new Log("logtest.txt", false);
+
+ //TODO task
+ private static final Log ltl = new Log("logtest.txt", false);
/** Attempts to test Log's behavior when called concurrently from several sources. Spawns NUM_THREADS LogTestThreads
* (see above)that wait a random number between 0 and DELAY milliseconds and then log a message. The function tests
@@ -247,9 +248,9 @@ public void testConcurrentWrites() throws IOException, InterruptedException {
Date now = new Date();
String s0 = fin.readLine();
Date time0 = log3.parse(s0);
- //ltl.log("earlier = " + earlier);
- //ltl.log("now = " + now);
- //ltl.log("time0 = " + time0);
+ ltl.log("earlier = " + earlier);
+ ltl.log("now = " + now);
+ ltl.log("time0 = " + time0);
assertTrue("Log not opened after 'earlier' and before 'now'", withinTolerance(earlier, time0, now));
String log3OpenMsg = "Log '" + file3.getName() + "' opened: ";
@@ -258,6 +259,7 @@ public void testConcurrentWrites() throws IOException, InterruptedException {
for (int i = 0; i < NUM_THREADS; i++) {
String s1 = fin.readLine();
Date time1 = log3.parse(s1);
+ ltl.log("time1 = " + time1);
assertTrue("Date of message not after 'earlier' and before 'now'", withinTolerance(earlier, time1, now));
assertTrue("Date of message not after 'previous time' and before 'now'", withinTolerance(time0, time1, now));
assertEquals("Log message", "Test message", getStringAfterDate(s1));