/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed 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 android.test;

import junit.framework.Assert;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.ArrayList;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Contains additional assertion methods not found in JUnit.
 */
public final class MoreAsserts {

    private MoreAsserts() { }

    /**
     * Asserts that the class  {@code expected} is assignable from the object
     * {@code actual}. This verifies {@code expected} is a parent class or a
     * interface that {@code actual} implements.
     */
    public static void assertAssignableFrom(Class<?> expected, Object actual) {
        assertAssignableFrom(expected, actual.getClass());
    }

    /**
     * Asserts that class {@code expected} is assignable from the class
     * {@code actual}. This verifies {@code expected} is a parent class or a
     * interface that {@code actual} implements.
     */
    public static void assertAssignableFrom(Class<?> expected, Class<?> actual) {
        Assert.assertTrue(
                "Expected " + expected.getCanonicalName() +
                        " to be assignable from actual class " + actual.getCanonicalName(),
                expected.isAssignableFrom(actual));
    }

    /**
     * Asserts that {@code actual} is not equal {@code unexpected}, according
     * to both {@code ==} and {@link Object#equals}.
     */
    public static void assertNotEqual(
            String message, Object unexpected, Object actual) {
        if (equal(unexpected, actual)) {
            failEqual(message, unexpected);
        }
    }

    /**
     * Variant of {@link #assertNotEqual(String,Object,Object)} using a
     * generic message.
     */
    public static void assertNotEqual(Object unexpected, Object actual) {
        assertNotEqual(null, unexpected, actual);
    }

    /**
     * Asserts that array {@code actual} is the same size and every element equals
     * those in array {@code expected}. On failure, message indicates specific
     * element mismatch.
     */
    public static void assertEquals(
            String message, byte[] expected, byte[] actual) {
        if (expected.length != actual.length) {
            failWrongLength(message, expected.length, actual.length);
        }
        for (int i = 0; i < expected.length; i++) {
            if (expected[i] != actual[i]) {
                failWrongElement(message, i, expected[i], actual[i]);
            }
        }
    }

    /**
     * Asserts that array {@code actual} is the same size and every element equals
     * those in array {@code expected}. On failure, message indicates specific
     * element mismatch.
     */
    public static void assertEquals(byte[] expected, byte[] actual) {
        assertEquals(null, expected, actual);
    }

    /**
     * Asserts that array {@code actual} is the same size and every element equals
     * those in array {@code expected}. On failure, message indicates first
     * specific element mismatch.
     */
    public static void assertEquals(
            String message, int[] expected, int[] actual) {
        if (expected.length != actual.length) {
            failWrongLength(message, expected.length, actual.length);
        }
        for (int i = 0; i < expected.length; i++) {
            if (expected[i] != actual[i]) {
                failWrongElement(message, i, expected[i], actual[i]);
            }
        }
    }

    /**
     * Asserts that array {@code actual} is the same size and every element equals
     * those in array {@code expected}. On failure, message indicates first
     * specific element mismatch.
     */
    public static void assertEquals(int[] expected, int[] actual) {
        assertEquals(null, expected, actual);
    }

    /**
     * @hide Asserts that array {@code actual} is the same size and every element equals
     * those in array {@code expected}. On failure, message indicates first
     * specific element mismatch.
     */
    public static void assertEquals(
            String message, long[] expected, long[] actual) {
        if (expected.length != actual.length) {
            failWrongLength(message, expected.length, actual.length);
        }
        for (int i = 0; i < expected.length; i++) {
            if (expected[i] != actual[i]) {
                failWrongElement(message, i, expected[i], actual[i]);
            }
        }
    }

    /**
     * @hide Asserts that array {@code actual} is the same size and every element equals
     * those in array {@code expected}. On failure, message indicates first
     * specific element mismatch.
     */
    public static void assertEquals(long[] expected, long[] actual) {
        assertEquals(null, expected, actual);
    }


    /**
     * Asserts that array {@code actual} is the same size and every element equals
     * those in array {@code expected}. On failure, message indicates first
     * specific element mismatch.
     */
    public static void assertEquals(
            String message, double[] expected, double[] actual) {
        if (expected.length != actual.length) {
            failWrongLength(message, expected.length, actual.length);
        }
        for (int i = 0; i < expected.length; i++) {
            if (expected[i] != actual[i]) {
                failWrongElement(message, i, expected[i], actual[i]);
            }
        }
    }

