Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2012 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 package com.google.common.collect;
     17 
     18 import static com.google.common.base.Preconditions.checkArgument;
     19 import static com.google.common.base.Preconditions.checkNotNull;
     20 import static com.google.common.collect.testing.Helpers.mapEntry;
     21 
     22 import com.google.common.base.Charsets;
     23 import com.google.common.base.Function;
     24 import com.google.common.base.Predicate;
     25 import com.google.common.collect.Maps.EntryTransformer;
     26 import com.google.common.collect.testing.Helpers;
     27 import com.google.common.collect.testing.MapTestSuiteBuilder;
     28 import com.google.common.collect.testing.NavigableMapTestSuiteBuilder;
     29 import com.google.common.collect.testing.SafeTreeMap;
     30 import com.google.common.collect.testing.SampleElements;
     31 import com.google.common.collect.testing.SortedMapTestSuiteBuilder;
     32 import com.google.common.collect.testing.TestMapGenerator;
     33 import com.google.common.collect.testing.TestStringMapGenerator;
     34 import com.google.common.collect.testing.TestStringSortedMapGenerator;
     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.MapFeature;
     38 import com.google.common.collect.testing.google.BiMapTestSuiteBuilder;
     39 import com.google.common.collect.testing.google.TestStringBiMapGenerator;
     40 import com.google.common.io.BaseEncoding;
     41 
     42 import junit.framework.Test;
     43 import junit.framework.TestCase;
     44 import junit.framework.TestSuite;
     45 
     46 import java.util.Collections;
     47 import java.util.Comparator;
     48 import java.util.List;
     49 import java.util.Map;
     50 import java.util.Map.Entry;
     51 import java.util.NavigableMap;
     52 import java.util.NavigableSet;
     53 import java.util.Set;
     54 import java.util.SortedMap;
     55 import java.util.SortedSet;
     56 
     57 import javax.annotation.Nullable;
     58 
     59 /**
     60  * Test suites for wrappers in {@code Maps}.
     61  *
     62  * @author Louis Wasserman
     63  */
     64 public class MapsCollectionTest extends TestCase {
     65   public static Test suite() {
     66     TestSuite suite = new TestSuite();
     67 
     68     suite.addTest(NavigableMapTestSuiteBuilder
     69         .using(new TestStringSortedMapGenerator() {
     70           @Override
     71           protected SortedMap<String, String> create(Entry<String, String>[] entries) {
     72             SafeTreeMap<String, String> map = new SafeTreeMap<String, String>();
     73             putEntries(map, entries);
     74             return Maps.unmodifiableNavigableMap(map);
     75           }
     76         })
     77         .named("unmodifiableNavigableMap[SafeTreeMap]")
     78         .withFeatures(CollectionSize.ANY,
     79             MapFeature.ALLOWS_NULL_VALUES,
     80             CollectionFeature.SERIALIZABLE)
     81         .createTestSuite());
     82     suite.addTest(BiMapTestSuiteBuilder
     83         .using(new TestStringBiMapGenerator() {
     84           @Override
     85           protected BiMap<String, String> create(Entry<String, String>[] entries) {
     86             BiMap<String, String> bimap = HashBiMap.create(entries.length);
     87             for (Entry<String, String> entry : entries) {
     88               checkArgument(!bimap.containsKey(entry.getKey()));
     89               bimap.put(entry.getKey(), entry.getValue());
     90             }
     91             return Maps.unmodifiableBiMap(bimap);
     92           }
     93         })
     94         .named("unmodifiableBiMap[HashBiMap]")
     95         .withFeatures(
     96             CollectionSize.ANY,
     97             MapFeature.ALLOWS_NULL_VALUES,
     98             MapFeature.ALLOWS_NULL_KEYS,
     99             MapFeature.ALLOWS_ANY_NULL_QUERIES,
    100             MapFeature.REJECTS_DUPLICATES_AT_CREATION,
    101             CollectionFeature.SERIALIZABLE)
    102         .createTestSuite());
    103     suite.addTest(MapTestSuiteBuilder
    104         .using(new TestMapGenerator<String, Integer>() {
    105           @Override
    106           public SampleElements<Entry<String, Integer>> samples() {
    107             return new SampleElements<Entry<String, Integer>>(
    108                 mapEntry("x", 1),
    109                 mapEntry("xxx", 3),
    110                 mapEntry("xx", 2),
    111                 mapEntry("xxxx", 4),
    112                 mapEntry("aaaaa", 5));
    113           }
    114 
    115           @Override
    116           public Map<String, Integer> create(Object... elements) {
    117             Set<String> set = Sets.newLinkedHashSet();
    118             for (Object e : elements) {
    119               Entry<?, ?> entry = (Entry<?, ?>) e;
    120               checkNotNull(entry.getValue());
    121               set.add((String) checkNotNull(entry.getKey()));
    122             }
    123             return Maps.asMap(set, new Function<String, Integer>() {
    124               @Override
    125               public Integer apply(String input) {
    126                 return input.length();
    127               }
    128             });
    129           }
    130 
    131           @SuppressWarnings("unchecked")
    132           @Override
    133           public Entry<String, Integer>[] createArray(int length) {
    134             return new Entry[length];
    135           }
    136 
    137           @Override
    138           public Iterable<Entry<String, Integer>> order(
    139               List<Entry<String, Integer>> insertionOrder) {
    140             return insertionOrder;
    141           }
    142 
    143           @Override
    144           public String[] createKeyArray(int length) {
    145             return new String[length];
    146           }
    147 
    148           @Override
    149           public Integer[] createValueArray(int length) {
    150             return new Integer[length];
    151           }
    152         })
    153         .named("Maps.asMap[Set, Function]")
    154         .withFeatures(CollectionSize.ANY,
    155             MapFeature.SUPPORTS_REMOVE,
    156             CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    157         .createTestSuite());
    158     suite.addTest(SortedMapTestSuiteBuilder
    159         .using(new TestMapGenerator<String, Integer>() {
    160           @Override
    161           public String[] createKeyArray(int length) {
    162             return new String[length];
    163           }
    164 
    165           @Override
    166           public Integer[] createValueArray(int length) {
    167             return new Integer[length];
    168           }
    169 
    170           @Override
    171           public SampleElements<Entry<String, Integer>> samples() {
    172             return new SampleElements<Entry<String, Integer>>(
    173                 mapEntry("a", 1),
    174                 mapEntry("aa", 2),
    175                 mapEntry("aba", 3),
    176                 mapEntry("bbbb", 4),
    177                 mapEntry("ccccc", 5));
    178           }
    179 
    180           @Override
    181           public SortedMap<String, Integer> create(Object... elements) {
    182             SortedSet<String> set = new NonNavigableSortedSet();
    183             for (Object e : elements) {
    184               Entry<?, ?> entry = (Entry<?, ?>) e;
    185               checkNotNull(entry.getValue());
    186               set.add((String) checkNotNull(entry.getKey()));
    187             }
    188             return Maps.asMap(set, new Function<String, Integer>() {
    189               @Override
    190               public Integer apply(String input) {
    191                 return input.length();
    192               }
    193             });
    194           }
    195 
    196           @SuppressWarnings("unchecked")
    197           @Override
    198           public Entry<String, Integer>[] createArray(int length) {
    199             return new Entry[length];
    200           }
    201 
    202           @Override
    203           public Iterable<Entry<String, Integer>> order(
    204               List<Entry<String, Integer>> insertionOrder) {
    205             Collections.sort(insertionOrder, new Comparator<Entry<String, Integer>>() {
    206               @Override
    207               public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
    208                 return o1.getKey().compareTo(o2.getKey());
    209               }
    210             });
    211             return insertionOrder;
    212           }
    213         })
    214         .named("Maps.asMap[SortedSet, Function]")
    215         .withFeatures(CollectionSize.ANY,
    216             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
    217             MapFeature.SUPPORTS_REMOVE)
    218         .createTestSuite());
    219     suite.addTest(NavigableMapTestSuiteBuilder
    220         .using(new TestMapGenerator<String, Integer>() {
    221           @Override
    222           public String[] createKeyArray(int length) {
    223             return new String[length];
    224           }
    225 
    226           @Override
    227           public Integer[] createValueArray(int length) {
    228             return new Integer[length];
    229           }
    230 
    231           @Override
    232           public SampleElements<Entry<String, Integer>> samples() {
    233             return new SampleElements<Entry<String, Integer>>(
    234                 mapEntry("a", 1),
    235                 mapEntry("aa", 2),
    236                 mapEntry("aba", 3),
    237                 mapEntry("bbbb", 4),
    238                 mapEntry("ccccc", 5));
    239           }
    240 
    241           @Override
    242           public NavigableMap<String, Integer> create(Object... elements) {
    243             NavigableSet<String> set = Sets.newTreeSet(Ordering.natural());
    244             for (Object e : elements) {
    245               Map.Entry<?, ?> entry = (Entry<?, ?>) e;
    246               checkNotNull(entry.getValue());
    247               set.add((String) checkNotNull(entry.getKey()));
    248             }
    249             return Maps.asMap(set, new Function<String, Integer>() {
    250               @Override
    251               public Integer apply(String input) {
    252                 return input.length();
    253               }
    254             });
    255           }
    256 
    257           @SuppressWarnings("unchecked")
    258           @Override
    259           public Entry<String, Integer>[] createArray(int length) {
    260             return new Entry[length];
    261           }
    262 
    263           @Override
    264           public Iterable<Entry<String, Integer>> order(
    265               List<Entry<String, Integer>> insertionOrder) {
    266             Collections.sort(insertionOrder, new Comparator<Entry<String, Integer>>() {
    267               @Override
    268               public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
    269                 return o1.getKey().compareTo(o2.getKey());
    270               }
    271             });
    272             return insertionOrder;
    273           }
    274         })
    275         .named("Maps.asMap[NavigableSet, Function]")
    276         .withFeatures(CollectionSize.ANY,
    277             MapFeature.SUPPORTS_REMOVE,
    278             CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    279         .createTestSuite());
    280     suite.addTest(filterSuite());
    281     suite.addTest(transformSuite());
    282     return suite;
    283   }
    284 
    285   static TestSuite filterSuite() {
    286     TestSuite suite = new TestSuite("Filter");
    287     suite.addTest(filterMapSuite());
    288     suite.addTest(filterBiMapSuite());
    289     suite.addTest(filterSortedMapSuite());
    290     suite.addTest(filterNavigableMapSuite());
    291     return suite;
    292   }
    293 
    294   static TestSuite filterMapSuite() {
    295     TestSuite suite = new TestSuite("FilterMap");
    296     suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() {
    297         @Override
    298         protected Map<String, String> create(Entry<String, String>[] entries) {
    299           Map<String, String> map = Maps.newHashMap();
    300           putEntries(map, entries);
    301           map.putAll(ENTRIES_TO_FILTER);
    302           return Maps.filterKeys(map, FILTER_KEYS);
    303         }
    304       })
    305       .named("Maps.filterKeys[Map, Predicate]")
    306       .withFeatures(
    307           MapFeature.ALLOWS_NULL_KEYS,
    308           MapFeature.ALLOWS_NULL_VALUES,
    309           MapFeature.ALLOWS_ANY_NULL_QUERIES,
    310           MapFeature.GENERAL_PURPOSE,
    311           CollectionSize.ANY)
    312       .createTestSuite());
    313     suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() {
    314         @Override
    315         protected Map<String, String> create(Entry<String, String>[] entries) {
    316           Map<String, String> map = Maps.newHashMap();
    317           putEntries(map, entries);
    318           map.putAll(ENTRIES_TO_FILTER);
    319           return Maps.filterValues(map, FILTER_VALUES);
    320         }
    321       })
    322       .named("Maps.filterValues[Map, Predicate]")
    323       .withFeatures(
    324           MapFeature.ALLOWS_NULL_KEYS,
    325           MapFeature.ALLOWS_NULL_VALUES,
    326           MapFeature.ALLOWS_ANY_NULL_QUERIES,
    327           MapFeature.GENERAL_PURPOSE,
    328           CollectionSize.ANY)
    329       .createTestSuite());
    330     suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() {
    331         @Override
    332         protected Map<String, String> create(Entry<String, String>[] entries) {
    333           Map<String, String> map = Maps.newHashMap();
    334           putEntries(map, entries);
    335            map.putAll(ENTRIES_TO_FILTER);
    336           return Maps.filterEntries(map, FILTER_ENTRIES);
    337         }
    338       })
    339       .named("Maps.filterEntries[Map, Predicate]")
    340       .withFeatures(
    341           MapFeature.ALLOWS_NULL_KEYS,
    342           MapFeature.ALLOWS_NULL_VALUES,
    343           MapFeature.ALLOWS_ANY_NULL_QUERIES,
    344           MapFeature.GENERAL_PURPOSE,
    345           CollectionSize.ANY)
    346       .createTestSuite());
    347     suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() {
    348         @Override
    349         protected Map<String, String> create(Entry<String, String>[] entries) {
    350           Map<String, String> map = Maps.newHashMap();
    351           putEntries(map, entries);
    352           map.putAll(ENTRIES_TO_FILTER);
    353           map = Maps.filterEntries(map, FILTER_ENTRIES_1);
    354           return Maps.filterEntries(map, FILTER_ENTRIES_2);
    355         }
    356       })
    357       .named("Maps.filterEntries[Maps.filterEntries[Map, Predicate], Predicate]")
    358       .withFeatures(
    359           MapFeature.ALLOWS_NULL_KEYS,
    360           MapFeature.ALLOWS_NULL_VALUES,
    361           MapFeature.ALLOWS_ANY_NULL_QUERIES,
    362           MapFeature.GENERAL_PURPOSE,
    363           CollectionSize.ANY)
    364       .createTestSuite());
    365     return suite;
    366   }
    367 
    368   static TestSuite filterBiMapSuite() {
    369     TestSuite suite = new TestSuite("FilterBiMap");
    370     suite.addTest(BiMapTestSuiteBuilder.using(new TestStringBiMapGenerator() {
    371         @Override
    372         protected BiMap<String, String> create(Entry<String, String>[] entries) {
    373           BiMap<String, String> map = HashBiMap.create();
    374           putEntries(map, entries);
    375           map.putAll(ENTRIES_TO_FILTER);
    376           return Maps.filterKeys(map, FILTER_KEYS);
    377         }
    378       })
    379       .named("Maps.filterKeys[BiMap, Predicate]")
    380       .withFeatures(
    381           MapFeature.ALLOWS_NULL_KEYS,
    382           MapFeature.ALLOWS_NULL_VALUES,
    383           MapFeature.GENERAL_PURPOSE,
    384           CollectionSize.ANY)
    385       .createTestSuite());
    386     suite.addTest(BiMapTestSuiteBuilder.using(new TestStringBiMapGenerator() {
    387         @Override
    388         protected BiMap<String, String> create(Entry<String, String>[] entries) {
    389           BiMap<String, String> map = HashBiMap.create();
    390           putEntries(map, entries);
    391           map.putAll(ENTRIES_TO_FILTER);
    392           return Maps.filterValues(map, FILTER_VALUES);
    393         }
    394       })
    395       .named("Maps.filterValues[BiMap, Predicate]")
    396       .withFeatures(
    397           MapFeature.ALLOWS_NULL_KEYS,
    398           MapFeature.ALLOWS_NULL_VALUES,
    399           MapFeature.ALLOWS_ANY_NULL_QUERIES,
    400           MapFeature.GENERAL_PURPOSE,
    401           CollectionSize.ANY)
    402       .createTestSuite());
    403     suite.addTest(BiMapTestSuiteBuilder.using(new TestStringBiMapGenerator() {
    404         @Override
    405         protected BiMap<String, String> create(Entry<String, String>[] entries) {
    406           BiMap<String, String> map = HashBiMap.create();
    407           putEntries(map, entries);
    408           map.putAll(ENTRIES_TO_FILTER);
    409           return Maps.filterEntries(map, FILTER_ENTRIES);
    410         }
    411       })
    412       .named("Maps.filterEntries[BiMap, Predicate]")
    413       .withFeatures(
    414           MapFeature.ALLOWS_NULL_KEYS,
    415           MapFeature.ALLOWS_NULL_VALUES,
    416           MapFeature.ALLOWS_ANY_NULL_QUERIES,
    417           MapFeature.GENERAL_PURPOSE,
    418           CollectionSize.ANY)
    419       .createTestSuite());
    420     return suite;
    421   }
    422 
    423   static TestSuite filterSortedMapSuite() {
    424     TestSuite suite = new TestSuite("FilterSortedMap");
    425     suite.addTest(SortedMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
    426         @Override
    427         protected SortedMap<String, String> create(Entry<String, String>[] entries) {
    428           SortedMap<String, String> map = new NonNavigableSortedMap();
    429           putEntries(map, entries);
    430           map.putAll(ENTRIES_TO_FILTER);
    431          return Maps.filterKeys(map, FILTER_KEYS);
    432         }
    433       })
    434       .named("Maps.filterKeys[SortedMap, Predicate]")
    435       .withFeatures(
    436           MapFeature.ALLOWS_NULL_VALUES,
    437           MapFeature.GENERAL_PURPOSE,
    438           CollectionSize.ANY)
    439       .createTestSuite());
    440     suite.addTest(SortedMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
    441         @Override
    442         protected SortedMap<String, String> create(Entry<String, String>[] entries) {
    443           SortedMap<String, String> map = new NonNavigableSortedMap();
    444           putEntries(map, entries);
    445           map.putAll(ENTRIES_TO_FILTER);
    446           return Maps.filterValues(map, FILTER_VALUES);
    447         }
    448       })
    449       .named("Maps.filterValues[SortedMap, Predicate]")
    450       .withFeatures(
    451           MapFeature.ALLOWS_NULL_VALUES,
    452           MapFeature.GENERAL_PURPOSE,
    453           CollectionSize.ANY)
    454       .createTestSuite());
    455     suite.addTest(SortedMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
    456         @Override
    457         protected SortedMap<String, String> create(Entry<String, String>[] entries) {
    458           SortedMap<String, String> map = new NonNavigableSortedMap();
    459           putEntries(map, entries);
    460           map.putAll(ENTRIES_TO_FILTER);
    461           return Maps.filterEntries(map, FILTER_ENTRIES);
    462         }
    463       })
    464       .named("Maps.filterEntries[SortedMap, Predicate]")
    465       .withFeatures(
    466           MapFeature.ALLOWS_NULL_VALUES,
    467           MapFeature.GENERAL_PURPOSE,
    468           CollectionSize.ANY)
    469       .createTestSuite());
    470     return suite;
    471   }
    472 
    473   static TestSuite filterNavigableMapSuite() {
    474     TestSuite suite = new TestSuite("FilterNavigableMap");
    475     suite.addTest(NavigableMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
    476       @Override
    477       protected NavigableMap<String, String> create(Entry<String, String>[] entries) {
    478         NavigableMap<String, String> map = new SafeTreeMap<String, String>();
    479         putEntries(map, entries);
    480         map.put("banana", "toast");
    481         map.put("eggplant", "spam");
    482         return Maps.filterKeys(map, FILTER_KEYS);
    483       }
    484     })
    485     .named("Maps.filterKeys[NavigableMap, Predicate]")
    486     .withFeatures(
    487         MapFeature.ALLOWS_NULL_VALUES,
    488         MapFeature.GENERAL_PURPOSE,
    489         CollectionSize.ANY)
    490         .createTestSuite());
    491     suite.addTest(NavigableMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
    492       @Override
    493       protected NavigableMap<String, String> create(Entry<String, String>[] entries) {
    494         NavigableMap<String, String> map = new SafeTreeMap<String, String>();
    495         putEntries(map, entries);
    496         map.put("banana", "toast");
    497         map.put("eggplant", "spam");
    498           return Maps.filterValues(map, FILTER_VALUES);
    499         }
    500       })
    501       .named("Maps.filterValues[NavigableMap, Predicate]")
    502       .withFeatures(
    503           MapFeature.ALLOWS_NULL_VALUES,
    504           MapFeature.GENERAL_PURPOSE,
    505           CollectionSize.ANY)
    506           .createTestSuite());
    507     suite.addTest(NavigableMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
    508       @Override
    509       protected NavigableMap<String, String> create(Entry<String, String>[] entries) {
    510         NavigableMap<String, String> map = new SafeTreeMap<String, String>();
    511         putEntries(map, entries);
    512         map.put("banana", "toast");
    513         map.put("eggplant", "spam");
    514           return Maps.filterEntries(map, FILTER_ENTRIES);
    515         }
    516       })
    517       .named("Maps.filterEntries[NavigableMap, Predicate]")
    518       .withFeatures(
    519           MapFeature.ALLOWS_NULL_VALUES,
    520           MapFeature.GENERAL_PURPOSE,
    521           CollectionSize.ANY)
    522           .createTestSuite());
    523     return suite;
    524   }
    525 
    526   static void putEntries(Map<String, String> map, Entry<String, String>[] entries) {
    527     for (Entry<String, String> entry : entries) {
    528        map.put(entry.getKey(), entry.getValue());
    529      }
    530   }
    531 
    532   static final Predicate<String> FILTER_KEYS = new Predicate<String>() {
    533     @Override
    534     public boolean apply(@Nullable String string) {
    535       return !"banana".equals(string) && !"eggplant".equals(string);
    536     }
    537   };
    538 
    539   static final Predicate<String> FILTER_VALUES = new Predicate<String>() {
    540     @Override
    541     public boolean apply(@Nullable String string) {
    542       return !"toast".equals(string) && !"spam".equals(string);
    543     }
    544   };
    545 
    546   static final Predicate<Entry<String, String>> FILTER_ENTRIES =
    547       new Predicate<Entry<String, String>>() {
    548     @Override
    549     public boolean apply(Entry<String, String> entry) {
    550       return !Helpers.mapEntry("banana", "toast").equals(entry)
    551           && !Helpers.mapEntry("eggplant", "spam").equals(entry);
    552     }
    553   };
    554 
    555   static final Predicate<Entry<String, String>> FILTER_ENTRIES_1 =
    556       new Predicate<Entry<String, String>>() {
    557     @Override
    558     public boolean apply(Entry<String, String> entry) {
    559       return !Helpers.mapEntry("banana", "toast").equals(entry);
    560     }
    561   };
    562 
    563   static final Predicate<Entry<String, String>> FILTER_ENTRIES_2 =
    564       new Predicate<Entry<String, String>>() {
    565     @Override
    566     public boolean apply(Entry<String, String> entry) {
    567       return !Helpers.mapEntry("eggplant", "spam").equals(entry);
    568     }
    569   };
    570 
    571   static final Map<String, String> ENTRIES_TO_FILTER =
    572       ImmutableMap.of("banana", "toast", "eggplant", "spam");
    573 
    574   static final Predicate<Entry<String, String>> NOT_NULL_ENTRY =
    575       new Predicate<Entry<String, String>>() {
    576     @Override
    577     public boolean apply(Entry<String, String> entry) {
    578       return entry.getKey() != null && entry.getValue() != null;
    579     }
    580   };
    581 
    582   private static class NonNavigableSortedSet
    583       extends ForwardingSortedSet<String> {
    584 
    585     private final SortedSet<String> delegate = Sets.newTreeSet(Ordering.natural());
    586 
    587     @Override
    588     protected SortedSet<String> delegate() {
    589       return delegate;
    590     }
    591   }
    592 
    593   private static class NonNavigableSortedMap
    594       extends ForwardingSortedMap<String, String> {
    595 
    596     private final SortedMap<String, String> delegate =
    597         new SafeTreeMap<String, String>(Ordering.natural());
    598 
    599     @Override
    600     protected SortedMap<String, String> delegate() {
    601       return delegate;
    602     }
    603   }
    604 
    605   private static String encode(String str) {
    606     return BaseEncoding.base64().encode(str.getBytes(Charsets.UTF_8));
    607   }
    608 
    609   private static final Function<String, String> DECODE_FUNCTION = new Function<String, String>() {
    610     @Override
    611     public String apply(String input) {
    612       return new String(BaseEncoding.base64().decode(input), Charsets.UTF_8);
    613     }
    614   };
    615 
    616   private static final EntryTransformer<String, String, String> DECODE_ENTRY_TRANSFORMER =
    617       new EntryTransformer<String, String, String>() {
    618     @Override
    619     public String transformEntry(String key, String value) {
    620       return DECODE_FUNCTION.apply(value);
    621     }
    622   };
    623 
    624   static TestSuite transformSuite() {
    625     TestSuite suite = new TestSuite("Maps.transform");
    626     suite.addTest(transformMapSuite());
    627     suite.addTest(transformSortedMapSuite());
    628     suite.addTest(transformNavigableMapSuite());
    629     return suite;
    630   }
    631 
    632   static TestSuite transformMapSuite() {
    633     TestSuite suite = new TestSuite("TransformMap");
    634     suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() {
    635         @Override
    636         protected Map<String, String> create(Entry<String, String>[] entries) {
    637           Map<String, String> map = Maps.newLinkedHashMap();
    638           for (Entry<String, String> entry : entries) {
    639             map.put(entry.getKey(), encode(entry.getValue()));
    640           }
    641           return Maps.transformValues(map, DECODE_FUNCTION);
    642         }
    643       })
    644       .named("Maps.transformValues[Map, Function]")
    645       .withFeatures(
    646           CollectionSize.ANY,
    647           CollectionFeature.KNOWN_ORDER,
    648           MapFeature.ALLOWS_NULL_KEYS,
    649           MapFeature.ALLOWS_ANY_NULL_QUERIES,
    650           MapFeature.SUPPORTS_REMOVE,
    651           CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    652       .createTestSuite());
    653     suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() {
    654         @Override
    655         protected Map<String, String> create(Entry<String, String>[] entries) {
    656           Map<String, String> map = Maps.newLinkedHashMap();
    657           for (Entry<String, String> entry : entries) {
    658             map.put(entry.getKey(), encode(entry.getValue()));
    659           }
    660           return Maps.transformEntries(map, DECODE_ENTRY_TRANSFORMER);
    661         }
    662       })
    663       .named("Maps.transformEntries[Map, EntryTransformer]")
    664       .withFeatures(
    665           CollectionSize.ANY,
    666           CollectionFeature.KNOWN_ORDER,
    667           MapFeature.ALLOWS_NULL_KEYS,
    668           MapFeature.ALLOWS_ANY_NULL_QUERIES,
    669           MapFeature.SUPPORTS_REMOVE,
    670           CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    671       .createTestSuite());
    672     return suite;
    673   }
    674 
    675   static TestSuite transformSortedMapSuite() {
    676     TestSuite suite = new TestSuite("TransformSortedMap");
    677     suite.addTest(SortedMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
    678         @Override
    679         protected SortedMap<String, String> create(Entry<String, String>[] entries) {
    680           SortedMap<String, String> map = new NonNavigableSortedMap();
    681           for (Entry<String, String> entry : entries) {
    682             map.put(entry.getKey(), encode(entry.getValue()));
    683           }
    684           return Maps.transformValues(map, DECODE_FUNCTION);
    685         }
    686       })
    687       .named("Maps.transformValues[SortedMap, Function]")
    688       .withFeatures(
    689           CollectionSize.ANY,
    690           CollectionFeature.KNOWN_ORDER,
    691           MapFeature.SUPPORTS_REMOVE,
    692           CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    693       .createTestSuite());
    694     suite.addTest(SortedMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
    695         @Override
    696         protected SortedMap<String, String> create(Entry<String, String>[] entries) {
    697           SortedMap<String, String> map = new NonNavigableSortedMap();
    698           for (Entry<String, String> entry : entries) {
    699             map.put(entry.getKey(), encode(entry.getValue()));
    700           }
    701           return Maps.transformEntries(map, DECODE_ENTRY_TRANSFORMER);
    702         }
    703       })
    704       .named("Maps.transformEntries[SortedMap, EntryTransformer]")
    705       .withFeatures(
    706           CollectionSize.ANY,
    707           CollectionFeature.KNOWN_ORDER,
    708           MapFeature.SUPPORTS_REMOVE,
    709           CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    710       .createTestSuite());
    711     return suite;
    712   }
    713 
    714   static TestSuite transformNavigableMapSuite() {
    715     TestSuite suite = new TestSuite("TransformNavigableMap");
    716     suite.addTest(NavigableMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
    717         @Override
    718         protected NavigableMap<String, String> create(Entry<String, String>[] entries) {
    719           NavigableMap<String, String> map = new SafeTreeMap<String, String>();
    720           for (Entry<String, String> entry : entries) {
    721             map.put(entry.getKey(), encode(entry.getValue()));
    722           }
    723           return Maps.transformValues(map, DECODE_FUNCTION);
    724         }
    725       })
    726       .named("Maps.transformValues[NavigableMap, Function]")
    727       .withFeatures(
    728           CollectionSize.ANY,
    729           CollectionFeature.KNOWN_ORDER,
    730           MapFeature.SUPPORTS_REMOVE,
    731           CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    732       .createTestSuite());
    733     suite.addTest(NavigableMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
    734         @Override
    735         protected NavigableMap<String, String> create(Entry<String, String>[] entries) {
    736           NavigableMap<String, String> map = new SafeTreeMap<String, String>();
    737           for (Entry<String, String> entry : entries) {
    738             map.put(entry.getKey(), encode(entry.getValue()));
    739           }
    740           return Maps.transformEntries(map, DECODE_ENTRY_TRANSFORMER);
    741         }
    742       })
    743       .named("Maps.transformEntries[NavigableMap, EntryTransformer]")
    744       .withFeatures(
    745           CollectionSize.ANY,
    746           CollectionFeature.KNOWN_ORDER,
    747           MapFeature.SUPPORTS_REMOVE,
    748           CollectionFeature.SUPPORTS_ITERATOR_REMOVE)
    749       .createTestSuite());
    750     return suite;
    751   }
    752 }
    753