View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3;
18  
19  import static org.apache.commons.lang3.LangAssertions.assertIllegalArgumentException;
20  import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
21  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
22  import static org.mockito.ArgumentMatchers.any;
23  import static org.mockito.ArgumentMatchers.eq;
24  import static org.mockito.Mockito.mockStatic;
25  import static org.junit.jupiter.api.Assertions.assertEquals;
26  import static org.junit.jupiter.api.Assertions.assertFalse;
27  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
28  import static org.junit.jupiter.api.Assertions.assertNotNull;
29  import static org.junit.jupiter.api.Assertions.assertNotSame;
30  import static org.junit.jupiter.api.Assertions.assertNull;
31  import static org.junit.jupiter.api.Assertions.assertSame;
32  import static org.junit.jupiter.api.Assertions.assertThrows;
33  import static org.junit.jupiter.api.Assertions.assertTrue;
34  import static org.junit.jupiter.api.Assertions.fail;
35  
36  import java.io.IOException;
37  import java.lang.reflect.Constructor;
38  import java.lang.reflect.Modifier;
39  import java.time.Duration;
40  import java.util.ArrayList;
41  import java.util.Arrays;
42  import java.util.Calendar;
43  import java.util.Collections;
44  import java.util.Comparator;
45  import java.util.Date;
46  import java.util.HashMap;
47  import java.util.HashSet;
48  import java.util.List;
49  import java.util.Map;
50  import java.util.Objects;
51  import java.util.Optional;
52  import java.util.Set;
53  import java.util.function.Supplier;
54  
55  import org.apache.commons.lang3.exception.CloneFailedException;
56  import org.apache.commons.lang3.function.Suppliers;
57  import org.apache.commons.lang3.mutable.MutableInt;
58  import org.apache.commons.lang3.mutable.MutableObject;
59  import org.apache.commons.lang3.text.StrBuilder;
60  import org.apache.commons.lang3.time.DurationUtils;
61  import org.junit.jupiter.api.Test;
62  import org.mockito.MockedStatic;
63  
64  /**
65   * Tests {@link ObjectUtils}.
66   */
67  @SuppressWarnings("deprecation") // deliberate use of deprecated code
68  class ObjectUtilsTest extends AbstractLangTest {
69  
70      static final class CharSequenceComparator implements Comparator<CharSequence> {
71  
72          @Override
73          public int compare(final CharSequence o1, final CharSequence o2) {
74              return o1.toString().compareTo(o2.toString());
75          }
76  
77      }
78  
79      /**
80       * String that is cloneable.
81       */
82      static final class CloneableString extends MutableObject<String> implements Cloneable {
83          private static final long serialVersionUID = 1L;
84          CloneableString(final String s) {
85              super(s);
86          }
87  
88          @Override
89          public CloneableString clone() throws CloneNotSupportedException {
90              return (CloneableString) super.clone();
91          }
92      }
93  
94      static final class NonComparableCharSequence implements CharSequence {
95          final String value;
96  
97          /**
98           * Create a new NonComparableCharSequence instance.
99           *
100          * @param value The CharSequence value
101          */
102         NonComparableCharSequence(final String value) {
103             Validate.notNull(value);
104             this.value = value;
105         }
106 
107         @Override
108         public char charAt(final int arg0) {
109             return value.charAt(arg0);
110         }
111 
112         @Override
113         public int length() {
114             return value.length();
115         }
116 
117         @Override
118         public CharSequence subSequence(final int arg0, final int arg1) {
119             return value.subSequence(arg0, arg1);
120         }
121 
122         @Override
123         public String toString() {
124             return value;
125         }
126     }
127 
128     /**
129      * String that is not cloneable.
130      */
131     static final class UncloneableString extends MutableObject<String> implements Cloneable {
132         private static final long serialVersionUID = 1L;
133         UncloneableString(final String s) {
134             super(s);
135         }
136     }
137 
138     private static final Supplier<?> NULL_SUPPLIER = null;
139 
140     private static final String FOO = "foo";
141     private static final String BAR = "bar";
142     private static final String[] NON_EMPTY_ARRAY = { FOO, BAR, };
143 
144     private static final List<String> NON_EMPTY_LIST = Arrays.asList(NON_EMPTY_ARRAY);
145 
146     private static final Set<String> NON_EMPTY_SET = new HashSet<>(NON_EMPTY_LIST);
147 
148     private static final Map<String, String> NON_EMPTY_MAP = new HashMap<>();
149 
150     static {
151         NON_EMPTY_MAP.put(FOO, BAR);
152     }
153 
154     /**
155      * Tests {@link ObjectUtils#allNotNull(Object...)}.
156      */
157     @Test
158     void testAllNotNull() {
159         assertFalse(ObjectUtils.allNotNull((Object) null));
160         assertFalse(ObjectUtils.allNotNull((Object[]) null));
161         assertFalse(ObjectUtils.allNotNull(null, null, null));
162         assertFalse(ObjectUtils.allNotNull(null, FOO, BAR));
163         assertFalse(ObjectUtils.allNotNull(FOO, BAR, null));
164         assertFalse(ObjectUtils.allNotNull(FOO, BAR, null, FOO, BAR));
165 
166         assertTrue(ObjectUtils.allNotNull());
167         assertTrue(ObjectUtils.allNotNull(FOO));
168         assertTrue(ObjectUtils.allNotNull(FOO, BAR, 1, Boolean.TRUE, new Object(), new Object[]{}));
169     }
170 
171     /**
172      * Tests {@link ObjectUtils#allNull(Object...)}.
173      */
174     @Test
175     void testAllNull() {
176         assertTrue(ObjectUtils.allNull());
177         assertTrue(ObjectUtils.allNull((Object) null));
178         assertTrue(ObjectUtils.allNull((Object[]) null));
179         assertTrue(ObjectUtils.allNull(null, null, null));
180 
181         assertFalse(ObjectUtils.allNull(FOO));
182         assertFalse(ObjectUtils.allNull(null, FOO, null));
183         assertFalse(ObjectUtils.allNull(null, null, null, null, FOO, BAR));
184     }
185 
186     /**
187      * Tests {@link ObjectUtils#anyNotNull(Object...)}.
188      */
189     @Test
190     void testAnyNotNull() {
191         assertFalse(ObjectUtils.anyNotNull());
192         assertFalse(ObjectUtils.anyNotNull((Object) null));
193         assertFalse(ObjectUtils.anyNotNull((Object[]) null));
194         assertFalse(ObjectUtils.anyNotNull(null, null, null));
195 
196         assertTrue(ObjectUtils.anyNotNull(FOO));
197         assertTrue(ObjectUtils.anyNotNull(null, FOO, null));
198         assertTrue(ObjectUtils.anyNotNull(null, null, null, null, FOO, BAR));
199     }
200 
201     /**
202      * Tests {@link ObjectUtils#anyNull(Object...)}.
203      */
204     @Test
205     void testAnyNull() {
206         assertTrue(ObjectUtils.anyNull((Object) null));
207         assertTrue(ObjectUtils.anyNull(null, null, null));
208         assertTrue(ObjectUtils.anyNull(null, FOO, BAR));
209         assertTrue(ObjectUtils.anyNull(FOO, BAR, null));
210         assertTrue(ObjectUtils.anyNull(FOO, BAR, null, FOO, BAR));
211 
212         assertFalse(ObjectUtils.anyNull());
213         assertFalse(ObjectUtils.anyNull(FOO));
214         assertFalse(ObjectUtils.anyNull(FOO, BAR, 1, Boolean.TRUE, new Object(), new Object[]{}));
215     }
216 
217     /**
218      * Test for {@link ObjectUtils#isArray(Object)}.
219      */
220     @Test
221     void testArray() {
222         assertFalse(ObjectUtils.isArray(null));
223         assertFalse(ObjectUtils.isArray(""));
224         assertFalse(ObjectUtils.isArray("abg"));
225         assertFalse(ObjectUtils.isArray(123));
226         assertTrue(ObjectUtils.isArray(NON_EMPTY_ARRAY));
227         assertTrue(ObjectUtils.isArray(new int[]{1, 2, 3}));
228         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_BOOLEAN_ARRAY));
229         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_BOOLEAN_ARRAY));
230         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_BOOLEAN_OBJECT_ARRAY));
231         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_BYTE_ARRAY));
232         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_BYTE_OBJECT_ARRAY));
233         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_CHAR_ARRAY));
234         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_CHARACTER_OBJECT_ARRAY));
235         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_CLASS_ARRAY));
236         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_DOUBLE_ARRAY));
237         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_DOUBLE_OBJECT_ARRAY));
238         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_FIELD_ARRAY));
239         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_FLOAT_ARRAY));
240         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_FLOAT_OBJECT_ARRAY));
241         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_INT_ARRAY));
242         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_INTEGER_OBJECT_ARRAY));
243         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_LONG_ARRAY));
244         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
245         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_METHOD_ARRAY));
246         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_OBJECT_ARRAY));
247         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_SHORT_ARRAY));
248         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_SHORT_OBJECT_ARRAY));
249         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_STRING_ARRAY));
250         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_THROWABLE_ARRAY));
251         assertTrue(ObjectUtils.isArray(ArrayUtils.EMPTY_TYPE_ARRAY));
252     }
253 
254     /**
255      * Tests {@link ObjectUtils#clone(Object)} with a cloneable object.
256      */
257     @Test
258     void testCloneOfCloneable() {
259         final CloneableString string = new CloneableString("apache");
260         final CloneableString stringClone = ObjectUtils.clone(string);
261         assertEquals("apache", stringClone.get());
262     }
263 
264     /**
265      * Tests {@link ObjectUtils#clone(Object)} with a not cloneable object.
266      */
267     @Test
268     void testCloneOfNotCloneable() {
269         final String string = "apache";
270         assertNull(ObjectUtils.clone(string));
271     }
272 
273     /**
274      * Tests {@link ObjectUtils#clone(Object)} with an array of primitives.
275      */
276     @Test
277     void testCloneOfPrimitiveArray() {
278         assertArrayEquals(new int[]{1}, ObjectUtils.clone(new int[]{1}));
279     }
280 
281     /**
282      * Tests {@link ObjectUtils#clone(Object)} with an object array.
283      */
284     @Test
285     void testCloneOfStringArray() {
286         assertTrue(Arrays.deepEquals(
287             new String[]{"string"}, ObjectUtils.clone(new String[]{"string"})));
288     }
289 
290     /**
291      * Tests {@link ObjectUtils#clone(Object)} with an uncloneable object.
292      */
293     @Test
294     void testCloneOfUncloneable() {
295         final UncloneableString string = new UncloneableString("apache");
296         final CloneFailedException e = assertThrows(CloneFailedException.class, () -> ObjectUtils.clone(string));
297         assertNotNull(e);
298         assertNotNull(e.getCause());
299         assertEquals(NoSuchMethodException.class, e.getCause().getClass());
300     }
301 
302     @Test
303     void testComparatorMedian() {
304         final CharSequenceComparator cmp = new CharSequenceComparator();
305         final NonComparableCharSequence foo = new NonComparableCharSequence("foo");
306         final NonComparableCharSequence bar = new NonComparableCharSequence("bar");
307         final NonComparableCharSequence baz = new NonComparableCharSequence("baz");
308         final NonComparableCharSequence blah = new NonComparableCharSequence("blah");
309         final NonComparableCharSequence wah = new NonComparableCharSequence("wah");
310         assertSame(foo, ObjectUtils.median(cmp, foo));
311         assertSame(bar, ObjectUtils.median(cmp, foo, bar));
312         assertSame(baz, ObjectUtils.median(cmp, foo, bar, baz));
313         assertSame(baz, ObjectUtils.median(cmp, foo, bar, baz, blah));
314         assertSame(blah, ObjectUtils.median(cmp, foo, bar, baz, blah, wah));
315         // duplicates are counted, not collapsed
316         assertSame(foo, ObjectUtils.median(cmp, foo, foo, bar));
317     }
318 
319     @Test
320     void testComparatorMedian_emptyItems() {
321         assertIllegalArgumentException(() -> ObjectUtils.median(new CharSequenceComparator()));
322     }
323 
324     @Test
325     void testComparatorMedian_nullComparator() {
326         assertNullPointerException(
327                 () -> ObjectUtils.median((Comparator<CharSequence>) null, new NonComparableCharSequence("foo")));
328     }
329 
330     @Test
331     void testComparatorMedian_nullItems() {
332         assertNullPointerException(
333                 () -> ObjectUtils.median(new CharSequenceComparator(), (CharSequence[]) null));
334     }
335 
336     /**
337      * Tests {@link ObjectUtils#compare(Comparable, Comparable, boolean)}.
338      */
339     @Test
340     void testCompare() {
341         final Integer one = Integer.valueOf(1);
342         final Integer two = Integer.valueOf(2);
343         final Integer nullValue = null;
344 
345         assertEquals(0, ObjectUtils.compare(nullValue, nullValue), "Null Null false");
346         assertEquals(0, ObjectUtils.compare(nullValue, nullValue, true), "Null Null true");
347 
348         assertEquals(-1, ObjectUtils.compare(nullValue, one), "Null one false");
349         assertEquals(1, ObjectUtils.compare(nullValue, one, true), "Null one true");
350 
351         assertEquals(1, ObjectUtils.compare(one, nullValue), "one Null false");
352         assertEquals(-1, ObjectUtils.compare(one, nullValue, true), "one Null true");
353 
354         assertEquals(-1, ObjectUtils.compare(one, two), "one two false");
355         assertEquals(-1, ObjectUtils.compare(one, two, true), "one two true");
356     }
357 
358     @Test
359     void testConstMethods() {
360         // To truly test the CONST() method, we'd want to look in the
361         // bytecode to see if the literals were folded into the
362         // class, or if the bytecode kept the method call.
363         assertTrue(ObjectUtils.CONST(true), "CONST(boolean)");
364         assertEquals((byte) 3, ObjectUtils.CONST((byte) 3), "CONST(byte)");
365         assertEquals((char) 3, ObjectUtils.CONST((char) 3), "CONST(char)");
366         assertEquals((short) 3, ObjectUtils.CONST((short) 3), "CONST(short)");
367         assertEquals(3, ObjectUtils.CONST(3), "CONST(int)");
368         assertEquals(3L, ObjectUtils.CONST(3L), "CONST(long)");
369         assertEquals(3f, ObjectUtils.CONST(3f), "CONST(float)");
370         assertEquals(3.0, ObjectUtils.CONST(3.0), "CONST(double)");
371         assertEquals("abc", ObjectUtils.CONST("abc"), "CONST(Object)");
372         // Make sure documentation examples from Javadoc all work
373         // (this fixed a lot of my bugs when I these!)
374         //
375         // My bugs should be in a software engineering textbook
376         // for "Can you screw this up?" The answer is, yes,
377         // you can even screw this up. (When you == Julius)
378         // .
379         final boolean MAGIC_FLAG = ObjectUtils.CONST(true);
380         final byte MAGIC_BYTE1 = ObjectUtils.CONST((byte) 127);
381         final byte MAGIC_BYTE2 = ObjectUtils.CONST_BYTE(127);
382         final char MAGIC_CHAR = ObjectUtils.CONST('a');
383         final short MAGIC_SHORT1 = ObjectUtils.CONST((short) 123);
384         final short MAGIC_SHORT2 = ObjectUtils.CONST_SHORT(127);
385         final int MAGIC_INT = ObjectUtils.CONST(123);
386         final long MAGIC_LONG1 = ObjectUtils.CONST(123L);
387         final long MAGIC_LONG2 = ObjectUtils.CONST(3);
388         final float MAGIC_FLOAT = ObjectUtils.CONST(1.0f);
389         final double MAGIC_DOUBLE = ObjectUtils.CONST(1.0);
390         final String MAGIC_STRING = ObjectUtils.CONST("abc");
391         assertTrue(MAGIC_FLAG);
392         assertEquals(127, MAGIC_BYTE1);
393         assertEquals(127, MAGIC_BYTE2);
394         assertEquals('a', MAGIC_CHAR);
395         assertEquals(123, MAGIC_SHORT1);
396         assertEquals(127, MAGIC_SHORT2);
397         assertEquals(123, MAGIC_INT);
398         assertEquals(123, MAGIC_LONG1);
399         assertEquals(3, MAGIC_LONG2);
400         assertEquals(1.0f, MAGIC_FLOAT);
401         assertEquals(1.0, MAGIC_DOUBLE);
402         assertEquals("abc", MAGIC_STRING);
403         assertIllegalArgumentException(() -> ObjectUtils.CONST_BYTE(-129), "CONST_BYTE(-129): IllegalArgumentException should have been thrown.");
404         assertIllegalArgumentException(() -> ObjectUtils.CONST_BYTE(128), "CONST_BYTE(128): IllegalArgumentException should have been thrown.");
405         assertIllegalArgumentException(() -> ObjectUtils.CONST_SHORT(-32769),
406                 "CONST_SHORT(-32769): IllegalArgumentException should have been thrown.");
407         assertIllegalArgumentException(() -> ObjectUtils.CONST_SHORT(32768),
408                 "CONST_SHORT(32768): IllegalArgumentException should have been thrown.");
409     }
410 
411     @Test
412     void testConstructor() {
413         assertNotNull(new ObjectUtils());
414         final Constructor<?>[] cons = ObjectUtils.class.getDeclaredConstructors();
415         assertEquals(1, cons.length);
416         assertTrue(Modifier.isPublic(cons[0].getModifiers()));
417         assertTrue(Modifier.isPublic(ObjectUtils.class.getModifiers()));
418         assertFalse(Modifier.isFinal(ObjectUtils.class.getModifiers()));
419     }
420 
421     @Test
422     void testDefaultIfNull() {
423         final Object o = FOO;
424         final Object dflt = BAR;
425         assertSame(dflt, ObjectUtils.defaultIfNull(null, dflt), "dflt was not returned when o was null");
426         assertSame(o, ObjectUtils.defaultIfNull(o, dflt), "dflt was returned when o was not null");
427         assertSame(dflt, ObjectUtils.getIfNull(null, () -> dflt), "dflt was not returned when o was null");
428         assertSame(o, ObjectUtils.getIfNull(o, () -> dflt), "dflt was returned when o was not null");
429         assertSame(o, ObjectUtils.getIfNull(FOO, () -> dflt), "dflt was returned when o was not null");
430         assertSame(o, ObjectUtils.getIfNull("foo", () -> dflt), "dflt was returned when o was not null");
431         final MutableInt callsCounter = new MutableInt(0);
432         final Supplier<Object> countingDefaultSupplier = () -> {
433             callsCounter.increment();
434             return dflt;
435         };
436         ObjectUtils.getIfNull(o, countingDefaultSupplier);
437         assertEquals(0, callsCounter.get());
438         ObjectUtils.getIfNull(null, countingDefaultSupplier);
439         assertEquals(1, callsCounter.get());
440     }
441 
442     @Test
443     void testEquals() {
444         assertTrue(ObjectUtils.equals(null, null), "ObjectUtils.equals(null, null) returned false");
445         assertFalse(ObjectUtils.equals(FOO, null), "ObjectUtils.equals(\"foo\", null) returned true");
446         assertFalse(ObjectUtils.equals(null, BAR), "ObjectUtils.equals(null, \"bar\") returned true");
447         assertFalse(ObjectUtils.equals(FOO, BAR), "ObjectUtils.equals(\"foo\", \"bar\") returned true");
448         assertTrue(ObjectUtils.equals(FOO, FOO), "ObjectUtils.equals(\"foo\", \"foo\") returned false");
449     }
450 
451     @Test
452     void testFirstNonNull() {
453         assertEquals("", ObjectUtils.firstNonNull(null, ""));
454         final String firstNonNullGenerics = ObjectUtils.firstNonNull(null, null, "123", "456");
455         assertEquals("123", firstNonNullGenerics);
456         assertEquals("123", ObjectUtils.firstNonNull("123", null, "456", null));
457         assertSame(Boolean.TRUE, ObjectUtils.firstNonNull(Boolean.TRUE));
458 
459         // Explicitly pass in an empty array of Object type to ensure compiler doesn't complain of unchecked generic array creation
460         assertNull(ObjectUtils.firstNonNull());
461 
462         // Cast to Object in line below ensures compiler doesn't complain of unchecked generic array creation
463         assertNull(ObjectUtils.firstNonNull(null, null));
464 
465         assertNull(ObjectUtils.firstNonNull((Object) null));
466         assertNull(ObjectUtils.firstNonNull((Object[]) null));
467     }
468 
469     @Test
470     void testGetClass() {
471         final String[] newArray = ArrayUtils.EMPTY_STRING_ARRAY;
472         // No type-cast required.
473         final Class<String[]> cls = ObjectUtils.getClass(newArray);
474         assertEquals(String[].class, cls);
475         assertNull(ObjectUtils.getClass(null));
476     }
477 
478     @Test
479     void testGetFirstNonNull() {
480         // first non-null
481         assertEquals("", ObjectUtils.getFirstNonNull(null, () -> ""));
482         assertEquals("", ObjectUtils.getFirstNonNull(Suppliers.nul(), () -> ""));
483         // first encountered value is used
484         assertEquals("1", ObjectUtils.getFirstNonNull(Suppliers.nul(), () -> "1", () -> "2", Suppliers.nul()));
485         assertEquals("123", ObjectUtils.getFirstNonNull(() -> "123", Suppliers.nul(), () -> "456"));
486         // don't evaluate suppliers after first value is found
487         assertEquals("123", ObjectUtils.getFirstNonNull(Suppliers.nul(), () -> "123", () -> fail("Supplier after first non-null value should not be evaluated")));
488         // supplier returning null and null supplier both result in null
489         assertNull(ObjectUtils.getFirstNonNull(null, Suppliers.nul()));
490         // Explicitly pass in an empty array of Object type to ensure compiler doesn't complain of unchecked generic array creation
491         assertNull(ObjectUtils.getFirstNonNull());
492         // supplier is null
493         assertNull(ObjectUtils.getFirstNonNull((Supplier<Object>) null));
494         // varargs array itself is null
495         assertNull(ObjectUtils.getFirstNonNull((Supplier<Object>[]) null));
496         // test different types
497         assertEquals(1, ObjectUtils.getFirstNonNull(Suppliers.nul(), () -> 1));
498         assertEquals(Boolean.TRUE, ObjectUtils.getFirstNonNull(Suppliers.nul(), () -> Boolean.TRUE));
499     }
500 
501     @Test
502     void testGetIfNullObject() {
503         final Object o = FOO;
504         final Object defaultObject = BAR;
505         assertNull(ObjectUtils.getIfNull(null, (Object) null));
506         assertSame(defaultObject, ObjectUtils.getIfNull(null, defaultObject), "dflt was not returned when o was null");
507         assertSame(o, ObjectUtils.getIfNull(o, defaultObject), "dflt was returned when o was not null");
508     }
509 
510     @Test
511     void testGetIfNullSupplier() {
512         final Object o = FOO;
513         final Object defaultObject = BAR;
514         assertNull(ObjectUtils.getIfNull(null, (Supplier<Object>) null));
515         assertSame(defaultObject, ObjectUtils.getIfNull(null, () -> defaultObject), "dflt was not returned when o was null");
516         assertSame(o, ObjectUtils.getIfNull(o, () -> defaultObject), "dflt was returned when o was not null");
517         assertSame(o, ObjectUtils.getIfNull(FOO, () -> defaultObject), "dflt was returned when o was not null");
518         assertSame(o, ObjectUtils.getIfNull("foo", () -> defaultObject), "dflt was returned when o was not null");
519         final MutableInt callsCounter = new MutableInt(0);
520         final Supplier<Object> countingDefaultSupplier = () -> {
521             callsCounter.increment();
522             return defaultObject;
523         };
524         ObjectUtils.getIfNull(o, countingDefaultSupplier);
525         assertEquals(0, callsCounter.get());
526         ObjectUtils.getIfNull(null, countingDefaultSupplier);
527         assertEquals(1, callsCounter.get());
528     }
529 
530     @Test
531     void testHashCode() {
532         assertEquals(0, ObjectUtils.hashCode(null));
533         assertEquals("a".hashCode(), ObjectUtils.hashCode("a"));
534     }
535 
536     @Test
537     void testHashCodeHex() {
538         final Integer i = Integer.valueOf(90);
539         assertEquals(Integer.toHexString(Objects.hashCode(i)), ObjectUtils.hashCodeHex(i));
540         final Integer zero = Integer.valueOf(0);
541         assertEquals(Integer.toHexString(Objects.hashCode(zero)), ObjectUtils.hashCodeHex(zero));
542         assertEquals(Integer.toHexString(Objects.hashCode(null)), ObjectUtils.hashCodeHex(null));
543     }
544 
545     @Test
546     void testHashCodeMulti_multiple_emptyArray() {
547         final Object[] array = {};
548         assertEquals(1, ObjectUtils.hashCodeMulti(array));
549     }
550 
551     @Test
552     void testHashCodeMulti_multiple_likeList() {
553         final List<Object> list0 = new ArrayList<>(Collections.emptyList());
554         assertEquals(list0.hashCode(), ObjectUtils.hashCodeMulti());
555 
556         final List<Object> list1 = new ArrayList<>(Collections.singletonList("a"));
557         assertEquals(list1.hashCode(), ObjectUtils.hashCodeMulti("a"));
558 
559         final List<Object> list2 = new ArrayList<>(Arrays.asList("a", "b"));
560         assertEquals(list2.hashCode(), ObjectUtils.hashCodeMulti("a", "b"));
561 
562         final List<Object> list3 = new ArrayList<>(Arrays.asList("a", "b", "c"));
563         assertEquals(list3.hashCode(), ObjectUtils.hashCodeMulti("a", "b", "c"));
564     }
565 
566     @Test
567     void testHashCodeMulti_multiple_nullArray() {
568         final Object[] array = null;
569         assertEquals(1, ObjectUtils.hashCodeMulti(array));
570     }
571 
572     @Test
573     void testIdentityHashCodeHex() {
574         final Integer i = Integer.valueOf(90);
575         assertEquals(Integer.toHexString(System.identityHashCode(i)), ObjectUtils.identityHashCodeHex(i));
576         final Integer zero = Integer.valueOf(0);
577         assertEquals(Integer.toHexString(System.identityHashCode(zero)), ObjectUtils.identityHashCodeHex(zero));
578         assertEquals(Integer.toHexString(System.identityHashCode(null)), ObjectUtils.identityHashCodeHex(null));
579     }
580 
581     @Test
582     void testIdentityToStringAppendable() throws IOException {
583         final Integer i = Integer.valueOf(121);
584         final String expected = "java.lang.Integer@" + Integer.toHexString(System.identityHashCode(i));
585         final Appendable appendable = new StringBuilder();
586         ObjectUtils.identityToString(appendable, i);
587         assertEquals(expected, appendable.toString());
588         assertNullPointerException(() -> ObjectUtils.identityToString((Appendable) null, "tmp"));
589         assertNullPointerException(() -> ObjectUtils.identityToString((Appendable) new StringBuilder(), null));
590     }
591 
592     @Test
593     void testIdentityToStringInteger() {
594         final Integer i = Integer.valueOf(90);
595         final String expected = "java.lang.Integer@" + Integer.toHexString(System.identityHashCode(i));
596 
597         assertEquals(expected, ObjectUtils.identityToString(i));
598     }
599 
600     @Test
601     void testIdentityToStringObjectNull() {
602         assertNull(ObjectUtils.identityToString(null));
603     }
604 
605     @Test
606     void testIdentityToStringStrBuilder() {
607         final Integer i = Integer.valueOf(102);
608         final String expected = "java.lang.Integer@" + Integer.toHexString(System.identityHashCode(i));
609         final StrBuilder builder = new StrBuilder();
610         ObjectUtils.identityToString(builder, i);
611         assertEquals(expected, builder.toString());
612         assertNullPointerException(() -> ObjectUtils.identityToString((StrBuilder) null, "tmp"));
613         assertNullPointerException(() -> ObjectUtils.identityToString(new StrBuilder(), null));
614     }
615 
616     @Test
617     void testIdentityToStringString() {
618         assertEquals(
619                 "java.lang.String@" + Integer.toHexString(System.identityHashCode(FOO)),
620                 ObjectUtils.identityToString(FOO));
621     }
622 
623     @Test
624     void testIdentityToStringStringBuffer() {
625         final Integer i = Integer.valueOf(45);
626         final String expected = "java.lang.Integer@" + Integer.toHexString(System.identityHashCode(i));
627         final StringBuffer buffer = new StringBuffer();
628         ObjectUtils.identityToString(buffer, i);
629         assertEquals(expected, buffer.toString());
630         assertNullPointerException(() -> ObjectUtils.identityToString((StringBuffer) null, "tmp"));
631         assertNullPointerException(() -> ObjectUtils.identityToString(new StringBuffer(), null));
632     }
633 
634     @Test
635     void testIdentityToStringStringBuilder() {
636         final Integer i = Integer.valueOf(90);
637         final String expected = "java.lang.Integer@" + Integer.toHexString(System.identityHashCode(i));
638 
639         final StringBuilder builder = new StringBuilder();
640         ObjectUtils.identityToString(builder, i);
641         assertEquals(expected, builder.toString());
642     }
643 
644     @Test
645     void testIdentityToStringStringBuilderInUse() {
646         final Integer i = Integer.valueOf(90);
647         final String expected = "ABC = java.lang.Integer@" + Integer.toHexString(System.identityHashCode(i));
648         final StringBuilder builder = new StringBuilder("ABC = ");
649         ObjectUtils.identityToString(builder, i);
650         assertEquals(expected, builder.toString());
651     }
652 
653     @Test
654     public  void testIdentityToStringStringBuilderNullStringBuilder() {
655         assertNullPointerException(() -> ObjectUtils.identityToString((StringBuilder) null, "tmp"));
656     }
657 
658     @Test
659     void testIdentityToStringStringBuilderNullValue() {
660         assertNullPointerException(() -> ObjectUtils.identityToString(new StringBuilder(), null));
661     }
662 
663     @Test
664     void testIsEmpty() {
665         assertTrue(ObjectUtils.isEmpty(null));
666         assertTrue(ObjectUtils.isEmpty(""));
667         assertTrue(ObjectUtils.isEmpty(new int[] {}));
668         assertTrue(ObjectUtils.isEmpty(Collections.emptyList()));
669         assertTrue(ObjectUtils.isEmpty(Collections.emptySet()));
670         assertTrue(ObjectUtils.isEmpty(Collections.emptyMap()));
671         assertTrue(ObjectUtils.isEmpty(Optional.empty()));
672         assertTrue(ObjectUtils.isEmpty(Optional.ofNullable(null)));
673 
674         assertFalse(ObjectUtils.isEmpty("  "));
675         assertFalse(ObjectUtils.isEmpty("ab"));
676         assertFalse(ObjectUtils.isEmpty(NON_EMPTY_ARRAY));
677         assertFalse(ObjectUtils.isEmpty(NON_EMPTY_LIST));
678         assertFalse(ObjectUtils.isEmpty(NON_EMPTY_SET));
679         assertFalse(ObjectUtils.isEmpty(NON_EMPTY_MAP));
680         assertFalse(ObjectUtils.isEmpty(Optional.of(new Object())));
681         assertFalse(ObjectUtils.isEmpty(Optional.ofNullable(new Object())));
682         assertFalse(ObjectUtils.isEmpty(1234));
683     }
684 
685     @Test
686     void testIsNotEmpty() {
687         assertFalse(ObjectUtils.isNotEmpty(null));
688         assertFalse(ObjectUtils.isNotEmpty(""));
689         assertFalse(ObjectUtils.isNotEmpty(new int[] {}));
690         assertFalse(ObjectUtils.isNotEmpty(Collections.emptyList()));
691         assertFalse(ObjectUtils.isNotEmpty(Collections.emptySet()));
692         assertFalse(ObjectUtils.isNotEmpty(Collections.emptyMap()));
693         assertFalse(ObjectUtils.isNotEmpty(Optional.empty()));
694         assertFalse(ObjectUtils.isNotEmpty(Optional.ofNullable(null)));
695 
696         assertTrue(ObjectUtils.isNotEmpty("  "));
697         assertTrue(ObjectUtils.isNotEmpty("ab"));
698         assertTrue(ObjectUtils.isNotEmpty(NON_EMPTY_ARRAY));
699         assertTrue(ObjectUtils.isNotEmpty(NON_EMPTY_LIST));
700         assertTrue(ObjectUtils.isNotEmpty(NON_EMPTY_SET));
701         assertTrue(ObjectUtils.isNotEmpty(NON_EMPTY_MAP));
702         assertTrue(ObjectUtils.isNotEmpty(Optional.of(new Object())));
703         assertTrue(ObjectUtils.isNotEmpty(Optional.ofNullable(new Object())));
704     }
705 
706     @Test
707     void testMax() {
708         final Calendar calendar = Calendar.getInstance();
709         final Date nonNullComparable1 = calendar.getTime();
710         final Date nonNullComparable2 = calendar.getTime();
711         final String[] nullArray = null;
712 
713         calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 1);
714         final Date minComparable = calendar.getTime();
715 
716         assertNotSame(nonNullComparable1, nonNullComparable2);
717 
718         assertNull(ObjectUtils.max((String) null));
719         assertNull(ObjectUtils.max(nullArray));
720         assertSame(nonNullComparable1, ObjectUtils.max(null, nonNullComparable1));
721         assertSame(nonNullComparable1, ObjectUtils.max(nonNullComparable1, null));
722         assertSame(nonNullComparable1, ObjectUtils.max(null, nonNullComparable1, null));
723         assertSame(nonNullComparable1, ObjectUtils.max(nonNullComparable1, nonNullComparable2));
724         assertSame(nonNullComparable2, ObjectUtils.max(nonNullComparable2, nonNullComparable1));
725         assertSame(nonNullComparable1, ObjectUtils.max(nonNullComparable1, minComparable));
726         assertSame(nonNullComparable1, ObjectUtils.max(minComparable, nonNullComparable1));
727         assertSame(nonNullComparable1, ObjectUtils.max(null, minComparable, null, nonNullComparable1));
728 
729         assertNull(ObjectUtils.max(null, null));
730     }
731 
732     @Test
733     void testMedian() {
734         assertEquals("foo", ObjectUtils.median("foo"));
735         assertEquals("bar", ObjectUtils.median("foo", "bar"));
736         assertEquals("baz", ObjectUtils.median("foo", "bar", "baz"));
737         assertEquals("baz", ObjectUtils.median("foo", "bar", "baz", "blah"));
738         assertEquals("blah", ObjectUtils.median("foo", "bar", "baz", "blah", "wah"));
739         assertEquals(Integer.valueOf(5),
740             ObjectUtils.median(Integer.valueOf(1), Integer.valueOf(5), Integer.valueOf(10)));
741         assertEquals(
742             Integer.valueOf(7),
743             ObjectUtils.median(Integer.valueOf(5), Integer.valueOf(6), Integer.valueOf(7), Integer.valueOf(8),
744                 Integer.valueOf(9)));
745         assertEquals(Integer.valueOf(6),
746             ObjectUtils.median(Integer.valueOf(5), Integer.valueOf(6), Integer.valueOf(7), Integer.valueOf(8)));
747         // duplicates are counted, not collapsed
748         assertEquals(Integer.valueOf(3),
749             ObjectUtils.median(Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(3),
750                 Integer.valueOf(3), Integer.valueOf(4)));
751         assertEquals(Integer.valueOf(5),
752             ObjectUtils.median(Integer.valueOf(5), Integer.valueOf(5), Integer.valueOf(5), Integer.valueOf(1)));
753     }
754 
755     @Test
756     void testMedian_emptyItems() {
757         assertIllegalArgumentException(ObjectUtils::<String>median);
758     }
759 
760     @Test
761     void testMedian_nullItems() {
762         assertNullPointerException(() -> ObjectUtils.median((String[]) null));
763     }
764 
765     @Test
766     void testMin() {
767         final Calendar calendar = Calendar.getInstance();
768         final Date nonNullComparable1 = calendar.getTime();
769         final Date nonNullComparable2 = calendar.getTime();
770         final String[] nullArray = null;
771 
772         calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 1);
773         final Date minComparable = calendar.getTime();
774 
775         assertNotSame(nonNullComparable1, nonNullComparable2);
776 
777         assertNull(ObjectUtils.min((String) null));
778         assertNull(ObjectUtils.min(nullArray));
779         assertSame(nonNullComparable1, ObjectUtils.min(null, nonNullComparable1));
780         assertSame(nonNullComparable1, ObjectUtils.min(nonNullComparable1, null));
781         assertSame(nonNullComparable1, ObjectUtils.min(null, nonNullComparable1, null));
782         assertSame(nonNullComparable1, ObjectUtils.min(nonNullComparable1, nonNullComparable2));
783         assertSame(nonNullComparable2, ObjectUtils.min(nonNullComparable2, nonNullComparable1));
784         assertSame(minComparable, ObjectUtils.min(nonNullComparable1, minComparable));
785         assertSame(minComparable, ObjectUtils.min(minComparable, nonNullComparable1));
786         assertSame(minComparable, ObjectUtils.min(null, nonNullComparable1, null, minComparable));
787 
788         assertNull(ObjectUtils.min(null, null));
789     }
790 
791     @Test
792     void testMode() {
793         assertNull(ObjectUtils.mode((Object[]) null));
794         assertNull(ObjectUtils.mode());
795         assertNull(ObjectUtils.mode("foo", "bar", "baz"));
796         assertNull(ObjectUtils.mode("foo", "bar", "baz", "foo", "bar"));
797         assertEquals("foo", ObjectUtils.mode("foo", "bar", "baz", "foo"));
798         assertEquals(Integer.valueOf(9),
799             ObjectUtils.mode("foo", "bar", "baz", Integer.valueOf(9), Integer.valueOf(10), Integer.valueOf(9)));
800     }
801 
802     @Test
803     void testNotEqual() {
804         assertFalse(ObjectUtils.notEqual(null, null), "ObjectUtils.notEqual(null, null) returned false");
805         assertTrue(ObjectUtils.notEqual(FOO, null), "ObjectUtils.notEqual(\"foo\", null) returned true");
806         assertTrue(ObjectUtils.notEqual(null, BAR), "ObjectUtils.notEqual(null, \"bar\") returned true");
807         assertTrue(ObjectUtils.notEqual(FOO, BAR), "ObjectUtils.notEqual(\"foo\", \"bar\") returned true");
808         assertFalse(ObjectUtils.notEqual(FOO, FOO), "ObjectUtils.notEqual(\"foo\", \"foo\") returned false");
809     }
810 
811     @SuppressWarnings("cast") // 1 OK, because we are checking for code change
812     @Test
813     void testNull() {
814         assertNotNull(ObjectUtils.NULL);
815         // 1 Check that NULL really is a Null i.e. the definition has not been changed
816         assertInstanceOf(ObjectUtils.Null.class, ObjectUtils.NULL);
817         assertSame(ObjectUtils.NULL, SerializationUtils.clone(ObjectUtils.NULL));
818     }
819 
820     /**
821      * Tests {@link ObjectUtils#cloneIfPossible(Object)} with a cloneable object.
822      */
823     @Test
824     void testPossibleCloneOfCloneable() {
825         final CloneableString string = new CloneableString("apache");
826         final CloneableString stringClone = ObjectUtils.cloneIfPossible(string);
827         assertEquals("apache", stringClone.get());
828     }
829 
830     /**
831      * Tests {@link ObjectUtils#cloneIfPossible(Object)} with a not cloneable object.
832      */
833     @Test
834     void testPossibleCloneOfNotCloneable() {
835         final String string = "apache";
836         assertSame(string, ObjectUtils.cloneIfPossible(string));
837     }
838 
839     /**
840      * Tests {@link ObjectUtils#cloneIfPossible(Object)} with an uncloneable object.
841      */
842     @Test
843     void testPossibleCloneOfUncloneable() {
844         final UncloneableString string = new UncloneableString("apache");
845         final CloneFailedException e = assertThrows(CloneFailedException.class, () -> ObjectUtils.cloneIfPossible(string));
846         assertNotNull(e);
847         assertNotNull(e.getCause());
848         assertEquals(NoSuchMethodException.class, e.getCause().getClass());
849     }
850 
851     @Test
852     void testRequireNonEmpty() {
853         assertEquals("foo", ObjectUtils.requireNonEmpty("foo"));
854         assertEquals("foo", ObjectUtils.requireNonEmpty("foo", "foo"));
855         //
856         assertNullPointerException(() -> ObjectUtils.requireNonEmpty(null));
857         assertNullPointerException(() -> ObjectUtils.requireNonEmpty(null, "foo"));
858         //
859         assertIllegalArgumentException(() -> ObjectUtils.requireNonEmpty(""));
860         assertIllegalArgumentException(() -> ObjectUtils.requireNonEmpty("", "foo"));
861     }
862 
863     @Test
864     void testToString_Object() {
865         assertEquals("", ObjectUtils.toString(null));
866         assertEquals(Boolean.TRUE.toString(), ObjectUtils.toString(Boolean.TRUE));
867     }
868 
869     @Test
870     void testToString_Object_String() {
871         assertEquals(BAR, ObjectUtils.toString(null, BAR));
872         assertEquals(Boolean.TRUE.toString(), ObjectUtils.toString(Boolean.TRUE, BAR));
873     }
874 
875     @Test
876     void testToString_String_Supplier() {
877         assertNull(ObjectUtils.toString(null, (Supplier<String>) null));
878         assertNull(ObjectUtils.toString(null, Suppliers.nul()));
879         // Pretend computing BAR is expensive.
880         assertEquals(BAR, ObjectUtils.toString(null, () -> BAR));
881         assertEquals(Boolean.TRUE.toString(), ObjectUtils.toString(Boolean.TRUE, () -> BAR));
882     }
883 
884     @Test
885     void testToString_Supplier_Supplier() {
886         assertNull(ObjectUtils.toString(NULL_SUPPLIER, (Supplier<String>) null));
887         assertNull(ObjectUtils.toString(Suppliers.nul(), (Supplier<String>) null));
888         assertNull(ObjectUtils.toString(NULL_SUPPLIER, Suppliers.nul()));
889         assertNull(ObjectUtils.toString(Suppliers.nul(), Suppliers.nul()));
890         // Pretend computing BAR is expensive.
891         assertEquals(BAR, ObjectUtils.toString(NULL_SUPPLIER, () -> BAR));
892         assertEquals(BAR, ObjectUtils.toString(Suppliers.nul(), () -> BAR));
893         assertEquals(Boolean.TRUE.toString(), ObjectUtils.toString(() -> Boolean.TRUE, () -> BAR));
894     }
895 
896     @Test
897     void testWaitDuration() throws InterruptedException {
898         final Object lock = new Object();
899         try (MockedStatic<DurationUtils> mocked = mockStatic(DurationUtils.class)) {
900             // Let zeroIfNull run for real so the Duration reaches accept unchanged.
901             mocked.when(() -> DurationUtils.zeroIfNull(any())).thenCallRealMethod();
902             // accept is mocked to do nothing, so no actual waiting occurs.
903             final int millis = 1_500;
904             synchronized (lock) {
905                 ObjectUtils.wait(lock, Duration.ofMillis(millis));
906             }
907             // Verify accept was called with the expected Duration.
908             mocked.verify(() -> DurationUtils.accept(any(), eq(Duration.ofMillis(millis))));
909         }
910     }
911 
912     @Test
913     void testWaitDurationThrows() throws InterruptedException {
914         assertThrows(IllegalArgumentException.class, () -> ObjectUtils.wait(new Object(), Duration.ofSeconds(-10)));
915         assertThrows(IllegalMonitorStateException.class, () -> ObjectUtils.wait(new Object(), Duration.ZERO));
916     }
917 
918 }