blob: ab7541f2c12794b5a2b279146928fd2a4cc797a0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.openide.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Enumerations;
/** This is the base test for new and old enumerations. It contains
* factory methods for various kinds of enumerations and set of tests
* that use them. Factory methods are overriden in OldEnumerationsTest
*
* @author Jaroslav Tulach
*/
public class EnumerationsTest extends NbTestCase {
/** Creates a new instance of EnumerationsTest */
public EnumerationsTest(String testName) {
super(testName);
}
//
// Factory methods
//
protected <T> Enumeration<T> singleton(T obj) {
return Enumerations.singleton(obj);
}
protected <T> Enumeration<T> concat(Enumeration<T> en1, Enumeration<T> en2) {
return Enumerations.concat(en1, en2);
}
protected <T> Enumeration<T> concat(Enumeration<Enumeration<T>> enumOfEnums) {
return Enumerations.concat(enumOfEnums);
}
protected <T> Enumeration<T> removeDuplicates(Enumeration<T> en) {
return Enumerations.removeDuplicates(en);
}
protected <T> Enumeration<T> empty() {
return Enumerations.empty();
}
protected <T> Enumeration<T> array(T[] arr) {
return Enumerations.array(arr);
}
protected <T,R> Enumeration<R> convert(Enumeration<T> en, final Map<T,R> map) {
class P implements Enumerations.Processor<T,R> {
public R process(T obj, Collection<T> nothing) {
return map.get(obj);
}
}
return Enumerations.convert(en, new P());
}
protected <T> Enumeration<T> removeNulls(Enumeration<T> en) {
return Enumerations.removeNulls(en);
}
protected <T> Enumeration<T> filter(Enumeration<T> en, final Set<T> filter) {
class P implements Enumerations.Processor<T,T> {
public T process(T obj, Collection<T> nothing) {
return filter.contains(obj) ? obj : null;
}
}
return Enumerations.filter(en, new P());
}
protected <T,R> Enumeration<R> filter(Enumeration<T> en, final QueueProcess<T,R> filter) {
class P implements Enumerations.Processor<T,R> {
public R process(T obj, Collection<T> nothing) {
return filter.process(obj, nothing);
}
}
return Enumerations.filter(en, new P());
}
/**
* @param filter the set.contains (...) is called before each object is produced
* @return Enumeration
*/
protected <T,R> Enumeration<R> queue(Collection<T> initContent, final QueueProcess<T,R> process) {
class C implements Enumerations.Processor<T,R> {
public R process(T object, Collection<T> toAdd) {
return process.process(object, toAdd);
}
}
return Enumerations.queue(
Collections.enumeration(initContent),
new C()
);
}
/** Processor interface.
*/
public static interface QueueProcess<T,R> {
public R process(T object, Collection<T> toAdd);
}
//
// The tests
//
public void testEmptyIsEmpty() {
Enumeration<?> e = empty();
assertFalse(e.hasMoreElements());
try {
e.nextElement();
fail("No elements");
} catch (NoSuchElementException ex) {
// ok
}
}
public void testSingleIsSingle() {
Enumeration<EnumerationsTest> e = singleton(this);
assertTrue(e.hasMoreElements());
assertEquals("Returns me", this, e.nextElement());
assertFalse("Now it is empty", e.hasMoreElements());
try {
e.nextElement();
fail("No elements");
} catch (NoSuchElementException ex) {
// ok
}
}
public void testConcatTwoAndArray() {
Object[] one = { 1, 2, 3 };
Object[] two = { "1", "2", "3" };
List<Object> list = new ArrayList<Object>(Arrays.asList(one));
list.addAll(Arrays.asList(two));
assertEnums(
concat(array(one), array(two)),
Collections.enumeration(list)
);
}
public void testConcatTwoAndArrayAndTakeOnlyStrings() {
Object[] one = { 1, 2, 3 };
Object[] two = { "1", "2", "3" };
Object[] three = { 1L };
Object[] four = { "Kuk" };
List<Object> list = new ArrayList<Object>(Arrays.asList(two));
list.addAll(Arrays.asList(four));
@SuppressWarnings("unchecked")
Enumeration<Object>[] alls = (Enumeration<Object>[]) new Enumeration<?>[] {
array(one), array(two), array(three), array(four)
};
assertEnums(
filter(concat(array(alls)), new OnlyStrings()),
Collections.enumeration(list)
);
}
public void testRemoveDuplicates() {
Object[] one = { 1, 2, 3 };
Object[] two = { "1", "2", "3" };
Object[] three = { 1 };
Object[] four = { "2", "3", "4" };
@SuppressWarnings("unchecked")
Enumeration<Object>[] alls = (Enumeration<Object>[]) new Enumeration<?>[] {
array(one), array(two), array(three), array(four)
};
assertEnums(
removeDuplicates(concat(array(alls))),
array(new Object[] { 1, 2, 3, "1", "2", "3", "4" })
);
}
public void testRemoveDuplicatesAndGCWorks() {
/*** Return { i1, "", "", "", i2 } */
class WeakEnum implements Enumeration<Object> {
public Object i1 = new Integer(1);
public Object i2 = new Integer(1);
private int state;
public boolean hasMoreElements() {
return state < 5;
}
public Object nextElement() {
switch (state++) {
case 0: return i1;
case 1: case 2: case 3: return "";
default: return i2;
}
}
}
WeakEnum weak = new WeakEnum();
Enumeration<Object> en = removeDuplicates(weak);
assertTrue("Has some elements", en.hasMoreElements());
assertEquals("And the first one is get", weak.i1, en.nextElement());
/*
try {
Reference<?> ref = new WeakReference<Object>(weak.i1);
*/
weak.i1 = null;
/*
assertGC("Try hard to GC the first integer", ref);
// does not matter whether it GCs or not
} catch (Throwable tw) {
// not GCed, but does not matter
}
*/
assertTrue("Next object will be string", en.hasMoreElements());
assertEquals("is empty string", "", en.nextElement());
assertFalse("The second integer is however equal to the original i1 and thus" +
" the enum should not be there", en.hasMoreElements());
}
public void testQueueEnum() {
class Pr implements QueueProcess<Integer,Integer> {
public Integer process(Integer i, Collection<Integer> c) {
int plus = i + 1;
if (plus < 10) {
c.add(plus);
}
return i;
}
}
Pr p = new Pr();
Enumeration<Integer> en = queue(
Collections.nCopies(1, 0), p
);
for (int i = 0; i < 10; i++) {
assertTrue("has next", en.hasMoreElements());
en.nextElement();
}
assertFalse("No next element", en.hasMoreElements());
}
public void testFilteringAlsoDoesConvertions() throws Exception {
class Pr implements QueueProcess<Integer,Integer> {
public Integer process(Integer i, Collection<Integer> ignore) {
return i + 1;
}
}
Pr p = new Pr();
Enumeration<Integer> onetwo = array(new Integer[] { 1, 2 });
Enumeration<Integer> twothree = array(new Integer[] { 2, 3 });
assertEnums(
filter(onetwo, p), twothree
);
}
private static <T> void assertEnums(Enumeration<T> e1, Enumeration<T> e2) {
int indx = 0;
while (e1.hasMoreElements() && e2.hasMoreElements()) {
T i1 = e1.nextElement();
T i2 = e2.nextElement();
assertEquals(indx++ + "th: ", i1, i2);
}
if (e1.hasMoreElements()) {
fail("first one contains another element: " + e1.nextElement());
}
if (e2.hasMoreElements()) {
fail("second one contains another element: " + e2.nextElement());
}
try {
e1.nextElement();
fail("First one should throw exception, but nothing happend");
} catch (NoSuchElementException ex) {
// ok
}
try {
e2.nextElement();
fail("Second one should throw exception, but nothing happend");
} catch (NoSuchElementException ex) {
// ok
}
}
public void testConvertIntegersToStringRemoveNulls() {
Object[] garbage = { 1, "kuk", "hle", 5 };
assertEnums(
removeNulls(convert(array(garbage), new MapIntegers())),
array(new Object[] { "1", "5" })
);
}
public void testQueueEnumerationCanReturnNulls() {
Object[] nuls = { null, "NULL" };
class P implements QueueProcess<Object,Object> {
public Object process(Object toRet, Collection<Object> toAdd) {
if (toRet == null) return null;
if ("NULL".equals(toRet)) {
toAdd.add(null);
return null;
}
return null;
}
}
assertEnums(
array(new Object[] { null, null, null }),
queue(Arrays.asList(nuls), new P())
);
}
/** Filters only strings.
*/
private static final class OnlyStrings implements Set<Object> {
public boolean add(Object o) {
fail("Should not be every called");
return false;
}
public boolean addAll(Collection c) {
fail("Should not be every called");
return false;
}
public void clear() {
fail("Should not be every called");
}
public boolean contains(Object o) {
return o instanceof String;
}
public boolean containsAll(Collection c) {
fail("Should not be every called");
return false;
}
public boolean isEmpty() {
fail("Should not be every called");
return false;
}
public Iterator<Object> iterator() {
fail("Should not be every called");
return null;
}
public boolean remove(Object o) {
fail("Should not be every called");
return false;
}
public boolean removeAll(Collection c) {
fail("Should not be every called");
return false;
}
public boolean retainAll(Collection c) {
fail("Should not be every called");
return false;
}
public int size() {
fail("Should not be every called");
return 1;
}
public Object[] toArray() {
fail("Should not be every called");
return null;
}
public <T> T[] toArray(T[] a) {
fail("Should not be every called");
return null;
}
}
/** Filters only strings.
*/
private static final class MapIntegers implements Map<Object,Object> {
public boolean containsKey(Object key) {
fail("Should not be every called");
return false;
}
public boolean containsValue(Object value) {
fail("Should not be every called");
return false;
}
public Set<Map.Entry<Object,Object>> entrySet() {
fail("Should not be every called");
return null;
}
public Object get(Object key) {
if (key instanceof Integer) {
return key.toString();
}
return null;
}
public Set<Object> keySet() {
fail("Should not be every called");
return null;
}
public Object put(Object key, Object value) {
fail("Should not be every called");
return null;
}
public void putAll(Map t) {
fail("Should not be every called");
}
public Collection<Object> values() {
fail("Should not be every called");
return null;
}
public void clear() {
fail("Should not be every called");
}
public boolean isEmpty() {
fail("Should not be every called");
return false;
}
public Object remove(Object key) {
fail("Should not be every called");
return null;
}
public int size() {
fail("Should not be every called");
return 1;
}
}
}