/*
 * 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.commons.lang.enum;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

import org.apache.commons.lang.SerializationUtils;

/**
 * Test cases for the {@link Enum} class.
 * 
 * @author Apache Software Foundation
 * @author Gary D. Gregory
 * @version $Id$
 */

public final class EnumTest extends TestCase {

    private static final String ENUM_CLASS_NAME = "org.apache.commons.lang.enum.ColorEnum";

    public EnumTest(String name) {
        super(name);
    }

    public void setUp() {
    }

    public void testName() {
        assertEquals("Red", ColorEnum.RED.getName());
        assertEquals("Green", ColorEnum.GREEN.getName());
        assertEquals("Blue", ColorEnum.BLUE.getName());
    }

    public void testCompareTo() {
        assertTrue(ColorEnum.BLUE.compareTo(ColorEnum.BLUE) == 0);
        assertTrue(ColorEnum.RED.compareTo(ColorEnum.BLUE) > 0);
        assertTrue(ColorEnum.BLUE.compareTo(ColorEnum.RED) < 0);
        try {
            ColorEnum.RED.compareTo(null);
            fail();
        } catch (NullPointerException ex) {
        }
        try {
            ColorEnum.RED.compareTo(new Object());
            fail();
        } catch (ClassCastException ex) {
        }
    }

    public void testEquals() {
        assertSame(ColorEnum.RED, ColorEnum.RED);
        assertSame(ColorEnum.getEnum("Red"), ColorEnum.RED);
        assertEquals(false, ColorEnum.RED.equals(null));
        assertEquals(true, ColorEnum.RED.equals(ColorEnum.RED));
        assertEquals(true, ColorEnum.RED.equals(ColorEnum.getEnum("Red")));
    }

    public void testHashCode() {
        assertEquals(ColorEnum.RED.hashCode(), ColorEnum.RED.hashCode());
        assertEquals(7 + ColorEnum.class.hashCode() + 3 * "Red".hashCode(), ColorEnum.RED.hashCode());
    }

    public void testToString() {
        String toString = ColorEnum.RED.toString();
        assertEquals("ColorEnum[Red]", toString);
        assertSame(toString, ColorEnum.RED.toString());
    }

    public void testIterator() {
        Iterator it = ColorEnum.iterator();
        assertSame(ColorEnum.RED, it.next());
        assertSame(ColorEnum.GREEN, it.next());
        assertSame(ColorEnum.BLUE, it.next());
    }

    public void testList() {
        List list = new ArrayList(ColorEnum.getEnumList());

        assertNotNull(list);

        assertEquals(list.size(), ColorEnum.getEnumMap().keySet().size());

        Iterator it = list.iterator();
        assertSame(ColorEnum.RED, it.next());
        assertSame(ColorEnum.GREEN, it.next());
        assertSame(ColorEnum.BLUE, it.next());
    }

    public void testMap() {
        Map map = new HashMap(ColorEnum.getEnumMap());

        assertNotNull(map);
        assertTrue(map.containsValue(ColorEnum.RED));
        assertTrue(map.containsValue(ColorEnum.GREEN));
        assertTrue(map.containsValue(ColorEnum.BLUE));
        assertSame(ColorEnum.RED, map.get("Red"));
        assertSame(ColorEnum.GREEN, map.get("Green"));
        assertSame(ColorEnum.BLUE, map.get("Blue"));
        assertEquals(map.keySet().size(), ColorEnum.getEnumList().size());
    }

    public void testGet() {
        assertSame(ColorEnum.RED, ColorEnum.getEnum("Red"));
        assertSame(ColorEnum.GREEN, ColorEnum.getEnum("Green"));
        assertSame(ColorEnum.BLUE, ColorEnum.getEnum("Blue"));
        assertSame(null, ColorEnum.getEnum("Pink"));
    }

    public void testSerialization() {
        int hashCode = ColorEnum.RED.hashCode();
        assertSame(ColorEnum.RED, SerializationUtils.clone(ColorEnum.RED));
        assertEquals(hashCode, SerializationUtils.clone(ColorEnum.RED).hashCode());
        assertSame(ColorEnum.GREEN, SerializationUtils.clone(ColorEnum.GREEN));
        assertSame(ColorEnum.BLUE, SerializationUtils.clone(ColorEnum.BLUE));
    }

