1/*
2 * Copyright (C) 2011 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
17package com.google.common.collect;
18
19import com.google.common.annotations.GwtCompatible;
20import com.google.common.annotations.GwtIncompatible;
21import com.google.common.collect.testing.SampleElements;
22import com.google.common.collect.testing.SetTestSuiteBuilder;
23import com.google.common.collect.testing.TestSetGenerator;
24import com.google.common.collect.testing.features.CollectionFeature;
25import com.google.common.collect.testing.features.CollectionSize;
26import com.google.common.collect.testing.features.SetFeature;
27
28import junit.framework.TestCase;
29import junit.framework.TestSuite;
30
31import java.util.Arrays;
32import java.util.List;
33import java.util.Set;
34
35/**
36 * Tests for {@link Sets#transform(Set, Sets.InvertibleFunction)}.
37 *
38 * @author Dimitris Andreou
39 */
40@GwtCompatible(emulated = true)
41public class TransformedSetTest extends TestCase {
42  // Negates each integer. This is a true bijection, even considering MIN_VALUE
43  private static final Sets.InvertibleFunction<Integer, Integer> integerBijection =
44      new Sets.InvertibleFunction<Integer, Integer>() {
45        @Override public Integer apply(Integer integer) {
46          return integer != null ? -integer : null;
47        }
48
49        @Override
50        public Integer invert(Integer integer) {
51          return integer != null ? -integer : null;
52        }
53      };
54
55  @GwtIncompatible("suite")
56  public static TestSuite suite() {
57    TestSuite suite = new TestSuite();
58    suite.addTest(SetTestSuiteBuilder
59        .using(new TransformedIntegerSetGenerator())
60        .named("TransformedSet")
61        .withFeatures(
62        SetFeature.GENERAL_PURPOSE,
63        CollectionFeature.ALLOWS_NULL_VALUES,
64        CollectionSize.SEVERAL)
65      .createTestSuite());
66    return suite;
67  }
68
69  public void testSimpleCases() {
70    Set<Integer> original = Sets.newHashSet(0, 1, 2, 3);
71    Set<Integer> transformed = Sets.transform(original, integerBijection);
72
73    assertEquals(ImmutableSet.of(0, -1, -2, -3), transformed);
74
75    // adding/removing to the original, see if transformed is affected
76    assertTrue(original.remove(2));
77    assertTrue(original.add(4));
78    assertEquals(ImmutableSet.of(0,  1,  3,  4), original);
79    assertEquals(ImmutableSet.of(0, -1, -3, -4), transformed);
80
81    // adding/removing to the transformed, see if original is affected
82    assertTrue(transformed.remove(-1));
83    assertTrue(transformed.add(-5));
84    assertEquals(ImmutableSet.of(0, -3, -4, -5), transformed);
85    assertEquals(ImmutableSet.of(0,  3,  4,  5), original);
86
87    // redoing the same actions as above; no effect
88    assertFalse(transformed.remove(-1));
89    assertFalse(transformed.add(-5));
90
91    // they should always have the same size
92    assertEquals(original.size(), transformed.size());
93
94    transformed.clear();
95    assertTrue(original.isEmpty());
96    assertTrue(transformed.isEmpty());
97  }
98
99  public static class TransformedIntegerSetGenerator implements TestSetGenerator<Integer> {
100    @Override public Set<Integer> create(Object... elements) {
101      // Would use Collections#checkedCollection, but I get:
102      // [ERROR] The method checkedCollection(Collection, Class<Integer>)
103      // is undefined for the type Collections
104      @SuppressWarnings("unchecked")
105      Iterable<Integer> integers = (Iterable) Arrays.asList(elements);
106
107      // I invert these before adding, so that the transformed set will have
108      // the expected elements themselves, not their image under the bijection
109      Set<Integer> invertedIntegers = Sets.newHashSet(Iterables.transform(integers,
110          integerBijection.inverse()));
111      return Sets.transform(invertedIntegers, integerBijection);
112    }
113
114    @Override public Integer[] createArray(int length) {
115      return new Integer[length];
116    }
117
118    @Override public SampleElements<Integer> samples() {
119      return new SampleElements<Integer>(-1, 0, 1, 2, 3);
120    }
121
122    @Override public Iterable<Integer> order(List<Integer> insertionOrder) {
123      throw new AssertionError();
124    }
125  }
126}
127