001: /*
002: * Copyright 2001-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.collections.bag;
017:
018: import java.io.IOException;
019: import java.io.Serializable;
020: import java.util.ArrayList;
021: import java.util.ConcurrentModificationException;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.NoSuchElementException;
025:
026: import org.apache.commons.collections.AbstractTestObject;
027: import org.apache.commons.collections.Bag;
028:
029: /**
030: * Abstract test class for {@link org.apache.commons.collections.Bag Bag} methods and contracts.
031: * <p>
032: * To use, simply extend this class, and implement
033: * the {@link #makeBag} method.
034: * <p>
035: * If your bag fails one of these tests by design,
036: * you may still use this base set of cases. Simply override the
037: * test case (method) your bag fails.
038: *
039: * @version $Revision: 219131 $ $Date: 2005-07-15 00:11:12 +0100 (Fri, 15 Jul 2005) $
040: *
041: * @author Chuck Burdick
042: * @author Stephen Colebourne
043: */
044: public abstract class AbstractTestBag extends AbstractTestObject {
045: // TODO: this class should really extend from TestCollection, but the bag
046: // implementations currently do not conform to the Collection interface. Once
047: // those are fixed or at least a strategy is made for resolving the issue, this
048: // can be changed back to extend TestCollection instead.
049:
050: /**
051: * JUnit constructor.
052: *
053: * @param testName the test class name
054: */
055: public AbstractTestBag(String testName) {
056: super (testName);
057: }
058:
059: //-----------------------------------------------------------------------
060: /**
061: * Return a new, empty bag to used for testing.
062: *
063: * @return the bag to be tested
064: */
065: public abstract Bag makeBag();
066:
067: /**
068: * Implements the superclass method to return the Bag.
069: *
070: * @return the bag to be tested
071: */
072: public Object makeObject() {
073: return makeBag();
074: }
075:
076: //-----------------------------------------------------------------------
077: public void testBagAdd() {
078: Bag bag = makeBag();
079: bag.add("A");
080: assertTrue("Should contain 'A'", bag.contains("A"));
081: assertEquals("Should have count of 1", 1, bag.getCount("A"));
082: bag.add("A");
083: assertTrue("Should contain 'A'", bag.contains("A"));
084: assertEquals("Should have count of 2", 2, bag.getCount("A"));
085: bag.add("B");
086: assertTrue(bag.contains("A"));
087: assertTrue(bag.contains("B"));
088: }
089:
090: public void testBagEqualsSelf() {
091: Bag bag = makeBag();
092: assertTrue(bag.equals(bag));
093: bag.add("elt");
094: assertTrue(bag.equals(bag));
095: bag.add("elt"); // again
096: assertTrue(bag.equals(bag));
097: bag.add("elt2");
098: assertTrue(bag.equals(bag));
099: }
100:
101: public void testRemove() {
102: Bag bag = makeBag();
103: bag.add("A");
104: assertEquals("Should have count of 1", 1, bag.getCount("A"));
105: bag.remove("A");
106: assertEquals("Should have count of 0", 0, bag.getCount("A"));
107: bag.add("A");
108: bag.add("A");
109: bag.add("A");
110: bag.add("A");
111: assertEquals("Should have count of 4", 4, bag.getCount("A"));
112: bag.remove("A", 0);
113: assertEquals("Should have count of 4", 4, bag.getCount("A"));
114: bag.remove("A", 2);
115: assertEquals("Should have count of 2", 2, bag.getCount("A"));
116: bag.remove("A");
117: assertEquals("Should have count of 0", 0, bag.getCount("A"));
118: }
119:
120: public void testRemoveAll() {
121: Bag bag = makeBag();
122: bag.add("A", 2);
123: assertEquals("Should have count of 2", 2, bag.getCount("A"));
124: bag.add("B");
125: bag.add("C");
126: assertEquals("Should have count of 4", 4, bag.size());
127: List delete = new ArrayList();
128: delete.add("A");
129: delete.add("B");
130: bag.removeAll(delete);
131: assertEquals("Should have count of 1", 1, bag.getCount("A"));
132: assertEquals("Should have count of 0", 0, bag.getCount("B"));
133: assertEquals("Should have count of 1", 1, bag.getCount("C"));
134: assertEquals("Should have count of 2", 2, bag.size());
135: }
136:
137: public void testContains() {
138: Bag bag = makeBag();
139:
140: assertEquals("Bag does not have at least 1 'A'", false, bag
141: .contains("A"));
142: assertEquals("Bag does not have at least 1 'B'", false, bag
143: .contains("B"));
144:
145: bag.add("A"); // bag 1A
146: assertEquals("Bag has at least 1 'A'", true, bag.contains("A"));
147: assertEquals("Bag does not have at least 1 'B'", false, bag
148: .contains("B"));
149:
150: bag.add("A"); // bag 2A
151: assertEquals("Bag has at least 1 'A'", true, bag.contains("A"));
152: assertEquals("Bag does not have at least 1 'B'", false, bag
153: .contains("B"));
154:
155: bag.add("B"); // bag 2A,1B
156: assertEquals("Bag has at least 1 'A'", true, bag.contains("A"));
157: assertEquals("Bag has at least 1 'B'", true, bag.contains("B"));
158: }
159:
160: public void testContainsAll() {
161: Bag bag = makeBag();
162: List known = new ArrayList();
163: List known1A = new ArrayList();
164: known1A.add("A");
165: List known2A = new ArrayList();
166: known2A.add("A");
167: known2A.add("A");
168: List known1B = new ArrayList();
169: known1B.add("B");
170: List known1A1B = new ArrayList();
171: known1A1B.add("A");
172: known1A1B.add("B");
173:
174: assertEquals("Bag containsAll of empty", true, bag
175: .containsAll(known));
176: assertEquals("Bag does not containsAll of 1 'A'", false, bag
177: .containsAll(known1A));
178: assertEquals("Bag does not containsAll of 2 'A'", false, bag
179: .containsAll(known2A));
180: assertEquals("Bag does not containsAll of 1 'B'", false, bag
181: .containsAll(known1B));
182: assertEquals("Bag does not containsAll of 1 'A' 1 'B'", false,
183: bag.containsAll(known1A1B));
184:
185: bag.add("A"); // bag 1A
186: assertEquals("Bag containsAll of empty", true, bag
187: .containsAll(known));
188: assertEquals("Bag containsAll of 1 'A'", true, bag
189: .containsAll(known1A));
190: assertEquals("Bag does not containsAll of 2 'A'", false, bag
191: .containsAll(known2A));
192: assertEquals("Bag does not containsAll of 1 'B'", false, bag
193: .containsAll(known1B));
194: assertEquals("Bag does not containsAll of 1 'A' 1 'B'", false,
195: bag.containsAll(known1A1B));
196:
197: bag.add("A"); // bag 2A
198: assertEquals("Bag containsAll of empty", true, bag
199: .containsAll(known));
200: assertEquals("Bag containsAll of 1 'A'", true, bag
201: .containsAll(known1A));
202: assertEquals("Bag containsAll of 2 'A'", true, bag
203: .containsAll(known2A));
204: assertEquals("Bag does not containsAll of 1 'B'", false, bag
205: .containsAll(known1B));
206: assertEquals("Bag does not containsAll of 1 'A' 1 'B'", false,
207: bag.containsAll(known1A1B));
208:
209: bag.add("A"); // bag 3A
210: assertEquals("Bag containsAll of empty", true, bag
211: .containsAll(known));
212: assertEquals("Bag containsAll of 1 'A'", true, bag
213: .containsAll(known1A));
214: assertEquals("Bag containsAll of 2 'A'", true, bag
215: .containsAll(known2A));
216: assertEquals("Bag does not containsAll of 1 'B'", false, bag
217: .containsAll(known1B));
218: assertEquals("Bag does not containsAll of 1 'A' 1 'B'", false,
219: bag.containsAll(known1A1B));
220:
221: bag.add("B"); // bag 3A1B
222: assertEquals("Bag containsAll of empty", true, bag
223: .containsAll(known));
224: assertEquals("Bag containsAll of 1 'A'", true, bag
225: .containsAll(known1A));
226: assertEquals("Bag containsAll of 2 'A'", true, bag
227: .containsAll(known2A));
228: assertEquals("Bag containsAll of 1 'B'", true, bag
229: .containsAll(known1B));
230: assertEquals("Bag containsAll of 1 'A' 1 'B'", true, bag
231: .containsAll(known1A1B));
232: }
233:
234: public void testSize() {
235: Bag bag = makeBag();
236: assertEquals("Should have 0 total items", 0, bag.size());
237: bag.add("A");
238: assertEquals("Should have 1 total items", 1, bag.size());
239: bag.add("A");
240: assertEquals("Should have 2 total items", 2, bag.size());
241: bag.add("A");
242: assertEquals("Should have 3 total items", 3, bag.size());
243: bag.add("B");
244: assertEquals("Should have 4 total items", 4, bag.size());
245: bag.add("B");
246: assertEquals("Should have 5 total items", 5, bag.size());
247: bag.remove("A", 2);
248: assertEquals("Should have 1 'A'", 1, bag.getCount("A"));
249: assertEquals("Should have 3 total items", 3, bag.size());
250: bag.remove("B");
251: assertEquals("Should have 1 total item", 1, bag.size());
252: }
253:
254: public void testRetainAll() {
255: Bag bag = makeBag();
256: bag.add("A");
257: bag.add("A");
258: bag.add("A");
259: bag.add("B");
260: bag.add("B");
261: bag.add("C");
262: List retains = new ArrayList();
263: retains.add("B");
264: retains.add("C");
265: bag.retainAll(retains);
266: assertEquals("Should have 2 total items", 2, bag.size());
267: }
268:
269: public void testIterator() {
270: Bag bag = makeBag();
271: bag.add("A");
272: bag.add("A");
273: bag.add("B");
274: assertEquals("Bag should have 3 items", 3, bag.size());
275: Iterator i = bag.iterator();
276:
277: boolean foundA = false;
278: while (i.hasNext()) {
279: String element = (String) i.next();
280: // ignore the first A, remove the second via Iterator.remove()
281: if (element.equals("A")) {
282: if (foundA == false) {
283: foundA = true;
284: } else {
285: i.remove();
286: }
287: }
288: }
289:
290: assertTrue("Bag should still contain 'A'", bag.contains("A"));
291: assertEquals("Bag should have 2 items", 2, bag.size());
292: assertEquals("Bag should have 1 'A'", 1, bag.getCount("A"));
293: }
294:
295: public void testIteratorFail() {
296: Bag bag = makeBag();
297: bag.add("A");
298: bag.add("A");
299: bag.add("B");
300: Iterator it = bag.iterator();
301: it.next();
302: bag.remove("A");
303: try {
304: it.next();
305: fail("Should throw ConcurrentModificationException");
306: } catch (ConcurrentModificationException e) {
307: // expected
308: }
309: }
310:
311: public void testIteratorFailNoMore() {
312: Bag bag = makeBag();
313: bag.add("A");
314: bag.add("A");
315: bag.add("B");
316: Iterator it = bag.iterator();
317: it.next();
318: it.next();
319: it.next();
320: try {
321: it.next();
322: fail("Should throw NoSuchElementException");
323: } catch (NoSuchElementException ex) {
324: // expected
325: }
326: }
327:
328: public void testIteratorFailDoubleRemove() {
329: Bag bag = makeBag();
330: bag.add("A");
331: bag.add("A");
332: bag.add("B");
333: Iterator it = bag.iterator();
334: it.next();
335: it.next();
336: assertEquals(3, bag.size());
337: it.remove();
338: assertEquals(2, bag.size());
339: try {
340: it.remove();
341: fail("Should throw IllegalStateException");
342: } catch (IllegalStateException ex) {
343: // expected
344: }
345: assertEquals(2, bag.size());
346: it.next();
347: it.remove();
348: assertEquals(1, bag.size());
349: }
350:
351: public void testIteratorRemoveProtectsInvariants() {
352: Bag bag = makeBag();
353: bag.add("A");
354: bag.add("A");
355: assertEquals(2, bag.size());
356: Iterator it = bag.iterator();
357: assertEquals("A", it.next());
358: assertEquals(true, it.hasNext());
359: it.remove();
360: assertEquals(1, bag.size());
361: assertEquals(true, it.hasNext());
362: assertEquals("A", it.next());
363: assertEquals(false, it.hasNext());
364: it.remove();
365: assertEquals(0, bag.size());
366: assertEquals(false, it.hasNext());
367:
368: Iterator it2 = bag.iterator();
369: assertEquals(false, it2.hasNext());
370: }
371:
372: public void testToArray() {
373: Bag bag = makeBag();
374: bag.add("A");
375: bag.add("A");
376: bag.add("B");
377: bag.add("B");
378: bag.add("C");
379: Object[] array = bag.toArray();
380: int a = 0, b = 0, c = 0;
381: for (int i = 0; i < array.length; i++) {
382: a += (array[i].equals("A") ? 1 : 0);
383: b += (array[i].equals("B") ? 1 : 0);
384: c += (array[i].equals("C") ? 1 : 0);
385: }
386: assertEquals(2, a);
387: assertEquals(2, b);
388: assertEquals(1, c);
389: }
390:
391: public void testToArrayPopulate() {
392: Bag bag = makeBag();
393: bag.add("A");
394: bag.add("A");
395: bag.add("B");
396: bag.add("B");
397: bag.add("C");
398: String[] array = (String[]) bag.toArray(new String[0]);
399: int a = 0, b = 0, c = 0;
400: for (int i = 0; i < array.length; i++) {
401: a += (array[i].equals("A") ? 1 : 0);
402: b += (array[i].equals("B") ? 1 : 0);
403: c += (array[i].equals("C") ? 1 : 0);
404: }
405: assertEquals(2, a);
406: assertEquals(2, b);
407: assertEquals(1, c);
408: }
409:
410: //-----------------------------------------------------------------------
411: public void testEquals() {
412: Bag bag = makeBag();
413: Bag bag2 = makeBag();
414: assertEquals(true, bag.equals(bag2));
415: bag.add("A");
416: assertEquals(false, bag.equals(bag2));
417: bag2.add("A");
418: assertEquals(true, bag.equals(bag2));
419: bag.add("A");
420: bag.add("B");
421: bag.add("B");
422: bag.add("C");
423: bag2.add("A");
424: bag2.add("B");
425: bag2.add("B");
426: bag2.add("C");
427: assertEquals(true, bag.equals(bag2));
428: }
429:
430: public void testEqualsHashBag() {
431: Bag bag = makeBag();
432: Bag bag2 = new HashBag();
433: assertEquals(true, bag.equals(bag2));
434: bag.add("A");
435: assertEquals(false, bag.equals(bag2));
436: bag2.add("A");
437: assertEquals(true, bag.equals(bag2));
438: bag.add("A");
439: bag.add("B");
440: bag.add("B");
441: bag.add("C");
442: bag2.add("A");
443: bag2.add("B");
444: bag2.add("B");
445: bag2.add("C");
446: assertEquals(true, bag.equals(bag2));
447: }
448:
449: public void testHashCode() {
450: Bag bag = makeBag();
451: Bag bag2 = makeBag();
452: assertEquals(0, bag.hashCode());
453: assertEquals(0, bag2.hashCode());
454: assertEquals(bag.hashCode(), bag2.hashCode());
455: bag.add("A");
456: bag.add("A");
457: bag.add("B");
458: bag.add("B");
459: bag.add("C");
460: bag2.add("A");
461: bag2.add("A");
462: bag2.add("B");
463: bag2.add("B");
464: bag2.add("C");
465: assertEquals(bag.hashCode(), bag2.hashCode());
466:
467: int total = 0;
468: total += ("A".hashCode() ^ 2);
469: total += ("B".hashCode() ^ 2);
470: total += ("C".hashCode() ^ 1);
471: assertEquals(total, bag.hashCode());
472: assertEquals(total, bag2.hashCode());
473: }
474:
475: //-----------------------------------------------------------------------
476: public void testEmptyBagSerialization() throws IOException,
477: ClassNotFoundException {
478: Bag bag = makeBag();
479: if (!(bag instanceof Serializable && isTestSerialization()))
480: return;
481:
482: byte[] objekt = writeExternalFormToBytes((Serializable) bag);
483: Bag bag2 = (Bag) readExternalFormFromBytes(objekt);
484:
485: assertEquals("Bag should be empty", 0, bag.size());
486: assertEquals("Bag should be empty", 0, bag2.size());
487: }
488:
489: public void testFullBagSerialization() throws IOException,
490: ClassNotFoundException {
491: Bag bag = makeBag();
492: bag.add("A");
493: bag.add("A");
494: bag.add("B");
495: bag.add("B");
496: bag.add("C");
497: int size = bag.size();
498: if (!(bag instanceof Serializable && isTestSerialization()))
499: return;
500:
501: byte[] objekt = writeExternalFormToBytes((Serializable) bag);
502: Bag bag2 = (Bag) readExternalFormFromBytes(objekt);
503:
504: assertEquals("Bag should be same size", size, bag.size());
505: assertEquals("Bag should be same size", size, bag2.size());
506: }
507:
508: /**
509: * Compare the current serialized form of the Bag
510: * against the canonical version in CVS.
511: */
512: public void testEmptyBagCompatibility() throws IOException,
513: ClassNotFoundException {
514: // test to make sure the canonical form has been preserved
515: Bag bag = makeBag();
516: if (bag instanceof Serializable
517: && !skipSerializedCanonicalTests()
518: && isTestSerialization()) {
519: Bag bag2 = (Bag) readExternalFormFromDisk(getCanonicalEmptyCollectionName(bag));
520: assertTrue("Bag is empty", bag2.size() == 0);
521: assertEquals(bag, bag2);
522: }
523: }
524:
525: /**
526: * Compare the current serialized form of the Bag
527: * against the canonical version in CVS.
528: */
529: public void testFullBagCompatibility() throws IOException,
530: ClassNotFoundException {
531: // test to make sure the canonical form has been preserved
532: Bag bag = makeBag();
533: bag.add("A");
534: bag.add("A");
535: bag.add("B");
536: bag.add("B");
537: bag.add("C");
538: if (bag instanceof Serializable
539: && !skipSerializedCanonicalTests()
540: && isTestSerialization()) {
541: Bag bag2 = (Bag) readExternalFormFromDisk(getCanonicalFullCollectionName(bag));
542: assertEquals("Bag is the right size", bag.size(), bag2
543: .size());
544: assertEquals(bag, bag2);
545: }
546: }
547: }
|