/* ====================================================================
   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.poi;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.CoreMatchers.endsWith;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.hasItem;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.apache.poi.util.SuppressForbidden;
import org.apache.poi.util.Internal;

/**
 * Util class for POI JUnit TestCases, which provide additional features 
 */
@Internal
public final class POITestCase {

    public static void assertStartsWith(String string, String prefix) {
        assertNotNull(string);
        assertNotNull(prefix);
        assertThat(string, startsWith(prefix));
    }

    public static void assertStartsWith(String message, String string, String prefix) {
        assertNotNull(message, string);
        assertNotNull(message, prefix);
        assertThat(message, string, startsWith(prefix));
    }

    public static void assertEndsWith(String string, String suffix) {
        assertNotNull(string);
        assertNotNull(suffix);
        assertThat(string, endsWith(suffix));
    }
    
    public static void assertContains(String haystack, String needle) {
        assertNotNull(haystack);
        assertNotNull(needle);
        assertThat(haystack, containsString(needle));
    }

    public static void assertContains(String message, String haystack, String needle) {
        assertNotNull(message, haystack);
        assertNotNull(message, needle);
        assertThat(message, haystack, containsString(needle));
    }

    public static void assertContainsIgnoreCase(String haystack, String needle, Locale locale) {
        assertNotNull(haystack);
        assertNotNull(needle);
        String hay = haystack.toLowerCase(locale);
        String n = needle.toLowerCase(locale);
        assertTrue("Unable to find expected text '" + needle + "' in text:\n" + haystack,
                hay.contains(n)
        );
    }
    public static void assertContainsIgnoreCase(String haystack, String needle) {
        assertContainsIgnoreCase(haystack, needle, Locale.ROOT);
    }
    
    public static void assertNotContained(String haystack, String needle) {
        assertNotNull(haystack);
        assertNotNull(needle);
        assertThat(haystack, not(containsString(needle)));
    }
    
    /**
     * @param map haystack
     * @param key needle
     */
    public static  <T> void assertContains(Map<T, ?> map, T key) {
        if (map.containsKey(key)) {
            return;
        }
        fail("Unable to find " + key + " in " + map);
    }

    public static <T> void assertNotContained(Set<T> set, T element) {
        assertThat(set, not(hasItem(element)));
        /*if (set.contains(element)) {
            fail("Set should not contain " + element);
        }*/
    }
     
    /**
     * Utility method to get the value of a private/protected field.
     * Only use this method in test cases!!!
     */
    public static <R,T> R getFieldValue(final Class<? super T> clazz, final T instance, final Class<R> fieldType, final String fieldName) {
        assertTrue("Reflection of private fields is only allowed for POI classes.", clazz.getName().startsWith("org.apache.poi."));
        try {
            return AccessController.doPrivileged(new PrivilegedExceptionAction<R>() {
                @Override
                @SuppressWarnings("unchecked")
                @SuppressForbidden("For test usage only")
                public R run() throws Exception {
                    Field f = clazz.getDeclaredField(fieldName);
                    f.setAccessible(true);
                    return (R) f.get(instance);
                }
            });
        } catch (PrivilegedActionException pae) {
            throw new RuntimeException("Cannot access field '" + fieldName + "' of class " + clazz, pae.getException());
        }
    }
     
    /**
     * Utility method to call a private/protected method.
     * Only use this method in test cases!!!
     */
    public static <R,T> R callMethod(final Class<? super T> clazz, final T instance, final Class<R> returnType, final String methodName,
        final Class<?>[] parameterTypes, final Object[] parameters) {
        assertTrue("Reflection of private methods is only allowed for POI classes.", clazz.getName().startsWith("org.apache.poi."));
        try {
            return AccessController.doPrivileged(new PrivilegedExceptionAction<R>() {
                @Override
                @SuppressWarnings("unchecked")
                @SuppressForbidden("For test usage only")
                public R run() throws Exception {
                    Method m = clazz.getDeclaredMethod(methodName, parameterTypes);
                    m.setAccessible(true);
                    return (R) m.invoke(instance, parameters);
                }
            });
        } catch (PrivilegedActionException pae) {
            throw new RuntimeException("Cannot access method '" + methodName + "' of class " + clazz, pae.getException());
        }
    }

