/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.cuni.amis.pogamut.base.agent.jmx;

import cz.cuni.amis.pogamut.base.agent.AbstractAgent;
import cz.cuni.amis.pogamut.base.agent.AgentStateType;
import cz.cuni.amis.pogamut.base.agent.TestingEmptyAgent;
import cz.cuni.amis.pogamut.base.agent.exceptions.AgentException;
import cz.cuni.amis.pogamut.base.exceptions.PogamutException;
import cz.cuni.amis.pogamut.base.utils.Pogamut;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.JMX;
import javax.management.MBeanRegistrationException;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 * Exports agent as MBean and then test functionality of this MBean.
 * @author Ik
 */
public class AgentMBeanAdapterTest {

    public AgentMBeanAdapterTest() {
    }

    @BeforeClass
    public static void setUpClass() throws PogamutException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, MalformedObjectNameException, InstanceNotFoundException, IOException, InterruptedException {
        agent = new TestingEmptyAgent();
        // export mbean
        agent.getJMX().enableJMX(
                Pogamut.getPlatform().getMBeanServer());

        // get mbean from the 
        agentObjectInstance = Pogamut.getPlatform().getMBeanServerConnection().getObjectInstance(
                agent.getJMX().getAgentJMXName());

        agentProxy = JMX.newMBeanProxy(
                Pogamut.getPlatform().getMBeanServerConnection(),
                agentObjectInstance.getObjectName(), AgentMBeanAdapterMBean.class, true);
    //Thread.sleep(100000000);
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
    }
    static AbstractAgent agent = null;
    static ObjectInstance agentObjectInstance = null;
    static AgentMBeanAdapterMBean agentProxy = null;

    @Before
    public void setUp() {
    }

    @After
    public void tearDown() {
    }
    ArrayBlockingQueue<AgentStateType> state = new ArrayBlockingQueue<AgentStateType>(1);

    /**
     * Test of getAgentState method from class AgentMBeanAdapter.
     */
    @Test
    public void testAgentNotifications() throws AgentException, InterruptedException {

        agentProxy.addNotificationListener(new NotificationListener() {

            public void handleNotification(Notification notification, Object handback) {
                state.add((AgentStateType) notification.getUserData());
            }
        }, null, null);

        agent.start();
        assertEquals(agent.getAgentState().getFlag(), state.take());
    }

    /**
     * Agent throws an exception in his resume method and the exception
     * should propagate through the JMX.
     * @throws cz.cuni.amis.pogamut.base.agent.exceptions.AgentException
     * @throws java.lang.InterruptedException
     */
    @Test(expected = AgentException.class)
    public void testExceptionFromMethod() throws AgentException, InterruptedException {
        agentProxy.resume();
    }
}