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