    /**
     * Asserts that array {@code actual} is the same size and every element equals
     * those in array {@code expected}. On failure, message indicates first
     * specific element mismatch.
     */
    public static void assertEquals(double[] expected, double[] actual) {
        assertEquals(null, expected, actual);
    }

    /**
     * Asserts that array {@code actual} is the same size and every element
     * is the same as those in array {@code expected}. Note that this uses
     * {@code equals()} instead of {@code ==} to compare the objects.
     * {@code null} will be considered equal to {@code null} (unlike SQL).
     * On failure, message indicates first specific element mismatch.
     */
    public static void assertEquals(
            String message, Object[] expected, Object[] actual) {
        if (expected.length != actual.length) {
            failWrongLength(message, expected.length, actual.length);
        }
        for (int i = 0; i < expected.length; i++) {
            Object exp = expected[i];
            Object act = actual[i];
            // The following borrowed from java.util.equals(Object[], Object[]).
            if (!((exp==null) ? act==null : exp.equals(act))) {
                failWrongElement(message, i, exp, act);
            }
        }
    }

    /**
     * Asserts that array {@code actual} is the same size and every element
     * is the same as those in array {@code expected}. Note that this uses
     * {@code ==} instead of {@code equals()} to compare the objects.
     * On failure, message indicates first specific element mismatch.
     */
    public static void assertEquals(Object[] expected, Object[] actual) {
        assertEquals(null, expected, actual);
    }

    /** Asserts that two sets contain the same elements. */
    public static void assertEquals(
            String message, Set<? extends Object> expected, Set<? extends Object> actual) {
        Set<Object> onlyInExpected = new HashSet<Object>(expected);
        onlyInExpected.removeAll(actual);
        Set<Object> onlyInActual = new HashSet<Object>(actual);
        onlyInActual.removeAll(expected);
        if (onlyInExpected.size() != 0 || onlyInActual.size() != 0) {
            Set<Object> intersection = new HashSet<Object>(expected);
            intersection.retainAll(actual);
            failWithMessage(
                    message,
                    "Sets do not match.\nOnly in expected: " + onlyInExpected
                    + "\nOnly in actual: " + onlyInActual
                    + "\nIntersection: " + intersection);
        }
    }

    /** Asserts that two sets contain the same elements. */
    public static void assertEquals(Set<? extends Object> expected, Set<? extends Object> actual) {
        assertEquals(null, expected, actual);
    }

    /**
     * Asserts that {@code expectedRegex} exactly matches {@code actual} and
     * fails with {@code message} if it does not.  The MatchResult is returned
     * in case the test needs access to any captured groups.  Note that you can
     * also use this for a literal string, by wrapping your expected string in
     * {@link Pattern#quote}.
     */
    public static MatchResult assertMatchesRegex(
            String message, String expectedRegex, String actual) {
        if (actual == null) {
            failNotMatches(message, expectedRegex, actual);
        }
        Matcher matcher = getMatcher(expectedRegex, actual);
        if (!matcher.matches()) {
            failNotMatches(message, expectedRegex, actual);
        }
        return matcher;
    }

    /**
     * Variant of {@link #assertMatchesRegex(String,String,String)} using a
     * generic message.
     */
    public static MatchResult assertMatchesRegex(
            String expectedRegex, String actual) {
        return assertMatchesRegex(null, expectedRegex, actual);
    }

    /**
     * Asserts that {@code expectedRegex} matches any substring of {@code actual}
     * and fails with {@code message} if it does not.  The Matcher is returned in
     * case the test needs access to any captured groups.  Note that you can also
     * use this for a literal string, by wrapping your expected string in
     * {@link Pattern#quote}.
     */
    public static MatchResult assertContainsRegex(
            String message, String expectedRegex, String actual) {
        if (actual == null) {
            failNotContains(message, expectedRegex, actual);
        }
        Matcher matcher = getMatcher(expectedRegex, actual);
        if (!matcher.find()) {
            failNotContains(message, expectedRegex, actual);
        }
        return matcher;
    }

    /**
     * Variant of {@link #assertContainsRegex(String,String,String)} using a
     * generic message.
     */
    public static MatchResult assertContainsRegex(
            String expectedRegex, String actual) {
        return assertContainsRegex(null, expectedRegex, actual);
    }

