/* * 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()); } } }