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 junit.framework.Assert;
20 
21 import java.util.Arrays;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.Map;
25 import java.util.Set;
26 import java.util.ArrayList;
27 import java.util.regex.MatchResult;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30 
31 /**
32  * Contains additional assertion methods not found in JUnit.
33  */
34 public final class MoreAsserts {
35 
MoreAsserts()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      */
assertAssignableFrom(Class<?> expected, Object actual)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      */
assertAssignableFrom(Class<?> expected, Class<?> actual)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      */
assertNotEqual( String message, Object unexpected, Object actual)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      */
assertNotEqual(Object unexpected, Object actual)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      */
assertEquals( String message, byte[] expected, byte[] actual)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      */
assertEquals(byte[] expected, byte[] actual)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      */
assertEquals( String message, int[] expected, int[] actual)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      */
assertEquals(int[] expected, int[] actual)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      */
assertEquals( String message, long[] expected, long[] actual)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      */
assertEquals(long[] expected, long[] actual)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      */
assertEquals( String message, double[] expected, double[] actual)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      */
assertEquals(double[] expected, double[] actual)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      */
assertEquals( String message, Object[] expected, Object[] actual)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      */
assertEquals(Object[] expected, Object[] actual)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. */
assertEquals( String message, Set<? extends Object> expected, Set<? extends Object> actual)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. */
assertEquals(Set<? extends Object> expected, Set<? extends Object> actual)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      */
assertMatchesRegex( String message, String expectedRegex, String actual)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      */
assertMatchesRegex( String expectedRegex, String actual)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      */
assertContainsRegex( String message, String expectedRegex, String actual)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      */
assertContainsRegex( String expectedRegex, String actual)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      */
assertNotMatchesRegex( String message, String expectedRegex, String actual)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      */
assertNotMatchesRegex( String expectedRegex, String actual)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      */
assertNotContainsRegex( String message, String expectedRegex, String actual)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      */
assertNotContainsRegex( String expectedRegex, String actual)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      */
assertContentsInOrder( String message, Iterable<?> actual, Object... expected)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      */
assertContentsInOrder( Iterable<?> actual, Object... expected)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      */
assertContentsInAnyOrder(String message, Iterable<?> actual, Object... expected)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      */
assertContentsInAnyOrder(Iterable<?> actual, Object... expected)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      */
assertEmpty(String message, Iterable<?> iterable)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      */
assertEmpty(Iterable<?> iterable)405     public static void assertEmpty(Iterable<?> iterable) {
406         assertEmpty(null, iterable);
407     }
408 
409     /**
410      * Asserts that {@code map} is empty.
411      */
assertEmpty(String message, Map<?,?> map)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      */
assertEmpty(Map<?,?> map)422     public  static void assertEmpty(Map<?,?> map) {
423         assertEmpty(null, map);
424     }
425 
426     /**
427      * Asserts that {@code iterable} is not empty.
428      */
assertNotEmpty(String message, Iterable<?> iterable)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      */
assertNotEmpty(Iterable<?> iterable)439     public static void assertNotEmpty(Iterable<?> iterable) {
440         assertNotEmpty(null, iterable);
441     }
442 
443     /**
444      * Asserts that {@code map} is not empty.
445      */
assertNotEmpty(String message, Map<?,?> map)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      */
assertNotEmpty(Map<?,?> map)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      */
checkEqualsAndHashCodeMethods( String message, Object lhs, Object rhs, boolean expectedResult)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      */
checkEqualsAndHashCodeMethods(Object lhs, Object rhs, boolean expectedResult)510     public static void checkEqualsAndHashCodeMethods(Object lhs, Object rhs,
511             boolean expectedResult) {
512         checkEqualsAndHashCodeMethods((String) null, lhs, rhs, expectedResult);
513     }
514 
getMatcher(String expectedRegex, String actual)515     private static Matcher getMatcher(String expectedRegex, String actual) {
516         Pattern pattern = Pattern.compile(expectedRegex);
517         return pattern.matcher(actual);
518     }
519 
failEqual(String message, Object unexpected)520     private static void failEqual(String message, Object unexpected) {
521         failWithMessage(message, "expected not to be:<" + unexpected + ">");
522     }
523 
failWrongLength( String message, int expected, int actual)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 
failWrongElement( String message, int index, Object expected, Object actual)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 
failNotMatches( String message, String expectedRegex, String actual)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 
failNotContains( String message, String expectedRegex, String actual)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 
failMatch( String message, String expectedRegex, String actual)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 
failContains( String message, String expectedRegex, String actual)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 
failNotEmpty( String message, String actual)562     private static void failNotEmpty(
563             String message, String actual) {
564         failWithMessage(message, "expected to be empty, but contained: <"
565                 + actual + ">");
566     }
567 
failEmpty(String message)568     private static void failEmpty(String message) {
569         failWithMessage(message, "expected not to be empty, but was");
570     }
571 
failWithMessage(String userMessage, String ourMessage)572     private static void failWithMessage(String userMessage, String ourMessage) {
573         Assert.fail((userMessage == null)
574                 ? ourMessage
575                 : userMessage + ' ' + ourMessage);
576     }
577 
equal(Object a, Object b)578     private static boolean equal(Object a, Object b) {
579         return a == b || (a != null && a.equals(b));
580     }
581 
582 }
583