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