package org.apache.maven.surefire.junitcore.pc;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import net.jcip.annotations.NotThreadSafe;
import org.apache.maven.surefire.report.ConsoleStream;
import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Stopwatch;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.core.AnyOf.anyOf;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.apache.maven.surefire.junitcore.pc.RangeMatcher.between;
import static org.junit.Assert.*;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
/**
* @author Tibor Digana (tibor17)
* @since 2.16
*/
public class ParallelComputerBuilderTest
{
private static final Object class1Lock = new Object();
private static volatile boolean beforeShutdown;
private static volatile Runnable shutdownTask;
private static final ConsoleStream logger = new DefaultDirectConsoleReporter( System.out );
@Rule
public final Stopwatch stopwatch = new Stopwatch() {};
private static void testKeepBeforeAfter( ParallelComputerBuilder builder, Class<?>... classes )
{
JUnitCore core = new JUnitCore();
for ( int round = 0; round < 5; round++ )
{
NothingDoingTest1.methods.clear();
Result result = core.run( builder.buildComputer(), classes );
assertTrue( result.wasSuccessful() );
Iterator<String> methods = NothingDoingTest1.methods.iterator();
for ( Class<?> clazz : classes )
{
String a = clazz.getName() + "#a()";
String b = clazz.getName() + "#b()";
assertThat( methods.next(), is( "init" ) );
assertThat( methods.next(), anyOf( is( a ), is( b ) ) );
assertThat( methods.next(), anyOf( is( a ), is( b ) ) );
assertThat( methods.next(), is( "deinit" ) );
}
}
}
@Before
public void beforeTest() throws InterruptedException {
Class1.maxConcurrentMethods = 0;
Class1.concurrentMethods = 0;
shutdownTask = null;
NotThreadSafeTest1.t = null;
NotThreadSafeTest2.t = null;
NotThreadSafeTest3.t = null;
NormalTest1.t = null;
NormalTest2.t = null;
System.gc();
Thread.sleep( 50L );
}
@Test
public void parallelMethodsReuseOneOrTwoThreads()
{
ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
parallelComputerBuilder.useOnePool( 4 );
// One thread because one suite: TestSuite, however the capacity is 5.
parallelComputerBuilder.parallelSuites( 5 );
// Two threads because TestSuite has two classes, however the capacity is 5.
parallelComputerBuilder.parallelClasses( 5 );
// One or two threads because one threads comes from '#useOnePool(4)'
// and next thread may be reused from finished class, however the capacity is 3.
parallelComputerBuilder.parallelMethods( 3 );
assertFalse( parallelComputerBuilder.isOptimized() );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer();
Result result = new JUnitCore().run( computer, TestSuite.class );
long timeSpent = stopwatch.runtime( MILLISECONDS );
assertThat( computer.getSuites().size(), is( 1 ) );
assertThat( computer.getClasses().size(), is( 0 ) );
assertThat( computer.getNestedClasses().size(), is( 2 ) );
assertThat( computer.getNestedSuites().size(), is( 0 ) );
assertFalse( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( 4 ) );
assertTrue( result.wasSuccessful() );
if ( Class1.maxConcurrentMethods == 1 )
{
assertThat( timeSpent, between( 1950, 2250 ) );
}
else if ( Class1.maxConcurrentMethods == 2 )
{
assertThat( timeSpent, between( 1450, 1750 ) );
}
else
{
fail();
}
}
@Test
public void suiteAndClassInOnePool()
{
ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
parallelComputerBuilder.useOnePool( 5 );
parallelComputerBuilder.parallelSuites( 5 );
parallelComputerBuilder.parallelClasses( 5 );
parallelComputerBuilder.parallelMethods( 3 );
assertFalse( parallelComputerBuilder.isOptimized() );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer();
Result result = new JUnitCore().run( computer, TestSuite.class, Class1.class );
long timeSpent = stopwatch.runtime( MILLISECONDS );
assertThat( computer.getSuites().size(), is( 1 ) );
assertThat( computer.getClasses().size(), is( 1 ) );
assertThat( computer.getNestedClasses().size(), is( 2 ) );
assertThat( computer.getNestedSuites().size(), is( 0 ) );
assertFalse( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( 5 ) );
assertTrue( result.wasSuccessful() );
assertThat( Class1.maxConcurrentMethods, is( 2 ) );
assertThat( timeSpent, anyOf( between( 1450, 1750 ), between( 1950, 2250 ), between( 2450, 2750 ) ) );
}
@Test
public void onePoolWithUnlimitedParallelMethods()
{
// see ParallelComputerBuilder Javadoc
ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
parallelComputerBuilder.useOnePool( 8 );
parallelComputerBuilder.parallelSuites( 2 );
parallelComputerBuilder.parallelClasses( 4 );
parallelComputerBuilder.parallelMethods();
assertFalse( parallelComputerBuilder.isOptimized() );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer();
Result result = new JUnitCore().run( computer, TestSuite.class, Class1.class );
long timeSpent = stopwatch.runtime( MILLISECONDS );
assertThat( computer.getSuites().size(), is( 1 ) );
assertThat( computer.getClasses().size(), is( 1 ) );
assertThat( computer.getNestedClasses().size(), is( 2 ) );
assertThat( computer.getNestedSuites().size(), is( 0 ) );
assertFalse( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( 8 ) );
assertTrue( result.wasSuccessful() );
assertThat( Class1.maxConcurrentMethods, is( 4 ) );
assertThat( timeSpent, between( 950, 1250 ) );
}
@Test
public void underflowParallelism()
{
ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
parallelComputerBuilder.useOnePool( 3 );
// One thread because one suite: TestSuite.
parallelComputerBuilder.parallelSuites( 5 );
// One thread because of the limitation which is bottleneck.
parallelComputerBuilder.parallelClasses( 1 );
// One thread remains from '#useOnePool(3)'.
parallelComputerBuilder.parallelMethods( 3 );
assertFalse( parallelComputerBuilder.isOptimized() );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer();
Result result = new JUnitCore().run( computer, TestSuite.class );
long timeSpent = stopwatch.runtime( MILLISECONDS );
assertThat( computer.getSuites().size(), is( 1 ) );
assertThat( computer.getClasses().size(), is( 0 ) );
assertThat( computer.getNestedClasses().size(), is( 2 ) );
assertThat( computer.getNestedSuites().size(), is( 0 ) );
assertFalse( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( 3 ) );
assertTrue( result.wasSuccessful() );
assertThat( Class1.maxConcurrentMethods, is( 1 ) );
assertThat( timeSpent, between( 1950, 2250 ) );
}
@Test
public void separatePoolsWithSuite()
{
ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
parallelComputerBuilder.parallelSuites( 5 );
parallelComputerBuilder.parallelClasses( 5 );
parallelComputerBuilder.parallelMethods( 3 );
assertFalse( parallelComputerBuilder.isOptimized() );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer();
Result result = new JUnitCore().run( computer, TestSuite.class );
long timeSpent = stopwatch.runtime( MILLISECONDS );
assertThat( computer.getSuites().size(), is( 1 ) );
assertThat( computer.getClasses().size(), is( 0 ) );
assertThat( computer.getNestedClasses().size(), is( 2 ) );
assertThat( computer.getNestedSuites().size(), is( 0 ) );
assertTrue( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( ParallelComputerBuilder.TOTAL_POOL_SIZE_UNDEFINED ) );
assertTrue( result.wasSuccessful() );
assertThat( Class1.maxConcurrentMethods, is( 3 ) );
assertThat( timeSpent, between( 950, 1250 ) );
}
@Test
public void separatePoolsWithSuiteAndClass()
{
ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
parallelComputerBuilder.parallelSuites( 5 );
parallelComputerBuilder.parallelClasses( 5 );
parallelComputerBuilder.parallelMethods( 3 );
assertFalse( parallelComputerBuilder.isOptimized() );
// 6 methods altogether.
// 2 groups with 3 threads.
// Each group takes 0.5s.
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer();
Result result = new JUnitCore().run( computer, TestSuite.class, Class1.class );
long timeSpent = stopwatch.runtime( MILLISECONDS );
assertThat( computer.getSuites().size(), is( 1 ) );
assertThat( computer.getClasses().size(), is( 1 ) );
assertThat( computer.getNestedClasses().size(), is( 2 ) );
assertThat( computer.getNestedSuites().size(), is( 0 ) );
assertTrue( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( ParallelComputerBuilder.TOTAL_POOL_SIZE_UNDEFINED ) );
assertTrue( result.wasSuccessful() );
assertThat( Class1.maxConcurrentMethods, is( 3 ) );
assertThat( timeSpent, between( 950, 1250 ) );
}
@Test
public void separatePoolsWithSuiteAndSequentialClasses()
{
ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
parallelComputerBuilder.parallelSuites( 5 );
parallelComputerBuilder.parallelClasses( 1 );
parallelComputerBuilder.parallelMethods( 3 );
assertFalse( parallelComputerBuilder.isOptimized() );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer();
Result result = new JUnitCore().run( computer, TestSuite.class, Class1.class );
long timeSpent = stopwatch.runtime( MILLISECONDS );
assertThat( computer.getSuites().size(), is( 1 ) );
assertThat( computer.getClasses().size(), is( 1 ) );
assertThat( computer.getNestedClasses().size(), is( 2 ) );
assertThat( computer.getNestedSuites().size(), is( 0 ) );
assertTrue( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( ParallelComputerBuilder.TOTAL_POOL_SIZE_UNDEFINED ) );
assertTrue( result.wasSuccessful() );
assertThat( Class1.maxConcurrentMethods, is( 2 ) );
assertThat( timeSpent, between( 1450, 1750 ) );
}
@Test( timeout = 2000 )
public void shutdown()
{
Result result = new ShutdownTest().run( false );
long timeSpent = stopwatch.runtime( MILLISECONDS );
assertTrue( result.wasSuccessful() );
assertTrue( beforeShutdown );
assertThat( timeSpent, between( 450, 1250 ) );
}
@Test( timeout = 2000 )
public void shutdownWithInterrupt()
{
new ShutdownTest().run( true );
long timeSpent = stopwatch.runtime( MILLISECONDS );
assertTrue( beforeShutdown );
assertThat( timeSpent, between( 450, 1250 ) );
}
@Test
public void nothingParallel()
{
JUnitCore core = new JUnitCore();
ParallelComputerBuilder builder = new ParallelComputerBuilder( logger );
assertFalse( builder.isOptimized() );
Result result = core.run( builder.buildComputer(), NothingDoingTest1.class, NothingDoingTest2.class );
assertTrue( result.wasSuccessful() );
result = core.run( builder.buildComputer(), NothingDoingTest1.class, NothingDoingSuite.class );
assertTrue( result.wasSuccessful() );
builder.useOnePool( 1 );
assertFalse( builder.isOptimized() );
result = core.run( builder.buildComputer(), NothingDoingTest1.class, NothingDoingTest2.class );
assertTrue( result.wasSuccessful() );
builder.useOnePool( 1 );
assertFalse( builder.isOptimized() );
result = core.run( builder.buildComputer(), NothingDoingTest1.class, NothingDoingSuite.class );
assertTrue( result.wasSuccessful() );
builder.useOnePool( 2 );
assertFalse( builder.isOptimized() );
result = core.run( builder.buildComputer(), NothingDoingTest1.class, NothingDoingSuite.class );
assertTrue( result.wasSuccessful() );
Class<?>[] classes = { NothingDoingTest1.class, NothingDoingSuite.class };
builder.useOnePool( 2 ).parallelSuites( 1 ).parallelClasses( 1 );
assertFalse( builder.isOptimized() );
result = core.run( builder.buildComputer(), classes );
assertTrue( result.wasSuccessful() );
builder.useOnePool( 2 ).parallelSuites( 1 ).parallelClasses();
assertFalse( builder.isOptimized() );
result = core.run( builder.buildComputer(), classes );
assertTrue( result.wasSuccessful() );
classes = new Class<?>[]{ NothingDoingSuite.class, NothingDoingSuite.class, NothingDoingTest1.class,
NothingDoingTest2.class, NothingDoingTest3.class };
builder.useOnePool( 2 ).parallelSuites( 1 ).parallelClasses( 1 );
assertFalse( builder.isOptimized() );
result = core.run( builder.buildComputer(), classes );
assertTrue( result.wasSuccessful() );
builder.useOnePool( 2 ).parallelSuites( 1 ).parallelClasses();
assertFalse( builder.isOptimized() );
result = core.run( builder.buildComputer(), classes );
assertTrue( result.wasSuccessful() );
}
@Test
public void keepBeforeAfterOneClass()
{
ParallelComputerBuilder builder = new ParallelComputerBuilder( logger );
builder.parallelMethods();
assertFalse( builder.isOptimized() );
testKeepBeforeAfter( builder, NothingDoingTest1.class );
}
@Test
public void keepBeforeAfterTwoClasses()
{
ParallelComputerBuilder builder = new ParallelComputerBuilder( logger );
builder.useOnePool( 5 ).parallelClasses( 1 ).parallelMethods( 2 );
assertFalse( builder.isOptimized() );
testKeepBeforeAfter( builder, NothingDoingTest1.class, NothingDoingTest2.class );
}
@Test
public void keepBeforeAfterTwoParallelClasses()
{
ParallelComputerBuilder builder = new ParallelComputerBuilder( logger );
builder.useOnePool( 8 ).parallelClasses( 2 ).parallelMethods( 2 );
assertFalse( builder.isOptimized() );
JUnitCore core = new JUnitCore();
NothingDoingTest1.methods.clear();
Class<?>[] classes = { NothingDoingTest1.class, NothingDoingTest2.class, NothingDoingTest3.class };
Result result = core.run( builder.buildComputer(), classes );
assertTrue( result.wasSuccessful() );
ArrayList<String> methods = new ArrayList<String>( NothingDoingTest1.methods );
assertThat( methods.size(), is( 12 ) );
assertThat( methods.subList( 9, 12 ), is( not( Arrays.asList( "deinit", "deinit", "deinit" ) ) ) );
}
@Test
public void notThreadSafeTest()
{
ParallelComputerBuilder builder = new ParallelComputerBuilder( logger )
.useOnePool( 6 ).optimize( true ).parallelClasses( 3 ).parallelMethods( 3 );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer();
Result result = new JUnitCore().run( computer, NotThreadSafeTest1.class, NotThreadSafeTest2.class );
assertTrue( result.wasSuccessful() );
assertThat( result.getRunCount(), is( 2 ) );
assertNotNull( NotThreadSafeTest1.t );
assertNotNull( NotThreadSafeTest2.t );
assertSame( NotThreadSafeTest1.t, NotThreadSafeTest2.t );
assertThat( computer.getNotParallelRunners().size(), is( 2 ) );
assertTrue( computer.getSuites().isEmpty() );
assertTrue( computer.getClasses().isEmpty() );
assertTrue( computer.getNestedClasses().isEmpty() );
assertTrue( computer.getNestedSuites().isEmpty() );
assertFalse( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( 6 ) );
}
@Test
public void mixedThreadSafety()
{
ParallelComputerBuilder builder = new ParallelComputerBuilder( logger )
.useOnePool( 6 ).optimize( true ).parallelClasses( 3 ).parallelMethods( 3 );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer();
Result result = new JUnitCore().run( computer, NotThreadSafeTest1.class, NormalTest1.class );
assertTrue( result.wasSuccessful() );
assertThat( result.getRunCount(), is( 2 ) );
assertNotNull( NotThreadSafeTest1.t );
assertNotNull( NormalTest1.t );
assertThat( NormalTest1.t.getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
assertNotSame( NotThreadSafeTest1.t, NormalTest1.t );
assertThat( computer.getNotParallelRunners().size(), is( 1 ) );
assertTrue( computer.getSuites().isEmpty() );
assertThat( computer.getClasses().size(), is( 1 ) );
assertTrue( computer.getNestedClasses().isEmpty() );
assertTrue( computer.getNestedSuites().isEmpty() );
assertFalse( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( 6 ) );
}
@Test
public void notThreadSafeTestsInSuite()
{
ParallelComputerBuilder builder = new ParallelComputerBuilder( logger )
.useOnePool( 5 ).parallelMethods( 3 );
assertFalse( builder.isOptimized() );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer();
Result result = new JUnitCore().run( computer, NotThreadSafeTestSuite.class );
assertTrue( result.wasSuccessful() );
assertNotNull( NormalTest1.t );
assertNotNull( NormalTest2.t );
assertSame( NormalTest1.t, NormalTest2.t );
assertThat( NormalTest1.t.getName(), is( "maven-surefire-plugin@NotThreadSafe" ) );
assertThat( NormalTest2.t.getName(), is( "maven-surefire-plugin@NotThreadSafe" ) );
assertThat( computer.getNotParallelRunners().size(), is( 1 ) );
assertTrue( computer.getSuites().isEmpty() );
assertTrue( computer.getClasses().isEmpty() );
assertTrue( computer.getNestedClasses().isEmpty() );
assertTrue( computer.getNestedSuites().isEmpty() );
assertFalse( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( 5 ) );
}
@Test
public void mixedThreadSafetyInSuite()
{
ParallelComputerBuilder builder = new ParallelComputerBuilder( logger )
.useOnePool( 10 ).optimize( true ).parallelSuites( 2 ).parallelClasses( 3 ).parallelMethods( 3 );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer();
Result result = new JUnitCore().run( computer, MixedSuite.class );
assertTrue( result.wasSuccessful() );
assertThat( result.getRunCount(), is( 2 ) );
assertNotNull( NotThreadSafeTest1.t );
assertNotNull( NormalTest1.t );
assertThat( NormalTest1.t.getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
assertNotSame( NotThreadSafeTest1.t, NormalTest1.t );
assertTrue( computer.getNotParallelRunners().isEmpty() );
assertThat( computer.getSuites().size(), is( 1 ) );
assertTrue( computer.getClasses().isEmpty() );
assertThat( computer.getNestedClasses().size(), is( 1 ) );
assertTrue( computer.getNestedSuites().isEmpty() );
assertFalse( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( 10 ) );
}
@Test
public void inheritanceWithNotThreadSafe()
{
ParallelComputerBuilder builder = new ParallelComputerBuilder( logger )
.useOnePool( 10 ).optimize( true ).parallelSuites( 2 ).parallelClasses( 3 ).parallelMethods( 3 );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer();
Result result = new JUnitCore().run( computer, OverMixedSuite.class );
assertTrue( result.wasSuccessful() );
assertThat( result.getRunCount(), is( 2 ) );
assertNotNull( NotThreadSafeTest3.t );
assertNotNull( NormalTest1.t );
assertThat( NormalTest1.t.getName(), is( "maven-surefire-plugin@NotThreadSafe" ) );
assertSame( NotThreadSafeTest3.t, NormalTest1.t );
assertThat( computer.getNotParallelRunners().size(), is( 1 ) );
assertTrue( computer.getSuites().isEmpty() );
assertTrue( computer.getClasses().isEmpty() );
assertTrue( computer.getNestedClasses().isEmpty() );
assertTrue( computer.getNestedSuites().isEmpty() );
assertFalse( computer.isSplitPool() );
assertThat( computer.getPoolCapacity(), is( 10 ) );
}
@Test
public void beforeAfterThreadChanges()
throws InterruptedException
{
// try to GC dead Thread objects from previous tests
for ( int i = 0; i < 5; i++ )
{
System.gc();
TimeUnit.MILLISECONDS.sleep( 500 );
}
Collection<Thread> expectedThreads = jvmThreads();
ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger );
parallelComputerBuilder.parallelMethods( 3 );
ParallelComputer computer = parallelComputerBuilder.buildComputer();
Result result = new JUnitCore().run( computer, TestWithBeforeAfter.class );
assertTrue( result.wasSuccessful() );
// try to GC dead Thread objects
for ( int i = 0; i < 5 && expectedThreads.size() != jvmThreads().size(); i++ )
{
System.gc();
TimeUnit.MILLISECONDS.sleep( 500 );
}
assertThat( jvmThreads(), is( expectedThreads ) );
}
private static Collection<Thread> jvmThreads()
{
Thread[] t = new Thread[1000];
Thread.enumerate( t );
ArrayList<Thread> appThreads = new ArrayList<Thread>( t.length );
Collections.addAll( appThreads, t );
appThreads.removeAll( Collections.singleton( (Thread) null ) );
Collections.sort( appThreads, new Comparator<Thread>()
{
@Override
public int compare( Thread t1, Thread t2 )
{
return (int) Math.signum( t1.getId() - t2.getId() );
}
} );
return appThreads;
}
private static class ShutdownTest
{
Result run( final boolean useInterrupt )
{
ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger )
.useOnePool( 8 )
.parallelSuites( 2 )
.parallelClasses( 3 )
.parallelMethods( 3 );
assertFalse( parallelComputerBuilder.isOptimized() );
final ParallelComputerBuilder.PC computer =
(ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer();
shutdownTask = new Runnable()
{
@Override
public void run()
{
Collection<Description> startedTests = computer.describeStopped( useInterrupt ).getTriggeredTests();
assertThat( startedTests.size(), is( not( 0 ) ) );
}
};
return new JUnitCore().run( computer, TestSuite.class, Class2.class, Class3.class );
}
}
public static class Class1
{
static volatile int concurrentMethods = 0;
static volatile int maxConcurrentMethods = 0;
@Test
public void test1()
throws InterruptedException
{
synchronized ( class1Lock )
{
++concurrentMethods;
class1Lock.wait( 500 );
maxConcurrentMethods = Math.max( maxConcurrentMethods, concurrentMethods-- );
}
}
@Test
public void test2()
throws InterruptedException
{
test1();
Runnable shutdownTask = ParallelComputerBuilderTest.shutdownTask;
if ( shutdownTask != null )
{
beforeShutdown = true;
shutdownTask.run();
}
}
}
public static class Class2
extends Class1
{
}
public static class Class3
extends Class1
{
}
public static class NothingDoingTest1
{
static final Collection<String> methods = new ConcurrentLinkedQueue<String>();
@BeforeClass
public static void init()
{
methods.add( "init" );
}
@AfterClass
public static void deinit()
{
methods.add( "deinit" );
}
@Test
public void a()
throws InterruptedException
{
Thread.sleep( 5 );
methods.add( getClass().getName() + "#a()" );
}
@Test
public void b()
throws InterruptedException
{
Thread.sleep( 5 );
methods.add( getClass().getName() + "#b()" );
}
}
public static class NothingDoingTest2
extends NothingDoingTest1
{
}
public static class NothingDoingTest3
extends NothingDoingTest1
{
}
@RunWith( Suite.class )
@Suite.SuiteClasses( { NothingDoingTest1.class, NothingDoingTest2.class } )
public static class NothingDoingSuite
{
}
@RunWith( Suite.class )
@Suite.SuiteClasses( { Class2.class, Class1.class } )
public static class TestSuite
{
}
@NotThreadSafe
public static class NotThreadSafeTest1
{
static volatile Thread t;
@BeforeClass
public static void beforeSuite()
{
assertThat( Thread.currentThread().getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
}
@AfterClass
public static void afterSuite()
{
assertThat( Thread.currentThread().getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
}
@Test
public void test()
{
t = Thread.currentThread();
assertThat( t.getName(), is( "maven-surefire-plugin@NotThreadSafe" ) );
}
}
@NotThreadSafe
public static class NotThreadSafeTest2
{
static volatile Thread t;
@BeforeClass
public static void beforeSuite()
{
assertThat( Thread.currentThread().getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
}
@AfterClass
public static void afterSuite()
{
assertThat( Thread.currentThread().getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
}
@Test
public void test()
{
t = Thread.currentThread();
assertThat( t.getName(), is( "maven-surefire-plugin@NotThreadSafe" ) );
}
}
@NotThreadSafe
public static class NotThreadSafeTest3
{
static volatile Thread t;
@Test
public void test()
{
t = Thread.currentThread();
assertThat( t.getName(), is( "maven-surefire-plugin@NotThreadSafe" ) );
}
}
@RunWith( Suite.class )
@Suite.SuiteClasses( { NormalTest1.class, NormalTest2.class } )
@NotThreadSafe
public static class NotThreadSafeTestSuite
{
@BeforeClass
public static void beforeSuite()
{
assertThat( Thread.currentThread().getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
}
@AfterClass
public static void afterSuite()
{
assertThat( Thread.currentThread().getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
}
}
public static class NormalTest1
{
static volatile Thread t;
@Test
public void test()
{
t = Thread.currentThread();
}
}
public static class NormalTest2
{
static volatile Thread t;
@Test
public void test()
{
t = Thread.currentThread();
}
}
@RunWith( Suite.class )
@Suite.SuiteClasses( { NotThreadSafeTest1.class, NormalTest1.class } )
public static class MixedSuite
{
@BeforeClass
public static void beforeSuite()
{
assertThat( Thread.currentThread().getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
}
@AfterClass
public static void afterSuite()
{
assertThat( Thread.currentThread().getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
}
}
@RunWith( Suite.class )
@Suite.SuiteClasses( { NotThreadSafeTest3.class, NormalTest1.class } )
@NotThreadSafe
public static class OverMixedSuite
{
@BeforeClass
public static void beforeSuite()
{
assertThat( Thread.currentThread().getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
}
@AfterClass
public static void afterSuite()
{
assertThat( Thread.currentThread().getName(), is( not( "maven-surefire-plugin@NotThreadSafe" ) ) );
}
}
public static class TestWithBeforeAfter
{
@BeforeClass
public static void beforeClass()
throws InterruptedException
{
System.out.println( new Date() + " BEG: beforeClass" );
TimeUnit.SECONDS.sleep( 1 );
System.out.println( new Date() + " END: beforeClass" );
}
@Before
public void before()
throws InterruptedException
{
System.out.println( new Date() + " BEG: before" );
TimeUnit.SECONDS.sleep( 1 );
System.out.println( new Date() + " END: before" );
}
@Test
public void test()
throws InterruptedException
{
System.out.println( new Date() + " BEG: test" );
TimeUnit.SECONDS.sleep( 1 );
System.out.println( new Date() + " END: test" );
}
@After
public void after()
throws InterruptedException
{
System.out.println( new Date() + " BEG: after" );
TimeUnit.SECONDS.sleep( 1 );
System.out.println( new Date() + " END: after" );
}
@AfterClass
public static void afterClass()
throws InterruptedException
{
System.out.println( new Date() + " BEG: afterClass" );
TimeUnit.SECONDS.sleep( 1 );
System.out.println( new Date() + " END: afterClass" );
}
}
}