Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2008 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.base.Preconditions.checkNotNull;
     20 
     21 import com.google.common.annotations.GwtCompatible;
     22 import com.google.common.annotations.GwtIncompatible;
     23 import com.google.common.base.Function;
     24 import com.google.common.base.Functions;
     25 import com.google.common.collect.Table.Cell;
     26 import com.google.common.collect.testing.CollectionTestSuiteBuilder;
     27 import com.google.common.collect.testing.MapInterfaceTest;
     28 import com.google.common.collect.testing.SampleElements;
     29 import com.google.common.collect.testing.SetTestSuiteBuilder;
     30 import com.google.common.collect.testing.SortedSetTestSuiteBuilder;
     31 import com.google.common.collect.testing.TestSetGenerator;
     32 import com.google.common.collect.testing.TestStringCollectionGenerator;
     33 import com.google.common.collect.testing.TestStringSetGenerator;
     34 import com.google.common.collect.testing.TestStringSortedSetGenerator;
     35 import com.google.common.collect.testing.features.CollectionFeature;
     36 import com.google.common.collect.testing.features.CollectionSize;
     37 import com.google.common.collect.testing.features.Feature;
     38 
     39 import junit.framework.Test;
     40 import junit.framework.TestCase;
     41 import junit.framework.TestSuite;
     42 
     43 import java.util.Arrays;
     44 import java.util.Collection;
     45 import java.util.Collections;
     46 import java.util.List;
     47 import java.util.Map;
     48 import java.util.Set;
     49 import java.util.SortedMap;
     50 import java.util.SortedSet;
     51 
     52 /**
     53  * Collection tests for {@link Table} implementations.
     54  *
     55  * @author Jared Levy
     56  * @author Louis Wasserman
     57  */
     58 @GwtCompatible(emulated = true)
     59 public class TableCollectionTest extends TestCase {
     60 
     61   private static final Feature<?>[] COLLECTION_FEATURES = {
     62     CollectionSize.ANY,
     63     CollectionFeature.ALLOWS_NULL_QUERIES
     64   };
     65 
     66   private static final Feature<?>[] COLLECTION_FEATURES_ORDER = {
     67     CollectionSize.ANY,
     68     CollectionFeature.KNOWN_ORDER,
     69     CollectionFeature.ALLOWS_NULL_QUERIES
     70   };
     71 
     72   private static final Feature<?>[] COLLECTION_FEATURES_REMOVE = {
     73     CollectionSize.ANY,
     74     CollectionFeature.SUPPORTS_REMOVE,
     75     CollectionFeature.ALLOWS_NULL_QUERIES
     76   };
     77 
     78   private static final Feature<?>[] COLLECTION_FEATURES_REMOVE_ORDER = {
     79     CollectionSize.ANY,
     80     CollectionFeature.KNOWN_ORDER,
     81     CollectionFeature.SUPPORTS_REMOVE,
     82     CollectionFeature.ALLOWS_NULL_QUERIES
     83   };
     84 
     85   @GwtIncompatible("suite")
     86   public static Test suite() {
     87     TestSuite suite = new TestSuite();
     88     suite.addTestSuite(ArrayRowTests.class);
     89     suite.addTestSuite(HashRowTests.class);
     90     suite.addTestSuite(TreeRowTests.class);
     91     suite.addTestSuite(TransposeRowTests.class);
     92     suite.addTestSuite(TransformValueRowTests.class);
     93     suite.addTestSuite(UnmodifiableHashRowTests.class);
     94     suite.addTestSuite(UnmodifiableTreeRowTests.class);
     95     suite.addTestSuite(ArrayColumnTests.class);
     96     suite.addTestSuite(HashColumnTests.class);
     97     suite.addTestSuite(TreeColumnTests.class);
     98     suite.addTestSuite(TransposeColumnTests.class);
     99     suite.addTestSuite(TransformValueColumnTests.class);
    100     suite.addTestSuite(UnmodifiableHashColumnTests.class);
    101     suite.addTestSuite(UnmodifiableTreeColumnTests.class);
    102     suite.addTestSuite(ArrayRowMapTests.class);
    103     suite.addTestSuite(HashRowMapTests.class);
    104     suite.addTestSuite(TreeRowMapTests.class);
    105     suite.addTestSuite(TreeRowMapHeadMapTests.class);
    106     suite.addTestSuite(TreeRowMapTailMapTests.class);
    107     suite.addTestSuite(TreeRowMapSubMapTests.class);
    108     suite.addTestSuite(TransformValueRowMapTests.class);
    109     suite.addTestSuite(UnmodifiableHashRowMapTests.class);
    110     suite.addTestSuite(UnmodifiableTreeRowMapTests.class);
    111     suite.addTestSuite(ArrayColumnMapTests.class);
    112     suite.addTestSuite(HashColumnMapTests.class);
    113     suite.addTestSuite(TreeColumnMapTests.class);
    114     suite.addTestSuite(TransformValueColumnMapTests.class);
    115     suite.addTestSuite(UnmodifiableHashColumnMapTests.class);
    116     suite.addTestSuite(UnmodifiableTreeColumnMapTests.class);
    117 
    118     // Not testing rowKeySet() or columnKeySet() of Table.transformValues()
    119     // since the transformation doesn't affect the row and column key sets.
    120 
    121     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    122           @Override protected Set<String> create(String[] elements) {
    123             Table<String, Integer, Character> table
    124                 = ArrayTable.create(
    125                     ImmutableList.copyOf(elements), ImmutableList.of(1, 2));
    126             populateForRowKeySet(table, elements);
    127             return table.rowKeySet();
    128           }
    129         })
    130         .named("ArrayTable.rowKeySet")
    131         .withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL,
    132             CollectionFeature.KNOWN_ORDER,
    133             CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
    134             CollectionFeature.ALLOWS_NULL_QUERIES)
    135         .createTestSuite());
    136 
    137     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    138           @Override protected Set<String> create(String[] elements) {
    139             Table<String, Integer, Character> table = HashBasedTable.create();
    140             populateForRowKeySet(table, elements);
    141             return table.rowKeySet();
    142           }
    143         })
    144         .named("HashBasedTable.rowKeySet")
    145         .withFeatures(COLLECTION_FEATURES_REMOVE)
    146         .withFeatures(CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    147         .createTestSuite());
    148 
    149     suite.addTest(SortedSetTestSuiteBuilder.using(new TestStringSortedSetGenerator() {
    150           @Override protected SortedSet<String> create(String[] elements) {
    151             TreeBasedTable<String, Integer, Character> table = TreeBasedTable.create();
    152             populateForRowKeySet(table, elements);
    153             return table.rowKeySet();
    154           }
    155 
    156           @Override public List<String> order(List<String> insertionOrder) {
    157             Collections.sort(insertionOrder);
    158             return insertionOrder;
    159           }
    160         })
    161         .named("TreeBasedTable.rowKeySet")
    162         .withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
    163         .withFeatures(CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    164         .createTestSuite());
    165 
    166     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    167           @Override protected Set<String> create(String[] elements) {
    168             Table<String, Integer, Character> table = HashBasedTable.create();
    169             populateForRowKeySet(table, elements);
    170             return Tables.unmodifiableTable(table).rowKeySet();
    171           }
    172         })
    173         .named("unmodifiableTable[HashBasedTable].rowKeySet")
    174         .withFeatures(COLLECTION_FEATURES)
    175         .createTestSuite());
    176 
    177     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    178           @Override protected Set<String> create(String[] elements) {
    179             RowSortedTable<String, Integer, Character> table = TreeBasedTable.create();
    180             populateForRowKeySet(table, elements);
    181             return Tables.unmodifiableRowSortedTable(table).rowKeySet();
    182           }
    183 
    184           @Override public List<String> order(List<String> insertionOrder) {
    185             Collections.sort(insertionOrder);
    186             return insertionOrder;
    187           }
    188         })
    189         .named("unmodifiableRowSortedTable[TreeBasedTable].rowKeySet")
    190         .withFeatures(COLLECTION_FEATURES_ORDER)
    191         .createTestSuite());
    192 
    193     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    194           @Override protected Set<String> create(String[] elements) {
    195             Table<Integer, String, Character> table
    196                 = ArrayTable.create(
    197                     ImmutableList.of(1, 2), ImmutableList.copyOf(elements));
    198             populateForColumnKeySet(table, elements);
    199             return table.columnKeySet();
    200           }
    201         })
    202         .named("ArrayTable.columnKeySet")
    203         .withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL,
    204             CollectionFeature.KNOWN_ORDER,
    205             CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
    206             CollectionFeature.ALLOWS_NULL_QUERIES)
    207         .createTestSuite());
    208 
    209     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    210           @Override protected Set<String> create(String[] elements) {
    211             Table<Integer, String, Character> table = HashBasedTable.create();
    212             populateForColumnKeySet(table, elements);
    213             return table.columnKeySet();
    214           }
    215         })
    216         .named("HashBasedTable.columnKeySet")
    217         .withFeatures(COLLECTION_FEATURES_REMOVE)
    218         .createTestSuite());
    219 
    220     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    221           @Override protected Set<String> create(String[] elements) {
    222             Table<Integer, String, Character> table = TreeBasedTable.create();
    223             populateForColumnKeySet(table, elements);
    224             return table.columnKeySet();
    225           }
    226 
    227           @Override public List<String> order(List<String> insertionOrder) {
    228             Collections.sort(insertionOrder);
    229             return insertionOrder;
    230           }
    231         })
    232         .named("TreeBasedTable.columnKeySet")
    233         .withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
    234         .createTestSuite());
    235 
    236     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    237           @Override protected Set<String> create(String[] elements) {
    238             Table<Integer, String, Character> table = HashBasedTable.create();
    239             populateForColumnKeySet(table, elements);
    240             return Tables.unmodifiableTable(table).columnKeySet();
    241           }
    242         })
    243         .named("unmodifiableTable[HashBasedTable].columnKeySet")
    244         .withFeatures(COLLECTION_FEATURES)
    245         .createTestSuite());
    246 
    247     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    248           @Override protected Set<String> create(String[] elements) {
    249             RowSortedTable<Integer, String, Character> table = TreeBasedTable.create();
    250             populateForColumnKeySet(table, elements);
    251             return Tables.unmodifiableRowSortedTable(table).columnKeySet();
    252           }
    253 
    254           @Override public List<String> order(List<String> insertionOrder) {
    255             Collections.sort(insertionOrder);
    256             return insertionOrder;
    257           }
    258         })
    259         .named("unmodifiableRowSortedTable[TreeBasedTable].columnKeySet")
    260         .withFeatures(COLLECTION_FEATURES_ORDER)
    261         .createTestSuite());
    262 
    263     suite.addTest(CollectionTestSuiteBuilder.using(
    264         new TestStringCollectionGenerator() {
    265           @Override protected Collection<String> create(String[] elements) {
    266             List<Integer> rowKeys = Lists.newArrayList();
    267             for (int i = 0; i < elements.length; i++) {
    268               rowKeys.add(i);
    269             }
    270             Table<Integer, Character, String> table
    271                 = ArrayTable.create(rowKeys, ImmutableList.of('a'));
    272             populateForValues(table, elements);
    273             return table.values();
    274           }
    275         })
    276         .named("ArrayTable.values")
    277         .withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL,
    278             CollectionFeature.ALLOWS_NULL_VALUES,
    279             CollectionFeature.KNOWN_ORDER)
    280         .createTestSuite());
    281 
    282     suite.addTest(CollectionTestSuiteBuilder.using(
    283         new TestStringCollectionGenerator() {
    284           @Override protected Collection<String> create(String[] elements) {
    285             Table<Integer, Character, String> table = HashBasedTable.create();
    286             table.put(1, 'a', "foo");
    287             table.clear();
    288             populateForValues(table, elements);
    289             return table.values();
    290           }
    291         })
    292         .named("HashBasedTable.values")
    293         .withFeatures(COLLECTION_FEATURES_REMOVE)
    294         .withFeatures(CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    295         .createTestSuite());
    296 
    297     suite.addTest(CollectionTestSuiteBuilder.using(
    298         new TestStringCollectionGenerator() {
    299           @Override protected Collection<String> create(String[] elements) {
    300             Table<Integer, Character, String> table = TreeBasedTable.create();
    301             table.put(1, 'a', "foo");
    302             table.clear();
    303             populateForValues(table, elements);
    304             return table.values();
    305           }
    306         })
    307         .named("TreeBasedTable.values")
    308         .withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
    309         .withFeatures(CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    310         .createTestSuite());
    311 
    312     final Function<String, String> removeFirstCharacter
    313         = new Function<String, String>() {
    314           @Override public String apply(String input) {
    315             return input.substring(1);
    316           }
    317         };
    318 
    319     suite.addTest(CollectionTestSuiteBuilder.using(
    320         new TestStringCollectionGenerator() {
    321           @Override protected Collection<String> create(String[] elements) {
    322             Table<Integer, Character, String> table = HashBasedTable.create();
    323             for (int i = 0; i < elements.length; i++) {
    324               table.put(i, 'a', "x" + checkNotNull(elements[i]));
    325             }
    326             return Tables.transformValues(table, removeFirstCharacter).values();
    327           }
    328         })
    329         .named("TransformValues.values")
    330         .withFeatures(COLLECTION_FEATURES_REMOVE)
    331         .withFeatures(CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    332         .createTestSuite());
    333 
    334     suite.addTest(CollectionTestSuiteBuilder.using(
    335         new TestStringCollectionGenerator() {
    336           @Override protected Collection<String> create(String[] elements) {
    337             Table<Integer, Character, String> table = HashBasedTable.create();
    338             table.put(1, 'a', "foo");
    339             table.clear();
    340             populateForValues(table, elements);
    341             return Tables.unmodifiableTable(table).values();
    342           }
    343         })
    344         .named("unmodifiableTable[HashBasedTable].values")
    345         .withFeatures(COLLECTION_FEATURES)
    346         .createTestSuite());
    347 
    348     suite.addTest(CollectionTestSuiteBuilder.using(
    349         new TestStringCollectionGenerator() {
    350           @Override protected Collection<String> create(String[] elements) {
    351             RowSortedTable<Integer, Character, String> table = TreeBasedTable.create();
    352             table.put(1, 'a', "foo");
    353             table.clear();
    354             populateForValues(table, elements);
    355             return Tables.unmodifiableRowSortedTable(table).values();
    356           }
    357         })
    358         .named("unmodifiableTable[TreeBasedTable].values")
    359         .withFeatures(COLLECTION_FEATURES_ORDER)
    360         .createTestSuite());
    361 
    362     suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
    363           @Override public SampleElements<Cell<String, Integer, Character>>
    364               samples() {
    365             return new SampleElements<Cell<String, Integer, Character>>(
    366                 Tables.immutableCell("bar", 1, 'a'),
    367                 Tables.immutableCell("bar", 2, 'b'),
    368                 Tables.immutableCell("bar", 3, (Character) null),
    369                 Tables.immutableCell("bar", 4, 'b'),
    370                 Tables.immutableCell("bar", 5, 'b'));
    371           }
    372           @Override public Set<Cell<String, Integer, Character>> create(
    373               Object... elements) {
    374             List<Integer> columnKeys = Lists.newArrayList();
    375             for (Object element : elements) {
    376               @SuppressWarnings("unchecked")
    377               Cell<String, Integer, Character> cell
    378                   = (Cell<String, Integer, Character>) element;
    379               columnKeys.add(cell.getColumnKey());
    380             }
    381             Table<String, Integer, Character> table
    382                 = ArrayTable.create(ImmutableList.of("bar"), columnKeys);
    383             for (Object element : elements) {
    384               @SuppressWarnings("unchecked")
    385               Cell<String, Integer, Character> cell
    386                   = (Cell<String, Integer, Character>) element;
    387               table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
    388             }
    389             return table.cellSet();
    390           }
    391           @Override Table<String, Integer, Character> createTable() {
    392             throw new UnsupportedOperationException();
    393           }
    394         })
    395         .named("ArrayTable.cellSet")
    396         .withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL,
    397             CollectionFeature.KNOWN_ORDER,
    398             CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
    399             CollectionFeature.ALLOWS_NULL_QUERIES)
    400         .createTestSuite());
    401 
    402     suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
    403           @Override Table<String, Integer, Character> createTable() {
    404             return HashBasedTable.create();
    405           }
    406         })
    407         .named("HashBasedTable.cellSet")
    408         .withFeatures(CollectionSize.ANY, CollectionFeature.REMOVE_OPERATIONS,
    409             CollectionFeature.ALLOWS_NULL_QUERIES)
    410         .createTestSuite());
    411 
    412     suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
    413           @Override Table<String, Integer, Character> createTable() {
    414             return TreeBasedTable.create();
    415           }
    416         })
    417         .named("TreeBasedTable.cellSet")
    418         .withFeatures(CollectionSize.ANY, CollectionFeature.REMOVE_OPERATIONS,
    419             CollectionFeature.ALLOWS_NULL_QUERIES)
    420         .createTestSuite());
    421 
    422     suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
    423           @Override Table<String, Integer, Character> createTable() {
    424             Table<Integer, String, Character> original
    425                 = TreeBasedTable.create();
    426             return Tables.transpose(original);
    427           }
    428         })
    429         .named("TransposedTable.cellSet")
    430         .withFeatures(CollectionSize.ANY, CollectionFeature.REMOVE_OPERATIONS,
    431             CollectionFeature.ALLOWS_NULL_QUERIES)
    432         .createTestSuite());
    433 
    434     suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
    435           @Override Table<String, Integer, Character> createTable() {
    436             return HashBasedTable.create();
    437           }
    438           @Override
    439           public Set<Cell<String, Integer, Character>> create(
    440               Object... elements) {
    441             Table<String, Integer, Character> table = createTable();
    442             for (Object element : elements) {
    443               @SuppressWarnings("unchecked")
    444               Cell<String, Integer, Character> cell
    445                   = (Cell<String, Integer, Character>) element;
    446               table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
    447             }
    448             return Tables.transformValues(table, Functions.<Character>identity()).cellSet();
    449           }
    450         })
    451         .named("TransformValues.cellSet")
    452         .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES,
    453             CollectionFeature.REMOVE_OPERATIONS)
    454         .createTestSuite());
    455 
    456     suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
    457           @Override Table<String, Integer, Character> createTable() {
    458             return Tables.unmodifiableTable(HashBasedTable.<String, Integer, Character> create());
    459           }
    460           @Override
    461           public Set<Cell<String, Integer, Character>> create(
    462               Object... elements) {
    463             Table<String, Integer, Character> table = HashBasedTable.create();
    464             for (Object element : elements) {
    465               @SuppressWarnings("unchecked")
    466               Cell<String, Integer, Character> cell
    467                   = (Cell<String, Integer, Character>) element;
    468               table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
    469             }
    470             return Tables.unmodifiableTable(table).cellSet();
    471           }
    472         })
    473         .named("unmodifiableTable[HashBasedTable].cellSet")
    474         .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES)
    475         .createTestSuite());
    476 
    477     suite.addTest(SetTestSuiteBuilder.using(new TestCellSetGenerator() {
    478           @Override RowSortedTable<String, Integer, Character> createTable() {
    479             return Tables.unmodifiableRowSortedTable(TreeBasedTable
    480                 .<String, Integer, Character> create());
    481           }
    482           @Override
    483           public Set<Cell<String, Integer, Character>> create(
    484               Object... elements) {
    485             RowSortedTable<String, Integer, Character> table = TreeBasedTable.create();
    486             for (Object element : elements) {
    487               @SuppressWarnings("unchecked")
    488               Cell<String, Integer, Character> cell
    489                   = (Cell<String, Integer, Character>) element;
    490               table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
    491             }
    492             return Tables.unmodifiableRowSortedTable(table).cellSet();
    493           }
    494         })
    495         .named("unmodifiableRowSortedTable[TreeBasedTable].cellSet")
    496         .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES)
    497         .createTestSuite());
    498 
    499     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    500           @Override protected Set<String> create(String[] elements) {
    501             Iterable<String> rowKeys = ImmutableSet.copyOf(elements);
    502             Iterable<Integer> columnKeys = ImmutableList.of(1, 2, 3);
    503             Table<String, Integer, Character> table
    504                 = ArrayTable.create(rowKeys, columnKeys);
    505             populateForRowKeySet(table, elements);
    506             return table.column(1).keySet();
    507           }
    508         })
    509         .named("ArrayTable.column.keySet")
    510         .withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL,
    511             CollectionFeature.KNOWN_ORDER,
    512             CollectionFeature.ALLOWS_NULL_QUERIES)
    513         .createTestSuite());
    514 
    515     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    516           @Override protected Set<String> create(String[] elements) {
    517             Table<String, Integer, Character> table = HashBasedTable.create();
    518             populateForRowKeySet(table, elements);
    519             return table.column(1).keySet();
    520           }
    521         })
    522         .named("HashBasedTable.column.keySet")
    523         .withFeatures(COLLECTION_FEATURES_REMOVE)
    524     .createTestSuite());
    525 
    526     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    527           @Override protected Set<String> create(String[] elements) {
    528             Table<String, Integer, Character> table = TreeBasedTable.create();
    529             populateForRowKeySet(table, elements);
    530             return table.column(1).keySet();
    531           }
    532           @Override public List<String> order(List<String> insertionOrder) {
    533             Collections.sort(insertionOrder);
    534             return insertionOrder;
    535           }
    536         })
    537         .named("TreeBasedTable.column.keySet")
    538         .withFeatures(COLLECTION_FEATURES_REMOVE_ORDER)
    539         .createTestSuite());
    540 
    541     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    542           @Override protected Set<String> create(String[] elements) {
    543             Table<String, Integer, Character> table = HashBasedTable.create();
    544             populateForRowKeySet(table, elements);
    545             return Tables.transformValues(table, Functions.toStringFunction()).column(1).keySet();
    546           }
    547         })
    548         .named("TransformValues.column.keySet")
    549         .withFeatures(COLLECTION_FEATURES_REMOVE)
    550     .createTestSuite());
    551 
    552     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    553           @Override protected Set<String> create(String[] elements) {
    554             Table<String, Integer, Character> table = HashBasedTable.create();
    555             populateForRowKeySet(table, elements);
    556             return Tables.unmodifiableTable(table).column(1).keySet();
    557           }
    558         })
    559         .named("unmodifiableTable[HashBasedTable].column.keySet")
    560         .withFeatures(COLLECTION_FEATURES)
    561     .createTestSuite());
    562 
    563     suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
    564           @Override protected Set<String> create(String[] elements) {
    565             RowSortedTable<String, Integer, Character> table = TreeBasedTable.create();
    566             populateForRowKeySet(table, elements);
    567             return Tables.unmodifiableRowSortedTable(table).column(1).keySet();
    568           }
    569           @Override public List<String> order(List<String> insertionOrder) {
    570             Collections.sort(insertionOrder);
    571             return insertionOrder;
    572           }
    573         })
    574         .named("unmodifiableRowSortedTable[TreeBasedTable].column.keySet")
    575         .withFeatures(COLLECTION_FEATURES_ORDER)
    576         .createTestSuite());
    577 
    578     return suite;
    579   }
    580 
    581   private static void populateForRowKeySet(
    582       Table<String, Integer, Character> table, String[] elements) {
    583     for (String row : elements) {
    584       table.put(row, 1, 'a');
    585       table.put(row, 2, 'b');
    586     }
    587   }
    588 
    589   private static void populateForColumnKeySet(
    590       Table<Integer, String, Character> table, String[] elements) {
    591     for (String column : elements) {
    592       table.put(1, column, 'a');
    593       table.put(2, column, 'b');
    594     }
    595   }
    596 
    597   private static void populateForValues(
    598       Table<Integer, Character, String> table, String[] elements) {
    599     for (int i = 0; i < elements.length; i++) {
    600       table.put(i, 'a', elements[i]);
    601     }
    602   }
    603 
    604   private static abstract class TestCellSetGenerator
    605       implements TestSetGenerator<Cell<String, Integer, Character>> {
    606     @Override
    607     public SampleElements<Cell<String, Integer, Character>> samples() {
    608       return new SampleElements<Cell<String, Integer, Character>>(
    609           Tables.immutableCell("bar", 1, 'a'),
    610           Tables.immutableCell("bar", 2, 'b'),
    611           Tables.immutableCell("foo", 3, 'c'),
    612           Tables.immutableCell("bar", 1, 'b'),
    613           Tables.immutableCell("cat", 2, 'b'));
    614     }
    615 
    616     @Override
    617     public Set<Cell<String, Integer, Character>> create(
    618         Object... elements) {
    619       Table<String, Integer, Character> table = createTable();
    620       for (Object element : elements) {
    621         @SuppressWarnings("unchecked")
    622         Cell<String, Integer, Character> cell
    623             = (Cell<String, Integer, Character>) element;
    624         table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
    625       }
    626       return table.cellSet();
    627     }
    628 
    629     abstract Table<String, Integer, Character> createTable();
    630 
    631     @Override
    632     @SuppressWarnings("unchecked")
    633     public Cell<String, Integer, Character>[] createArray(int length) {
    634       return (Cell<String, Integer, Character>[]) new Cell<?, ?, ?>[length];
    635     }
    636 
    637     @Override
    638     public List<Cell<String, Integer, Character>> order(
    639         List<Cell<String, Integer, Character>> insertionOrder) {
    640       return insertionOrder;
    641     }
    642   }
    643 
    644   private static abstract class MapTests
    645       extends MapInterfaceTest<String, Integer> {
    646 
    647     MapTests(boolean allowsNullValues, boolean supportsPut, boolean supportsRemove,
    648         boolean supportsClear, boolean supportsIteratorRemove) {
    649       super(false, allowsNullValues, supportsPut, supportsRemove, supportsClear,
    650           supportsIteratorRemove);
    651     }
    652 
    653     @Override protected String getKeyNotInPopulatedMap() {
    654       return "four";
    655     }
    656 
    657     @Override protected Integer getValueNotInPopulatedMap() {
    658       return 4;
    659     }
    660   }
    661 
    662   private static abstract class RowTests extends MapTests {
    663     RowTests(boolean allowsNullValues, boolean supportsPut, boolean supportsRemove,
    664         boolean supportsClear, boolean supportsIteratorRemove) {
    665       super(allowsNullValues, supportsPut, supportsRemove, supportsClear,
    666           supportsIteratorRemove);
    667     }
    668 
    669     abstract Table<Character, String, Integer> makeTable();
    670 
    671     @Override protected Map<String, Integer> makeEmptyMap() {
    672       return makeTable().row('a');
    673     }
    674 
    675     @Override protected Map<String, Integer> makePopulatedMap() {
    676       Table<Character, String, Integer> table = makeTable();
    677       table.put('a', "one", 1);
    678       table.put('a', "two", 2);
    679       table.put('a', "three", 3);
    680       table.put('b', "four", 4);
    681       return table.row('a');
    682     }
    683   }
    684 
    685   @GwtIncompatible("TODO(hhchan): ArrayTable")
    686   public static class ArrayRowTests extends RowTests {
    687     public ArrayRowTests() {
    688       super(true, true, false, false, false);
    689     }
    690 
    691     @Override protected String getKeyNotInPopulatedMap() {
    692       throw new UnsupportedOperationException();
    693     }
    694 
    695     @Override protected Map<String, Integer> makeEmptyMap() {
    696       throw new UnsupportedOperationException();
    697     }
    698 
    699     @Override protected Table<Character, String, Integer> makeTable() {
    700       return ArrayTable.create(Arrays.asList('a', 'b', 'c'),
    701           Arrays.asList("one", "two", "three", "four"));
    702     }
    703   }
    704 
    705   public static class HashRowTests extends RowTests {
    706     public HashRowTests() {
    707       super(false, true, true, true, true);
    708     }
    709 
    710     @Override Table<Character, String, Integer> makeTable() {
    711       return HashBasedTable.create();
    712     }
    713   }
    714 
    715   public static class TreeRowTests extends RowTests {
    716     public TreeRowTests() {
    717       super(false, true, true, true, true);
    718     }
    719 
    720     @Override Table<Character, String, Integer> makeTable() {
    721       return TreeBasedTable.create();
    722     }
    723   }
    724 
    725   public static class TransposeRowTests extends RowTests {
    726     public TransposeRowTests() {
    727       super(false, true, true, true, false);
    728     }
    729 
    730     @Override Table<Character, String, Integer> makeTable() {
    731       Table<String, Character, Integer> original = TreeBasedTable.create();
    732       return Tables.transpose(original);
    733     }
    734   }
    735 
    736   private static final Function<Integer, Integer> DIVIDE_BY_2
    737       = new Function<Integer, Integer>() {
    738         @Override public Integer apply(Integer input) {
    739           return (input == null) ? null : input / 2;
    740         }
    741   };
    742 
    743   public static class TransformValueRowTests extends RowTests {
    744     public TransformValueRowTests() {
    745       super(false, false, true, true, true);
    746     }
    747 
    748     @Override Table<Character, String, Integer> makeTable() {
    749       Table<Character, String, Integer> table = HashBasedTable.create();
    750       return Tables.transformValues(table, DIVIDE_BY_2);
    751     }
    752 
    753     @Override protected Map<String, Integer> makePopulatedMap() {
    754       Table<Character, String, Integer> table = HashBasedTable.create();
    755       table.put('a', "one", 2);
    756       table.put('a', "two", 4);
    757       table.put('a', "three", 6);
    758       table.put('b', "four", 8);
    759       return Tables.transformValues(table, DIVIDE_BY_2).row('a');
    760     }
    761   }
    762 
    763   public static class UnmodifiableHashRowTests extends RowTests {
    764     public UnmodifiableHashRowTests() {
    765       super(false, false, false, false, false);
    766     }
    767 
    768     @Override Table<Character, String, Integer> makeTable() {
    769       Table<Character, String, Integer> table = HashBasedTable.create();
    770       return Tables.unmodifiableTable(table);
    771     }
    772 
    773     @Override protected Map<String, Integer> makePopulatedMap() {
    774       Table<Character, String, Integer> table = HashBasedTable.create();
    775       table.put('a', "one", 1);
    776       table.put('a', "two", 2);
    777       table.put('a', "three", 3);
    778       table.put('b', "four", 4);
    779       return Tables.unmodifiableTable(table).row('a');
    780     }
    781   }
    782 
    783   public static class UnmodifiableTreeRowTests extends RowTests {
    784     public UnmodifiableTreeRowTests() {
    785       super(false, false, false, false, false);
    786     }
    787 
    788     @Override Table<Character, String, Integer> makeTable() {
    789       RowSortedTable<Character, String, Integer> table = TreeBasedTable.create();
    790       return Tables.unmodifiableRowSortedTable(table);
    791     }
    792 
    793     @Override protected Map<String, Integer> makePopulatedMap() {
    794       RowSortedTable<Character, String, Integer> table = TreeBasedTable.create();
    795       table.put('a', "one", 1);
    796       table.put('a', "two", 2);
    797       table.put('a', "three", 3);
    798       table.put('b', "four", 4);
    799       return Tables.unmodifiableRowSortedTable(table).row('a');
    800     }
    801   }
    802 
    803   private static abstract class ColumnTests extends MapTests {
    804     ColumnTests(boolean allowsNullValues, boolean supportsPut, boolean supportsRemove,
    805         boolean supportsClear, boolean supportsIteratorRemove) {
    806       super(allowsNullValues, supportsPut, supportsRemove, supportsClear,
    807           supportsIteratorRemove);
    808     }
    809 
    810     abstract Table<String, Character, Integer> makeTable();
    811 
    812     @Override protected Map<String, Integer> makeEmptyMap() {
    813       return makeTable().column('a');
    814     }
    815 
    816     @Override protected Map<String, Integer> makePopulatedMap() {
    817       Table<String, Character, Integer> table = makeTable();
    818       table.put("one", 'a', 1);
    819       table.put("two", 'a', 2);
    820       table.put("three", 'a', 3);
    821       table.put("four", 'b', 4);
    822       return table.column('a');
    823     }
    824   }
    825 
    826   @GwtIncompatible("TODO(hhchan): ArrayTable")
    827   public static class ArrayColumnTests extends ColumnTests {
    828     public ArrayColumnTests() {
    829       super(true, true, false, false, false);
    830     }
    831 
    832     @Override protected String getKeyNotInPopulatedMap() {
    833       throw new UnsupportedOperationException();
    834     }
    835 
    836     @Override protected Map<String, Integer> makeEmptyMap() {
    837       throw new UnsupportedOperationException();
    838     }
    839 
    840     @Override Table<String, Character, Integer> makeTable() {
    841       return ArrayTable.create(Arrays.asList("one", "two", "three", "four"),
    842           Arrays.asList('a', 'b', 'c'));
    843     }
    844   }
    845 
    846   public static class HashColumnTests extends ColumnTests {
    847     public HashColumnTests() {
    848       super(false, true, true, true, false);
    849     }
    850 
    851     @Override Table<String, Character, Integer> makeTable() {
    852       return HashBasedTable.create();
    853     }
    854   }
    855 
    856   public static class TreeColumnTests extends ColumnTests {
    857     public TreeColumnTests() {
    858       super(false, true, true, true, false);
    859     }
    860 
    861     @Override Table<String, Character, Integer> makeTable() {
    862       return TreeBasedTable.create();
    863     }
    864   }
    865 
    866   public static class TransposeColumnTests extends ColumnTests {
    867     public TransposeColumnTests() {
    868       super(false, true, true, true, true);
    869     }
    870 
    871     @Override Table<String, Character, Integer> makeTable() {
    872       Table<Character, String, Integer> original = TreeBasedTable.create();
    873       return Tables.transpose(original);
    874     }
    875   }
    876 
    877   public static class TransformValueColumnTests extends ColumnTests {
    878     public TransformValueColumnTests() {
    879       super(false, false, true, true, false);
    880     }
    881 
    882     @Override Table<String, Character, Integer> makeTable() {
    883       Table<String, Character, Integer> table = HashBasedTable.create();
    884       return Tables.transformValues(table, DIVIDE_BY_2);
    885     }
    886 
    887     @Override protected Map<String, Integer> makePopulatedMap() {
    888       Table<String, Character, Integer> table = HashBasedTable.create();
    889       table.put("one", 'a', 1);
    890       table.put("two", 'a', 2);
    891       table.put("three", 'a', 3);
    892       table.put("four", 'b', 4);
    893       return Tables.transformValues(table, DIVIDE_BY_2).column('a');
    894     }
    895   }
    896 
    897   public static class UnmodifiableHashColumnTests extends ColumnTests {
    898     public UnmodifiableHashColumnTests() {
    899       super(false, false, false, false, false);
    900     }
    901 
    902     @Override Table<String, Character, Integer> makeTable() {
    903       Table<String, Character, Integer> table = HashBasedTable.create();
    904       return Tables.unmodifiableTable(table);
    905     }
    906 
    907     @Override protected Map<String, Integer> makePopulatedMap() {
    908       Table<String, Character, Integer> table = HashBasedTable.create();
    909       table.put("one", 'a', 1);
    910       table.put("two", 'a', 2);
    911       table.put("three", 'a', 3);
    912       table.put("four", 'b', 4);
    913       return Tables.unmodifiableTable(table).column('a');
    914     }
    915   }
    916 
    917   public static class UnmodifiableTreeColumnTests extends ColumnTests {
    918     public UnmodifiableTreeColumnTests() {
    919       super(false, false, false, false, false);
    920     }
    921 
    922     @Override Table<String, Character, Integer> makeTable() {
    923       RowSortedTable<String, Character, Integer> table = TreeBasedTable.create();
    924       return Tables.unmodifiableRowSortedTable(table);
    925     }
    926 
    927     @Override protected Map<String, Integer> makePopulatedMap() {
    928       RowSortedTable<String, Character, Integer> table = TreeBasedTable.create();
    929       table.put("one", 'a', 1);
    930       table.put("two", 'a', 2);
    931       table.put("three", 'a', 3);
    932       table.put("four", 'b', 4);
    933       return Tables.unmodifiableRowSortedTable(table).column('a');
    934     }
    935   }
    936 
    937   private static abstract class MapMapTests
    938       extends MapInterfaceTest<String, Map<Integer, Character>> {
    939 
    940     MapMapTests(boolean allowsNullValues, boolean supportsRemove,
    941         boolean supportsClear, boolean supportsIteratorRemove) {
    942       super(false, allowsNullValues, false, supportsRemove, supportsClear,
    943           supportsIteratorRemove);
    944     }
    945 
    946     @Override protected String getKeyNotInPopulatedMap() {
    947       return "cat";
    948     }
    949 
    950     @Override protected Map<Integer, Character> getValueNotInPopulatedMap() {
    951       return ImmutableMap.of();
    952     }
    953 
    954     /**
    955      * The version of this test supplied by {@link MapInterfaceTest} fails for
    956      * this particular map implementation, because {@code map.get()} returns a
    957      * view collection that changes in the course of a call to {@code remove()}.
    958      * Thus, the expectation doesn't hold that {@code map.remove(x)} returns the
    959      * same value which {@code map.get(x)} did immediately beforehand.
    960      */
    961     @Override public void testRemove() {
    962       final Map<String, Map<Integer, Character>> map;
    963       final String keyToRemove;
    964       try {
    965         map = makePopulatedMap();
    966       } catch (UnsupportedOperationException e) {
    967         return;
    968       }
    969       keyToRemove = map.keySet().iterator().next();
    970       if (supportsRemove) {
    971         int initialSize = map.size();
    972         map.get(keyToRemove);
    973         map.remove(keyToRemove);
    974         // This line doesn't hold - see the Javadoc comments above.
    975         // assertEquals(expectedValue, oldValue);
    976         assertFalse(map.containsKey(keyToRemove));
    977         assertEquals(initialSize - 1, map.size());
    978       } else {
    979         try {
    980           map.remove(keyToRemove);
    981           fail("Expected UnsupportedOperationException.");
    982         } catch (UnsupportedOperationException e) {
    983           // Expected.
    984         }
    985       }
    986       assertInvariants(map);
    987     }
    988   }
    989 
    990   private static abstract class RowMapTests extends MapMapTests {
    991     RowMapTests(boolean allowsNullValues, boolean supportsRemove,
    992         boolean supportsClear, boolean supportsIteratorRemove) {
    993       super(allowsNullValues, supportsRemove, supportsClear,
    994           supportsIteratorRemove);
    995     }
    996 
    997     abstract Table<String, Integer, Character> makeTable();
    998 
    999     @Override protected Map<String, Map<Integer, Character>>
   1000         makePopulatedMap() {
   1001       Table<String, Integer, Character> table = makeTable();
   1002       populateTable(table);
   1003       return table.rowMap();
   1004     }
   1005 
   1006     void populateTable(Table<String, Integer, Character> table) {
   1007       table.put("foo", 1, 'a');
   1008       table.put("bar", 1, 'b');
   1009       table.put("foo", 3, 'c');
   1010     }
   1011 
   1012     @Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
   1013       return makeTable().rowMap();
   1014     }
   1015   }
   1016 
   1017   @GwtIncompatible("TODO(hhchan): ArrayTable")
   1018   public static class ArrayRowMapTests extends RowMapTests {
   1019     public ArrayRowMapTests() {
   1020       super(true, false, false, false);
   1021     }
   1022 
   1023     @Override Table<String, Integer, Character> makeTable() {
   1024       return ArrayTable.create(Arrays.asList("foo", "bar", "dog"),
   1025           Arrays.asList(1, 2, 3));
   1026     }
   1027 
   1028     @Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
   1029       throw new UnsupportedOperationException();
   1030     }
   1031   }
   1032 
   1033   public static class HashRowMapTests extends RowMapTests {
   1034     public HashRowMapTests() {
   1035       super(false, true, true, true);
   1036     }
   1037 
   1038     @Override Table<String, Integer, Character> makeTable() {
   1039       return HashBasedTable.create();
   1040     }
   1041   }
   1042 
   1043   public static class TreeRowMapTests extends RowMapTests {
   1044     public TreeRowMapTests() {
   1045       super(false, true, true, true);
   1046     }
   1047 
   1048     @Override Table<String, Integer, Character> makeTable() {
   1049       return TreeBasedTable.create();
   1050     }
   1051   }
   1052 
   1053   public static class TreeRowMapHeadMapTests extends RowMapTests {
   1054     public TreeRowMapHeadMapTests() {
   1055       super(false, true, true, true);
   1056     }
   1057 
   1058     @Override TreeBasedTable<String, Integer, Character> makeTable() {
   1059       TreeBasedTable<String, Integer, Character> table =
   1060           TreeBasedTable.create();
   1061       table.put("z", 1, 'a');
   1062       return table;
   1063     }
   1064 
   1065     @Override protected Map<String, Map<Integer, Character>>
   1066         makePopulatedMap() {
   1067       TreeBasedTable<String, Integer, Character> table = makeTable();
   1068       populateTable(table);
   1069       return table.rowMap().headMap("x");
   1070     }
   1071 
   1072     @Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
   1073       return makeTable().rowMap().headMap("x");
   1074     }
   1075 
   1076     @Override protected String getKeyNotInPopulatedMap() {
   1077       return "z";
   1078     }
   1079   }
   1080 
   1081   public static class TreeRowMapTailMapTests extends RowMapTests {
   1082     public TreeRowMapTailMapTests() {
   1083       super(false, true, true, true);
   1084     }
   1085 
   1086     @Override TreeBasedTable<String, Integer, Character> makeTable() {
   1087       TreeBasedTable<String, Integer, Character> table =
   1088           TreeBasedTable.create();
   1089       table.put("a", 1, 'a');
   1090       return table;
   1091     }
   1092 
   1093     @Override protected Map<String, Map<Integer, Character>>
   1094         makePopulatedMap() {
   1095       TreeBasedTable<String, Integer, Character> table = makeTable();
   1096       populateTable(table);
   1097       return table.rowMap().tailMap("b");
   1098     }
   1099 
   1100     @Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
   1101       return makeTable().rowMap().tailMap("b");
   1102     }
   1103 
   1104     @Override protected String getKeyNotInPopulatedMap() {
   1105       return "a";
   1106     }
   1107   }
   1108 
   1109   public static class TreeRowMapSubMapTests extends RowMapTests {
   1110     public TreeRowMapSubMapTests() {
   1111       super(false, true, true, true);
   1112     }
   1113 
   1114     @Override TreeBasedTable<String, Integer, Character> makeTable() {
   1115       TreeBasedTable<String, Integer, Character> table =
   1116           TreeBasedTable.create();
   1117       table.put("a", 1, 'a');
   1118       table.put("z", 1, 'a');
   1119       return table;
   1120     }
   1121 
   1122     @Override protected Map<String, Map<Integer, Character>>
   1123         makePopulatedMap() {
   1124       TreeBasedTable<String, Integer, Character> table = makeTable();
   1125       populateTable(table);
   1126       return table.rowMap().subMap("b", "x");
   1127     }
   1128 
   1129     @Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
   1130       return makeTable().rowMap().subMap("b", "x");
   1131     }
   1132 
   1133     @Override protected String getKeyNotInPopulatedMap() {
   1134       return "z";
   1135     }
   1136   }
   1137 
   1138   private static final Function<String, Character> FIRST_CHARACTER =
   1139       new Function<String, Character>() {
   1140         @Override
   1141         public Character apply(String input) {
   1142           return input == null ? null : input.charAt(0);
   1143         }
   1144       };
   1145 
   1146   public static class TransformValueRowMapTests extends RowMapTests {
   1147     public TransformValueRowMapTests() {
   1148       super(false, true, true, true);
   1149     }
   1150 
   1151     @Override Table<String, Integer, Character> makeTable() {
   1152       Table<String, Integer, String> original = HashBasedTable.create();
   1153       return Tables.transformValues(original, FIRST_CHARACTER);
   1154     }
   1155 
   1156     @Override
   1157     protected Map<String, Map<Integer, Character>> makePopulatedMap() {
   1158       Table<String, Integer, String> table = HashBasedTable.create();
   1159       table.put("foo", 1, "apple");
   1160       table.put("bar", 1, "banana");
   1161       table.put("foo", 3, "cat");
   1162       return Tables.transformValues(table, FIRST_CHARACTER).rowMap();
   1163     }
   1164   }
   1165 
   1166   public static class UnmodifiableHashRowMapTests extends RowMapTests {
   1167     public UnmodifiableHashRowMapTests() {
   1168       super(false, false, false, false);
   1169     }
   1170 
   1171     @Override Table<String, Integer, Character> makeTable() {
   1172       Table<String, Integer, Character> original = HashBasedTable.create();
   1173       return Tables.unmodifiableTable(original);
   1174     }
   1175 
   1176     @Override
   1177     protected Map<String, Map<Integer, Character>> makePopulatedMap() {
   1178       Table<String, Integer, Character> table = HashBasedTable.create();
   1179       table.put("foo", 1, 'a');
   1180       table.put("bar", 1, 'b');
   1181       table.put("foo", 3, 'c');
   1182       return Tables.unmodifiableTable(table).rowMap();
   1183     }
   1184   }
   1185 
   1186   public static class UnmodifiableTreeRowMapTests extends RowMapTests {
   1187     public UnmodifiableTreeRowMapTests() {
   1188       super(false, false, false, false);
   1189     }
   1190 
   1191     @Override RowSortedTable<String, Integer, Character> makeTable() {
   1192       RowSortedTable<String, Integer, Character> original = TreeBasedTable.create();
   1193       return Tables.unmodifiableRowSortedTable(original);
   1194     }
   1195 
   1196     @Override
   1197     protected SortedMap<String, Map<Integer, Character>> makePopulatedMap() {
   1198       RowSortedTable<String, Integer, Character> table = TreeBasedTable.create();
   1199       table.put("foo", 1, 'a');
   1200       table.put("bar", 1, 'b');
   1201       table.put("foo", 3, 'c');
   1202       return Tables.unmodifiableRowSortedTable(table).rowMap();
   1203     }
   1204   }
   1205 
   1206   private static abstract class ColumnMapTests extends MapMapTests {
   1207     ColumnMapTests(boolean allowsNullValues, boolean supportsRemove,
   1208         boolean supportsClear, boolean supportsIteratorRemove) {
   1209       super(allowsNullValues, supportsRemove, supportsClear,
   1210           supportsIteratorRemove);
   1211     }
   1212 
   1213     abstract Table<Integer, String, Character> makeTable();
   1214 
   1215     @Override protected Map<String, Map<Integer, Character>>
   1216         makePopulatedMap() {
   1217       Table<Integer, String, Character> table = makeTable();
   1218       table.put(1, "foo", 'a');
   1219       table.put(1, "bar", 'b');
   1220       table.put(3, "foo", 'c');
   1221       return table.columnMap();
   1222     }
   1223 
   1224     @Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
   1225       return makeTable().columnMap();
   1226     }
   1227   }
   1228 
   1229   @GwtIncompatible("TODO(hhchan): ArrayTable")
   1230   public static class ArrayColumnMapTests extends ColumnMapTests {
   1231     public ArrayColumnMapTests() {
   1232       super(true, false, false, false);
   1233     }
   1234 
   1235     @Override Table<Integer, String, Character> makeTable() {
   1236       return ArrayTable.create(Arrays.asList(1, 2, 3),
   1237           Arrays.asList("foo", "bar", "dog"));
   1238     }
   1239 
   1240     @Override protected Map<String, Map<Integer, Character>> makeEmptyMap() {
   1241       throw new UnsupportedOperationException();
   1242     }
   1243   }
   1244 
   1245   public static class HashColumnMapTests extends ColumnMapTests {
   1246     public HashColumnMapTests() {
   1247       super(false, true, true, false);
   1248     }
   1249 
   1250     @Override Table<Integer, String, Character> makeTable() {
   1251       return HashBasedTable.create();
   1252     }
   1253   }
   1254 
   1255   public static class TreeColumnMapTests extends ColumnMapTests {
   1256     public TreeColumnMapTests() {
   1257       super(false, true, true, false);
   1258     }
   1259 
   1260     @Override Table<Integer, String, Character> makeTable() {
   1261       return TreeBasedTable.create();
   1262     }
   1263   }
   1264 
   1265   public static class TransformValueColumnMapTests extends ColumnMapTests {
   1266     public TransformValueColumnMapTests() {
   1267       super(false, true, true, false);
   1268     }
   1269 
   1270     @Override Table<Integer, String, Character> makeTable() {
   1271       Table<Integer, String, String> original = HashBasedTable.create();
   1272       return Tables.transformValues(original, FIRST_CHARACTER);
   1273     }
   1274 
   1275     @Override
   1276     protected Map<String, Map<Integer, Character>> makePopulatedMap() {
   1277       Table<Integer, String, String> table = HashBasedTable.create();
   1278       table.put(1, "foo", "apple");
   1279       table.put(1, "bar", "banana");
   1280       table.put(3, "foo", "cat");
   1281       return Tables.transformValues(table, FIRST_CHARACTER).columnMap();
   1282     }
   1283   }
   1284 
   1285   public static class UnmodifiableHashColumnMapTests extends ColumnMapTests {
   1286     public UnmodifiableHashColumnMapTests() {
   1287       super(false, false, false, false);
   1288     }
   1289 
   1290     @Override Table<Integer, String, Character> makeTable() {
   1291       Table<Integer, String, Character> original = HashBasedTable.create();
   1292       return Tables.unmodifiableTable(original);
   1293     }
   1294 
   1295     @Override
   1296     protected Map<String, Map<Integer, Character>> makePopulatedMap() {
   1297       Table<Integer, String, Character> table = HashBasedTable.create();
   1298       table.put(1, "foo", 'a');
   1299       table.put(1, "bar", 'b');
   1300       table.put(3, "foo", 'c');
   1301       return Tables.unmodifiableTable(table).columnMap();
   1302     }
   1303   }
   1304 
   1305   public static class UnmodifiableTreeColumnMapTests extends ColumnMapTests {
   1306     public UnmodifiableTreeColumnMapTests() {
   1307       super(false, false, false, false);
   1308     }
   1309 
   1310     @Override Table<Integer, String, Character> makeTable() {
   1311       RowSortedTable<Integer, String, Character> original = TreeBasedTable.create();
   1312       return Tables.unmodifiableRowSortedTable(original);
   1313     }
   1314 
   1315     @Override
   1316     protected Map<String, Map<Integer, Character>> makePopulatedMap() {
   1317       RowSortedTable<Integer, String, Character> table = TreeBasedTable.create();
   1318       table.put(1, "foo", 'a');
   1319       table.put(1, "bar", 'b');
   1320       table.put(3, "foo", 'c');
   1321       return Tables.unmodifiableRowSortedTable(table).columnMap();
   1322     }
   1323   }
   1324 }
   1325