/*
* Copyright (C) 2009 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 java.util.Arrays.asList;
import static org.junit.contrib.truth.Truth.ASSERT;
import com.google.common.base.Objects;
import com.google.common.collect.Table.Cell;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.SerializableTester;
import java.util.Arrays;
import java.util.Map;
/**
* Test cases for {@link ArrayTable}.
*
* @author Jared Levy
*/
public class ArrayTableTest extends AbstractTableTest {
@Override protected ArrayTable<String, Integer, Character> create(
Object... data) {
// TODO: Specify different numbers of rows and columns, to detect problems
// that arise when the wrong size is used.
ArrayTable<String, Integer, Character> table =
ArrayTable.create(asList("foo", "bar", "cat"), asList(1, 2, 3));
populate(table, data);
return table;
}
@Override protected void assertSize(int expectedSize) {
assertEquals(9, table.size());
}
@Override protected boolean supportsRemove() {
return false;
}
@Override protected boolean supportsNullValues() {
return true;
}
// Overriding tests of behavior that differs for ArrayTable.
@Override public void testContains() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertTrue(table.contains("foo", 1));
assertTrue(table.contains("bar", 1));
assertTrue(table.contains("foo", 3));
assertTrue(table.contains("foo", 2));
assertTrue(table.contains("bar", 3));
assertTrue(table.contains("cat", 1));
assertFalse(table.contains("foo", -1));
assertFalse(table.contains("bad", 1));
assertFalse(table.contains("bad", -1));
assertFalse(table.contains("foo", null));
assertFalse(table.contains(null, 1));
assertFalse(table.contains(null, null));
}
@Override public void testContainsRow() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertTrue(table.containsRow("foo"));
assertTrue(table.containsRow("bar"));
assertTrue(table.containsRow("cat"));
assertFalse(table.containsRow("bad"));
assertFalse(table.containsRow(null));
}
@Override public void testContainsColumn() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertTrue(table.containsColumn(1));
assertTrue(table.containsColumn(3));
assertTrue(table.containsColumn(2));
assertFalse(table.containsColumn(-1));
assertFalse(table.containsColumn(null));
}
@Override public void testContainsValue() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertTrue(table.containsValue('a'));
assertTrue(table.containsValue('b'));
assertTrue(table.containsValue('c'));
assertFalse(table.containsValue('x'));
assertTrue(table.containsValue(null));
}
@Override public void testIsEmpty() {
assertFalse(table.isEmpty());
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertFalse(table.isEmpty());
}
@Override public void testEquals() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Table<String, Integer, Character> hashCopy = HashBasedTable.create();
hashCopy.put("foo", 1, 'a');
hashCopy.put("bar", 1, 'b');
hashCopy.put("foo", 3, 'c');
Table<String, Integer, Character> reordered
= create("foo", 3, 'c', "foo", 1, 'a', "bar", 1, 'b');
Table<String, Integer, Character> smaller
= create("foo", 1, 'a', "bar", 1, 'b');
Table<String, Integer, Character> swapOuter
= create("bar", 1, 'a', "foo", 1, 'b', "bar", 3, 'c');
Table<String, Integer, Character> swapValues
= create("foo", 1, 'c', "bar", 1, 'b', "foo", 3, 'a');
new EqualsTester()
.addEqualityGroup(table, reordered)
.addEqualityGroup(hashCopy)
.addEqualityGroup(smaller)
.addEqualityGroup(swapOuter)
.addEqualityGroup(swapValues)
.testEquals();
}
@Override public void testHashCode() {
table = ArrayTable.create(asList("foo", "bar"), asList(1, 3));
table.put("foo", 1, 'a');
table.put("bar", 1, 'b');
table.put("foo", 3, 'c');
int expected = Objects.hashCode("foo", 1, 'a')
+ Objects.hashCode("bar", 1, 'b')
+ Objects.hashCode("foo", 3, 'c')
+ Objects.hashCode("bar", 3, 0);
assertEquals(expected, table.hashCode());
}
@Override public void testRow() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Map<Integer, Character> expected = Maps.newHashMap();
expected.put(1, 'a');
expected.put(3, 'c');
expected.put(2, null);
assertEquals(expected, table.row("foo"));
}
@Override public void testColumn() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Map<String, Character> expected = Maps.newHashMap();
expected.put("foo", 'a');
expected.put("bar", 'b');
expected.put("cat", null);
assertEquals(expected, table.column(1));
}
@Override public void testToStringSize1() {
table = ArrayTable.create(ImmutableList.of("foo"), ImmutableList.of(1));
table.put("foo", 1, 'a');
assertEquals("{foo={1=a}}", table.toString());
}
public void testCreateDuplicateRows() {
try {
ArrayTable.create(asList("foo", "bar", "foo"), asList(1, 2, 3));
fail();
} catch (IllegalArgumentException expected) {}
}
public void testCreateDuplicateColumns() {
try {
ArrayTable.create(asList("foo", "bar"), asList(1, 2, 3, 2));
fail();
} catch (IllegalArgumentException expected) {}
}
public void testCreateEmptyRows() {
try {
ArrayTable.create(Arrays.<String>asList(), asList(1, 2, 3));
fail();
} catch (IllegalArgumentException expected) {}
}
public void testCreateEmptyColumns() {
try {
ArrayTable.create(asList("foo", "bar"), Arrays.<Integer>asList());
fail();
} catch (IllegalArgumentException expected) {}
}
public void testCreateCopyArrayTable() {
Table<String, Integer, Character> original
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Table<String, Integer, Character> copy = ArrayTable.create(original);
assertEquals(original, copy);
original.put("foo", 1, 'd');
assertEquals((Character) 'd', original.get("foo", 1));
assertEquals((Character) 'a', copy.get("foo", 1));
assertEquals(copy.rowKeySet(), original.rowKeySet());
assertEquals(copy.columnKeySet(), original.columnKeySet());
}
public void testCreateCopyHashBasedTable() {
Table<String, Integer, Character> original = HashBasedTable.create();
original.put("foo", 1, 'a');
original.put("bar", 1, 'b');
original.put("foo", 3, 'c');
Table<String, Integer, Character> copy = ArrayTable.create(original);
assertEquals(4, copy.size());
assertEquals((Character) 'a', copy.get("foo", 1));
assertEquals((Character) 'b', copy.get("bar", 1));
assertEquals((Character) 'c', copy.get("foo", 3));
assertNull(copy.get("bar", 3));
original.put("foo", 1, 'd');
assertEquals((Character) 'd', original.get("foo", 1));
assertEquals((Character) 'a', copy.get("foo", 1));
assertEquals(copy.rowKeySet(), ImmutableSet.of("foo", "bar"));
assertEquals(copy.columnKeySet(), ImmutableSet.of(1, 3));
}
public void testCreateCopyEmptyTable() {
Table<String, Integer, Character> original = HashBasedTable.create();
try {
ArrayTable.create(original);
fail();
} catch (IllegalArgumentException expected) {}
}
public void testSerialization() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
SerializableTester.reserializeAndAssert(table);
}
public void testNullPointerStatic() throws Exception {
new NullPointerTester().testAllPublicStaticMethods(ArrayTable.class);
}
public void testToString_ordered() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertEquals("{foo={1=a, 2=null, 3=c}, " +
"bar={1=b, 2=null, 3=null}, " +
"cat={1=null, 2=null, 3=null}}",
table.toString());
assertEquals("{foo={1=a, 2=null, 3=c}, " +
"bar={1=b, 2=null, 3=null}, " +
"cat={1=null, 2=null, 3=null}}",
table.rowMap().toString());
}
public void testCellSetToString_ordered() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertEquals("[(foo,1)=a, (foo,2)=null, (foo,3)=c, " +
"(bar,1)=b, (bar,2)=null, (bar,3)=null, " +
"(cat,1)=null, (cat,2)=null, (cat,3)=null]",
table.cellSet().toString());
}
public void testRowKeySetToString_ordered() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertEquals("[foo, bar, cat]", table.rowKeySet().toString());
}
public void testColumnKeySetToString_ordered() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertEquals("[1, 2, 3]", table.columnKeySet().toString());
}
public void testValuesToString_ordered() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertEquals("[a, null, c, b, null, null, null, null, null]",
table.values().toString());
}
public void testRowKeyList() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
ASSERT.that(table.rowKeyList()).hasContentsInOrder("foo", "bar", "cat");
}
public void testColumnKeyList() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
ASSERT.that(table.columnKeyList()).hasContentsInOrder(1, 2, 3);
}
public void testGetMissingKeys() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertNull(table.get("dog", 1));
assertNull(table.get("foo", 4));
}
public void testAt() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertEquals((Character) 'b', table.at(1, 0));
assertEquals((Character) 'c', table.at(0, 2));
assertNull(table.at(1, 2));
try {
table.at(1, 3);
fail();
} catch (IndexOutOfBoundsException expected) {}
try {
table.at(1, -1);
fail();
} catch (IndexOutOfBoundsException expected) {}
try {
table.at(3, 2);
fail();
} catch (IndexOutOfBoundsException expected) {}
try {
table.at(-1, 2);
fail();
} catch (IndexOutOfBoundsException expected) {}
}
public void testSet() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertEquals((Character) 'b', table.set(1, 0, 'd'));
assertEquals((Character) 'd', table.get("bar", 1));
assertNull(table.set(2, 0, 'e'));
assertEquals((Character) 'e', table.get("cat", 1));
assertEquals((Character) 'a', table.set(0, 0, null));
assertNull(table.get("foo", 1));
try {
table.set(1, 3, 'z');
fail();
} catch (IndexOutOfBoundsException expected) {}
try {
table.set(1, -1, 'z');
fail();
} catch (IndexOutOfBoundsException expected) {}
try {
table.set(3, 2, 'z');
fail();
} catch (IndexOutOfBoundsException expected) {}
try {
table.set(-1, 2, 'z');
fail();
} catch (IndexOutOfBoundsException expected) {}
assertFalse(table.containsValue('z'));
}
public void testEraseAll() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
table.eraseAll();
assertEquals(9, table.size());
assertNull(table.get("bar", 1));
assertTrue(table.containsRow("foo"));
assertFalse(table.containsValue('a'));
}
public void testPutIllegal() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
try {
table.put("dog", 1, 'd');
fail();
} catch (IllegalArgumentException expected) {
assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
}
try {
table.put("foo", 4, 'd');
fail();
} catch (IllegalArgumentException expected) {
assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
}
assertFalse(table.containsValue('d'));
}
public void testErase() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
assertEquals((Character) 'b', table.erase("bar", 1));
assertNull(table.get("bar", 1));
assertEquals(9, table.size());
assertNull(table.erase("bar", 1));
assertNull(table.erase("foo", 2));
assertNull(table.erase("dog", 1));
assertNull(table.erase("bar", 5));
assertNull(table.erase(null, 1));
assertNull(table.erase("bar", null));
}
public void testToArray() {
ArrayTable<String, Integer, Character> table
= create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Character[][] array = table.toArray(Character.class);
assertEquals(3, array.length);
ASSERT.that(array[0]).hasContentsInOrder('a', null, 'c');
ASSERT.that(array[1]).hasContentsInOrder('b', null, null);
ASSERT.that(array[2]).hasContentsInOrder(null, null, null);
table.set(0, 2, 'd');
assertEquals((Character) 'c', array[0][2]);
array[0][2] = 'e';
assertEquals((Character) 'd', table.at(0, 2));
}
public void testCellReflectsChanges() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Cell<String, Integer, Character> cell = table.cellSet().iterator().next();
assertEquals(Tables.immutableCell("foo", 1, 'a'), cell);
assertEquals((Character) 'a', table.put("foo", 1, 'd'));
assertEquals(Tables.immutableCell("foo", 1, 'd'), cell);
}
public void testRowMissing() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Map<Integer, Character> row = table.row("dog");
assertTrue(row.isEmpty());
try {
row.put(1, 'd');
fail();
} catch (UnsupportedOperationException expected) {}
}
public void testColumnMissing() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Map<String, Character> column = table.column(4);
assertTrue(column.isEmpty());
try {
column.put("foo", 'd');
fail();
} catch (UnsupportedOperationException expected) {}
}
public void testRowPutIllegal() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Map<Integer, Character> map = table.row("foo");
try {
map.put(4, 'd');
fail();
} catch (IllegalArgumentException expected) {
assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
}
}
public void testColumnPutIllegal() {
table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
Map<String, Character> map = table.column(3);
try {
map.put("dog", 'd');
fail();
} catch (IllegalArgumentException expected) {
assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
}
}
}