| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.math3.util; |
| |
| import java.util.ConcurrentModificationException; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.NoSuchElementException; |
| import java.util.Random; |
| import java.util.Set; |
| import java.util.Map.Entry; |
| |
| import org.apache.commons.math3.Field; |
| import org.apache.commons.math3.fraction.Fraction; |
| import org.apache.commons.math3.fraction.FractionConversionException; |
| import org.apache.commons.math3.fraction.FractionField; |
| import org.junit.Assert; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| |
| @SuppressWarnings("boxing") |
| public class OpenIntToFieldTest { |
| |
| private Map<Integer, Fraction> javaMap = new HashMap<Integer, Fraction>(); |
| private FractionField field = FractionField.getInstance(); |
| |
| @Before |
| public void setUp() throws FractionConversionException { |
| javaMap.put(50, new Fraction(100.0)); |
| javaMap.put(75, new Fraction(75.0)); |
| javaMap.put(25, new Fraction(500.0)); |
| javaMap.put(Integer.MAX_VALUE, new Fraction(Integer.MAX_VALUE)); |
| javaMap.put(0, new Fraction(-1.0)); |
| javaMap.put(1, new Fraction(0.0)); |
| javaMap.put(33, new Fraction(-0.1)); |
| javaMap.put(23234234, new Fraction(-242343.0)); |
| javaMap.put(23321, new Fraction (Integer.MIN_VALUE)); |
| javaMap.put(-4444, new Fraction(332.0)); |
| javaMap.put(-1, new Fraction(-2323.0)); |
| javaMap.put(Integer.MIN_VALUE, new Fraction(44.0)); |
| |
| /* Add a few more to cause the table to rehash */ |
| javaMap.putAll(generate()); |
| |
| } |
| |
| private Map<Integer, Fraction> generate() { |
| Map<Integer, Fraction> map = new HashMap<Integer, Fraction>(); |
| Random r = new Random(); |
| double dd=0; |
| for (int i = 0; i < 2000; ++i) |
| dd = r.nextDouble(); |
| try { |
| map.put(r.nextInt(), new Fraction(dd)); |
| } catch (FractionConversionException e) { |
| throw new IllegalStateException("Invalid :"+dd, e); |
| } |
| return map; |
| } |
| |
| private OpenIntToFieldHashMap<Fraction> createFromJavaMap(Field<Fraction> field) { |
| OpenIntToFieldHashMap<Fraction> map = new OpenIntToFieldHashMap<Fraction>(field); |
| for (Map.Entry<Integer, Fraction> mapEntry : javaMap.entrySet()) { |
| map.put(mapEntry.getKey(), mapEntry.getValue()); |
| } |
| return map; |
| } |
| |
| @Test |
| public void testPutAndGetWith0ExpectedSize() { |
| OpenIntToFieldHashMap<Fraction> map = new OpenIntToFieldHashMap<Fraction>(field,0); |
| assertPutAndGet(map); |
| } |
| |
| @Test |
| public void testPutAndGetWithExpectedSize() { |
| OpenIntToFieldHashMap<Fraction> map = new OpenIntToFieldHashMap<Fraction>(field,500); |
| assertPutAndGet(map); |
| } |
| |
| @Test |
| public void testPutAndGet() { |
| OpenIntToFieldHashMap<Fraction> map = new OpenIntToFieldHashMap<Fraction>(field); |
| assertPutAndGet(map); |
| } |
| |
| private void assertPutAndGet(OpenIntToFieldHashMap<Fraction> map) { |
| assertPutAndGet(map, 0, new HashSet<Integer>()); |
| } |
| |
| private void assertPutAndGet(OpenIntToFieldHashMap<Fraction> map, int mapSize, |
| Set<Integer> keysInMap) { |
| Assert.assertEquals(mapSize, map.size()); |
| for (Map.Entry<Integer, Fraction> mapEntry : javaMap.entrySet()) { |
| map.put(mapEntry.getKey(), mapEntry.getValue()); |
| if (!keysInMap.contains(mapEntry.getKey())) |
| ++mapSize; |
| Assert.assertEquals(mapSize, map.size()); |
| Assert.assertEquals(mapEntry.getValue(), map.get(mapEntry.getKey())); |
| } |
| } |
| |
| @Test |
| public void testPutAbsentOnExisting() { |
| OpenIntToFieldHashMap<Fraction> map = createFromJavaMap(field); |
| int size = javaMap.size(); |
| for (Map.Entry<Integer, Fraction> mapEntry : generateAbsent().entrySet()) { |
| map.put(mapEntry.getKey(), mapEntry.getValue()); |
| Assert.assertEquals(++size, map.size()); |
| Assert.assertEquals(mapEntry.getValue(), map.get(mapEntry.getKey())); |
| } |
| } |
| |
| @Test |
| public void testPutOnExisting() { |
| OpenIntToFieldHashMap<Fraction> map = createFromJavaMap(field); |
| for (Map.Entry<Integer, Fraction> mapEntry : javaMap.entrySet()) { |
| map.put(mapEntry.getKey(), mapEntry.getValue()); |
| Assert.assertEquals(javaMap.size(), map.size()); |
| Assert.assertEquals(mapEntry.getValue(), map.get(mapEntry.getKey())); |
| } |
| } |
| |
| @Test |
| public void testGetAbsent() { |
| Map<Integer, Fraction> generated = generateAbsent(); |
| OpenIntToFieldHashMap<Fraction> map = createFromJavaMap(field); |
| |
| for (Map.Entry<Integer, Fraction> mapEntry : generated.entrySet()) |
| Assert.assertTrue(field.getZero().equals(map.get(mapEntry.getKey()))); |
| } |
| |
| @Test |
| public void testGetFromEmpty() { |
| OpenIntToFieldHashMap<Fraction> map = new OpenIntToFieldHashMap<Fraction>(field); |
| Assert.assertTrue(field.getZero().equals(map.get(5))); |
| Assert.assertTrue(field.getZero().equals(map.get(0))); |
| Assert.assertTrue(field.getZero().equals(map.get(50))); |
| } |
| |
| @Test |
| public void testRemove() { |
| OpenIntToFieldHashMap<Fraction> map = createFromJavaMap(field); |
| int mapSize = javaMap.size(); |
| Assert.assertEquals(mapSize, map.size()); |
| for (Map.Entry<Integer, Fraction> mapEntry : javaMap.entrySet()) { |
| map.remove(mapEntry.getKey()); |
| Assert.assertEquals(--mapSize, map.size()); |
| Assert.assertTrue(field.getZero().equals(map.get(mapEntry.getKey()))); |
| } |
| |
| /* Ensure that put and get still work correctly after removals */ |
| assertPutAndGet(map); |
| } |
| |
| /* This time only remove some entries */ |
| @Test |
| public void testRemove2() { |
| OpenIntToFieldHashMap<Fraction> map = createFromJavaMap(field); |
| int mapSize = javaMap.size(); |
| int count = 0; |
| Set<Integer> keysInMap = new HashSet<Integer>(javaMap.keySet()); |
| for (Map.Entry<Integer, Fraction> mapEntry : javaMap.entrySet()) { |
| keysInMap.remove(mapEntry.getKey()); |
| map.remove(mapEntry.getKey()); |
| Assert.assertEquals(--mapSize, map.size()); |
| Assert.assertTrue(field.getZero().equals(map.get(mapEntry.getKey()))); |
| if (count++ > 5) |
| break; |
| } |
| |
| /* Ensure that put and get still work correctly after removals */ |
| assertPutAndGet(map, mapSize, keysInMap); |
| } |
| |
| @Test |
| public void testRemoveFromEmpty() { |
| OpenIntToFieldHashMap<Fraction> map = new OpenIntToFieldHashMap<Fraction>(field); |
| Assert.assertTrue(field.getZero().equals(map.remove(50))); |
| } |
| |
| @Test |
| public void testRemoveAbsent() { |
| Map<Integer, Fraction> generated = generateAbsent(); |
| |
| OpenIntToFieldHashMap<Fraction> map = createFromJavaMap(field); |
| int mapSize = map.size(); |
| |
| for (Map.Entry<Integer, Fraction> mapEntry : generated.entrySet()) { |
| map.remove(mapEntry.getKey()); |
| Assert.assertEquals(mapSize, map.size()); |
| Assert.assertTrue(field.getZero().equals(map.get(mapEntry.getKey()))); |
| } |
| } |
| |
| /** |
| * Returns a map with at least 100 elements where each element is absent from javaMap. |
| */ |
| private Map<Integer, Fraction> generateAbsent() { |
| Map<Integer, Fraction> generated = new HashMap<Integer, Fraction>(); |
| do { |
| generated.putAll(generate()); |
| for (Integer key : javaMap.keySet()) |
| generated.remove(key); |
| } while (generated.size() < 100); |
| return generated; |
| } |
| |
| @Test |
| public void testCopy() { |
| OpenIntToFieldHashMap<Fraction> copy = |
| new OpenIntToFieldHashMap<Fraction>(createFromJavaMap(field)); |
| Assert.assertEquals(javaMap.size(), copy.size()); |
| |
| for (Map.Entry<Integer, Fraction> mapEntry : javaMap.entrySet()) |
| Assert.assertEquals(mapEntry.getValue(), copy.get(mapEntry.getKey())); |
| } |
| |
| @Test |
| public void testContainsKey() { |
| OpenIntToFieldHashMap<Fraction> map = createFromJavaMap(field); |
| for (Entry<Integer, Fraction> mapEntry : javaMap.entrySet()) { |
| Assert.assertTrue(map.containsKey(mapEntry.getKey())); |
| } |
| for (Map.Entry<Integer, Fraction> mapEntry : generateAbsent().entrySet()) { |
| Assert.assertFalse(map.containsKey(mapEntry.getKey())); |
| } |
| for (Entry<Integer, Fraction> mapEntry : javaMap.entrySet()) { |
| int key = mapEntry.getKey(); |
| Assert.assertTrue(map.containsKey(key)); |
| map.remove(key); |
| Assert.assertFalse(map.containsKey(key)); |
| } |
| } |
| |
| @Test |
| public void testIterator() { |
| OpenIntToFieldHashMap<Fraction> map = createFromJavaMap(field); |
| OpenIntToFieldHashMap<Fraction>.Iterator iterator = map.iterator(); |
| for (int i = 0; i < map.size(); ++i) { |
| Assert.assertTrue(iterator.hasNext()); |
| iterator.advance(); |
| int key = iterator.key(); |
| Assert.assertTrue(map.containsKey(key)); |
| Assert.assertEquals(javaMap.get(key), map.get(key)); |
| Assert.assertEquals(javaMap.get(key), iterator.value()); |
| Assert.assertTrue(javaMap.containsKey(key)); |
| } |
| Assert.assertFalse(iterator.hasNext()); |
| try { |
| iterator.advance(); |
| Assert.fail("an exception should have been thrown"); |
| } catch (NoSuchElementException nsee) { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testConcurrentModification() { |
| OpenIntToFieldHashMap<Fraction> map = createFromJavaMap(field); |
| OpenIntToFieldHashMap<Fraction>.Iterator iterator = map.iterator(); |
| map.put(3, new Fraction(3)); |
| try { |
| iterator.advance(); |
| Assert.fail("an exception should have been thrown"); |
| } catch (ConcurrentModificationException cme) { |
| // expected |
| } |
| } |
| |
| /** |
| * Regression test for a bug in findInsertionIndex where the hashing in the second probing |
| * loop was inconsistent with the first causing duplicate keys after the right sequence |
| * of puts and removes. |
| */ |
| @Test |
| public void testPutKeysWithCollisions() { |
| OpenIntToFieldHashMap<Fraction> map = new OpenIntToFieldHashMap<Fraction>(field); |
| int key1 = -1996012590; |
| Fraction value1 = new Fraction(1); |
| map.put(key1, value1); |
| int key2 = 835099822; |
| map.put(key2, value1); |
| int key3 = 1008859686; |
| map.put(key3, value1); |
| Assert.assertEquals(value1, map.get(key3)); |
| Assert.assertEquals(3, map.size()); |
| |
| map.remove(key2); |
| Fraction value2 = new Fraction(2); |
| map.put(key3, value2); |
| Assert.assertEquals(value2, map.get(key3)); |
| Assert.assertEquals(2, map.size()); |
| } |
| |
| /** |
| * Similar to testPutKeysWithCollisions() but exercises the codepaths in a slightly |
| * different manner. |
| */ |
| @Test |
| public void testPutKeysWithCollision2() { |
| OpenIntToFieldHashMap<Fraction>map = new OpenIntToFieldHashMap<Fraction>(field); |
| int key1 = 837989881; |
| Fraction value1 = new Fraction(1); |
| map.put(key1, value1); |
| int key2 = 476463321; |
| map.put(key2, value1); |
| Assert.assertEquals(2, map.size()); |
| Assert.assertEquals(value1, map.get(key2)); |
| |
| map.remove(key1); |
| Fraction value2 = new Fraction(2); |
| map.put(key2, value2); |
| Assert.assertEquals(1, map.size()); |
| Assert.assertEquals(value2, map.get(key2)); |
| } |
| |
| |
| } |