Rework test fixtures

Next, grow the amount of data tested to find bugs in the tests with
non-repeatable map ordering
This commit is contained in:
Gary Gregory 2024-03-31 08:46:47 -04:00
parent 5e8368dbd5
commit c47f52c1ec
2 changed files with 152 additions and 109 deletions

View File

@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@ -511,6 +512,10 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
return this.map; return this.map;
} }
public int getSampleCountPerKey() {
return 2;
}
/** /**
* Returns the set of keys in the mappings used to test the map. This method * Returns the set of keys in the mappings used to test the map. This method
* must return an array with the same length as {@link #getSampleValues()} * must return an array with the same length as {@link #getSampleValues()}
@ -520,22 +525,24 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public K[] getSampleKeys() { public K[] getSampleKeys() {
final Object[] result = new Object[getSampleSize()]; final Object[] result = new Object[getSampleTotalValueCount()];
final int cpk = getSampleCountPerKey();
int k = 0; int k = 0;
for (int i = 0; i < result.length; i += 2, k++) { for (int i = 0; i < result.length; i += cpk, k++) {
final String key = "k" + Integer.valueOf(k); final K key = makeKey(k);
result[i] = key; for (int j = 0; j < cpk; j++) {
result[i + 1] = key; result[i + j] = key;
}
} }
return (K[]) result; return (K[]) result;
} }
public int getSampleSize() { public int getSampleKeySize() {
return 6; return 3;
} }
public int getSampleValuesPerKey() { public int getSampleTotalValueCount() {
return 2; return getSampleCountPerKey() * getSampleKeySize();
} }
/** /**
@ -546,12 +553,13 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public V[] getSampleValues() { public V[] getSampleValues() {
final Object[] result = new Object[getSampleSize()]; final Object[] result = new Object[getSampleTotalValueCount()];
final int cpk = getSampleCountPerKey();
int k = 0; int k = 0;
for (int i = 0; i < result.length; i += 2, k++) { for (int i = 0; i < result.length; i += cpk, k++) {
final String key = "v" + Integer.valueOf(k); for (int j = 0; j < cpk; j++) {
result[i] = key + "_a"; result[i + j] = makeValue(k, j);
result[i + 1] = key + "_b"; }
} }
return (V[]) result; return (V[]) result;
} }
@ -627,9 +635,17 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
return map; return map;
} }
<E> E makeKey(final int key) {
return (E) new StringBuilder("k").append(key).toString();
}
@Override @Override
public abstract MultiValuedMap<K, V> makeObject(); public abstract MultiValuedMap<K, V> makeObject();
String makeValue(final int key, final int value) {
return new StringBuilder("v").append(key).append('_').append(value).toString();
}
/** /**
* Resets the {@link #map} and {@link #confirmed} fields to empty. * Resets the {@link #map} and {@link #confirmed} fields to empty.
*/ */
@ -654,7 +670,7 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
// public void testKeyedIterator() { // public void testKeyedIterator() {
// final MultiValuedMap<K, V> map = makeFullMap(); // final MultiValuedMap<K, V> map = makeFullMap();
// final ArrayList<Object> actual = new ArrayList<Object>(IteratorUtils.toList(map.iterator("k0"))); // final ArrayList<Object> actual = new ArrayList<Object>(IteratorUtils.toList(map.iterator("k0")));
// final ArrayList<Object> expected = new ArrayList<Object>(Arrays.asList("v1_b", "v0_b")); // final ArrayList<Object> expected = new ArrayList<Object>(Arrays.asList("v1_1", "v0_1"));
// assertEquals(expected, actual); // assertEquals(expected, actual);
// } // }
@ -675,15 +691,15 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
assertTrue(col1.isEmpty()); assertTrue(col1.isEmpty());
assertTrue(col2.isEmpty()); assertTrue(col2.isEmpty());
assertEquals(0, map.size()); assertEquals(0, map.size());
col1.add((V) "v1_b"); col1.add((V) "v1_1");
col2.add((V) "v0_b"); col2.add((V) "v0_1");
assertTrue(map.containsKey("k0")); assertTrue(map.containsKey("k0"));
assertTrue(map.containsMapping("k0", "v1_b")); assertTrue(map.containsMapping("k0", "v1_1"));
assertTrue(map.containsMapping("k0", "v0_b")); assertTrue(map.containsMapping("k0", "v0_1"));
assertTrue(map.containsValue("v1_b")); assertTrue(map.containsValue("v1_1"));
assertTrue(map.containsValue("v0_b")); assertTrue(map.containsValue("v0_1"));
assertTrue(col1.contains("v0_b")); assertTrue(col1.contains("v0_1"));
assertTrue(col2.contains("v1_b")); assertTrue(col2.contains("v1_1"));
} }
/*public void testRemoveViaGetCollectionRemove() { /*public void testRemoveViaGetCollectionRemove() {
@ -692,8 +708,8 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
} }
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
Collection<V> values = map.get("k0"); Collection<V> values = map.get("k0");
values.remove("v1_b"); values.remove("v1_1");
values.remove("v0_b"); values.remove("v0_1");
assertFalse(map.containsKey("k0")); assertFalse(map.containsKey("k0"));
assertEquals(4, map.size()); assertEquals(4, map.size());
}*/ }*/
@ -712,18 +728,25 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
// } // }
@Test @Test
public void testAsMapGet() { public void testAsMapGet_Empty() {
resetEmpty(); resetEmpty();
Map<K, Collection<V>> mapCol = getMap().asMap(); final Map<K, Collection<V>> mapCol = getMap().asMap();
assertNull(mapCol.get("k0")); assertNull(mapCol.get("k0"));
assertEquals(0, mapCol.size()); assertEquals(0, mapCol.size());
}
@Test
public void testAsMapGet_Full() {
resetFull(); resetFull();
mapCol = getMap().asMap(); final Map<K, Collection<V>> mapCol = getMap().asMap();
final Collection<V> col = mapCol.get("k0"); final int maxK = getSampleKeySize();
assertNotNull(col); final int maxV = getSampleCountPerKey();
assertTrue(col.contains("v0_a")); for (int k = 0; k < maxK; k++) {
assertTrue(col.contains("v0_b")); final Collection<V> col = mapCol.get(makeKey(k));
for (int v = 0; v < maxV; v++) {
assertTrue(col.contains(makeValue(k, v)));
}
}
} }
@Test @Test
@ -741,12 +764,13 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
@Test @Test
public void testContainsValue() { public void testContainsValue() {
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
assertTrue(map.containsValue("v1_b")); final int maxK = getSampleKeySize();
assertTrue(map.containsValue("v0_b")); final int maxV = getSampleCountPerKey();
assertTrue(map.containsValue("v1_a")); for (int k = 0; k < maxK; k++) {
assertTrue(map.containsValue("v1_b")); for (int v = 0; v < maxV; v++) {
assertTrue(map.containsValue("v2_a")); assertTrue(map.containsValue(makeValue(k, v)));
assertTrue(map.containsValue("v2_b")); }
}
assertFalse(map.containsValue("quatro")); assertFalse(map.containsValue("quatro"));
} }
@ -754,7 +778,7 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testContainsValue_Key() { public void testContainsValue_Key() {
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
assertTrue(map.containsMapping("k0", "v0_b")); assertTrue(map.containsMapping("k0", "v0_1"));
assertFalse(map.containsMapping("k1", "2")); assertFalse(map.containsMapping("k1", "2"));
if (!isAddSupported()) { if (!isAddSupported()) {
return; return;
@ -820,8 +844,8 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
// while (it.hasNext()) { // while (it.hasNext()) {
// values.add(it.next()); // values.add(it.next());
// } // }
// assertTrue( values.contains("v0_b")); // assertTrue( values.contains("v0_1"));
// assertTrue( values.contains("v1_b")); // assertTrue( values.contains("v1_1"));
// assertFalse(map.iterator("A").hasNext()); // assertFalse(map.iterator("A").hasNext());
// assertFalse(map.iterator("A").hasNext()); // assertFalse(map.iterator("A").hasNext());
// if (!isAddSupported()) { // if (!isAddSupported()) {
@ -838,48 +862,59 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testGet() { public void testGet() {
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
assertTrue(map.get((K) "k0").contains("v0_a")); final int maxK = getSampleKeySize();
assertTrue(map.get((K) "k0").contains("v0_b")); final int maxV = getSampleCountPerKey();
assertTrue(map.get((K) "k1").contains("v1_a")); for (int k = 0; k < maxK; k++) {
assertTrue(map.get((K) "k1").contains("v1_b")); for (int v = 0; v < maxV; v++) {
assertTrue(map.get((K) "k2").contains("v2_a")); assertTrue(map.get((K) makeKey(k)).contains(makeValue(k, v)));
assertTrue(map.get((K) "k2").contains("v2_b")); }
}
} }
@Test @Test
public void testKeyContainsValue() { public void testKeyContainsValue() {
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
assertTrue(map.containsMapping("k0", "v0_a")); final int maxK = getSampleKeySize();
assertTrue(map.containsMapping("k0", "v0_b")); final int maxV = getSampleCountPerKey();
assertTrue(map.containsMapping("k1", "v1_a")); for (int k = 0; k < maxK; k++) {
assertTrue(map.containsMapping("k1", "v1_b")); for (int v = 0; v < maxV; v++) {
assertTrue(map.containsMapping("k2", "v2_a")); assertTrue(map.containsMapping(makeKey(k), makeValue(k, v)));
assertTrue(map.containsMapping("k2", "v2_b")); }
}
assertFalse(map.containsMapping("k", "v")); assertFalse(map.containsMapping("k", "v"));
} }
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "cast" })
public void testKeysBagContainsAll() { public void testKeysBagContainsAll() {
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
final MultiSet<K> keyMultiSet = map.keys(); final MultiSet<K> keyMultiSet = map.keys();
final Collection<K> col = (Collection<K>) Arrays.asList("k0", "k1", "k2", "k0", "k1", "k2");
assertTrue(keyMultiSet.containsAll(col)); final List<String> col = new ArrayList<>();
final int maxK = getSampleKeySize();
for (int k = 0; k < maxK; k++) {
col.add(makeKey(k));
}
for (int k = 0; k < maxK; k++) {
col.add(makeKey(k));
}
// Make sure we test Collection API
assertTrue(keyMultiSet.containsAll((Collection<K>) col));
} }
@Test @Test
public void testKeysBagIterator() { public void testKeysBagIterator() {
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
final Collection<K> col = new ArrayList<>(); final Collection<K> col = new ArrayList<>();
final Iterator<K> it = map.keys().iterator(); for (K element : map.keys()) {
while (it.hasNext()) { col.add(element);
col.add(it.next());
} }
final Bag<K> bag = new HashBag<>(col); final Bag<K> bag = new HashBag<>(col);
assertEquals(2, bag.getCount("k0")); final int maxK = getSampleKeySize();
assertEquals(2, bag.getCount("k1")); for (int k = 0; k < maxK; k++) {
assertEquals(2, bag.getCount("k2")); assertEquals(getSampleCountPerKey(), bag.getCount(makeKey(k)));
assertEquals(getSampleSize(), bag.size()); }
assertEquals(getSampleTotalValueCount(), bag.size());
} }
@Test @Test
@ -892,11 +927,12 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
public void testKeysMultiSet() { public void testKeysMultiSet() {
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
final MultiSet<K> keyMultiSet = map.keys(); final MultiSet<K> keyMultiSet = map.keys();
assertEquals(2, keyMultiSet.getCount("k0")); final int maxK = getSampleKeySize();
assertEquals(2, keyMultiSet.getCount("k1")); for (int k = 0; k < maxK; k++) {
assertEquals(2, keyMultiSet.getCount("k2")); assertEquals(getSampleCountPerKey(), keyMultiSet.getCount(makeKey(k)));
}
assertEquals(0, keyMultiSet.getCount("conut")); assertEquals(0, keyMultiSet.getCount("conut"));
assertEquals(getSampleSize(), keyMultiSet.size()); assertEquals(getSampleTotalValueCount(), keyMultiSet.size());
} }
@Test @Test
@ -955,10 +991,15 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
@Test @Test
public void testMultipleValues() { public void testMultipleValues() {
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
@SuppressWarnings("unchecked") final int maxK = getSampleKeySize();
final Collection<V> col = map.get((K) "k0"); final int maxV = getSampleCountPerKey();
assertTrue(col.contains("v0_a")); for (int k = 0; k < maxK; k++) {
assertTrue(col.contains("v0_b")); final Collection<V> col = map.get(makeKey(k));
for (int v = 0; v < maxV; v++) {
assertTrue(col.contains(makeValue(k, v)));
}
}
} }
@Test @Test
@ -976,22 +1017,22 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
assertTrue(it.hasNext() ); assertTrue(it.hasNext() );
assertEquals("k0", it.next()); assertEquals("k0", it.next());
assertEquals("k0", it.getKey()); assertEquals("k0", it.getKey());
assertEquals("v0_a", it.getValue()); assertEquals("v0_0", it.getValue());
assertEquals("k0", it.next()); assertEquals("k0", it.next());
assertEquals("k0", it.getKey()); assertEquals("k0", it.getKey());
assertEquals("v0_b", it.getValue()); assertEquals("v0_1", it.getValue());
assertEquals("k1", it.next()); assertEquals("k1", it.next());
assertEquals("k1", it.getKey()); assertEquals("k1", it.getKey());
assertEquals("v1_a", it.getValue()); assertEquals("v1_0", it.getValue());
assertEquals("k1", it.next()); assertEquals("k1", it.next());
assertEquals("k1", it.getKey()); assertEquals("k1", it.getKey());
assertEquals("v1_b", it.getValue()); assertEquals("v1_1", it.getValue());
assertEquals("k2", it.next()); assertEquals("k2", it.next());
assertEquals("k2", it.getKey()); assertEquals("k2", it.getKey());
assertEquals("v2_a", it.getValue()); assertEquals("v2_0", it.getValue());
assertEquals("k2", it.next()); assertEquals("k2", it.next());
assertEquals("k2", it.getKey()); assertEquals("k2", it.getKey());
assertEquals("v2_b", it.getValue()); assertEquals("v2_1", it.getValue());
assertThrows(UnsupportedOperationException.class, () -> it.setValue((V) "threetrois")); assertThrows(UnsupportedOperationException.class, () -> it.setValue((V) "threetrois"));
} }
} }
@ -1157,15 +1198,15 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
final MultiValuedMap<K, V> map = getMap(); final MultiValuedMap<K, V> map = getMap();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Collection<V> col = map.get((K) "k0"); Collection<V> col = map.get((K) "k0");
assertEquals(2, col.size()); assertEquals(getSampleCountPerKey(), col.size());
assertEquals(getSampleSize(), map.size()); assertEquals(getSampleTotalValueCount(), map.size());
assertTrue(col.remove("v0_a")); assertTrue(col.remove("v0_0"));
assertTrue(col.remove("v0_b")); assertTrue(col.remove("v0_1"));
assertFalse(map.containsKey("k0")); assertFalse(map.containsKey("k0"));
assertFalse(map.containsMapping("k0", "v0_a")); assertFalse(map.containsMapping("k0", "v0_0"));
assertFalse(map.containsMapping("k0", "v0_b")); assertFalse(map.containsMapping("k0", "v0_1"));
assertFalse(map.containsValue("v0_a")); assertFalse(map.containsValue("v0_0"));
assertFalse(map.containsValue("v0_b")); assertFalse(map.containsValue("v0_1"));
assertEquals(4, map.size()); assertEquals(4, map.size());
col = map.remove("k0"); col = map.remove("k0");
assertNotNull(col); assertNotNull(col);
@ -1186,10 +1227,10 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
it.remove(); it.remove();
} }
assertFalse(map.containsKey("k0")); assertFalse(map.containsKey("k0"));
assertFalse(map.containsMapping("k0", "v1_b")); assertFalse(map.containsMapping("k0", "v1_1"));
assertFalse(map.containsMapping("k0", "v0_b")); assertFalse(map.containsMapping("k0", "v0_1"));
assertFalse(map.containsValue("v0_a")); assertFalse(map.containsValue("v0_0"));
assertFalse(map.containsValue("v0_b")); assertFalse(map.containsValue("v0_1"));
assertEquals(4, map.size()); assertEquals(4, map.size());
final Collection<V> coll = map.remove("k0"); final Collection<V> coll = map.remove("k0");
assertNotNull(coll); assertNotNull(coll);
@ -1203,24 +1244,25 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
} }
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
final Collection<V> values = map.values(); final Collection<V> values = map.values();
values.remove("v0_a"); values.remove("v0_0");
values.remove("v0_b"); values.remove("v0_1");
assertFalse(map.containsKey("k0")); assertFalse(map.containsKey("k0"));
assertEquals(4, map.size()); assertEquals(4, map.size());
} }
@Test @Test
public void testSize() { public void testSize() {
assertEquals(getSampleSize(), makeFullMap().size()); assertEquals(getSampleTotalValueCount(), makeFullMap().size());
} }
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testSize_Key() { public void testSize_Key() {
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
assertEquals(2, map.get((K) "k0").size()); final int maxK = getSampleKeySize();
assertEquals(2, map.get((K) "k1").size()); for (int k = 0; k < maxK; k++) {
assertEquals(2, map.get((K) "k2").size()); assertEquals(getSampleCountPerKey(), map.get((K) makeKey(k)).size());
}
if (!isAddSupported()) { if (!isAddSupported()) {
return; return;
} }
@ -1304,14 +1346,15 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
public void testValues() { public void testValues() {
final MultiValuedMap<K, V> map = makeFullMap(); final MultiValuedMap<K, V> map = makeFullMap();
final HashSet<V> expected = new HashSet<>(); final HashSet<V> expected = new HashSet<>();
expected.add((V) "v0_a"); final int maxK = getSampleKeySize();
expected.add((V) "v0_b"); final int maxV = getSampleCountPerKey();
expected.add((V) "v1_a"); for (int k = 0; k < maxK; k++) {
expected.add((V) "v1_b"); for (int v = 0; v < maxV; v++) {
expected.add((V) "v2_a"); expected.add((V) makeValue(k, v));
expected.add((V) "v2_b"); }
}
final Collection<V> c = map.values(); final Collection<V> c = map.values();
assertEquals(getSampleSize(), c.size()); assertEquals(getSampleTotalValueCount(), c.size());
assertEquals(expected, new HashSet<>(c)); assertEquals(expected, new HashSet<>(c));
} }

View File

@ -52,9 +52,9 @@ public class UnmodifiableMultiValuedMapTest<K, V> extends AbstractMultiValuedMap
* @param map the MultiValuedMap<K, V> to check * @param map the MultiValuedMap<K, V> to check
*/ */
private void assertMapContainsAllValues(final MultiValuedMap<K, V> map) { private void assertMapContainsAllValues(final MultiValuedMap<K, V> map) {
assertEquals("[v0_a, v0_b]", map.get((K) "k0").toString()); assertEquals("[v0_0, v0_1]", map.get((K) "k0").toString());
assertEquals("[v1_a, v1_b]", map.get((K) "k1").toString()); assertEquals("[v1_0, v1_1]", map.get((K) "k1").toString());
assertEquals("[v2_a, v2_b]", map.get((K) "k2").toString()); assertEquals("[v2_0, v2_1]", map.get((K) "k2").toString());
} }
@Override @Override