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