    /**
     * Asserts that {@code expectedRegex} does not exactly match {@code actual},
     * and fails with {@code message} if it does. Note that you can also use
     * this for a literal string, by wrapping your expected string in
     * {@link Pattern#quote}.
     */
    public static void assertNotMatchesRegex(
            String message, String expectedRegex, String actual) {
        Matcher matcher = getMatcher(expectedRegex, actual);
        if (matcher.matches()) {
            failMatch(message, expectedRegex, actual);
        }
    }

    /**
     * Variant of {@link #assertNotMatchesRegex(String,String,String)} using a
     * generic message.
     */
    public static void assertNotMatchesRegex(
            String expectedRegex, String actual) {
        assertNotMatchesRegex(null, expectedRegex, actual);
    }

    /**
     * Asserts that {@code expectedRegex} does not match any substring of
     * {@code actual}, and fails with {@code message} if it does.  Note that you
     * can also use this for a literal string, by wrapping your expected string
     * in {@link Pattern#quote}.
     */
    public static void assertNotContainsRegex(
            String message, String expectedRegex, String actual) {
        Matcher matcher = getMatcher(expectedRegex, actual);
        if (matcher.find()) {
            failContains(message, expectedRegex, actual);
        }
    }

    /**
     * Variant of {@link #assertNotContainsRegex(String,String,String)} using a
     * generic message.
     */
    public static void assertNotContainsRegex(
            String expectedRegex, String actual) {
        assertNotContainsRegex(null, expectedRegex, actual);
    }

    /**
     * Asserts that {@code actual} contains precisely the elements
     * {@code expected}, and in the same order.
     */
    public static void assertContentsInOrder(
            String message, Iterable<?> actual, Object... expected) {
        ArrayList actualList = new ArrayList();
        for (Object o : actual) {
            actualList.add(o);
        }
        Assert.assertEquals(message, Arrays.asList(expected), actualList);
    }

    /**
     * Variant of assertContentsInOrder(String, Iterable<?>, Object...)
     * using a generic message.
     */
    public static void assertContentsInOrder(
            Iterable<?> actual, Object... expected) {
        assertContentsInOrder((String) null, actual, expected);
    }

    /**
     * Asserts that {@code actual} contains precisely the elements
     * {@code expected}, but in any order.
     */
    public static void assertContentsInAnyOrder(String message, Iterable<?> actual,
            Object... expected) {
        HashMap<Object, Object> expectedMap = new HashMap<Object, Object>(expected.length);
        for (Object expectedObj : expected) {
            expectedMap.put(expectedObj, expectedObj);
        }

        for (Object actualObj : actual) {
            if (expectedMap.remove(actualObj) == null) {
                failWithMessage(message, "Extra object in actual: (" + actualObj.toString() + ")");
            }
        }
        
        if (expectedMap.size() > 0) {
            failWithMessage(message, "Extra objects in expected.");
        }
    }

    /**
     * Variant of assertContentsInAnyOrder(String, Iterable<?>, Object...)
     * using a generic message.
     */
    public static void assertContentsInAnyOrder(Iterable<?> actual, Object... expected) {
        assertContentsInAnyOrder((String)null, actual, expected);
    }

    /**
     * Asserts that {@code iterable} is empty.
     */
    public static void assertEmpty(String message, Iterable<?> iterable) {
        if (iterable.iterator().hasNext()) {
            failNotEmpty(message, iterable.toString());
        }
    }

    /**
     * Variant of {@link #assertEmpty(String, Iterable)} using a
     * generic message.
     */
    public static void assertEmpty(Iterable<?> iterable) {
        assertEmpty(null, iterable);
    }

    /**
     * Asserts that {@code map} is empty.
     */
    public static void assertEmpty(String message, Map<?,?> map) {
        if (!map.isEmpty()) {
            failNotEmpty(message, map.toString());
        }
    }

    /**
     * Variant of {@link #assertEmpty(String, Map)} using a generic
     * message.
     */
    public  static void assertEmpty(Map<?,?> map) {
        assertEmpty(null, map);
    }

    /**
     * Asserts that {@code iterable} is not empty.
     */
    public static void assertNotEmpty(String message, Iterable<?> iterable) {
        if (!iterable.iterator().hasNext()) {
            failEmpty(message);
        }
    }

    /**
     * Variant of assertNotEmpty(String, Iterable<?>)
     * using a generic message.
     */
    public static void assertNotEmpty(Iterable<?> iterable) {
        assertNotEmpty(null, iterable);
    }

