• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 java.util.Arrays.asList;
20 import static org.junit.contrib.truth.Truth.ASSERT;
21 
22 import com.google.common.annotations.GwtCompatible;
23 import com.google.common.annotations.GwtIncompatible;
24 import com.google.common.testing.SerializableTester;
25 
26 import junit.framework.TestCase;
27 
28 import java.util.AbstractCollection;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.ListIterator;
34 import java.util.RandomAccess;
35 import java.util.Set;
36 import java.util.SortedSet;
37 
38 /**
39  * Tests for {@code Constraints}.
40  *
41  * @author Mike Bostock
42  * @author Jared Levy
43  */
44 @GwtCompatible(emulated = true)
45 public class ConstraintsTest extends TestCase {
46 
47   private static final String TEST_ELEMENT = "test";
48 
49   private static final class TestElementException
50       extends IllegalArgumentException {
51     private static final long serialVersionUID = 0;
52   }
53 
54   private static final Constraint<String> TEST_CONSTRAINT
55       = new Constraint<String>() {
56           @Override
57           public String checkElement(String element) {
58             if (TEST_ELEMENT.equals(element)) {
59               throw new TestElementException();
60             }
61             return element;
62           }
63         };
64 
testNotNull()65   public void testNotNull() {
66     Constraint<? super String> constraint = Constraints.notNull();
67     assertSame(TEST_ELEMENT, constraint.checkElement(TEST_ELEMENT));
68     try {
69       constraint.checkElement(null);
70       fail("NullPointerException expected");
71     } catch (NullPointerException expected) {}
72     assertEquals("Not null", constraint.toString());
73   }
74 
testConstrainedCollectionLegal()75   public void testConstrainedCollectionLegal() {
76     Collection<String> collection = Lists.newArrayList("foo", "bar");
77     Collection<String> constrained = Constraints.constrainedCollection(
78         collection, TEST_CONSTRAINT);
79     collection.add(TEST_ELEMENT);
80     constrained.add("qux");
81     constrained.addAll(asList("cat", "dog"));
82     /* equals and hashCode aren't defined for Collection */
83     ASSERT.that(collection).hasContentsInOrder("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog");
84     ASSERT.that(constrained).hasContentsInOrder("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog");
85   }
86 
testConstrainedCollectionIllegal()87   public void testConstrainedCollectionIllegal() {
88     Collection<String> collection = Lists.newArrayList("foo", "bar");
89     Collection<String> constrained = Constraints.constrainedCollection(
90         collection, TEST_CONSTRAINT);
91     try {
92       constrained.add(TEST_ELEMENT);
93       fail("TestElementException expected");
94     } catch (TestElementException expected) {}
95     try {
96       constrained.addAll(asList("baz", TEST_ELEMENT));
97       fail("TestElementException expected");
98     } catch (TestElementException expected) {}
99     ASSERT.that(constrained).hasContentsInOrder("foo", "bar");
100     ASSERT.that(collection).hasContentsInOrder("foo", "bar");
101   }
102 
testConstrainedSetLegal()103   public void testConstrainedSetLegal() {
104     Set<String> set = Sets.newLinkedHashSet(asList("foo", "bar"));
105     Set<String> constrained = Constraints.constrainedSet(set, TEST_CONSTRAINT);
106     set.add(TEST_ELEMENT);
107     constrained.add("qux");
108     constrained.addAll(asList("cat", "dog"));
109     assertTrue(set.equals(constrained));
110     assertTrue(constrained.equals(set));
111     assertEquals(set.toString(), constrained.toString());
112     assertEquals(set.hashCode(), constrained.hashCode());
113     ASSERT.that(set).hasContentsInOrder("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog");
114     ASSERT.that(constrained).hasContentsInOrder("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog");
115   }
116 
testConstrainedSetIllegal()117   public void testConstrainedSetIllegal() {
118     Set<String> set = Sets.newLinkedHashSet(asList("foo", "bar"));
119     Set<String> constrained = Constraints.constrainedSet(set, TEST_CONSTRAINT);
120     try {
121       constrained.add(TEST_ELEMENT);
122       fail("TestElementException expected");
123     } catch (TestElementException expected) {}
124     try {
125       constrained.addAll(asList("baz", TEST_ELEMENT));
126       fail("TestElementException expected");
127     } catch (TestElementException expected) {}
128     ASSERT.that(constrained).hasContentsInOrder("foo", "bar");
129     ASSERT.that(set).hasContentsInOrder("foo", "bar");
130   }
131 
testConstrainedSortedSetLegal()132   public void testConstrainedSortedSetLegal() {
133     SortedSet<String> sortedSet = Sets.newTreeSet(asList("foo", "bar"));
134     SortedSet<String> constrained = Constraints.constrainedSortedSet(
135         sortedSet, TEST_CONSTRAINT);
136     sortedSet.add(TEST_ELEMENT);
137     constrained.add("qux");
138     constrained.addAll(asList("cat", "dog"));
139     assertTrue(sortedSet.equals(constrained));
140     assertTrue(constrained.equals(sortedSet));
141     assertEquals(sortedSet.toString(), constrained.toString());
142     assertEquals(sortedSet.hashCode(), constrained.hashCode());
143     ASSERT.that(sortedSet).hasContentsInOrder("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT);
144     ASSERT.that(constrained).hasContentsInOrder("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT);
145     assertNull(constrained.comparator());
146     assertEquals("bar", constrained.first());
147     assertEquals(TEST_ELEMENT, constrained.last());
148   }
149 
testConstrainedSortedSetIllegal()150   public void testConstrainedSortedSetIllegal() {
151     SortedSet<String> sortedSet = Sets.newTreeSet(asList("foo", "bar"));
152     SortedSet<String> constrained = Constraints.constrainedSortedSet(
153         sortedSet, TEST_CONSTRAINT);
154     try {
155       constrained.add(TEST_ELEMENT);
156       fail("TestElementException expected");
157     } catch (TestElementException expected) {}
158     try {
159       constrained.subSet("bar", "foo").add(TEST_ELEMENT);
160       fail("TestElementException expected");
161     } catch (TestElementException expected) {}
162     try {
163       constrained.headSet("bar").add(TEST_ELEMENT);
164       fail("TestElementException expected");
165     } catch (TestElementException expected) {}
166     try {
167       constrained.tailSet("foo").add(TEST_ELEMENT);
168       fail("TestElementException expected");
169     } catch (TestElementException expected) {}
170     try {
171       constrained.addAll(asList("baz", TEST_ELEMENT));
172       fail("TestElementException expected");
173     } catch (TestElementException expected) {}
174     ASSERT.that(constrained).hasContentsInOrder("bar", "foo");
175     ASSERT.that(sortedSet).hasContentsInOrder("bar", "foo");
176   }
177 
testConstrainedListLegal()178   public void testConstrainedListLegal() {
179     List<String> list = Lists.newArrayList("foo", "bar");
180     List<String> constrained = Constraints.constrainedList(
181         list, TEST_CONSTRAINT);
182     list.add(TEST_ELEMENT);
183     constrained.add("qux");
184     constrained.addAll(asList("cat", "dog"));
185     constrained.add(1, "cow");
186     constrained.addAll(4, asList("box", "fan"));
187     constrained.set(2, "baz");
188     assertTrue(list.equals(constrained));
189     assertTrue(constrained.equals(list));
190     assertEquals(list.toString(), constrained.toString());
191     assertEquals(list.hashCode(), constrained.hashCode());
192     ASSERT.that(list).hasContentsInOrder(
193         "foo", "cow", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog");
194     ASSERT.that(constrained).hasContentsInOrder(
195         "foo", "cow", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog");
196     ListIterator<String> iterator = constrained.listIterator();
197     iterator.next();
198     iterator.set("sun");
199     constrained.listIterator(2).add("sky");
200     ASSERT.that(list).hasContentsInOrder(
201         "sun", "cow", "sky", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog");
202     ASSERT.that(constrained).hasContentsInOrder(
203         "sun", "cow", "sky", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog");
204     assertTrue(constrained instanceof RandomAccess);
205   }
206 
testConstrainedListRandomAccessFalse()207   public void testConstrainedListRandomAccessFalse() {
208     List<String> list = Lists.newLinkedList(asList("foo", "bar"));
209     List<String> constrained = Constraints.constrainedList(
210         list, TEST_CONSTRAINT);
211     list.add(TEST_ELEMENT);
212     constrained.add("qux");
213     assertFalse(constrained instanceof RandomAccess);
214   }
215 
testConstrainedListIllegal()216   public void testConstrainedListIllegal() {
217     List<String> list = Lists.newArrayList("foo", "bar");
218     List<String> constrained = Constraints.constrainedList(
219         list, TEST_CONSTRAINT);
220     try {
221       constrained.add(TEST_ELEMENT);
222       fail("TestElementException expected");
223     } catch (TestElementException expected) {}
224     try {
225       constrained.listIterator().add(TEST_ELEMENT);
226       fail("TestElementException expected");
227     } catch (TestElementException expected) {}
228     try {
229       constrained.listIterator(1).add(TEST_ELEMENT);
230       fail("TestElementException expected");
231     } catch (TestElementException expected) {}
232     try {
233       constrained.listIterator().set(TEST_ELEMENT);
234       fail("TestElementException expected");
235     } catch (TestElementException expected) {}
236     try {
237       constrained.listIterator(1).set(TEST_ELEMENT);
238       fail("TestElementException expected");
239     } catch (TestElementException expected) {}
240     try {
241       constrained.subList(0, 1).add(TEST_ELEMENT);
242       fail("TestElementException expected");
243     } catch (TestElementException expected) {}
244     try {
245       constrained.add(1, TEST_ELEMENT);
246       fail("TestElementException expected");
247     } catch (TestElementException expected) {}
248     try {
249       constrained.set(1, TEST_ELEMENT);
250       fail("TestElementException expected");
251     } catch (TestElementException expected) {}
252     try {
253       constrained.addAll(asList("baz", TEST_ELEMENT));
254       fail("TestElementException expected");
255     } catch (TestElementException expected) {}
256     try {
257       constrained.addAll(1, asList("baz", TEST_ELEMENT));
258       fail("TestElementException expected");
259     } catch (TestElementException expected) {}
260     ASSERT.that(constrained).hasContentsInOrder("foo", "bar");
261     ASSERT.that(list).hasContentsInOrder("foo", "bar");
262   }
263 
testConstrainedMultisetLegal()264   public void testConstrainedMultisetLegal() {
265     Multiset<String> multiset = HashMultiset.create(asList("foo", "bar"));
266     Multiset<String> constrained = Constraints.constrainedMultiset(
267         multiset, TEST_CONSTRAINT);
268     multiset.add(TEST_ELEMENT);
269     constrained.add("qux");
270     constrained.addAll(asList("cat", "dog"));
271     constrained.add("cow", 2);
272     assertTrue(multiset.equals(constrained));
273     assertTrue(constrained.equals(multiset));
274     assertEquals(multiset.toString(), constrained.toString());
275     assertEquals(multiset.hashCode(), constrained.hashCode());
276     ASSERT.that(multiset).hasContentsAnyOrder(
277         "foo", "bar", TEST_ELEMENT, "qux", "cat", "dog", "cow", "cow");
278     ASSERT.that(constrained).hasContentsAnyOrder(
279         "foo", "bar", TEST_ELEMENT, "qux", "cat", "dog", "cow", "cow");
280     assertEquals(1, constrained.count("foo"));
281     assertEquals(1, constrained.remove("foo", 3));
282     assertEquals(2, constrained.setCount("cow", 0));
283     ASSERT.that(multiset).hasContentsAnyOrder("bar", TEST_ELEMENT, "qux", "cat", "dog");
284     ASSERT.that(constrained).hasContentsAnyOrder("bar", TEST_ELEMENT, "qux", "cat", "dog");
285   }
286 
testConstrainedMultisetIllegal()287   public void testConstrainedMultisetIllegal() {
288     Multiset<String> multiset = HashMultiset.create(asList("foo", "bar"));
289     Multiset<String> constrained = Constraints.constrainedMultiset(
290         multiset, TEST_CONSTRAINT);
291     try {
292       constrained.add(TEST_ELEMENT);
293       fail("TestElementException expected");
294     } catch (TestElementException expected) {}
295     try {
296       constrained.add(TEST_ELEMENT, 2);
297       fail("TestElementException expected");
298     } catch (TestElementException expected) {}
299     try {
300       constrained.addAll(asList("baz", TEST_ELEMENT));
301       fail("TestElementException expected");
302     } catch (TestElementException expected) {}
303     ASSERT.that(constrained).hasContentsAnyOrder("foo", "bar");
304     ASSERT.that(multiset).hasContentsAnyOrder("foo", "bar");
305   }
306 
testNefariousAddAll()307   public void testNefariousAddAll() {
308     List<String> list = Lists.newArrayList("foo", "bar");
309     List<String> constrained = Constraints.constrainedList(
310         list, TEST_CONSTRAINT);
311     Collection<String> onceIterable = onceIterableCollection("baz");
312     constrained.addAll(onceIterable);
313     ASSERT.that(constrained).hasContentsInOrder("foo", "bar", "baz");
314     ASSERT.that(list).hasContentsInOrder("foo", "bar", "baz");
315   }
316 
317   /**
318    * Returns a "nefarious" collection, which permits only one call to
319    * iterator(). This verifies that the constrained collection uses a defensive
320    * copy instead of potentially checking the elements in one snapshot and
321    * adding the elements from another.
322    *
323    * @param element the element to be contained in the collection
324    */
onceIterableCollection(final E element)325   static <E> Collection<E> onceIterableCollection(final E element) {
326     return new AbstractCollection<E>() {
327       boolean iteratorCalled;
328       @Override public int size() {
329         /*
330          * We could make the collection empty, but that seems more likely to
331          * trigger special cases (so maybe we should test both empty and
332          * nonempty...).
333          */
334         return 1;
335       }
336       @Override public Iterator<E> iterator() {
337         assertFalse("Expected only one call to iterator()", iteratorCalled);
338         iteratorCalled = true;
339         return Collections.singleton(element).iterator();
340       }
341     };
342   }
343 
344   @GwtIncompatible("SerializableTester")
testSerialization()345   public void testSerialization() {
346     // TODO: Test serialization of constrained collections.
347     assertSame(Constraints.notNull(),
348         SerializableTester.reserialize(Constraints.notNull()));
349   }
350 }
351