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