    /**
     * Asserts that {@code map} is not empty.
     */
    public static void assertNotEmpty(String message, Map<?,?> map) {
        if (map.isEmpty()) {
            failEmpty(message);
        }
    }

    /**
     * Variant of {@link #assertNotEmpty(String, Map)} using a generic
     * message.
     */
    public static void assertNotEmpty(Map<?,?> map) {
        assertNotEmpty(null, map);
    }

    /**
     * Utility for testing equals() and hashCode() results at once.
     * Tests that lhs.equals(rhs) matches expectedResult, as well as
     * rhs.equals(lhs).  Also tests that hashCode() return values are
     * equal if expectedResult is true.  (hashCode() is not tested if
     * expectedResult is false, as unequal objects can have equal hashCodes.)
     *
     * @param lhs An Object for which equals() and hashCode() are to be tested.
     * @param rhs As lhs.
     * @param expectedResult True if the objects should compare equal,
     *   false if not.
     */
    public static void checkEqualsAndHashCodeMethods(
            String message, Object lhs, Object rhs, boolean expectedResult) {

        if ((lhs == null) && (rhs == null)) {
            Assert.assertTrue(
                    "Your check is dubious...why would you expect null != null?",
                    expectedResult);
            return;
        }

        if ((lhs == null) || (rhs == null)) {
            Assert.assertFalse(
                    "Your check is dubious...why would you expect an object "
                            + "to be equal to null?", expectedResult);
        }

        if (lhs != null) {
            Assert.assertEquals(message, expectedResult, lhs.equals(rhs));
        }
        if (rhs != null) {
            Assert.assertEquals(message, expectedResult, rhs.equals(lhs));
        }

        if (expectedResult) {
            String hashMessage =
                    "hashCode() values for equal objects should be the same";
            if (message != null) {
                hashMessage += ": " + message;
            }
            Assert.assertTrue(hashMessage, lhs.hashCode() == rhs.hashCode());
        }
    }

    /**
     * Variant of
     * checkEqualsAndHashCodeMethods(String,Object,Object,boolean...)}
     * using a generic message.
     */
    public static void checkEqualsAndHashCodeMethods(Object lhs, Object rhs,
            boolean expectedResult) {
        checkEqualsAndHashCodeMethods((String) null, lhs, rhs, expectedResult);
    }

    private static Matcher getMatcher(String expectedRegex, String actual) {
        Pattern pattern = Pattern.compile(expectedRegex);
        return pattern.matcher(actual);
    }

    private static void failEqual(String message, Object unexpected) {
        failWithMessage(message, "expected not to be:<" + unexpected + ">");
    }

    private static void failWrongLength(
            String message, int expected, int actual) {
        failWithMessage(message, "expected array length:<" + expected
                + "> but was:<" + actual + '>');
    }

    private static void failWrongElement(
            String message, int index, Object expected, Object actual) {
        failWithMessage(message, "expected array element[" + index + "]:<"
                + expected + "> but was:<" + actual + '>');
    }

    private static void failNotMatches(
            String message, String expectedRegex, String actual) {
        String actualDesc = (actual == null) ? "null" : ('<' + actual + '>');
        failWithMessage(message, "expected to match regex:<" + expectedRegex
                + "> but was:" + actualDesc);
    }

    private static void failNotContains(
            String message, String expectedRegex, String actual) {
        String actualDesc = (actual == null) ? "null" : ('<' + actual + '>');
        failWithMessage(message, "expected to contain regex:<" + expectedRegex
                + "> but was:" + actualDesc);
    }

    private static void failMatch(
            String message, String expectedRegex, String actual) {
        failWithMessage(message, "expected not to match regex:<" + expectedRegex
                + "> but was:<" + actual + '>');
    }

    private static void failContains(
            String message, String expectedRegex, String actual) {
        failWithMessage(message, "expected not to contain regex:<" + expectedRegex
                + "> but was:<" + actual + '>');
    }

    private static void failNotEmpty(
            String message, String actual) {
        failWithMessage(message, "expected to be empty, but contained: <"
                + actual + ">");
    }

    private static void failEmpty(String message) {
        failWithMessage(message, "expected not to be empty, but was");
    }

    private static void failWithMessage(String userMessage, String ourMessage) {
        Assert.fail((userMessage == null)
                ? ourMessage
                : userMessage + ' ' + ourMessage);
    }

    private static boolean equal(Object a, Object b) {
        return a == b || (a != null && a.equals(b));
    }

}
