| 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 ); |
| } |
| } |