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