org.pircbotx.hooks.ListenerAdapterTest.java Source code

Java tutorial

Introduction

Here is the source code for org.pircbotx.hooks.ListenerAdapterTest.java

Source

/**
 * Copyright (C) 2010-2014 Leon Blakey <lord.quackstar at gmail.com>
 *
 * This file is part of PircBotX.
 *
 * PircBotX is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * PircBotX is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * PircBotX. If not, see <http://www.gnu.org/licenses/>.
 */
package org.pircbotx.hooks;

import com.google.common.collect.Sets;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.pircbotx.hooks.events.MessageEvent;
import org.pircbotx.hooks.types.GenericMessageEvent;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import static org.mockito.Mockito.*;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.pircbotx.Configuration;
import org.pircbotx.PircBotX;
import org.pircbotx.TestUtils;
import org.pircbotx.hooks.events.WhoisEvent;
import org.pircbotx.hooks.managers.GenericListenerManager;
import org.pircbotx.hooks.types.GenericEvent;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;

/**
 *
 * @author Leon Blakey
 */
public class ListenerAdapterTest {
    protected PircBotX bot;

    @BeforeMethod
    public void setUp() {
        bot = new PircBotX(TestUtils.generateConfigurationBuilder().buildConfiguration());
    }

    /**
     * Makes sure adapter uses all events
     *
     * @throws Exception
     */
    @Test(dataProviderClass = TestUtils.class, dataProvider = "eventAllDataProvider", description = "Verify ListenerAdapter has methods for all events")
    public void eventImplementTest(Class eventClass) throws NoSuchMethodException {
        //Just try to load it. If the method doesn't exist then it throws a NoSuchMethodException
        String eventName = eventClass.getSimpleName();
        assertTrue(StringUtils.endsWith(eventName, "Event"), "Unknown event class " + eventClass);
        String methodName = "on" + StringUtils.removeEnd(StringUtils.capitalize(eventName), "Event");
        ListenerAdapter.class.getDeclaredMethod(methodName, eventClass);
    }

    @Test(dependsOnMethods = "eventImplementTest", dataProviderClass = TestUtils.class, dataProvider = "eventAllDataProvider", description = "Verify all methods in ListenerAdapter throw an exception")
    public void throwsExceptionTest(Class eventClass) throws NoSuchMethodException {
        String methodName = "on"
                + StringUtils.removeEnd(StringUtils.capitalize(eventClass.getSimpleName()), "Event");
        Method eventMethod = ListenerAdapter.class.getDeclaredMethod(methodName, eventClass);
        Class<?>[] exceptions = eventMethod.getExceptionTypes();
        assertEquals(exceptions.length, 1,
                "Method " + eventMethod + " in ListenerManager doesn't throw an exception or thows too many");
        assertEquals(exceptions[0], Exception.class,
                "Method " + eventMethod + " in ListenerManager doesn't throw the right exception");
    }

    @Test(description = "Do an actual test with a sample ListenerAdapter")
    public void usabilityTest() throws Exception {
        final MutableBoolean onMessageCalled = new MutableBoolean(false);
        final MutableBoolean onGenericMessageCalled = new MutableBoolean(false);
        ListenerAdapter testListener = new ListenerAdapter() {
            @Override
            public void onMessage(MessageEvent event) throws Exception {
                onMessageCalled.setValue(true);
            }

            @Override
            public void onGenericMessage(GenericMessageEvent event) throws Exception {
                onGenericMessageCalled.setValue(true);
            }
        };

        testListener.onEvent(mock(MessageEvent.class));
        assertTrue(onMessageCalled.isTrue(), "onMessage wasn't called on MessageEvent");
        assertTrue(onGenericMessageCalled.isTrue(), "onGenericMessage wasn't called on MessageEvent");
    }

    @Test(description = "Test with an unknown Event to make sure it doesn't throw an exception")
    public void unknownEventTest() throws Exception {
        Event customEvent = new Event(bot) {
            @Override
            public void respond(String response) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        };
        ListenerAdapter customListener = new ListenerAdapter() {
        };

        customListener.onEvent(customEvent);
    }

    @DataProvider
    @SuppressWarnings("unchecked")
    public static Object[][] onEventTestDataProvider() {
        //Map events to methods
        Map<Class<? extends Event>, Set<Method>> eventToMethod = new HashMap();
        for (Method curMethod : ListenerAdapter.class.getDeclaredMethods()) {
            //Filter out methods by basic criteria
            if (curMethod.getName().equals("onEvent") || curMethod.getParameterTypes().length != 1
                    || curMethod.isSynthetic())
                continue;
            Class<?> curClass = curMethod.getParameterTypes()[0];
            //Filter out methods that don't have the right param or are already added
            if (curClass.isAssignableFrom(Event.class) || curClass.isInterface()
                    || (eventToMethod.containsKey(curClass) && eventToMethod.get(curClass).contains(curMethod)))
                continue;
            Set<Method> methods = Sets.newHashSet();
            methods.add(curMethod);
            eventToMethod.put((Class<? extends Event>) curClass, methods);
        }

        //Now that we have all the events, start mapping interfaces
        for (Method curMethod : ListenerAdapter.class.getDeclaredMethods()) {
            //Make sure this is an event method
            if (curMethod.getParameterTypes().length != 1 || curMethod.isSynthetic())
                continue;
            Class<?> curClass = curMethod.getParameterTypes()[0];
            if (!curClass.isInterface() || !GenericEvent.class.isAssignableFrom(curClass))
                continue;
            //Add this interface method to all events that implement it
            for (Class curEvent : eventToMethod.keySet())
                if (curClass.isAssignableFrom(curEvent) && !eventToMethod.get(curEvent).contains(curMethod))
                    eventToMethod.get(curEvent).add(curMethod);
        }

        //Build object array that TestNG understands
        Object[][] params = new Object[eventToMethod.size()][];
        int paramsCounter = 0;
        for (Map.Entry<Class<? extends Event>, Set<Method>> curEntry : eventToMethod.entrySet())
            params[paramsCounter++] = new Object[] { curEntry.getKey(), curEntry.getValue() };
        return params;
    }

    @Test(dependsOnMethods = {
            "eventImplementTest" }, dataProvider = "onEventTestDataProvider", description = "Tests onEvent's completness")
    public void onEventTest(Class<? extends Event> eventClass, Set<Method> methodsToCall) throws Exception {
        //Init, using mocks to store method calls
        final Set<Method> calledMethods = Sets.newHashSet();
        ListenerAdapter mockListener = mock(ListenerAdapter.class, new Answer() {
            public Object answer(InvocationOnMock invocation) throws Throwable {
                calledMethods.add(invocation.getMethod());
                return null;
            }
        });
        doCallRealMethod().when(mockListener).onEvent(any(Event.class));

        //Execute onEvent
        Event eventObject = mock(eventClass);
        mockListener.onEvent(eventObject);

        //Make sure our methods were called
        assertEquals(methodsToCall, calledMethods,
                "Event " + eventClass + " doesn't call expected methods:" + SystemUtils.LINE_SEPARATOR
                        + "Expected: " + SystemUtils.LINE_SEPARATOR
                        + StringUtils.join(methodsToCall, SystemUtils.LINE_SEPARATOR) + SystemUtils.LINE_SEPARATOR
                        + "Called: " + SystemUtils.LINE_SEPARATOR
                        + StringUtils.join(calledMethods, SystemUtils.LINE_SEPARATOR));
    }
}