import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
+import org.junit.Before;
import org.junit.Test;
public class OffsetMapTest {
private final Map<String, String> threeEntryMap = ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3");
private ImmutableOffsetMap<String, String> createMap() {
- return (ImmutableOffsetMap<String, String>) ImmutableOffsetMap.copyOf(twoEntryMap);
+ return (ImmutableOffsetMap<String, String>) ImmutableOffsetMap.orderedCopyOf(twoEntryMap);
+ }
+
+ private ImmutableOffsetMap<String, String> unorderedMap() {
+ return (ImmutableOffsetMap<String, String>) ImmutableOffsetMap.unorderedCopyOf(twoEntryMap);
+ }
+
+ @Before
+ public void setup() {
+ OffsetMapCache.invalidateCache();
}
@Test(expected=IllegalArgumentException.class)
public void testWrongImmutableConstruction() {
- new ImmutableOffsetMap<String, String>(Collections.<String, Integer>emptyMap(), new Object[1]);
+ new ImmutableOffsetMap.Ordered<String, String>(Collections.<String, Integer>emptyMap(), new String[1]);
}
@Test
public void testCopyEmptyMap() {
final Map<String, String> source = Collections.emptyMap();
- final Map<String, String> result = ImmutableOffsetMap.copyOf(source);
+ final Map<String, String> result = ImmutableOffsetMap.orderedCopyOf(source);
assertEquals(source, result);
assertTrue(result instanceof ImmutableMap);
@Test
public void testCopySingletonMap() {
final Map<String, String> source = Collections.singletonMap("a", "b");
- final Map<String, String> result = ImmutableOffsetMap.copyOf(source);
+ final Map<String, String> result = ImmutableOffsetMap.orderedCopyOf(source);
assertEquals(source, result);
- assertTrue(result instanceof ImmutableMap);
+ assertTrue(result instanceof SharedSingletonMap);
}
@Test
assertEquals(twoEntryMap, map);
assertEquals(map, twoEntryMap);
+ // hashcode has to match
+ assertEquals(twoEntryMap.hashCode(), map.hashCode());
+
// Iterator order needs to be preserved
assertTrue(Iterators.elementsEqual(twoEntryMap.entrySet().iterator(), map.entrySet().iterator()));
// Should result in the same object
- assertSame(map, ImmutableOffsetMap.copyOf(map));
+ assertSame(map, ImmutableOffsetMap.orderedCopyOf(map));
final Map<String, String> mutable = map.toModifiableMap();
- final Map<String, String> copy = ImmutableOffsetMap.copyOf(mutable);
+ final Map<String, String> copy = ImmutableOffsetMap.orderedCopyOf(mutable);
assertEquals(mutable, copy);
assertEquals(map, copy);
assertFalse(map.equals("string"));
}
- @Test
- public void testImmutableCopyConstructor() {
- final ImmutableOffsetMap<String, String> source = createMap();
- final ImmutableOffsetMap<String, String> result = new ImmutableOffsetMap<>(source);
-
- assertSame(source.offsets(), result.offsets());
- assertSame(source.objects(), result.objects());
- }
-
@Test
public void testImmutableGet() {
final Map<String, String> map = createMap();
mutable.remove("k1");
mutable.put("k1", "v1");
+ final ImmutableOffsetMap<String, String> result = (ImmutableOffsetMap<String, String>) mutable.toUnmodifiableMap();
+ assertTrue(source.equals(result));
+ assertTrue(result.equals(source));
+
+ // Iterator order must not be preserved
+ assertFalse(Iterators.elementsEqual(source.entrySet().iterator(), result.entrySet().iterator()));
+ }
+
+ @Test
+ public void testReusedOffsetsUnordered() {
+ final ImmutableOffsetMap<String, String> source = unorderedMap();
+ final MutableOffsetMap<String, String> mutable = source.toModifiableMap();
+
+ mutable.remove("k1");
+ mutable.put("k1", "v1");
+
final ImmutableOffsetMap<String, String> result = (ImmutableOffsetMap<String, String>) mutable.toUnmodifiableMap();
assertEquals(source, result);
@Test
public void testEmptyMutable() throws CloneNotSupportedException {
- final MutableOffsetMap<String, String> map = new MutableOffsetMap<>();
+ final MutableOffsetMap<String, String> map = MutableOffsetMap.ordered();
assertTrue(map.isEmpty());
final Map<String, String> other = map.clone();
assertNotSame(other, map);
}
- @Test
- public void testMutableWithKeyset() {
- final MutableOffsetMap<String, String> map = new MutableOffsetMap<>(ImmutableSet.of("k1", "k2"));
- assertTrue(map.isEmpty());
- assertTrue(map.keySet().isEmpty());
- assertNull(map.get("k1"));
- assertNull(map.remove("k2"));
- }
-
@Test
public void testMutableToEmpty() {
final MutableOffsetMap<String, String> mutable = createMap().toModifiableMap();
final Map<String, String> result = mutable.toUnmodifiableMap();
// Should devolve to a singleton
- assertTrue(result instanceof ImmutableMap);
+ assertTrue(result instanceof SharedSingletonMap);
assertEquals(ImmutableMap.of("k2", "v2"), result);
}
mutable.put("k3", "v3");
mutable.put("k1", "v1");
+ assertEquals(ImmutableMap.of("k1", "v1", "k3", "v3"), mutable.newKeys());
+
+ final Map<String, String> result = mutable.toUnmodifiableMap();
+
+ assertTrue(result instanceof ImmutableOffsetMap);
+ assertEquals(threeEntryMap, result);
+ assertEquals(result, threeEntryMap);
+ assertFalse(Iterators.elementsEqual(threeEntryMap.entrySet().iterator(), result.entrySet().iterator()));
+ }
+
+ @Test
+ public void testExpansionWithoutOrder() {
+ final MutableOffsetMap<String, String> mutable = unorderedMap().toModifiableMap();
+
+ mutable.remove("k1");
+ mutable.put("k3", "v3");
+ mutable.put("k1", "v1");
+
assertEquals(ImmutableMap.of("k3", "v3"), mutable.newKeys());
final Map<String, String> result = mutable.toUnmodifiableMap();
assertFalse(source.needClone());
assertTrue(result.needClone());
+ // Forced copy, no cloning needed, but maps are equal
+ final ImmutableOffsetMap<String, String> immutable = (ImmutableOffsetMap<String, String>) source.toUnmodifiableMap();
+ assertFalse(source.needClone());
+ assertTrue(source.equals(immutable));
+ assertTrue(immutable.equals(source));
+ assertTrue(Iterables.elementsEqual(source.entrySet(), immutable.entrySet()));
+ }
+
+ @Test
+ public void testCloneableFlippingUnordered() throws CloneNotSupportedException {
+ final MutableOffsetMap<String, String> source = unorderedMap().toModifiableMap();
+
+ // Must clone before mutation
+ assertTrue(source.needClone());
+
+ // Non-existent entry, should not clone
+ source.remove("non-existent");
+ assertTrue(source.needClone());
+
+ // Changes the array, should clone
+ source.remove("k1");
+ assertFalse(source.needClone());
+
+ // Create a clone of the map, which shares the array
+ final MutableOffsetMap<String, String> result = source.clone();
+ assertFalse(source.needClone());
+ assertTrue(result.needClone());
+ assertSame(source.array(), result.array());
+
+ // Changes the array, should clone
+ source.put("k1", "v2");
+ assertFalse(source.needClone());
+ assertTrue(result.needClone());
+
// Creates a immutable view, which shares the array
final ImmutableOffsetMap<String, String> immutable = (ImmutableOffsetMap<String, String>) source.toUnmodifiableMap();
assertTrue(source.needClone());
assertTrue(map.equals(source));
}
+ @Test
+ public void testMutableSimpleHashCode() {
+ final Map<String, String> map = createMap().toModifiableMap();
+
+ assertEquals(twoEntryMap.hashCode(), map.hashCode());
+ }
+
@Test
public void testMutableIteratorBasics() {
final MutableOffsetMap<String, String> map = createMap().toModifiableMap();