blue.lapis.pore.impl.event.PoreEventImplTest.java Source code

Java tutorial

Introduction

Here is the source code for blue.lapis.pore.impl.event.PoreEventImplTest.java

Source

/*
 * Pore
 * Copyright (c) 2014-2015, Lapis <https://github.com/LapisBlue>
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package blue.lapis.pore.impl.event;

import static blue.lapis.pore.impl.event.PoreEventTest.BUKKIT_PACKAGE;
import static blue.lapis.pore.impl.event.PoreEventTest.PORE_PACKAGE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import blue.lapis.pore.PoreTests;

import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.ClassPath;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.event.Event;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Set;

@RunWith(Parameterized.class)
public class PoreEventImplTest {

    private static final String BUKKIT_PREFIX = BUKKIT_PACKAGE + '.';
    private static final String PORE_PREFIX = PORE_PACKAGE + '.';

    @Parameterized.Parameters(name = "{0}")
    public static Set<String> getEvents() throws Exception {
        ImmutableSet.Builder<String> events = ImmutableSet.builder();
        for (ClassPath.ClassInfo event : PoreTests.getClassPath().getTopLevelClassesRecursive(PORE_PACKAGE)) {
            String name = event.getName();
            if (!name.endsWith("Test")) {
                events.add(StringUtils.removeStart(event.getName(), PORE_PREFIX));
            }
        }
        return events.build();
    }

    @Parameterized.Parameter
    public String event;

    private Class<?> eventImpl;

    @Before
    public void load() throws ClassNotFoundException {
        this.eventImpl = Class.forName(PORE_PREFIX + event, true, ClassLoader.getSystemClassLoader());
        assumeTrue(Event.class.isAssignableFrom(eventImpl));
    }

    @Test
    public void checkName() {
        Class<?> bukkitEvent = eventImpl.getSuperclass();

        String poreName = event;
        String porePackage = StringUtils.substringBeforeLast(poreName, ".");
        poreName = StringUtils.substringAfterLast(poreName, ".");

        String bukkitName = StringUtils.removeStart(bukkitEvent.getName(), BUKKIT_PREFIX);
        String bukkitPackage = StringUtils.substringBeforeLast(bukkitName, ".");
        bukkitName = StringUtils.substringAfterLast(bukkitName, ".");

        String expectedName = "Pore" + bukkitName;

        assertEquals(poreName + " should be called " + expectedName, poreName, expectedName);
        assertEquals(poreName + " is in wrong package: should be in " + PORE_PREFIX + bukkitPackage, porePackage,
                bukkitPackage);
    }

    private static void checkSpongeEvent(Class<?> eventImpl, Class<?> type) {
        assertTrue(eventImpl.getSimpleName() + ": " + type.getSimpleName() + " is not a sponge event",
                org.spongepowered.api.event.Event.class.isAssignableFrom(type));
    }

    @Test
    public void checkHandleGetter() {
        try {
            Method method = eventImpl.getMethod("getHandle");
            checkSpongeEvent(eventImpl, method.getReturnType());
        } catch (NoSuchMethodException ignored) {
            fail(eventImpl.getSimpleName() + ": missing getHandle() method (handle getter)");
        }
    }

    @Test
    public void checkHandleField() {
        try {
            Field field = eventImpl.getDeclaredField("handle");
            checkSpongeEvent(eventImpl, field.getType());
        } catch (NoSuchFieldException e) {
            fail(eventImpl.getSimpleName() + ": missing handle field");
        }
    }

    @Test
    public void checkConstructor() throws Throwable {
        for (Constructor<?> constructor : eventImpl.getConstructors()) {
            Class<?>[] parameters = constructor.getParameterTypes();
            if (parameters.length == 1) {
                Class<?> handle = parameters[0];
                if (org.spongepowered.api.event.Event.class.isAssignableFrom(handle)) {
                    // Check for null check
                    try {
                        constructor.newInstance(new Object[] { null });
                    } catch (InvocationTargetException e) {
                        Throwable cause = e.getCause();
                        if (cause != null) {
                            if (cause instanceof NullPointerException
                                    && Objects.equal(cause.getMessage(), "handle")) {
                                return;
                            }

                            throw cause;
                        }

                        throw e;
                    }

                    fail(eventImpl.getSimpleName() + ": missing null-check for handle");
                }
            }
        }

        fail(eventImpl.getSimpleName() + ": missing handle constructor");
    }

    @Test
    public void checkImplementedMethods() {
        Class<?> bukkitEvent = eventImpl.getSuperclass();
        for (Method method : bukkitEvent.getMethods()) {
            int modifiers = method.getModifiers();
            if (Modifier.isStatic(modifiers) || isDefault(method) || method.getDeclaringClass() == Event.class
                    || method.getDeclaringClass() == Object.class || method.getName().equals("getHandlers")
                    || method.getName().startsWith("_INVALID_")) {
                continue;
            }

            try {
                eventImpl.getDeclaredMethod(method.getName(), method.getParameterTypes());
            } catch (NoSuchMethodException e) {
                fail(eventImpl.getSimpleName() + ": should override method " + method);
            }
        }
    }

    // Taken from JDK8 for compatibility with older Java versions
    private static boolean isDefault(Method method) {
        // Default methods are public non-abstract instance methods declared in an interface.
        return ((method.getModifiers()
                & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == Modifier.PUBLIC)
                && method.getDeclaringClass().isInterface();
    }

    @Test
    public void checkInvalidMethods() {
        for (Method method : eventImpl.getDeclaredMethods()) {
            if (method.getName().startsWith("_INVALID_")) {
                fail(eventImpl.getSimpleName() + ": shouldn't override _INVALID_ method " + method);
            }
        }
    }

}