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 MoreAsserts()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 */ assertAssignableFrom(Class<?> expected, Object actual)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 */ assertAssignableFrom(Class<?> expected, Class<?> actual)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 */ assertNotEqual( String message, Object unexpected, Object actual)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 */ assertNotEqual(Object unexpected, Object actual)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 */ assertEquals( String message, byte[] expected, byte[] actual)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 */ assertEquals(byte[] expected, byte[] actual)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 */ assertEquals( String message, int[] expected, int[] actual)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 */ assertEquals(int[] expected, int[] actual)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 */ assertEquals( String message, double[] expected, double[] actual)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 */ assertEquals(double[] expected, double[] actual)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 */ assertEquals( String message, Object[] expected, Object[] actual)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 */ assertEquals(Object[] expected, Object[] actual)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. */ assertEquals( String message, Set<? extends Object> expected, Set<? extends Object> actual)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. */ assertEquals(Set<? extends Object> expected, Set<? extends Object> actual)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 */ assertMatchesRegex( String message, String expectedRegex, String actual)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 */ assertMatchesRegex( String expectedRegex, String actual)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 */ assertContainsRegex( String message, String expectedRegex, String actual)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 */ assertContainsRegex( String expectedRegex, String actual)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 */ assertNotMatchesRegex( String message, String expectedRegex, String actual)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 */ assertNotMatchesRegex( String expectedRegex, String actual)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 */ assertNotContainsRegex( String message, String expectedRegex, String actual)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 */ assertNotContainsRegex( String expectedRegex, String actual)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 */ assertContentsInOrder( String message, Iterable<?> actual, Object... expected)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 */ assertContentsInOrder( Iterable<?> actual, Object... expected)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 */ assertContentsInAnyOrder(String message, Iterable<?> actual, Object... expected)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 */ assertContentsInAnyOrder(Iterable<?> actual, Object... expected)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 */ assertEmpty(String message, Iterable<?> iterable)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 */ assertEmpty(Iterable<?> iterable)379 public static void assertEmpty(Iterable<?> iterable) { 380 assertEmpty(null, iterable); 381 } 382 383 /** 384 * Asserts that {@code map} is empty. 385 */ assertEmpty(String message, Map<?,?> map)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 */ assertEmpty(Map<?,?> map)396 public static void assertEmpty(Map<?,?> map) { 397 assertEmpty(null, map); 398 } 399 400 /** 401 * Asserts that {@code iterable} is not empty. 402 */ assertNotEmpty(String message, Iterable<?> iterable)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 */ assertNotEmpty(Iterable<?> iterable)413 public static void assertNotEmpty(Iterable<?> iterable) { 414 assertNotEmpty(null, iterable); 415 } 416 417 /** 418 * Asserts that {@code map} is not empty. 419 */ assertNotEmpty(String message, Map<?,?> map)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 */ assertNotEmpty(Map<?,?> map)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 */ checkEqualsAndHashCodeMethods( String message, Object lhs, Object rhs, boolean expectedResult)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 */ checkEqualsAndHashCodeMethods(Object lhs, Object rhs, boolean expectedResult)484 public static void checkEqualsAndHashCodeMethods(Object lhs, Object rhs, 485 boolean expectedResult) { 486 checkEqualsAndHashCodeMethods((String) null, lhs, rhs, expectedResult); 487 } 488 getMatcher(String expectedRegex, String actual)489 private static Matcher getMatcher(String expectedRegex, String actual) { 490 Pattern pattern = Pattern.compile(expectedRegex); 491 return pattern.matcher(actual); 492 } 493 failEqual(String message, Object unexpected)494 private static void failEqual(String message, Object unexpected) { 495 failWithMessage(message, "expected not to be:<" + unexpected + ">"); 496 } 497 failWrongLength( String message, int expected, int actual)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 failWrongElement( String message, int index, Object expected, Object actual)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 failNotMatches( String message, String expectedRegex, String actual)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 failNotContains( String message, String expectedRegex, String actual)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 failMatch( String message, String expectedRegex, String actual)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 failContains( String message, String expectedRegex, String actual)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 failNotEmpty( String message, String actual)536 private static void failNotEmpty( 537 String message, String actual) { 538 failWithMessage(message, "expected to be empty, but contained: <" 539 + actual + ">"); 540 } 541 failEmpty(String message)542 private static void failEmpty(String message) { 543 failWithMessage(message, "expected not to be empty, but was"); 544 } 545 failWithMessage(String userMessage, String ourMessage)546 private static void failWithMessage(String userMessage, String ourMessage) { 547 Assert.fail((userMessage == null) 548 ? ourMessage 549 : userMessage + ' ' + ourMessage); 550 } 551 equal(Object a, Object b)552 private static boolean equal(Object a, Object b) { 553 return a == b || (a != null && a.equals(b)); 554 } 555 556 } 557