Skip to content

Commit

Permalink
Introduce support for blacklisted exceptions
Browse files Browse the repository at this point in the history
This commit introduces a BlacklistedExceptions utility class for
rethrowing blacklisted exceptions (i.e., errors that always terminate
the test plan execution immediately).

HierarchicalTestExecutor and SingleTestExecutor have been retrofitted to
support blacklisted exceptions.

Issue: #83

------------------------------------------------------------------------
On behalf of the community, the JUnit Lambda Team thanks msg systems ag
(http://www.msg-systems.com) for supporting the JUnit crowdfunding
campaign!
------------------------------------------------------------------------
  • Loading branch information
sbrannen committed Jan 5, 2016
1 parent 3542b7a commit a02c0e2
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 10 deletions.
@@ -0,0 +1,52 @@
/*
* Copyright 2015-2016 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.junit.gen5.engine;

import java.util.Collections;
import java.util.List;

import org.junit.gen5.commons.util.ExceptionUtils;

/**
* Internal utilities for working with <em>blacklisted</em> exceptions.
*
* <p><em>Blacklisted</em> exceptions are those that should always terminate
* test plan execution immediately.
*
* <h4>Currently Blacklisted Exceptions</h4>
* <ul>
* <li>{@link OutOfMemoryError}</li>
* </ul>
*
* @since 5.0
*/
final class BlacklistedExceptions {

private static final List<Class<? extends Throwable>> blacklist = Collections.singletonList(OutOfMemoryError.class);

private BlacklistedExceptions() {
/* no-op */
}

/**
* Rethrow the supplied {@link Throwable exception} if it is
* <em>blacklisted</em>.
*
* <p>If the supplied {@code exception} is not <em>blacklisted</em>,
* this method does nothing.
*/
static void rethrowIfBlackListed(Throwable exception) {
if (blacklist.stream().anyMatch(exceptionType -> exceptionType.isInstance(exception))) {
ExceptionUtils.throwAsRuntimeException(exception);
}
}

}
Expand Up @@ -10,6 +10,8 @@

package org.junit.gen5.engine;

import static org.junit.gen5.engine.BlacklistedExceptions.rethrowIfBlackListed;

import org.junit.gen5.engine.Node.SkipResult;

/**
Expand Down Expand Up @@ -52,7 +54,9 @@ private void executeAll(TestDescriptor testDescriptor, C parentContext) {
}
}
catch (Throwable throwable) {
//TODO: Is this what we want?
rethrowIfBlackListed(throwable);

// TODO Is this what we want?
listener.executionStarted(testDescriptor);
listener.executionFinished(testDescriptor, TestExecutionResult.failed(throwable));
return;
Expand Down
Expand Up @@ -10,6 +10,7 @@

package org.junit.gen5.engine;

import static org.junit.gen5.engine.BlacklistedExceptions.rethrowIfBlackListed;
import static org.junit.gen5.engine.TestExecutionResult.aborted;
import static org.junit.gen5.engine.TestExecutionResult.failed;
import static org.junit.gen5.engine.TestExecutionResult.successful;
Expand All @@ -21,21 +22,22 @@
*/
class SingleTestExecutor {

interface TestExecutable {
interface Executable {

void execute() throws Exception;

}

TestExecutionResult executeSafely(TestExecutable test) {
TestExecutionResult executeSafely(Executable executable) {
try {
test.execute();
executable.execute();
return successful();
}
catch (TestAbortedException e) {
return aborted(e);
}
catch (Throwable t) {
rethrowIfBlackListed(t);
return failed(t);
}
}
Expand Down
Expand Up @@ -12,9 +12,15 @@

import static org.junit.gen5.api.Assertions.assertSame;
import static org.junit.gen5.api.Assertions.assertTrue;
import static org.junit.gen5.api.Assertions.expectThrows;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.stub;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

import org.junit.gen5.api.BeforeEach;
import org.junit.gen5.api.Test;
Expand All @@ -24,7 +30,7 @@
import org.opentest4j.TestAbortedException;

/**
* Microtests that verify behavior of {@link HierarchicalTestExecutor}.
* Micro-tests that verify behavior of {@link HierarchicalTestExecutor}.
*/
public class HierarchicalTestExecutorTests {

Expand Down Expand Up @@ -154,7 +160,7 @@ public void skippingALeaf() throws Exception {
public void exceptionInShouldBeSkipped() throws Exception {

MyContainer child = spy(new MyContainer("child container"));
RuntimeException anException = new RuntimeException("in test");
RuntimeException anException = new RuntimeException("in skip");
stub(child.shouldBeSkipped(rootContext)).toThrow(anException);
root.addChild(child);

Expand Down Expand Up @@ -235,7 +241,7 @@ public void exceptionInContainerAfterAll() throws Exception {
@Test
public void exceptionInLeafExecute() throws Exception {

MyLeaf child = spy(new MyLeaf("child container"));
MyLeaf child = spy(new MyLeaf("leaf"));
RuntimeException anException = new RuntimeException("in test");
stub(child.execute(rootContext)).toThrow(anException);
root.addChild(child);
Expand Down Expand Up @@ -263,7 +269,7 @@ public void abortInContainerBeforeAll() throws Exception {

MyContainer child = spy(new MyContainer("child container"));
root.addChild(child);
TestAbortedException anAbortedException = new TestAbortedException("in test");
TestAbortedException anAbortedException = new TestAbortedException("in BeforeAll");
stub(root.beforeAll(rootContext)).toThrow(anAbortedException);

InOrder inOrder = inOrder(listener, root, child);
Expand All @@ -288,7 +294,7 @@ public void abortInContainerBeforeAll() throws Exception {
@Test
public void abortInLeafExecute() throws Exception {

MyLeaf child = spy(new MyLeaf("child container"));
MyLeaf child = spy(new MyLeaf("leaf"));
TestAbortedException anAbortedException = new TestAbortedException("in test");
stub(child.execute(rootContext)).toThrow(anAbortedException);
root.addChild(child);
Expand All @@ -311,6 +317,36 @@ public void abortInLeafExecute() throws Exception {
assertSame(childExecutionResult.getValue().getThrowable().get(), anAbortedException);
}

/**
* Verifies support for blacklisted exceptions.
*/
@Test
public void outOfMemoryErrorInShouldBeSkipped() throws Exception {
MyContainer child = spy(new MyContainer("child container"));
OutOfMemoryError outOfMemoryError = new OutOfMemoryError("in skip");
stub(child.shouldBeSkipped(rootContext)).toThrow(outOfMemoryError);
root.addChild(child);

Throwable actualException = expectThrows(OutOfMemoryError.class, () -> executor.execute());
assertSame(outOfMemoryError, actualException);
}

/**
* Verifies support for blacklisted exceptions.
*/
@Test
public void outOfMemoryErrorInLeafExecution() throws Exception {
MyLeaf child = spy(new MyLeaf("leaf"));
OutOfMemoryError outOfMemoryError = new OutOfMemoryError("in test");
stub(child.execute(rootContext)).toThrow(outOfMemoryError);
root.addChild(child);

Throwable actualException = expectThrows(OutOfMemoryError.class, () -> executor.execute());
assertSame(outOfMemoryError, actualException);
}

// -------------------------------------------------------------------

private static class MyEngineExecutionContext implements EngineExecutionContext {
}

Expand Down Expand Up @@ -370,4 +406,5 @@ private static class MyExecutor extends HierarchicalTestExecutor<MyEngineExecuti
super(request, rootContext);
}
}

}

0 comments on commit a02c0e2

Please sign in to comment.