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