001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.junit; 018 019import java.util.concurrent.TimeUnit; 020 021import org.junit.Test; 022import org.junit.internal.runners.statements.FailOnTimeout; 023import org.junit.runners.BlockJUnit4ClassRunner; 024import org.junit.runners.model.FrameworkMethod; 025import org.junit.runners.model.InitializationError; 026import org.junit.runners.model.Statement; 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029 030/** 031 * A Custom JUnit test runner for customizing JUnit tests run in ActiveMQ. 032 */ 033public class ActiveMQTestRunner extends BlockJUnit4ClassRunner { 034 035 private static final Logger LOG = LoggerFactory.getLogger(ActiveMQTestRunner.class); 036 037 public ActiveMQTestRunner(Class<?> klass) throws InitializationError { 038 super(klass); 039 } 040 041 @Override 042 protected Statement methodBlock(final FrameworkMethod method) { 043 Statement statement = super.methodBlock(method); 044 045 // Check for repeats needed 046 statement = withPotentialRepeat(method, statement); 047 048 return statement; 049 } 050 051 /** 052 * Perform the same logic as 053 * {@link BlockJUnit4ClassRunner#withPotentialTimeout(FrameworkMethod, Object, Statement)} 054 * but with additional support for changing the coded timeout with an extended value. 055 * 056 * @return either a {@link FailOnTimeout}, or the supplied {@link Statement} as appropriate. 057 */ 058 @SuppressWarnings("deprecation") 059 @Override 060 protected Statement withPotentialTimeout(FrameworkMethod frameworkMethod, Object testInstance, Statement next) { 061 long testTimeout = getOriginalTimeout(frameworkMethod); 062 063 if (testTimeout > 0) { 064 String multiplierString = System.getProperty("org.apache.activemq.junit.testTimeoutMultiplier"); 065 double multiplier = 0.0; 066 067 try { 068 multiplier = Double.parseDouble(multiplierString); 069 } catch (NullPointerException npe) { 070 } catch (NumberFormatException nfe) { 071 LOG.warn("Ignoring testTimeoutMultiplier not set to a valid value: " + multiplierString); 072 } 073 074 if (multiplier > 0.0) { 075 LOG.info("Test timeout multiple {} applied to test timeout {}ms: new timeout = {}", 076 multiplier, testTimeout, (long) (testTimeout * multiplier)); 077 testTimeout = (long) (testTimeout * multiplier); 078 } 079 080 next = FailOnTimeout.builder(). 081 withTimeout(testTimeout, TimeUnit.MILLISECONDS).build(next); 082 } else { 083 next = super.withPotentialTimeout(frameworkMethod, testInstance, next); 084 } 085 086 return next; 087 } 088 089 /** 090 * Check for the presence of a {@link Repeat} annotation and return a {@link RepeatStatement} 091 * to handle executing the test repeated or the original value if not repeating. 092 * 093 * @return either a {@link RepeatStatement}, or the supplied {@link Statement} as appropriate. 094 */ 095 protected Statement withPotentialRepeat(FrameworkMethod frameworkMethod, Statement next) { 096 097 Repeat repeatAnnotation = frameworkMethod.getAnnotation(Repeat.class); 098 099 if (repeatAnnotation != null) { 100 next = RepeatStatement.builder().build(repeatAnnotation, next); 101 } 102 103 return next; 104 } 105 106 /** 107 * Retrieve the original JUnit {@code timeout} from the {@link Test @Test} 108 * annotation on the incoming {@linkplain FrameworkMethod test method}. 109 * 110 * @return the timeout, or {@code 0} if none was specified 111 */ 112 protected long getOriginalTimeout(FrameworkMethod frameworkMethod) { 113 Test test = frameworkMethod.getAnnotation(Test.class); 114 return (test != null && test.timeout() > 0 ? test.timeout() : 0); 115 } 116}