1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.util;
18 
19 import android.annotation.IntRange;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.compat.annotation.UnsupportedAppUsage;
23 import android.os.Build;
24 import android.text.TextUtils;
25 
26 import com.google.errorprone.annotations.CompileTimeConstant;
27 
28 import java.util.Arrays;
29 import java.util.Collection;
30 import java.util.Objects;
31 
32 /**
33  * Simple static methods to be called at the start of your own methods to verify
34  * correct arguments and state.
35  */
36 public class Preconditions {
37 
38     /**
39      * Ensures that an expression checking an argument is true.
40      *
41      * @param expression the expression to check
42      * @throws IllegalArgumentException if {@code expression} is false
43      */
44     @UnsupportedAppUsage
checkArgument(boolean expression)45     public static void checkArgument(boolean expression) {
46         if (!expression) {
47             throw new IllegalArgumentException();
48         }
49     }
50 
51     /**
52      * Ensures that an expression checking an argument is true.
53      *
54      * @param expression the expression to check
55      * @param errorMessage the exception message to use if the check fails; will
56      *     be converted to a string using {@link String#valueOf(Object)}
57      * @throws IllegalArgumentException if {@code expression} is false
58      */
59     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
checkArgument( boolean expression, final @CompileTimeConstant Object errorMessage)60     public static void checkArgument(
61             boolean expression,
62             final @CompileTimeConstant Object errorMessage) {
63         if (!expression) {
64             throw new IllegalArgumentException(String.valueOf(errorMessage));
65         }
66     }
67 
68     /**
69      * Ensures that an expression checking an argument is true.
70      *
71      * @param expression the expression to check
72      * @param messageTemplate a printf-style message template to use if the check fails; will
73      *     be converted to a string using {@link String#format(String, Object...)}
74      * @param messageArgs arguments for {@code messageTemplate}
75      * @throws IllegalArgumentException if {@code expression} is false
76      */
checkArgument( final boolean expression, final @CompileTimeConstant @NonNull String messageTemplate, final Object... messageArgs)77     public static void checkArgument(
78             final boolean expression,
79             final @CompileTimeConstant @NonNull String messageTemplate,
80             final Object... messageArgs) {
81         if (!expression) {
82             throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
83         }
84     }
85 
86     /**
87      * Ensures that an string reference passed as a parameter to the calling
88      * method is not empty.
89      *
90      * @param string an string reference
91      * @return the string reference that was validated
92      * @throws IllegalArgumentException if {@code string} is empty
93      */
checkStringNotEmpty(final T string)94     public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string) {
95         if (TextUtils.isEmpty(string)) {
96             throw new IllegalArgumentException();
97         }
98         return string;
99     }
100 
101     /**
102      * Ensures that an string reference passed as a parameter to the calling
103      * method is not empty.
104      *
105      * @param string an string reference
106      * @param errorMessage the exception message to use if the check fails; will
107      *     be converted to a string using {@link String#valueOf(Object)}
108      * @return the string reference that was validated
109      * @throws IllegalArgumentException if {@code string} is empty
110      */
checkStringNotEmpty(final T string, final @CompileTimeConstant Object errorMessage)111     public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string,
112             final @CompileTimeConstant Object errorMessage) {
113         if (TextUtils.isEmpty(string)) {
114             throw new IllegalArgumentException(String.valueOf(errorMessage));
115         }
116         return string;
117     }
118 
119     /**
120      * Ensures that an string reference passed as a parameter to the calling method is not empty.
121      *
122      * @param string an string reference
123      * @param messageTemplate a printf-style message template to use if the check fails; will be
124      *     converted to a string using {@link String#format(String, Object...)}
125      * @param messageArgs arguments for {@code messageTemplate}
126      * @return the string reference that was validated
127      * @throws IllegalArgumentException if {@code string} is empty
128      */
checkStringNotEmpty( final T string, final @NonNull @CompileTimeConstant String messageTemplate, final Object... messageArgs)129     public static @NonNull <T extends CharSequence> T checkStringNotEmpty(
130             final T string,
131             final @NonNull @CompileTimeConstant String messageTemplate,
132             final Object... messageArgs) {
133         if (TextUtils.isEmpty(string)) {
134             throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
135         }
136         return string;
137     }
138 
139     /**
140      * Ensures that an object reference passed as a parameter to the calling
141      * method is not null.
142      *
143      * @param reference an object reference
144      * @return the non-null reference that was validated
145      * @throws NullPointerException if {@code reference} is null
146      * @deprecated - use {@link java.util.Objects.requireNonNull} instead.
147      */
148     @Deprecated
149     @UnsupportedAppUsage
checkNotNull(final T reference)150     public static @NonNull <T> T checkNotNull(final T reference) {
151         if (reference == null) {
152             throw new NullPointerException();
153         }
154         return reference;
155     }
156 
157     /**
158      * Ensures that an object reference passed as a parameter to the calling
159      * method is not null.
160      *
161      * @param reference an object reference
162      * @param errorMessage the exception message to use if the check fails; will
163      *     be converted to a string using {@link String#valueOf(Object)}
164      * @return the non-null reference that was validated
165      * @throws NullPointerException if {@code reference} is null
166      * @deprecated - use {@link java.util.Objects#requireNonNull} instead.
167      */
168     @Deprecated
169     @UnsupportedAppUsage
checkNotNull( final T reference, final @CompileTimeConstant Object errorMessage)170     public static @NonNull <T> T checkNotNull(
171             final T reference,
172             final @CompileTimeConstant Object errorMessage) {
173         if (reference == null) {
174             throw new NullPointerException(String.valueOf(errorMessage));
175         }
176         return reference;
177     }
178 
179     /**
180      * Ensures that an object reference passed as a parameter to the calling
181      * method is not null.
182      *
183      * @param messageTemplate a printf-style message template to use if the check fails; will
184      *     be converted to a string using {@link String#format(String, Object...)}
185      * @param messageArgs arguments for {@code messageTemplate}
186      * @throws NullPointerException if {@code reference} is null
187      */
checkNotNull( final T reference, final @NonNull @CompileTimeConstant String messageTemplate, final Object... messageArgs)188     public static @NonNull <T> T checkNotNull(
189             final T reference,
190             final @NonNull @CompileTimeConstant String messageTemplate,
191             final Object... messageArgs) {
192         if (reference == null) {
193             throw new NullPointerException(String.format(messageTemplate, messageArgs));
194         }
195         return reference;
196     }
197 
198     /**
199      * Ensures the truth of an expression involving the state of the calling
200      * instance, but not involving any parameters to the calling method.
201      *
202      * @param expression a boolean expression
203      * @throws IllegalStateException if {@code expression} is false
204      */
205     @UnsupportedAppUsage
checkState(final boolean expression)206     public static void checkState(final boolean expression) {
207         checkState(expression, null);
208     }
209 
210     /**
211      * Ensures the truth of an expression involving the state of the calling
212      * instance, but not involving any parameters to the calling method.
213      *
214      * @param expression a boolean expression
215      * @param errorMessage the exception message to use if the check fails; will
216      *     be converted to a string using {@link String#valueOf(Object)}
217      * @throws IllegalStateException if {@code expression} is false
218      */
219     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
checkState(final boolean expression, String errorMessage)220     public static void checkState(final boolean expression, String errorMessage) {
221         if (!expression) {
222             throw new IllegalStateException(errorMessage);
223         }
224     }
225 
226     /**
227      * Ensures the truth of an expression involving the state of the calling
228      * instance, but not involving any parameters to the calling method.
229      *
230      * @param expression a boolean expression
231      * @param messageTemplate a printf-style message template to use if the check fails; will
232      *     be converted to a string using {@link String#format(String, Object...)}
233      * @param messageArgs arguments for {@code messageTemplate}
234      * @throws IllegalStateException if {@code expression} is false
235      */
checkState( final boolean expression, final @NonNull @CompileTimeConstant String messageTemplate, final Object... messageArgs)236     public static void checkState(
237             final boolean expression,
238             final @NonNull @CompileTimeConstant String messageTemplate,
239             final Object... messageArgs) {
240         if (!expression) {
241             throw new IllegalStateException(String.format(messageTemplate, messageArgs));
242         }
243     }
244 
245     /**
246      * Ensures the truth of an expression involving whether the calling identity is authorized to
247      * call the calling method.
248      *
249      * @param expression a boolean expression
250      * @throws SecurityException if {@code expression} is false
251      */
checkCallAuthorization(final boolean expression)252     public static void checkCallAuthorization(final boolean expression) {
253         if (!expression) {
254             throw new SecurityException("Calling identity is not authorized");
255         }
256     }
257 
258     /**
259      * Ensures the truth of an expression involving whether the calling identity is authorized to
260      * call the calling method.
261      *
262      * @param expression a boolean expression
263      * @param message the message of the security exception to be thrown
264      * @throws SecurityException if {@code expression} is false
265      */
checkCallAuthorization(final boolean expression, final String message)266     public static void checkCallAuthorization(final boolean expression, final String message) {
267         if (!expression) {
268             throw new SecurityException(message);
269         }
270     }
271 
272     /**
273      * Ensures the truth of an expression involving whether the calling identity is authorized to
274      * call the calling method.
275      *
276      * @param expression a boolean expression
277      * @param messageTemplate a printf-style message template to use if the check fails; will
278      *     be converted to a string using {@link String#format(String, Object...)}
279      * @param messageArgs arguments for {@code messageTemplate}
280      * @throws SecurityException if {@code expression} is false
281      */
checkCallAuthorization( final boolean expression, final @NonNull @CompileTimeConstant String messageTemplate, final Object... messageArgs)282     public static void checkCallAuthorization(
283             final boolean expression,
284             final @NonNull @CompileTimeConstant String messageTemplate,
285             final Object... messageArgs) {
286         if (!expression) {
287             throw new SecurityException(String.format(messageTemplate, messageArgs));
288         }
289     }
290 
291     /**
292      * Ensures the truth of an expression involving whether the calling user is authorized to
293      * call the calling method.
294      *
295      * @param expression a boolean expression
296      * @throws SecurityException if {@code expression} is false
297      */
checkCallingUser(final boolean expression)298     public static void checkCallingUser(final boolean expression) {
299         if (!expression) {
300             throw new SecurityException("Calling user is not authorized");
301         }
302     }
303 
304     /**
305      * Check the requested flags, throwing if any requested flags are outside
306      * the allowed set.
307      *
308      * @return the validated requested flags.
309      */
checkFlagsArgument(final int requestedFlags, final int allowedFlags)310     public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
311         if ((requestedFlags & allowedFlags) != requestedFlags) {
312             throw new IllegalArgumentException("Requested flags 0x"
313                     + Integer.toHexString(requestedFlags) + ", but only 0x"
314                     + Integer.toHexString(allowedFlags) + " are allowed");
315         }
316 
317         return requestedFlags;
318     }
319 
320     /**
321      * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
322      *
323      * @param value a numeric int value
324      * @param errorMessage the exception message to use if the check fails
325      * @return the validated numeric value
326      * @throws IllegalArgumentException if {@code value} was negative
327      */
checkArgumentNonnegative(final int value, final String errorMessage)328     public static @IntRange(from = 0) int checkArgumentNonnegative(final int value,
329             final String errorMessage) {
330         if (value < 0) {
331             throw new IllegalArgumentException(errorMessage);
332         }
333 
334         return value;
335     }
336 
337     /**
338      * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
339      *
340      * @param value a numeric int value
341      *
342      * @return the validated numeric value
343      * @throws IllegalArgumentException if {@code value} was negative
344      */
checkArgumentNonnegative(final int value)345     public static @IntRange(from = 0) int checkArgumentNonnegative(final int value) {
346         if (value < 0) {
347             throw new IllegalArgumentException();
348         }
349 
350         return value;
351     }
352 
353     /**
354      * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
355      *
356      * @param value a numeric long value
357      * @return the validated numeric value
358      * @throws IllegalArgumentException if {@code value} was negative
359      */
checkArgumentNonnegative(final long value)360     public static long checkArgumentNonnegative(final long value) {
361         if (value < 0) {
362             throw new IllegalArgumentException();
363         }
364 
365         return value;
366     }
367 
368     /**
369      * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
370      *
371      * @param value a numeric long value
372      * @param errorMessage the exception message to use if the check fails
373      * @return the validated numeric value
374      * @throws IllegalArgumentException if {@code value} was negative
375      */
checkArgumentNonnegative(final long value, final String errorMessage)376     public static long checkArgumentNonnegative(final long value, final String errorMessage) {
377         if (value < 0) {
378             throw new IllegalArgumentException(errorMessage);
379         }
380 
381         return value;
382     }
383 
384     /**
385      * Ensures that that the argument numeric value is positive (greater than 0).
386      *
387      * @param value a numeric int value
388      * @param errorMessage the exception message to use if the check fails
389      * @return the validated numeric value
390      * @throws IllegalArgumentException if {@code value} was not positive
391      */
checkArgumentPositive(final int value, final String errorMessage)392     public static int checkArgumentPositive(final int value, final String errorMessage) {
393         if (value <= 0) {
394             throw new IllegalArgumentException(errorMessage);
395         }
396 
397         return value;
398     }
399 
400     /**
401      * Ensures that the argument floating point value is non-negative (greater than or equal to 0).
402      * @param value a floating point value
403      * @param errorMessage the exteption message to use if the check fails
404      * @return the validated numeric value
405      * @throws IllegalArgumentException if {@code value} was negative
406      */
checkArgumentNonNegative(final float value, final String errorMessage)407     public static float checkArgumentNonNegative(final float value, final String errorMessage) {
408         if (value < 0) {
409             throw new IllegalArgumentException(errorMessage);
410         }
411 
412         return value;
413     }
414 
415     /**
416      * Ensures that the argument floating point value is positive (greater than 0).
417      * @param value a floating point value
418      * @param errorMessage the exteption message to use if the check fails
419      * @return the validated numeric value
420      * @throws IllegalArgumentException if {@code value} was not positive
421      */
checkArgumentPositive(final float value, final String errorMessage)422     public static float checkArgumentPositive(final float value, final String errorMessage) {
423         if (value <= 0) {
424             throw new IllegalArgumentException(errorMessage);
425         }
426 
427         return value;
428     }
429 
430     /**
431      * Ensures that the argument floating point value is a finite number.
432      *
433      * <p>A finite number is defined to be both representable (that is, not NaN) and
434      * not infinite (that is neither positive or negative infinity).</p>
435      *
436      * @param value a floating point value
437      * @param valueName the name of the argument to use if the check fails
438      *
439      * @return the validated floating point value
440      *
441      * @throws IllegalArgumentException if {@code value} was not finite
442      */
checkArgumentFinite(final float value, final String valueName)443     public static float checkArgumentFinite(final float value, final String valueName) {
444         if (Float.isNaN(value)) {
445             throw new IllegalArgumentException(valueName + " must not be NaN");
446         } else if (Float.isInfinite(value)) {
447             throw new IllegalArgumentException(valueName + " must not be infinite");
448         }
449 
450         return value;
451     }
452 
453     /**
454      * Ensures that the argument floating point value is within the inclusive range.
455      *
456      * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
457      * will always be out of range.</p>
458      *
459      * @param value a floating point value
460      * @param lower the lower endpoint of the inclusive range
461      * @param upper the upper endpoint of the inclusive range
462      * @param valueName the name of the argument to use if the check fails
463      *
464      * @return the validated floating point value
465      *
466      * @throws IllegalArgumentException if {@code value} was not within the range
467      */
checkArgumentInRange(float value, float lower, float upper, String valueName)468     public static float checkArgumentInRange(float value, float lower, float upper,
469             String valueName) {
470         if (Float.isNaN(value)) {
471             throw new IllegalArgumentException(valueName + " must not be NaN");
472         } else if (value < lower) {
473             throw new IllegalArgumentException(
474                     String.format(
475                             "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
476         } else if (value > upper) {
477             throw new IllegalArgumentException(
478                     String.format(
479                             "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
480         }
481 
482         return value;
483     }
484 
485     /**
486      * Ensures that the argument floating point value is within the inclusive range.
487      *
488      * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
489      * will always be out of range.</p>
490      *
491      * @param value a floating point value
492      * @param lower the lower endpoint of the inclusive range
493      * @param upper the upper endpoint of the inclusive range
494      * @param valueName the name of the argument to use if the check fails
495      *
496      * @return the validated floating point value
497      *
498      * @throws IllegalArgumentException if {@code value} was not within the range
499      */
checkArgumentInRange(double value, double lower, double upper, String valueName)500     public static double checkArgumentInRange(double value, double lower, double upper,
501             String valueName) {
502         if (Double.isNaN(value)) {
503             throw new IllegalArgumentException(valueName + " must not be NaN");
504         } else if (value < lower) {
505             throw new IllegalArgumentException(
506                     String.format(
507                             "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
508         } else if (value > upper) {
509             throw new IllegalArgumentException(
510                     String.format(
511                             "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
512         }
513 
514         return value;
515     }
516 
517     /**
518      * Ensures that the argument int value is within the inclusive range.
519      *
520      * @param value a int value
521      * @param lower the lower endpoint of the inclusive range
522      * @param upper the upper endpoint of the inclusive range
523      * @param valueName the name of the argument to use if the check fails
524      *
525      * @return the validated int value
526      *
527      * @throws IllegalArgumentException if {@code value} was not within the range
528      */
529     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
checkArgumentInRange(int value, int lower, int upper, String valueName)530     public static int checkArgumentInRange(int value, int lower, int upper,
531             String valueName) {
532         if (value < lower) {
533             throw new IllegalArgumentException(
534                     String.format(
535                             "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
536         } else if (value > upper) {
537             throw new IllegalArgumentException(
538                     String.format(
539                             "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
540         }
541 
542         return value;
543     }
544 
545     /**
546      * Ensures that the argument long value is within the inclusive range.
547      *
548      * @param value a long value
549      * @param lower the lower endpoint of the inclusive range
550      * @param upper the upper endpoint of the inclusive range
551      * @param valueName the name of the argument to use if the check fails
552      *
553      * @return the validated long value
554      *
555      * @throws IllegalArgumentException if {@code value} was not within the range
556      */
checkArgumentInRange(long value, long lower, long upper, String valueName)557     public static long checkArgumentInRange(long value, long lower, long upper,
558             String valueName) {
559         if (value < lower) {
560             throw new IllegalArgumentException(
561                     String.format(
562                             "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
563         } else if (value > upper) {
564             throw new IllegalArgumentException(
565                     String.format(
566                             "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
567         }
568 
569         return value;
570     }
571 
572     /**
573      * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
574      *
575      * @param value an array of boxed objects
576      * @param valueName the name of the argument to use if the check fails
577      *
578      * @return the validated array
579      *
580      * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
581      */
checkArrayElementsNotNull(final T[] value, final String valueName)582     public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
583         if (value == null) {
584             throw new NullPointerException(valueName + " must not be null");
585         }
586 
587         for (int i = 0; i < value.length; ++i) {
588             if (value[i] == null) {
589                 throw new NullPointerException(
590                         String.format("%s[%d] must not be null", valueName, i));
591             }
592         }
593 
594         return value;
595     }
596 
597     /**
598      * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
599      * {@code null}.
600      *
601      * @param value a {@link Collection} of boxed objects
602      * @param valueName the name of the argument to use if the check fails
603      *
604      * @return the validated {@link Collection}
605      *
606      * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
607      */
checkCollectionElementsNotNull( final C value, final String valueName)608     public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
609             final C value, final String valueName) {
610         if (value == null) {
611             throw new NullPointerException(valueName + " must not be null");
612         }
613 
614         long ctr = 0;
615         for (T elem : value) {
616             if (elem == null) {
617                 throw new NullPointerException(
618                         String.format("%s[%d] must not be null", valueName, ctr));
619             }
620             ++ctr;
621         }
622 
623         return value;
624     }
625 
626     /**
627      * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
628      *
629      * @param value a {@link Collection} of boxed elements.
630      * @param valueName the name of the argument to use if the check fails.
631 
632      * @return the validated {@link Collection}
633      *
634      * @throws NullPointerException if the {@code value} was {@code null}
635      * @throws IllegalArgumentException if the {@code value} was empty
636      */
checkCollectionNotEmpty(final Collection<T> value, final String valueName)637     public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
638             final String valueName) {
639         if (value == null) {
640             throw new NullPointerException(valueName + " must not be null");
641         }
642         if (value.isEmpty()) {
643             throw new IllegalArgumentException(valueName + " is empty");
644         }
645         return value;
646     }
647 
648     /**
649      * Ensures that the given byte array is not {@code null}, and contains at least one element.
650      *
651      * @param value an array of elements.
652      * @param valueName the name of the argument to use if the check fails.
653 
654      * @return the validated array
655      *
656      * @throws NullPointerException if the {@code value} was {@code null}
657      * @throws IllegalArgumentException if the {@code value} was empty
658      */
659     @NonNull
checkByteArrayNotEmpty(final byte[] value, final String valueName)660     public static byte[] checkByteArrayNotEmpty(final byte[] value, final String valueName) {
661         if (value == null) {
662             throw new NullPointerException(valueName + " must not be null");
663         }
664         if (value.length == 0) {
665             throw new IllegalArgumentException(valueName + " is empty");
666         }
667         return value;
668     }
669 
670     /**
671      * Ensures that argument {@code value} is one of {@code supportedValues}.
672      *
673      * @param supportedValues an array of string values
674      * @param value a string value
675      *
676      * @return the validated value
677      *
678      * @throws NullPointerException if either {@code value} or {@code supportedValues} is null
679      * @throws IllegalArgumentException if the {@code value} is not in {@code supportedValues}
680      */
681     @NonNull
checkArgumentIsSupported(final String[] supportedValues, final String value)682     public static String checkArgumentIsSupported(final String[] supportedValues,
683             final String value) {
684         checkNotNull(value);
685         checkNotNull(supportedValues);
686 
687         if (!contains(supportedValues, value)) {
688             throw new IllegalArgumentException(value + "is not supported "
689                     + Arrays.toString(supportedValues));
690         }
691         return value;
692     }
693 
contains(String[] values, String value)694     private static boolean contains(String[] values, String value) {
695         if (values == null) {
696             return false;
697         }
698         for (int i = 0; i < values.length; ++i) {
699             if (Objects.equals(value, values[i])) {
700                 return true;
701             }
702         }
703         return false;
704     }
705 
706     /**
707      * Ensures that all elements in the argument floating point array are within the inclusive range
708      *
709      * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
710      * will always be out of range.</p>
711      *
712      * @param value a floating point array of values
713      * @param lower the lower endpoint of the inclusive range
714      * @param upper the upper endpoint of the inclusive range
715      * @param valueName the name of the argument to use if the check fails
716      *
717      * @return the validated floating point value
718      *
719      * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
720      * @throws NullPointerException if the {@code value} was {@code null}
721      */
checkArrayElementsInRange(float[] value, float lower, float upper, String valueName)722     public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
723             String valueName) {
724         checkNotNull(value, "%s must not be null", valueName);
725 
726         for (int i = 0; i < value.length; ++i) {
727             float v = value[i];
728 
729             if (Float.isNaN(v)) {
730                 throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
731             } else if (v < lower) {
732                 throw new IllegalArgumentException(
733                         String.format("%s[%d] is out of range of [%f, %f] (too low)",
734                                 valueName, i, lower, upper));
735             } else if (v > upper) {
736                 throw new IllegalArgumentException(
737                         String.format("%s[%d] is out of range of [%f, %f] (too high)",
738                                 valueName, i, lower, upper));
739             }
740         }
741 
742         return value;
743     }
744 
745     /**
746      * Ensures that all elements in the argument integer array are within the inclusive range
747      *
748      * @param value an integer array of values
749      * @param lower the lower endpoint of the inclusive range
750      * @param upper the upper endpoint of the inclusive range
751      * @param valueName the name of the argument to use if the check fails
752      *
753      * @return the validated integer array
754      *
755      * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
756      * @throws NullPointerException if the {@code value} was {@code null}
757      */
checkArrayElementsInRange(int[] value, int lower, int upper, String valueName)758     public static int[] checkArrayElementsInRange(int[] value, int lower, int upper,
759             String valueName) {
760         checkNotNull(value, "%s must not be null", valueName);
761 
762         for (int i = 0; i < value.length; ++i) {
763             int v = value[i];
764 
765             if (v < lower) {
766                 throw new IllegalArgumentException(
767                         String.format("%s[%d] is out of range of [%d, %d] (too low)",
768                                 valueName, i, lower, upper));
769             } else if (v > upper) {
770                 throw new IllegalArgumentException(
771                         String.format("%s[%d] is out of range of [%d, %d] (too high)",
772                                 valueName, i, lower, upper));
773             }
774         }
775 
776         return value;
777     }
778 
779     /**
780      * Throws an exception that guides developers to configure a {@code RavenwoodRule} when the
781      * given argument is {@code null}.
782      */
requireNonNullViaRavenwoodRule(@ullable T t)783     public static <T> @NonNull T requireNonNullViaRavenwoodRule(@Nullable T t) {
784         if (t == null) {
785             throw new IllegalStateException("This operation requires that a RavenwoodRule be "
786                     + "configured to accurately define the expected test environment");
787         } else {
788             return t;
789         }
790     }
791 }
792