All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.anarsoft.vmlens.concurrent.junit.ConcurrentTestRunner Maven / Gradle / Ivy

The newest version!
package com.anarsoft.vmlens.concurrent.junit;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;







import org.junit.After;
import org.junit.Before;
import org.junit.internal.runners.model.EachTestNotifier;
import org.junit.internal.runners.model.ReflectiveCallable;
import org.junit.internal.runners.statements.Fail;
import org.junit.rules.RunRules;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;

import com.anarsoft.vmlens.concurrent.junit.internal.ConcurrentStatement;
import com.anarsoft.vmlens.concurrent.junit.internal.InvokeListOfMethods;
import com.anarsoft.vmlens.concurrent.junit.internal.NoOpStatement;
import com.anarsoft.vmlens.concurrent.junit.internal.ParallelExecutorThread;
import com.anarsoft.vmlens.concurrent.junit.internal.TestResult;



/**
 * 

A JUnit test runner to run concurrent unit tests. Runs the tests of one test class in the following order: *

*
    *
  1. Runs methods marked with org.junit.Before annotation in the main thread.
  2. *
  3. Runs methods marked with org.junit.Test annotation. Each method is run in 4 parallel threads.
  4. *
  5. Runs methods marked with org.junit.After annotation in the main thread.
  6. *
*

* Most useful when using a dynamic race condition catcher like vmlens.

* * * @author Thomas * */ public class ConcurrentTestRunner extends BlockJUnit4ClassRunner { public ConcurrentTestRunner(Class klass) throws InitializationError { super(klass); } private boolean alreadyRun = false; protected Statement childrenInvoker(final RunNotifier notifier) { return new Statement() { @Override public void evaluate() { runChildrenConcurrently(notifier); } }; } private void runChildrenConcurrently(final RunNotifier notifier) { if(alreadyRun) { return; } alreadyRun = true; List eachTestNotifierList = new LinkedList(); List concurrentStatementList = new LinkedList(); Object test; try { test = new ReflectiveCallable() { @Override protected Object runReflectiveCall() throws Throwable { return createTest(); } }.run(); } catch (Throwable e) { for (FrameworkMethod method : getChildren()) { Description description = describeChild(method); notifier.fireTestFailure(new Failure(description , e)); } return; } for (FrameworkMethod method : getChildren()) { Description description = describeChild(method); if (callIsIgnoredWithReflection(method)) { notifier.fireTestIgnored(description); } else { EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description); eachNotifier.fireTestStarted(); eachTestNotifierList.add(eachNotifier); Statement st = createMethodStatement( method, test); ThreadCount threadCountAnnotation = method.getAnnotation(ThreadCount.class); int threadCount = 4; if( threadCountAnnotation != null ) { threadCount = threadCountAnnotation.value(); } for( int i = 0 ; i < threadCount ; i++ ) { concurrentStatementList.add(new ConcurrentStatement(st,eachNotifier)); } } } Statement before = createBefores( test); evaluateStatement(before , eachTestNotifierList ); List threadList = new LinkedList(); for( ConcurrentStatement st : concurrentStatementList ) { ParallelExecutorThread t = new ParallelExecutorThread(st); threadList.add(t); t.start(); } int stillRunningThreads = 0; for( ParallelExecutorThread t : threadList ) { try { t.join(30 * 5 * 1000); if( t.isAlive() ) { stillRunningThreads++; t.interrupt(); } } catch( Exception e) { e.printStackTrace(); } } if(stillRunningThreads > 0) { System.err.println("still running threads: "+ stillRunningThreads ); } else { for( ConcurrentStatement st : concurrentStatementList ) { st.addFailures(); } Statement after = createAfters( test); evaluateStatement(after , eachTestNotifierList ); } for( EachTestNotifier eachTestNotifier : eachTestNotifierList ) { eachTestNotifier.fireTestFinished(); } } private boolean callIsIgnoredWithReflection(FrameworkMethod method) { Method m; try { m = BlockJUnit4ClassRunner.class.getDeclaredMethod("isIgnored", FrameworkMethod.class); } catch (NoSuchMethodException e) { return false; } catch (SecurityException e) { return false; } try { return ((Boolean) m.invoke(this, method)).booleanValue(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return false; } private void evaluateStatement(Statement statement ,List eachTestNotifierList ) { TestResult testResult = ConcurrentStatement.evaluateStatement( statement); for( EachTestNotifier eachTestNotifier : eachTestNotifierList ) { testResult.addFailure(eachTestNotifier); } } private List getMethodRules(Object target) { return rules(target); } private Statement withTestRules(FrameworkMethod method, List testRules, Statement statement) { return testRules.isEmpty() ? statement : new RunRules(statement, testRules, describeChild(method)); } private Statement withRules(FrameworkMethod method, Object target, Statement statement) { List testRules = getTestRules(target); Statement result = statement; result = withMethodRules(method, testRules, target, result); result = withTestRules(method, testRules, result); return result; } private Statement withMethodRules(FrameworkMethod method, List testRules, Object target, Statement result) { for (org.junit.rules.MethodRule each : getMethodRules(target)) { if (!testRules.contains(each)) { result = each.apply(result, method, target); } } return result; } protected Statement createMethodStatement( FrameworkMethod method, Object test) { Statement statement; try { statement = methodInvoker(method, test); statement = possiblyExpectingExceptions(method, test, statement); statement = withRules(method, test, statement); } catch (Throwable ex) { statement = new Fail(ex); } return statement; } protected Statement createBefores( Object target) { List befores = getTestClass().getAnnotatedMethods( Before.class); return befores.isEmpty() ? new NoOpStatement() : new InvokeListOfMethods( befores, target); } protected Statement createAfters(Object target) { List afters = getTestClass().getAnnotatedMethods( After.class); return afters.isEmpty() ? new NoOpStatement() : new InvokeListOfMethods( afters, target); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy