/*
 * 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.
 * @deprecated Use
 * <a href="https://github.com/hamcrest">Hamcrest matchers</a> instead.
 */
@Deprecated
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));
    }

}
