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