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