    public void testBroken1() {
        try {
            Broken1Enum.RED.getName();
            fail();
        } catch (ExceptionInInitializerError ex) {
            assertTrue(ex.getException() instanceof IllegalArgumentException);
        }
    }

    public void testBroken2() {
        try {
            Broken2Enum.RED.getName();
            fail();
        } catch (ExceptionInInitializerError ex) {
            assertTrue(ex.getException() instanceof IllegalArgumentException);
        }
    }

    public void testBroken3() {
        try {
            Broken3Enum.RED.getName();
            fail();
        } catch (ExceptionInInitializerError ex) {
            assertTrue(ex.getException() instanceof IllegalArgumentException);
        }
    }

    public void testBroken1Operation() {
        try {
            Broken1OperationEnum.PLUS.getName();
            fail();
        } catch (ExceptionInInitializerError ex) {
            assertTrue(ex.getException() instanceof IllegalArgumentException);
        }
    }

    public void testBroken2Operation() {
        try {
            Broken2OperationEnum.PLUS.getName();
            fail();
        } catch (ExceptionInInitializerError ex) {
            assertTrue(ex.getException() instanceof IllegalArgumentException);
        }
    }

    public void testBroken3Operation() {
        try {
            Broken3OperationEnum.PLUS.getName();
            fail();
        } catch (ExceptionInInitializerError ex) {
            assertTrue(ex.getException() instanceof IllegalArgumentException);
        }
    }

    public void testBroken4Operation() {
        try {
            Broken4OperationEnum.PLUS.getName();
            fail();
        } catch (ExceptionInInitializerError ex) {
            assertTrue(ex.getException() instanceof IllegalArgumentException);
        }
    }

    public void testBroken5Operation() {
        try {
            Broken5OperationEnum.PLUS.getName();
            fail();
        } catch (ExceptionInInitializerError ex) {
            assertTrue(ex.getException() instanceof IllegalArgumentException);
        }
    }

    public void testOperationGet() {
        assertSame(OperationEnum.PLUS, OperationEnum.getEnum("Plus"));
        assertSame(OperationEnum.MINUS, OperationEnum.getEnum("Minus"));
        assertSame(null, OperationEnum.getEnum("Pink"));
    }

    public void testOperationSerialization() {
        assertSame(OperationEnum.PLUS, SerializationUtils.clone(OperationEnum.PLUS));
        assertSame(OperationEnum.MINUS, SerializationUtils.clone(OperationEnum.MINUS));
    }

    public void testOperationToString() {
        assertEquals("OperationEnum[Plus]", OperationEnum.PLUS.toString());
    }

    public void testOperationList() {
        List list = OperationEnum.getEnumList();
        assertNotNull(list);
        assertEquals(2, list.size());
        assertEquals(list.size(), OperationEnum.getEnumMap().keySet().size());

        Iterator it = list.iterator();
        assertSame(OperationEnum.PLUS, it.next());
        assertSame(OperationEnum.MINUS, it.next());
    }

    public void testOperationMap() {
        Map map = OperationEnum.getEnumMap();
        assertNotNull(map);
        assertEquals(map.keySet().size(), OperationEnum.getEnumList().size());

        assertTrue(map.containsValue(OperationEnum.PLUS));
        assertTrue(map.containsValue(OperationEnum.MINUS));
        assertSame(OperationEnum.PLUS, map.get("Plus"));
        assertSame(OperationEnum.MINUS, map.get("Minus"));
    }

    public void testOperationCalculation() {
        assertEquals(3, OperationEnum.PLUS.eval(1, 2));
        assertEquals(-1, OperationEnum.MINUS.eval(1, 2));
    }

    // -----------------------------------------------------------------------
    public void testExtended1Get() {
        assertSame(Extended1Enum.ALPHA, Extended1Enum.getEnum("Alpha"));
        assertSame(Extended1Enum.BETA, Extended1Enum.getEnum("Beta"));
        assertSame(null, Extended1Enum.getEnum("Gamma"));
        assertSame(null, Extended1Enum.getEnum("Delta"));
    }

    public void testExtended2Get() {
        assertSame(Extended1Enum.ALPHA, Extended2Enum.ALPHA);
        assertSame(Extended1Enum.BETA, Extended2Enum.BETA);

        assertSame(Extended2Enum.ALPHA, Extended2Enum.getEnum("Alpha"));
        assertSame(Extended2Enum.BETA, Extended2Enum.getEnum("Beta"));
        assertSame(Extended2Enum.GAMMA, Extended2Enum.getEnum("Gamma"));
        assertSame(null, Extended2Enum.getEnum("Delta"));
    }