    /**
     * Utility method to shallow compare all fields of the objects
     * Only use this method in test cases!!!
     */
    public static void assertReflectEquals(final Object expected, Object actual) throws Exception {
        final List<Field> fields;
        try {
            fields = AccessController.doPrivileged(new PrivilegedExceptionAction<List<Field>>() {
                @Override
                @SuppressForbidden("Test only")
                public List<Field> run() throws Exception {
                    List<Field> flds = new ArrayList<Field>();
                    for (Class<?> c = expected.getClass(); c != null; c = c.getSuperclass()) {
                        Field[] fs = c.getDeclaredFields();
                        AccessibleObject.setAccessible(fs, true);                        
                        for (Field f : fs) {
                            // JaCoCo Code Coverage adds it's own field, don't look at this one here
                            if(f.getName().equals("$jacocoData")) {
                                continue;
                            }
                            
                            flds.add(f);
                        }
                    }
                    return flds;
                }
            });
        } catch (PrivilegedActionException pae) {
            throw pae.getException();
        }
        
        for (Field f : fields) {
            Class<?> t = f.getType();
            if (t.isArray()) {
                if (Object[].class.isAssignableFrom(t)) {
                    assertArrayEquals((Object[])f.get(expected), (Object[])f.get(actual));
                } else if (byte[].class.isAssignableFrom(t)) {
                    assertArrayEquals((byte[])f.get(expected), (byte[])f.get(actual));
                } else {
                    fail("Array type is not yet implemented ... add it!");
                }
            } else {
                assertEquals(f.get(expected), f.get(actual));
            }
        }
    }
    
    /**
     * Rather than adding {@literal @}Ignore to known-failing tests,
     * write the test so that it notifies us if it starts passing.
     * This is useful for closing related or forgotten bugs.
     * 
     * An Example:
     * <code><pre>
     * public static int add(int a, int b) {
     *     // a known bug in behavior that has not been fixed yet
     *     raise UnsupportedOperationException("add");
     * }
     * 
     * {@literal @}Test
     * public void knownFailingUnitTest() {
     *     try {
     *         assertEquals(2, add(1,1));
     *         // this test fails because the assumption that this bug had not been fixed is false
     *         testPassesNow(12345);
     *     } catch (UnsupportedOperationException e) {
     *         // test is skipped because the assumption that this bug had not been fixed is true
     *         skipTest(e);
     *     }
     * }
     * 
     * Once passing, this unit test can be rewritten as:
     * {@literal @}Test
     * public void knownPassingUnitTest() {
     *     assertEquals(2, add(1,1));
     * }
     * 
     * If you have a better idea how to simplify test code while still notifying
     * us when a previous known-failing test now passes, please improve these.
     * As a bonus, a known-failing test that fails should not be counted as a
     * passing test.
     * 
     * One possible alternative is to expect the known exception, but without
     * a clear message that it is a good thing to no longer get the expected
     * exception once the test passes.
     * {@literal @}Test(expected=UnsupportedOperationException.class)
     * public void knownFailingUnitTest() {
     *     assertEquals(2, add(1,1));
     * }
     *
     * @param e  the exception that was caught that will no longer
     * be raised when the bug is fixed 
     */
    public static void skipTest(Throwable e) {
        assumeTrue("This test currently fails with " + e, false);
    }
    /**
     * @see #skipTest(Throwable)
     *
     * @param bug  the bug number corresponding to a known bug in bugzilla
     */
    public static void testPassesNow(int bug) {
        fail("This test passes now. Please update the unit test and bug " + bug + ".");
    }
    
    public static void assertBetween(String message, int value, int min, int max) {
        assertTrue(message + ": " + value + " is less than the minimum value of " + min,
                min <= value);
        assertTrue(message + ": " + value + " is greater than the maximum value of " + max,
                value <= max);
    }
    public static void assertStrictlyBetween(String message, int value, int min, int max) {
        assertTrue(message + ": " + value + " is less than or equal to the minimum value of " + min,
                min < value);
        assertTrue(message + ": " + value + " is greater than or equal to the maximum value of " + max,
                value < max);
    }

}
