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