Remove caching gear from jena-core and use instead that in jena-base This closes #59.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/23cef37f Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/23cef37f Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/23cef37f Branch: refs/heads/add-contract-tests Commit: 23cef37f94b9ccc21b54c5a657cc693000ea01f5 Parents: add538f Author: Andy Seaborne <[email protected]> Authored: Mon May 11 19:24:14 2015 +0100 Committer: Andy Seaborne <[email protected]> Committed: Mon May 11 19:24:14 2015 +0100 ---------------------------------------------------------------------- .../java/org/apache/jena/enhanced/EnhGraph.java | 22 +-- .../java/org/apache/jena/util/cache/Cache.java | 49 ------ .../apache/jena/util/cache/CacheControl.java | 70 -------- .../apache/jena/util/cache/CacheManager.java | 53 ------ .../jena/util/cache/EnhancedNodeCache.java | 120 -------------- .../org/apache/jena/util/cache/RandCache.java | 162 ------------------- .../apache/jena/enhanced/test/TestPackage.java | 33 +--- .../java/org/apache/jena/util/TestCache.java | 125 -------------- .../java/org/apache/jena/util/TestPackage.java | 1 - 9 files changed, 10 insertions(+), 625 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jena/blob/23cef37f/jena-core/src/main/java/org/apache/jena/enhanced/EnhGraph.java ---------------------------------------------------------------------- diff --git a/jena-core/src/main/java/org/apache/jena/enhanced/EnhGraph.java b/jena-core/src/main/java/org/apache/jena/enhanced/EnhGraph.java index 1254675..efecff7 100644 --- a/jena-core/src/main/java/org/apache/jena/enhanced/EnhGraph.java +++ b/jena-core/src/main/java/org/apache/jena/enhanced/EnhGraph.java @@ -18,9 +18,10 @@ package org.apache.jena.enhanced; +import org.apache.jena.atlas.lib.Cache; +import org.apache.jena.atlas.lib.CacheFactory; import org.apache.jena.graph.* ; import org.apache.jena.rdf.model.RDFNode ; -import org.apache.jena.util.cache.* ; /** TODO: remove the polymorphic aspect of EnhGraphs. @@ -41,11 +42,10 @@ public class EnhGraph /** The graph that this enhanced graph is wrapping */ protected Graph graph; - /** Counter that helps to ensure that caches are kept distinct */ - static private int cnt = 0; - /** Cache of enhanced nodes that have been created */ - protected Cache enhNodes = CacheManager.createCache( CacheManager.ENHNODECACHE, "EnhGraph-" + cnt++, 1000 ); + // TODO The cache size of 1000 seems to be a "magic number". Perhaps this could be explained + // or parameterized? + protected Cache<Node, RDFNode> enhNodes = CacheFactory.createCache(1000); /** The unique personality that is bound to this polymorphic instace */ private Personality<RDFNode> personality; @@ -130,7 +130,7 @@ public class EnhGraph public <X extends RDFNode> X getNodeAs( Node n, Class<X> interf ) { // We use a cache to avoid reconstructing the same Node too many times. - EnhNode eh = (EnhNode) enhNodes.get( n ); + EnhNode eh = (EnhNode) enhNodes.getIfPresent( n ); if (eh == null) { // not in the cache, so build a new one @@ -143,18 +143,10 @@ public class EnhGraph } /** - * Answer the cache controlle for this graph - * @return A cache controller object - */ - public CacheControl getNodeCacheControl() { - return enhNodes; - } - - /** * Set the cache controller object for this graph * @param cc The cache controller */ - public void setNodeCache(Cache cc) { + public void setNodeCache(Cache<Node, RDFNode> cc) { enhNodes = cc; } http://git-wip-us.apache.org/repos/asf/jena/blob/23cef37f/jena-core/src/main/java/org/apache/jena/util/cache/Cache.java ---------------------------------------------------------------------- diff --git a/jena-core/src/main/java/org/apache/jena/util/cache/Cache.java b/jena-core/src/main/java/org/apache/jena/util/cache/Cache.java deleted file mode 100644 index 66c4989..0000000 --- a/jena-core/src/main/java/org/apache/jena/util/cache/Cache.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.apache.jena.util.cache; - -/** A caching store for objects. - * - * <p>A caching store will hold on to some objects for some - * time, but may fail to store them. It is used as an - * optimization, so that objects that have already been - * constructed, need not be made again. The null object - * should not be stored under a key as there is no way - * to distingish this from a missing object.</p> - * - * <p>Cache objects are usually created using the {@link CacheManager }.</p> - * - * <p>An object is associated with a key which is used to - * identify the object on retrieval. Only one object may be - * associated with a key.</p> - */ -public interface Cache extends CacheControl { - /** Get and object from the cache, if it is there. - * @param key the key for the object sought - * @return the object associated with the key, or null if - * the key is not found in the cache - */ - public Object get(Object key); - /** Store an object in the cache - * @param key the key for the object being stored - * @param value the object stored under the key - * - */ - public void put(Object key, Object value); -} http://git-wip-us.apache.org/repos/asf/jena/blob/23cef37f/jena-core/src/main/java/org/apache/jena/util/cache/CacheControl.java ---------------------------------------------------------------------- diff --git a/jena-core/src/main/java/org/apache/jena/util/cache/CacheControl.java b/jena-core/src/main/java/org/apache/jena/util/cache/CacheControl.java deleted file mode 100644 index 4614936..0000000 --- a/jena-core/src/main/java/org/apache/jena/util/cache/CacheControl.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.apache.jena.util.cache; - -/** An interface for controlling the behaviour of a cache. - * - * <p>This is separated from the main {@link Cache } interface - * so that methods return an object that can set control - * parameters on a cache, without granting read/write access - * to the cache itself.</p> - * - * <p>Cache's may be enabled or disabled. A disabled cache - * is a silent cache; it will silently not return objects - * from its store and not update its store. It will operate - * as if the cache always missed.</p> - * - * <p>Cache's keep statistics on their accesses. On a long - * running cache the numbers may exceeed the size of the - * variables counting the statistics, in which case, the - * fields counting gets hits and puts are reduced - * proportionately.</p> - */ -public interface CacheControl { - - /** Get the enabled state of the cache - * @return The enabled state of the cache - */ - public boolean getEnabled(); - - /** Set the enabled state of a cache - * @param enabled the new enabled state of the cache - * @return the previous enabled state of the cache - */ - public boolean setEnabled(boolean enabled); - - /** Clear the cache's store - */ - public void clear(); - - /** Return number of gets on this cache. - * - * - * @return The number of gets on this cache. - */ - public long getGets(); - /** Get the number of puts on this cache - * @return the number of puts - */ - public long getPuts(); - /** Get the number of hits on this cache - * @return the number of hits - */ - public long getHits(); -} http://git-wip-us.apache.org/repos/asf/jena/blob/23cef37f/jena-core/src/main/java/org/apache/jena/util/cache/CacheManager.java ---------------------------------------------------------------------- diff --git a/jena-core/src/main/java/org/apache/jena/util/cache/CacheManager.java b/jena-core/src/main/java/org/apache/jena/util/cache/CacheManager.java deleted file mode 100644 index c63431b..0000000 --- a/jena-core/src/main/java/org/apache/jena/util/cache/CacheManager.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.apache.jena.util.cache; - -/** A factory for creating cache objects - */ - -public class CacheManager { - - public static final String RAND = "RAND"; - - public static final String ENHNODECACHE = "ENHNODECACHE"; - - /** Creates new Manager */ - private CacheManager() { - } - - /** Create a new cache - * @param type The type of cache to create. This should be one - * of the standard cache types defined in this class. - * @param name A name for the cache. This should be unique and - * may be used to identify the cache in logging and - * other operations. To ensure uniqueness it is - * suggested that cache's be given names similar to - * full java names such as org.apache.jena.graph.Node.NodeCache. - * @param size The size of the cache in terms of the number of - * objects it can store. - * @return a newly created cache object - * - */ - public static Cache createCache(String type, String name, int size) { - // for now we just have one type - if (type.equals(RAND)) return new RandCache( name, size ); - if (type.equals(ENHNODECACHE)) return new EnhancedNodeCache( name, size ); - throw new Error( "Bad cache type: " + type ); - } -} http://git-wip-us.apache.org/repos/asf/jena/blob/23cef37f/jena-core/src/main/java/org/apache/jena/util/cache/EnhancedNodeCache.java ---------------------------------------------------------------------- diff --git a/jena-core/src/main/java/org/apache/jena/util/cache/EnhancedNodeCache.java b/jena-core/src/main/java/org/apache/jena/util/cache/EnhancedNodeCache.java deleted file mode 100644 index 115e117..0000000 --- a/jena-core/src/main/java/org/apache/jena/util/cache/EnhancedNodeCache.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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.apache.jena.util.cache; - -import org.apache.jena.enhanced.EnhNode ; -import org.apache.jena.graph.Node ; - -/** - EnhancedNodeCache - the cache to use for enhanced nodes (mapping a Node - to one of the enhanced nodes it can represent). - - <p>The cache methods do not need to be synchronised. Java guarantees that - access/update of reference values is atomic. The <code>get</code> method - does a single read operation of the cache, and then checks that the - returned element matches the key, only returning legal objects; changes - to the cache subsequently don't affect the correctness of the result. - - <p>The <code>put</code> method updates the appropriate cache entry as - a one-shot deal. gets on different slots don't matter. Gets on the same - slot have either completed (and thus don't care about the change) or - are about to happen (and will be equally happy with the old or new - value). - - <p>Synchronisation *is* required when updating the EnhNode sibling ring, - but that doesn't happen here. -*/ -public class EnhancedNodeCache implements Cache - { - protected String name; - - protected EnhNode [] elements; - - protected boolean enabled = true; - - protected long gets, puts, hits; - - public EnhancedNodeCache( String name, int size ) - { this.name = name; - this.elements = new EnhNode[size]; } - - @Override - public Object get( Object key ) - { - if (enabled) - { - gets += 1; - Node n = (Node) key; - int i = hashNode( n ); - EnhNode result = elements[i]; - if (result != null && result.asNode().equals( key )) - { - hits += 1; - return result; - } - } - return null; - } - - @Override - public void put( Object key, Object value ) - { - if (enabled) - { - puts += 1; - Node n = (Node) key; - int i = hashNode( n ) ; - elements[i] = (EnhNode) value; - } - } - - /** - * @param n - * @return - */ - protected int hashNode( Node n ) - { return (n.hashCode() & 0x7fffffff) % elements.length; } - - @Override - public boolean getEnabled() - { return enabled; } - - @Override - public boolean setEnabled( boolean enabled ) - { boolean result = this.enabled; - this.enabled = enabled; - return result; } - - @Override - public void clear() - { for (int i = 0; i < elements.length; i += 1) elements[i] = null; } - - @Override - public long getGets() - { return gets; } - - @Override - public long getPuts() - { return puts; } - - @Override - public long getHits() - { return hits; } - - } http://git-wip-us.apache.org/repos/asf/jena/blob/23cef37f/jena-core/src/main/java/org/apache/jena/util/cache/RandCache.java ---------------------------------------------------------------------- diff --git a/jena-core/src/main/java/org/apache/jena/util/cache/RandCache.java b/jena-core/src/main/java/org/apache/jena/util/cache/RandCache.java deleted file mode 100644 index 4b6c500..0000000 --- a/jena-core/src/main/java/org/apache/jena/util/cache/RandCache.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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.apache.jena.util.cache; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class RandCache implements Cache, CacheControl { - int size; - int threshhold; - boolean enabled = true; - // so we can identify caches - String name; // e.g. when logging - - HashMap<Object, Object> map; - Collection<Object> collection; - - protected static Logger logger = LoggerFactory.getLogger(RandCache.class); - - long gets = 0; - long puts = 0; - long hits = 0; - - /** Creates new RandCache */ - RandCache(String name, int size) { - this.size = size; - try { - map = new HashMap<>(size * 100 / 75); // based on .75 loadfactor - } catch (IllegalArgumentException e) { - if ("Illegal load factor: NaN".equals(e.getMessage())) { - // This strange construction needs explanation. - // When we implemented XSDbase64Binary/XSDhexBinary support involving use - // of byte[] we started seeing this error here. Since the default loadfactor - // is a static final constant in HashMap this should never be possible. - // It only happens under JDK 1.4.1 not under 1.3.1 nor 1.4.2. - // The retry, however does seem to work and hence gives us a work around - // which is completely mysterious but at least enables the unit tests to pass. - // - der 4/5/04 - logger.warn("Detected a NaN anomaly believed to be due to use of JDK 1.4.1"); - map = new HashMap<>(size*100/75, 0.75f); - } else { - throw e; - } - } - threshhold = size; - if (threshhold < 2) { - throw new Error("Cache size too small: " + size); - } - collection = map.values(); - } - - @Override - public synchronized Object get(Object key) { - if (enabled) { - if (gets == Long.MAX_VALUE) { - forgetStats(); - } - gets++; - Object result = map.get(key); - if (result != null) { - hits++; - } - return result; - } else { - return null; - } - } - - @Override - public synchronized void put(Object key, Object value) { - - // don't allow null values - if (value == null) { - throw new NullPointerException(); - } - - if (enabled) { - if (puts == Long.MAX_VALUE) { - forgetStats(); - } - puts++; - if (map.size() >= threshhold) { - makeSpace(); - } - map.put(key, value); - } - } - - protected void makeSpace() { - Iterator<Object> iter = collection.iterator(); - - // we are going to remove every 3rd member of the cache - int size = map.size(); - int i = 3; - while (i < size ) { - iter.next(); - iter.remove(); - iter.next(); - iter.next(); - i = i + 3; - } - } - - @Override - public synchronized boolean getEnabled() { - return enabled; - } - - @Override - public synchronized boolean setEnabled(boolean enabled) { - boolean result = enabled; - this.enabled = enabled; - return result; - } - - @Override - public synchronized void clear() { - map.clear(); - } - - @Override - public synchronized long getHits() { - return hits; - } - - @Override - public synchronized long getGets() { - return gets; - } - - @Override - public synchronized long getPuts() { - return puts; - } - - protected void forgetStats() { - gets = gets/2; - puts = puts/2; - hits = hits/2; - } - -} http://git-wip-us.apache.org/repos/asf/jena/blob/23cef37f/jena-core/src/test/java/org/apache/jena/enhanced/test/TestPackage.java ---------------------------------------------------------------------- diff --git a/jena-core/src/test/java/org/apache/jena/enhanced/test/TestPackage.java b/jena-core/src/test/java/org/apache/jena/enhanced/test/TestPackage.java index cd6ba84..f895560 100644 --- a/jena-core/src/test/java/org/apache/jena/enhanced/test/TestPackage.java +++ b/jena-core/src/test/java/org/apache/jena/enhanced/test/TestPackage.java @@ -290,23 +290,7 @@ public class TestPackage extends GraphTestBase { }); assertTrue("Model cache test",nodes[0].asProperty().anObject()==nodes[2]); } - private void cache(String title, Personality<RDFNode> p) { - Graph g = Factory.createGraphMem(); - TestModel model = new TestModelImpl(g,p); - // create some data - graphAdd( g, "a b a;" ); - - // get the same node in two different ways. - assertTrue("Caching is on",model.aSubject().asObject()==model.anObject()); - - ((TestModelImpl)model).getNodeCacheControl().setEnabled(false); - - - // get the same node in two different ways; if there isn't any caching - // then we reconstruct the node. - assertFalse("Caching is off",model.aSubject()==model.anObject()); - - } + public static void testSplitBasic() { basic("Split: ",split); } @@ -319,25 +303,14 @@ public class TestPackage extends GraphTestBase { public void testComboFollow() { follow("Combo: ",combo); } - - public void testSplitCache() { - cache("Split: ",split); - } - public void testComboCache() { - cache("Combo: ",combo); - } - + public static void testBitOfBothBasic() { basic("bob: ",bitOfBoth); } public void testBitOfBothFollow() { follow("bob: ",bitOfBoth); } - - public void testBitOfBothCache() { - cache("bob: ",bitOfBoth); - } - + public static void testBitOfBothSurprise() { // bitOfBoth is a surprising personality ... // we can have two different java objects implementing the same interface. http://git-wip-us.apache.org/repos/asf/jena/blob/23cef37f/jena-core/src/test/java/org/apache/jena/util/TestCache.java ---------------------------------------------------------------------- diff --git a/jena-core/src/test/java/org/apache/jena/util/TestCache.java b/jena-core/src/test/java/org/apache/jena/util/TestCache.java deleted file mode 100644 index 9547c9d..0000000 --- a/jena-core/src/test/java/org/apache/jena/util/TestCache.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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.apache.jena.util; - -import junit.framework.*; -import org.apache.jena.util.cache.* ; - - -public class TestCache extends TestCase - { - - public TestCache(String name) - { super( name ); } - - public static TestSuite suite() { - TestSuite suite = new TestSuite("Cache"); - suite.addTest( new CacheTestCase(CacheManager.RAND)); - // suite.addTest( new CacheTestCase(CacheManager.ENHNODECACHE)); - return suite; - } - - static class CacheTestCase extends TestCase { - String cacheType; - - CacheTestCase(String cacheType) { - super( cacheType ); - this.cacheType = cacheType; - } - - @Override - protected void runTest() { - testCache(); - } - - public void testCache() { - testCacheCreation(cacheType); - testCacheSimpleReturn(cacheType); - testFillTheCache(cacheType); - } - - public void testCacheCreation(String type) { - Cache c1 = CacheManager.createCache(type, "c1", 100); - try { - Cache c2 = CacheManager.createCache(type, "c2", 1); - assertTrue("Missing error on bad cache size: " + type, false); - } catch (Error e) {} - } - - public void testCacheSimpleReturn(String type) { - - int size = 100; - // this test does not fill the cache - Cache c1 = CacheManager.createCache(type, "c1", size); - - String k1 = "one"; - String k2 = k1; - String k3 = k2; - Integer v1 = -1; - Integer v2 = v1; - Integer v3 = v2; - c1.put(k1, v1); - - for (int i=0; i<size; i++) { - k1 = k2; - v1 = v2; - Object o = c1.get(k1); - assertTrue("expected a hit", o != null); - assertEquals("should be the expected object", o, v1); - k2 = k3; - v2 = v3; - o = c1.get(k2); - assertTrue("expected a hit", o != null); - assertEquals("should be the expected object", o, v2); - - k3 = "T" + i; - v3 = i; - c1.put(k3,v3); - } - } - - public void testFillTheCache(String type) { - final int size = 100; - Cache c1 = CacheManager.createCache(type, "c1", size); - String[] k = new String[size]; - String[] v = new String[size]; - - for (int i=0; i<size; i++) { - k[i] = "K" + i; - v[i] = "V" + i; - c1.put(k[i], v[i]); - } - - int count = 0; - - for (int i=0; i<size; i++) { - if (c1.get(k[i]) != null) { - count++; - } - } - - assertTrue("too low a hit rate: " + type + " = " + count, - count > size/2); - assertEquals("count puts", size, c1.getPuts()); - assertEquals("count gets", size, c1.getGets()); - assertEquals("count hits", count, c1.getHits()); - } - } - -} http://git-wip-us.apache.org/repos/asf/jena/blob/23cef37f/jena-core/src/test/java/org/apache/jena/util/TestPackage.java ---------------------------------------------------------------------- diff --git a/jena-core/src/test/java/org/apache/jena/util/TestPackage.java b/jena-core/src/test/java/org/apache/jena/util/TestPackage.java index abf2e0e..dc213e6 100644 --- a/jena-core/src/test/java/org/apache/jena/util/TestPackage.java +++ b/jena-core/src/test/java/org/apache/jena/util/TestPackage.java @@ -35,7 +35,6 @@ public class TestPackage extends TestSuite { /** Creates new TestPackage */ private TestPackage() { super( "util" ); - addTest( "TestCache", TestCache.suite() ); addTest( "TestTokenzier", TestTokenizer.suite()); addTest( "TestFileUtils", TestFileUtils.suite() ); addTest( "TestHashUtils", TestCollectionFactory.suite() );