    public void testExtended3Get() {
        assertSame(Extended2Enum.ALPHA, Extended3Enum.ALPHA);
        assertSame(Extended2Enum.BETA, Extended3Enum.BETA);
        assertSame(Extended2Enum.GAMMA, Extended3Enum.GAMMA);

        assertSame(Extended3Enum.ALPHA, Extended3Enum.getEnum("Alpha"));
        assertSame(Extended3Enum.BETA, Extended3Enum.getEnum("Beta"));
        assertSame(Extended3Enum.GAMMA, Extended3Enum.getEnum("Gamma"));
        assertSame(Extended3Enum.DELTA, Extended3Enum.getEnum("Delta"));
    }

    public void testExtendedSerialization() {
        assertSame(Extended1Enum.ALPHA, SerializationUtils.clone(Extended1Enum.ALPHA));
        assertSame(Extended1Enum.BETA, SerializationUtils.clone(Extended1Enum.BETA));
        assertSame(Extended2Enum.GAMMA, SerializationUtils.clone(Extended2Enum.GAMMA));
        assertSame(Extended3Enum.DELTA, SerializationUtils.clone(Extended3Enum.DELTA));
    }

    public void testExtendedToString() {
        assertEquals("Extended1Enum[Alpha]", Extended1Enum.ALPHA.toString());
        assertEquals("Extended1Enum[Beta]", Extended1Enum.BETA.toString());

        assertEquals("Extended1Enum[Alpha]", Extended2Enum.ALPHA.toString());
        assertEquals("Extended1Enum[Beta]", Extended2Enum.BETA.toString());
        assertEquals("Extended2Enum[Gamma]", Extended2Enum.GAMMA.toString());

        assertEquals("Extended1Enum[Alpha]", Extended3Enum.ALPHA.toString());
        assertEquals("Extended1Enum[Beta]", Extended3Enum.BETA.toString());
        assertEquals("Extended2Enum[Gamma]", Extended3Enum.GAMMA.toString());
        assertEquals("Extended3Enum[Delta]", Extended3Enum.DELTA.toString());
    }

    public void testExtended1List() {
        List list = Extended1Enum.getEnumList();
        assertNotNull(list);
        assertEquals(2, list.size());
        assertEquals(list.size(), Extended1Enum.getEnumMap().keySet().size());

        Iterator it = list.iterator();
        assertSame(Extended1Enum.ALPHA, it.next());
        assertSame(Extended1Enum.BETA, it.next());
    }

    public void testExtended2List() {
        List list = Extended2Enum.getEnumList();
        assertNotNull(list);
        assertEquals(3, list.size());
        assertEquals(list.size(), Extended2Enum.getEnumMap().keySet().size());

        Iterator it = list.iterator();
        assertSame(Extended2Enum.ALPHA, it.next());
        assertSame(Extended2Enum.BETA, it.next());
        assertSame(Extended2Enum.GAMMA, it.next());
    }

    public void testExtended3List() {
        List list = Extended3Enum.getEnumList();
        assertNotNull(list);
        assertEquals(4, list.size());
        assertEquals(list.size(), Extended3Enum.getEnumMap().keySet().size());

        Iterator it = list.iterator();
        assertSame(Extended3Enum.ALPHA, it.next());
        assertSame(Extended3Enum.BETA, it.next());
        assertSame(Extended3Enum.GAMMA, it.next());
        assertSame(Extended3Enum.DELTA, it.next());
    }

    public void testExtended1Map() {
        Map map = Extended1Enum.getEnumMap();
        assertNotNull(map);
        assertEquals(map.keySet().size(), Extended1Enum.getEnumList().size());

        assertTrue(map.containsValue(Extended1Enum.ALPHA));
        assertTrue(map.containsValue(Extended1Enum.BETA));
        assertSame(Extended1Enum.ALPHA, map.get("Alpha"));
        assertSame(Extended1Enum.BETA, map.get("Beta"));
    }

    public void testExtended2Map() {
        Map map = Extended2Enum.getEnumMap();
        assertNotNull(map);
        assertEquals(map.keySet().size(), Extended2Enum.getEnumList().size());

        assertTrue(map.containsValue(Extended2Enum.ALPHA));
        assertTrue(map.containsValue(Extended2Enum.BETA));
        assertTrue(map.containsValue(Extended2Enum.GAMMA));
        assertSame(Extended2Enum.ALPHA, map.get("Alpha"));
        assertSame(Extended2Enum.BETA, map.get("Beta"));
        assertSame(Extended2Enum.GAMMA, map.get("Gamma"));
    }

