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