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.assertNotNull;
21  import static org.junit.jupiter.api.Assertions.assertNull;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import java.io.IOException;
26  import java.io.Serializable;
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.Collection;
30  import java.util.Iterator;
31  import java.util.NoSuchElementException;
32  import java.util.Queue;
33  
34  import org.apache.commons.collections4.collection.AbstractCollectionTest;
35  import org.junit.jupiter.api.Test;
36  
37  /**
38   * Tests {@link java.util.Queue}.
39   * <p>
40   * To use, simply extend this class, and implement
41   * the {@link #makeObject} method.
42   * <p>
43   * If your {@link Queue} fails one of these tests by design,
44   * you may still use this base set of cases.  Simply override the
45   * test case (method) your {@link Queue} fails or override one of the
46   * protected methods from AbstractCollectionTest.
47   */
48  public abstract class AbstractQueueTest<E> extends AbstractCollectionTest<E> {
49  
50      /**
51       * Returns the {@link #collection} field cast to a {@link Queue}.
52       *
53       * @return the collection field as a Queue
54       */
55      @Override
56      public Queue<E> getCollection() {
57          return (Queue<E>) super.getCollection();
58      }
59  
60      /**
61       *  Returns true if the collections produced by
62       *  {@link #makeObject()} and {@link #makeFullCollection()}
63       *  support the <code>set operation.<p>
64       *  Default implementation returns true.  Override if your collection
65       *  class does not support set.
66       */
67      public boolean isSetSupported() {
68          return true;
69      }
70  
71      /**
72       * Returns an empty {@link ArrayList}.
73       */
74      @Override
75      public Collection<E> makeConfirmedCollection() {
76          return new ArrayList<>();
77      }
78  
79      /**
80       * Returns a full {@link ArrayList}.
81       */
82      @Override
83      public Collection<E> makeConfirmedFullCollection() {
84          return new ArrayList<>(Arrays.asList(getFullElements()));
85      }
86  
87      /**
88       * {@inheritDoc}
89       */
90      @Override
91      public Queue<E> makeFullCollection() {
92          // only works if queue supports optional "addAll(Collection)"
93          final Queue<E> queue = makeObject();
94          queue.addAll(Arrays.asList(getFullElements()));
95          return queue;
96      }
97  
98      /**
99       * Returns {@link #makeObject()}.
100      *
101      * @return an empty queue to be used for testing
102      */
103     @Override
104     public abstract Queue<E> makeObject();
105 
106     /**
107      * Compare the current serialized form of the Queue
108      * against the canonical version in SCM.
109      */
110     @Test
111     @SuppressWarnings("unchecked")
112     public void testEmptyQueueCompatibility() throws IOException, ClassNotFoundException {
113         /*
114          * Create canonical objects with this code
115         Queue queue = makeEmptyQueue();
116         if (!(queue instanceof Serializable)) return;
117 
118         writeExternalFormToDisk((Serializable) queue, getCanonicalEmptyCollectionName(queue));
119         */
120 
121         // test to make sure the canonical form has been preserved
122         final Queue<E> queue = makeObject();
123         if (queue instanceof Serializable && !skipSerializedCanonicalTests()
124                 && isTestSerialization()) {
125             final Queue<E> queue2 = (Queue<E>) readExternalFormFromDisk(getCanonicalEmptyCollectionName(queue));
126             assertEquals(0, queue2.size(), "Queue is empty");
127         }
128     }
129 
130     @Test
131     @SuppressWarnings("unchecked")
132     public void testEmptyQueueSerialization() throws IOException, ClassNotFoundException {
133         final Queue<E> queue = makeObject();
134         if (!(queue instanceof Serializable && isTestSerialization())) {
135             return;
136         }
137 
138         final byte[] object = writeExternalFormToBytes((Serializable) queue);
139         final Queue<E> queue2 = (Queue<E>) readExternalFormFromBytes(object);
140 
141         assertEquals(0, queue.size(), "Both queues are empty");
142         assertEquals(0, queue2.size(), "Both queues are empty");
143     }
144 
145     /**
146      * Compare the current serialized form of the Queue
147      * against the canonical version in SCM.
148      */
149     @Test
150     @SuppressWarnings("unchecked")
151     public void testFullQueueCompatibility() throws IOException, ClassNotFoundException {
152         /*
153          * Create canonical objects with this code
154         Queue queue = makeFullQueue();
155         if (!(queue instanceof Serializable)) return;
156 
157         writeExternalFormToDisk((Serializable) queue, getCanonicalFullCollectionName(queue));
158         */
159 
160         // test to make sure the canonical form has been preserved
161         final Queue<E> queue = makeFullCollection();
162         if (queue instanceof Serializable && !skipSerializedCanonicalTests() && isTestSerialization()) {
163             final Queue<E> queue2 = (Queue<E>) readExternalFormFromDisk(getCanonicalFullCollectionName(queue));
164             assertEquals(queue.size(), queue2.size(), "Queues are not the right size");
165         }
166     }
167 
168     @Test
169     @SuppressWarnings("unchecked")
170     public void testFullQueueSerialization() throws IOException, ClassNotFoundException {
171         final Queue<E> queue = makeFullCollection();
172         final int size = getFullElements().length;
173         if (!(queue instanceof Serializable && isTestSerialization())) {
174             return;
175         }
176 
177         final byte[] object = writeExternalFormToBytes((Serializable) queue);
178         final Queue<E> queue2 = (Queue<E>) readExternalFormFromBytes(object);
179 
180         assertEquals(size, queue.size(), "Both queues are same size");
181         assertEquals(size, queue2.size(), "Both queues are same size");
182     }
183 
184     /**
185      *  Tests {@link Queue#element()}.
186      */
187     @Test
188     public void testQueueElement() {
189         resetEmpty();
190 
191         assertThrows(NoSuchElementException.class, () -> getCollection().element(),
192                 "Queue.element should throw NoSuchElementException");
193 
194         resetFull();
195 
196         assertTrue(getConfirmed().contains(getCollection().element()));
197 
198         if (!isRemoveSupported()) {
199             return;
200         }
201 
202         final int max = getFullElements().length;
203         for (int i = 0; i < max; i++) {
204             final E element = getCollection().element();
205 
206             if (!isNullSupported()) {
207                 assertNotNull(element);
208             }
209 
210             assertTrue(getConfirmed().contains(element));
211 
212             getCollection().remove(element);
213             getConfirmed().remove(element);
214 
215             verify();
216         }
217 
218         assertThrows(NoSuchElementException.class, () -> getCollection().element(),
219                 "Queue.element should throw NoSuchElementException");
220     }
221 
222     /**
223      *  Tests {@link Queue#offer(Object)}.
224      */
225     @Test
226     public void testQueueOffer() {
227         if (!isAddSupported()) {
228             return;
229         }
230 
231         final E[] elements = getFullElements();
232         for (final E element : elements) {
233             resetEmpty();
234             final boolean r = getCollection().offer(element);
235             getConfirmed().add(element);
236             verify();
237             assertTrue(r, "Empty queue changed after add");
238             assertEquals(1, getCollection().size(), "Queue size is 1 after first add");
239         }
240 
241         resetEmpty();
242         int size = 0;
243         for (final E element : elements) {
244             final boolean r = getCollection().offer(element);
245             getConfirmed().add(element);
246             verify();
247             if (r) {
248                 size++;
249             }
250             assertEquals(size, getCollection().size(), "Queue size should grow after add");
251             assertTrue(getCollection().contains(element), "Queue should contain added element");
252         }
253     }
254 
255     /**
256      *  Tests {@link Queue#peek()}.
257      */
258     @Test
259     public void testQueuePeek() {
260         if (!isRemoveSupported()) {
261             return;
262         }
263 
264         resetEmpty();
265 
266         E element = getCollection().peek();
267         assertNull(element);
268 
269         resetFull();
270 
271         final int max = getFullElements().length;
272         for (int i = 0; i < max; i++) {
273             element = getCollection().peek();
274 
275             if (!isNullSupported()) {
276                 assertNotNull(element);
277             }
278 
279             assertTrue(getConfirmed().contains(element));
280 
281             getCollection().remove(element);
282             getConfirmed().remove(element);
283 
284             verify();
285         }
286 
287         element = getCollection().peek();
288         assertNull(element);
289     }
290 
291     /**
292      *  Tests {@link Queue#poll()}.
293      */
294     @Test
295     public void testQueuePoll() {
296         if (!isRemoveSupported()) {
297             return;
298         }
299 
300         resetEmpty();
301 
302         E element = getCollection().poll();
303         assertNull(element);
304 
305         resetFull();
306 
307         final int max = getFullElements().length;
308         for (int i = 0; i < max; i++) {
309             element = getCollection().poll();
310             final boolean success = getConfirmed().remove(element);
311             assertTrue(success, "poll should return correct element");
312             verify();
313         }
314 
315         element = getCollection().poll();
316         assertNull(element);
317     }
318 
319     /**
320      *  Tests {@link Queue#remove()}.
321      */
322     @Test
323     public void testQueueRemove() {
324         if (!isRemoveSupported()) {
325             return;
326         }
327 
328         resetEmpty();
329 
330         assertThrows(NoSuchElementException.class, () -> getCollection().remove(),
331                 "Queue.remove should throw NoSuchElementException");
332 
333         resetFull();
334 
335         final int max = getFullElements().length;
336         for (int i = 0; i < max; i++) {
337             final E element = getCollection().remove();
338             final boolean success = getConfirmed().remove(element);
339             assertTrue(success, "remove should return correct element");
340             verify();
341         }
342 
343         assertThrows(NoSuchElementException.class, () -> getCollection().element(),
344                 "Queue.remove should throw NoSuchElementException");
345     }
346 
347     /**
348      *  Verifies that the test queue implementation matches the confirmed queue
349      *  implementation.
350      */
351     @Override
352     public void verify() {
353         super.verify();
354         final Iterator<E> iterator1 = getCollection().iterator();
355         for (final E e : getConfirmed()) {
356             assertTrue(iterator1.hasNext());
357             final Object o1 = iterator1.next();
358             final Object o2 = e;
359             assertEquals(o1, o2);
360         }
361     }
362 
363 }