    public void testExtended3Map() {
        Map map = Extended3Enum.getEnumMap();
        assertNotNull(map);
        assertEquals(map.keySet().size(), Extended3Enum.getEnumList().size());

        assertTrue(map.containsValue(Extended3Enum.ALPHA));
        assertTrue(map.containsValue(Extended3Enum.BETA));
        assertTrue(map.containsValue(Extended3Enum.GAMMA));
        assertTrue(map.containsValue(Extended3Enum.DELTA));
        assertSame(Extended3Enum.ALPHA, map.get("Alpha"));
        assertSame(Extended3Enum.BETA, map.get("Beta"));
        assertSame(Extended3Enum.GAMMA, map.get("Gamma"));
        assertSame(Extended3Enum.DELTA, map.get("Delta"));
    }

    // -----------------------------------------------------------------------
    public void testNested() {
        List list = new ArrayList(Nest.ColorEnum.getEnumList());
        assertEquals(3, list.size()); // all is well
        Iterator it = list.iterator();
        assertSame(Nest.ColorEnum.RED, it.next());
        assertSame(Nest.ColorEnum.GREEN, it.next());
        assertSame(Nest.ColorEnum.BLUE, it.next());
        // This nesting works because the enum constants are defined in the SAME
        // class as the getEnumList(). It just acts as a normal enum.
    }

    public void testNestedBroken() {
        List list = new ArrayList(NestBroken.ColorEnum.getEnumList());
        try {
            assertEquals(0, list.size()); // no enums!!!
            // this is BROKEN because the enum constants are defined in a DIFFERENT
            // class from getEnumList(). Once NestBroken class is referenced,
            // and thus class loaded with its enum constants, the getEnumList works:
        } catch (AssertionFailedError ex) {
            // this actually works and isn't broken on Linux SunJDK1.4.1, so...
            assertEquals(3, list.size());
        }
        new NestBroken();
        list = new ArrayList(NestBroken.ColorEnum.getEnumList());
        assertEquals(3, list.size()); // all is well!!!
        Iterator it = list.iterator();
        assertSame(NestBroken.RED, it.next());
        assertSame(NestBroken.GREEN, it.next());
        assertSame(NestBroken.BLUE, it.next());
    }

    public void testNestedLinked() {
        List list = new ArrayList(NestLinked.ColorEnum.getEnumList());
        assertEquals(3, list.size()); // all is well
        Iterator it = list.iterator();
        assertSame(NestLinked.RED, it.next());
        assertSame(NestLinked.GREEN, it.next());
        assertSame(NestLinked.BLUE, it.next());
        // This nesting works because a static block in the enum class forces a
        // class load of the outer class which defines the enum constants.
    }

    public void testNestedReferenced() {
        List list = new ArrayList(NestReferenced.ColorEnum.getEnumList());
        assertEquals(3, list.size()); // all is well
        Iterator it = list.iterator();
        assertSame(NestReferenced.RED, it.next());
        assertSame(NestReferenced.GREEN, it.next());
        assertSame(NestReferenced.BLUE, it.next());
        // This nesting works because the enum constants are actually defined in
        // the SAME class as the getEnumList(). The references in the outer class
        // are just extra references.
    }

