1/*
2 * Copyright (C) 2008 The Guava Authors
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
17package com.google.common.primitives;
18
19import static java.lang.Float.NaN;
20import static org.junit.contrib.truth.Truth.ASSERT;
21
22import com.google.common.annotations.GwtCompatible;
23import com.google.common.annotations.GwtIncompatible;
24import com.google.common.collect.testing.Helpers;
25import com.google.common.testing.NullPointerTester;
26import com.google.common.testing.SerializableTester;
27
28import junit.framework.TestCase;
29
30import java.util.Arrays;
31import java.util.Collection;
32import java.util.Collections;
33import java.util.Comparator;
34import java.util.List;
35
36/**
37 * Unit test for {@link Floats}.
38 *
39 * @author Kevin Bourrillion
40 */
41@GwtCompatible(emulated = true)
42@SuppressWarnings("cast") // redundant casts are intentional and harmless
43public class FloatsTest extends TestCase {
44  private static final float[] EMPTY = {};
45  private static final float[] ARRAY1 = {(float) 1};
46  private static final float[] ARRAY234
47      = {(float) 2, (float) 3, (float) 4};
48
49  private static final float LEAST = Float.NEGATIVE_INFINITY;
50  private static final float GREATEST = Float.POSITIVE_INFINITY;
51
52  private static final float[] NUMBERS = new float[] {
53      LEAST, -Float.MAX_VALUE, -1f, -0f, 0f, 1f, Float.MAX_VALUE, GREATEST,
54      Float.MIN_NORMAL, -Float.MIN_NORMAL,  Float.MIN_VALUE, -Float.MIN_VALUE,
55      Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE
56  };
57
58  private static final float[] VALUES
59      = Floats.concat(NUMBERS, new float[] {NaN});
60
61  public void testHashCode() {
62    for (float value : VALUES) {
63      assertEquals(((Float) value).hashCode(), Floats.hashCode(value));
64    }
65  }
66
67  public void testIsFinite() {
68    for (float value : NUMBERS) {
69      assertEquals(!(Float.isInfinite(value) || Float.isNaN(value)), Floats.isFinite(value));
70    }
71  }
72
73  public void testCompare() {
74    for (float x : VALUES) {
75      for (float y : VALUES) {
76        // note: spec requires only that the sign is the same
77        assertEquals(x + ", " + y,
78                     Float.valueOf(x).compareTo(y),
79                     Floats.compare(x, y));
80      }
81    }
82  }
83
84  public void testContains() {
85    assertFalse(Floats.contains(EMPTY, (float) 1));
86    assertFalse(Floats.contains(ARRAY1, (float) 2));
87    assertFalse(Floats.contains(ARRAY234, (float) 1));
88    assertTrue(Floats.contains(new float[] {(float) -1}, (float) -1));
89    assertTrue(Floats.contains(ARRAY234, (float) 2));
90    assertTrue(Floats.contains(ARRAY234, (float) 3));
91    assertTrue(Floats.contains(ARRAY234, (float) 4));
92
93    for (float value : NUMBERS) {
94      assertTrue("" + value, Floats.contains(new float[] {5f, value}, value));
95    }
96    assertFalse(Floats.contains(new float[] {5f, NaN}, NaN));
97  }
98
99  public void testIndexOf() {
100    assertEquals(-1, Floats.indexOf(EMPTY, (float) 1));
101    assertEquals(-1, Floats.indexOf(ARRAY1, (float) 2));
102    assertEquals(-1, Floats.indexOf(ARRAY234, (float) 1));
103    assertEquals(0, Floats.indexOf(
104        new float[] {(float) -1}, (float) -1));
105    assertEquals(0, Floats.indexOf(ARRAY234, (float) 2));
106    assertEquals(1, Floats.indexOf(ARRAY234, (float) 3));
107    assertEquals(2, Floats.indexOf(ARRAY234, (float) 4));
108    assertEquals(1, Floats.indexOf(
109        new float[] { (float) 2, (float) 3, (float) 2, (float) 3 },
110        (float) 3));
111
112    for (float value : NUMBERS) {
113      assertEquals("" + value, 1,
114          Floats.indexOf(new float[] {5f, value}, value));
115    }
116    assertEquals(-1, Floats.indexOf(new float[] {5f, NaN}, NaN));
117  }
118
119  public void testIndexOf_arrayTarget() {
120    assertEquals(0, Floats.indexOf(EMPTY, EMPTY));
121    assertEquals(0, Floats.indexOf(ARRAY234, EMPTY));
122    assertEquals(-1, Floats.indexOf(EMPTY, ARRAY234));
123    assertEquals(-1, Floats.indexOf(ARRAY234, ARRAY1));
124    assertEquals(-1, Floats.indexOf(ARRAY1, ARRAY234));
125    assertEquals(0, Floats.indexOf(ARRAY1, ARRAY1));
126    assertEquals(0, Floats.indexOf(ARRAY234, ARRAY234));
127    assertEquals(0, Floats.indexOf(
128        ARRAY234, new float[] { (float) 2, (float) 3 }));
129    assertEquals(1, Floats.indexOf(
130        ARRAY234, new float[] { (float) 3, (float) 4 }));
131    assertEquals(1, Floats.indexOf(ARRAY234, new float[] { (float) 3 }));
132    assertEquals(2, Floats.indexOf(ARRAY234, new float[] { (float) 4 }));
133    assertEquals(1, Floats.indexOf(new float[] { (float) 2, (float) 3,
134        (float) 3, (float) 3, (float) 3 },
135        new float[] { (float) 3 }
136    ));
137    assertEquals(2, Floats.indexOf(
138        new float[] { (float) 2, (float) 3, (float) 2,
139            (float) 3, (float) 4, (float) 2, (float) 3},
140        new float[] { (float) 2, (float) 3, (float) 4}
141    ));
142    assertEquals(1, Floats.indexOf(
143        new float[] { (float) 2, (float) 2, (float) 3,
144            (float) 4, (float) 2, (float) 3, (float) 4},
145        new float[] { (float) 2, (float) 3, (float) 4}
146    ));
147    assertEquals(-1, Floats.indexOf(
148        new float[] { (float) 4, (float) 3, (float) 2},
149        new float[] { (float) 2, (float) 3, (float) 4}
150    ));
151
152    for (float value : NUMBERS) {
153      assertEquals("" + value, 1, Floats.indexOf(
154          new float[] {5f, value, value, 5f}, new float[] {value, value}));
155    }
156    assertEquals(-1, Floats.indexOf(
157        new float[] {5f, NaN, NaN, 5f}, new float[] {NaN, NaN}));
158  }
159
160  public void testLastIndexOf() {
161    assertEquals(-1, Floats.lastIndexOf(EMPTY, (float) 1));
162    assertEquals(-1, Floats.lastIndexOf(ARRAY1, (float) 2));
163    assertEquals(-1, Floats.lastIndexOf(ARRAY234, (float) 1));
164    assertEquals(0, Floats.lastIndexOf(
165        new float[] {(float) -1}, (float) -1));
166    assertEquals(0, Floats.lastIndexOf(ARRAY234, (float) 2));
167    assertEquals(1, Floats.lastIndexOf(ARRAY234, (float) 3));
168    assertEquals(2, Floats.lastIndexOf(ARRAY234, (float) 4));
169    assertEquals(3, Floats.lastIndexOf(
170        new float[] { (float) 2, (float) 3, (float) 2, (float) 3 },
171        (float) 3));
172
173    for (float value : NUMBERS) {
174      assertEquals("" + value,
175          0, Floats.lastIndexOf(new float[] {value, 5f}, value));
176    }
177    assertEquals(-1, Floats.lastIndexOf(new float[] {NaN, 5f}, NaN));
178  }
179
180  public void testMax_noArgs() {
181    try {
182      Floats.max();
183      fail();
184    } catch (IllegalArgumentException expected) {
185    }
186  }
187
188  public void testMax() {
189    assertEquals(GREATEST, Floats.max(GREATEST));
190    assertEquals(LEAST, Floats.max(LEAST));
191    assertEquals((float) 9, Floats.max(
192        (float) 8, (float) 6, (float) 7,
193        (float) 5, (float) 3, (float) 0, (float) 9));
194
195    assertEquals(0f, Floats.max(-0f, 0f));
196    assertEquals(0f, Floats.max(0f, -0f));
197    assertEquals(GREATEST, Floats.max(NUMBERS));
198    assertTrue(Float.isNaN(Floats.max(VALUES)));
199  }
200
201  public void testMin_noArgs() {
202    try {
203      Floats.min();
204      fail();
205    } catch (IllegalArgumentException expected) {
206    }
207  }
208
209  public void testMin() {
210    assertEquals(LEAST, Floats.min(LEAST));
211    assertEquals(GREATEST, Floats.min(GREATEST));
212    assertEquals((float) 0, Floats.min(
213        (float) 8, (float) 6, (float) 7,
214        (float) 5, (float) 3, (float) 0, (float) 9));
215
216    assertEquals(-0f, Floats.min(-0f, 0f));
217    assertEquals(-0f, Floats.min(0f, -0f));
218    assertEquals(LEAST, Floats.min(NUMBERS));
219    assertTrue(Float.isNaN(Floats.min(VALUES)));
220  }
221
222  public void testConcat() {
223    assertTrue(Arrays.equals(EMPTY, Floats.concat()));
224    assertTrue(Arrays.equals(EMPTY, Floats.concat(EMPTY)));
225    assertTrue(Arrays.equals(EMPTY, Floats.concat(EMPTY, EMPTY, EMPTY)));
226    assertTrue(Arrays.equals(ARRAY1, Floats.concat(ARRAY1)));
227    assertNotSame(ARRAY1, Floats.concat(ARRAY1));
228    assertTrue(Arrays.equals(ARRAY1, Floats.concat(EMPTY, ARRAY1, EMPTY)));
229    assertTrue(Arrays.equals(
230        new float[] {(float) 1, (float) 1, (float) 1},
231        Floats.concat(ARRAY1, ARRAY1, ARRAY1)));
232    assertTrue(Arrays.equals(
233        new float[] {(float) 1, (float) 2, (float) 3, (float) 4},
234        Floats.concat(ARRAY1, ARRAY234)));
235  }
236
237  public void testEnsureCapacity() {
238    assertSame(EMPTY, Floats.ensureCapacity(EMPTY, 0, 1));
239    assertSame(ARRAY1, Floats.ensureCapacity(ARRAY1, 0, 1));
240    assertSame(ARRAY1, Floats.ensureCapacity(ARRAY1, 1, 1));
241    assertTrue(Arrays.equals(
242        new float[] {(float) 1, (float) 0, (float) 0},
243        Floats.ensureCapacity(ARRAY1, 2, 1)));
244  }
245
246  public void testEnsureCapacity_fail() {
247    try {
248      Floats.ensureCapacity(ARRAY1, -1, 1);
249      fail();
250    } catch (IllegalArgumentException expected) {
251    }
252    try {
253      // notice that this should even fail when no growth was needed
254      Floats.ensureCapacity(ARRAY1, 1, -1);
255      fail();
256    } catch (IllegalArgumentException expected) {
257    }
258  }
259
260  @GwtIncompatible("Float.toString returns different value in GWT.")
261  public void testJoin() {
262    assertEquals("", Floats.join(",", EMPTY));
263    assertEquals("1.0", Floats.join(",", ARRAY1));
264    assertEquals("1.0,2.0", Floats.join(",", (float) 1, (float) 2));
265    assertEquals("1.02.03.0",
266        Floats.join("", (float) 1, (float) 2, (float) 3));
267  }
268
269  public void testLexicographicalComparator() {
270    List<float[]> ordered = Arrays.asList(
271        new float[] {},
272        new float[] {LEAST},
273        new float[] {LEAST, LEAST},
274        new float[] {LEAST, (float) 1},
275        new float[] {(float) 1},
276        new float[] {(float) 1, LEAST},
277        new float[] {GREATEST, Float.MAX_VALUE},
278        new float[] {GREATEST, GREATEST},
279        new float[] {GREATEST, GREATEST, GREATEST});
280
281    Comparator<float[]> comparator = Floats.lexicographicalComparator();
282    Helpers.testComparator(comparator, ordered);
283  }
284
285  @GwtIncompatible("SerializableTester")
286  public void testLexicographicalComparatorSerializable() {
287    Comparator<float[]> comparator = Floats.lexicographicalComparator();
288    assertSame(comparator, SerializableTester.reserialize(comparator));
289  }
290
291  public void testToArray() {
292    // need explicit type parameter to avoid javac warning!?
293    List<Float> none = Arrays.<Float>asList();
294    assertTrue(Arrays.equals(EMPTY, Floats.toArray(none)));
295
296    List<Float> one = Arrays.asList((float) 1);
297    assertTrue(Arrays.equals(ARRAY1, Floats.toArray(one)));
298
299    float[] array = {(float) 0, (float) 1, (float) 3};
300
301    List<Float> three = Arrays.asList((float) 0, (float) 1, (float) 3);
302    assertTrue(Arrays.equals(array, Floats.toArray(three)));
303
304    assertTrue(Arrays.equals(array, Floats.toArray(Floats.asList(array))));
305  }
306
307  public void testToArray_threadSafe() {
308    for (int delta : new int[] { +1, 0, -1 }) {
309      for (int i = 0; i < VALUES.length; i++) {
310        List<Float> list = Floats.asList(VALUES).subList(0, i);
311        Collection<Float> misleadingSize =
312            Helpers.misleadingSizeCollection(delta);
313        misleadingSize.addAll(list);
314        float[] arr = Floats.toArray(misleadingSize);
315        assertEquals(i, arr.length);
316        for (int j = 0; j < i; j++) {
317          assertEquals(VALUES[j], arr[j]);
318        }
319      }
320    }
321  }
322
323  public void testToArray_withNull() {
324    List<Float> list = Arrays.asList((float) 0, (float) 1, null);
325    try {
326      Floats.toArray(list);
327      fail();
328    } catch (NullPointerException expected) {
329    }
330  }
331
332  public void testAsList_isAView() {
333    float[] array = {(float) 0, (float) 1};
334    List<Float> list = Floats.asList(array);
335    list.set(0, (float) 2);
336    assertTrue(Arrays.equals(new float[] {(float) 2, (float) 1}, array));
337    array[1] = (float) 3;
338    ASSERT.that(list).hasContentsInOrder((float) 2, (float) 3);
339  }
340
341  public void testAsList_toArray_roundTrip() {
342    float[] array = { (float) 0, (float) 1, (float) 2 };
343    List<Float> list = Floats.asList(array);
344    float[] newArray = Floats.toArray(list);
345
346    // Make sure it returned a copy
347    list.set(0, (float) 4);
348    assertTrue(Arrays.equals(
349        new float[] { (float) 0, (float) 1, (float) 2 }, newArray));
350    newArray[1] = (float) 5;
351    assertEquals((float) 1, (float) list.get(1));
352  }
353
354  // This test stems from a real bug found by andrewk
355  public void testAsList_subList_toArray_roundTrip() {
356    float[] array = { (float) 0, (float) 1, (float) 2, (float) 3 };
357    List<Float> list = Floats.asList(array);
358    assertTrue(Arrays.equals(new float[] { (float) 1, (float) 2 },
359        Floats.toArray(list.subList(1, 3))));
360    assertTrue(Arrays.equals(new float[] {},
361        Floats.toArray(list.subList(2, 2))));
362  }
363
364  public void testAsListEmpty() {
365    assertSame(Collections.emptyList(), Floats.asList(EMPTY));
366  }
367
368  @GwtIncompatible("NullPointerTester")
369  public void testNulls() throws Exception {
370    NullPointerTester tester = new NullPointerTester();
371    tester.setDefault(float[].class, new float[0]);
372    tester.testAllPublicStaticMethods(Floats.class);
373  }
374}
375