blob: 0855aa7aafd568cbba77ff855053779de9d13efd [file] [log] [blame]
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.api.report.ConsoleStream;
import org.apache.maven.surefire.api.report.DefaultDirectConsoleReporter;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.RunWith;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.ParentRunner;
import org.junit.runners.Suite;
import org.junit.runners.model.InitializationError;
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.List;
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.fail;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
/**
* @author Tibor Digana (tibor17)
* @since 2.16
*/
@SuppressWarnings( "checkstyle:magicnumber" )
public class ParallelComputerBuilderTest
{
private static final int DELAY_MULTIPLIER = 7;
private static final Object CLASS1BLOCK = new Object();
private static volatile boolean beforeShutdown;
private static volatile Runnable shutdownTask;
private static final ConsoleStream LOGGER = new DefaultDirectConsoleReporter( System.out );
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" ) );
}
}
}
@BeforeClass
public static void cleanup() throws InterruptedException
{
System.gc();
Thread.sleep( 500L );
}
@Before
public void beforeTest()
{
Class1.maxConcurrentMethods = 0;
Class1.concurrentMethods = 0;
shutdownTask = null;
NotThreadSafeTest1.t = null;
NotThreadSafeTest2.t = null;
NotThreadSafeTest3.t = null;
NormalTest1.t = null;
NormalTest2.t = null;
}
@Test
public void testsWithoutChildrenShouldAlsoBeRun()
{
ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER );
ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer();
Result result = new JUnitCore().run( computer, TestWithoutPrecalculatedChildren.class );
assertThat( result.getRunCount(), is( 1 ) );
}
@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();
final JUnitCore core = new JUnitCore();
final long t1 = systemMillis();
final Result result = core.run( computer, TestSuite.class );
final long t2 = systemMillis();
final long timeSpent = t2 - t1;
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( 2000 * DELAY_MULTIPLIER - 50, 2250 * DELAY_MULTIPLIER ) );
}
else if ( Class1.maxConcurrentMethods == 2 )
{
assertThat( timeSpent, between( 1500 * DELAY_MULTIPLIER - 50, 1750 * DELAY_MULTIPLIER ) );
}
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();
final JUnitCore core = new JUnitCore();
final long t1 = systemMillis();
final Result result = core.run( computer, TestSuite.class, Class1.class );
final long t2 = systemMillis();
final long timeSpent = t2 - t1;
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( 1500 * DELAY_MULTIPLIER - 50, 1750 * DELAY_MULTIPLIER ),
between( 2000 * DELAY_MULTIPLIER - 50, 2250 * DELAY_MULTIPLIER ),
between( 2500 * DELAY_MULTIPLIER - 50, 2750 * DELAY_MULTIPLIER ) ) );
}
@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();
final JUnitCore core = new JUnitCore();
final long t1 = systemMillis();
final Result result = core.run( computer, TestSuite.class, Class1.class );
final long t2 = systemMillis();
final long timeSpent = t2 - t1;
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( 1000 * DELAY_MULTIPLIER - 50, 1250 * DELAY_MULTIPLIER ) );
}
@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();
final JUnitCore core = new JUnitCore();
final long t1 = systemMillis();
final Result result = core.run( computer, TestSuite.class );
final long t2 = systemMillis();
final long timeSpent = t2 - t1;
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( 2000 * DELAY_MULTIPLIER - 50, 2250 * DELAY_MULTIPLIER ) );
}
@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();
final JUnitCore core = new JUnitCore();
final long t1 = systemMillis();
final Result result = core.run( computer, TestSuite.class );
final long t2 = systemMillis();
final long timeSpent = t2 - t1;
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( 1000 * DELAY_MULTIPLIER - 50, 1250 * DELAY_MULTIPLIER ) );
}
@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();
final JUnitCore core = new JUnitCore();
final long t1 = systemMillis();
final Result result = core.run( computer, TestSuite.class, Class1.class );
final long t2 = systemMillis();
final long timeSpent = t2 - t1;
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( 1000 * DELAY_MULTIPLIER - 50, 1250 * DELAY_MULTIPLIER ) );
}
@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();
final JUnitCore core = new JUnitCore();
final long t1 = systemMillis();
final Result result = core.run( computer, TestSuite.class, Class1.class );
final long t2 = systemMillis();
final long timeSpent = t2 - t1;
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( 1500 * DELAY_MULTIPLIER - 50, 1750 * DELAY_MULTIPLIER ) );
}
@Test( timeout = 2000 * DELAY_MULTIPLIER )
public void shutdown()
{
final long t1 = systemMillis();
final Result result = new ShutdownTest().run( false );
final long t2 = systemMillis();
final long timeSpent = t2 - t1;
assertTrue( result.wasSuccessful() );
assertTrue( beforeShutdown );
assertThat( timeSpent, between( 500 * DELAY_MULTIPLIER - 50, 1250 * DELAY_MULTIPLIER ) );
}
@Test( timeout = 2000 * DELAY_MULTIPLIER )
public void shutdownWithInterrupt()
{
final long t1 = systemMillis();
new ShutdownTest().run( true );
final long t2 = systemMillis();
final long timeSpent = t2 - t1;
assertTrue( beforeShutdown );
assertThat( timeSpent, between( 500 * DELAY_MULTIPLIER - 50, 1250 * DELAY_MULTIPLIER ) );
}
@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<>( 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( 500L );
}
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( 500L );
}
assertThat( jvmThreads(), is( expectedThreads ) );
}
private static Collection<Thread> jvmThreads()
{
Thread[] t = new Thread[1000];
Thread.enumerate( t );
ArrayList<Thread> appThreads = new ArrayList<>( 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 ( CLASS1BLOCK )
{
++concurrentMethods;
CLASS1BLOCK.wait( DELAY_MULTIPLIER * 500L );
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
{
private static final Collection<String> METHODS = new ConcurrentLinkedQueue<>();
@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
{
}
/**
*
*/
public static class Test2
{
@Test
public void test()
{
}
}
/**
*
*/
@RunWith( ReportOneTestAtRuntimeRunner.class )
public static class TestWithoutPrecalculatedChildren
{
}
/**
*
*/
public static class ReportOneTestAtRuntimeRunner extends ParentRunner
{
private final Class<?> testClass;
private final Description suiteDescription;
private final Description myTestMethodDescr;
@SuppressWarnings( "unchecked" )
public ReportOneTestAtRuntimeRunner( Class<?> testClass ) throws InitializationError
{
super( Object.class );
this.testClass = testClass;
suiteDescription = Description.createSuiteDescription( testClass );
myTestMethodDescr = Description.createTestDescription( testClass, "my_test" );
// suiteDescription.addChild(myTestMethodDescr); // let it be not known at start time
}
protected List getChildren()
{
throw new UnsupportedOperationException( "workflow from ParentRunner not supported" );
}
protected Description describeChild( Object child )
{
throw new UnsupportedOperationException( "workflow from ParentRunner not supported" );
}
protected void runChild( Object child, RunNotifier notifier )
{
throw new UnsupportedOperationException( "workflow from ParentRunner not supported" );
}
public Description getDescription()
{
return suiteDescription;
}
public void run( RunNotifier notifier )
{
notifier.fireTestStarted( myTestMethodDescr );
notifier.fireTestFinished( Description.createTestDescription( testClass, "my_test" ) );
}
}
/**
*
*/
@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" );
sleepSeconds( 1 );
System.out.println( new Date() + " END: beforeClass" );
}
@Before
public void before() throws InterruptedException
{
System.out.println( new Date() + " BEG: before" );
sleepSeconds( 1 );
System.out.println( new Date() + " END: before" );
}
@Test
public void test() throws InterruptedException
{
System.out.println( new Date() + " BEG: test" );
sleepSeconds( 1 );
System.out.println( new Date() + " END: test" );
}
@After
public void after() throws InterruptedException
{
System.out.println( new Date() + " BEG: after" );
sleepSeconds( 1 );
System.out.println( new Date() + " END: after" );
}
@AfterClass
public static void afterClass() throws InterruptedException
{
System.out.println( new Date() + " BEG: afterClass" );
sleepSeconds( 1 );
System.out.println( new Date() + " END: afterClass" );
}
}
private static long systemMillis()
{
return TimeUnit.NANOSECONDS.toMillis( System.nanoTime() );
}
private static void sleepSeconds( int seconds ) throws InterruptedException
{
TimeUnit.SECONDS.sleep( seconds );
}
}