001/*002 * Copyright 2002-2018 the original author or authors.003 *004 * Licensed under the Apache License, Version 2.0 (the "License");005 * you may not use this file except in compliance with the License.006 * You may obtain a copy of the License at007 *008 * https://www.apache.org/licenses/LICENSE-2.0009 *010 * Unless required by applicable law or agreed to in writing, software011 * distributed under the License is distributed on an "AS IS" BASIS,012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.013 * See the License for the specific language governing permissions and014 * limitations under the License.015 */016017package org.springframework.test.context.junit4.statements;018019import java.lang.reflect.Method;020import java.util.concurrent.TimeoutException;021022import org.junit.runners.model.Statement;023024import org.springframework.test.annotation.TestAnnotationUtils;025import org.springframework.util.Assert;026027/**028 * {@code SpringFailOnTimeout} is a custom JUnit {@link Statement} which adds029 * support for Spring's {@link org.springframework.test.annotation.Timed @Timed}030 * annotation by throwing an exception if the next statement in the execution031 * chain takes more than the specified number of milliseconds.032 *033 * <p>In contrast to JUnit's034 * {@link org.junit.internal.runners.statements.FailOnTimeout FailOnTimeout},035 * the next {@code statement} will be executed in the same thread as the036 * caller and will therefore not be aborted preemptively.037 *038 * @author Sam Brannen039 * @since 3.0040 * @see #evaluate()041 */042public class SpringFailOnTimeout extends Statement {043044 private final Statement next;045046 private final long timeout;047048049 /**050 * Construct a new {@code SpringFailOnTimeout} statement for the supplied051 * {@code testMethod}, retrieving the configured timeout from the052 * {@code @Timed} annotation on the supplied method.053 * @param next the next {@code Statement} in the execution chain054 * @param testMethod the current test method055 * @see TestAnnotationUtils#getTimeout(Method)056 */057 public SpringFailOnTimeout(Statement next, Method testMethod) {058 this(next, TestAnnotationUtils.getTimeout(testMethod));059 }060061 /**062 * Construct a new {@code SpringFailOnTimeout} statement for the supplied063 * {@code timeout}.064 * <p>If the supplied {@code timeout} is {@code 0}, the execution of the065 * {@code next} statement will not be timed.066 * @param next the next {@code Statement} in the execution chain; never {@code null}067 * @param timeout the configured {@code timeout} for the current test, in milliseconds;068 * never negative069 */070 public SpringFailOnTimeout(Statement next, long timeout) {071 Assert.notNull(next, "next statement must not be null");072 Assert.isTrue(timeout >= 0, "timeout must be non-negative");073 this.next = next;07