/*
 * 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.
 */
package org.apache.maven.surefire.api.runorder;

import java.util.List;

import junit.framework.TestCase;
import org.apache.maven.surefire.api.util.internal.ClassMethod;

/**
 * @author Kristian Rosenvold
 */
public class ThreadedExecutionSchedulerTest extends TestCase {

    private final RunEntryStatistics a1 = fromValues(200, 2, A.class, "at1");

    private final RunEntryStatistics a2 = fromValues(300, 2, A.class, "at2");

    private final RunEntryStatistics b1 = fromValues(400, 2, B.class, "bt1");

    private final RunEntryStatistics b2 = fromValues(300, 2, B.class, "bt2");

    private final RunEntryStatistics c1 = fromValues(400, 2, C.class, "ct1");

    private final RunEntryStatistics c2 = fromValues(200, 2, C.class, "ct2");

    private final RunEntryStatistics d1 = fromValues(401, 2, D.class, "ct2");

    private final RunEntryStatistics e1 = fromValues(200, 2, E.class, "ct2");

    public void testAddTest() {
        ThreadedExecutionScheduler threadedExecutionScheduler = new ThreadedExecutionScheduler(2);
        addPrioritizedTests(threadedExecutionScheduler);
        final List<Class<?>> result = threadedExecutionScheduler.getResult();
        assertEquals(5, result.size());
        assertEquals(B.class, result.get(0));
        assertEquals(C.class, result.get(1));
        assertEquals(D.class, result.get(2));
        assertEquals(A.class, result.get(3));
        assertEquals(E.class, result.get(4));
    }

    public void testAddTestJaggedResult() {
        ThreadedExecutionScheduler threadedExecutionScheduler = new ThreadedExecutionScheduler(4);
        addPrioritizedTests(threadedExecutionScheduler);
        final List<Class<?>> result = threadedExecutionScheduler.getResult();
        assertEquals(5, result.size());
    }

    private void addPrioritizedTests(ThreadedExecutionScheduler threadedExecutionScheduler) {
        threadedExecutionScheduler.addTest(new PrioritizedTest(B.class, createPriority(b1, b2)));
        threadedExecutionScheduler.addTest(new PrioritizedTest(C.class, createPriority(c1, c2)));
        threadedExecutionScheduler.addTest(new PrioritizedTest(A.class, createPriority(a1, a2)));
        threadedExecutionScheduler.addTest(new PrioritizedTest(D.class, createPriority(d1)));
        threadedExecutionScheduler.addTest(new PrioritizedTest(E.class, createPriority(e1)));
    }

    private Priority createPriority(RunEntryStatistics runEntryStatistics) {
        final Priority priority = new Priority(A.class.getName());
        priority.addItem(runEntryStatistics);
        return priority;
    }

    private Priority createPriority(RunEntryStatistics runEntryStatistics, RunEntryStatistics runEntryStatistics2) {
        final Priority priority = new Priority(A.class.getName());
        priority.addItem(runEntryStatistics);
        priority.addItem(runEntryStatistics2);
        return priority;
    }

    private static RunEntryStatistics fromValues(int runTime, int successfulBuilds, Class clazz, String testName) {
        ClassMethod classMethod = new ClassMethod(clazz.getName(), testName);
        return new RunEntryStatistics(runTime, successfulBuilds, classMethod);
    }

    class A {} // 500 total

    class B {} // 700 total

    class C {} // 600  total

    class D {} // 400 total

    class E {} // 200 total
}
