package functionalTests.component.monitoring;

import static org.junit.Assert.assertTrue;

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

import org.objectweb.fractal.adl.Factory;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.control.NameController;
import org.objectweb.fractal.util.Fractal;
import org.objectweb.proactive.core.component.Constants;
import org.objectweb.proactive.core.component.controller.MethodStatistics;
import org.objectweb.proactive.core.component.controller.MonitorController;

import functionalTests.ComponentTest;


/**
 * Test the monitor controller.
 *
 * @author The ProActive Team
 */
public class TestMonitoring extends ComponentTest {
    private static final long OVERHEAD = 400;
    private Factory factory;
    private Component root;
    private MonitorController monitor;

    @org.junit.Test
    public void testMonitoringPrimitiveComponent() throws Exception {
        factory = org.objectweb.proactive.core.component.adl.FactoryFactory.getFactory();
        Map<Object, Object> context = new HashMap<Object, Object>();
        root = (Component) factory.newComponent("functionalTests.component.monitoring.adl.TestPrimitive",
                context);

        start();
    }

    @org.junit.Test
    public void testMonitoringCompositeComponent() throws Exception {
        factory = org.objectweb.proactive.core.component.adl.FactoryFactory.getFactory();
        Map<Object, Object> context = new HashMap<Object, Object>();
        root = (Component) factory.newComponent("functionalTests.component.monitoring.adl.TestComposite",
                context);

        start();
    }

    @org.junit.Test
    public void testMonitoringCompositeComponentWithMulticast() throws Exception {
        factory = org.objectweb.proactive.core.component.adl.FactoryFactory.getFactory();
        Map<Object, Object> context = new HashMap<Object, Object>();
        root = (Component) factory.newComponent(
                "functionalTests.component.monitoring.adl.TestCompositeMulticast", context);

        start();
    }

    private void printStats() {
        Iterator<MethodStatistics> stats = monitor.getAllStatistics().values().iterator();
        while (stats.hasNext()) {
            System.out.println(stats.next().toString());
        }
    }

    private boolean checkTime(double supposedTime, double realTime) {
        return ((supposedTime * 0.7) <= realTime) && (realTime <= ((supposedTime * 1.3) + OVERHEAD));
    }

    private void checkMethodStatistics(String itfName, String methodName, int nbCalls, int nbMethods,
            long sleepTimeCallMethod) throws Exception {
        MethodStatistics methodStats = monitor.getStatistics(itfName, methodName);
        assertTrue(checkTime(ServerImpl.EXECUTION_TIME, methodStats.getAverageServiceTime()));
        assertTrue(checkTime(nbMethods * sleepTimeCallMethod, methodStats.getAverageInterArrivalTime()));
    }

    public void start() throws Exception {
        Component[] subComponents = Fractal.getContentController(root).getFcSubComponents();
        for (int i = 0; i < subComponents.length; i++) {
            if (((NameController) subComponents[i].getFcInterface(Constants.NAME_CONTROLLER)).getFcName()
                    .equals("server")) {
                monitor = (MonitorController) subComponents[i].getFcInterface(Constants.MONITOR_CONTROLLER);
            }
        }

        Fractal.getLifeCycleController(root).startFc();

        Runner runner1 = ((Runner) root.getFcInterface("runner1"));
        Runner runner2 = ((Runner) root.getFcInterface("runner2"));
        monitor.startMonitoring();

        System.out.println();
        System.out.println("-----------------------------------------------------------");
        System.out.println("Before execution:");
        System.out.println();
        printStats();

        runner1.run();
        runner2.run();

        int totalNbMethodCalls = runner1.getTotalNbMethodCalls() + runner2.getTotalNbMethodCalls();

        Thread.sleep(ServerImpl.EXECUTION_TIME * totalNbMethodCalls / 2);

        System.out.println();
        System.out.println("-----------------------------------------------------------");
        System.out.println("During execution:");
        System.out.println();
        printStats();

        Thread.sleep(ServerImpl.EXECUTION_TIME * totalNbMethodCalls / 2);

        System.out.println();
        System.out.println("-----------------------------------------------------------");
        System.out.println("After execution:");
        System.out.println();
        printStats();

        String[] itfNamesForEachMethod = runner1.getItfNamesForEachMethod();
        String[] methodNames = runner1.getMethodNames();
        int[] nbCallsPerMethod = runner1.getNbCallsPerMethod();
        for (int i = 0; i < methodNames.length; i++) {
            checkMethodStatistics(itfNamesForEachMethod[i], methodNames[i], nbCallsPerMethod[i],
                    methodNames.length, runner1.getSleepTime());
        }
        itfNamesForEachMethod = runner2.getItfNamesForEachMethod();
        methodNames = runner2.getMethodNames();
        nbCallsPerMethod = runner2.getNbCallsPerMethod();
        for (int i = 0; i < methodNames.length; i++) {
            checkMethodStatistics(itfNamesForEachMethod[i], methodNames[i], nbCallsPerMethod[i],
                    methodNames.length, runner2.getSleepTime());
        }
    }
}

@@ -2351,15 +2351,12 @@
 ate 
-boolean
+void
  che
@@ -2414,54 +2414,311 @@
     
-return ((supposedTime * 0.7) %3C= realTime) && (
+assertTrue(%22Measured time is lesser than expected (%22 + realTime + %22 instead of %22 +%0A            (supposedTime * 0.7) + %22)%22, (supposedTime * 0.7) %3C= realTime);%0A        assertTrue(%22Measured time is greater than expected (%22 + realTime + %22 instead of %22 +%0A            ((supposedTime * 1.3) + OVERHEAD) + %22)%22, 
 real
@@ -3014,35 +3014,24 @@
 e);%0A        
-assertTrue(
 checkTime(Se
@@ -3087,25 +3087,24 @@
 rviceTime())
-)
 ;%0A        as
@@ -3101,27 +3101,16 @@
         
-assertTrue(
 checkTim
@@ -3185,17 +3185,16 @@
 lTime())
-)
 ;%0A    %7D%0A

improve assertion message