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, "left pt too right", "left pt too left", actual.left, expected.left, 506 errorPercent)) return false; 507 508 if (!expectSimilarValues( 509 formattedMsg, "right pt too right", "right pt too left", 510 actual.right, expected.right, errorPercent)) return false; 511 512 if (!expectSimilarValues( 513 formattedMsg, "top pt too low", "top pt too high", actual.top, expected.top, 514 errorPercent)) return false; 515 516 if (!expectSimilarValues( 517 formattedMsg, "bottom pt too low", "bottom pt too high", actual.top, expected.top, 518 errorPercent)) return false; 519 520 return true; 521 } 522 523 /** 524 * Check that two sizes are similar enough by ensuring that their width and height 525 * are within {@code errorPercent} of each other. 526 * 527 * <p>Only the first error is collected, to avoid spamming several error messages when 528 * the rectangle is hugely dissimilar.</p> 529 * 530 * @param msg Message to be logged 531 * @param expected The reference 'expected' value to be used to check against 532 * @param actual The actual value that was received 533 * @param errorPercent Within how many percent the components should be 534 * 535 * @return {@code true} if all expects passed, {@code false} otherwise 536 */ expectSizesAreSimilar(String msg, Size expected, Size actual, float errorPercent)537 public boolean expectSizesAreSimilar(String msg, Size expected, Size actual, 538 float errorPercent) { 539 String formattedMsg = String.format("%s: rects are not similar enough; expected (%s), " + 540 "actual (%s), error percent (%s), reason: ", 541 msg, expected, actual, errorPercent); 542 543 if (!expectSimilarValues( 544 formattedMsg, "too wide", "too narrow", actual.getWidth(), expected.getWidth(), 545 errorPercent)) return false; 546 547 if (!expectSimilarValues( 548 formattedMsg, "too tall", "too short", actual.getHeight(), expected.getHeight(), 549 errorPercent)) return false; 550 551 return true; 552 } 553 554 /** 555 * Check that the rectangle is centered within a certain tolerance of {@code errorPercent}, 556 * with respect to the {@code bounds} bounding rectangle. 557 * 558 * @param msg Message to be logged 559 * @param expectedBounds The width/height of the bounding rectangle 560 * @param actual The actual value that was received 561 * @param errorPercent Within how many percent the centering should be 562 */ expectRectCentered(String msg, Size expectedBounds, Rect actual, float errorPercent)563 public void expectRectCentered(String msg, Size expectedBounds, Rect actual, 564 float errorPercent) { 565 String formattedMsg = String.format("%s: rect should be centered; expected bounds (%s), " + 566 "actual (%s), error percent (%s), reason: ", 567 msg, expectedBounds, actual, errorPercent); 568 569 int centerBoundX = expectedBounds.getWidth() / 2; 570 int centerBoundY = expectedBounds.getHeight() / 2; 571 572 expectSimilarValues( 573 formattedMsg, "too low", "too high", actual.centerY(), centerBoundY, 574 errorPercent); 575 576 expectSimilarValues( 577 formattedMsg, "too right", "too left", actual.centerX(), centerBoundX, 578 errorPercent); 579 } 580 expectSimilarValues( String formattedMsg, String tooSmall, String tooLarge, int actualValue, int expectedValue, float errorPercent)581 private boolean expectSimilarValues( 582 String formattedMsg, String tooSmall, String tooLarge, int actualValue, 583 int expectedValue, float errorPercent) { 584 boolean succ = true; 585 succ = expectTrue(formattedMsg + tooLarge, 586 actualValue <= (expectedValue * (1.0f + errorPercent))) && succ; 587 succ = expectTrue(formattedMsg + tooSmall, 588 actualValue >= (expectedValue * (1.0f - errorPercent))) && succ; 589 590 return succ; 591 } 592 expectNotNull(String msg, Object obj)593 public void expectNotNull(String msg, Object obj) { 594 checkThat(msg, obj, CoreMatchers.notNullValue()); 595 } 596 expectNull(String msg, Object obj)597 public void expectNull(String msg, Object obj) { 598 if (obj != null) { 599 addMessage(msg); 600 } 601 } 602 603 /** 604 * Check if the values in the array are monotonically increasing (decreasing) and not all 605 * equal. 606 * 607 * @param array The array of values to be checked 608 * @param ascendingOrder The monotonicity ordering to be checked with 609 */ checkArrayMonotonicityAndNotAllEqual(T[] array, boolean ascendingOrder)610 public <T extends Comparable<? super T>> void checkArrayMonotonicityAndNotAllEqual(T[] array, 611 boolean ascendingOrder) { 612 String orderMsg = ascendingOrder ? ("increasing order") : ("decreasing order"); 613 for (int i = 0; i < array.length - 1; i++) { 614 int compareResult = array[i + 1].compareTo(array[i]); 615 boolean condition = compareResult >= 0; 616 if (!ascendingOrder) { 617 condition = compareResult <= 0; 618 } 619 620 expectTrue(String.format("Adjacent values (%s and %s) %s monotonicity is broken", 621 array[i].toString(), array[i + 1].toString(), orderMsg), condition); 622 } 623 624 expectTrue("All values of this array are equal: " + array[0].toString(), 625 array[0].compareTo(array[array.length - 1]) != 0); 626 } 627 628 /** 629 * Check if the key value is not null and return the value. 630 * 631 * @param characteristics The {@link CameraCharacteristics} to get the key from. 632 * @param key The {@link CameraCharacteristics} key to be checked. 633 * 634 * @return The value of the key. 635 */ expectKeyValueNotNull(CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key)636 public <T> T expectKeyValueNotNull(CameraCharacteristics characteristics, 637 CameraCharacteristics.Key<T> key) { 638 639 T value = characteristics.get(key); 640 if (value == null) { 641 addMessage("Key " + key.getName() + " shouldn't be null"); 642 } 643 644 return value; 645 } 646 647 /** 648 * Check if the key value is not null and return the value. 649 * 650 * @param request The {@link CaptureRequest} to get the key from. 651 * @param key The {@link CaptureRequest} key to be checked. 652 * 653 * @return The value of the key. 654 */ expectKeyValueNotNull(CaptureRequest request, CaptureRequest.Key<T> key)655 public <T> T expectKeyValueNotNull(CaptureRequest request, 656 CaptureRequest.Key<T> key) { 657 658 T value = request.get(key); 659 if (value == null) { 660 addMessage("Key " + key.getName() + " shouldn't be null"); 661 } 662 663 return value; 664 } 665 666 /** 667 * Check if the key value is not null and return the value. 668 * 669 * @param request The {@link CaptureRequest#Builder} to get the key from. 670 * @param key The {@link CaptureRequest} key to be checked. 671 * @return The value of the key. 672 */ expectKeyValueNotNull(Builder request, CaptureRequest.Key<T> key)673 public <T> T expectKeyValueNotNull(Builder request, CaptureRequest.Key<T> key) { 674 675 T value = request.get(key); 676 if (value == null) { 677 addMessage("Key " + key.getName() + " shouldn't be null"); 678 } 679 680 return value; 681 } 682 683 /** 684 * Check if the key value is not null and return the value. 685 * 686 * @param result The {@link CaptureResult} to get the key from. 687 * @param key The {@link CaptureResult} key to be checked. 688 * @return The value of the key. 689 */ expectKeyValueNotNull(CaptureResult result, CaptureResult.Key<T> key)690 public <T> T expectKeyValueNotNull(CaptureResult result, CaptureResult.Key<T> key) { 691 return expectKeyValueNotNull("", result, key); 692 } 693 694 /** 695 * Check if the key value is not null and return the value. 696 * 697 * @param msg The message to be logged. 698 * @param result The {@link CaptureResult} to get the key from. 699 * @param key The {@link CaptureResult} key to be checked. 700 * @return The value of the key. 701 */ expectKeyValueNotNull(String msg, CaptureResult result, CaptureResult.Key<T> key)702 public <T> T expectKeyValueNotNull(String msg, CaptureResult result, CaptureResult.Key<T> key) { 703 704 T value = result.get(key); 705 if (value == null) { 706 addMessage(msg + " Key " + key.getName() + " shouldn't be null"); 707 } 708 709 return value; 710 } 711 712 /** 713 * Check if the key is non-null and the value is not equal to target. 714 * 715 * @param request The The {@link CaptureRequest#Builder} to get the key from. 716 * @param key The {@link CaptureRequest} key to be checked. 717 * @param expected The expected value of the CaptureRequest key. 718 */ expectKeyValueNotEquals( Builder request, CaptureRequest.Key<T> key, T expected)719 public <T> void expectKeyValueNotEquals( 720 Builder request, CaptureRequest.Key<T> key, T expected) { 721 if (request == null || key == null || expected == null) { 722 throw new IllegalArgumentException("request, key and expected shouldn't be null"); 723 } 724 725 T value; 726 if ((value = expectKeyValueNotNull(request, key)) == null) { 727 return; 728 } 729 730 String reason = "Key " + key.getName() + " shouldn't have value " + value.toString(); 731 checkThat(reason, value, CoreMatchers.not(expected)); 732 } 733 734 /** 735 * Check if the key is non-null and the value is not equal to target. 736 * 737 * @param result The {@link CaptureResult} to get the key from. 738 * @param key The {@link CaptureResult} key to be checked. 739 * @param expected The expected value of the CaptureResult key. 740 */ expectKeyValueNotEquals( CaptureResult result, CaptureResult.Key<T> key, T expected)741 public <T> void expectKeyValueNotEquals( 742 CaptureResult result, CaptureResult.Key<T> key, T expected) { 743 if (result == null || key == null || expected == null) { 744 throw new IllegalArgumentException("result, key and expected shouldn't be null"); 745 } 746 747 T value; 748 if ((value = expectKeyValueNotNull(result, key)) == null) { 749 return; 750 } 751 752 String reason = "Key " + key.getName() + " shouldn't have value " + value.toString(); 753 checkThat(reason, value, CoreMatchers.not(expected)); 754 } 755 756 /** 757 * Check if the value is non-null and the value is equal to target. 758 * 759 * @param result The {@link CaptureResult} to lookup the value in. 760 * @param key The {@link CaptureResult} key to be checked. 761 * @param expected The expected value of the {@link CaptureResult} key. 762 */ expectKeyValueEquals(CaptureResult result, CaptureResult.Key<T> key, T expected)763 public <T> void expectKeyValueEquals(CaptureResult result, CaptureResult.Key<T> key, 764 T expected) { 765 if (result == null || key == null || expected == null) { 766 throw new IllegalArgumentException("request, key and expected shouldn't be null"); 767 } 768 769 T value; 770 if ((value = expectKeyValueNotNull(result, key)) == null) { 771 return; 772 } 773 774 String reason = "Key " + key.getName() + " value " + value.toString() 775 + " doesn't match the expected value " + expected.toString(); 776 checkThat(reason, value, CoreMatchers.equalTo(expected)); 777 } 778 779 /** 780 * Check if the key is non-null and the value is equal to target. 781 * 782 * <p>Only check non-null if the target is null.</p> 783 * 784 * @param request The The {@link CaptureRequest#Builder} to get the key from. 785 * @param key The {@link CaptureRequest} key to be checked. 786 * @param expected The expected value of the CaptureRequest key. 787 */ expectKeyValueEquals(Builder request, CaptureRequest.Key<T> key, T expected)788 public <T> void expectKeyValueEquals(Builder request, CaptureRequest.Key<T> key, T expected) { 789 if (request == null || key == null || expected == null) { 790 throw new IllegalArgumentException("request, key and expected shouldn't be null"); 791 } 792 793 T value; 794 if ((value = expectKeyValueNotNull(request, key)) == null) { 795 return; 796 } 797 798 String reason = "Key " + key.getName() + " value " + value.toString() 799 + " doesn't match the expected value " + expected.toString(); 800 checkThat(reason, value, CoreMatchers.equalTo(expected)); 801 } 802 803 /** 804 * Check if the key is non-null, and the key value is greater than the expected value. 805 * 806 * @param result {@link CaptureResult} to check. 807 * @param key The {@link CaptureResult} key to be checked. 808 * @param expected The expected to be compared to the value for the given key. 809 */ expectKeyValueGreaterOrEqual( CaptureResult result, CaptureResult.Key<T> key, T expected)810 public <T extends Comparable<? super T>> void expectKeyValueGreaterOrEqual( 811 CaptureResult result, CaptureResult.Key<T> key, T expected) { 812 T value; 813 if ((value = expectKeyValueNotNull(result, key)) == null) { 814 return; 815 } 816 817 expectGreaterOrEqual(key.getName(), expected, value); 818 } 819 820 /** 821 * Check if the key is non-null, and the key value is greater than the expected value. 822 * 823 * @param characteristics {@link CameraCharacteristics} to check. 824 * @param key The {@link CameraCharacteristics} key to be checked. 825 * @param expected The expected to be compared to the value for the given key. 826 */ expectKeyValueGreaterThan( CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T expected)827 public <T extends Comparable<? super T>> void expectKeyValueGreaterThan( 828 CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T expected) { 829 T value; 830 if ((value = expectKeyValueNotNull(characteristics, key)) == null) { 831 return; 832 } 833 834 expectGreater(key.getName(), expected, value); 835 } 836 837 /** 838 * Check if the key is non-null, and the key value is in the expected range. 839 * 840 * @param characteristics {@link CameraCharacteristics} to check. 841 * @param key The {@link CameraCharacteristics} key to be checked. 842 * @param min The min value of the range 843 * @param max The max value of the range 844 */ expectKeyValueInRange( CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T min, T max)845 public <T extends Comparable<? super T>> void expectKeyValueInRange( 846 CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T min, T max) { 847 T value; 848 if ((value = expectKeyValueNotNull(characteristics, key)) == null) { 849 return; 850 } 851 expectInRange(key.getName(), value, min, max); 852 } 853 854 /** 855 * Check if the key is non-null, and the key value is one of the expected values. 856 * 857 * @param characteristics {@link CameraCharacteristics} to check. 858 * @param key The {@link CameraCharacteristics} key to be checked. 859 * @param expected The expected values for the given key. 860 */ expectKeyValueIsIn(CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T... expected)861 public <T> void expectKeyValueIsIn(CameraCharacteristics characteristics, 862 CameraCharacteristics.Key<T> key, T... expected) { 863 T value = expectKeyValueNotNull(characteristics, key); 864 if (value == null) { 865 return; 866 } 867 String reason = "Key " + key.getName() + " value " + value 868 + " isn't one of the expected values " + Arrays.deepToString(expected); 869 expectContains(reason, expected, value); 870 } 871 872 /** 873 * Check if the key is non-null, and the key value is one of the expected values. 874 * 875 * @param request The The {@link CaptureRequest#Builder} to get the key from. 876 * @param key The {@link CaptureRequest} key to be checked. 877 * @param expected The expected values of the CaptureRequest key. 878 */ expectKeyValueIsIn(Builder request, CaptureRequest.Key<T> key, T... expected)879 public <T> void expectKeyValueIsIn(Builder request, CaptureRequest.Key<T> key, T... expected) { 880 T value = expectKeyValueNotNull(request, key); 881 if (value == null) { 882 return; 883 } 884 String reason = "Key " + key.getName() + " value " + value 885 + " isn't one of the expected values " + Arrays.deepToString(expected); 886 expectContains(reason, expected, value); 887 } 888 889 /** 890 * Check if the key is non-null, and the key value contains the expected element. 891 * 892 * @param characteristics {@link CameraCharacteristics} to check. 893 * @param key The {@link CameraCharacteristics} key to be checked. 894 * @param expected The expected element to be contained in the value for the given key. 895 */ expectKeyValueContains(CameraCharacteristics characteristics, CameraCharacteristics.Key<T[]> key, T expected)896 public <T> void expectKeyValueContains(CameraCharacteristics characteristics, 897 CameraCharacteristics.Key<T[]> key, T expected) { 898 T[] value; 899 if ((value = expectKeyValueNotNull(characteristics, key)) == null) { 900 return; 901 } 902 String reason = "Key " + key.getName() + " value " + value 903 + " doesn't contain the expected value " + expected; 904 expectContains(reason, value, expected); 905 } 906 907 /** 908 * Check if the key is non-null, and the key value contains the expected element. 909 * 910 * @param characteristics {@link CameraCharacteristics} to check. 911 * @param key The {@link CameraCharacteristics} key to be checked. 912 * @param expected The expected element to be contained in the value for the given key. 913 */ expectKeyValueContains(CameraCharacteristics characteristics, CameraCharacteristics.Key<int[]> key, int expected)914 public void expectKeyValueContains(CameraCharacteristics characteristics, 915 CameraCharacteristics.Key<int[]> key, int expected) { 916 int[] value; 917 if ((value = expectKeyValueNotNull(characteristics, key)) == null) { 918 return; 919 } 920 String reason = "Key " + key.getName() + " value " + value 921 + " doesn't contain the expected value " + expected; 922 expectContains(reason, value, expected); 923 } 924 925 /** 926 * Check if the key is non-null, and the key value contains the expected element. 927 * 928 * @param characteristics {@link CameraCharacteristics} to check. 929 * @param key The {@link CameraCharacteristics} key to be checked. 930 * @param expected The expected element to be contained in the value for the given key. 931 */ expectKeyValueContains(CameraCharacteristics characteristics, CameraCharacteristics.Key<boolean[]> key, boolean expected)932 public void expectKeyValueContains(CameraCharacteristics characteristics, 933 CameraCharacteristics.Key<boolean[]> key, boolean expected) { 934 boolean[] value; 935 if ((value = expectKeyValueNotNull(characteristics, key)) == null) { 936 return; 937 } 938 String reason = "Key " + key.getName() + " value " + value 939 + " doesn't contain the expected value " + expected; 940 expectContains(reason, value, expected); 941 } 942 943 /** 944 * Check if the {@code values} array contains the expected element. 945 * 946 * @param reason reason to print for failure. 947 * @param values array to check for membership in. 948 * @param expected the value to check. 949 */ expectContains(String reason, T[] values, T expected)950 public <T> void expectContains(String reason, T[] values, T expected) { 951 if (values == null) { 952 throw new NullPointerException(); 953 } 954 checkThat(reason, expected, InMatcher.in(values)); 955 } 956 expectContains(T[] values, T expected)957 public <T> void expectContains(T[] values, T expected) { 958 String reason = "Expected value " + expected 959 + " is not contained in the given values " + values; 960 expectContains(reason, values, expected); 961 } 962 963 /** 964 * Specialize {@link InMatcher} class for integer primitive array. 965 */ 966 private static class IntInMatcher extends InMatcher<Integer> { IntInMatcher(int[] values)967 public IntInMatcher(int[] values) { 968 Preconditions.checkNotNull("values", values); 969 mValues = new ArrayList<>(values.length); 970 for (int i : values) { 971 mValues.add(i); 972 } 973 } 974 } 975 976 /** 977 * Check if the {@code values} array contains the expected element. 978 * 979 * <p>Specialized for primitive int arrays</p> 980 * 981 * @param reason reason to print for failure. 982 * @param values array to check for membership in. 983 * @param expected the value to check. 984 */ expectContains(String reason, int[] values, int expected)985 public void expectContains(String reason, int[] values, int expected) { 986 if (values == null) { 987 throw new NullPointerException(); 988 } 989 990 checkThat(reason, expected, new IntInMatcher(values)); 991 } 992 expectContains(int[] values, int expected)993 public void expectContains(int[] values, int expected) { 994 String reason = "Expected value " + expected 995 + " is not contained in the given values " + values; 996 expectContains(reason, values, expected); 997 } 998 999 /** 1000 * Specialize {@link BooleanInMatcher} class for boolean primitive array. 1001 */ 1002 private static class BooleanInMatcher extends InMatcher<Boolean> { BooleanInMatcher(boolean[] values)1003 public BooleanInMatcher(boolean[] values) { 1004 Preconditions.checkNotNull("values", values); 1005 mValues = new ArrayList<>(values.length); 1006 for (boolean i : values) { 1007 mValues.add(i); 1008 } 1009 } 1010 } 1011 1012 /** 1013 * Check if the {@code values} array contains the expected element. 1014 * 1015 * <p>Specialized for primitive boolean arrays</p> 1016 * 1017 * @param reason reason to print for failure. 1018 * @param values array to check for membership in. 1019 * @param expected the value to check. 1020 */ expectContains(String reason, boolean[] values, boolean expected)1021 public void expectContains(String reason, boolean[] values, boolean expected) { 1022 if (values == null) { 1023 throw new NullPointerException(); 1024 } 1025 1026 checkThat(reason, expected, new BooleanInMatcher(values)); 1027 } 1028 1029 /** 1030 * Check if the {@code values} array contains the expected element. 1031 * 1032 * <p>Specialized for primitive boolean arrays</p> 1033 * 1034 * @param values array to check for membership in. 1035 * @param expected the value to check. 1036 */ expectContains(boolean[] values, boolean expected)1037 public void expectContains(boolean[] values, boolean expected) { 1038 String reason = "Expected value " + expected 1039 + " is not contained in the given values " + values; 1040 expectContains(reason, values, expected); 1041 } 1042 1043 /** 1044 * Check if the element inside of the list are unique. 1045 * 1046 * @param msg The message to be logged 1047 * @param list The list of values to be checked 1048 */ expectValuesUnique(String msg, List<T> list)1049 public <T> void expectValuesUnique(String msg, List<T> list) { 1050 Set<T> sizeSet = new HashSet<T>(list); 1051 expectTrue(msg + " each element must be distinct", sizeSet.size() == list.size()); 1052 } 1053 expectImageProperties(String msg, Image image, int format, Size size, long timestampNs)1054 public void expectImageProperties(String msg, Image image, int format, Size size, 1055 long timestampNs) { 1056 expectEquals(msg + "Image format is wrong.", image.getFormat(), format); 1057 expectEquals(msg + "Image width is wrong.", image.getWidth(), size.getWidth()); 1058 expectEquals(msg + "Image height is wrong.", image.getHeight(), size.getHeight()); 1059 expectEquals(msg + "Image timestamp is wrong.", image.getTimestamp(), timestampNs); 1060 } 1061 1062 } 1063