    public void testColorEnumEqualsWithDifferentClassLoaders() throws SecurityException, IllegalArgumentException,
            ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        this.testWithDifferentClassLoaders(ColorEnum.BLUE);
        this.testWithDifferentClassLoaders(ColorEnum.GREEN);
        this.testWithDifferentClassLoaders(ColorEnum.RED);
    }

    void testWithDifferentClassLoaders(ColorEnum colorEnum) throws ClassNotFoundException, SecurityException,
            NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        // Sanity checks:
        assertTrue(colorEnum.equals(colorEnum));
        assertNotNull(ColorEnum.class.getClassLoader());
        // set up:
        ClassLoader myClassLoader = EnumTest.class.getClassLoader();
        if (!(myClassLoader instanceof URLClassLoader)) {
            fail("EnumTest ClassLoader = " + (myClassLoader == null ? null : myClassLoader.getClass().getName()));
        }
        ClassLoader classLoader = URLClassLoader.newInstance( ((URLClassLoader)myClassLoader).getURLs(), null);
        Object enumObjectFromOtherClassLoader = this.getColorEnum(classLoader, colorEnum.getName());

        // the real test, part 1.
        try {
            ColorEnum testCase = (ColorEnum) enumObjectFromOtherClassLoader;
            fail("Should have thrown a ClassCastException for " + testCase);
        } catch (ClassCastException e) {
            // normal.
        }

        // the real test, part 2.
        assertEquals("The two objects should match even though they are from different class loaders", colorEnum,
                enumObjectFromOtherClassLoader);

        // the real test, part 3 - testing equals(Object)
        int falseCount = 0;
        for (Iterator iter = ColorEnum.iterator(); iter.hasNext();) {
            ColorEnum element = (ColorEnum) iter.next();
            if (!colorEnum.equals(element)) {
                falseCount++;
                assertFalse(enumObjectFromOtherClassLoader.equals(element));
            }
        }
        assertEquals(ColorEnum.getEnumList().size() - 1, falseCount);

        // the real test, part 4 - testing compareTo(Object) == 0
        falseCount = 0;
        for (Iterator iter = ColorEnum.iterator(); iter.hasNext();) {
            ColorEnum element = (ColorEnum) iter.next();
            if (!colorEnum.equals(element)) {
                falseCount++;
                assertFalse( ((Comparable)enumObjectFromOtherClassLoader).compareTo(element) == 0);
            }
        }
        assertEquals(ColorEnum.getEnumList().size() - 1, falseCount);
    }

    Object getColorEnum(ClassLoader classLoader, String color) throws ClassNotFoundException, SecurityException,
            NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        // Sanity check:
        ColorEnum.RED.equals(ColorEnum.RED);
        assertNotNull(ColorEnum.class.getClassLoader());
        // set up:
        assertNotNull(classLoader);
        assertFalse(classLoader.equals(ColorEnum.class.getClassLoader()));
        Class otherColorEnumClass = null;
        try {
            otherColorEnumClass = classLoader.loadClass(ENUM_CLASS_NAME);
        } catch (ClassNotFoundException e) {
            // Dump some information to help debug class loader issues under different JREs, Ant, Eclipse.
            System.err.println("Could not load " + ENUM_CLASS_NAME + " from the class loader " + classLoader);
            URLClassLoader urlCl = (URLClassLoader) classLoader;
            URL[] urls = urlCl.getURLs();
            System.err.println("Class loader has " + urls.length + " URLs:");
            for (int i = 0; i < urls.length; i++) {
                System.err.println("URL[" + i + "] = " + urls[i]);
            }
            e.printStackTrace();
            throw e;
        }
        assertNotNull(otherColorEnumClass);
        assertNotNull(otherColorEnumClass.getClassLoader());
        assertTrue(classLoader.equals(otherColorEnumClass.getClassLoader()));
        assertFalse(otherColorEnumClass.getClassLoader().equals(ColorEnum.class.getClassLoader()));
        Method method = otherColorEnumClass.getMethod("getEnum", new Class[]{String.class});
        Object enumObject = method.invoke(otherColorEnumClass, new Object[]{color});
        assertNotNull(enumObject);
        assertFalse(ColorEnum.class.equals(enumObject.getClass()));
        assertFalse(ColorEnum.class == enumObject.getClass());
        return enumObject;
    }

    public void testEqualsToWrongInstance() {
        for (Iterator iter = ColorEnum.iterator(); iter.hasNext();) {
            ColorEnum element = (ColorEnum) iter.next();
            this.testEqualsToWrongInstance(element);
        }
    }

    void testEqualsToWrongInstance(ColorEnum colorEnum) {
        assertEquals(false, colorEnum.equals("test"));
        assertEquals(false, colorEnum.equals(new Integer(1)));
        assertEquals(false, colorEnum.equals(new Boolean(true)));
        assertEquals(false, colorEnum.equals(new StringBuffer("test")));
        assertEquals(false, colorEnum.equals(new Object()));
        assertEquals(false, colorEnum.equals(null));
        assertEquals(false, colorEnum.equals(""));
        assertEquals(false, colorEnum.equals(ColorEnum.getEnum(null)));
        assertEquals(false, colorEnum.equals(ColorEnum.getEnum("")));
        assertEquals(false, colorEnum.equals(ColorEnum.getEnum("This ColorEnum does not exist.")));
    }
}
