• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 org.truth0.Truth.ASSERT;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.annotations.GwtIncompatible;
23 
24 /**
25  * Tests common methods in {@link ImmutableTable}
26  *
27  * @author Gregory Kick
28  */
29 @GwtCompatible(emulated = true)
30 public class ImmutableTableTest extends AbstractTableReadTest {
create(Object... data)31   @Override protected Table<String, Integer, Character> create(Object... data) {
32     ImmutableTable.Builder<String, Integer, Character> builder =
33         ImmutableTable.builder();
34     for (int i = 0; i < data.length; i = i + 3) {
35       builder.put((String) data[i], (Integer) data[i + 1],
36           (Character) data[i + 2]);
37     }
38     return builder.build();
39   }
40 
testBuilder()41   public void testBuilder() {
42     ImmutableTable.Builder<Character, Integer, String> builder =
43         new ImmutableTable.Builder<Character, Integer, String>();
44     assertEquals(ImmutableTable.of(), builder.build());
45     assertEquals(ImmutableTable.of('a', 1, "foo"), builder
46         .put('a', 1, "foo")
47         .build());
48     Table<Character, Integer, String> expectedTable = HashBasedTable.create();
49     expectedTable.put('a', 1, "foo");
50     expectedTable.put('b', 1, "bar");
51     expectedTable.put('a', 2, "baz");
52     Table<Character, Integer, String> otherTable = HashBasedTable.create();
53     otherTable.put('b', 1, "bar");
54     otherTable.put('a', 2, "baz");
55     assertEquals(expectedTable, builder
56         .putAll(otherTable)
57         .build());
58   }
59 
testBuilder_withImmutableCell()60   public void testBuilder_withImmutableCell() {
61     ImmutableTable.Builder<Character, Integer, String> builder =
62         new ImmutableTable.Builder<Character, Integer, String>();
63     assertEquals(ImmutableTable.of('a', 1, "foo"), builder
64         .put(Tables.immutableCell('a', 1, "foo"))
65         .build());
66   }
67 
testBuilder_withImmutableCellAndNullContents()68   public void testBuilder_withImmutableCellAndNullContents() {
69     ImmutableTable.Builder<Character, Integer, String> builder =
70         new ImmutableTable.Builder<Character, Integer, String>();
71     try {
72       builder.put(Tables.immutableCell((Character) null, 1, "foo"));
73       fail();
74     } catch (NullPointerException e) {
75       // success
76     }
77     try {
78       builder.put(Tables.immutableCell('a', (Integer) null, "foo"));
79       fail();
80     } catch (NullPointerException e) {
81       // success
82     }
83     try {
84       builder.put(Tables.immutableCell('a', 1, (String) null));
85       fail();
86     } catch (NullPointerException e) {
87       // success
88     }
89   }
90 
91   private static class StringHolder {
92     String string;
93   }
94 
testBuilder_withMutableCell()95   public void testBuilder_withMutableCell() {
96     ImmutableTable.Builder<Character, Integer, String> builder =
97         new ImmutableTable.Builder<Character, Integer, String>();
98 
99     final StringHolder holder = new StringHolder();
100     holder.string = "foo";
101     Table.Cell<Character, Integer, String> mutableCell =
102         new Tables.AbstractCell<Character, Integer, String>() {
103           @Override public Character getRowKey() {
104             return 'K';
105           }
106           @Override public Integer getColumnKey() {
107             return 42;
108           }
109           @Override public String getValue() {
110             return holder.string;
111           }
112         };
113 
114     // Add the mutable cell to the builder
115     builder.put(mutableCell);
116 
117     // Mutate the value
118     holder.string = "bar";
119 
120     // Make sure it uses the original value.
121     assertEquals(ImmutableTable.of('K', 42, "foo"), builder.build());
122   }
123 
testBuilder_noDuplicates()124   public void testBuilder_noDuplicates() {
125     ImmutableTable.Builder<Character, Integer, String> builder =
126         new ImmutableTable.Builder<Character, Integer, String>()
127             .put('a', 1, "foo")
128             .put('a', 1, "bar");
129     try {
130       builder.build();
131       fail();
132     } catch (IllegalArgumentException e) {
133       // success
134     }
135   }
136 
testBuilder_noNulls()137   public void testBuilder_noNulls() {
138     ImmutableTable.Builder<Character, Integer, String> builder =
139         new ImmutableTable.Builder<Character, Integer, String>();
140     try {
141       builder.put(null, 1, "foo");
142       fail();
143     } catch (NullPointerException e) {
144       // success
145     }
146     try {
147       builder.put('a', null, "foo");
148       fail();
149     } catch (NullPointerException e) {
150       // success
151     }
152     try {
153       builder.put('a', 1, null);
154       fail();
155     } catch (NullPointerException e) {
156       // success
157     }
158   }
159 
validateTableCopies(Table<R, C, V> original)160   private static <R, C, V> void validateTableCopies(Table<R, C, V> original) {
161     Table<R, C, V> copy = ImmutableTable.copyOf(original);
162     assertEquals(original, copy);
163     validateViewOrdering(original, copy);
164 
165     Table<R, C, V> built
166         = ImmutableTable.<R, C, V>builder().putAll(original).build();
167     assertEquals(original, built);
168     validateViewOrdering(original, built);
169   }
170 
validateViewOrdering( Table<R, C, V> original, Table<R, C, V> copy)171   private static <R, C, V> void validateViewOrdering(
172       Table<R, C, V> original, Table<R, C, V> copy) {
173     assertTrue(Iterables.elementsEqual(original.cellSet(), copy.cellSet()));
174     assertTrue(Iterables.elementsEqual(original.rowKeySet(), copy.rowKeySet()));
175     assertTrue(Iterables.elementsEqual(original.values(), copy.values()));
176   }
177 
testCopyOf()178   public void testCopyOf() {
179     Table<Character, Integer, String> table = TreeBasedTable.create();
180     validateTableCopies(table);
181     table.put('b', 2, "foo");
182     validateTableCopies(table);
183     table.put('b', 1, "bar");
184     table.put('a', 2, "baz");
185     validateTableCopies(table);
186     // Even though rowKeySet, columnKeySet, and cellSet have the same
187     // iteration ordering, row has an inconsistent ordering.
188     ASSERT.that(table.row('b').keySet()).has().exactly(1, 2).inOrder();
189     ASSERT.that(ImmutableTable.copyOf(table).row('b').keySet())
190         .has().exactly(2, 1).inOrder();
191   }
192 
testCopyOfSparse()193   public void testCopyOfSparse() {
194     Table<Character, Integer, String> table = TreeBasedTable.create();
195     table.put('x', 2, "foo");
196     table.put('r', 1, "bar");
197     table.put('c', 3, "baz");
198     table.put('b', 7, "cat");
199     table.put('e', 5, "dog");
200     table.put('c', 0, "axe");
201     table.put('e', 3, "tub");
202     table.put('r', 4, "foo");
203     table.put('x', 5, "bar");
204     validateTableCopies(table);
205   }
206 
testCopyOfDense()207   public void testCopyOfDense() {
208     Table<Character, Integer, String> table = TreeBasedTable.create();
209     table.put('c', 3, "foo");
210     table.put('c', 2, "bar");
211     table.put('c', 1, "baz");
212     table.put('b', 3, "cat");
213     table.put('b', 1, "dog");
214     table.put('a', 3, "foo");
215     table.put('a', 2, "bar");
216     table.put('a', 1, "baz");
217     validateTableCopies(table);
218   }
219 
testBuilder_orderRowsAndColumnsBy_putAll()220   public void testBuilder_orderRowsAndColumnsBy_putAll() {
221     Table<Character, Integer, String> table = HashBasedTable.create();
222     table.put('b', 2, "foo");
223     table.put('b', 1, "bar");
224     table.put('a', 2, "baz");
225     ImmutableTable.Builder<Character, Integer, String> builder
226         = ImmutableTable.builder();
227     Table<Character, Integer, String> copy
228         = builder.orderRowsBy(Ordering.natural())
229             .orderColumnsBy(Ordering.natural())
230             .putAll(table).build();
231     ASSERT.that(copy.rowKeySet()).has().exactly('a', 'b').inOrder();
232     ASSERT.that(copy.columnKeySet()).has().exactly(1, 2).inOrder();
233     ASSERT.that(copy.values()).has().exactly("baz", "bar", "foo").inOrder();
234     ASSERT.that(copy.row('b').keySet()).has().exactly(1, 2).inOrder();
235   }
236 
testBuilder_orderRowsAndColumnsBy_sparse()237   public void testBuilder_orderRowsAndColumnsBy_sparse() {
238     ImmutableTable.Builder<Character, Integer, String> builder
239         = ImmutableTable.builder();
240     builder.orderRowsBy(Ordering.natural());
241     builder.orderColumnsBy(Ordering.natural());
242     builder.put('x', 2, "foo");
243     builder.put('r', 1, "bar");
244     builder.put('c', 3, "baz");
245     builder.put('b', 7, "cat");
246     builder.put('e', 5, "dog");
247     builder.put('c', 0, "axe");
248     builder.put('e', 3, "tub");
249     builder.put('r', 4, "foo");
250     builder.put('x', 5, "bar");
251     Table<Character, Integer, String> table = builder.build();
252     ASSERT.that(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
253     ASSERT.that(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
254     ASSERT.that(table.values()).has().exactly("cat", "axe", "baz", "tub",
255         "dog", "bar", "foo", "foo", "bar").inOrder();
256     ASSERT.that(table.row('c').keySet()).has().exactly(0, 3).inOrder();
257     ASSERT.that(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
258   }
259 
testBuilder_orderRowsAndColumnsBy_dense()260   public void testBuilder_orderRowsAndColumnsBy_dense() {
261     ImmutableTable.Builder<Character, Integer, String> builder
262         = ImmutableTable.builder();
263     builder.orderRowsBy(Ordering.natural());
264     builder.orderColumnsBy(Ordering.natural());
265     builder.put('c', 3, "foo");
266     builder.put('c', 2, "bar");
267     builder.put('c', 1, "baz");
268     builder.put('b', 3, "cat");
269     builder.put('b', 1, "dog");
270     builder.put('a', 3, "foo");
271     builder.put('a', 2, "bar");
272     builder.put('a', 1, "baz");
273     Table<Character, Integer, String> table = builder.build();
274     ASSERT.that(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
275     ASSERT.that(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
276     ASSERT.that(table.values()).has().exactly("baz", "bar", "foo", "dog",
277         "cat", "baz", "bar", "foo").inOrder();
278     ASSERT.that(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
279     ASSERT.that(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
280   }
281 
testBuilder_orderRowsBy_sparse()282   public void testBuilder_orderRowsBy_sparse() {
283     ImmutableTable.Builder<Character, Integer, String> builder
284         = ImmutableTable.builder();
285     builder.orderRowsBy(Ordering.natural());
286     builder.put('x', 2, "foo");
287     builder.put('r', 1, "bar");
288     builder.put('c', 3, "baz");
289     builder.put('b', 7, "cat");
290     builder.put('e', 5, "dog");
291     builder.put('c', 0, "axe");
292     builder.put('e', 3, "tub");
293     builder.put('r', 4, "foo");
294     builder.put('x', 5, "bar");
295     Table<Character, Integer, String> table = builder.build();
296     ASSERT.that(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
297     ASSERT.that(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
298   }
299 
testBuilder_orderRowsBy_dense()300   public void testBuilder_orderRowsBy_dense() {
301     ImmutableTable.Builder<Character, Integer, String> builder
302         = ImmutableTable.builder();
303     builder.orderRowsBy(Ordering.natural());
304     builder.put('c', 3, "foo");
305     builder.put('c', 2, "bar");
306     builder.put('c', 1, "baz");
307     builder.put('b', 3, "cat");
308     builder.put('b', 1, "dog");
309     builder.put('a', 3, "foo");
310     builder.put('a', 2, "bar");
311     builder.put('a', 1, "baz");
312     Table<Character, Integer, String> table = builder.build();
313     ASSERT.that(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
314     ASSERT.that(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
315   }
316 
testBuilder_orderColumnsBy_sparse()317   public void testBuilder_orderColumnsBy_sparse() {
318     ImmutableTable.Builder<Character, Integer, String> builder
319         = ImmutableTable.builder();
320     builder.orderColumnsBy(Ordering.natural());
321     builder.put('x', 2, "foo");
322     builder.put('r', 1, "bar");
323     builder.put('c', 3, "baz");
324     builder.put('b', 7, "cat");
325     builder.put('e', 5, "dog");
326     builder.put('c', 0, "axe");
327     builder.put('e', 3, "tub");
328     builder.put('r', 4, "foo");
329     builder.put('x', 5, "bar");
330     Table<Character, Integer, String> table = builder.build();
331     ASSERT.that(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
332     ASSERT.that(table.row('c').keySet()).has().exactly(0, 3).inOrder();
333   }
334 
testBuilder_orderColumnsBy_dense()335   public void testBuilder_orderColumnsBy_dense() {
336     ImmutableTable.Builder<Character, Integer, String> builder
337         = ImmutableTable.builder();
338     builder.orderColumnsBy(Ordering.natural());
339     builder.put('c', 3, "foo");
340     builder.put('c', 2, "bar");
341     builder.put('c', 1, "baz");
342     builder.put('b', 3, "cat");
343     builder.put('b', 1, "dog");
344     builder.put('a', 3, "foo");
345     builder.put('a', 2, "bar");
346     builder.put('a', 1, "baz");
347     Table<Character, Integer, String> table = builder.build();
348     ASSERT.that(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
349     ASSERT.that(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
350   }
351 
352   @GwtIncompatible("Mind-bogglingly slow in GWT")
testOverflowCondition()353   public void testOverflowCondition() {
354     // See https://code.google.com/p/guava-libraries/issues/detail?id=1322 for details.
355     ImmutableTable.Builder<Integer, Integer, String> builder = ImmutableTable.builder();
356     for (int i = 1; i < 0x10000; i++) {
357       builder.put(i, 0, "foo");
358       builder.put(0, i, "bar");
359     }
360     assertTrue(builder.build() instanceof SparseImmutableTable);
361   }
362 }
363