Home | History | Annotate | Download | only in test
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.test;
     18 
     19 import com.google.android.collect.Lists;
     20 import junit.framework.Assert;
     21 
     22 import java.util.Arrays;
     23 import java.util.HashMap;
     24 import java.util.HashSet;
     25 import java.util.Map;
     26 import java.util.Set;
     27 import java.util.ArrayList;
     28 import java.util.regex.MatchResult;
     29 import java.util.regex.Matcher;
     30 import java.util.regex.Pattern;
     31 
     32 /**
     33  * Contains additional assertion methods not found in JUnit.
     34  */
     35 public final class MoreAsserts {
     36 
     37     private MoreAsserts() { }
     38 
     39     /**
     40      * Asserts that the class  {@code expected} is assignable from the object
     41      * {@code actual}. This verifies {@code expected} is a parent class or a
     42      * interface that {@code actual} implements.
     43      */
     44     public static void assertAssignableFrom(Class<?> expected, Object actual) {
     45         assertAssignableFrom(expected, actual.getClass());
     46     }
     47 
     48     /**
     49      * Asserts that class {@code expected} is assignable from the class
     50      * {@code actual}. This verifies {@code expected} is a parent class or a
     51      * interface that {@code actual} implements.
     52      */
     53     public static void assertAssignableFrom(Class<?> expected, Class<?> actual) {
     54         Assert.assertTrue(
     55                 "Expected " + expected.getCanonicalName() +
     56                         " to be assignable from actual class " + actual.getCanonicalName(),
     57                 expected.isAssignableFrom(actual));
     58     }
     59 
     60     /**
     61      * Asserts that {@code actual} is not equal {@code unexpected}, according
     62      * to both {@code ==} and {@link Object#equals}.
     63      */
     64     public static void assertNotEqual(
     65             String message, Object unexpected, Object actual) {
     66         if (equal(unexpected, actual)) {
     67             failEqual(message, unexpected);
     68         }
     69     }
     70 
     71     /**
     72      * Variant of {@link #assertNotEqual(String,Object,Object)} using a
     73      * generic message.
     74      */
     75     public static void assertNotEqual(Object unexpected, Object actual) {
     76         assertNotEqual(null, unexpected, actual);
     77     }
     78 
     79     /**
     80      * Asserts that array {@code actual} is the same size and every element equals
     81      * those in array {@code expected}. On failure, message indicates specific
     82      * element mismatch.
     83      */
     84     public static void assertEquals(
     85             String message, byte[] expected, byte[] actual) {
     86         if (expected.length != actual.length) {
     87             failWrongLength(message, expected.length, actual.length);
     88         }
     89         for (int i = 0; i < expected.length; i++) {
     90             if (expected[i] != actual[i]) {
     91                 failWrongElement(message, i, expected[i], actual[i]);
     92             }
     93         }
     94     }
     95 
     96     /**
     97      * Asserts that array {@code actual} is the same size and every element equals
     98      * those in array {@code expected}. On failure, message indicates specific
     99      * element mismatch.
    100      */
    101     public static void assertEquals(byte[] expected, byte[] actual) {
    102         assertEquals(null, expected, actual);
    103     }
    104 
    105     /**
    106      * Asserts that array {@code actual} is the same size and every element equals
    107      * those in array {@code expected}. On failure, message indicates first
    108      * specific element mismatch.
    109      */
    110     public static void assertEquals(
    111             String message, int[] expected, int[] actual) {
    112         if (expected.length != actual.length) {
    113             failWrongLength(message, expected.length, actual.length);
    114         }
    115         for (int i = 0; i < expected.length; i++) {
    116             if (expected[i] != actual[i]) {
    117                 failWrongElement(message, i, expected[i], actual[i]);
    118             }
    119         }
    120     }
    121 
    122     /**
    123      * Asserts that array {@code actual} is the same size and every element equals
    124      * those in array {@code expected}. On failure, message indicates first
    125      * specific element mismatch.
    126      */
    127     public static void assertEquals(int[] expected, int[] actual) {
    128         assertEquals(null, expected, actual);
    129     }
    130 
    131     /**
    132      * Asserts that array {@code actual} is the same size and every element equals
    133      * those in array {@code expected}. On failure, message indicates first
    134      * specific element mismatch.
    135      */
    136     public static void assertEquals(
    137             String message, double[] expected, double[] actual) {
    138         if (expected.length != actual.length) {
    139             failWrongLength(message, expected.length, actual.length);
    140         }
    141         for (int i = 0; i < expected.length; i++) {
    142             if (expected[i] != actual[i]) {
    143                 failWrongElement(message, i, expected[i], actual[i]);
    144             }
    145         }
    146     }
    147 
    148     /**
    149      * Asserts that array {@code actual} is the same size and every element equals
    150      * those in array {@code expected}. On failure, message indicates first
    151      * specific element mismatch.
    152      */
    153     public static void assertEquals(double[] expected, double[] actual) {
    154         assertEquals(null, expected, actual);
    155     }
    156 
    157     /**
    158      * Asserts that array {@code actual} is the same size and every element
    159      * is the same as those in array {@code expected}. Note that this uses
    160      * {@code equals()} instead of {@code ==} to compare the objects.
    161      * {@code null} will be considered equal to {@code null} (unlike SQL).
    162      * On failure, message indicates first specific element mismatch.
    163      */
    164     public static void assertEquals(
    165             String message, Object[] expected, Object[] actual) {
    166         if (expected.length != actual.length) {
    167             failWrongLength(message, expected.length, actual.length);
    168         }
    169         for (int i = 0; i < expected.length; i++) {
    170             Object exp = expected[i];
    171             Object act = actual[i];
    172             // The following borrowed from java.util.equals(Object[], Object[]).
    173             if (!((exp==null) ? act==null : exp.equals(act))) {
    174                 failWrongElement(message, i, exp, act);
    175             }
    176         }
    177     }
    178 
    179     /**
    180      * Asserts that array {@code actual} is the same size and every element
    181      * is the same as those in array {@code expected}. Note that this uses
    182      * {@code ==} instead of {@code equals()} to compare the objects.
    183      * On failure, message indicates first specific element mismatch.
    184      */
    185     public static void assertEquals(Object[] expected, Object[] actual) {
    186         assertEquals(null, expected, actual);
    187     }
    188 
    189     /** Asserts that two sets contain the same elements. */
    190     public static void assertEquals(
    191             String message, Set<? extends Object> expected, Set<? extends Object> actual) {
    192         Set<Object> onlyInExpected = new HashSet<Object>(expected);
    193         onlyInExpected.removeAll(actual);
    194         Set<Object> onlyInActual = new HashSet<Object>(actual);
    195         onlyInActual.removeAll(expected);
    196         if (onlyInExpected.size() != 0 || onlyInActual.size() != 0) {
    197             Set<Object> intersection = new HashSet<Object>(expected);
    198             intersection.retainAll(actual);
    199             failWithMessage(
    200                     message,
    201                     "Sets do not match.\nOnly in expected: " + onlyInExpected
    202                     + "\nOnly in actual: " + onlyInActual
    203                     + "\nIntersection: " + intersection);
    204         }
    205     }
    206 
    207     /** Asserts that two sets contain the same elements. */
    208     public static void assertEquals(Set<? extends Object> expected, Set<? extends Object> actual) {
    209         assertEquals(null, expected, actual);
    210     }
    211 
    212     /**
    213      * Asserts that {@code expectedRegex} exactly matches {@code actual} and
    214      * fails with {@code message} if it does not.  The MatchResult is returned
    215      * in case the test needs access to any captured groups.  Note that you can
    216      * also use this for a literal string, by wrapping your expected string in
    217      * {@link Pattern#quote}.
    218      */
    219     public static MatchResult assertMatchesRegex(
    220             String message, String expectedRegex, String actual) {
    221         if (actual == null) {
    222             failNotMatches(message, expectedRegex, actual);
    223         }
    224         Matcher matcher = getMatcher(expectedRegex, actual);
    225         if (!matcher.matches()) {
    226             failNotMatches(message, expectedRegex, actual);
    227         }
    228         return matcher;
    229     }
    230 
    231     /**
    232      * Variant of {@link #assertMatchesRegex(String,String,String)} using a
    233      * generic message.
    234      */
    235     public static MatchResult assertMatchesRegex(
    236             String expectedRegex, String actual) {
    237         return assertMatchesRegex(null, expectedRegex, actual);
    238     }
    239 
    240     /**
    241      * Asserts that {@code expectedRegex} matches any substring of {@code actual}
    242      * and fails with {@code message} if it does not.  The Matcher is returned in
    243      * case the test needs access to any captured groups.  Note that you can also
    244      * use this for a literal string, by wrapping your expected string in
    245      * {@link Pattern#quote}.
    246      */
    247     public static MatchResult assertContainsRegex(
    248             String message, String expectedRegex, String actual) {
    249         if (actual == null) {
    250             failNotContains(message, expectedRegex, actual);
    251         }
    252         Matcher matcher = getMatcher(expectedRegex, actual);
    253         if (!matcher.find()) {
    254             failNotContains(message, expectedRegex, actual);
    255         }
    256         return matcher;
    257     }
    258 
    259     /**
    260      * Variant of {@link #assertContainsRegex(String,String,String)} using a
    261      * generic message.
    262      */
    263     public static MatchResult assertContainsRegex(
    264             String expectedRegex, String actual) {
    265         return assertContainsRegex(null, expectedRegex, actual);
    266     }
    267 
    268     /**
    269      * Asserts that {@code expectedRegex} does not exactly match {@code actual},
    270      * and fails with {@code message} if it does. Note that you can also use
    271      * this for a literal string, by wrapping your expected string in
    272      * {@link Pattern#quote}.
    273      */
    274     public static void assertNotMatchesRegex(
    275             String message, String expectedRegex, String actual) {
    276         Matcher matcher = getMatcher(expectedRegex, actual);
    277         if (matcher.matches()) {
    278             failMatch(message, expectedRegex, actual);
    279         }
    280     }
    281 
    282     /**
    283      * Variant of {@link #assertNotMatchesRegex(String,String,String)} using a
    284      * generic message.
    285      */
    286     public static void assertNotMatchesRegex(
    287             String expectedRegex, String actual) {
    288         assertNotMatchesRegex(null, expectedRegex, actual);
    289     }
    290 
    291     /**
    292      * Asserts that {@code expectedRegex} does not match any substring of
    293      * {@code actual}, and fails with {@code message} if it does.  Note that you
    294      * can also use this for a literal string, by wrapping your expected string
    295      * in {@link Pattern#quote}.
    296      */
    297     public static void assertNotContainsRegex(
    298             String message, String expectedRegex, String actual) {
    299         Matcher matcher = getMatcher(expectedRegex, actual);
    300         if (matcher.find()) {
    301             failContains(message, expectedRegex, actual);
    302         }
    303     }
    304 
    305     /**
    306      * Variant of {@link #assertNotContainsRegex(String,String,String)} using a
    307      * generic message.
    308      */
    309     public static void assertNotContainsRegex(
    310             String expectedRegex, String actual) {
    311         assertNotContainsRegex(null, expectedRegex, actual);
    312     }
    313 
    314     /**
    315      * Asserts that {@code actual} contains precisely the elements
    316      * {@code expected}, and in the same order.
    317      */
    318     public static void assertContentsInOrder(
    319             String message, Iterable<?> actual, Object... expected) {
    320         ArrayList actualList = new ArrayList();
    321         for (Object o : actual) {
    322             actualList.add(o);
    323         }
    324         Assert.assertEquals(message, Arrays.asList(expected), actualList);
    325     }
    326 
    327     /**
    328      * Variant of assertContentsInOrder(String, Iterable<?>, Object...)
    329      * using a generic message.
    330      */
    331     public static void assertContentsInOrder(
    332             Iterable<?> actual, Object... expected) {
    333         assertContentsInOrder((String) null, actual, expected);
    334     }
    335 
    336     /**
    337      * Asserts that {@code actual} contains precisely the elements
    338      * {@code expected}, but in any order.
    339      */
    340     public static void assertContentsInAnyOrder(String message, Iterable<?> actual,
    341             Object... expected) {
    342         HashMap<Object, Object> expectedMap = new HashMap<Object, Object>(expected.length);
    343         for (Object expectedObj : expected) {
    344             expectedMap.put(expectedObj, expectedObj);
    345         }
    346 
    347         for (Object actualObj : actual) {
    348             if (expectedMap.remove(actualObj) == null) {
    349                 failWithMessage(message, "Extra object in actual: (" + actualObj.toString() + ")");
    350             }
    351         }
    352 
    353         if (expectedMap.size() > 0) {
    354             failWithMessage(message, "Extra objects in expected.");
    355         }
    356     }
    357 
    358     /**
    359      * Variant of assertContentsInAnyOrder(String, Iterable<?>, Object...)
    360      * using a generic message.
    361      */
    362     public static void assertContentsInAnyOrder(Iterable<?> actual, Object... expected) {
    363         assertContentsInAnyOrder((String)null, actual, expected);
    364     }
    365 
    366     /**
    367      * Asserts that {@code iterable} is empty.
    368      */
    369     public static void assertEmpty(String message, Iterable<?> iterable) {
    370         if (iterable.iterator().hasNext()) {
    371             failNotEmpty(message, iterable.toString());
    372         }
    373     }
    374 
    375     /**
    376      * Variant of {@link #assertEmpty(String, Iterable)} using a
    377      * generic message.
    378      */
    379     public static void assertEmpty(Iterable<?> iterable) {
    380         assertEmpty(null, iterable);
    381     }
    382 
    383     /**
    384      * Asserts that {@code map} is empty.
    385      */
    386     public static void assertEmpty(String message, Map<?,?> map) {
    387         if (!map.isEmpty()) {
    388             failNotEmpty(message, map.toString());
    389         }
    390     }
    391 
    392     /**
    393      * Variant of {@link #assertEmpty(String, Map)} using a generic
    394      * message.
    395      */
    396     public  static void assertEmpty(Map<?,?> map) {
    397         assertEmpty(null, map);
    398     }
    399 
    400     /**
    401      * Asserts that {@code iterable} is not empty.
    402      */
    403     public static void assertNotEmpty(String message, Iterable<?> iterable) {
    404         if (!iterable.iterator().hasNext()) {
    405             failEmpty(message);
    406         }
    407     }
    408 
    409     /**
    410      * Variant of assertNotEmpty(String, Iterable<?>)
    411      * using a generic message.
    412      */
    413     public static void assertNotEmpty(Iterable<?> iterable) {
    414         assertNotEmpty(null, iterable);
    415     }
    416 
    417     /**
    418      * Asserts that {@code map} is not empty.
    419      */
    420     public static void assertNotEmpty(String message, Map<?,?> map) {
    421         if (map.isEmpty()) {
    422             failEmpty(message);
    423         }
    424     }
    425 
    426     /**
    427      * Variant of {@link #assertNotEmpty(String, Map)} using a generic
    428      * message.
    429      */
    430     public static void assertNotEmpty(Map<?,?> map) {
    431         assertNotEmpty(null, map);
    432     }
    433 
    434     /**
    435      * Utility for testing equals() and hashCode() results at once.
    436      * Tests that lhs.equals(rhs) matches expectedResult, as well as
    437      * rhs.equals(lhs).  Also tests that hashCode() return values are
    438      * equal if expectedResult is true.  (hashCode() is not tested if
    439      * expectedResult is false, as unequal objects can have equal hashCodes.)
    440      *
    441      * @param lhs An Object for which equals() and hashCode() are to be tested.
    442      * @param rhs As lhs.
    443      * @param expectedResult True if the objects should compare equal,
    444      *   false if not.
    445      */
    446     public static void checkEqualsAndHashCodeMethods(
    447             String message, Object lhs, Object rhs, boolean expectedResult) {
    448 
    449         if ((lhs == null) && (rhs == null)) {
    450             Assert.assertTrue(
    451                     "Your check is dubious...why would you expect null != null?",
    452                     expectedResult);
    453             return;
    454         }
    455 
    456         if ((lhs == null) || (rhs == null)) {
    457             Assert.assertFalse(
    458                     "Your check is dubious...why would you expect an object "
    459                             + "to be equal to null?", expectedResult);
    460         }
    461 
    462         if (lhs != null) {
    463             Assert.assertEquals(message, expectedResult, lhs.equals(rhs));
    464         }
    465         if (rhs != null) {
    466             Assert.assertEquals(message, expectedResult, rhs.equals(lhs));
    467         }
    468 
    469         if (expectedResult) {
    470             String hashMessage =
    471                     "hashCode() values for equal objects should be the same";
    472             if (message != null) {
    473                 hashMessage += ": " + message;
    474             }
    475             Assert.assertTrue(hashMessage, lhs.hashCode() == rhs.hashCode());
    476         }
    477     }
    478 
    479     /**
    480      * Variant of
    481      * checkEqualsAndHashCodeMethods(String,Object,Object,boolean...)}
    482      * using a generic message.
    483      */
    484     public static void checkEqualsAndHashCodeMethods(Object lhs, Object rhs,
    485             boolean expectedResult) {
    486         checkEqualsAndHashCodeMethods((String) null, lhs, rhs, expectedResult);
    487     }
    488 
    489     private static Matcher getMatcher(String expectedRegex, String actual) {
    490         Pattern pattern = Pattern.compile(expectedRegex);
    491         return pattern.matcher(actual);
    492     }
    493 
    494     private static void failEqual(String message, Object unexpected) {
    495         failWithMessage(message, "expected not to be:<" + unexpected + ">");
    496     }
    497 
    498     private static void failWrongLength(
    499             String message, int expected, int actual) {
    500         failWithMessage(message, "expected array length:<" + expected
    501                 + "> but was:<" + actual + '>');
    502     }
    503 
    504     private static void failWrongElement(
    505             String message, int index, Object expected, Object actual) {
    506         failWithMessage(message, "expected array element[" + index + "]:<"
    507                 + expected + "> but was:<" + actual + '>');
    508     }
    509 
    510     private static void failNotMatches(
    511             String message, String expectedRegex, String actual) {
    512         String actualDesc = (actual == null) ? "null" : ('<' + actual + '>');
    513         failWithMessage(message, "expected to match regex:<" + expectedRegex
    514                 + "> but was:" + actualDesc);
    515     }
    516 
    517     private static void failNotContains(
    518             String message, String expectedRegex, String actual) {
    519         String actualDesc = (actual == null) ? "null" : ('<' + actual + '>');
    520         failWithMessage(message, "expected to contain regex:<" + expectedRegex
    521                 + "> but was:" + actualDesc);
    522     }
    523 
    524     private static void failMatch(
    525             String message, String expectedRegex, String actual) {
    526         failWithMessage(message, "expected not to match regex:<" + expectedRegex
    527                 + "> but was:<" + actual + '>');
    528     }
    529 
    530     private static void failContains(
    531             String message, String expectedRegex, String actual) {
    532         failWithMessage(message, "expected not to contain regex:<" + expectedRegex
    533                 + "> but was:<" + actual + '>');
    534     }
    535 
    536     private static void failNotEmpty(
    537             String message, String actual) {
    538         failWithMessage(message, "expected to be empty, but contained: <"
    539                 + actual + ">");
    540     }
    541 
    542     private static void failEmpty(String message) {
    543         failWithMessage(message, "expected not to be empty, but was");
    544     }
    545 
    546     private static void failWithMessage(String userMessage, String ourMessage) {
    547         Assert.fail((userMessage == null)
    548                 ? ourMessage
    549                 : userMessage + ' ' + ourMessage);
    550     }
    551 
    552     private static boolean equal(Object a, Object b) {
    553         return a == b || (a != null && a.equals(b));
    554     }
    555 
    556 }
    557