Home | History | Annotate | Download | only in collect
      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 
     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 {
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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     assertThat(table.row('b').keySet()).has().exactly(1, 2).inOrder();
    189     assertThat(ImmutableTable.copyOf(table).row('b').keySet())
    190         .has().exactly(2, 1).inOrder();
    191   }
    192 
    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 
    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 
    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     assertThat(copy.rowKeySet()).has().exactly('a', 'b').inOrder();
    232     assertThat(copy.columnKeySet()).has().exactly(1, 2).inOrder();
    233     assertThat(copy.values()).has().exactly("baz", "bar", "foo").inOrder();
    234     assertThat(copy.row('b').keySet()).has().exactly(1, 2).inOrder();
    235   }
    236 
    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     assertThat(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
    253     assertThat(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
    254     assertThat(table.values()).has().exactly("cat", "axe", "baz", "tub",
    255         "dog", "bar", "foo", "foo", "bar").inOrder();
    256     assertThat(table.row('c').keySet()).has().exactly(0, 3).inOrder();
    257     assertThat(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
    258   }
    259 
    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     assertThat(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
    275     assertThat(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
    276     assertThat(table.values()).has().exactly("baz", "bar", "foo", "dog",
    277         "cat", "baz", "bar", "foo").inOrder();
    278     assertThat(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
    279     assertThat(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
    280   }
    281 
    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     assertThat(table.rowKeySet()).has().exactly('b', 'c', 'e', 'r', 'x').inOrder();
    297     assertThat(table.column(5).keySet()).has().exactly('e', 'x').inOrder();
    298   }
    299 
    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     assertThat(table.rowKeySet()).has().exactly('a', 'b', 'c').inOrder();
    314     assertThat(table.column(1).keySet()).has().exactly('a', 'b', 'c').inOrder();
    315   }
    316 
    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     assertThat(table.columnKeySet()).has().exactly(0, 1, 2, 3, 4, 5, 7).inOrder();
    332     assertThat(table.row('c').keySet()).has().exactly(0, 3).inOrder();
    333   }
    334 
    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     assertThat(table.columnKeySet()).has().exactly(1, 2, 3).inOrder();
    349     assertThat(table.row('c').keySet()).has().exactly(1, 2, 3).inOrder();
    350   }
    351 
    352   @GwtIncompatible("Mind-bogglingly slow in GWT")
    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