Skip to content

Commit

Permalink
Add hash flooding protection to HashBiMap.
Browse files Browse the repository at this point in the history
RELNOTES=Add hash flooding protection to HashBiMap.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=185433235
  • Loading branch information
lowasser authored and cpovirk committed Feb 12, 2018
1 parent afe6ff8 commit c92686d
Show file tree
Hide file tree
Showing 6 changed files with 581 additions and 240 deletions.
171 changes: 71 additions & 100 deletions android/guava-tests/test/com/google/common/collect/HashBiMapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@

package com.google.common.collect;

import static com.google.common.collect.testing.Helpers.mapEntry;
import static com.google.common.truth.Truth.assertThat;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.HashBiMapTest.HashBiMapGenerator;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.collect.testing.features.MapFeature;
import com.google.common.collect.testing.google.BiMapTestSuiteBuilder;
import com.google.common.collect.testing.google.TestBiMapGenerator;
import com.google.common.collect.testing.google.TestStringBiMapGenerator;
import java.util.Iterator;
import java.util.Map;
Expand All @@ -41,10 +44,13 @@
@GwtCompatible(emulated = true)
public class HashBiMapTest extends TestCase {

public static final class HashBiMapGenerator extends TestStringBiMapGenerator {
private static final ImmutableList<HashBiMapGenerator> GENERATORS =
ImmutableList.of(new HashBiMapGenerator());

public static class HashBiMapGenerator extends TestStringBiMapGenerator {
@Override
protected BiMap<String, String> create(Entry<String, String>[] entries) {
BiMap<String, String> result = HashBiMap.create();
protected HashBiMap<String, String> create(Entry<String, String>[] entries) {
HashBiMap<String, String> result = HashBiMap.create();
for (Entry<String, String> entry : entries) {
result.put(entry.getKey(), entry.getValue());
}
Expand Down Expand Up @@ -119,127 +125,92 @@ public void testBashIt() throws Exception {
}

public void testBiMapEntrySetIteratorRemove() {
BiMap<Integer, String> map = HashBiMap.create();
map.put(1, "one");
Set<Entry<Integer, String>> entries = map.entrySet();
Iterator<Entry<Integer, String>> iterator = entries.iterator();
Entry<Integer, String> entry = iterator.next();
entry.setValue("two"); // changes the iterator's current entry value
assertEquals("two", map.get(1));
assertEquals(Integer.valueOf(1), map.inverse().get("two"));
iterator.remove(); // removes the updated entry
assertTrue(map.isEmpty());
for (TestBiMapGenerator<String, String> generator : GENERATORS) {
BiMap<String, String> map = generator.create(mapEntry("1", "one"));
Set<Entry<String, String>> entries = map.entrySet();
Iterator<Entry<String, String>> iterator = entries.iterator();
Entry<String, String> entry = iterator.next();
entry.setValue("two"); // changes the iterator's current entry value
assertEquals("two", map.get("1"));
assertEquals("1", map.inverse().get("two"));
iterator.remove(); // removes the updated entry
assertTrue(map.isEmpty());
}
}

public void testInsertionOrder() {
BiMap<String, Integer> map = HashBiMap.create();
map.put("foo", 1);
map.put("bar", 2);
map.put("quux", 3);
assertThat(map.entrySet())
.containsExactly(
Maps.immutableEntry("foo", 1),
Maps.immutableEntry("bar", 2),
Maps.immutableEntry("quux", 3))
.inOrder();
for (TestBiMapGenerator<String, String> generator : GENERATORS) {
BiMap<String, String> map =
generator.create(mapEntry("foo", "1"), mapEntry("bar", "2"), mapEntry("quux", "3"));
assertThat(map).containsExactly("foo", "1", "bar", "2", "quux", "3").inOrder();
}
}

public void testInsertionOrderAfterRemoveFirst() {
BiMap<String, Integer> map = HashBiMap.create();
map.put("foo", 1);
map.put("bar", 2);
map.put("quux", 3);

map.remove("foo");
assertThat(map.entrySet())
.containsExactly(Maps.immutableEntry("bar", 2), Maps.immutableEntry("quux", 3))
.inOrder();
for (TestBiMapGenerator<String, String> generator : GENERATORS) {
BiMap<String, String> map =
generator.create(mapEntry("foo", "1"), mapEntry("bar", "2"), mapEntry("quux", "3"));
map.remove("foo");
assertThat(map).containsExactly("bar", "2", "quux", "3").inOrder();
}
}

public void testInsertionOrderAfterRemoveMiddle() {
BiMap<String, Integer> map = HashBiMap.create();
map.put("foo", 1);
map.put("bar", 2);
map.put("quux", 3);

map.remove("bar");
assertThat(map.entrySet())
.containsExactly(Maps.immutableEntry("foo", 1), Maps.immutableEntry("quux", 3))
.inOrder();
for (TestBiMapGenerator<String, String> generator : GENERATORS) {
BiMap<String, String> map =
generator.create(mapEntry("foo", "1"), mapEntry("bar", "2"), mapEntry("quux", "3"));
map.remove("bar");
assertThat(map).containsExactly("foo", "1", "quux", "3").inOrder();
}
}

public void testInsertionOrderAfterRemoveLast() {
BiMap<String, Integer> map = HashBiMap.create();
map.put("foo", 1);
map.put("bar", 2);
map.put("quux", 3);

map.remove("quux");
assertThat(map.entrySet())
.containsExactly(Maps.immutableEntry("foo", 1), Maps.immutableEntry("bar", 2))
.inOrder();
for (TestBiMapGenerator<String, String> generator : GENERATORS) {
BiMap<String, String> map =
generator.create(mapEntry("foo", "1"), mapEntry("bar", "2"), mapEntry("quux", "3"));
map.remove("quux");
assertThat(map).containsExactly("foo", "1", "bar", "2").inOrder();
}
}

public void testInsertionOrderAfterForcePut() {
BiMap<String, Integer> map = HashBiMap.create();
map.put("foo", 1);
map.put("bar", 2);
map.put("quux", 3);

map.forcePut("quux", 1);
assertThat(map.entrySet())
.containsExactly(Maps.immutableEntry("bar", 2), Maps.immutableEntry("quux", 1))
.inOrder();
for (TestBiMapGenerator<String, String> generator : GENERATORS) {
BiMap<String, String> map =
generator.create(mapEntry("foo", "1"), mapEntry("bar", "2"), mapEntry("quux", "3"));
map.forcePut("quux", "1");
assertThat(map).containsExactly("bar", "2", "quux", "1").inOrder();
assertThat(map.inverse()).containsExactly("2", "bar", "1", "quux").inOrder();
}
}

public void testInsertionOrderAfterInverseForcePut() {
BiMap<String, Integer> map = HashBiMap.create();
map.put("foo", 1);
map.put("bar", 2);
map.put("quux", 3);

map.inverse().forcePut(1, "quux");
assertThat(map.entrySet())
.containsExactly(Maps.immutableEntry("bar", 2), Maps.immutableEntry("quux", 1))
.inOrder();
for (TestBiMapGenerator<String, String> generator : GENERATORS) {
BiMap<String, String> map =
generator.create(mapEntry("foo", "1"), mapEntry("bar", "2"), mapEntry("quux", "3"));
map.inverse().forcePut("1", "quux");
assertThat(map).containsExactly("bar", "2", "quux", "1").inOrder();
assertThat(map.inverse()).containsExactly("2", "bar", "1", "quux").inOrder();
}
}

public void testInverseInsertionOrderAfterInverse() {
BiMap<String, Integer> map = HashBiMap.create();
map.put("bar", 2);
map.put("quux", 1);

assertThat(map.inverse().entrySet())
.containsExactly(Maps.immutableEntry(2, "bar"), Maps.immutableEntry(1, "quux"))
.inOrder();
}

public void testInverseInsertionOrderAfterInverseForcePut() {
BiMap<String, Integer> map = HashBiMap.create();
map.put("foo", 1);
map.put("bar", 2);
map.put("quux", 3);

map.inverse().forcePut(1, "quux");
assertThat(map.inverse().entrySet())
.containsExactly(Maps.immutableEntry(2, "bar"), Maps.immutableEntry(1, "quux"))
.inOrder();
for (TestBiMapGenerator<String, String> generator : GENERATORS) {
BiMap<String, String> map = generator.create(mapEntry("bar", "2"), mapEntry("quux", "1"));
assertThat(map.inverse()).containsExactly("2", "bar", "1", "quux").inOrder();
}
}

public void testInverseInsertionOrderAfterInverseForcePutPresentKey() {
BiMap<String, Integer> map = HashBiMap.create();
map.put("foo", 1);
map.put("bar", 2);
map.put("quux", 3);
map.put("nab", 4);

map.inverse().forcePut(4, "bar");
assertThat(map.entrySet())
.containsExactly(
Maps.immutableEntry("foo", 1),
Maps.immutableEntry("bar", 4),
Maps.immutableEntry("quux", 3))
.inOrder();
for (TestBiMapGenerator<String, String> generator : GENERATORS) {
BiMap<String, String> map =
generator.create(
mapEntry("foo", "1"),
mapEntry("bar", "2"),
mapEntry("quux", "3"),
mapEntry("nab", "4"));
map.inverse().forcePut("4", "bar");
assertThat(map).containsExactly("foo", "1", "bar", "4", "quux", "3").inOrder();
}
}

public void testInverseEntrySetValueNewKey() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,13 @@ static class Inverse<K, V> extends AbstractBiMap<K, V> {
* instances have inverse() methods that return the other.
*/

@Override
public V forcePut(K key, V value) {
V result = get(key);
inverse().forcePut(value, key);
return result;
}

@Override
K checkKey(K key) {
return inverse.checkValue(key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ public void testInverseInsertionOrderAfterInverse() throws Exception {
testCase.testInverseInsertionOrderAfterInverse();
}

public void testInverseInsertionOrderAfterInverseForcePut() throws Exception {
com.google.common.collect.HashBiMapTest testCase = new com.google.common.collect.HashBiMapTest();
testCase.testInverseInsertionOrderAfterInverseForcePut();
}

public void testInverseInsertionOrderAfterInverseForcePutPresentKey() throws Exception {
com.google.common.collect.HashBiMapTest testCase = new com.google.common.collect.HashBiMapTest();
testCase.testInverseInsertionOrderAfterInverseForcePutPresentKey();
Expand Down
Loading

0 comments on commit c92686d

Please sign in to comment.