Skip to content

Commit 48e9711

Browse files
author
rcartwright
committed
This revision cleans up the test code associated with
JUnitErrorModelTest, which hangs about half of the time on a dual core Linux machine. The revised version will still hang if multiple JUnitErrorModelTest executions are run back to back. Evidently, a new test can start before the preceding completely cleans up. The following files were modified: M src/edu/rice/cs/drjava/model/GlobalModelTestCase.java M src/edu/rice/cs/drjava/model/cache/DocumentCache.java M src/edu/rice/cs/drjava/model/definitions/reducedmodel/ReducedModelComment.java M src/edu/rice/cs/drjava/model/definitions/reducedmodel/AbstractReducedModel.java M src/edu/rice/cs/drjava/model/definitions/reducedmodel/ReducedModelBrace.java M src/edu/rice/cs/drjava/model/junit/JUnitErrorModelTest.java M src/edu/rice/cs/drjava/model/junit/JUnitTestManager.java git-svn-id: file:///tmp/test-svn/trunk@5437 fe72c1cf-3628-48e9-8b72-1c46755d3cff
1 parent cfce2bb commit 48e9711

File tree

7 files changed

+123
-55
lines changed

7 files changed

+123
-55
lines changed

drjava/src/edu/rice/cs/drjava/model/GlobalModelTestCase.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,7 +1019,7 @@ public void consoleReset() {
10191019

10201020
public void resetConsoleResetCount() { consoleResetCount = 0; }
10211021

1022-
public void logInteractionStart() {
1022+
public synchronized void logInteractionStart() {
10231023
_interactionDone.reset();
10241024
_resetDone.reset();
10251025
}
@@ -1044,7 +1044,7 @@ public static class CompileShouldSucceedListener extends InteractionListener {
10441044
private volatile boolean _compileDone = false; // records when compilaton is done
10451045
private final Object _compileLock = new Object(); // lock for _compileDone
10461046

1047-
public void logCompileStart() {
1047+
public synchronized void logCompileStart() {
10481048
logInteractionStart();
10491049
_compileDone = false;
10501050
}
@@ -1190,8 +1190,8 @@ public JUnitTestListener(boolean printListenerMessages) {
11901190
this.printMessages = printListenerMessages;
11911191
}
11921192

1193-
public void logJUnitStart() {
1194-
logCompileStart();
1193+
public synchronized void logJUnitStart() {
1194+
// logCompileStart();
11951195
_junitDone = false;
11961196
}
11971197

@@ -1219,7 +1219,7 @@ public void waitJUnitDone() throws InterruptedException {
12191219
private void _notifyJUnitDone() {
12201220
synchronized(_junitLock) {
12211221
_junitDone = true;
1222-
_junitLock.notify();
1222+
_junitLock.notifyAll();
12231223
}
12241224
}
12251225

@@ -1229,7 +1229,7 @@ public void resetCompileCounts() {
12291229
activeCompilerChangedCount = 0;
12301230
}
12311231

1232-
public void resetJUnitCounts() {
1232+
public synchronized void resetJUnitCounts() {
12331233
junitStartCount = 0;
12341234
junitSuiteStartedCount = 0;
12351235
junitTestStartedCount = 0;
@@ -1281,7 +1281,7 @@ public void resetJUnitCounts() {
12811281
/** Listener class for failing JUnit invocation. */
12821282
public static class JUnitNonTestListener extends JUnitTestListener {
12831283
private volatile boolean _shouldBeTestAll;
1284-
public JUnitNonTestListener() { this(false); }
1284+
public JUnitNonTestListener() { this(false); }
12851285
public JUnitNonTestListener(boolean shouldBeTestAll) { _shouldBeTestAll = shouldBeTestAll; }
12861286
public void nonTestCase(boolean isTestAll, boolean didCompileFail) {
12871287
synchronized(this) { nonTestCaseCount++; }

drjava/src/edu/rice/cs/drjava/model/cache/DocumentCache.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,6 @@ public int getLength() {
213213
return doc.getLength();
214214
}
215215

216-
217216
/** Gets the text of this document using the cached reconstructor if document is not resident or it is unchanged.
218217
* If document is not locked, may return stale data. */
219218
public String getText() {

drjava/src/edu/rice/cs/drjava/model/definitions/reducedmodel/AbstractReducedModel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public abstract class AbstractReducedModel implements ReducedModelStates {
4747
public static final char PTR_CHAR = '#';
4848

4949
/** The reduced model for a document is a list of ReducedTokens (braces and gaps). */
50-
TokenList _tokens;
50+
volatile TokenList _tokens;
5151

5252
/** Keeps track of cursor position in document. */
5353
TokenList.Iterator _cursor;

drjava/src/edu/rice/cs/drjava/model/definitions/reducedmodel/ReducedModelBrace.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
*/
4747
public class ReducedModelBrace extends AbstractReducedModel {
4848

49-
private ReducedModelControl _parent; // contains the walker which is moved by moveWalkerGetState
49+
private volatile ReducedModelControl _parent; // contains the walker which is moved by moveWalkerGetState
5050

5151
public ReducedModelBrace(ReducedModelControl parent) {
5252
super();

drjava/src/edu/rice/cs/drjava/model/definitions/reducedmodel/ReducedModelComment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
public class ReducedModelComment extends AbstractReducedModel {
4747

4848
/** Can be used by other classes to walk through the list of comment chars*/
49-
TokenList.Iterator _walker;
49+
volatile TokenList.Iterator _walker;
5050

5151
/** Constructor. Creates a new reduced model with the cursor at the start of a blank "page." */
5252
public ReducedModelComment() {

drjava/src/edu/rice/cs/drjava/model/junit/JUnitErrorModelTest.java

Lines changed: 112 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import edu.rice.cs.drjava.model.GlobalModelTestCase;
4040
import edu.rice.cs.drjava.model.OpenDefinitionsDocument;
4141
import edu.rice.cs.util.swing.Utilities;
42+
import edu.rice.cs.util.Log;
4243

4344
import java.io.File;
4445
import javax.swing.text.BadLocationException;
@@ -51,6 +52,7 @@
5152
public final class JUnitErrorModelTest extends GlobalModelTestCase {
5253

5354
private JUnitErrorModel _m;
55+
protected static final Log _log = new Log("JUnitError.txt", true);
5456

5557
private static final String MONKEYTEST_FAIL_TEXT =
5658
"import junit.framework.*; \n" +
@@ -154,39 +156,59 @@ public final class JUnitErrorModelTest extends GlobalModelTestCase {
154156
/** Tests that the errors array contains all encountered failures and error in the right order. */
155157
public void testErrorsArrayInOrder_NOJOIN() throws Exception {
156158
debug.logStart();
157-
_m = new JUnitErrorModel(new JUnitError[0], _model, false);
159+
_log.log("testErrorArrayInOrder_NOJOIN started");
160+
final JUnitTestListener listener = new JUnitTestListener();
158161
final OpenDefinitionsDocument doc = setupDocument(MONKEYTEST_FAIL_TEXT);
159-
final File file = new File(_tempDir, "MonkeyTestFail.java");
160-
saveFile(doc, new FileSelector(file));
161-
162-
JUnitTestListener listener = new JUnitTestListener();
163-
_model.addListener(listener);
164-
165-
testStartCompile(doc);
166-
167-
listener.waitCompileDone();
168-
169-
if (_model.getCompilerModel().getNumErrors() > 0) fail("compile failed: " + getCompilerErrorString());
170-
listener.checkCompileOccurred();
162+
_log.log("doc setUp");
171163

164+
Utilities.invokeAndWait(new Runnable() {
165+
public void run() {
166+
try {
167+
_m = new JUnitErrorModel(new JUnitError[0], _model, false);
168+
169+
final File file = new File(_tempDir, "MonkeyTestFail.java");
170+
saveFile(doc, new FileSelector(file));
171+
172+
_model.addListener(listener);
173+
174+
testStartCompile(doc);
175+
_log.log("Compile started");
176+
177+
listener.waitCompileDone();
178+
_log.log("Compile done");
179+
180+
if (_model.getCompilerModel().getNumErrors() > 0) fail("compile failed: " + getCompilerErrorString());
181+
listener.checkCompileOccurred();
182+
_log.log("Done with first block");
183+
}
184+
catch(Exception e) { fail("The following exception was thrown in the first block of testErrorsArrayInOrder: /n" + e); }
185+
}
186+
});
187+
172188
listener.runJUnit(doc);
173189
// runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
174190

175191
listener.assertJUnitStartCount(1);
176-
// Clear document so we can make sure it's written to after startJUnit;
177-
// ?? When does the clear operation happen? How is the timing of this clear operation controlled?
178-
// Perform the clear operation atomically in the event thread.
192+
179193
Utilities.invokeAndWait(new Runnable() {
180194
public void run() {
181-
try {
195+
try {
196+
// Clear document so we can make sure it's written to after startJUnit;
197+
// ?? When does the clear operation happen? How is the timing of this clear operation controlled?
198+
// Performing the clear operation atomically in the event thread.
199+
182200
_model.getJUnitModel().getJUnitDocument().remove(0, _model.getJUnitModel().getJUnitDocument().getLength() - 1);
201+
assertEquals("Confirm document is empty", 0, _model.getJUnitModel().getJUnitDocument().getLength());
202+
_log.log("JUnitDocument is empty");
183203
}
184204
catch(BadLocationException e) { fail("BadLocationException in clearing JUnitDocument"); }
205+
catch(Exception e) { fail("The following exception was thrown in testErrorsArrayInOrder: /n" + e); }
185206
}
186207
});
187-
//final TestResult testResults = doc.startJUnit();
188208

189-
//_m = new JUnitErrorModel(doc.getDocument(), "MonkeyTestFail", testResults);
209+
// Wait until events triggered by running unit tests have cleared ? (should be done by code above)
210+
Utilities.clearEventQueue();
211+
_log.log("Event queue cleared");
190212
_m = _model.getJUnitModel().getJUnitErrorModel();
191213

192214
//JUnitError[] errorsWithPositions = _m.getErrorsWithPositions();
@@ -199,6 +221,11 @@ public void run() {
199221

200222
assertEquals("test case has one failure reported" + _m.getError(1).message(), _m.getError(1).isWarning(), true);
201223
//_model.setResetAfterCompile(true);
224+
225+
//final TestResult testResults = doc.startJUnit();
226+
227+
_log.log("testErrorArrayInOrder complete");
228+
//_m = new JUnitErrorModel(doc.getDocument(), "MonkeyTestFail", testResults);
202229
debug.logEnd();
203230
}
204231

@@ -208,34 +235,51 @@ public void run() {
208235
* blow up in the other JVM and never notify us that it's finished.
209236
*/
210237
public void testVerifyErrorHandledCorrectly_NOJOIN() throws Exception {
211-
OpenDefinitionsDocument doc = setupDocument(ABC_CLASS_ONE);
212-
final File file = new File(_tempDir, "ABC1.java");
213-
saveFile(doc, new FileSelector(file));
238+
_log.log("testVerifyErrorHandledCorrectly_NOJOIN started");
214239

215-
Utilities.clearEventQueue();
216-
217-
OpenDefinitionsDocument doc2 = setupDocument(ABC_TEST);
240+
final OpenDefinitionsDocument doc = setupDocument(ABC_CLASS_ONE);
241+
final File file = new File(_tempDir, "ABC1.java");
242+
final OpenDefinitionsDocument doc2 = setupDocument(ABC_TEST);
218243
final File file2 = new File(_tempDir, "ABCTest.java");
219-
saveFile(doc2, new FileSelector(file2));
220244

221-
// Compile the correct ABC and the test
222-
// JUnitTestListener listener = new JUnitTestListener(false);
223-
// System.out.println("compiling all");
224-
_model.getCompilerModel().compileAll();
225-
Utilities.clearEventQueue();
245+
Utilities.invokeAndWait(new Runnable() {
246+
public void run() {
247+
try {
248+
saveFile(doc, new FileSelector(file));
249+
saveFile(doc2, new FileSelector(file2));
250+
251+
// Compile the correct ABC and the test
252+
// JUnitTestListener listener = new JUnitTestListener(false);
253+
// System.out.println("compiling all");
254+
_model.getCompilerModel().compileAll();
255+
}
256+
catch(Exception e) { fail("The following exception was thrown in testVerifyErrorHandledCorrectly_NOJOIN location 1: /n" + e); }
257+
}
258+
});
226259

260+
_log.log("First compile in testVerifyErrorHandledCorrectly_NOJOIN comlete");
261+
227262
final OpenDefinitionsDocument doc3 = setupDocument(ABC_CLASS_TWO);
228263
final File file3 = new File(_tempDir, "ABC2.java");
229-
saveFile(doc3, new FileSelector(file3));
230264

231-
JUnitTestListener listener = new JUnitNonTestListener();
265+
Utilities.invokeAndWait(new Runnable() {
266+
public void run() { saveFile(doc3, new FileSelector(file3)); }
267+
});
268+
269+
final JUnitTestListener listener = new JUnitNonTestListener();
232270
// Compile the incorrect ABC
233271
// System.out.println("compiling doc3");
234272

235273
_model.addListener(listener);
236274

237-
listener.compile(doc3);
238-
275+
Utilities.invokeAndWait(new Runnable() {
276+
public void run() {
277+
try { listener.compile(doc3); }
278+
catch(Exception e) { fail("The following exception was thrown in testVerifyErrorHandledCorrectly_NOJOIN location 2: /n" + e); }
279+
}
280+
});
281+
282+
_log.log("Second compile complete");
239283
if (_model.getCompilerModel().getNumErrors() > 0) {
240284
fail("compile failed: " + getCompilerErrorString());
241285
}
@@ -248,12 +292,15 @@ public void testVerifyErrorHandledCorrectly_NOJOIN() throws Exception {
248292
listener.runJUnit(doc2);
249293
listener.waitJUnitDone();
250294

295+
_log.log("JUnit execution complete");
296+
251297
double version = Double.valueOf(System.getProperty("java.specification.version"));
252298
if (version < 1.5) listener.assertClassFileErrorCount(1);
253299
else
254300
assertEquals("Should report one error", 1, _model.getJUnitModel().getJUnitErrorModel().getNumErrors());
255301

256302
_model.removeListener(listener);
303+
_log.log("testVerifyErrorHandledCorrectly_NOJOIN comlete");
257304
}
258305

259306

@@ -298,22 +345,40 @@ public void testVerifyErrorHandledCorrectly_NOJOIN() throws Exception {
298345

299346
/** Test errors that occur in superclass. */
300347
public void testErrorInSuperClass_NOJOIN() throws Exception {
348+
_log.log("testErrorInSuperClass_NOJOIN started");
301349
debug.logStart();
302-
OpenDefinitionsDocument doc1 = setupDocument(TEST_ONE);
303-
OpenDefinitionsDocument doc2 = setupDocument(TEST_TWO);
350+
final OpenDefinitionsDocument doc1 = setupDocument(TEST_ONE);
351+
final OpenDefinitionsDocument doc2 = setupDocument(TEST_TWO);
304352
final File file1 = new File(_tempDir, "TestOne.java");
305353
final File file2 = new File(_tempDir, "TestTwo.java");
306-
saveFile(doc1, new FileSelector(file1));
307-
saveFile(doc2, new FileSelector(file2));
308354

309-
JUnitTestListener listener = new JUnitTestListener();
355+
Utilities.invokeAndWait(new Runnable() {
356+
public void run() {
357+
try {
358+
saveFile(doc1, new FileSelector(file1));
359+
saveFile(doc2, new FileSelector(file2));
360+
}
361+
catch(Exception e) { fail("The following exception was thrown in testErrorInSuperClass_NOJOIN location 1: /n" + e); }
362+
}
363+
});
364+
JUnitTestListener listener = new JUnitTestListener(true);
310365
_model.addListener(listener);
311-
_model.getCompilerModel().compileAll();
366+
367+
Utilities.invokeAndWait(new Runnable() {
368+
public void run() {
369+
try { _model.getCompilerModel().compileAll(); }
370+
catch(Exception e) { fail("The following exception was thrown in testErrorInSuperClass_NOJOIN location 12: /n" + e); }
371+
}
372+
});
312373
// doc1.startCompile();
313374
// doc2.startCompile();
314375

315376
listener.waitCompileDone();
377+
378+
Utilities.clearEventQueue();
379+
316380
_log.log("Testing the first document");
381+
317382
listener.runJUnit(doc1); // waits until JUnit is done
318383

319384
Utilities.clearEventQueue();
@@ -332,14 +397,17 @@ public void testErrorInSuperClass_NOJOIN() throws Exception {
332397
assertEquals("The first error is on line 5", 19, _m.getError(1).lineNumber());
333398
assertEquals("The first error is on line 5", 22, _m.getError(2).lineNumber());
334399

400+
Utilities.clearEventQueue();
401+
Utilities.clearEventQueue();
402+
335403
_log.log("Testing the second document");
336404
listener.resetJUnitCounts();
337-
405+
338406
listener.runJUnit(doc2);
339407
// runJUnit waits until the thread started in DefaultJUnitModel._rawJUnitOpenDefDocs has called notify
340-
_log.log("Second document testing should be complete");
341408

342409
Utilities.clearEventQueue();
410+
_log.log("Second document testing should be complete");
343411

344412
listener.assertJUnitStartCount(1);
345413

@@ -351,6 +419,7 @@ public void testErrorInSuperClass_NOJOIN() throws Exception {
351419

352420
_model.removeListener(listener);
353421
debug.logEnd();
422+
_log.log("testErrorInSuperClass_NOJOIN complete");
354423
}
355424
}
356425

drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
*/
6969
public class JUnitTestManager {
7070

71-
protected static final Log _log = new Log("/home/jfc1/drjava/JUnitTestManager.txt", false);
71+
protected static final Log _log = new Log("JUnitTestManager.txt", false);
7272

7373
/** The interface to the master JVM via RMI. */
7474
private final JUnitModelCallback _jmc;

0 commit comments

Comments
 (0)