/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed 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 com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.testing.testers.CollectionIteratorTester.getIteratorKnownOrderRemoveSupportedMethod;
import static com.google.common.collect.testing.testers.CollectionIteratorTester.getIteratorUnknownOrderRemoveSupportedMethod;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.Table.Cell;
import com.google.common.collect.testing.CollectionTestSuiteBuilder;
import com.google.common.collect.testing.MapInterfaceTest;
import com.google.common.collect.testing.SampleElements;
import com.google.common.collect.testing.SetTestSuiteBuilder;
import com.google.common.collect.testing.TestSetGenerator;
import com.google.common.collect.testing.TestStringCollectionGenerator;
import com.google.common.collect.testing.TestStringSetGenerator;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.collect.testing.features.Feature;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
/**
* Collection tests for {@link Table} implementations.
*
* @author Jared Levy
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
public class TableCollectionTest extends TestCase {
private static final Feature<?>[] COLLECTION_FEATURES = {
CollectionSize.ANY,
CollectionFeature.ALLOWS_NULL_QUERIES
};
private static final Feature<?>[] COLLECTION_FEATURES_ORDER = {
CollectionSize.ANY,
CollectionFeature.KNOWN_ORDER,
CollectionFeature.ALLOWS_NULL_QUERIES
};
private static final Feature<?>[] COLLECTION_FEATURES_REMOVE = {
CollectionSize.ANY,
CollectionFeature.REMOVE_OPERATIONS,
CollectionFeature.ALLOWS_NULL_QUERIES
};
private static final Feature<?>[] COLLECTION_FEATURES_REMOVE_ORDER = {
CollectionSize.ANY,
CollectionFeature.KNOWN_ORDER,
CollectionFeature.REMOVE_OPERATIONS,
CollectionFeature.ALLOWS_NULL_QUERIES
};
@GwtIncompatible("suite")
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(ArrayRowTests.class);
suite.addTestSuite(HashRowTests.class);
suite.addTestSuite(TreeRowTests.class);
suite.addTestSuite(TransposeRowTests.class);
suite.addTestSuite(TransformValueRowTests.class);
suite.addTestSuite(UnmodifiableHashRowTests.class);
suite.addTestSuite(UnmodifiableTreeRowTests.class);
suite.addTestSuite(ArrayColumnTests.class);
suite.addTestSuite(HashColumnTests.class);
suite.addTestSuite(TreeColumnTests.class);
suite.addTestSuite(TransposeColumnTests.class);
suite.addTestSuite(TransformValueColumnTests.class);
suite.addTestSuite(UnmodifiableHashColumnTests.class);
suite.addTestSuite(UnmodifiableTreeColumnTests.class);
suite.addTestSuite(ArrayRowMapTests.class);
suite.addTestSuite(HashRowMapTests.class);
suite.addTestSuite(TreeRowMapTests.class);
suite.addTestSuite(TreeRowMapHeadMapTests.class);
suite.addTestSuite(TreeRowMapTailMapTests.class);
suite.addTestSuite(TreeRowMapSubMapTests.class);
suite.addTestSuite(TransformValueRowMapTests.class);
suite.addTestSuite(UnmodifiableHashRowMapTests.class);
suite.addTestSuite(UnmodifiableTreeRowMapTests.class);
suite.addTestSuite(ArrayColumnMapTests.class);
suite.addTestSuite(HashColumnMapTests.class);
suite.addTestSuite(TreeColumnMapTests.class);
suite.addTestSuite(TransformValueColumnMapTests.class);
suite.addTestSuite(UnmodifiableHashColumnMapTests.class);
suite.addTestSuite(UnmodifiableTreeColumnMapTests.class);
// Not testing rowKeySet() or columnKeySet() of Table.transformValues()
// since the transformation doesn't affect the row and column key sets.
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<String, Integer, Character> table
= ArrayTable.create(
ImmutableList.copyOf(elements), ImmutableList.of(1, 2));
populateForRowKeySet(table, elements);
return table.rowKeySet();
}
})
.named("ArrayTable.rowKeySet")
.withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL,
CollectionFeature.KNOWN_ORDER,
CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
CollectionFeature.ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<String, Integer, Character> table = HashBasedTable.create();
populateForRowKeySet(table, elements);
return table.rowKeySet();
}
})
.named("HashBasedTable.rowKeySet")
.withFeatures(COLLECTION_FEATURES_REMOVE)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<String, Integer, Character> table = TreeBasedTable.create();
populateForRowKeySet(table, elements);
return table.rowKeySet();
}
@Override public List<String> order(List<String> insertionOrder) {
Collections.sort(insertionOrder);
return insertionOrder;
}
})
.named("TreeBasedTable.rowKeySet")
.withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
TreeBasedTable<String, Integer, Character> table
= TreeBasedTable.create();
populateForRowKeySet(table, elements);
table.put("z", 1, 'a');
return table.rowKeySet().headSet("x");
}
@Override public List<String> order(List<String> insertionOrder) {
Collections.sort(insertionOrder);
return insertionOrder;
}
})
.named("TreeBasedTable.rowKeySet.headSet")
.withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
TreeBasedTable<String, Integer, Character> table
= TreeBasedTable.create();
populateForRowKeySet(table, elements);
table.put("\0", 1, 'a');
return table.rowKeySet().tailSet("a");
}
@Override public List<String> order(List<String> insertionOrder) {
Collections.sort(insertionOrder);
return insertionOrder;
}
})
.named("TreeBasedTable.rowKeySet.tailSet")
.withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
TreeBasedTable<String, Integer, Character> table
= TreeBasedTable.create();
populateForRowKeySet(table, elements);
table.put("\0", 1, 'a');
table.put("z", 1, 'a');
return table.rowKeySet().subSet("a", "x");
}
@Override public List<String> order(List<String> insertionOrder) {
Collections.sort(insertionOrder);
return insertionOrder;
}
})
.named("TreeBasedTable.rowKeySet.subSet")
.withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<String, Integer, Character> table = HashBasedTable.create();
populateForRowKeySet(table, elements);
return Tables.unmodifiableTable(table).rowKeySet();
}
})
.named("unmodifiableTable[HashBasedTable].rowKeySet")
.withFeatures(COLLECTION_FEATURES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
RowSortedTable<String, Integer, Character> table = TreeBasedTable.create();
populateForRowKeySet(table, elements);
return Tables.unmodifiableRowSortedTable(table).rowKeySet();
}
@Override public List<String> order(List<String> insertionOrder) {
Collections.sort(insertionOrder);
return insertionOrder;
}
})
.named("unmodifiableRowSortedTable[TreeBasedTable].rowKeySet")
.withFeatures(COLLECTION_FEATURES_ORDER)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<Integer, String, Character> table
= ArrayTable.create(
ImmutableList.of(1, 2), ImmutableList.copyOf(elements));
populateForColumnKeySet(table, elements);
return table.columnKeySet();
}
})
.named("ArrayTable.columnKeySet")
.withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL,
CollectionFeature.KNOWN_ORDER,
CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
CollectionFeature.ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<Integer, String, Character> table = HashBasedTable.create();
populateForColumnKeySet(table, elements);
return table.columnKeySet();
}
})
.named("HashBasedTable.columnKeySet")
.withFeatures(COLLECTION_FEATURES_REMOVE)
.suppressing(getIteratorUnknownOrderRemoveSupportedMethod())
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<Integer, String, Character> table = TreeBasedTable.create();
populateForColumnKeySet(table, elements);
return table.columnKeySet();
}
@Override public List<String> order(List<String> insertionOrder) {
Collections.sort(insertionOrder);
return insertionOrder;
}
})
.named("TreeBasedTable.columnKeySet")
.withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
.suppressing(getIteratorKnownOrderRemoveSupportedMethod())
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<Integer, String, Character> table = HashBasedTable.create();
populateForColumnKeySet(table, elements);
return Tables.unmodifiableTable(table).columnKeySet();
}
})
.named("unmodifiableTable[HashBasedTable].columnKeySet")
.withFeatures(COLLECTION_FEATURES)
.suppressing(getIteratorUnknownOrderRemoveSupportedMethod())
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
RowSortedTable<Integer, String, Character> table = TreeBasedTable.create();
populateForColumnKeySet(table, elements);
return Tables.unmodifiableRowSortedTable(table).columnKeySet();
}
@Override public List<String> order(List<String> insertionOrder) {
Collections.sort(insertionOrder);
return insertionOrder;
}
})
.named("unmodifiableRowSortedTable[TreeBasedTable].columnKeySet")
.withFeatures(COLLECTION_FEATURES_ORDER)
.suppressing(getIteratorKnownOrderRemoveSupportedMethod())
.createTestSuite());
suite.addTest(CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override protected Collection<String> create(String[] elements) {
List<Integer> rowKeys = Lists.newArrayList();
for (int i = 0; i < elements.length; i++) {
rowKeys.add(i);
}
Table<Integer, Character, String> table
= ArrayTable.create(rowKeys, ImmutableList.of('a'));
populateForValues(table, elements);
return table.values();
}
})
.named("ArrayTable.values")
.withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL,
CollectionFeature.ALLOWS_NULL_VALUES,
CollectionFeature.KNOWN_ORDER)
.createTestSuite());
suite.addTest(CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override protected Collection<String> create(String[] elements) {
Table<Integer, Character, String> table = HashBasedTable.create();
table.put(1, 'a', "foo");
table.clear();
populateForValues(table, elements);
return table.values();
}
})
.named("HashBasedTable.values")
.withFeatures(COLLECTION_FEATURES_REMOVE)
.createTestSuite());
suite.addTest(CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override protected Collection<String> create(String[] elements) {
Table<Integer, Character, String> table = TreeBasedTable.create();
table.put(1, 'a', "foo");
table.clear();
populateForValues(table, elements);
return table.values();
}
})
.named("TreeBasedTable.values")
.withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
.createTestSuite());
final Function<String, String> removeFirstCharacter
= new Function<String, String>() {
@Override public String apply(String input) {
return input.substring(1);
}
};
suite.addTest(CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override protected Collection<String> create(String[] elements) {
Table<Integer, Character, String> table = HashBasedTable.create();
for (int i = 0; i < elements.length; i++) {
table.put(i, 'a', "x" + checkNotNull(elements[i]));
}
return Tables.transformValues(table, removeFirstCharacter).values();
}
})
.named("TransformValues.values")
.withFeatures(COLLECTION_FEATURES_REMOVE)
.createTestSuite());
suite.addTest(CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override protected Collection<String> create(String[] elements) {
Table<Integer, Character, String> table = HashBasedTable.create();
table.put(1, 'a', "foo");
table.clear();
populateForValues(table, elements);
return Tables.unmodifiableTable(table).values();
}
})
.named("unmodifiableTable[HashBasedTable].values")
.withFeatures(COLLECTION_FEATURES)
.createTestSuite());
suite.addTest(CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override protected Collection<String> create(String[] elements) {
RowSortedTable<Integer, Character, String> table = TreeBasedTable.create();
table.put(1, 'a', "foo");
table.clear();
populateForValues(table, elements);
return Tables.unmodifiableRowSortedTable(table).values();
}
})
.named("unmodifiableTable[TreeBasedTable].values")
.withFeatures(COLLECTION_FEATURES_ORDER)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
@Override public SampleElements<Cell<String, Integer, Character>>
samples() {
return new SampleElements<Cell<String, Integer, Character>>(
Tables.immutableCell("bar", 1, 'a'),
Tables.immutableCell("bar", 2, 'b'),
Tables.immutableCell("bar", 3, (Character) null),
Tables.immutableCell("bar", 4, 'b'),
Tables.immutableCell("bar", 5, 'b'));
}
@Override public Set<Cell<String, Integer, Character>> create(
Object... elements) {
List<Integer> columnKeys = Lists.newArrayList();
for (Object element : elements) {
@SuppressWarnings("unchecked")
Cell<String, Integer, Character> cell
= (Cell<String, Integer, Character>) element;
columnKeys.add(cell.getColumnKey());
}
Table<String, Integer, Character> table
= ArrayTable.create(ImmutableList.of("bar"), columnKeys);
for (Object element : elements) {
@SuppressWarnings("unchecked")
Cell<String, Integer, Character> cell
= (Cell<String, Integer, Character>) element;
table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
}
return table.cellSet();
}
@Override Table<String, Integer, Character> createTable() {
throw new UnsupportedOperationException();
}
})
.named("ArrayTable.cellSet")
.withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL,
CollectionFeature.KNOWN_ORDER,
CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
CollectionFeature.ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
@Override Table<String, Integer, Character> createTable() {
return HashBasedTable.create();
}
})
.named("HashBasedTable.cellSet")
.withFeatures(CollectionSize.ANY, CollectionFeature.REMOVE_OPERATIONS,
CollectionFeature.ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
@Override Table<String, Integer, Character> createTable() {
return TreeBasedTable.create();
}
})
.named("TreeBasedTable.cellSet")
.withFeatures(CollectionSize.ANY, CollectionFeature.REMOVE_OPERATIONS,
CollectionFeature.ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
@Override Table<String, Integer, Character> createTable() {
Table<Integer, String, Character> original
= TreeBasedTable.create();
return Tables.transpose(original);
}
})
.named("TransposedTable.cellSet")
.withFeatures(CollectionSize.ANY, CollectionFeature.REMOVE_OPERATIONS,
CollectionFeature.ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
@Override Table<String, Integer, Character> createTable() {
return HashBasedTable.create();
}
@Override
public Set<Cell<String, Integer, Character>> create(
Object... elements) {
Table<String, Integer, Character> table = createTable();
for (Object element : elements) {
@SuppressWarnings("unchecked")
Cell<String, Integer, Character> cell
= (Cell<String, Integer, Character>) element;
table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
}
return Tables.transformValues(table, Functions.<Character>identity()).cellSet();
}
})
.named("TransformValues.cellSet")
.withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
@Override Table<String, Integer, Character> createTable() {
return Tables.unmodifiableTable(HashBasedTable.<String, Integer, Character> create());
}
@Override
public Set<Cell<String, Integer, Character>> create(
Object... elements) {
Table<String, Integer, Character> table = HashBasedTable.create();
for (Object element : elements) {
@SuppressWarnings("unchecked")
Cell<String, Integer, Character> cell
= (Cell<String, Integer, Character>) element;
table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
}
return Tables.unmodifiableTable(table).cellSet();
}
})
.named("unmodifiableTable[HashBasedTable].cellSet")
.withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
@Override RowSortedTable<String, Integer, Character> createTable() {
return Tables.unmodifiableRowSortedTable(TreeBasedTable
.<String, Integer, Character> create());
}
@Override
public Set<Cell<String, Integer, Character>> create(
Object... elements) {
RowSortedTable<String, Integer, Character> table = TreeBasedTable.create();
for (Object element : elements) {
@SuppressWarnings("unchecked")
Cell<String, Integer, Character> cell
= (Cell<String, Integer, Character>) element;
table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
}
return Tables.unmodifiableRowSortedTable(table).cellSet();
}
})
.named("unmodifiableRowSortedTable[TreeBasedTable].cellSet")
.withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Iterable<String> rowKeys = ImmutableSet.copyOf(elements);
Iterable<Integer> columnKeys = ImmutableList.of(1, 2, 3);
Table<String, Integer, Character> table
= ArrayTable.create(rowKeys, columnKeys);
populateForRowKeySet(table, elements);
return table.column(1).keySet();
}
})
.named("ArrayTable.column.keySet")
.withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL,
CollectionFeature.KNOWN_ORDER,
CollectionFeature.ALLOWS_NULL_QUERIES)
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<String, Integer, Character> table = HashBasedTable.create();
populateForRowKeySet(table, elements);
return table.column(1).keySet();
}
})
.named("HashBasedTable.column.keySet")
.withFeatures(COLLECTION_FEATURES_REMOVE)
.suppressing(getIteratorUnknownOrderRemoveSupportedMethod())
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<String, Integer, Character> table = TreeBasedTable.create();
populateForRowKeySet(table, elements);
return table.column(1).keySet();
}
@Override public List<String> order(List<String> insertionOrder) {
Collections.sort(insertionOrder);
return insertionOrder;
}
})
.named("TreeBasedTable.column.keySet")
.withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
.suppressing(getIteratorKnownOrderRemoveSupportedMethod())
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<String, Integer, Character> table = HashBasedTable.create();
populateForRowKeySet(table, elements);
return Tables.transformValues(table, Functions.toStringFunction()).column(1).keySet();
}
})
.named("TransformValues.column.keySet")
.withFeatures(COLLECTION_FEATURES_REMOVE)
.suppressing(getIteratorUnknownOrderRemoveSupportedMethod())
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
Table<String, Integer, Character> table = HashBasedTable.create();
populateForRowKeySet(table, elements);
return Tables.unmodifiableTable(table).column(1).keySet();
}
})
.named("unmodifiableTable[HashBasedTable].column.keySet")
.withFeatures(COLLECTION_FEATURES)
.suppressing(getIteratorUnknownOrderRemoveSupportedMethod())
.createTestSuite());
suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override protected Set<String> create(String[] elements) {
RowSortedTable<String, Integer, Character> table = TreeBasedTable.create();
populateForRowKeySet(table, elements);
return Tables.unmodifiableRowSortedTable(table).column(1).keySet();
}
@Override public List<String> order(List<String> insertionOrder) {
Collections.sort(insertionOrder);
return insertionOrder;
}
})
.named("unmodifiableRowSortedTable[TreeBasedTable].column.keySet")
.withFeatures(COLLECTION_FEATURES_ORDER)
.suppressing(getIteratorKnownOrderRemoveSupportedMethod())
.createTestSuite());
return suite;
}
private static void populateForRowKeySet(
Table<String, Integer, Character> table, String[] elements) {
for (String row : elements) {
table.put(row, 1, 'a');
table.put(row, 2, 'b');
}
}
private static void populateForColumnKeySet(
Table<Integer, String, Character> table, String[] elements) {
for (String column : elements) {
table.put(1, column, 'a');
table.put(2, column, 'b');
}
}
private static void populateForValues(
Table<Integer, Character, String> table, String[] elements) {
for (int i = 0; i < elements.length; i++) {
table.put(i, 'a', elements[i]);
}
}
private static abstract class TestCellSetGenerator
implements TestSetGenerator<Cell<String, Integer, Character>> {
@Override
public SampleElements<Cell<String, Integer, Character>> samples() {
return new SampleElements<Cell<String, Integer, Character>>(
Tables.immutableCell("bar", 1, 'a'),
Tables.immutableCell("bar", 2, 'b'),
Tables.immutableCell("foo", 3, 'c'),
Tables.immutableCell("bar", 1, 'b'),
Tables.immutableCell("cat", 2, 'b'));
}
@Override
public Set<Cell<String, Integer, Character>> create(
Object... elements) {
Table<String, Integer, Character> table = createTable();
for (Object element : elements) {
@SuppressWarnings("unchecked")
Cell<String, Integer, Character> cell
= (Cell<String, Integer, Character>) element;
table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
}
return table.cellSet();
}
abstract Table<String, Integer, Character> createTable();
@Override
@SuppressWarnings("unchecked")
public Cell<String, Integer, Character>[] createArray(int length) {
return (Cell<String, Integer, Character>[]) new Cell<?, ?, ?>[length];
}
@Override
public List<Cell<String, Integer, Character>> order(
List<Cell<String, Integer, Character>> insertionOrder) {
return insertionOrder;
}
}
private static abstract class MapTests
extends MapInterfaceTest<String, Integer> {
MapTests(boolean allowsNullValues, boolean supportsPut, boolean supportsRemove,
boolean supportsClear, boolean supportsIteratorRemove) {
super(false, allowsNullValues, supportsPut, supportsRemove, supportsClear,
supportsIteratorRemove);
}
@Override protected String getKeyNotInPopulatedMap() {
return "four";
}
@Override protected Integer getValueNotInPopulatedMap() {
return 4;
}
}
private static abstract class RowTests extends MapTests {
RowTests(boolean allowsNullValues, boolean supportsPut, boolean supportsRemove,
boolean supportsClear, boolean supportsIteratorRemove) {
super(allowsNullValues, supportsPut, supportsRemove, supportsClear,
supportsIteratorRemove);
}
abstract Table<Character, String, Integer> makeTable();
@Override protected Map<String, Integer> makeEmptyMap() {
return makeTable().row('a');
}
@Override protected Map<String, Integer> makePopulatedMap() {
Table<Character, String, Integer> table = makeTable();
table.put('a', "one", 1);
table.put('a', "two", 2);
table.put('a', "three", 3);
table.put('b', "four", 4);
return table.row('a');
}
}
@GwtIncompatible("TODO(hhchan): ArrayTable")
public static class ArrayRowTests extends RowTests {
public ArrayRowTests() {
super(true, true, false, false, false);
}
@Override protected String getKeyNotInPopulatedMap() {
throw new UnsupportedOperationException();
}
@Override protected Map<String, Integer> makeEmptyMap() {
throw new UnsupportedOperationException();
}
@Override protected Table<Character, String, Integer> makeTable() {
return ArrayTable.create(Arrays.asList('a', 'b', 'c'),
Arrays.asList("one", "two", "three", "four"));
}
}
public static class HashRowTests extends RowTests {
public HashRowTests() {
super(false, true, true, true, true);
}
@Override Table<Character, String, Integer> makeTable() {
return HashBasedTable.create();
}
}
public static class TreeRowTests extends RowTests {
public TreeRowTests() {
super(false, true, true, true, true);
}
@Override Table<Character, String, Integer> makeTable() {
return TreeBasedTable.create();
}
}
public static class TransposeRowTests extends RowTests {
public TransposeRowTests() {
super(false, true, true, true, false);
}
@Override Table<Character, String, Integer> makeTable() {
Table<String, Character, Integer> original = TreeBasedTable.create();
return Tables.transpose(original);
}
}
private static final Function<Integer, Integer> DIVIDE_BY_2
= new Function<Integer, Integer>() {
@Override public Integer apply(Integer input) {
return (input == null) ? null : input / 2;
}
};
public static class TransformValueRowTests extends RowTests {
public TransformValueRowTests() {
super(false, false, true, true, true);
}
@Override Table<Character, String, Integer> makeTable() {
Table<Character, String, Integer> table = HashBasedTable.create();
return Tables.transformValues(table, DIVIDE_BY_2);
}
@Override protected Map<String, Integer> makePopulatedMap() {
Table<Character, String, Integer> table = HashBasedTable.create();
table.put('a', "one", 2);
table.put('a', "two", 4);
table.put('a', "three", 6);
table.put('b', "four", 8);
return Tables.transformValues(table, DIVIDE_BY_2).row('a');
}
}
public static class UnmodifiableHashRowTests extends RowTests {
public UnmodifiableHashRowTests() {
super(false, false, false, false, false);
}
@Override Table<Character, String, Integer> makeTable() {
Table<Character, String, Integer> table = HashBasedTable.create();
return Tables.unmodifiableTable(table);
}
@Override protected Map<String, Integer> makePopulatedMap() {
Table<Character, String, Integer> table = HashBasedTable.create();
table.put('a', "one", 1);
table.put('a', "two", 2);
table.put('a', "three", 3);
table.put('b', "four", 4);
return Tables.unmodifiableTable(table).row('a');
}
}
public static class UnmodifiableTreeRowTests extends RowTests {
public UnmodifiableTreeRowTests() {
super(false, false, false, false, false);
}
@Override Table<Character, String, Integer> makeTable() {
RowSortedTable<Character, String, Integer> table = TreeBasedTable.create();
return Tables.unmodifiableRowSortedTable(table);
}
@Override protected Map<String, Integer> makePopulatedMap() {
RowSortedTable<Character, String, Integer> table = TreeBasedTable.create();
table.put('a', "one", 1);
table.put('a', "two", 2);
table.put('a', "three", 3);
table.put('b', "four", 4);
return Tables.unmodifiableRowSortedTable(table).row('a');
}
}
private static abstract class ColumnTests extends MapTests {
ColumnTests(boolean allowsNullValues, boolean supportsPut, boolean supportsRemove,
boolean supportsClear, boolean supportsIteratorRemove) {
super(allowsNullValues, supportsPut, supportsRemove, supportsClear,
supportsIteratorRemove);
}
abstract Table<String, Character, Integer> makeTable();
@Override protected Map<String, Integer> makeEmptyMap() {
return makeTable().column('a');
}
@Override protected Map<String, Integer> makePopulatedMap() {
Table<String, Character, Integer> table = makeTable();
table.put("one", 'a', 1);
table.put("two", 'a', 2);
table.put("three", 'a', 3);
table.put("four", 'b', 4);
return table.column('a');
}
}
@GwtIncompatible("TODO(hhchan): ArrayTable")
public static class ArrayColumnTests extends ColumnTests {
public ArrayColumnTests() {
super(true, true, false, false, false);
}
@Override protected String getKeyNotInPopulatedMap() {
throw new UnsupportedOperationException();
}
@Override protected Map<String, Integer> makeEmptyMap() {
throw new UnsupportedOperationException();
}
@Override Table<String, Character, Integer> makeTable() {
return ArrayTable.create(Arrays.asList("one", "two", "three", "four"),
Arrays.asList('a', 'b', 'c'));
}
}
public static class HashColumnTests extends ColumnTests {
public HashColumnTests() {
super(false, true, true, true, false);
}
@Override Table<String, Character, Integer> makeTable() {
return HashBasedTable.create();
}
}
public static class TreeColumnTests extends ColumnTests {
public TreeColumnTests() {
super(false, true, true, true, false);
}
@Override Table<String, Character, Integer> makeTable() {
return TreeBasedTable.create();
}
}
public static class TransposeColumnTests extends ColumnTests {
public TransposeColumnTests() {
super(false, true, true, true, true);
}
@Override Table<String, Character, Integer> makeTable() {
Table<Character, String, Integer> original = TreeBasedTable.create();
return Tables.transpose(original);
}
}
public static class TransformValueColumnTests extends ColumnTests {
public TransformValueColumnTests() {
super(false, false, true, true, false);
}
@Override Table<String, Character, Integer> makeTable() {
Table<String, Character, Integer> table = HashBasedTable.create();
return Tables.transformValues(table, DIVIDE_BY_2);
}
@Override protected Map<String, Integer> makePopulatedMap() {
Table<String, Character, Integer> table = HashBasedTable.create();
table.put("one", 'a', 1);
table.put("two", 'a', 2);
table.put("three", 'a', 3);
table.put("four", 'b', 4);
return Tables.transformValues(table, DIVIDE_BY_2).column('a');
}
}
public static class UnmodifiableHashColumnTests extends ColumnTests {
public UnmodifiableHashColumnTests() {
super(false, false, false, false, false);
}
@Override Table<String, Character, Integer> makeTable() {
Table<String, Character, Integer> table = HashBasedTable.create();
return Tables.unmodifiableTable(table);
}
@Override protected Map<String, Integer> makePopulatedMap() {
Table<String, Character, Integer> table = HashBasedTable.create();
table.put("one", 'a', 1);
table.put("two", 'a', 2);
table.put("three", 'a', 3);
table.put("four", 'b', 4);
return Tables.unmodifiableTable(table).column('a');
}
}
public static class UnmodifiableTreeColumnTests extends ColumnTests {
public UnmodifiableTreeColumnTests() {
super(false, false, false, false, false);
}
@Override Table<String, Character, Integer> makeTable() {
RowSortedTable<String, Character, Integer> table = TreeBasedTable.create();
return Tables.unmodifiableRowSortedTable(table);
}
@Override protected Map<String, Integer> makePopulatedMap() {
RowSortedTable<String, Character, Integer> table = TreeBasedTable.create();
table.put("one", 'a', 1);
table.put("two", 'a', 2);
table.put("three", 'a', 3);
table.put("four", 'b', 4);
return Tables.unmodifiableRowSortedTable(table).column('a');
}
}
private static abstract class MapMapTests
extends MapInterfaceTest<String, Map<Integer, Character>> {
MapMapTests(boolean allowsNullValues, boolean supportsRemove,
boolean supportsClear, boolean supportsIteratorRemove) {
super(false, allowsNullValues, false, supportsRemove, supportsClear,
supportsIteratorRemove);
}
@Override protected String getKeyNotInPopulatedMap() {
return "cat";
}
@Override protected Map<Integer, Character> getValueNotInPopulatedMap() {
return ImmutableMap.of();
}
/**
* The version of this test supplied by {@link MapInterfaceTest} fails for
* this particular map implementation, because {@code map.get()} returns a
* view collection that changes in the course of a call to {@code remove()}.
* Thus, the expectation doesn't hold that {@code map.remove(x)} returns the
* same value which {@code map.get(x)} did immediately beforehand.
*/
@Override public void testRemove() {
final Map<String, Map<Integer, Character>> map;
final String keyToRemove;
try {
map = makePopulatedMap();
} catch (UnsupportedOperationException e) {
return;
}
keyToRemove = map.keySet().iterator().next();
if (supportsRemove) {
int initialSize = map.size();
map.get(keyToRemove);
map.remove(keyToRemove);
// This line doesn't hold - see the Javadoc comments above.
// assertEquals(expectedValue, oldValue);
assertFalse(map.containsKey(keyToRemove));
assertEquals(initialSize - 1, map.size());
} else {
try {
map.remove(keyToRemove);
fail("Expected UnsupportedOperationException.");
} catch (UnsupportedOperationException e) {
// Expected.
}
}
assertInvariants(map);
}
}
private static abstract class RowMapTests extends MapMapTests {
RowMapTests(boolean allowsNullValues, boolean supportsRemove,
boolean supportsClear, boolean supportsIteratorRemove) {
super(allowsNullValues, supportsRemove, supportsClear,
supportsIteratorRemove);
}
abstract Table<String, Integer, Character> makeTable();
@Override protected Map<String, Map<Integer, Character>>
makePopulatedMap() {
Table<String, Integer, Character> table = makeTable();
populateTable(table);
return table.rowMap();
}
void populateTable(Table<String, Integer, Character> table) {
table.put("foo", 1, 'a');
table.put("bar", 1, 'b');
table.put("foo", 3, 'c');
}
@Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
return makeTable().rowMap();
}
}
@GwtIncompatible("TODO(hhchan): ArrayTable")
public static class ArrayRowMapTests extends RowMapTests {
public ArrayRowMapTests() {
super(true, false, false, false);
}
@Override Table<String, Integer, Character> makeTable() {
return ArrayTable.create(Arrays.asList("foo", "bar", "dog"),
Arrays.asList(1, 2, 3));
}
@Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
throw new UnsupportedOperationException();
}
}
public static class HashRowMapTests extends RowMapTests {
public HashRowMapTests() {
super(false, true, true, true);
}
@Override Table<String, Integer, Character> makeTable() {
return HashBasedTable.create();
}
}
public static class TreeRowMapTests extends RowMapTests {
public TreeRowMapTests() {
super(false, true, true, true);
}
@Override Table<String, Integer, Character> makeTable() {
return TreeBasedTable.create();
}
}
public static class TreeRowMapHeadMapTests extends RowMapTests {
public TreeRowMapHeadMapTests() {
super(false, true, true, true);
}
@Override TreeBasedTable<String, Integer, Character> makeTable() {
TreeBasedTable<String, Integer, Character> table =
TreeBasedTable.create();
table.put("z", 1, 'a');
return table;
}
@Override protected Map<String, Map<Integer, Character>>
makePopulatedMap() {
TreeBasedTable<String, Integer, Character> table = makeTable();
populateTable(table);
return table.rowMap().headMap("x");
}
@Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
return makeTable().rowMap().headMap("x");
}
@Override protected String getKeyNotInPopulatedMap() {
return "z";
}
}
public static class TreeRowMapTailMapTests extends RowMapTests {
public TreeRowMapTailMapTests() {
super(false, true, true, true);
}
@Override TreeBasedTable<String, Integer, Character> makeTable() {
TreeBasedTable<String, Integer, Character> table =
TreeBasedTable.create();
table.put("a", 1, 'a');
return table;
}
@Override protected Map<String, Map<Integer, Character>>
makePopulatedMap() {
TreeBasedTable<String, Integer, Character> table = makeTable();
populateTable(table);
return table.rowMap().tailMap("b");
}
@Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
return makeTable().rowMap().tailMap("b");
}
@Override protected String getKeyNotInPopulatedMap() {
return "a";
}
}
public static class TreeRowMapSubMapTests extends RowMapTests {
public TreeRowMapSubMapTests() {
super(false, true, true, true);
}
@Override TreeBasedTable<String, Integer, Character> makeTable() {
TreeBasedTable<String, Integer, Character> table =
TreeBasedTable.create();
table.put("a", 1, 'a');
table.put("z", 1, 'a');
return table;
}
@Override protected Map<String, Map<Integer, Character>>
makePopulatedMap() {
TreeBasedTable<String, Integer, Character> table = makeTable();
populateTable(table);
return table.rowMap().subMap("b", "x");
}
@Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
return makeTable().rowMap().subMap("b", "x");
}
@Override protected String getKeyNotInPopulatedMap() {
return "z";
}
}
private static final Function<String, Character> FIRST_CHARACTER =
new Function<String, Character>() {
@Override
public Character apply(String input) {
return input == null ? null : input.charAt(0);
}
};
public static class TransformValueRowMapTests extends RowMapTests {
public TransformValueRowMapTests() {
super(false, true, true, true);
}
@Override Table<String, Integer, Character> makeTable() {
Table<String, Integer, String> original = HashBasedTable.create();
return Tables.transformValues(original, FIRST_CHARACTER);
}
@Override
protected Map<String, Map<Integer, Character>> makePopulatedMap() {
Table<String, Integer, String> table = HashBasedTable.create();
table.put("foo", 1, "apple");
table.put("bar", 1, "banana");
table.put("foo", 3, "cat");
return Tables.transformValues(table, FIRST_CHARACTER).rowMap();
}
}
public static class UnmodifiableHashRowMapTests extends RowMapTests {
public UnmodifiableHashRowMapTests() {
super(false, false, false, false);
}
@Override Table<String, Integer, Character> makeTable() {
Table<String, Integer, Character> original = HashBasedTable.create();
return Tables.unmodifiableTable(original);
}
@Override
protected Map<String, Map<Integer, Character>> makePopulatedMap() {
Table<String, Integer, Character> table = HashBasedTable.create();
table.put("foo", 1, 'a');
table.put("bar", 1, 'b');
table.put("foo", 3, 'c');
return Tables.unmodifiableTable(table).rowMap();
}
}
public static class UnmodifiableTreeRowMapTests extends RowMapTests {
public UnmodifiableTreeRowMapTests() {
super(false, false, false, false);
}
@Override RowSortedTable<String, Integer, Character> makeTable() {
RowSortedTable<String, Integer, Character> original = TreeBasedTable.create();
return Tables.unmodifiableRowSortedTable(original);
}
@Override
protected SortedMap<String, Map<Integer, Character>> makePopulatedMap() {
RowSortedTable<String, Integer, Character> table = TreeBasedTable.create();
table.put("foo", 1, 'a');
table.put("bar", 1, 'b');
table.put("foo", 3, 'c');
return Tables.unmodifiableRowSortedTable(table).rowMap();
}
}
private static abstract class ColumnMapTests extends MapMapTests {
ColumnMapTests(boolean allowsNullValues, boolean supportsRemove,
boolean supportsClear, boolean supportsIteratorRemove) {
super(allowsNullValues, supportsRemove, supportsClear,
supportsIteratorRemove);
}
abstract Table<Integer, String, Character> makeTable();
@Override protected Map<String, Map<Integer, Character>>
makePopulatedMap() {
Table<Integer, String, Character> table = makeTable();
table.put(1, "foo", 'a');
table.put(1, "bar", 'b');
table.put(3, "foo", 'c');
return table.columnMap();
}
@Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
return makeTable().columnMap();
}
}
@GwtIncompatible("TODO(hhchan): ArrayTable")
public static class ArrayColumnMapTests extends ColumnMapTests {
public ArrayColumnMapTests() {
super(true, false, false, false);
}
@Override Table<Integer, String, Character> makeTable() {
return ArrayTable.create(Arrays.asList(1, 2, 3),
Arrays.asList("foo", "bar", "dog"));
}
@Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
throw new UnsupportedOperationException();
}
}
public static class HashColumnMapTests extends ColumnMapTests {
public HashColumnMapTests() {
super(false, true, true, false);
}
@Override Table<Integer, String, Character> makeTable() {
return HashBasedTable.create();
}
}
public static class TreeColumnMapTests extends ColumnMapTests {
public TreeColumnMapTests() {
super(false, true, true, false);
}
@Override Table<Integer, String, Character> makeTable() {
return TreeBasedTable.create();
}
}
public static class TransformValueColumnMapTests extends ColumnMapTests {
public TransformValueColumnMapTests() {
super(false, true, true, false);
}
@Override Table<Integer, String, Character> makeTable() {
Table<Integer, String, String> original = HashBasedTable.create();
return Tables.transformValues(original, FIRST_CHARACTER);
}
@Override
protected Map<String, Map<Integer, Character>> makePopulatedMap() {
Table<Integer, String, String> table = HashBasedTable.create();
table.put(1, "foo", "apple");
table.put(1, "bar", "banana");
table.put(3, "foo", "cat");
return Tables.transformValues(table, FIRST_CHARACTER).columnMap();
}
}
public static class UnmodifiableHashColumnMapTests extends ColumnMapTests {
public UnmodifiableHashColumnMapTests() {
super(false, false, false, false);
}
@Override Table<Integer, String, Character> makeTable() {
Table<Integer, String, Character> original = HashBasedTable.create();
return Tables.unmodifiableTable(original);
}
@Override
protected Map<String, Map<Integer, Character>> makePopulatedMap() {
Table<Integer, String, Character> table = HashBasedTable.create();
table.put(1, "foo", 'a');
table.put(1, "bar", 'b');
table.put(3, "foo", 'c');
return Tables.unmodifiableTable(table).columnMap();
}
}
public static class UnmodifiableTreeColumnMapTests extends ColumnMapTests {
public UnmodifiableTreeColumnMapTests() {
super(false, false, false, false);
}
@Override Table<Integer, String, Character> makeTable() {
RowSortedTable<Integer, String, Character> original = TreeBasedTable.create();
return Tables.unmodifiableRowSortedTable(original);
}
@Override
protected Map<String, Map<Integer, Character>> makePopulatedMap() {
RowSortedTable<Integer, String, Character> table = TreeBasedTable.create();
table.put(1, "foo", 'a');
table.put(1, "bar", 'b');
table.put(3, "foo", 'c');
return Tables.unmodifiableRowSortedTable(table).columnMap();
}
}
}