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