@@ -291,6 +291,7 @@ public void uncaughtException(final Thread t, final Throwable e) {
291291 }
292292 }
293293 };
294+ tg .setDaemon (true );
294295 final Thread t = new Thread (tg , "TestExecutionMainThread" ) {
295296 @ Override
296297 public void run () {
@@ -318,10 +319,20 @@ public void run() {
318319 /* Interrupted while waiting for test; interrupt test and exit */
319320 tg .interrupt ();
320321 throw e ;
321- }
322- ensureThreadGroupTerminated (logEntry , tg , t );
323- if (!tg .isDestroyed ()) {
324- tg .destroy ();
322+ } finally {
323+ ensureThreadGroupTerminated (logEntry , tg , t );
324+ if (!tg .isDestroyed ()) {
325+ /* The ThreadGroup isn't destroyed -- a Thread won't
326+ * stop. Mark all Threads as daemon so the JVM won't
327+ * wait for any of them at JVM exit time.
328+ */
329+ Thread [] threadList = new Thread [tg .activeCount () * 2 ];
330+ /* 2 here is an arbitrary fudge factor -- all of this is best effort only */
331+ tg .enumerate (threadList );
332+ for (Thread threadListElement : threadList ) {
333+ threadListElement .setDaemon (true );
334+ }
335+ }
325336 }
326337 }
327338
@@ -431,7 +442,7 @@ protected void executeTest(final TestExecutionResult<C, R> logEntry) throws Thro
431442
432443 protected void starting (final C instanceUnderTest , final TestExecutionResult <C , R > logEntry ) {
433444 if (instanceUnderTest == null ) {
434- throw new NullPointerException ("Attempt to execute test on null test item" );
445+ throw new NullTestItemException ("Attempt to execute test on null test item" );
435446 }
436447 logEntry .processing (instanceUnderTest );
437448 }
@@ -443,7 +454,7 @@ protected void starting(final C instanceUnderTest) {
443454
444455 protected void startingStatic (final Class <? extends C > actualClassUnderTest , final TestExecutionResult <C , R > logEntry ) {
445456 if (actualClassUnderTest == null ) {
446- throw new NullPointerException ("Attempt to execute test on null test class" );
457+ throw new NullTestItemException ("Attempt to execute test on null test class" );
447458 }
448459 logEntry .processingStatic (actualClassUnderTest );
449460 }
@@ -1030,6 +1041,26 @@ public enum Evaluation {
10301041
10311042 }
10321043
1044+ /**
1045+ * A <code>NullTestItemException</code> is a
1046+ * <code>NullPointerException</code> thrown by BevoTest because the item
1047+ * under test was null.
1048+ *
1049+ * @author John Thywissen
1050+ */
1051+ @ SuppressWarnings ("serial" )
1052+ public static class NullTestItemException extends NullPointerException {
1053+ /**
1054+ * Constructs a <code>NullTestItemException</code> with the specified
1055+ * detail message.
1056+ *
1057+ * @param s the detail message.
1058+ */
1059+ public NullTestItemException (String s ) {
1060+ super (s );
1061+ }
1062+ }
1063+
10331064 /**
10341065 * A <code>TimeoutStackTrace</code> holds the stack trace found in a
10351066 * test execution thread that was terminated because it exceeded the test
0 commit comments