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.queue;
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.io.ByteArrayInputStream;
25  import java.io.ByteArrayOutputStream;
26  import java.io.ObjectInputStream;
27  import java.io.ObjectOutputStream;
28  import java.util.ArrayList;
29  import java.util.Collection;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.NoSuchElementException;
33  import java.util.Queue;
34  
35  import org.junit.jupiter.api.Test;
36  
37  /**
38   * Test cases for CircularFifoQueue.
39   */
40  public class CircularFifoQueueTest<E> extends AbstractQueueTest<E> {
41  
42      /**
43       * {@inheritDoc}
44       */
45      @Override
46      public CircularFifoQueue<E> getCollection() {
47          return (CircularFifoQueue<E>) super.getCollection();
48      }
49  
50      @Override
51      public String getCompatibilityVersion() {
52          return "4";
53      }
54  
55      /**
56       * Overridden because CircularFifoQueue isn't fail fast.
57       * @return false
58       */
59      @Override
60      public boolean isFailFastSupported() {
61          return false;
62      }
63  
64      /**
65       * Overridden because CircularFifoQueue doesn't allow null elements.
66       * @return false
67       */
68      @Override
69      public boolean isNullSupported() {
70          return false;
71      }
72  
73      /**
74       * Returns an empty ArrayList.
75       *
76       * @return an empty ArrayList
77       */
78      @Override
79      public Collection<E> makeConfirmedCollection() {
80          return new ArrayList<>();
81      }
82  
83      /**
84       * Returns a full ArrayList.
85       *
86       * @return a full ArrayList
87       */
88      @Override
89      public Collection<E> makeConfirmedFullCollection() {
90          final Collection<E> c = makeConfirmedCollection();
91          c.addAll(java.util.Arrays.asList(getFullElements()));
92          return c;
93      }
94  
95      /**
96       * Returns an empty CircularFifoQueue that won't overflow.
97       *
98       * @return an empty CircularFifoQueue
99       */
100     @Override
101     public Queue<E> makeObject() {
102         return new CircularFifoQueue<>(100);
103     }
104 
105     @Test
106     public void testAddNull() {
107         final CircularFifoQueue<E> b = new CircularFifoQueue<>(2);
108         assertThrows(NullPointerException.class, () -> b.add(null));
109     }
110 
111     /**
112      * Tests that the removal operation actually removes the first element.
113      */
114     @Test
115     @SuppressWarnings("unchecked")
116     public void testCircularFifoQueueCircular() {
117         final List<E> list = new ArrayList<>();
118         list.add((E) "A");
119         list.add((E) "B");
120         list.add((E) "C");
121         final Queue<E> queue = new CircularFifoQueue<>(list);
122 
123         assertTrue(queue.contains("A"));
124         assertTrue(queue.contains("B"));
125         assertTrue(queue.contains("C"));
126 
127         queue.add((E) "D");
128 
129         assertFalse(queue.contains("A"));
130         assertTrue(queue.contains("B"));
131         assertTrue(queue.contains("C"));
132         assertTrue(queue.contains("D"));
133 
134         assertEquals("B", queue.peek());
135         assertEquals("B", queue.remove());
136         assertEquals("C", queue.remove());
137         assertEquals("D", queue.remove());
138     }
139 
140     /**
141      * Tests that the removal operation actually removes the first element.
142      */
143     @Test
144     public void testCircularFifoQueueRemove() {
145         resetFull();
146         final int size = getConfirmed().size();
147         for (int i = 0; i < size; i++) {
148             final Object o1 = getCollection().remove();
149             final Object o2 = ((List<?>) getConfirmed()).remove(0);
150             assertEquals(o1, o2, "Removed objects should be equal");
151             verify();
152         }
153 
154         assertThrows(NoSuchElementException.class, () -> getCollection().remove(),
155                 "Empty queue should raise Underflow.");
156     }
157 
158     /**
159      * Tests that the constructor correctly throws an exception.
160      */
161     @Test
162     public void testConstructorException1() {
163         assertThrows(IllegalArgumentException.class, () -> new CircularFifoQueue<E>(0));
164     }
165 
166     /**
167      * Tests that the constructor correctly throws an exception.
168      */
169     @Test
170     public void testConstructorException2() {
171         assertThrows(IllegalArgumentException.class, () -> new CircularFifoQueue<E>(-20));
172     }
173 
174     /**
175      * Tests that the constructor correctly throws an exception.
176      */
177     @Test
178     public void testConstructorException3() {
179         assertThrows(NullPointerException.class, () -> new CircularFifoQueue<E>(null));
180     }
181 
182     @Test
183     public void testDefaultSizeAndGetError1() {
184         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>();
185         assertEquals(32, fifo.maxSize());
186         fifo.add((E) "1");
187         fifo.add((E) "2");
188         fifo.add((E) "3");
189         fifo.add((E) "4");
190         fifo.add((E) "5");
191         assertEquals(5, fifo.size());
192         assertThrows(NoSuchElementException.class, () -> fifo.get(5));
193     }
194 
195     @Test
196     public void testDefaultSizeAndGetError2() {
197         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>();
198         assertEquals(32, fifo.maxSize());
199         fifo.add((E) "1");
200         fifo.add((E) "2");
201         fifo.add((E) "3");
202         fifo.add((E) "4");
203         fifo.add((E) "5");
204         assertEquals(5, fifo.size());
205         assertThrows(NoSuchElementException.class, () -> fifo.get(-2));
206     }
207 
208     @Test
209     public void testGetIndex() {
210         resetFull();
211 
212         final CircularFifoQueue<E> queue = getCollection();
213         final List<E> confirmed = (List<E>) getConfirmed();
214         for (int i = 0; i < confirmed.size(); i++) {
215             assertEquals(confirmed.get(i), queue.get(i));
216         }
217 
218         // remove the first two elements and check again
219         queue.remove();
220         queue.remove();
221 
222         for (int i = 0; i < queue.size(); i++) {
223             assertEquals(confirmed.get(i + 2), queue.get(i));
224         }
225     }
226 
227     @Test
228     @SuppressWarnings("unchecked")
229     public void testRemoveError1() throws Exception {
230         // based on bug 33071
231         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>(5);
232         fifo.add((E) "1");
233         fifo.add((E) "2");
234         fifo.add((E) "3");
235         fifo.add((E) "4");
236         fifo.add((E) "5");
237 
238         assertEquals("[1, 2, 3, 4, 5]", fifo.toString());
239 
240         fifo.remove("3");
241         assertEquals("[1, 2, 4, 5]", fifo.toString());
242 
243         fifo.remove("4");
244         assertEquals("[1, 2, 5]", fifo.toString());
245     }
246 
247     @Test
248     @SuppressWarnings("unchecked")
249     public void testRemoveError2() throws Exception {
250         // based on bug 33071
251         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>(5);
252         fifo.add((E) "1");
253         fifo.add((E) "2");
254         fifo.add((E) "3");
255         fifo.add((E) "4");
256         fifo.add((E) "5");
257         fifo.add((E) "6");
258 
259         assertEquals(5, fifo.size());
260         assertEquals("[2, 3, 4, 5, 6]", fifo.toString());
261 
262         fifo.remove("3");
263         assertEquals("[2, 4, 5, 6]", fifo.toString());
264 
265         fifo.remove("4");
266         assertEquals("[2, 5, 6]", fifo.toString());
267     }
268 
269     @Test
270     @SuppressWarnings("unchecked")
271     public void testRemoveError3() throws Exception {
272         // based on bug 33071
273         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>(5);
274         fifo.add((E) "1");
275         fifo.add((E) "2");
276         fifo.add((E) "3");
277         fifo.add((E) "4");
278         fifo.add((E) "5");
279 
280         assertEquals("[1, 2, 3, 4, 5]", fifo.toString());
281 
282         fifo.remove("3");
283         assertEquals("[1, 2, 4, 5]", fifo.toString());
284 
285         fifo.add((E) "6");
286         fifo.add((E) "7");
287         assertEquals("[2, 4, 5, 6, 7]", fifo.toString());
288 
289         fifo.remove("4");
290         assertEquals("[2, 5, 6, 7]", fifo.toString());
291     }
292 
293     @Test
294     @SuppressWarnings("unchecked")
295     public void testRemoveError4() throws Exception {
296         // based on bug 33071
297         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>(5);
298         fifo.add((E) "1");
299         fifo.add((E) "2");
300         fifo.add((E) "3");
301         fifo.add((E) "4");
302         fifo.add((E) "5");  // end=0
303         fifo.add((E) "6");  // end=1
304         fifo.add((E) "7");  // end=2
305 
306         assertEquals("[3, 4, 5, 6, 7]", fifo.toString());
307 
308         fifo.remove("4");  // remove element in middle of array, after start
309         assertEquals("[3, 5, 6, 7]", fifo.toString());
310     }
311 
312     @Test
313     @SuppressWarnings("unchecked")
314     public void testRemoveError5() throws Exception {
315         // based on bug 33071
316         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>(5);
317         fifo.add((E) "1");
318         fifo.add((E) "2");
319         fifo.add((E) "3");
320         fifo.add((E) "4");
321         fifo.add((E) "5");  // end=0
322         fifo.add((E) "6");  // end=1
323         fifo.add((E) "7");  // end=2
324 
325         assertEquals("[3, 4, 5, 6, 7]", fifo.toString());
326 
327         fifo.remove("5");  // remove element at last pos in array
328         assertEquals("[3, 4, 6, 7]", fifo.toString());
329     }
330 
331     @Test
332     @SuppressWarnings("unchecked")
333     public void testRemoveError6() throws Exception {
334         // based on bug 33071
335         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>(5);
336         fifo.add((E) "1");
337         fifo.add((E) "2");
338         fifo.add((E) "3");
339         fifo.add((E) "4");
340         fifo.add((E) "5");  // end=0
341         fifo.add((E) "6");  // end=1
342         fifo.add((E) "7");  // end=2
343 
344         assertEquals("[3, 4, 5, 6, 7]", fifo.toString());
345 
346         fifo.remove("6");  // remove element at position zero in array
347         assertEquals("[3, 4, 5, 7]", fifo.toString());
348     }
349 
350     @Test
351     @SuppressWarnings("unchecked")
352     public void testRemoveError7() throws Exception {
353         // based on bug 33071
354         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>(5);
355         fifo.add((E) "1");
356         fifo.add((E) "2");
357         fifo.add((E) "3");
358         fifo.add((E) "4");
359         fifo.add((E) "5");  // end=0
360         fifo.add((E) "6");  // end=1
361         fifo.add((E) "7");  // end=2
362 
363         assertEquals("[3, 4, 5, 6, 7]", fifo.toString());
364 
365         fifo.remove("7");  // remove element at position one in array
366         assertEquals("[3, 4, 5, 6]", fifo.toString());
367     }
368 
369     @Test
370     @SuppressWarnings("unchecked")
371     public void testRemoveError8() throws Exception {
372         // based on bug 33071
373         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>(5);
374         fifo.add((E) "1");
375         fifo.add((E) "2");
376         fifo.add((E) "3");
377         fifo.add((E) "4");
378         fifo.add((E) "5");  // end=0
379         fifo.add((E) "6");  // end=1
380         fifo.add((E) "7");  // end=2
381         fifo.add((E) "8");  // end=3
382 
383         assertEquals("[4, 5, 6, 7, 8]", fifo.toString());
384 
385         fifo.remove("7");  // remove element at position one in array, need to shift 8
386         assertEquals("[4, 5, 6, 8]", fifo.toString());
387     }
388 
389     @Test
390     @SuppressWarnings("unchecked")
391     public void testRemoveError9() throws Exception {
392         // based on bug 33071
393         final CircularFifoQueue<E> fifo = new CircularFifoQueue<>(5);
394         fifo.add((E) "1");
395         fifo.add((E) "2");
396         fifo.add((E) "3");
397         fifo.add((E) "4");
398         fifo.add((E) "5");  // end=0
399         fifo.add((E) "6");  // end=1
400         fifo.add((E) "7");  // end=2
401         fifo.add((E) "8");  // end=3
402 
403         assertEquals("[4, 5, 6, 7, 8]", fifo.toString());
404 
405         fifo.remove("8");  // remove element at position two in array
406         assertEquals("[4, 5, 6, 7]", fifo.toString());
407     }
408 
409     @Test
410     @SuppressWarnings("unchecked")
411     public void testRepeatedSerialization() throws Exception {
412         // bug 31433
413         final CircularFifoQueue<E> b = new CircularFifoQueue<>(2);
414         b.add((E) "a");
415         assertEquals(1, b.size());
416         assertTrue(b.contains("a"));
417 
418         ByteArrayOutputStream bos = new ByteArrayOutputStream();
419         new ObjectOutputStream(bos).writeObject(b);
420 
421         final CircularFifoQueue<E> b2 = (CircularFifoQueue<E>) new ObjectInputStream(
422             new ByteArrayInputStream(bos.toByteArray())).readObject();
423 
424         assertEquals(1, b2.size());
425         assertTrue(b2.contains("a"));
426         b2.add((E) "b");
427         assertEquals(2, b2.size());
428         assertTrue(b2.contains("a"));
429         assertTrue(b2.contains("b"));
430 
431         bos = new ByteArrayOutputStream();
432         new ObjectOutputStream(bos).writeObject(b2);
433 
434         final CircularFifoQueue<E> b3 = (CircularFifoQueue<E>) new ObjectInputStream(
435             new ByteArrayInputStream(bos.toByteArray())).readObject();
436 
437         assertEquals(2, b3.size());
438         assertTrue(b3.contains("a"));
439         assertTrue(b3.contains("b"));
440         b3.add((E) "c");
441         assertEquals(2, b3.size());
442         assertTrue(b3.contains("b"));
443         assertTrue(b3.contains("c"));
444     }
445 
446 //    public void testCreate() throws Exception {
447 //        resetEmpty();
448 //        writeExternalFormToDisk((java.io.Serializable) getCollection(), "src/test/resources/data/test/CircularFifoQueue.emptyCollection.version4.obj");
449 //        resetFull();
450 //        writeExternalFormToDisk((java.io.Serializable) getCollection(), "src/test/resources/data/test/CircularFifoQueue.fullCollection.version4.obj");
451 //    }
452 
453     /**
454      *  Runs through the regular verifications, but also verifies that
455      *  the buffer contains the same elements in the same sequence as the
456      *  list.
457      */
458     @Override
459     public void verify() {
460         super.verify();
461         final Iterator<E> iterator1 = getCollection().iterator();
462         for (final E e : getConfirmed()) {
463             assertTrue(iterator1.hasNext());
464             final Object o1 = iterator1.next();
465             final Object o2 = e;
466             assertEquals(o1, o2);
467         }
468     }
469 
470 }