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