/*
 * 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.jmeter.control;

import org.apache.jmeter.junit.JMeterTestCase;
import org.apache.jmeter.junit.stubs.TestSampler;
import org.apache.jmeter.testelement.TestElement;

/**
 * This class represents a controller that can controll the number of times that
 * it is executed, either by the total number of times the user wants the
 * controller executed (BYNUMBER) or by the percentage of time it is called
 * (BYPERCENT)
 * 
 */
public class TestThroughputController extends JMeterTestCase {
        public TestThroughputController(String name) {
            super(name);
        }

        public void testByNumber() throws Exception {
            ThroughputController sub_1 = new ThroughputController();
            sub_1.setStyle(ThroughputController.BYNUMBER);
            sub_1.setMaxThroughput(2);
            sub_1.addTestElement(new TestSampler("one"));
            sub_1.addTestElement(new TestSampler("two"));

            LoopController loop = new LoopController();
            loop.setLoops(5);
            loop.addTestElement(new TestSampler("zero"));
            loop.addTestElement(sub_1);
            loop.addIterationListener(sub_1);
            loop.addTestElement(new TestSampler("three"));

            LoopController test = new LoopController();
            test.setLoops(2);
            test.addTestElement(loop);

            String[] order = new String[] { "zero", "one", "two", "three", "zero", "one", "two", "three", "zero",
                    "three", "zero", "three", "zero", "three", "zero", "three", "zero", "three", "zero", "three",
                    "zero", "three", "zero", "three", };
            sub_1.testStarted();
            test.setRunningVersion(true);
            sub_1.setRunningVersion(true);
            loop.setRunningVersion(true);
            test.initialize();
            for (int counter = 0; counter < order.length; counter++) {
                TestElement sampler = test.next();
                assertNotNull(sampler);
                assertEquals("Counter: " + counter, order[counter], sampler.getName());
            }
            assertNull(test.next());
            sub_1.testEnded();
        }

        public void testByNumberZero() throws Exception {
            ThroughputController sub_1 = new ThroughputController();
            sub_1.setStyle(ThroughputController.BYNUMBER);
            sub_1.setMaxThroughput(0);
            sub_1.addTestElement(new TestSampler("one"));
            sub_1.addTestElement(new TestSampler("two"));

            LoopController controller = new LoopController();
            controller.setLoops(5);
            controller.addTestElement(new TestSampler("zero"));
            controller.addTestElement(sub_1);
            controller.addIterationListener(sub_1);
            controller.addTestElement(new TestSampler("three"));

            String[] order = new String[] { "zero", "three", "zero", "three", "zero", "three", "zero", "three", "zero",
                    "three", };
            int counter = 0;
            controller.setRunningVersion(true);
            sub_1.setRunningVersion(true);
            sub_1.testStarted();
            controller.initialize();
            for (int i = 0; i < 3; i++) {
                TestElement sampler = null;
                while ((sampler = controller.next()) != null) {
                    assertEquals("Counter: " + counter + ", i: " + i, order[counter], sampler.getName());
                    counter++;
                }
                assertEquals(counter, order.length);
                counter = 0;
            }
            sub_1.testEnded();
        }

        public void testByPercent33() throws Exception {
            ThroughputController sub_1 = new ThroughputController();
            sub_1.setStyle(ThroughputController.BYPERCENT);
            sub_1.setPercentThroughput(33.33f);
            sub_1.addTestElement(new TestSampler("one"));
            sub_1.addTestElement(new TestSampler("two"));

            LoopController controller = new LoopController();
            controller.setLoops(6);
            controller.addTestElement(new TestSampler("zero"));
            controller.addTestElement(sub_1);
            controller.addIterationListener(sub_1);
            controller.addTestElement(new TestSampler("three"));
            // Expected results established using the DDA
            // algorithm (see
            // http://www.siggraph.org/education/materials/HyperGraph/scanline/outprims/drawline.htm):
            String[] order = new String[] { "zero", // 0/1 vs. 1/1 -> 0 is
                                                    // closer to 33.33
                    "three", "zero", // 0/2 vs. 1/2 -> 50.0 is closer to
                                        // 33.33
                    "one", "two", "three", "zero", // 1/3 vs. 2/3 -> 33.33 is
                                                    // closer to 33.33
                    "three", "zero", // 1/4 vs. 2/4 -> 25.0 is closer to
                                        // 33.33
                    "three", "zero", // 1/5 vs. 2/5 -> 40.0 is closer to
                                        // 33.33
                    "one", "two", "three", "zero", // 2/6 vs. 3/6 -> 33.33 is
                                                    // closer to 33.33
                    "three",
            // etc...
            };
            int counter = 0;
            controller.setRunningVersion(true);
            sub_1.setRunningVersion(true);
            sub_1.testStarted();
            controller.initialize();
            for (int i = 0; i < 3; i++) {
                TestElement sampler = null;
                while ((sampler = controller.next()) != null) {
                    assertEquals("Counter: " + counter + ", i: " + i, order[counter], sampler.getName());
                    counter++;
                }
                assertEquals(counter, order.length);
                counter = 0;
            }
            sub_1.testEnded();
        }

        public void testByPercentZero() throws Exception {
            ThroughputController sub_1 = new ThroughputController();
            sub_1.setStyle(ThroughputController.BYPERCENT);
            sub_1.setPercentThroughput(0.0f);
            sub_1.addTestElement(new TestSampler("one"));
            sub_1.addTestElement(new TestSampler("two"));

            LoopController controller = new LoopController();
            controller.setLoops(150);
            controller.addTestElement(new TestSampler("zero"));
            controller.addTestElement(sub_1);
            controller.addIterationListener(sub_1);
            controller.addTestElement(new TestSampler("three"));

            String[] order = new String[] { "zero", "three", };
            int counter = 0;
            controller.setRunningVersion(true);
            sub_1.setRunningVersion(true);
            sub_1.testStarted();
            controller.initialize();
            for (int i = 0; i < 3; i++) {
                TestElement sampler = null;
                while ((sampler = controller.next()) != null) {
                    assertEquals("Counter: " + counter + ", i: " + i, order[counter % order.length], sampler.getName());
                    counter++;
                }
                assertEquals(counter, 150 * order.length);
                counter = 0;
            }
            sub_1.testEnded();
        }

        public void testByPercent100() throws Exception {
            ThroughputController sub_1 = new ThroughputController();
            sub_1.setStyle(ThroughputController.BYPERCENT);
            sub_1.setPercentThroughput(100.0f);
            sub_1.addTestElement(new TestSampler("one"));
            sub_1.addTestElement(new TestSampler("two"));

            LoopController controller = new LoopController();
            controller.setLoops(150);
            controller.addTestElement(new TestSampler("zero"));
            controller.addTestElement(sub_1);
            controller.addIterationListener(sub_1);
            controller.addTestElement(new TestSampler("three"));

            String[] order = new String[] { "zero", "one", "two", "three", };
            int counter = 0;
            controller.setRunningVersion(true);
            sub_1.setRunningVersion(true);
            sub_1.testStarted();
            controller.initialize();
            for (int i = 0; i < 3; i++) {
                TestElement sampler = null;
                while ((sampler = controller.next()) != null) {
                    assertEquals("Counter: " + counter + ", i: " + i, order[counter % order.length], sampler.getName());
                    counter++;
                }
                assertEquals(counter, 150 * order.length);
                counter = 0;
            }
            sub_1.testEnded();
        }
}
