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 org.apache.maven.surefire.junitcore.JUnitCoreParameters;
import org.apache.maven.surefire.api.testset.TestSetFailedException;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;

import java.util.HashMap;
import java.util.Map;

import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.PARALLEL_KEY;
import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNT_KEY;
import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTSUITES_KEY;
import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTCLASSES_KEY;
import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.resolveConcurrency;
import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.overrideAvailableProcessors;
import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.setDefaultAvailableProcessors;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

/**
 * Testing an algorithm in {@link ParallelComputerUtil} which configures optimized thread resources in ParallelComputer
 * by given {@link org.apache.maven.surefire.junitcore.JUnitCoreParameters}.
 *
 * @author Tibor Digana (tibor17)
 * @see ParallelComputerUtil
 * @since 2.17
 */
@RunWith( Theories.class )
@SuppressWarnings( "checkstyle:magicnumber" )
public final class OptimizedParallelComputerTest
{
    @DataPoint
    public static final int CPU_1 = 1;

    @DataPoint
    public static final int CPU_4 = 4;

    @Rule
    public final ExpectedException exception = ExpectedException.none();

    @BeforeClass
    public static void beforeClass()
    {
        overrideAvailableProcessors( 1 );
    }

    @AfterClass
    public static void afterClass()
    {
        setDefaultAvailableProcessors();
    }

