View Javadoc
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  
17  package com.google.common.primitives;
18  
19  import static com.google.common.truth.Truth.assertThat;
20  import static java.lang.Float.NaN;
21  
22  import com.google.common.annotations.GwtCompatible;
23  import com.google.common.collect.testing.Helpers;
24  
25  import junit.framework.TestCase;
26  
27  import java.util.Arrays;
28  import java.util.Collection;
29  import java.util.Collections;
30  import java.util.Comparator;
31  import java.util.List;
32  
33  /**
34   * Unit test for {@link Floats}.
35   *
36   * @author Kevin Bourrillion
37   */
38  @GwtCompatible(emulated = true)
39  @SuppressWarnings("cast") // redundant casts are intentional and harmless
40  public class FloatsTest extends TestCase {
41    private static final float[] EMPTY = {};
42    private static final float[] ARRAY1 = {(float) 1};
43    private static final float[] ARRAY234
44        = {(float) 2, (float) 3, (float) 4};
45  
46    private static final float LEAST = Float.NEGATIVE_INFINITY;
47    private static final float GREATEST = Float.POSITIVE_INFINITY;
48  
49    private static final float[] NUMBERS = new float[] {
50        LEAST, -Float.MAX_VALUE, -1f, -0f, 0f, 1f, Float.MAX_VALUE, GREATEST,
51        Float.MIN_NORMAL, -Float.MIN_NORMAL,  Float.MIN_VALUE, -Float.MIN_VALUE,
52        Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE
53    };
54  
55    private static final float[] VALUES
56        = Floats.concat(NUMBERS, new float[] {NaN});
57  
58    public void testHashCode() {
59      for (float value : VALUES) {
60        assertEquals(((Float) value).hashCode(), Floats.hashCode(value));
61      }
62    }
63  
64    public void testIsFinite() {
65      for (float value : NUMBERS) {
66        assertEquals(!(Float.isInfinite(value) || Float.isNaN(value)), Floats.isFinite(value));
67      }
68    }
69  
70    public void testCompare() {
71      for (float x : VALUES) {
72        for (float y : VALUES) {
73          // note: spec requires only that the sign is the same
74          assertEquals(x + ", " + y,
75                       Float.valueOf(x).compareTo(y),
76                       Floats.compare(x, y));
77        }
78      }
79    }
80  
81    public void testContains() {
82      assertFalse(Floats.contains(EMPTY, (float) 1));
83      assertFalse(Floats.contains(ARRAY1, (float) 2));
84      assertFalse(Floats.contains(ARRAY234, (float) 1));
85      assertTrue(Floats.contains(new float[] {(float) -1}, (float) -1));
86      assertTrue(Floats.contains(ARRAY234, (float) 2));
87      assertTrue(Floats.contains(ARRAY234, (float) 3));
88      assertTrue(Floats.contains(ARRAY234, (float) 4));
89  
90      for (float value : NUMBERS) {
91        assertTrue("" + value, Floats.contains(new float[] {5f, value}, value));
92      }
93      assertFalse(Floats.contains(new float[] {5f, NaN}, NaN));
94    }
95  
96    public void testIndexOf() {
97      assertEquals(-1, Floats.indexOf(EMPTY, (float) 1));
98      assertEquals(-1, Floats.indexOf(ARRAY1, (float) 2));
99      assertEquals(-1, Floats.indexOf(ARRAY234, (float) 1));
100     assertEquals(0, Floats.indexOf(
101         new float[] {(float) -1}, (float) -1));
102     assertEquals(0, Floats.indexOf(ARRAY234, (float) 2));
103     assertEquals(1, Floats.indexOf(ARRAY234, (float) 3));
104     assertEquals(2, Floats.indexOf(ARRAY234, (float) 4));
105     assertEquals(1, Floats.indexOf(
106         new float[] { (float) 2, (float) 3, (float) 2, (float) 3 },
107         (float) 3));
108 
109     for (float value : NUMBERS) {
110       assertEquals("" + value, 1,
111           Floats.indexOf(new float[] {5f, value}, value));
112     }
113     assertEquals(-1, Floats.indexOf(new float[] {5f, NaN}, NaN));
114   }
115 
116   public void testIndexOf_arrayTarget() {
117     assertEquals(0, Floats.indexOf(EMPTY, EMPTY));
118     assertEquals(0, Floats.indexOf(ARRAY234, EMPTY));
119     assertEquals(-1, Floats.indexOf(EMPTY, ARRAY234));
120     assertEquals(-1, Floats.indexOf(ARRAY234, ARRAY1));
121     assertEquals(-1, Floats.indexOf(ARRAY1, ARRAY234));
122     assertEquals(0, Floats.indexOf(ARRAY1, ARRAY1));
123     assertEquals(0, Floats.indexOf(ARRAY234, ARRAY234));
124     assertEquals(0, Floats.indexOf(
125         ARRAY234, new float[] { (float) 2, (float) 3 }));
126     assertEquals(1, Floats.indexOf(
127         ARRAY234, new float[] { (float) 3, (float) 4 }));
128     assertEquals(1, Floats.indexOf(ARRAY234, new float[] { (float) 3 }));
129     assertEquals(2, Floats.indexOf(ARRAY234, new float[] { (float) 4 }));
130     assertEquals(1, Floats.indexOf(new float[] { (float) 2, (float) 3,
131         (float) 3, (float) 3, (float) 3 },
132         new float[] { (float) 3 }
133     ));
134     assertEquals(2, Floats.indexOf(
135         new float[] { (float) 2, (float) 3, (float) 2,
136             (float) 3, (float) 4, (float) 2, (float) 3},
137         new float[] { (float) 2, (float) 3, (float) 4}
138     ));
139     assertEquals(1, Floats.indexOf(
140         new float[] { (float) 2, (float) 2, (float) 3,
141             (float) 4, (float) 2, (float) 3, (float) 4},
142         new float[] { (float) 2, (float) 3, (float) 4}
143     ));
144     assertEquals(-1, Floats.indexOf(
145         new float[] { (float) 4, (float) 3, (float) 2},
146         new float[] { (float) 2, (float) 3, (float) 4}
147     ));
148 
149     for (float value : NUMBERS) {
150       assertEquals("" + value, 1, Floats.indexOf(
151           new float[] {5f, value, value, 5f}, new float[] {value, value}));
152     }
153     assertEquals(-1, Floats.indexOf(
154         new float[] {5f, NaN, NaN, 5f}, new float[] {NaN, NaN}));
155   }
156 
157   public void testLastIndexOf() {
158     assertEquals(-1, Floats.lastIndexOf(EMPTY, (float) 1));
159     assertEquals(-1, Floats.lastIndexOf(ARRAY1, (float) 2));
160     assertEquals(-1, Floats.lastIndexOf(ARRAY234, (float) 1));
161     assertEquals(0, Floats.lastIndexOf(
162         new float[] {(float) -1}, (float) -1));
163     assertEquals(0, Floats.lastIndexOf(ARRAY234, (float) 2));
164     assertEquals(1, Floats.lastIndexOf(ARRAY234, (float) 3));
165     assertEquals(2, Floats.lastIndexOf(ARRAY234, (float) 4));
166     assertEquals(3, Floats.lastIndexOf(
167         new float[] { (float) 2, (float) 3, (float) 2, (float) 3 },
168         (float) 3));
169 
170     for (float value : NUMBERS) {
171       assertEquals("" + value,
172           0, Floats.lastIndexOf(new float[] {value, 5f}, value));
173     }
174     assertEquals(-1, Floats.lastIndexOf(new float[] {NaN, 5f}, NaN));
175   }
176 
177   public void testMax_noArgs() {
178     try {
179       Floats.max();
180       fail();
181     } catch (IllegalArgumentException expected) {
182     }
183   }
184 
185   public void testMax() {
186     assertEquals(GREATEST, Floats.max(GREATEST));
187     assertEquals(LEAST, Floats.max(LEAST));
188     assertEquals((float) 9, Floats.max(
189         (float) 8, (float) 6, (float) 7,
190         (float) 5, (float) 3, (float) 0, (float) 9));
191 
192     assertEquals(0f, Floats.max(-0f, 0f));
193     assertEquals(0f, Floats.max(0f, -0f));
194     assertEquals(GREATEST, Floats.max(NUMBERS));
195     assertTrue(Float.isNaN(Floats.max(VALUES)));
196   }
197 
198   public void testMin_noArgs() {
199     try {
200       Floats.min();
201       fail();
202     } catch (IllegalArgumentException expected) {
203     }
204   }
205 
206   public void testMin() {
207     assertEquals(LEAST, Floats.min(LEAST));
208     assertEquals(GREATEST, Floats.min(GREATEST));
209     assertEquals((float) 0, Floats.min(
210         (float) 8, (float) 6, (float) 7,
211         (float) 5, (float) 3, (float) 0, (float) 9));
212 
213     assertEquals(-0f, Floats.min(-0f, 0f));
214     assertEquals(-0f, Floats.min(0f, -0f));
215     assertEquals(LEAST, Floats.min(NUMBERS));
216     assertTrue(Float.isNaN(Floats.min(VALUES)));
217   }
218 
219   public void testConcat() {
220     assertTrue(Arrays.equals(EMPTY, Floats.concat()));
221     assertTrue(Arrays.equals(EMPTY, Floats.concat(EMPTY)));
222     assertTrue(Arrays.equals(EMPTY, Floats.concat(EMPTY, EMPTY, EMPTY)));
223     assertTrue(Arrays.equals(ARRAY1, Floats.concat(ARRAY1)));
224     assertNotSame(ARRAY1, Floats.concat(ARRAY1));
225     assertTrue(Arrays.equals(ARRAY1, Floats.concat(EMPTY, ARRAY1, EMPTY)));
226     assertTrue(Arrays.equals(
227         new float[] {(float) 1, (float) 1, (float) 1},
228         Floats.concat(ARRAY1, ARRAY1, ARRAY1)));
229     assertTrue(Arrays.equals(
230         new float[] {(float) 1, (float) 2, (float) 3, (float) 4},
231         Floats.concat(ARRAY1, ARRAY234)));
232   }
233 
234   public void testEnsureCapacity() {
235     assertSame(EMPTY, Floats.ensureCapacity(EMPTY, 0, 1));
236     assertSame(ARRAY1, Floats.ensureCapacity(ARRAY1, 0, 1));
237     assertSame(ARRAY1, Floats.ensureCapacity(ARRAY1, 1, 1));
238     assertTrue(Arrays.equals(
239         new float[] {(float) 1, (float) 0, (float) 0},
240         Floats.ensureCapacity(ARRAY1, 2, 1)));
241   }
242 
243   public void testEnsureCapacity_fail() {
244     try {
245       Floats.ensureCapacity(ARRAY1, -1, 1);
246       fail();
247     } catch (IllegalArgumentException expected) {
248     }
249     try {
250       // notice that this should even fail when no growth was needed
251       Floats.ensureCapacity(ARRAY1, 1, -1);
252       fail();
253     } catch (IllegalArgumentException expected) {
254     }
255   }
256 
257   public void testLexicographicalComparator() {
258     List<float[]> ordered = Arrays.asList(
259         new float[] {},
260         new float[] {LEAST},
261         new float[] {LEAST, LEAST},
262         new float[] {LEAST, (float) 1},
263         new float[] {(float) 1},
264         new float[] {(float) 1, LEAST},
265         new float[] {GREATEST, Float.MAX_VALUE},
266         new float[] {GREATEST, GREATEST},
267         new float[] {GREATEST, GREATEST, GREATEST});
268 
269     Comparator<float[]> comparator = Floats.lexicographicalComparator();
270     Helpers.testComparator(comparator, ordered);
271   }
272 
273   public void testToArray() {
274     // need explicit type parameter to avoid javac warning!?
275     List<Float> none = Arrays.<Float>asList();
276     assertTrue(Arrays.equals(EMPTY, Floats.toArray(none)));
277 
278     List<Float> one = Arrays.asList((float) 1);
279     assertTrue(Arrays.equals(ARRAY1, Floats.toArray(one)));
280 
281     float[] array = {(float) 0, (float) 1, (float) 3};
282 
283     List<Float> three = Arrays.asList((float) 0, (float) 1, (float) 3);
284     assertTrue(Arrays.equals(array, Floats.toArray(three)));
285 
286     assertTrue(Arrays.equals(array, Floats.toArray(Floats.asList(array))));
287   }
288 
289   public void testToArray_threadSafe() {
290     for (int delta : new int[] { +1, 0, -1 }) {
291       for (int i = 0; i < VALUES.length; i++) {
292         List<Float> list = Floats.asList(VALUES).subList(0, i);
293         Collection<Float> misleadingSize =
294             Helpers.misleadingSizeCollection(delta);
295         misleadingSize.addAll(list);
296         float[] arr = Floats.toArray(misleadingSize);
297         assertEquals(i, arr.length);
298         for (int j = 0; j < i; j++) {
299           assertEquals(VALUES[j], arr[j]);
300         }
301       }
302     }
303   }
304 
305   public void testToArray_withNull() {
306     List<Float> list = Arrays.asList((float) 0, (float) 1, null);
307     try {
308       Floats.toArray(list);
309       fail();
310     } catch (NullPointerException expected) {
311     }
312   }
313 
314   public void testToArray_withConversion() {
315     float[] array = {(float) 0, (float) 1, (float) 2};
316 
317     List<Byte> bytes = Arrays.asList((byte) 0, (byte) 1, (byte) 2);
318     List<Short> shorts = Arrays.asList((short) 0, (short) 1, (short) 2);
319     List<Integer> ints = Arrays.asList(0, 1, 2);
320     List<Float> floats = Arrays.asList((float) 0, (float) 1, (float) 2);
321     List<Long> longs = Arrays.asList((long) 0, (long) 1, (long) 2);
322     List<Double> doubles = Arrays.asList((double) 0, (double) 1, (double) 2);
323 
324     assertTrue(Arrays.equals(array, Floats.toArray(bytes)));
325     assertTrue(Arrays.equals(array, Floats.toArray(shorts)));
326     assertTrue(Arrays.equals(array, Floats.toArray(ints)));
327     assertTrue(Arrays.equals(array, Floats.toArray(floats)));
328     assertTrue(Arrays.equals(array, Floats.toArray(longs)));
329     assertTrue(Arrays.equals(array, Floats.toArray(doubles)));
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     assertThat(list).has().exactly((float) 2, (float) 3).inOrder();
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   /**
369    * A reference implementation for {@code tryParse} that just catches the exception from
370    * {@link Float#valueOf}.
371    */
372   private static Float referenceTryParse(String input) {
373     if (input.trim().length() < input.length()) {
374       return null;
375     }
376     try {
377       return Float.valueOf(input);
378     } catch (NumberFormatException e) {
379       return null;
380     }
381  }
382 
383   private static final String[] BAD_TRY_PARSE_INPUTS =
384     { "", "+-", "+-0", " 5", "32 ", " 55 ", "infinity", "POSITIVE_INFINITY", "0x9A", "0x9A.bE-5",
385       ".", ".e5", "NaNd", "InfinityF" };
386 
387   public void testStringConverter_convertError() {
388     try {
389       Floats.stringConverter().convert("notanumber");
390       fail();
391     } catch (NumberFormatException expected) {
392     }
393   }
394 
395   public void testStringConverter_nullConversions() {
396     assertNull(Floats.stringConverter().convert(null));
397     assertNull(Floats.stringConverter().reverse().convert(null));
398   }
399 }
400