openide.util/test/unit/src/org/openide/util/EnumerationsTest.java
author Jesse Glick <jglick@netbeans.org>
Fri, 09 Oct 2009 15:11:13 -0400
changeset 833 0e00857c5827
parent 829 3b2ed3e1f01b
child 876 efc7a0e42c5f
permissions -rw-r--r--
Warnings.
     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
     5  *
     6  * The contents of this file are subject to the terms of either the GNU
     7  * General Public License Version 2 only ("GPL") or the Common
     8  * Development and Distribution License("CDDL") (collectively, the
     9  * "License"). You may not use this file except in compliance with the
    10  * License. You can obtain a copy of the License at
    11  * http://www.netbeans.org/cddl-gplv2.html
    12  * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    13  * specific language governing permissions and limitations under the
    14  * License.  When distributing the software, include this License Header
    15  * Notice in each file and include the License file at
    16  * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    17  * particular file as subject to the "Classpath" exception as provided
    18  * by Sun in the GPL Version 2 section of the License file that
    19  * accompanied this code. If applicable, add the following below the
    20  * License Header, with the fields enclosed by brackets [] replaced by
    21  * your own identifying information:
    22  * "Portions Copyrighted [year] [name of copyright owner]"
    23  *
    24  * Contributor(s):
    25  *
    26  * The Original Software is NetBeans. The Initial Developer of the Original
    27  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
    28  * Microsystems, Inc. All Rights Reserved.
    29  *
    30  * If you wish your version of this file to be governed by only the CDDL
    31  * or only the GPL Version 2, indicate your decision by adding
    32  * "[Contributor] elects to include this software in this distribution
    33  * under the [CDDL or GPL Version 2] license." If you do not indicate a
    34  * single choice of license, a recipient has the option to distribute
    35  * your version of this file under either the CDDL, the GPL Version 2 or
    36  * to extend the choice of license to its licensees as provided above.
    37  * However, if you add GPL Version 2 code and therefore, elected the GPL
    38  * Version 2 license, then the option applies only if the new code is
    39  * made subject to such option by the copyright holder.
    40  */
    41 
    42 package org.openide.util;
    43 
    44 import java.util.ArrayList;
    45 import java.util.Arrays;
    46 import java.util.Collection;
    47 import java.util.Collections;
    48 import java.util.Enumeration;
    49 import java.util.Iterator;
    50 import java.util.List;
    51 import java.util.Map;
    52 import java.util.NoSuchElementException;
    53 import java.util.Set;
    54 import org.netbeans.junit.NbTestCase;
    55 
    56 /** This is the base test for new and old enumerations. It contains
    57  * factory methods for various kinds of enumerations and set of tests
    58  * that use them. Factory methods are overriden in OldEnumerationsTest
    59  *
    60  * @author Jaroslav Tulach
    61  */
    62 public class EnumerationsTest extends NbTestCase {
    63     
    64     /** Creates a new instance of EnumerationsTest */
    65     public EnumerationsTest(String testName) {
    66         super(testName);
    67     }
    68     
    69     //
    70     // Factory methods
    71     //
    72     
    73     protected <T> Enumeration<T> singleton(T obj) {
    74         return Enumerations.singleton(obj);
    75     }
    76     protected <T> Enumeration<T> concat(Enumeration<T> en1, Enumeration<T> en2) {
    77         return Enumerations.concat(en1, en2);
    78     }
    79     protected <T> Enumeration<T> concat(Enumeration<Enumeration<T>> enumOfEnums) {
    80         return Enumerations.concat(enumOfEnums);
    81     }
    82     protected <T> Enumeration<T> removeDuplicates(Enumeration<T> en) {
    83         return Enumerations.removeDuplicates(en);
    84     }
    85     protected <T> Enumeration<T> empty() {
    86         return Enumerations.empty();
    87     }
    88     protected <T> Enumeration<T> array(T[] arr) {
    89         return Enumerations.array(arr);
    90     }
    91     protected <T,R> Enumeration<R> convert(Enumeration<T> en, final Map<T,R> map) {
    92         class P implements Enumerations.Processor<T,R> {
    93             public R process(T obj, Collection<T> nothing) {
    94                 return map.get(obj);
    95             }
    96         }
    97         return Enumerations.convert(en, new P());
    98     }
    99     protected <T> Enumeration<T> removeNulls(Enumeration<T> en) {
   100         return Enumerations.removeNulls(en);
   101     }
   102     protected <T> Enumeration<T> filter(Enumeration<T> en, final Set<T> filter) {
   103         class P implements Enumerations.Processor<T,T> {
   104             public T process(T obj, Collection<T> nothing) {
   105                 return filter.contains(obj) ? obj : null;
   106             }
   107         }
   108         return Enumerations.filter(en, new P());
   109     }
   110     
   111     protected <T,R> Enumeration<R> filter(Enumeration<T> en, final QueueProcess<T,R> filter) {
   112         class P implements Enumerations.Processor<T,R> {
   113             public R process(T obj, Collection<T> nothing) {
   114                 return filter.process(obj, nothing);
   115             }
   116         }
   117         return Enumerations.filter(en, new P());
   118     }
   119     
   120     /**
   121      * @param filter the set.contains (...) is called before each object is produced
   122      * @return Enumeration
   123      */
   124     protected <T,R> Enumeration<R> queue(Collection<T> initContent, final QueueProcess<T,R> process) {
   125         class C implements Enumerations.Processor<T,R> {
   126             public R process(T object, Collection<T> toAdd) {
   127                 return process.process(object, toAdd);
   128             }
   129         }
   130         return Enumerations.queue(
   131                 Collections.enumeration(initContent),
   132                 new C()
   133                 );
   134     }
   135     
   136     /** Processor interface.
   137      */
   138     public static interface QueueProcess<T,R> {
   139         public R process(T object, Collection<T> toAdd);
   140     }
   141     
   142     //
   143     // The tests
   144     //
   145     
   146     public void testEmptyIsEmpty() {
   147         Enumeration e = empty();
   148         assertFalse(e.hasMoreElements());
   149         try {
   150             e.nextElement();
   151             fail("No elements");
   152         } catch (NoSuchElementException ex) {
   153             // ok
   154         }
   155     }
   156     
   157     public void testSingleIsSingle() {
   158         Enumeration e = singleton(this);
   159         assertTrue(e.hasMoreElements());
   160         assertEquals("Returns me", this, e.nextElement());
   161         assertFalse("Now it is empty", e.hasMoreElements());
   162         try {
   163             e.nextElement();
   164             fail("No elements");
   165         } catch (NoSuchElementException ex) {
   166             // ok
   167         }
   168     }
   169     
   170     public void testConcatTwoAndArray() {
   171         Object[] one = { 1, 2, 3 };
   172         Object[] two = { "1", "2", "3" };
   173         
   174         List<Object> list = new ArrayList<Object>(Arrays.asList(one));
   175         list.addAll(Arrays.asList(two));
   176         
   177         assertEnums(
   178                 concat(array(one), array(two)),
   179                 Collections.enumeration(list)
   180                 );
   181     }
   182     
   183     public void testConcatTwoAndArrayAndTakeOnlyStrings() {
   184         Object[] one = { 1, 2, 3 };
   185         Object[] two = { "1", "2", "3" };
   186         Object[] three = { 1L };
   187         Object[] four = { "Kuk" };
   188         
   189         List<Object> list = new ArrayList<Object>(Arrays.asList(two));
   190         list.addAll(Arrays.asList(four));
   191         
   192         @SuppressWarnings("unchecked")
   193         Enumeration<Object>[] alls = (Enumeration<Object>[]) new Enumeration<?>[] {
   194             array(one), array(two), array(three), array(four)
   195         };
   196         
   197         assertEnums(
   198                 filter(concat(array(alls)), new OnlyStrings()),
   199                 Collections.enumeration(list)
   200                 );
   201     }
   202     
   203     public void testRemoveDuplicates() {
   204         Object[] one = { 1, 2, 3 };
   205         Object[] two = { "1", "2", "3" };
   206         Object[] three = { 1 };
   207         Object[] four = { "2", "3", "4" };
   208         
   209         @SuppressWarnings("unchecked")
   210         Enumeration<Object>[] alls = (Enumeration<Object>[]) new Enumeration<?>[] {
   211             array(one), array(two), array(three), array(four)
   212         };
   213         
   214         assertEnums(
   215                 removeDuplicates(concat(array(alls))),
   216                 array(new Object[] { 1, 2, 3, "1", "2", "3", "4" })
   217                 );
   218         
   219     }
   220     
   221     public void testRemoveDuplicatesAndGCWorks() {
   222         
   223         /*** Return { i1, "", "", "", i2 } */
   224         class WeakEnum implements Enumeration<Object> {
   225             public Object i1 = new Integer(1);
   226             public Object i2 = new Integer(1);
   227             
   228             private int state;
   229             
   230             public boolean hasMoreElements() {
   231                 return state < 5;
   232             }
   233             
   234             public Object nextElement() {
   235                 switch (state++) {
   236                     case 0: return i1;
   237                     case 1: case 2: case 3: return "";
   238                     default: return i2;
   239                 }
   240             }
   241         }
   242         
   243         WeakEnum weak = new WeakEnum();
   244         Enumeration en = removeDuplicates(weak);
   245         
   246         assertTrue("Has some elements", en.hasMoreElements());
   247         assertEquals("And the first one is get", weak.i1, en.nextElement());
   248 
   249         /*
   250         try {
   251             Reference<?> ref = new WeakReference<Object>(weak.i1);
   252          */
   253             weak.i1 = null;
   254         /*
   255             assertGC("Try hard to GC the first integer", ref);
   256             // does not matter whether it GCs or not
   257         } catch (Throwable tw) {
   258             // not GCed, but does not matter
   259         }
   260          */
   261         assertTrue("Next object will be string", en.hasMoreElements());
   262         assertEquals("is empty string", "", en.nextElement());
   263         
   264         assertFalse("The second integer is however equal to the original i1 and thus" +
   265                 " the enum should not be there", en.hasMoreElements());
   266     }
   267     
   268     public void testQueueEnum() {
   269         class Pr implements QueueProcess<Integer,Integer> {
   270             public Integer process(Integer i, Collection<Integer> c) {
   271                 int plus = i + 1;
   272                 if (plus < 10) {
   273                     c.add(plus);
   274                 }
   275                 return i;
   276             }
   277         }
   278         Pr p = new Pr();
   279         
   280         Enumeration en = queue(
   281                 Collections.nCopies(1, 0), p
   282                 );
   283         
   284         for (int i = 0; i < 10; i++) {
   285             assertTrue("has next", en.hasMoreElements());
   286             en.nextElement();
   287         }
   288         
   289         assertFalse("No next element", en.hasMoreElements());
   290     }
   291     
   292     public void testFilteringAlsoDoesConvertions() throws Exception {
   293         class Pr implements QueueProcess<Integer,Integer> {
   294             public Integer process(Integer i, Collection<Integer> ignore) {
   295                 return i + 1;
   296             }
   297         }
   298         Pr p = new Pr();
   299         
   300         Enumeration<Integer> onetwo = array(new Integer[] { 1, 2 });
   301         Enumeration<Integer> twothree = array(new Integer[] { 2, 3 });
   302         
   303         assertEnums(
   304                 filter(onetwo, p), twothree
   305                 );
   306     }
   307     
   308     
   309     private static <T> void assertEnums(Enumeration<T> e1, Enumeration<T> e2) {
   310         int indx = 0;
   311         while (e1.hasMoreElements() && e2.hasMoreElements()) {
   312             T i1 = e1.nextElement();
   313             T i2 = e2.nextElement();
   314             assertEquals(indx++ + "th: ", i1, i2);
   315         }
   316         
   317         if (e1.hasMoreElements()) {
   318             fail("first one contains another element: " + e1.nextElement());
   319         }
   320         if (e2.hasMoreElements()) {
   321             fail("second one contains another element: " + e2.nextElement());
   322         }
   323         
   324         try {
   325             e1.nextElement();
   326             fail("First one should throw exception, but nothing happend");
   327         } catch (NoSuchElementException ex) {
   328             // ok
   329         }
   330         
   331         try {
   332             e2.nextElement();
   333             fail("Second one should throw exception, but nothing happend");
   334         } catch (NoSuchElementException ex) {
   335             // ok
   336         }
   337     }
   338     
   339     public void testConvertIntegersToStringRemoveNulls() {
   340         Object[] garbage = { 1, "kuk", "hle", 5 };
   341         
   342         assertEnums(
   343                 removeNulls(convert(array(garbage), new MapIntegers())),
   344                 array(new Object[] { "1", "5" })
   345                 );
   346     }
   347     
   348     public void testQueueEnumerationCanReturnNulls() {
   349         Object[] nuls = { null, "NULL" };
   350         
   351         class P implements QueueProcess<Object,Object> {
   352             public Object process(Object toRet, Collection<Object> toAdd) {
   353                 if (toRet == null) return null;
   354                 
   355                 if ("NULL".equals(toRet)) {
   356                     toAdd.add(null);
   357                     return null;
   358                 }
   359                 
   360                 return null;
   361             }
   362         }
   363         
   364         assertEnums(
   365                 array(new Object[] { null, null, null }),
   366                 queue(Arrays.asList(nuls), new P())
   367                 );
   368     }
   369     
   370     /** Filters only strings.
   371      */
   372     private static final class OnlyStrings implements Set<Object> {
   373         public boolean add(Object o) {
   374             fail("Should not be every called");
   375             return false;
   376         }
   377         
   378         public boolean addAll(Collection c) {
   379             fail("Should not be every called");
   380             return false;
   381         }
   382         
   383         public void clear() {
   384             fail("Should not be every called");
   385         }
   386         
   387         public boolean contains(Object o) {
   388             return o instanceof String;
   389         }
   390         
   391         public boolean containsAll(Collection c) {
   392             fail("Should not be every called");
   393             return false;
   394         }
   395         
   396         public boolean isEmpty() {
   397             fail("Should not be every called");
   398             return false;
   399         }
   400         
   401         public Iterator<Object> iterator() {
   402             fail("Should not be every called");
   403             return null;
   404         }
   405         
   406         public boolean remove(Object o) {
   407             fail("Should not be every called");
   408             return false;
   409         }
   410         
   411         public boolean removeAll(Collection c) {
   412             fail("Should not be every called");
   413             return false;
   414         }
   415         
   416         public boolean retainAll(Collection c) {
   417             fail("Should not be every called");
   418             return false;
   419         }
   420         
   421         public int size() {
   422             fail("Should not be every called");
   423             return 1;
   424         }
   425         
   426         public Object[] toArray() {
   427             fail("Should not be every called");
   428             return null;
   429         }
   430         
   431         public <T> T[] toArray(T[] a) {
   432             fail("Should not be every called");
   433             return null;
   434         }
   435     }
   436     
   437     /** Filters only strings.
   438      */
   439     private static final class MapIntegers implements Map<Object,Object> {
   440         public boolean containsKey(Object key) {
   441             fail("Should not be every called");
   442             return false;
   443         }
   444         
   445         public boolean containsValue(Object value) {
   446             fail("Should not be every called");
   447             return false;
   448         }
   449         
   450         public Set<Map.Entry<Object,Object>> entrySet() {
   451             fail("Should not be every called");
   452             return null;
   453         }
   454         
   455         public Object get(Object key) {
   456             if (key instanceof Integer) {
   457                 return key.toString();
   458             }
   459             return null;
   460         }
   461         
   462         public Set<Object> keySet() {
   463             fail("Should not be every called");
   464             return null;
   465         }
   466         
   467         public Object put(Object key, Object value) {
   468             fail("Should not be every called");
   469             return null;
   470         }
   471         
   472         public void putAll(Map t) {
   473             fail("Should not be every called");
   474         }
   475         
   476         public Collection<Object> values() {
   477             fail("Should not be every called");
   478             return null;
   479         }
   480         
   481         public void clear() {
   482             fail("Should not be every called");
   483         }
   484         
   485         public boolean isEmpty() {
   486             fail("Should not be every called");
   487             return false;
   488         }
   489         
   490         public Object remove(Object key) {
   491             fail("Should not be every called");
   492             return null;
   493         }
   494         
   495         public int size() {
   496             fail("Should not be every called");
   497             return 1;
   498         }
   499         
   500     }
   501 }