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