View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.collection;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertThrows;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.Collection;
27  import java.util.HashSet;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.function.Predicate;
31  
32  import org.junit.jupiter.api.Test;
33  
34  /**
35   * Extension of {@link AbstractCollectionTest} for exercising the
36   * {@link CompositeCollection} implementation.
37   */
38  public class CompositeCollectionTest<E> extends AbstractCollectionTest<E> {
39  
40      protected CompositeCollection<E> c;
41  
42      protected Collection<E> one;
43  
44      protected Collection<E> two;
45  
46      public CompositeCollectionTest() {
47          super(CompositeCollectionTest.class.getSimpleName());
48      }
49  
50      @Override
51      public String getCompatibilityVersion() {
52          return "4";
53      }
54  
55      @Override
56      @SuppressWarnings("unchecked")
57      public E[] getFullElements() {
58          return (E[]) new Object[] { "1", "2", "3", "4" };
59      }
60  
61      /**
62       * Run stock collection tests without Mutator, so turn off add, remove
63       */
64      @Override
65      public boolean isAddSupported() {
66          return false;
67      }
68  
69      @Override
70      public boolean isRemoveSupported() {
71          return false;
72      }
73  
74      @Override
75      public Collection<E> makeConfirmedCollection() {
76          return new HashSet<>();
77      }
78  
79      /**
80       * Full collection should look like a collection with 4 elements
81       */
82      @Override
83      public Collection<E> makeConfirmedFullCollection() {
84          return new HashSet<>(Arrays.asList(getFullElements()));
85      }
86      /**
87       * Full collection consists of 4 collections, each with one element
88       */
89      @Override
90      public Collection<E> makeFullCollection() {
91          final CompositeCollection<E> compositeCollection = new CompositeCollection<>();
92          final E[] elements = getFullElements();
93          for (final E element : elements) {
94              final Collection<E> summand = new HashSet<>();
95              summand.add(element);
96              compositeCollection.addComposited(summand);
97          }
98          return compositeCollection;
99      }
100     /**
101      * Empty collection is empty composite
102      */
103     @Override
104     public Collection<E> makeObject() {
105         return new CompositeCollection<>();
106     }
107 
108     @SuppressWarnings("serial")
109     protected void setUpMutatorTest() {
110         setUpTest();
111         c.setMutator(new CompositeCollection.CollectionMutator<E>() {
112 
113             private static final long serialVersionUID = 1L;
114 
115             @Override
116             public boolean add(final CompositeCollection<E> composite, final List<Collection<E>> collections, final E obj) {
117                 for (final Collection<E> coll : collections) {
118                     coll.add(obj);
119                 }
120                 return true;
121             }
122 
123             @Override
124             public boolean addAll(final CompositeCollection<E> composite,
125                     final List<Collection<E>> collections, final Collection<? extends E> coll) {
126                 for (final Collection<E> collection : collections) {
127                     collection.addAll(coll);
128                 }
129                 return true;
130             }
131 
132             @Override
133             public boolean remove(final CompositeCollection<E> composite,
134                     final List<Collection<E>> collections, final Object obj) {
135                 for (final Collection<E> collection : collections) {
136                     collection.remove(obj);
137                 }
138                 return true;
139             }
140         });
141     }
142 
143     protected void setUpTest() {
144         c = new CompositeCollection<>();
145         one = new HashSet<>();
146         two = new HashSet<>();
147     }
148 
149     @Test
150     @SuppressWarnings({ "unchecked", "serial" })
151     public void testAddAllMutator() {
152         setUpTest();
153         c.setMutator(new CompositeCollection.CollectionMutator<E>() {
154             @Override
155             public boolean add(final CompositeCollection<E> composite,
156                     final List<Collection<E>> collections, final E obj) {
157                 for (final Collection<E> collection : collections) {
158                     collection.add(obj);
159                 }
160                 return true;
161             }
162 
163             @Override
164             public boolean addAll(final CompositeCollection<E> composite,
165                     final List<Collection<E>> collections, final Collection<? extends E> coll) {
166                 for (final Collection<E> collection : collections) {
167                     collection.addAll(coll);
168                 }
169                 return true;
170             }
171 
172             @Override
173             public boolean remove(final CompositeCollection<E> composite,
174                     final List<Collection<E>> collections, final Object obj) {
175                 return false;
176             }
177         });
178 
179         c.addComposited(one);
180         two.add((E) "foo");
181         c.addAll(two);
182         assertTrue(c.contains("foo"));
183         assertTrue(one.contains("foo"));
184     }
185 
186     @Test
187     @SuppressWarnings("unchecked")
188     public void testAddAllToCollection() {
189         setUpTest();
190         one.add((E) "1");
191         two.add((E) "2");
192         c.addComposited(one, two);
193         final Collection<E> toCollection = new HashSet<>(c);
194         assertTrue(toCollection.containsAll(c));
195         assertEquals(c.size(), toCollection.size());
196     }
197 
198     @Test
199     @SuppressWarnings({ "unchecked", "serial" })
200     public void testAddMutator() {
201         setUpTest();
202         c.setMutator(new CompositeCollection.CollectionMutator<E>() {
203             @Override
204             public boolean add(final CompositeCollection<E> composite,
205                     final List<Collection<E>> collections, final E obj) {
206                 for (final Collection<E> collection : collections) {
207                     collection.add(obj);
208                 }
209                 return true;
210             }
211 
212             @Override
213             public boolean addAll(final CompositeCollection<E> composite,
214                     final List<Collection<E>> collections, final Collection<? extends E> coll) {
215                 for (final Collection<E> collection : collections) {
216                     collection.addAll(coll);
217                 }
218                 return true;
219             }
220 
221             @Override
222             public boolean remove(final CompositeCollection<E> composite,
223                     final List<Collection<E>> collections, final Object obj) {
224                 return false;
225             }
226         });
227 
228         c.addComposited(one);
229         c.add((E) "foo");
230         assertTrue(c.contains("foo"));
231         assertTrue(one.contains("foo"));
232     }
233 
234     @Test
235     public void testAddNullList() {
236         final ArrayList<String> nullList = null;
237         final CompositeCollection<String> cc = new CompositeCollection<>();
238         cc.addComposited(nullList);
239         assertEquals(0, cc.size());
240     }
241 
242     @Test
243     public void testAddNullLists2Args() {
244         final ArrayList<String> nullList = null;
245         final CompositeCollection<String> cc = new CompositeCollection<>();
246         cc.addComposited(nullList, nullList);
247         assertEquals(0, cc.size());
248     }
249 
250     @Test
251     public void testAddNullListsVarArgs() {
252         final ArrayList<String> nullList = null;
253         final CompositeCollection<String> cc = new CompositeCollection<>();
254         cc.addComposited(nullList, nullList, nullList);
255         assertEquals(0, cc.size());
256     }
257 
258     @Test
259     @SuppressWarnings("unchecked")
260     public void testClear() {
261         setUpTest();
262         one.add((E) "1");
263         two.add((E) "2");
264         c.addComposited(one, two);
265         c.clear();
266         assertTrue(one.isEmpty());
267         assertTrue(two.isEmpty());
268         assertTrue(c.isEmpty());
269     }
270 
271     @Test
272     @SuppressWarnings("unchecked")
273     public void testContainsAll() {
274         setUpTest();
275         one.add((E) "1");
276         two.add((E) "1");
277         c.addComposited(one);
278         assertTrue(c.containsAll(two));
279         assertFalse(c.containsAll(null));
280     }
281 
282     @Test
283     @SuppressWarnings("unchecked")
284     public void testIsEmpty() {
285         setUpTest();
286         assertTrue(c.isEmpty());
287         final HashSet<E> empty = new HashSet<>();
288         c.addComposited(empty);
289         assertTrue(c.isEmpty());
290         empty.add((E) "a");
291         assertFalse(c.isEmpty());
292     }
293 
294     @Test
295     @SuppressWarnings("unchecked")
296     public void testIterator() {
297         setUpTest();
298         one.add((E) "1");
299         two.add((E) "2");
300         c.addComposited(one);
301         c.addComposited(two);
302         final Iterator<E> i = c.iterator();
303         E next = i.next();
304         assertTrue(c.contains(next));
305         assertTrue(one.contains(next));
306         next = i.next();
307         i.remove();
308         assertFalse(c.contains(next));
309         assertFalse(two.contains(next));
310     }
311 
312     @Test
313     @SuppressWarnings("unchecked")
314     public void testMultipleCollectionsSize() {
315         setUpTest();
316         final HashSet<E> set = new HashSet<>();
317         set.add((E) "a");
318         set.add((E) "b");
319         c.addComposited(set);
320         final HashSet<E> other = new HashSet<>();
321         other.add((E) "c");
322         c.addComposited(other);
323         assertEquals(set.size() + other.size(), c.size());
324     }
325 
326     @Test
327     @SuppressWarnings("unchecked")
328     public void testRemove() {
329         setUpMutatorTest();
330         one.add((E) "1");
331         two.add((E) "2");
332         two.add((E) "1");
333         c.addComposited(one, two);
334         c.remove("1");
335         assertFalse(c.contains("1"));
336         assertFalse(one.contains("1"));
337         assertFalse(two.contains("1"));
338     }
339 
340     @Test
341     @SuppressWarnings("unchecked")
342     public void testRemoveAll() {
343         setUpMutatorTest();
344         one.add((E) "1");
345         two.add((E) "2");
346         two.add((E) "1");
347         // need separate list to remove, as otherwise one clears itself
348         final Collection<E> removing = new ArrayList<>(one);
349         c.addComposited(one, two);
350         c.removeAll(removing);
351         assertFalse(c.contains("1"));
352         assertFalse(one.contains("1"));
353         assertFalse(two.contains("1"));
354         c.removeAll(null);
355         assertFalse(c.contains("1"));
356         assertFalse(one.contains("1"));
357         assertFalse(two.contains("1"));
358     }
359 
360     @Test
361     @SuppressWarnings("unchecked")
362     public void testRemoveComposited() {
363         setUpMutatorTest();
364         one.add((E) "1");
365         two.add((E) "2");
366         two.add((E) "1");
367         c.addComposited(one, two);
368         c.removeComposited(one);
369         assertTrue(c.contains("1"));
370         assertEquals(2, c.size());
371     }
372 
373     /**
374      */
375     @Test
376     @SuppressWarnings("unchecked")
377     public void testRemoveIf() {
378         setUpMutatorTest();
379         one.add((E) "1");
380         two.add((E) "2");
381         two.add((E) "1");
382         // need separate list to remove, as otherwise one clears itself
383         final Predicate<E> predicate = e -> e == "1";
384         c.addComposited(one, two);
385         c.removeIf(predicate);
386         assertFalse(c.contains("1"));
387         assertFalse(one.contains("1"));
388         assertFalse(two.contains("1"));
389         c.removeIf(null);
390         assertFalse(c.contains("1"));
391         assertFalse(one.contains("1"));
392         assertFalse(two.contains("1"));
393     }
394 
395     @Test
396     @SuppressWarnings("unchecked")
397     public void testRetainAll() {
398         setUpTest();
399         one.add((E) "1");
400         one.add((E) "2");
401         two.add((E) "1");
402         c.addComposited(one);
403         c.retainAll(two);
404         assertFalse(c.contains("2"));
405         assertFalse(one.contains("2"));
406         assertTrue(c.contains("1"));
407         assertTrue(one.contains("1"));
408         c.retainAll(null);
409         assertFalse(c.contains("2"));
410         assertFalse(one.contains("2"));
411         assertTrue(c.contains("1"));
412         assertTrue(one.contains("1"));
413     }
414 
415     @Test
416     @SuppressWarnings("unchecked")
417     public void testSize() {
418         setUpTest();
419         final HashSet<E> set = new HashSet<>();
420         set.add((E) "a");
421         set.add((E) "b");
422         c.addComposited(set);
423         assertEquals(set.size(), c.size());
424     }
425 
426     @Test
427     @SuppressWarnings("unchecked")
428     public void testToCollection() {
429         setUpTest();
430         one.add((E) "1");
431         two.add((E) "2");
432         c.addComposited(one, two);
433         final Collection<E> foo = c.toCollection();
434         assertTrue(foo.containsAll(c));
435         assertEquals(c.size(), foo.size());
436         one.add((E) "3");
437         assertFalse(foo.containsAll(c));
438     }
439 
440     /**
441      * Override testUnsupportedRemove, since the default impl expects removeAll,
442      * retainAll and iterator().remove to throw
443      */
444     @Test
445     @Override
446     public void testUnsupportedRemove() {
447         resetFull();
448 
449         assertThrows(UnsupportedOperationException.class, () -> getCollection().remove(null));
450 
451         verify();
452     }
453 
454 //    public void testCreate() throws Exception {
455 //        resetEmpty();
456 //        writeExternalFormToDisk((java.io.Serializable) getCollection(), "src/test/resources/data/test/CompositeCollection.emptyCollection.version4.obj");
457 //        resetFull();
458 //        writeExternalFormToDisk((java.io.Serializable) getCollection(), "src/test/resources/data/test/CompositeCollection.fullCollection.version4.obj");
459 //    }
460 
461 }