    @Theory
    public void threadCountSuites( int cpu ) throws TestSetFailedException
    {
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "suites" );
        properties.put( THREADCOUNT_KEY, "3" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 5, 10, 20 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertTrue( params.isParallelSuites() );
        assertFalse( params.isParallelClasses() );
        assertFalse( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 0 ) );
        assertThat( concurrency.suites, is( (int) Math.min( 3 * cpu, counter.suites ) ) );
        assertThat( concurrency.classes, is( 0 ) );
        assertThat( concurrency.methods, is( 0 ) );
    }

    @Theory
    public void threadCountClasses( int cpu ) throws TestSetFailedException
    {
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "classes" );
        properties.put( THREADCOUNT_KEY, "3" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 1, 5, 10 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertFalse( params.isParallelSuites() );
        assertTrue( params.isParallelClasses() );
        assertFalse( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 0 ) );
        assertThat( concurrency.suites, is( 0 ) );
        assertThat( concurrency.classes, is( (int) Math.min( 3 * cpu, counter.classes ) ) );
        assertThat( concurrency.methods, is( 0 ) );
    }

    @Theory
    public void threadCountMethods( int cpu ) throws TestSetFailedException
    {
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "methods" );
        properties.put( THREADCOUNT_KEY, "3" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 1, 2, 5 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertFalse( params.isParallelSuites() );
        assertFalse( params.isParallelClasses() );
        assertTrue( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 0 ) );
        assertThat( concurrency.suites, is( 0 ) );
        assertThat( concurrency.classes, is( 0 ) );
        assertThat( concurrency.methods, is( (int) Math.min( 3 * cpu, counter.methods ) ) );
    }

    @Theory
    public void threadCountBoth( int cpu ) throws TestSetFailedException
    {
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "both" );
        properties.put( THREADCOUNT_KEY, "3" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 1, 2, 5 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertFalse( params.isParallelSuites() );
        assertTrue( params.isParallelClasses() );
        assertTrue( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 3 * cpu ) );
        assertThat( concurrency.suites, is( 0 ) );
        assertThat( concurrency.classes, is( (int) Math.min( ( 3d / 2 ) * cpu, 2 ) ) );
        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
    }

    @Theory
    public void threadCountClassesAndMethods( int cpu ) throws TestSetFailedException
    {
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "classesAndMethods" );
        properties.put( THREADCOUNT_KEY, "3" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 1, 2, 5 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertFalse( params.isParallelSuites() );
        assertTrue( params.isParallelClasses() );
        assertTrue( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 3 * cpu ) );
        assertThat( concurrency.suites, is( 0 ) );
        assertThat( concurrency.classes, is( (int) Math.min( ( 3d / 2 ) * cpu, 2 ) ) );
        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
    }

    @Theory
    public void threadCountSuitesAndMethods( int cpu ) throws TestSetFailedException
    {
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "suitesAndMethods" );
        properties.put( THREADCOUNT_KEY, "3" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 2, 3, 5 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertTrue( params.isParallelSuites() );
        assertFalse( params.isParallelClasses() );
        assertTrue( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 3 * cpu ) );
        assertThat( concurrency.suites, is( (int) Math.min( ( 3d / 2 ) * cpu, 2 ) ) );
        assertThat( concurrency.classes, is( 0 ) );
        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
    }

    @Theory
    public void threadCountSuitesAndClasses( int cpu ) throws TestSetFailedException
    {
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "suitesAndClasses" );
        properties.put( THREADCOUNT_KEY, "3" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 2, 5, 20 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertTrue( params.isParallelSuites() );
        assertTrue( params.isParallelClasses() );
        assertFalse( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 3 * cpu ) );
        assertThat( concurrency.suites, is( (int) Math.min( ( 2d * 3 / 7 ) * cpu, 2 ) ) );
        assertThat( concurrency.classes, is( Integer.MAX_VALUE ) );
        assertThat( concurrency.methods, is( 0 ) );
    }

    @Theory
    public void threadCountAll( int cpu ) throws TestSetFailedException
    {
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "all" );
        properties.put( THREADCOUNT_KEY, "3" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 2, 5, 20 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertTrue( params.isParallelSuites() );
        assertTrue( params.isParallelClasses() );
        assertTrue( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 3 * cpu ) );
        assertThat( concurrency.suites, is( (int) Math.min( ( 2d * 3 / 11 ) * cpu, 2 ) ) );
        assertThat( concurrency.classes, is( (int) Math.min( ( 5d * 3 / 11 ) * cpu, 5 ) ) );
        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
    }

    @Theory
    public void reusableThreadCountSuitesAndClasses( int cpu ) throws TestSetFailedException
    {
        // 4 * cpu to 5 * cpu threads to run test classes
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "suitesAndClasses" );
        properties.put( THREADCOUNT_KEY, "6" );
        properties.put( THREADCOUNTSUITES_KEY, "2" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 3, 5, 20 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertTrue( params.isParallelSuites() );
        assertTrue( params.isParallelClasses() );
        assertFalse( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 6 * cpu ) );
        assertThat( concurrency.suites, is( Math.min( 2 * cpu, 3 ) ) );
        assertThat( concurrency.classes, is( Integer.MAX_VALUE ) );
        assertThat( concurrency.methods, is( 0 ) );
    }

    @Theory
    public void reusableThreadCountSuitesAndMethods( int cpu ) throws TestSetFailedException
    {
        // 4 * cpu to 5 * cpu threads to run test methods
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "suitesAndMethods" );
        properties.put( THREADCOUNT_KEY, "6" );
        properties.put( THREADCOUNTSUITES_KEY, "2" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 3, 5, 20 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertTrue( params.isParallelSuites() );
        assertFalse( params.isParallelClasses() );
        assertTrue( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 6 * cpu ) );
        assertThat( concurrency.suites, is( Math.min( 2 * cpu, 3 ) ) );
        assertThat( concurrency.classes, is( 0 ) );
        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
    }

    @Theory
    public void reusableThreadCountClassesAndMethods( int cpu ) throws TestSetFailedException
    {
        // 4 * cpu to 5 * cpu threads to run test methods
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "classesAndMethods" );
        properties.put( THREADCOUNT_KEY, "6" );
        properties.put( THREADCOUNTCLASSES_KEY, "2" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 3, 5, 20 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertFalse( params.isParallelSuites() );
        assertTrue( params.isParallelClasses() );
        assertTrue( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 6 * cpu ) );
        assertThat( concurrency.suites, is( 0 ) );
        assertThat( concurrency.classes, is( Math.min( 2 * cpu, 5 ) ) );
        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
    }

    @Theory
    public void reusableThreadCountAll( int cpu ) throws TestSetFailedException
    {
        // 8 * cpu to 13 * cpu threads to run test methods
        overrideAvailableProcessors( cpu );
        Map<String, String> properties = new HashMap<>();
        properties.put( PARALLEL_KEY, "all" );
        properties.put( THREADCOUNT_KEY, "14" );
        properties.put( THREADCOUNTSUITES_KEY, "2" );
        properties.put( THREADCOUNTCLASSES_KEY, "4" );
        JUnitCoreParameters params = new JUnitCoreParameters( properties );
        RunnerCounter counter = new RunnerCounter( 3, 5, 20 );
        Concurrency concurrency = resolveConcurrency( params, counter );
        assertTrue( params.isParallelSuites() );
        assertTrue( params.isParallelClasses() );
        assertTrue( params.isParallelMethods() );
        assertThat( concurrency.capacity, is( 14 * cpu ) );
        assertThat( concurrency.suites, is( Math.min( 2 * cpu, 3 ) ) );
        assertThat( concurrency.classes, is( Math.min( 4 * cpu, 5 ) ) );
        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
    }
}
