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