1 /* 2 * Copyright 2014 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.hardware.camera2.cts.helpers; 18 19 import android.graphics.Rect; 20 import android.hardware.camera2.CameraCharacteristics; 21 import android.hardware.camera2.CaptureRequest; 22 import android.hardware.camera2.CaptureRequest.Builder; 23 import android.hardware.camera2.CaptureResult; 24 import android.hardware.camera2.params.MeteringRectangle; 25 import android.media.Image; 26 import android.util.Log; 27 import android.util.Size; 28 import java.util.ArrayList; 29 import java.util.Arrays; 30 import java.util.HashSet; 31 import java.util.List; 32 import java.util.Objects; 33 import java.util.Set; 34 import org.hamcrest.CoreMatchers; 35 import org.hamcrest.Matcher; 36 import org.junit.rules.ErrorCollector; 37 38 /** 39 * A camera test ErrorCollector class to gather the test failures during a test, 40 * instead of failing the test immediately for each failure. 41 */ 42 public class CameraErrorCollector extends ErrorCollector { 43 44 private static final String TAG = "CameraErrorCollector"; 45 private static final boolean LOG_ERRORS = Log.isLoggable(TAG, Log.ERROR); 46 47 private String mCameraMsg = ""; 48 49 @Override verify()50 public void verify() throws Throwable { 51 // Do not remove if using JUnit 3 test runners. super.verify() is protected. 52 super.verify(); 53 } 54 55 /** 56 * Adds an unconditional error to the table. 57 * 58 * <p>Execution continues, but test will fail at the end.</p> 59 * 60 * @param message A string containing the failure reason. 61 */ addMessage(String message)62 public void addMessage(String message) { 63 addErrorSuper(new Throwable(mCameraMsg + message)); 64 } 65 66 /** 67 * Adds a Throwable to the table. <p>Execution continues, but the test will fail at the end.</p> 68 */ 69 @Override addError(Throwable error)70 public void addError(Throwable error) { 71 addErrorSuper(new Throwable(mCameraMsg + error.getMessage(), error)); 72 } 73 addErrorSuper(Throwable error)74 private void addErrorSuper(Throwable error) { 75 if (LOG_ERRORS) Log.e(TAG, error.getMessage()); 76 super.addError(error); 77 } 78 79 /** 80 * Adds a failure to the table if {@code matcher} does not match {@code value}. 81 * Execution continues, but the test will fail at the end if the match fails. 82 * The camera id is included into the failure log. 83 */ 84 @Override checkThat(final T value, final Matcher<T> matcher)85 public <T> void checkThat(final T value, final Matcher<T> matcher) { 86 super.checkThat(mCameraMsg, value, matcher); 87 } 88 89 /** 90 * Adds a failure with the given {@code reason} to the table if 91 * {@code matcher} does not match {@code value}. Execution continues, but 92 * the test will fail at the end if the match fails. The camera id is 93 * included into the failure log. 94 */ 95 @Override checkThat(final String reason, final T value, final Matcher<T> matcher)96 public <T> void checkThat(final String reason, final T value, final Matcher<T> matcher) { 97 super.checkThat(mCameraMsg + reason, value, matcher); 98 } 99 100 /** 101 * Set the camera id to this error collector object for logging purpose. 102 * 103 * @param id The camera id to be set. 104 */ setCameraId(String id)105 public void setCameraId(String id) { 106 if (id != null) { 107 mCameraMsg = "Test failed for camera " + id + ": "; 108 } else { 109 mCameraMsg = ""; 110 } 111 } 112 113 /** 114 * Adds a failure to the table if {@code condition} is not {@code true}. 115 * <p> 116 * Execution continues, but the test will fail at the end if the condition 117 * failed. 118 * </p> 119 * 120 * @param msg Message to be logged when check fails. 121 * @param condition Log the failure if it is not true. 122 */ expectTrue(String msg, boolean condition)123 public boolean expectTrue(String msg, boolean condition) { 124 if (!condition) { 125 addMessage(msg); 126 } 127 128 return condition; 129 } 130 131 /** 132 * Check if the two values are equal. 133 * 134 * @param msg Message to be logged when check fails. 135 * @param expected Expected value to be checked against. 136 * @param actual Actual value to be checked. 137 * @return {@code true} if the two values are equal, {@code false} otherwise. 138 * 139 * @throws IllegalArgumentException if {@code expected} was {@code null} 140 */ expectEquals(String msg, T expected, T actual)141 public <T> boolean expectEquals(String msg, T expected, T actual) { 142 if (expected == null) { 143 throw new IllegalArgumentException("expected value shouldn't be null"); 144 } 145 146 if (!Objects.equals(expected, actual)) { 147 addMessage(String.format("%s (expected = %s, actual = %s) ", msg, expected, 148 actual)); 149 return false; 150 } 151 152 return true; 153 } 154 155 /** 156 * Check if the two values are not equal. 157 * 158 * @param msg Message to be logged when check fails. 159 * @param expected Expected value to be checked against. 160 * @param actual Actual value to be checked. 161 * @return {@code true} if the two values are not equal, {@code false} otherwise. 162 */ expectNotEquals(String msg, T expected, T actual)163 public <T> boolean expectNotEquals(String msg, T expected, T actual) { 164 if (Objects.equals(expected, actual)) { 165 addMessage(String.format("%s (expected = %s, actual = %s) ", msg, expected, 166 actual)); 167 return false; 168 } 169 170 return true; 171 } 172 173 /** 174 * Check if the two arrays of values are deeply equal. 175 * 176 * @param msg Message to be logged when check fails. 177 * @param expected Expected array of values to be checked against. 178 * @param actual Actual array of values to be checked. 179 * @return {@code true} if the two arrays of values are deeply equal, {@code false} otherwise. 180 * 181 * @throws IllegalArgumentException if {@code expected} was {@code null} 182 */ expectEquals(String msg, T[] expected, T[] actual)183 public <T> boolean expectEquals(String msg, T[] expected, T[] actual) { 184 if (expected == null) { 185 throw new IllegalArgumentException("expected value shouldn't be null"); 186 } 187 188 if (!Arrays.deepEquals(expected, actual)) { 189 addMessage(String.format("%s (expected = %s, actual = %s) ", msg, 190 Arrays.deepToString(expected), Arrays.deepToString(actual))); 191 return false; 192 } 193 194 return true; 195 } 196 197 /** 198 * Check if the two arrays of values are not deeply equal. 199 * 200 * @param msg Message to be logged when check fails. 201 * @param expected Expected array of values to be checked against. 202 * @param actual Actual array of values to be checked. 203 * @return {@code true} if the two arrays of values are not deeply equal, {@code false} 204 * otherwise. 205 * 206 * @throws IllegalArgumentException if {@code expected} was {@code null} 207 */ expectNotEquals(String msg, T[] expected, T[] actual)208 public <T> boolean expectNotEquals(String msg, T[] expected, T[] actual) { 209 if (expected == null) { 210 throw new IllegalArgumentException("expected value shouldn't be null"); 211 } 212 213 if (Arrays.deepEquals(expected, actual)) { 214 addMessage(String.format("%s (expected = %s, actual = %s) ", msg, 215 Arrays.deepToString(expected), Arrays.deepToString(actual))); 216 return false; 217 } 218 219 return true; 220 } 221 222 /** 223 * Check that the {@code actual} value is greater than the {@code expected} value. 224 * 225 * @param msg Message to be logged when check fails. 226 * @param expected The expected value to check that the actual value is larger than. 227 * @param actual Actual value to check. 228 * @return {@code true} if {@code actual} is greater than {@code expected}. 229 */ expectGreater(String msg, T expected, T actual)230 public <T extends Comparable<? super T>> boolean expectGreater(String msg, T expected, 231 T actual) { 232 return expectTrue(String.format("%s: (actual = %s was not greater than expected = %s) ", 233 msg, actual, expected), actual.compareTo(expected) > 0); 234 } 235 236 /** 237 * Check that the {@code actual} value is greater than or equal to the {@code expected} value. 238 * 239 * @param msg Message to be logged when check fails. 240 * @param expected The expected value to check that the actual value is larger than or equal to. 241 * @param actual Actual value to check. 242 * @return {@code true} if {@code actual} is greater than or equal to {@code expected}. 243 */ expectGreaterOrEqual(String msg, T expected, T actual)244 public <T extends Comparable<? super T>> boolean expectGreaterOrEqual(String msg, T expected, 245 T actual) { 246 return expectTrue(String.format("%s: (actual = %s was not greater than or equal to " 247 + "expected = %s) ", msg, actual, expected), actual.compareTo(expected) >= 0); 248 } 249 250 /** 251 * Check that the {@code actual} value is less than the {@code expected} value. 252 * 253 * @param msg Message to be logged when check fails. 254 * @param expected The expected value to check that the actual value is less than. 255 * @param actual Actual value to check. 256 * @return {@code true} if {@code actual} is less than {@code expected}. 257 */ expectLess(String msg, T expected, T actual)258 public <T extends Comparable<? super T>> boolean expectLess(String msg, T expected, 259 T actual) { 260 return expectTrue(String.format("%s: (actual = %s was not less than expected = %s) ", 261 msg, actual, expected), actual.compareTo(expected) < 0); 262 } 263 264 /** 265 * Check that the {@code actual} value is less than or equal to the {@code expected} value. 266 * 267 * @param msg Message to be logged when check fails. 268 * @param expected The expected value to check that the actual value is less than or equal to. 269 * @param actual Actual value to check. 270 * @return {@code true} if {@code actual} is less than or equal to {@code expected}. 271 */ expectLessOrEqual(String msg, T expected, T actual)272 public <T extends Comparable<? super T>> boolean expectLessOrEqual(String msg, T expected, 273 T actual) { 274 return expectTrue(String.format("%s: (actual = %s was not less than or equal to " 275 + "expected = %s) ", msg, actual, expected), actual.compareTo(expected) <= 0); 276 } 277 278 /** 279 * Check if the two float values are equal with given error tolerance. 280 * 281 * @param msg Message to be logged when check fails. 282 * @param expected Expected value to be checked against. 283 * @param actual Actual value to be checked. 284 * @param tolerance The error margin for the equality check. 285 * @return {@code true} if the two values are equal, {@code false} otherwise. 286 */ expectEquals(String msg, float expected, float actual, float tolerance)287 public <T> boolean expectEquals(String msg, float expected, float actual, float tolerance) { 288 if (expected == actual) { 289 return true; 290 } 291 292 if (!(Math.abs(expected - actual) <= tolerance)) { 293 addMessage(String.format("%s (expected = %s, actual = %s, tolerance = %s) ", msg, 294 expected, actual, tolerance)); 295 return false; 296 } 297 298 return true; 299 } 300 301 /** 302 * Check if the two double values are equal with given error tolerance. 303 * 304 * @param msg Message to be logged when check fails. 305 * @param expected Expected value to be checked against. 306 * @param actual Actual value to be checked. 307 * @param tolerance The error margin for the equality check 308 * @return {@code true} if the two values are equal, {@code false} otherwise. 309 */ expectEquals(String msg, double expected, double actual, double tolerance)310 public <T> boolean expectEquals(String msg, double expected, double actual, double tolerance) { 311 if (expected == actual) { 312 return true; 313 } 314 315 if (!(Math.abs(expected - actual) <= tolerance)) { 316 addMessage(String.format("%s (expected = %s, actual = %s, tolerance = %s) ", msg, 317 expected, actual, tolerance)); 318 return false; 319 } 320 321 return true; 322 } 323 324 /** 325 * Check that all values in the list are greater than or equal to the min value. 326 * 327 * @param msg Message to be logged when check fails 328 * @param list The list of values to be checked 329 * @param min The smallest allowed value 330 */ expectValuesGreaterOrEqual(String msg, List<T> list, T min)331 public <T extends Comparable<? super T>> void expectValuesGreaterOrEqual(String msg, 332 List<T> list, T min) { 333 for (T value : list) { 334 expectTrue(msg + String.format(", array value " + value.toString() + 335 " is less than %s", 336 min.toString()), value.compareTo(min) >= 0); 337 } 338 } 339 340 /** 341 * Check that all values in the array are greater than or equal to the min value. 342 * 343 * @param msg Message to be logged when check fails 344 * @param array The array of values to be checked 345 * @param min The smallest allowed value 346 */ expectValuesGreaterOrEqual(String msg, T[] array, T min)347 public <T extends Comparable<? super T>> void expectValuesGreaterOrEqual(String msg, 348 T[] array, T min) { 349 expectValuesGreaterOrEqual(msg, Arrays.asList(array), min); 350 } 351 352 /** 353 * Expect the list of values are in the range. 354 * 355 * @param msg Message to be logged 356 * @param list The list of values to be checked 357 * @param min The min value of the range 358 * @param max The max value of the range 359 */ expectValuesInRange(String msg, List<T> list, T min, T max)360 public <T extends Comparable<? super T>> void expectValuesInRange(String msg, List<T> list, 361 T min, T max) { 362 for (T value : list) { 363 expectTrue(msg + String.format(", array value " + value.toString() + 364 " is out of range [%s, %s]", 365 min.toString(), max.toString()), 366 value.compareTo(max)<= 0 && value.compareTo(min) >= 0); 367 } 368 } 369 370 /** 371 * Expect the array of values are in the range. 372 * 373 * @param msg Message to be logged 374 * @param array The array of values to be checked 375 * @param min The min value of the range 376 * @param max The max value of the range 377 */ expectValuesInRange(String msg, T[] array, T min, T max)378 public <T extends Comparable<? super T>> void expectValuesInRange(String msg, T[] array, 379 T min, T max) { 380 expectValuesInRange(msg, Arrays.asList(array), min, max); 381 } 382 383 /** 384 * Expect the array of values are in the range. 385 * 386 * @param msg Message to be logged 387 * @param array The array of values to be checked 388 * @param min The min value of the range 389 * @param max The max value of the range 390 */ expectValuesInRange(String msg, int[] array, int min, int max)391 public void expectValuesInRange(String msg, int[] array, int min, int max) { 392 ArrayList<Integer> l = new ArrayList<>(array.length); 393 for (int i : array) { 394 l.add(i); 395 } 396 expectValuesInRange(msg, l, min, max); 397 } 398 399 /** 400 * Expect the value is in the range. 401 * 402 * @param msg Message to be logged 403 * @param value The value to be checked 404 * @param min The min value of the range 405 * @param max The max value of the range 406 * 407 * @return {@code true} if the value was in range, {@code false} otherwise 408 */ expectInRange(String msg, T value, T min, T max)409 public <T extends Comparable<? super T>> boolean expectInRange(String msg, T value, 410 T min, T max) { 411 return expectTrue(msg + String.format(", value " + value.toString() 412 + " is out of range [%s, %s]", 413 min.toString(), max.toString()), 414 value.compareTo(max)<= 0 && value.compareTo(min) >= 0); 415 } 416 417 418 /** 419 * Check that two metering region arrays are similar enough by ensuring that each of their width, 420 * height, and all corners are within {@code errorPercent} of each other. 421 * 422 * <p>Note that the length of the arrays must be the same, and each weight must be the same 423 * as well. We assume the order is also equivalent.</p> 424 * 425 * <p>At most 1 error per each dissimilar metering region is collected.</p> 426 * 427 * @param msg Message to be logged 428 * @param expected The reference 'expected' values to be used to check against 429 * @param actual The actual values that were received 430 * @param errorPercent Within how many percent the components should be 431 * 432 * @return {@code true} if all expects passed, {@code false} otherwise 433 */ expectMeteringRegionsAreSimilar(String msg, MeteringRectangle[] expected, MeteringRectangle[] actual, float errorPercent)434 public boolean expectMeteringRegionsAreSimilar(String msg, 435 MeteringRectangle[] expected, MeteringRectangle[] actual, 436 float errorPercent) { 437 String expectedActualMsg = String.format("expected (%s), actual (%s)", 438 Arrays.deepToString(expected), Arrays.deepToString(actual)); 439 440 String differentSizesMsg = String.format( 441 "%s: rect lists are different sizes; %s", 442 msg, expectedActualMsg); 443 444 String differentWeightsMsg = String.format( 445 "%s: rect weights are different; %s", 446 msg, expectedActualMsg); 447 448 if (!expectTrue(differentSizesMsg, actual != null)) { 449 return false; 450 } 451 452 if (!expectEquals(differentSizesMsg, expected.length, actual.length)) return false; 453 454 boolean succ = true; 455 for (int i = 0; i < expected.length; ++i) { 456 if (i < actual.length) { 457 if (actual[i].equals(expected[i])) { 458 continue; 459 } 460 // Avoid printing multiple errors for the same rectangle 461 if (!expectRectsAreSimilar( 462 msg, expected[i].getRect(), actual[i].getRect(), errorPercent)) { 463 succ = false; 464 continue; 465 } 466 if (!expectEquals(differentWeightsMsg, 467 expected[i].getMeteringWeight(), actual[i].getMeteringWeight())) { 468 succ = false; 469 continue; 470 } 471 } 472 } 473 474 return succ; 475 } 476 477 /** 478 * Check that two rectangles are similar enough by ensuring that their width, height, 479 * and all corners are within {@code errorPercent} of each other. 480 * 481 * <p>Only the first error is collected, to avoid spamming several error messages when 482 * the rectangle is hugely dissimilar.</p> 483 * 484 * @param msg Message to be logged 485 * @param expected The reference 'expected' value to be used to check against 486 * @param actual The actual value that was received 487 * @param errorPercent Within how many percent the components should be 488 * 489 * @return {@code true} if all expects passed, {@code false} otherwise 490 */ expectRectsAreSimilar(String msg, Rect expected, Rect actual, float errorPercent)491 public boolean expectRectsAreSimilar(String msg, Rect expected, Rect actual, 492 float errorPercent) { 493 String formattedMsg = String.format("%s: rects are not similar enough; expected (%s), " + 494 "actual (%s), error percent (%s), reason: ", 495 msg, expected, actual, errorPercent); 496 497 if (!expectSimilarValues( 498 formattedMsg, "too wide", "too narrow", actual.width(), expected.width(), 499 errorPercent)) return false; 500 501 if (!expectSimilarValues( 502 formattedMsg, "too tall", "too short", actual.height(), expected.height(), 503 errorPercent)) return false; 504 505 if (!expectSimilarValues( 506 formattedMsg, "too low", "too high", actual.centerY(), expected.centerY(), 507 errorPercent)) return false; 508 509 if (!expectSimilarValues( 510 formattedMsg, "too right", "too left", actual.centerX(), expected.centerX(), 511 errorPercent)) return false; 512 513 return true; 514 } 515 516 /** 517 * Check that two sizes are similar enough by ensuring that their width and height 518 * are within {@code errorPercent} of each other. 519 * 520 * <p>Only the first error is collected, to avoid spamming several error messages when 521 * the rectangle is hugely dissimilar.</p> 522 * 523 * @param msg Message to be logged 524 * @param expected The reference 'expected' value to be used to check against 525 * @param actual The actual value that was received 526 * @param errorPercent Within how many percent the components should be 527 * 528 * @return {@code true} if all expects passed, {@code false} otherwise 529 */ expectSizesAreSimilar(String msg, Size expected, Size actual, float errorPercent)530 public boolean expectSizesAreSimilar(String msg, Size expected, Size actual, 531 float errorPercent) { 532 String formattedMsg = String.format("%s: rects are not similar enough; expected (%s), " + 533 "actual (%s), error percent (%s), reason: ", 534 msg, expected, actual, errorPercent); 535 536 if (!expectSimilarValues( 537 formattedMsg, "too wide", "too narrow", actual.getWidth(), expected.getWidth(), 538 errorPercent)) return false; 539 540 if (!expectSimilarValues( 541 formattedMsg, "too tall", "too short", actual.getHeight(), expected.getHeight(), 542 errorPercent)) return false; 543 544 return true; 545 } 546 547 /** 548 * Check that the rectangle is centered within a certain tolerance of {@code errorPercent}, 549 * with respect to the {@code bounds} bounding rectangle. 550 * 551 * @param msg Message to be logged 552 * @param expectedBounds The width/height of the bounding rectangle 553 * @param actual The actual value that was received 554 * @param errorPercent Within how many percent the centering should be 555 */ expectRectCentered(String msg, Size expectedBounds, Rect actual, float errorPercent)556 public void expectRectCentered(String msg, Size expectedBounds, Rect actual, 557 float errorPercent) { 558 String formattedMsg = String.format("%s: rect should be centered; expected bounds (%s), " + 559 "actual (%s), error percent (%s), reason: ", 560 msg, expectedBounds, actual, errorPercent); 561 562 int centerBoundX = expectedBounds.getWidth() / 2; 563 int centerBoundY = expectedBounds.getHeight() / 2; 564 565 expectSimilarValues( 566 formattedMsg, "too low", "too high", actual.centerY(), centerBoundY, 567 errorPercent); 568 569 expectSimilarValues( 570 formattedMsg, "too right", "too left", actual.centerX(), centerBoundX, 571 errorPercent); 572 } 573 expectSimilarValues( String formattedMsg, String tooSmall, String tooLarge, int actualValue, int expectedValue, float errorPercent)574 private boolean expectSimilarValues( 575 String formattedMsg, String tooSmall, String tooLarge, int actualValue, 576 int expectedValue, float errorPercent) { 577 boolean succ = true; 578 succ = expectTrue(formattedMsg + tooLarge, 579 actualValue <= (expectedValue * (1.0f + errorPercent))) && succ; 580 succ = expectTrue(formattedMsg + tooSmall, 581 actualValue >= (expectedValue * (1.0f - errorPercent))) && succ; 582 583 return succ; 584 } 585 expectNotNull(String msg, Object obj)586 public void expectNotNull(String msg, Object obj) { 587 checkThat(msg, obj, CoreMatchers.notNullValue()); 588 } 589 expectNull(String msg, Object obj)590 public void expectNull(String msg, Object obj) { 591 if (obj != null) { 592 addMessage(msg); 593 } 594 } 595 596 /** 597 * Check if the values in the array are monotonically increasing (decreasing) and not all 598 * equal. 599 * 600 * @param array The array of values to be checked 601 * @param ascendingOrder The monotonicity ordering to be checked with 602 */ checkArrayMonotonicityAndNotAllEqual(T[] array, boolean ascendingOrder)603 public <T extends Comparable<? super T>> void checkArrayMonotonicityAndNotAllEqual(T[] array, 604 boolean ascendingOrder) { 605 String orderMsg = ascendingOrder ? ("increasing order") : ("decreasing order"); 606 for (int i = 0; i < array.length - 1; i++) { 607 int compareResult = array[i + 1].compareTo(array[i]); 608 boolean condition = compareResult >= 0; 609 if (!ascendingOrder) { 610 condition = compareResult <= 0; 611 } 612 613 expectTrue(String.format("Adjacent values (%s and %s) %s monotonicity is broken", 614 array[i].toString(), array[i + 1].toString(), orderMsg), condition); 615 } 616 617 expectTrue("All values of this array are equal: " + array[0].toString(), 618 array[0].compareTo(array[array.length - 1]) != 0); 619 } 620 621 /** 622 * Check if the key value is not null and return the value. 623 * 624 * @param characteristics The {@link CameraCharacteristics} to get the key from. 625 * @param key The {@link CameraCharacteristics} key to be checked. 626 * 627 * @return The value of the key. 628 */ expectKeyValueNotNull(CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key)629 public <T> T expectKeyValueNotNull(CameraCharacteristics characteristics, 630 CameraCharacteristics.Key<T> key) { 631 632 T value = characteristics.get(key); 633 if (value == null) { 634 addMessage("Key " + key.getName() + " shouldn't be null"); 635 } 636 637 return value; 638 } 639 640 /** 641 * Check if the key value is not null and return the value. 642 * 643 * @param request The {@link CaptureRequest} to get the key from. 644 * @param key The {@link CaptureRequest} key to be checked. 645 * 646 * @return The value of the key. 647 */ expectKeyValueNotNull(CaptureRequest request, CaptureRequest.Key<T> key)648 public <T> T expectKeyValueNotNull(CaptureRequest request, 649 CaptureRequest.Key<T> key) { 650 651 T value = request.get(key); 652 if (value == null) { 653 addMessage("Key " + key.getName() + " shouldn't be null"); 654 } 655 656 return value; 657 } 658 659 /** 660 * Check if the key value is not null and return the value. 661 * 662 * @param request The {@link CaptureRequest#Builder} to get the key from. 663 * @param key The {@link CaptureRequest} key to be checked. 664 * @return The value of the key. 665 */ expectKeyValueNotNull(Builder request, CaptureRequest.Key<T> key)666 public <T> T expectKeyValueNotNull(Builder request, CaptureRequest.Key<T> key) { 667 668 T value = request.get(key); 669 if (value == null) { 670 addMessage("Key " + key.getName() + " shouldn't be null"); 671 } 672 673 return value; 674 } 675 676 /** 677 * Check if the key value is not null and return the value. 678 * 679 * @param result The {@link CaptureResult} to get the key from. 680 * @param key The {@link CaptureResult} key to be checked. 681 * @return The value of the key. 682 */ expectKeyValueNotNull(CaptureResult result, CaptureResult.Key<T> key)683 public <T> T expectKeyValueNotNull(CaptureResult result, CaptureResult.Key<T> key) { 684 return expectKeyValueNotNull("", result, key); 685 } 686 687 /** 688 * Check if the key value is not null and return the value. 689 * 690 * @param msg The message to be logged. 691 * @param result The {@link CaptureResult} to get the key from. 692 * @param key The {@link CaptureResult} key to be checked. 693 * @return The value of the key. 694 */ expectKeyValueNotNull(String msg, CaptureResult result, CaptureResult.Key<T> key)695 public <T> T expectKeyValueNotNull(String msg, CaptureResult result, CaptureResult.Key<T> key) { 696 697 T value = result.get(key); 698 if (value == null) { 699 addMessage(msg + " Key " + key.getName() + " shouldn't be null"); 700 } 701 702 return value; 703 } 704 705 /** 706 * Check if the key is non-null and the value is not equal to target. 707 * 708 * @param request The The {@link CaptureRequest#Builder} to get the key from. 709 * @param key The {@link CaptureRequest} key to be checked. 710 * @param expected The expected value of the CaptureRequest key. 711 */ expectKeyValueNotEquals( Builder request, CaptureRequest.Key<T> key, T expected)712 public <T> void expectKeyValueNotEquals( 713 Builder request, CaptureRequest.Key<T> key, T expected) { 714 if (request == null || key == null || expected == null) { 715 throw new IllegalArgumentException("request, key and expected shouldn't be null"); 716 } 717 718 T value; 719 if ((value = expectKeyValueNotNull(request, key)) == null) { 720 return; 721 } 722 723 String reason = "Key " + key.getName() + " shouldn't have value " + value.toString(); 724 checkThat(reason, value, CoreMatchers.not(expected)); 725 } 726 727 /** 728 * Check if the key is non-null and the value is not equal to target. 729 * 730 * @param result The {@link CaptureResult} to get the key from. 731 * @param key The {@link CaptureResult} key to be checked. 732 * @param expected The expected value of the CaptureResult key. 733 */ expectKeyValueNotEquals( CaptureResult result, CaptureResult.Key<T> key, T expected)734 public <T> void expectKeyValueNotEquals( 735 CaptureResult result, CaptureResult.Key<T> key, T expected) { 736 if (result == null || key == null || expected == null) { 737 throw new IllegalArgumentException("result, key and expected shouldn't be null"); 738 } 739 740 T value; 741 if ((value = expectKeyValueNotNull(result, key)) == null) { 742 return; 743 } 744 745 String reason = "Key " + key.getName() + " shouldn't have value " + value.toString(); 746 checkThat(reason, value, CoreMatchers.not(expected)); 747 } 748 749 /** 750 * Check if the value is non-null and the value is equal to target. 751 * 752 * @param result The {@link CaptureResult} to lookup the value in. 753 * @param key The {@link CaptureResult} key to be checked. 754 * @param expected The expected value of the {@link CaptureResult} key. 755 */ expectKeyValueEquals(CaptureResult result, CaptureResult.Key<T> key, T expected)756 public <T> void expectKeyValueEquals(CaptureResult result, CaptureResult.Key<T> key, 757 T expected) { 758 if (result == null || key == null || expected == null) { 759 throw new IllegalArgumentException("request, key and expected shouldn't be null"); 760 } 761 762 T value; 763 if ((value = expectKeyValueNotNull(result, key)) == null) { 764 return; 765 } 766 767 String reason = "Key " + key.getName() + " value " + value.toString() 768 + " doesn't match the expected value " + expected.toString(); 769 checkThat(reason, value, CoreMatchers.equalTo(expected)); 770 } 771 772 /** 773 * Check if the key is non-null and the value is equal to target. 774 * 775 * <p>Only check non-null if the target is null.</p> 776 * 777 * @param request The The {@link CaptureRequest#Builder} to get the key from. 778 * @param key The {@link CaptureRequest} key to be checked. 779 * @param expected The expected value of the CaptureRequest key. 780 */ expectKeyValueEquals(Builder request, CaptureRequest.Key<T> key, T expected)781 public <T> void expectKeyValueEquals(Builder request, CaptureRequest.Key<T> key, T expected) { 782 if (request == null || key == null || expected == null) { 783 throw new IllegalArgumentException("request, key and expected shouldn't be null"); 784 } 785 786 T value; 787 if ((value = expectKeyValueNotNull(request, key)) == null) { 788 return; 789 } 790 791 String reason = "Key " + key.getName() + " value " + value.toString() 792 + " doesn't match the expected value " + expected.toString(); 793 checkThat(reason, value, CoreMatchers.equalTo(expected)); 794 } 795 796 /** 797 * Check if the key is non-null, and the key value is greater than the expected value. 798 * 799 * @param result {@link CaptureResult} to check. 800 * @param key The {@link CaptureResult} key to be checked. 801 * @param expected The expected to be compared to the value for the given key. 802 */ expectKeyValueGreaterOrEqual( CaptureResult result, CaptureResult.Key<T> key, T expected)803 public <T extends Comparable<? super T>> void expectKeyValueGreaterOrEqual( 804 CaptureResult result, CaptureResult.Key<T> key, T expected) { 805 T value; 806 if ((value = expectKeyValueNotNull(result, key)) == null) { 807 return; 808 } 809 810 expectGreaterOrEqual(key.getName(), expected, value); 811 } 812 813 /** 814 * Check if the key is non-null, and the key value is greater than the expected value. 815 * 816 * @param characteristics {@link CameraCharacteristics} to check. 817 * @param key The {@link CameraCharacteristics} key to be checked. 818 * @param expected The expected to be compared to the value for the given key. 819 */ expectKeyValueGreaterThan( CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T expected)820 public <T extends Comparable<? super T>> void expectKeyValueGreaterThan( 821 CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T expected) { 822 T value; 823 if ((value = expectKeyValueNotNull(characteristics, key)) == null) { 824 return; 825 } 826 827 expectGreater(key.getName(), expected, value); 828 } 829 830 /** 831 * Check if the key is non-null, and the key value is in the expected range. 832 * 833 * @param characteristics {@link CameraCharacteristics} to check. 834 * @param key The {@link CameraCharacteristics} key to be checked. 835 * @param min The min value of the range 836 * @param max The max value of the range 837 */ expectKeyValueInRange( CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T min, T max)838 public <T extends Comparable<? super T>> void expectKeyValueInRange( 839 CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T min, T max) { 840 T value; 841 if ((value = expectKeyValueNotNull(characteristics, key)) == null) { 842 return; 843 } 844 expectInRange(key.getName(), value, min, max); 845 } 846 847 /** 848 * Check if the key is non-null, and the key value is in the expected range. 849 * 850 * @param request {@link CaptureRequest.Builder} to check. 851 * @param key The {@link CaptureRequest} key to be checked. 852 * @param min The min value of the range 853 * @param max The max value of the range 854 */ expectKeyValueInRange( Builder request, CaptureRequest.Key<T> key, T min, T max)855 public <T extends Comparable<? super T>> void expectKeyValueInRange( 856 Builder request, CaptureRequest.Key<T> key, T min, T max) { 857 T value; 858 if ((value = expectKeyValueNotNull(request, key)) == null) { 859 return; 860 } 861 expectInRange(key.getName(), value, min, max); 862 } 863 864 /** 865 * Check if the key is non-null, and the key value is one of the expected values. 866 * 867 * @param characteristics {@link CameraCharacteristics} to check. 868 * @param key The {@link CameraCharacteristics} key to be checked. 869 * @param expected The expected values for the given key. 870 */ expectKeyValueIsIn(CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T... expected)871 public <T> void expectKeyValueIsIn(CameraCharacteristics characteristics, 872 CameraCharacteristics.Key<T> key, T... expected) { 873 T value = expectKeyValueNotNull(characteristics, key); 874 if (value == null) { 875 return; 876 } 877 String reason = "Key " + key.getName() + " value " + value 878 + " isn't one of the expected values " + Arrays.deepToString(expected); 879 expectContains(reason, expected, value); 880 } 881 882 /** 883 * Check if the key is non-null, and the key value is one of the expected values. 884 * 885 * @param request The The {@link CaptureRequest#Builder} to get the key from. 886 * @param key The {@link CaptureRequest} key to be checked. 887 * @param expected The expected values of the CaptureRequest key. 888 */ expectKeyValueIsIn(Builder request, CaptureRequest.Key<T> key, T... expected)889 public <T> void expectKeyValueIsIn(Builder request, CaptureRequest.Key<T> key, T... expected) { 890 T value = expectKeyValueNotNull(request, key); 891 if (value == null) { 892 return; 893 } 894 String reason = "Key " + key.getName() + " value " + value 895 + " isn't one of the expected values " + Arrays.deepToString(expected); 896 expectContains(reason, expected, value); 897 } 898 899 /** 900 * Check if the key is non-null, and the key value is one of the expected values. 901 * 902 * @param result {@link CaptureResult} to get the key from. 903 * @param key The {@link CaptureResult} key to be checked. 904 * @param expected The expected values of the CaptureResult key. 905 */ expectKeyValueIsIn(CaptureResult result, CaptureResult.Key<T> key, T... expected)906 public <T> void expectKeyValueIsIn(CaptureResult result, 907 CaptureResult.Key<T> key, T... expected) { 908 T value = expectKeyValueNotNull(result, key); 909 if (value == null) { 910 return; 911 } 912 String reason = "Key " + key.getName() + " value " + value 913 + " isn't one of the expected values " + Arrays.deepToString(expected); 914 expectContains(reason, expected, value); 915 } 916 917 /** 918 * Check if the key is non-null, and the key value contains the expected element. 919 * 920 * @param characteristics {@link CameraCharacteristics} to check. 921 * @param key The {@link CameraCharacteristics} key to be checked. 922 * @param expected The expected element to be contained in the value for the given key. 923 */ expectKeyValueContains(CameraCharacteristics characteristics, CameraCharacteristics.Key<T[]> key, T expected)924 public <T> void expectKeyValueContains(CameraCharacteristics characteristics, 925 CameraCharacteristics.Key<T[]> key, T expected) { 926 T[] value; 927 if ((value = expectKeyValueNotNull(characteristics, key)) == null) { 928 return; 929 } 930 String reason = "Key " + key.getName() + " value " + Arrays.toString(value) 931 + " doesn't contain the expected value " + expected; 932 expectContains(reason, value, expected); 933 } 934 935 /** 936 * Check if the key is non-null, and the key value contains the expected element. 937 * 938 * @param characteristics {@link CameraCharacteristics} to check. 939 * @param key The {@link CameraCharacteristics} key to be checked. 940 * @param expected The expected element to be contained in the value for the given key. 941 */ expectKeyValueContains(CameraCharacteristics characteristics, CameraCharacteristics.Key<int[]> key, int expected)942 public void expectKeyValueContains(CameraCharacteristics characteristics, 943 CameraCharacteristics.Key<int[]> key, int expected) { 944 int[] value; 945 if ((value = expectKeyValueNotNull(characteristics, key)) == null) { 946 return; 947 } 948 String reason = "Key " + key.getName() + " value " + Arrays.toString(value) 949 + " doesn't contain the expected value " + expected; 950 expectContains(reason, value, expected); 951 } 952 953 /** 954 * Check if the key is non-null, and the key value contains the expected element. 955 * 956 * @param characteristics {@link CameraCharacteristics} to check. 957 * @param key The {@link CameraCharacteristics} key to be checked. 958 * @param expected The expected element to be contained in the value for the given key. 959 */ expectKeyValueContains(CameraCharacteristics characteristics, CameraCharacteristics.Key<boolean[]> key, boolean expected)960 public void expectKeyValueContains(CameraCharacteristics characteristics, 961 CameraCharacteristics.Key<boolean[]> key, boolean expected) { 962 boolean[] value; 963 if ((value = expectKeyValueNotNull(characteristics, key)) == null) { 964 return; 965 } 966 String reason = "Key " + key.getName() + " value " + Arrays.toString(value) 967 + " doesn't contain the expected value " + expected; 968 expectContains(reason, value, expected); 969 } 970 971 /** 972 * Check if the {@code values} array contains the expected element. 973 * 974 * @param reason reason to print for failure. 975 * @param values array to check for membership in. 976 * @param expected the value to check. 977 */ expectContains(String reason, T[] values, T expected)978 public <T> void expectContains(String reason, T[] values, T expected) { 979 if (values == null) { 980 throw new NullPointerException(); 981 } 982 checkThat(reason, expected, InMatcher.in(values)); 983 } 984 expectContains(T[] values, T expected)985 public <T> void expectContains(T[] values, T expected) { 986 String reason = "Expected value " + expected 987 + " is not contained in the given values " + Arrays.toString(values); 988 expectContains(reason, values, expected); 989 } 990 991 /** 992 * Specialize {@link InMatcher} class for integer primitive array. 993 */ 994 private static class IntInMatcher extends InMatcher<Integer> { IntInMatcher(int[] values)995 public IntInMatcher(int[] values) { 996 Preconditions.checkNotNull("values", values); 997 mValues = new ArrayList<>(values.length); 998 for (int i : values) { 999 mValues.add(i); 1000 } 1001 } 1002 } 1003 1004 /** 1005 * Check if the {@code values} array contains the expected element. 1006 * 1007 * <p>Specialized for primitive int arrays</p> 1008 * 1009 * @param reason reason to print for failure. 1010 * @param values array to check for membership in. 1011 * @param expected the value to check. 1012 */ expectContains(String reason, int[] values, int expected)1013 public void expectContains(String reason, int[] values, int expected) { 1014 if (values == null) { 1015 throw new NullPointerException(); 1016 } 1017 1018 checkThat(reason, expected, new IntInMatcher(values)); 1019 } 1020 expectContains(int[] values, int expected)1021 public void expectContains(int[] values, int expected) { 1022 String reason = "Expected value " + expected 1023 + " is not contained in the given values " + Arrays.toString(values); 1024 expectContains(reason, values, expected); 1025 } 1026 1027 /** 1028 * Specialize {@link BooleanInMatcher} class for boolean primitive array. 1029 */ 1030 private static class BooleanInMatcher extends InMatcher<Boolean> { BooleanInMatcher(boolean[] values)1031 public BooleanInMatcher(boolean[] values) { 1032 Preconditions.checkNotNull("values", values); 1033 mValues = new ArrayList<>(values.length); 1034 for (boolean i : values) { 1035 mValues.add(i); 1036 } 1037 } 1038 } 1039 1040 /** 1041 * Check if the {@code values} array contains the expected element. 1042 * 1043 * <p>Specialized for primitive boolean arrays</p> 1044 * 1045 * @param reason reason to print for failure. 1046 * @param values array to check for membership in. 1047 * @param expected the value to check. 1048 */ expectContains(String reason, boolean[] values, boolean expected)1049 public void expectContains(String reason, boolean[] values, boolean expected) { 1050 if (values == null) { 1051 throw new NullPointerException(); 1052 } 1053 1054 checkThat(reason, expected, new BooleanInMatcher(values)); 1055 } 1056 1057 /** 1058 * Check if the {@code values} array contains the expected element. 1059 * 1060 * <p>Specialized for primitive boolean arrays</p> 1061 * 1062 * @param values array to check for membership in. 1063 * @param expected the value to check. 1064 */ expectContains(boolean[] values, boolean expected)1065 public void expectContains(boolean[] values, boolean expected) { 1066 String reason = "Expected value " + expected 1067 + " is not contained in the given values " + Arrays.toString(values); 1068 expectContains(reason, values, expected); 1069 } 1070 1071 /** 1072 * Check if the element inside of the list are unique. 1073 * 1074 * @param msg The message to be logged 1075 * @param list The list of values to be checked 1076 */ expectValuesUnique(String msg, List<T> list)1077 public <T> void expectValuesUnique(String msg, List<T> list) { 1078 Set<T> sizeSet = new HashSet<T>(list); 1079 expectTrue(msg + " each element must be distinct", sizeSet.size() == list.size()); 1080 } 1081 expectImageProperties(String msg, Image image, int format, Size size, long timestampNs)1082 public void expectImageProperties(String msg, Image image, int format, Size size, 1083 long timestampNs) { 1084 expectEquals(msg + "Image format is wrong.", image.getFormat(), format); 1085 expectEquals(msg + "Image width is wrong.", image.getWidth(), size.getWidth()); 1086 expectEquals(msg + "Image height is wrong.", image.getHeight(), size.getHeight()); 1087 expectEquals(msg + "Image timestamp is wrong.", image.getTimestamp(), timestampNs); 1088 } 1089 1090 } 1091