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