View Javadoc
1   /*
2    * Copyright (C) 2009 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect;
18  
19  import static com.google.common.truth.Truth.assertThat;
20  import static java.util.Arrays.asList;
21  
22  import com.google.common.annotations.GwtCompatible;
23  import com.google.common.base.Objects;
24  import com.google.common.collect.Table.Cell;
25  import com.google.common.testing.EqualsTester;
26  import com.google.common.testing.SerializableTester;
27  
28  import java.util.Arrays;
29  import java.util.Map;
30  
31  /**
32   * Test cases for {@link ArrayTable}.
33   *
34   * @author Jared Levy
35   */
36  @GwtCompatible(emulated = true)
37  public class ArrayTableTest extends AbstractTableTest {
38  
39    @Override protected ArrayTable<String, Integer, Character> create(
40        Object... data) {
41      // TODO: Specify different numbers of rows and columns, to detect problems
42      // that arise when the wrong size is used.
43      ArrayTable<String, Integer, Character> table =
44          ArrayTable.create(asList("foo", "bar", "cat"), asList(1, 2, 3));
45      populate(table, data);
46      return table;
47    }
48  
49    @Override protected void assertSize(int expectedSize) {
50      assertEquals(9, table.size());
51    }
52  
53    @Override protected boolean supportsRemove() {
54      return false;
55    }
56  
57    @Override protected boolean supportsNullValues() {
58      return true;
59    }
60  
61    // Overriding tests of behavior that differs for ArrayTable.
62  
63    @Override public void testContains() {
64      table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
65      assertTrue(table.contains("foo", 1));
66      assertTrue(table.contains("bar", 1));
67      assertTrue(table.contains("foo", 3));
68      assertTrue(table.contains("foo", 2));
69      assertTrue(table.contains("bar", 3));
70      assertTrue(table.contains("cat", 1));
71      assertFalse(table.contains("foo", -1));
72      assertFalse(table.contains("bad", 1));
73      assertFalse(table.contains("bad", -1));
74      assertFalse(table.contains("foo", null));
75      assertFalse(table.contains(null, 1));
76      assertFalse(table.contains(null, null));
77    }
78  
79    @Override public void testContainsRow() {
80      table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
81      assertTrue(table.containsRow("foo"));
82      assertTrue(table.containsRow("bar"));
83      assertTrue(table.containsRow("cat"));
84      assertFalse(table.containsRow("bad"));
85      assertFalse(table.containsRow(null));
86    }
87  
88    @Override public void testContainsColumn() {
89      table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
90      assertTrue(table.containsColumn(1));
91      assertTrue(table.containsColumn(3));
92      assertTrue(table.containsColumn(2));
93      assertFalse(table.containsColumn(-1));
94      assertFalse(table.containsColumn(null));
95    }
96  
97    @Override public void testContainsValue() {
98      table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
99      assertTrue(table.containsValue('a'));
100     assertTrue(table.containsValue('b'));
101     assertTrue(table.containsValue('c'));
102     assertFalse(table.containsValue('x'));
103     assertTrue(table.containsValue(null));
104   }
105 
106   @Override public void testIsEmpty() {
107     assertFalse(table.isEmpty());
108     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
109     assertFalse(table.isEmpty());
110   }
111 
112   @Override public void testEquals() {
113     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
114     Table<String, Integer, Character> hashCopy = HashBasedTable.create();
115     hashCopy.put("foo", 1, 'a');
116     hashCopy.put("bar", 1, 'b');
117     hashCopy.put("foo", 3, 'c');
118     Table<String, Integer, Character> reordered
119         = create("foo", 3, 'c', "foo", 1, 'a', "bar", 1, 'b');
120     Table<String, Integer, Character> smaller
121         = create("foo", 1, 'a', "bar", 1, 'b');
122     Table<String, Integer, Character> swapOuter
123         = create("bar", 1, 'a', "foo", 1, 'b', "bar", 3, 'c');
124     Table<String, Integer, Character> swapValues
125         = create("foo", 1, 'c', "bar", 1, 'b', "foo", 3, 'a');
126 
127     new EqualsTester()
128         .addEqualityGroup(table, reordered)
129         .addEqualityGroup(hashCopy)
130         .addEqualityGroup(smaller)
131         .addEqualityGroup(swapOuter)
132         .addEqualityGroup(swapValues)
133         .testEquals();
134   }
135 
136   @Override public void testHashCode() {
137     table = ArrayTable.create(asList("foo", "bar"), asList(1, 3));
138     table.put("foo", 1, 'a');
139     table.put("bar", 1, 'b');
140     table.put("foo", 3, 'c');
141     int expected = Objects.hashCode("foo", 1, 'a')
142         + Objects.hashCode("bar", 1, 'b')
143         + Objects.hashCode("foo", 3, 'c')
144         + Objects.hashCode("bar", 3, 0);
145     assertEquals(expected, table.hashCode());
146   }
147 
148   @Override public void testRow() {
149     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
150     Map<Integer, Character> expected = Maps.newHashMap();
151     expected.put(1, 'a');
152     expected.put(3, 'c');
153     expected.put(2, null);
154     assertEquals(expected, table.row("foo"));
155   }
156 
157   @Override public void testColumn() {
158     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
159     Map<String, Character> expected = Maps.newHashMap();
160     expected.put("foo", 'a');
161     expected.put("bar", 'b');
162     expected.put("cat", null);
163     assertEquals(expected, table.column(1));
164   }
165 
166   @Override public void testToStringSize1() {
167     table = ArrayTable.create(ImmutableList.of("foo"), ImmutableList.of(1));
168     table.put("foo", 1, 'a');
169     assertEquals("{foo={1=a}}", table.toString());
170   }
171 
172   public void testCreateDuplicateRows() {
173     try {
174       ArrayTable.create(asList("foo", "bar", "foo"), asList(1, 2, 3));
175       fail();
176     } catch (IllegalArgumentException expected) {}
177   }
178 
179   public void testCreateDuplicateColumns() {
180     try {
181       ArrayTable.create(asList("foo", "bar"), asList(1, 2, 3, 2));
182       fail();
183     } catch (IllegalArgumentException expected) {}
184   }
185 
186   public void testCreateEmptyRows() {
187     try {
188       ArrayTable.create(Arrays.<String>asList(), asList(1, 2, 3));
189       fail();
190     } catch (IllegalArgumentException expected) {}
191   }
192 
193   public void testCreateEmptyColumns() {
194     try {
195       ArrayTable.create(asList("foo", "bar"), Arrays.<Integer>asList());
196       fail();
197     } catch (IllegalArgumentException expected) {}
198   }
199 
200   public void testCreateCopyArrayTable() {
201     Table<String, Integer, Character> original
202         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
203     Table<String, Integer, Character> copy = ArrayTable.create(original);
204     assertEquals(original, copy);
205     original.put("foo", 1, 'd');
206     assertEquals((Character) 'd', original.get("foo", 1));
207     assertEquals((Character) 'a', copy.get("foo", 1));
208     assertEquals(copy.rowKeySet(), original.rowKeySet());
209     assertEquals(copy.columnKeySet(), original.columnKeySet());
210   }
211 
212   public void testCreateCopyHashBasedTable() {
213     Table<String, Integer, Character> original = HashBasedTable.create();
214     original.put("foo", 1, 'a');
215     original.put("bar", 1, 'b');
216     original.put("foo", 3, 'c');
217     Table<String, Integer, Character> copy = ArrayTable.create(original);
218     assertEquals(4, copy.size());
219     assertEquals((Character) 'a', copy.get("foo", 1));
220     assertEquals((Character) 'b', copy.get("bar", 1));
221     assertEquals((Character) 'c', copy.get("foo", 3));
222     assertNull(copy.get("bar", 3));
223     original.put("foo", 1, 'd');
224     assertEquals((Character) 'd', original.get("foo", 1));
225     assertEquals((Character) 'a', copy.get("foo", 1));
226     assertEquals(copy.rowKeySet(), ImmutableSet.of("foo", "bar"));
227     assertEquals(copy.columnKeySet(), ImmutableSet.of(1, 3));
228   }
229 
230   public void testCreateCopyEmptyTable() {
231     Table<String, Integer, Character> original = HashBasedTable.create();
232     try {
233       ArrayTable.create(original);
234       fail();
235     } catch (IllegalArgumentException expected) {}
236   }
237 
238   public void testSerialization() {
239     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
240     SerializableTester.reserializeAndAssert(table);
241   }
242 
243   public void testToString_ordered() {
244     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
245     assertEquals("{foo={1=a, 2=null, 3=c}, " +
246         "bar={1=b, 2=null, 3=null}, " +
247         "cat={1=null, 2=null, 3=null}}",
248         table.toString());
249     assertEquals("{foo={1=a, 2=null, 3=c}, " +
250         "bar={1=b, 2=null, 3=null}, " +
251         "cat={1=null, 2=null, 3=null}}",
252         table.rowMap().toString());
253   }
254 
255   public void testCellSetToString_ordered() {
256     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
257     assertEquals("[(foo,1)=a, (foo,2)=null, (foo,3)=c, " +
258         "(bar,1)=b, (bar,2)=null, (bar,3)=null, " +
259         "(cat,1)=null, (cat,2)=null, (cat,3)=null]",
260         table.cellSet().toString());
261   }
262 
263   public void testRowKeySetToString_ordered() {
264     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
265     assertEquals("[foo, bar, cat]", table.rowKeySet().toString());
266   }
267 
268   public void testColumnKeySetToString_ordered() {
269     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
270     assertEquals("[1, 2, 3]", table.columnKeySet().toString());
271   }
272 
273   public void testValuesToString_ordered() {
274     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
275     assertEquals("[a, null, c, b, null, null, null, null, null]",
276         table.values().toString());
277   }
278 
279   public void testRowKeyList() {
280     ArrayTable<String, Integer, Character> table
281         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
282     assertThat(table.rowKeyList()).has().exactly("foo", "bar", "cat").inOrder();
283   }
284 
285   public void testColumnKeyList() {
286     ArrayTable<String, Integer, Character> table
287         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
288     assertThat(table.columnKeyList()).has().exactly(1, 2, 3).inOrder();
289   }
290 
291   public void testGetMissingKeys() {
292     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
293     assertNull(table.get("dog", 1));
294     assertNull(table.get("foo", 4));
295   }
296 
297   public void testAt() {
298     ArrayTable<String, Integer, Character> table
299         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
300     assertEquals((Character) 'b', table.at(1, 0));
301     assertEquals((Character) 'c', table.at(0, 2));
302     assertNull(table.at(1, 2));
303     try {
304       table.at(1, 3);
305       fail();
306     } catch (IndexOutOfBoundsException expected) {}
307     try {
308       table.at(1, -1);
309       fail();
310     } catch (IndexOutOfBoundsException expected) {}
311     try {
312       table.at(3, 2);
313       fail();
314     } catch (IndexOutOfBoundsException expected) {}
315     try {
316       table.at(-1, 2);
317       fail();
318     } catch (IndexOutOfBoundsException expected) {}
319   }
320 
321   public void testSet() {
322     ArrayTable<String, Integer, Character> table
323         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
324     assertEquals((Character) 'b', table.set(1, 0, 'd'));
325     assertEquals((Character) 'd', table.get("bar", 1));
326     assertNull(table.set(2, 0, 'e'));
327     assertEquals((Character) 'e', table.get("cat", 1));
328     assertEquals((Character) 'a', table.set(0, 0, null));
329     assertNull(table.get("foo", 1));
330     try {
331       table.set(1, 3, 'z');
332       fail();
333     } catch (IndexOutOfBoundsException expected) {}
334     try {
335       table.set(1, -1, 'z');
336       fail();
337     } catch (IndexOutOfBoundsException expected) {}
338     try {
339       table.set(3, 2, 'z');
340       fail();
341     } catch (IndexOutOfBoundsException expected) {}
342     try {
343       table.set(-1, 2, 'z');
344       fail();
345     } catch (IndexOutOfBoundsException expected) {}
346     assertFalse(table.containsValue('z'));
347   }
348 
349   public void testEraseAll() {
350     ArrayTable<String, Integer, Character> table
351         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
352     table.eraseAll();
353     assertEquals(9, table.size());
354     assertNull(table.get("bar", 1));
355     assertTrue(table.containsRow("foo"));
356     assertFalse(table.containsValue('a'));
357   }
358 
359   public void testPutIllegal() {
360     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
361     try {
362       table.put("dog", 1, 'd');
363       fail();
364     } catch (IllegalArgumentException expected) {
365       assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
366     }
367     try {
368       table.put("foo", 4, 'd');
369       fail();
370     } catch (IllegalArgumentException expected) {
371       assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
372     }
373     assertFalse(table.containsValue('d'));
374   }
375 
376   public void testErase() {
377     ArrayTable<String, Integer, Character> table
378         = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
379     assertEquals((Character) 'b', table.erase("bar", 1));
380     assertNull(table.get("bar", 1));
381     assertEquals(9, table.size());
382     assertNull(table.erase("bar", 1));
383     assertNull(table.erase("foo", 2));
384     assertNull(table.erase("dog", 1));
385     assertNull(table.erase("bar", 5));
386     assertNull(table.erase(null, 1));
387     assertNull(table.erase("bar", null));
388   }
389 
390   public void testCellReflectsChanges() {
391     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
392     Cell<String, Integer, Character> cell = table.cellSet().iterator().next();
393     assertEquals(Tables.immutableCell("foo", 1, 'a'), cell);
394     assertEquals((Character) 'a', table.put("foo", 1, 'd'));
395     assertEquals(Tables.immutableCell("foo", 1, 'd'), cell);
396   }
397 
398   public void testRowMissing() {
399     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
400     Map<Integer, Character> row = table.row("dog");
401     assertTrue(row.isEmpty());
402     try {
403       row.put(1, 'd');
404       fail();
405     } catch (UnsupportedOperationException expected) {}
406   }
407 
408   public void testColumnMissing() {
409     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
410     Map<String, Character> column = table.column(4);
411     assertTrue(column.isEmpty());
412     try {
413       column.put("foo", 'd');
414       fail();
415     } catch (UnsupportedOperationException expected) {}
416   }
417 
418   public void testRowPutIllegal() {
419     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
420     Map<Integer, Character> map = table.row("foo");
421     try {
422       map.put(4, 'd');
423       fail();
424     } catch (IllegalArgumentException expected) {
425       assertEquals("Column 4 not in [1, 2, 3]", expected.getMessage());
426     }
427   }
428 
429   public void testColumnPutIllegal() {
430     table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c');
431     Map<String, Character> map = table.column(3);
432     try {
433       map.put("dog", 'd');
434       fail();
435     } catch (IllegalArgumentException expected) {
436       assertEquals("Row dog not in [foo, bar, cat]", expected.getMessage());
437     }
438   }
439 }
440