001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.openide.util;
043:
044: import java.lang.ref.WeakReference;
045: import java.util.ArrayList;
046: import java.util.Arrays;
047: import java.util.Collection;
048: import java.util.Collections;
049: import java.util.Enumeration;
050: import java.util.Iterator;
051: import java.util.Map;
052: import java.util.NoSuchElementException;
053: import java.util.Set;
054: import junit.textui.TestRunner;
055: import org.netbeans.junit.NbTestCase;
056: import org.netbeans.junit.NbTestSuite;
057:
058: /** This is the base test for new and old enumerations. It contains
059: * factory methods for various kinds of enumerations and set of tests
060: * that use them. Factory methods are overriden in OldEnumerationsTest
061: *
062: * @author Jaroslav Tulach
063: */
064: public class EnumerationsTest extends NbTestCase {
065:
066: /** Creates a new instance of EnumerationsTest */
067: public EnumerationsTest(String testName) {
068: super (testName);
069: }
070:
071: //
072: // Factory methods
073: //
074:
075: protected Enumeration singleton(Object obj) {
076: return Enumerations.singleton(obj);
077: }
078:
079: protected Enumeration concat(Enumeration en1, Enumeration en2) {
080: return Enumerations.concat(en1, en2);
081: }
082:
083: protected Enumeration concat(Enumeration enumOfEnums) {
084: return Enumerations.concat(enumOfEnums);
085: }
086:
087: protected Enumeration removeDuplicates(Enumeration en) {
088: return Enumerations.removeDuplicates(en);
089: }
090:
091: protected Enumeration empty() {
092: return Enumerations.empty();
093: }
094:
095: protected Enumeration array(Object[] arr) {
096: return Enumerations.array(arr);
097: }
098:
099: protected Enumeration convert(Enumeration en, final Map map) {
100: class P implements Enumerations.Processor {
101: public Object process(Object obj, Collection nothing) {
102: return map.get(obj);
103: }
104: }
105:
106: return Enumerations.convert(en, new P());
107: }
108:
109: protected Enumeration removeNulls(Enumeration en) {
110: return Enumerations.removeNulls(en);
111: }
112:
113: protected Enumeration filter(Enumeration en, final Set filter) {
114: class P implements Enumerations.Processor {
115: public Object process(Object obj, Collection nothing) {
116: return filter.contains(obj) ? obj : null;
117: }
118: }
119:
120: return Enumerations.filter(en, new P());
121: }
122:
123: protected Enumeration filter(Enumeration en,
124: final QueueProcess filter) {
125: class P implements Enumerations.Processor {
126: public Object process(Object obj, Collection nothing) {
127: return filter.process(obj, nothing);
128: }
129: }
130:
131: return Enumerations.filter(en, new P());
132: }
133:
134: /**
135: * @param filter the set.contains (...) is called before each object is produced
136: * @return Enumeration
137: */
138: protected Enumeration queue(Collection initContent,
139: final QueueProcess process) {
140: class C implements Enumerations.Processor {
141: public Object process(Object object, Collection toAdd) {
142: return process.process(object, toAdd);
143: }
144: }
145: return Enumerations.queue(Collections.enumeration(initContent),
146: new C());
147: }
148:
149: /** Processor interface.
150: */
151: public static interface QueueProcess {
152: public Object process(Object object, Collection toAdd);
153: }
154:
155: //
156: // The tests
157: //
158:
159: public void testEmptyIsEmpty() {
160: Enumeration e = empty();
161: assertFalse(e.hasMoreElements());
162: try {
163: e.nextElement();
164: fail("No elements");
165: } catch (NoSuchElementException ex) {
166: // ok
167: }
168: }
169:
170: public void testSingleIsSingle() {
171: Enumeration e = singleton(this );
172: assertTrue(e.hasMoreElements());
173: assertEquals("Returns me", this , e.nextElement());
174: assertFalse("Now it is empty", e.hasMoreElements());
175: try {
176: e.nextElement();
177: fail("No elements");
178: } catch (NoSuchElementException ex) {
179: // ok
180: }
181: }
182:
183: public void testConcatTwoAndArray() {
184: Object[] one = { new Integer(1), new Integer(2), new Integer(3) };
185: Object[] two = { "1", "2", "3" };
186:
187: ArrayList list = new ArrayList(Arrays.asList(one));
188: list.addAll(Arrays.asList(two));
189:
190: assertEnums(concat(array(one), array(two)), Collections
191: .enumeration(list));
192: }
193:
194: public void testConcatTwoAndArrayAndTakeOnlyStrings() {
195: Object[] one = { new Integer(1), new Integer(2), new Integer(3) };
196: Object[] two = { "1", "2", "3" };
197: Object[] three = { new Long(1) };
198: Object[] four = { "Kuk" };
199:
200: ArrayList list = new ArrayList(Arrays.asList(two));
201: list.addAll(Arrays.asList(four));
202:
203: Enumeration[] alls = { array(one), array(two), array(three),
204: array(four) };
205:
206: assertEnums(filter(concat(array(alls)), new OnlyStrings()),
207: Collections.enumeration(list));
208: }
209:
210: public void testRemoveDuplicates() {
211: Object[] one = { new Integer(1), new Integer(2), new Integer(3) };
212: Object[] two = { "1", "2", "3" };
213: Object[] three = { new Integer(1) };
214: Object[] four = { "2", "3", "4" };
215:
216: Enumeration[] alls = { array(one), array(two), array(three),
217: array(four) };
218:
219: assertEnums(removeDuplicates(concat(array(alls))),
220: array(new Object[] { new Integer(1), new Integer(2),
221: new Integer(3), "1", "2", "3", "4" }));
222:
223: }
224:
225: public void testRemoveDuplicatesAndGCWorks() {
226:
227: /*** Return { i1, "", "", "", i2 } */
228: class WeakEnum implements Enumeration {
229: public Object i1 = new Integer(1);
230: public Object i2 = new Integer(1);
231:
232: private int state;
233:
234: public boolean hasMoreElements() {
235: return state < 5;
236: }
237:
238: public Object nextElement() {
239: switch (state++) {
240: case 0:
241: return i1;
242: case 1:
243: case 2:
244: case 3:
245: return "";
246: default:
247: return i2;
248: }
249: }
250: }
251:
252: WeakEnum weak = new WeakEnum();
253: Enumeration en = removeDuplicates(weak);
254:
255: assertTrue("Has some elements", en.hasMoreElements());
256: assertEquals("And the first one is get", weak.i1, en
257: .nextElement());
258:
259: try {
260: WeakReference ref = new WeakReference(weak.i1);
261: weak.i1 = null;
262: assertGC("Try hard to GC the first integer", ref);
263: // does not matter whether it GCs or not
264: } catch (Throwable tw) {
265: // not GCed, but does not matter
266: }
267: assertTrue("Next object will be string", en.hasMoreElements());
268: assertEquals("is empty string", "", en.nextElement());
269:
270: assertFalse(
271: "The second integer is however equal to the original i1 and thus"
272: + " the enum should not be there", en
273: .hasMoreElements());
274: }
275:
276: public void testQueueEnum() {
277: class Pr implements QueueProcess {
278: public Object process(Object o, Collection c) {
279: Integer i = (Integer) o;
280: int plus = i.intValue() + 1;
281: if (plus < 10) {
282: c.add(new Integer(plus));
283: }
284: return i;
285: }
286: }
287: Pr p = new Pr();
288:
289: Enumeration en = queue(Collections.nCopies(1, new Integer(0)),
290: p);
291:
292: for (int i = 0; i < 10; i++) {
293: assertTrue("has next", en.hasMoreElements());
294: en.nextElement();
295: }
296:
297: assertFalse("No next element", en.hasMoreElements());
298: }
299:
300: public void testFilteringAlsoDoesConvertions() throws Exception {
301: class Pr implements QueueProcess {
302: public Object process(Object o, Collection ignore) {
303: Integer i = (Integer) o;
304: int plus = i.intValue() + 1;
305: return new Integer(plus);
306: }
307: }
308: Pr p = new Pr();
309:
310: Enumeration onetwo = array(new Object[] { new Integer(1),
311: new Integer(2) });
312: Enumeration twothree = array(new Object[] { new Integer(2),
313: new Integer(3) });
314:
315: assertEnums(filter(onetwo, p), twothree);
316: }
317:
318: private static void assertEnums(Enumeration e1, Enumeration e2) {
319: int indx = 0;
320: while (e1.hasMoreElements() && e2.hasMoreElements()) {
321: Object i1 = e1.nextElement();
322: Object i2 = e2.nextElement();
323: assertEquals(indx++ + "th: ", i1, i2);
324: }
325:
326: if (e1.hasMoreElements()) {
327: fail("first one contains another element: "
328: + e1.nextElement());
329: }
330: if (e2.hasMoreElements()) {
331: fail("second one contains another element: "
332: + e2.nextElement());
333: }
334:
335: try {
336: e1.nextElement();
337: fail("First one should throw exception, but nothing happend");
338: } catch (NoSuchElementException ex) {
339: // ok
340: }
341:
342: try {
343: e2.nextElement();
344: fail("Second one should throw exception, but nothing happend");
345: } catch (NoSuchElementException ex) {
346: // ok
347: }
348: }
349:
350: public void testConvertIntegersToStringRemoveNulls() {
351: Object[] garbage = { new Integer(1), "kuk", "hle",
352: new Integer(5) };
353:
354: assertEnums(removeNulls(convert(array(garbage),
355: new MapIntegers())), array(new Object[] { "1", "5" }));
356: }
357:
358: public void testQueueEnumerationCanReturnNulls() {
359: Object[] nuls = { null, "NULL" };
360:
361: class P implements QueueProcess {
362: public Object process(Object toRet, Collection toAdd) {
363: if (toRet == null)
364: return null;
365:
366: if ("NULL".equals(toRet)) {
367: toAdd.add(null);
368: return null;
369: }
370:
371: return null;
372: }
373: }
374:
375: assertEnums(array(new Object[] { null, null, null }), queue(
376: Arrays.asList(nuls), new P()));
377: }
378:
379: /** Filters only strings.
380: */
381: private static final class OnlyStrings implements Set {
382: public boolean add(Object o) {
383: fail("Should not be every called");
384: return false;
385: }
386:
387: public boolean addAll(Collection c) {
388: fail("Should not be every called");
389: return false;
390: }
391:
392: public void clear() {
393: fail("Should not be every called");
394: }
395:
396: public boolean contains(Object o) {
397: return o instanceof String;
398: }
399:
400: public boolean containsAll(Collection c) {
401: fail("Should not be every called");
402: return false;
403: }
404:
405: public boolean isEmpty() {
406: fail("Should not be every called");
407: return false;
408: }
409:
410: public Iterator iterator() {
411: fail("Should not be every called");
412: return null;
413: }
414:
415: public boolean remove(Object o) {
416: fail("Should not be every called");
417: return false;
418: }
419:
420: public boolean removeAll(Collection c) {
421: fail("Should not be every called");
422: return false;
423: }
424:
425: public boolean retainAll(Collection c) {
426: fail("Should not be every called");
427: return false;
428: }
429:
430: public int size() {
431: fail("Should not be every called");
432: return 1;
433: }
434:
435: public Object[] toArray() {
436: fail("Should not be every called");
437: return null;
438: }
439:
440: public Object[] toArray(Object[] a) {
441: fail("Should not be every called");
442: return null;
443: }
444: }
445:
446: /** Filters only strings.
447: */
448: private static final class MapIntegers implements Map {
449: public boolean containsKey(Object key) {
450: fail("Should not be every called");
451: return false;
452: }
453:
454: public boolean containsValue(Object value) {
455: fail("Should not be every called");
456: return false;
457: }
458:
459: public Set entrySet() {
460: fail("Should not be every called");
461: return null;
462: }
463:
464: public Object get(Object key) {
465: if (key instanceof Integer) {
466: return key.toString();
467: }
468: return null;
469: }
470:
471: public Set keySet() {
472: fail("Should not be every called");
473: return null;
474: }
475:
476: public Object put(Object key, Object value) {
477: fail("Should not be every called");
478: return null;
479: }
480:
481: public void putAll(Map t) {
482: fail("Should not be every called");
483: }
484:
485: public Collection values() {
486: fail("Should not be every called");
487: return null;
488: }
489:
490: public void clear() {
491: fail("Should not be every called");
492: }
493:
494: public boolean isEmpty() {
495: fail("Should not be every called");
496: return false;
497: }
498:
499: public Object remove(Object key) {
500: fail("Should not be every called");
501: return null;
502: }
503:
504: public int size() {
505: fail("Should not be every called");
506: return 1;
507: }
508:
509: }
510: }
|