You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2012/06/21 01:12:20 UTC

git commit: Convert TestNG to Spock - fix some broken (not run?) tests related to injection - fix a incorrectly produced exception message - make @javax.annotations.Inject (without @Named) on a field work the same as @Inject

Updated Branches:
  refs/heads/master 0cf6562f4 -> 01ce2a458


Convert TestNG to Spock
- fix some broken (not run?) tests related to injection
- fix a incorrectly produced exception message
- make @javax.annotations.Inject (without @Named) on a field work the same as @Inject


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/01ce2a45
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/01ce2a45
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/01ce2a45

Branch: refs/heads/master
Commit: 01ce2a458ff25b72f6924ddd6fb60d1e237a8456
Parents: 0cf6562
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Wed Jun 20 16:11:59 2012 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Wed Jun 20 16:11:59 2012 -0700

----------------------------------------------------------------------
 .../tapestry5/ioc/internal/util/InternalUtils.java |   83 ++-
 .../tapestry5/ioc/util/InternalUtilsSpec.groovy    |  608 ++++++++++++
 .../ioc/internal/util/InternalUtilsTest.java       |  754 ---------------
 .../util/TooManyAutobuildConstructorsBean.java     |   16 +-
 4 files changed, 664 insertions(+), 797 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/01ce2a45/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
index 63f71f6..5f910d4 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
@@ -70,8 +70,10 @@ public class InternalUtils
      * (where possible). {@link #asString(Method)} is used under the covers, to present a detailed, but not excessive,
      * description of the class, method and parameters.
      *
-     * @param method       method to convert to a string
-     * @param proxyFactory used to obtain the {@link Location}
+     * @param method
+     *         method to convert to a string
+     * @param proxyFactory
+     *         used to obtain the {@link Location}
      * @return the method formatted for presentation to the user
      */
     public static String asString(Method method, PlasticProxyFactory proxyFactory)
@@ -161,8 +163,10 @@ public class InternalUtils
      * Finds a specific annotation type within an array of annotations.
      *
      * @param <T>
-     * @param annotations     to search
-     * @param annotationClass to match
+     * @param annotations
+     *         to search
+     * @param annotationClass
+     *         to match
      * @return the annotation instance, if found, or null otherwise
      */
     public static <T extends Annotation> T findAnnotation(Annotation[] annotations, Class<T> annotationClass)
@@ -294,10 +298,14 @@ public class InternalUtils
      * Injects into the fields (of all visibilities) when the {@link org.apache.tapestry5.ioc.annotations.Inject} or
      * {@link org.apache.tapestry5.ioc.annotations.InjectService} annotations are present.
      *
-     * @param object    to be initialized
-     * @param locator   used to resolve external dependencies
-     * @param resources provides injection resources for fields
-     * @param tracker   track operations
+     * @param object
+     *         to be initialized
+     * @param locator
+     *         used to resolve external dependencies
+     * @param resources
+     *         provides injection resources for fields
+     * @param tracker
+     *         track operations
      */
     public static void injectIntoFields(final Object object, final ObjectLocator locator,
                                         final InjectionResources resources, OperationTracker tracker)
@@ -362,6 +370,14 @@ public class InternalUtils
 
                             if (named == null)
                             {
+                                Object value = resources.findResource(fieldType, f.getGenericType());
+
+                                if (value != null)
+                                {
+                                    inject(object, f, value);
+                                    return;
+                                }
+
                                 inject(object, f, locator.getObject(fieldType, ap));
                             } else
                             {
@@ -410,8 +426,10 @@ public class InternalUtils
      * Joins together some number of elements. If a value in the list is the empty string, it is replaced with the
      * string "(blank)".
      *
-     * @param elements  objects to be joined together
-     * @param separator used between elements when joining
+     * @param elements
+     *         objects to be joined together
+     * @param separator
+     *         used between elements when joining
      */
     public static String join(List elements, String separator)
     {
@@ -529,7 +547,8 @@ public class InternalUtils
     /**
      * Extracts the string keys from a map and returns them in sorted order. The keys are converted to strings.
      *
-     * @param map the map to extract keys from (may be null)
+     * @param map
+     *         the map to extract keys from (may be null)
      * @return the sorted keys, or the empty set if map is null
      */
 
@@ -561,7 +580,8 @@ public class InternalUtils
      *
      * @param <K>
      * @param <V>
-     * @param map the map to extract from (may be null)
+     * @param map
+     *         the map to extract from (may be null)
      * @param key
      * @return the value from the map, or null if the map is null
      */
@@ -637,7 +657,8 @@ public class InternalUtils
      * annotated with {@link org.apache.tapestry5.ioc.annotations.Inject}, it will be used (no check for multiple such
      * constructors is made, only at most a single constructor should have the annotation).
      *
-     * @param clazz to search for a constructor for
+     * @param clazz
+     *         to search for a constructor for
      * @return the constructor to be used to instantiate the class, or null if no appropriate constructor was found
      */
     public static Constructor findAutobuildConstructor(Class clazz)
@@ -658,26 +679,24 @@ public class InternalUtils
                 break;
         }
 
-        for (Constructor c : constructors)
-        {
-            if (c.getAnnotation(Inject.class) != null)
-                return c;
-        }
-
         Constructor standardConstructor = findConstructorByAnnotation(constructors, Inject.class);
         Constructor javaxConstructor = findConstructorByAnnotation(constructors, javax.inject.Inject.class);
 
         if (standardConstructor != null && javaxConstructor != null)
             throw new IllegalArgumentException(
                     String.format(
-                            "Too many autobuilt constructors found. Please use either '@%s' or '@%s' annotation to mark a constructor for autobuilding.",
+                            "Too many autobuild constructors found: use either @%s or @%s annotation to mark a single constructor for autobuilding.",
                             Inject.class.getName(), javax.inject.Inject.class.getName()));
 
         if (standardConstructor != null)
+        {
             return standardConstructor;
+        }
 
         if (javaxConstructor != null)
+        {
             return javaxConstructor;
+        }
 
         // Choose a constructor with the most parameters.
 
@@ -710,11 +729,16 @@ public class InternalUtils
      * Adds a value to a specially organized map where the values are lists of objects. This somewhat simulates a map
      * that allows multiple values for the same key.
      *
-     * @param map   to store value into
-     * @param key   for which a value is added
-     * @param value to add
-     * @param <K>   the type of key
-     * @param <V>   the type of the list
+     * @param map
+     *         to store value into
+     * @param key
+     *         for which a value is added
+     * @param value
+     *         to add
+     * @param <K>
+     *         the type of key
+     * @param <V>
+     *         the type of the list
      */
     public static <K, V> void addToMapList(Map<K, List<V>> map, K key, V value)
     {
@@ -732,7 +756,8 @@ public class InternalUtils
     /**
      * Validates that the marker annotation class had a retention policy of runtime.
      *
-     * @param markerClass the marker annotation class
+     * @param markerClass
+     *         the marker annotation class
      */
     public static void validateMarkerAnnotation(Class markerClass)
     {
@@ -765,7 +790,8 @@ public class InternalUtils
     /**
      * Extracts the message from an exception. If the exception's message is null, returns the exceptions class name.
      *
-     * @param exception to extract message from
+     * @param exception
+     *         to extract message from
      * @return message or class name
      */
     public static String toMessage(Throwable exception)
@@ -1324,7 +1350,8 @@ public class InternalUtils
      * returned.
      * If neither of the annotations is present, <code>null</code> value is returned
      *
-     * @param annotated annotated element to get annotations from
+     * @param annotated
+     *         annotated element to get annotations from
      * @since 5.3
      */
     public static String getServiceId(AnnotatedElement annotated)

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/01ce2a45/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/util/InternalUtilsSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/util/InternalUtilsSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/util/InternalUtilsSpec.groovy
new file mode 100644
index 0000000..fa4b839
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/util/InternalUtilsSpec.groovy
@@ -0,0 +1,608 @@
+package org.apache.tapestry5.ioc.util
+
+import org.apache.tapestry5.func.F
+import org.apache.tapestry5.func.Predicate
+import org.apache.tapestry5.ioc.annotations.Inject
+import org.apache.tapestry5.ioc.def.ServiceDef
+import org.apache.tapestry5.ioc.def.ServiceDef2
+import org.apache.tapestry5.ioc.internal.QuietOperationTracker
+import org.apache.tapestry5.ioc.services.Builtin
+import org.apache.tapestry5.ioc.services.Coercion
+import org.apache.tapestry5.ioc.services.SymbolSource
+import spock.lang.Shared
+import spock.lang.Specification
+import spock.lang.Unroll
+
+import java.lang.reflect.Method
+
+import org.apache.tapestry5.ioc.*
+import org.apache.tapestry5.ioc.internal.util.*
+
+class InternalUtilsSpec extends Specification {
+
+  private static class PrivateInnerClass {
+
+    public PrivateInnerClass() {
+    }
+  }
+
+  static class PublicInnerClass {
+
+    protected PublicInnerClass() {
+    }
+  }
+
+  @Shared
+  def tracker = new QuietOperationTracker();
+
+
+  @Unroll
+  def "asString(): #desc"() {
+
+    when:
+
+    Method m = clazz.getMethod(methodName, * paramTypes)
+
+    then:
+
+    InternalUtils.asString(m) == expected
+
+    where:
+
+    clazz       | methodName | paramTypes         | expected                                       | desc
+    Object      | "toString" | []                 | "java.lang.Object.toString()"                  | "method with no arguments"
+    Collections | "sort"     | [List, Comparator] | "java.util.Collections.sort(List, Comparator)" | "method with multiple argments"
+    Object      | "wait"     | [long]             | "java.lang.Object.wait(long)"                  | "method with primitive argument"
+    Arrays      | "sort"     | [int[]]            | "java.util.Arrays.sort(int[])"                 | "method with primitive array argument"
+    Arrays      | "sort"     | [Object[]]         | "java.util.Arrays.sort(Object[])"              | "method with object array argument"
+  }
+
+  @Unroll
+  def "size(): #desc"() {
+    expect:
+
+    InternalUtils.size(array as Object[]) == expected
+
+    where:
+
+    array     | expected | desc
+    []        | 0        | "empty array"
+    null      | 0        | "null is size 0"
+    [1, 2, 3] | 3        | "non-empty array"
+  }
+
+  @Unroll
+  def "stripMemberName('#input') should be '#expected'"() {
+    expect:
+
+    InternalUtils.stripMemberName(input) == expected
+
+    where:
+
+    input                         | expected
+    "simple"                      | "simple"
+    "_name"                       | "name"
+    '$name'                       | "name"
+    '__$ruby_style_'              | "ruby_style"
+    '$_$__$__$_$____$_$_$_$$name' | "name"
+    "foo_"                        | "foo"
+    "_foo_"                       | "foo"
+  }
+
+  def "invalid input to stripMemberName() is an exception"() {
+    when:
+
+    InternalUtils.stripMemberName("!foo")
+
+    then:
+
+    IllegalArgumentException e = thrown()
+
+    e.message == "Input '!foo' is not a valid Java identifier."
+  }
+
+  def "toList(Enumeration) is a sorted list"() {
+    when:
+
+    def e = Collections.enumeration(["wilma", "fred", "barney"])
+
+    then:
+
+    InternalUtils.toList(e) == ["barney", "fred", "wilma"]
+  }
+
+  @Unroll
+  def "join(): #desc"() {
+    expect:
+
+    InternalUtils.join(list) == expected
+
+    where:
+
+    list                            | expected                       | desc
+    ["barney"]                      | "barney"                       | "single value"
+    ["fred", "barney", "wilma"]     | "fred, barney, wilma"          | "multiple values"
+    ["fred", "barney", "", "wilma"] | "fred, barney, (blank), wilma" | "empty string converted to '(blank)'"
+  }
+
+  @Unroll
+  def "joinSorted(): #desc"() {
+    InternalUtils.joinSorted(list) == expected
+
+    where:
+
+    list                            | expected                       | desc
+    null                            | "(none)"                       | "null list is '(none)'"
+    []                              | "(none)"                       | "empty list is '(none)'"
+    ["barney"]                      | "barney"                       | "single value"
+    ["fred", "barney", "wilma"]     | "barney, fred, wilma"          | "multiple values"
+    ["fred", "barney", "", "wilma"] | "(blank), barney, fred, wilma" | "empty string converted to '(blank)'"
+  }
+
+  @Unroll
+  def "capitalize('#input') is '#expected'"() {
+    expect:
+
+    InternalUtils.capitalize(input) == expected
+
+    where:
+
+    input     | expected
+    "hello"   | "Hello"
+    "Goodbye" | "Goodbye"
+    ""        | ""
+    "a"       | "A"
+    "A"       | "A"
+  }
+
+  def "locationOf(Object)"() {
+    Locatable locatable = Mock()
+    Location l = Mock()
+
+    expect:
+
+    InternalUtils.locationOf(null) == null
+    InternalUtils.locationOf("La! La!") == null
+
+    InternalUtils.locationOf(l).is(l)
+
+    when:
+
+    def actual = InternalUtils.locationOf(locatable)
+
+    then:
+
+    _ * locatable.location >> l
+
+    actual.is(l)
+  }
+
+  @Unroll
+  def "sortedKeys(): #desc"() {
+    expect:
+
+    InternalUtils.sortedKeys(map) == expected
+
+    where:
+
+    map                                        | expected           | desc
+    null                                       | []                 | "null map"
+    [:]                                        | []                 | "empty map"
+    ["fred": "flintstone", "barney": "rubble"] | ["barney", "fred"] | "standard map"
+  }
+
+  @Unroll
+  def "get(Map,Object): #desc"() {
+    expect:
+
+    InternalUtils.get(map, key) == expected
+
+    where:
+
+    map                    | key      | expected     | desc
+    null                   | null     | null         | "null key and map"
+    null                   | "foo"    | null         | "null map"
+    ["fred": "flintstone"] | "fred"   | "flintstone" | "real map and key"
+    ["fred": "flintstone"] | "barney" | null         | "real map with missing key"
+  }
+
+  def "reverseIterator(List)"() {
+    when:
+
+    def i = InternalUtils.reverseIterator(["a", "b", "c"])
+
+    then:
+
+    i.hasNext()
+    i.next() == "c"
+
+    i.hasNext()
+    i.next() == "b"
+
+    i.hasNext()
+    i.next() == "a"
+
+    !i.hasNext()
+  }
+
+  def "remove() not supported by reverse Iterator"() {
+    def i = InternalUtils.reverseIterator(["a", "b", "c"])
+
+    when:
+
+    i.remove()
+
+    then:
+
+    thrown(UnsupportedOperationException)
+  }
+
+  @Unroll
+  def "lastTerm(): #desc"() {
+    expect:
+
+    InternalUtils.lastTerm(input) == expected
+
+    where:
+
+    input             | expected | desc
+    "simple"          | "simple" | "single term"
+    ""                | ""       | "empty string"
+    "fee.fie.foe.fum" | "fum"    | "dotted name sequence"
+  }
+
+  def "simple value passed to lastTerm() returns the exact input value"() {
+    def input = "simple"
+
+    expect:
+
+    InternalUtils.lastTerm(input).is(input)
+  }
+
+  def "addToMapList()"() {
+    def map = [:]
+
+    when:
+
+    InternalUtils.addToMapList(map, "fred", 1)
+
+    then:
+
+    map == ["fred": [1]]
+
+    when:
+
+    InternalUtils.addToMapList(map, "fred", 2)
+
+    then:
+
+    map == ["fred": [1, 2]]
+  }
+
+  def "validateMarkerAnnotation()"() {
+
+    when:
+
+    InternalUtils.validateMarkerAnnotation(Inject)
+
+    then:
+
+    noExceptionThrown()
+
+    when:
+
+    InternalUtils.validateMarkerAnnotations([Inject, NotRetainedRuntime] as Class[])
+
+    then:
+
+    IllegalArgumentException e = thrown()
+
+    e.message == "Marker annotation class org.apache.tapestry5.ioc.internal.util.NotRetainedRuntime is not valid because it is not visible at runtime. Add a @Retention(RetentionPolicy.RUNTIME) to the class."
+  }
+
+  def "close(Closable) for null does nothing"() {
+    when:
+    InternalUtils.close(null)
+
+    then:
+    noExceptionThrown()
+  }
+
+  def "close(Closable) for success case"() {
+    Closeable c = Mock()
+
+    when:
+
+    InternalUtils.close(c)
+
+    then:
+
+    1 * c.close()
+  }
+
+  def "close(Closable) ignores exceptions"() {
+    Closeable c = Mock()
+
+    when:
+
+    InternalUtils.close(c)
+
+    then:
+
+    1 * c.close() >> {
+      throw new IOException("ignored")
+    }
+  }
+
+  def "constructor with Tapestry @Inject annotation"() {
+    when:
+
+    def c = InternalUtils.findAutobuildConstructor(InjectoBean)
+
+    then:
+
+    c.parameterTypes == [String]
+  }
+
+  def "constructor with javax @Inject annotation"() {
+    when:
+
+    def c = InternalUtils.findAutobuildConstructor(JavaxInjectBean)
+
+    then:
+
+    c.parameterTypes == [String]
+  }
+
+  def "too many autobuild constructors"() {
+    when:
+
+    InternalUtils.findAutobuildConstructor(TooManyAutobuildConstructorsBean)
+
+    then:
+
+    IllegalArgumentException e = thrown()
+
+    e.message == "Too many autobuild constructors found: use either @org.apache.tapestry5.ioc.annotations.Inject or @javax.inject.Inject annotation to mark a single constructor for autobuilding."
+  }
+
+  def "validateConstructorForAutobuild(): ensure check that the class itself is public"() {
+    def cons = PrivateInnerClass.constructors[0]
+
+    when:
+
+    InternalUtils.validateConstructorForAutobuild(cons)
+
+    then:
+
+    IllegalArgumentException e = thrown()
+
+    e.message == "Class ${PrivateInnerClass.name} is not a public class and may not be autobuilt."
+  }
+
+  def "validateConstructorForAutobuild(): ensure check that constructor is public"() {
+    def cons = PublicInnerClass.declaredConstructors[0]
+
+    when:
+
+    InternalUtils.validateConstructorForAutobuild(cons)
+
+    then:
+
+    IllegalArgumentException e = thrown()
+
+    e.message == "Constructor protected ${PublicInnerClass.name}() is not public and may not be used for autobuilding an instance of the class. " +
+        "You should make the constructor public, or mark an alternate public constructor with the @Inject annotation."
+  }
+
+  def "@Inject service annotation on a field"() {
+    ObjectLocator ol = Mock()
+    def target = new FieldInjectionViaInjectService()
+    Runnable fred = Mock()
+
+    when:
+
+    InternalUtils.injectIntoFields(target, ol, null, tracker)
+
+    then:
+
+    target.fred.is(fred)
+
+    1 * ol.getService("FredService", Runnable) >> fred
+  }
+
+  def "@javax.annotations.Inject / @Named annotation on field"() {
+    ObjectLocator ol = Mock()
+    def target = new FieldInjectionViaJavaxNamed()
+    Runnable fred = Mock()
+
+    when:
+
+    InternalUtils.injectIntoFields(target, ol, null, tracker)
+
+    then:
+
+    target.fred.is(fred)
+
+    1 * ol.getService("BarneyService", Runnable) >> fred
+  }
+
+  def "@Inject annotation on field"() {
+    ObjectLocator ol = Mock()
+    def target = new FieldInjectionViaInject()
+    SymbolSource source = Mock()
+    InjectionResources resources = Mock()
+
+    when:
+
+    InternalUtils.injectIntoFields(target, ol, resources, tracker)
+
+    then:
+
+    target.symbolSource.is(source)
+
+    1 * resources.findResource(SymbolSource, SymbolSource) >> null
+    1 * ol.getObject(SymbolSource, _) >> { type, ap ->
+      assert ap.getAnnotation(Builtin) != null
+
+      return source
+    }
+  }
+
+  def "@javax.annotation.Inject annotation on field"() {
+    ObjectLocator ol = Mock()
+    def target = new FieldInjectionViaJavaxInject()
+    SymbolSource source = Mock()
+    InjectionResources resources = Mock()
+
+    when:
+
+    InternalUtils.injectIntoFields(target, ol, resources, tracker)
+
+    then:
+
+    target.symbolSource.is(source)
+
+    1 * resources.findResource(SymbolSource, SymbolSource) >> null
+    1 * ol.getObject(SymbolSource, _) >> { type, ap ->
+      assert ap.getAnnotation(Builtin) != null
+
+      return source
+    }
+  }
+
+  def "check handling of exception while injecting into a field"() {
+    ObjectLocator ol = Mock()
+    def target = new FieldInjectionViaInjectService()
+
+    when:
+
+    InternalUtils.injectIntoFields(target, ol, null, tracker)
+
+    then:
+
+    Exception e = thrown()
+
+    1 * ol.getService("FredService", Runnable) >> "NotTheRightType"
+
+    e.message.contains "Unable to set field 'fred' of <FieldInjectionViaInjectService> to NotTheRightType"
+  }
+
+  @Unroll
+  def "keys(Map): #desc"() {
+    expect:
+
+    InternalUtils.keys(map) == (expected as Set)
+
+    where:
+
+    map                                        | expected           | desc
+    null                                       | []                 | "null map"
+    [:]                                        | []                 | "empty map"
+    ["fred": "flintstone", "barney": "rubble"] | ["fred", "barney"] | "non-empty map"
+  }
+
+  @Unroll
+  def "size(Collection): #desc"() {
+    expect:
+
+    InternalUtils.size(coll) == expected
+
+    where:
+
+    coll      | expected | desc
+    null      | 0        | "null collection"
+    []        | 0        | "empty collection"
+    [1, 2, 3] | 3        | "non-empty collection"
+  }
+
+  def "toServiceDef2() delegates most methods to ServiceDef instance"() {
+    ServiceDef delegate = Mock()
+    ServiceBuilderResources resources = Mock()
+    ObjectCreator creator = Mock()
+    def serviceId = "fred"
+    def markers = [] as Set
+
+    ServiceDef2 sd = InternalUtils.toServiceDef2(delegate)
+
+    when:
+
+    def actual = sd.createServiceCreator(resources)
+
+    then:
+
+    actual.is creator
+
+    1 * delegate.createServiceCreator(resources) >> creator
+
+
+    when:
+
+    actual = sd.getServiceId()
+
+    then:
+    actual.is serviceId
+
+    1 * delegate.serviceId >> serviceId
+
+    when:
+
+    actual = sd.markers
+
+    then:
+
+    actual.is markers
+    1 * delegate.markers >> markers
+
+
+    when:
+
+    actual = sd.serviceInterface
+
+    then:
+
+    actual == Runnable
+    1 * delegate.serviceInterface >> Runnable
+
+    when:
+
+    actual = sd.serviceScope
+
+    then:
+
+    actual == ScopeConstants.PERTHREAD
+    1 * delegate.serviceScope >> ScopeConstants.PERTHREAD
+
+    when:
+
+    actual = sd.eagerLoad
+
+    then:
+
+    actual == true
+    1 * delegate.eagerLoad >> true
+
+    expect:
+
+    !sd.preventDecoration
+  }
+
+  def "matchAndSort()"() {
+    def pred = { !it.startsWith(".") } as Predicate
+
+    expect:
+
+    InternalUtils.matchAndSort(["Fred", "Barney", "..", ".hidden", "Wilma"], pred) == ["Barney", "Fred", "Wilma"]
+  }
+
+  def "toMapper(Coercion)"() {
+    def coercion = { it.toUpperCase() } as Coercion
+
+    def flow = F.flow("Mary", "had", "a", "little", "lamb")
+
+    expect:
+
+    flow.map(InternalUtils.toMapper(coercion)).toList() == ["MARY", "HAD", "A", "LITTLE", "LAMB"]
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/01ce2a45/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/util/InternalUtilsTest.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/util/InternalUtilsTest.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/util/InternalUtilsTest.java
deleted file mode 100644
index 68f5241..0000000
--- a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/util/InternalUtilsTest.java
+++ /dev/null
@@ -1,754 +0,0 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
-//
-// Licensed 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.tapestry5.ioc.internal.util;
-
-import org.apache.tapestry5.func.F;
-import org.apache.tapestry5.func.Predicate;
-import org.apache.tapestry5.ioc.*;
-import org.apache.tapestry5.ioc.annotations.Inject;
-import org.apache.tapestry5.ioc.def.ServiceDef;
-import org.apache.tapestry5.ioc.def.ServiceDef2;
-import org.apache.tapestry5.ioc.internal.QuietOperationTracker;
-import org.apache.tapestry5.ioc.services.Builtin;
-import org.apache.tapestry5.ioc.services.Coercion;
-import org.apache.tapestry5.ioc.services.SymbolSource;
-import org.apache.tapestry5.ioc.test.IOCTestCase;
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.util.*;
-
-import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newMap;
-import static org.apache.tapestry5.ioc.internal.util.InternalUtils.toList;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.isA;
-
-public class InternalUtilsTest extends IOCTestCase
-{
-    private final OperationTracker tracker = new QuietOperationTracker();
-
-    private static class PrivateInnerClass
-    {
-        public PrivateInnerClass()
-        {
-        }
-    }
-
-    public static class PublicInnerClass
-    {
-        protected PublicInnerClass()
-        {
-        }
-    }
-
-    @Test
-    public void method_as_string_no_args() throws Exception
-    {
-
-        Method m = Object.class.getMethod("toString");
-
-        assertEquals(InternalUtils.asString(m), "java.lang.Object.toString()");
-    }
-
-    @Test
-    public void method_as_string_with_args() throws Exception
-    {
-        Method m = Collections.class.getMethod("sort", List.class, Comparator.class);
-
-        assertEquals(InternalUtils.asString(m), "java.util.Collections.sort(List, Comparator)");
-    }
-
-    @Test
-    public void method_as_string_primitive_arg() throws Exception
-    {
-        Method m = Object.class.getMethod("wait", long.class);
-
-        assertEquals(InternalUtils.asString(m), "java.lang.Object.wait(long)");
-    }
-
-    @Test
-    public void method_as_string_primitive_array_arg() throws Exception
-    {
-        Method m = Arrays.class.getMethod("sort", int[].class);
-
-        assertEquals(InternalUtils.asString(m), "java.util.Arrays.sort(int[])");
-    }
-
-    @Test
-    public void method_as_string_array_arg() throws Exception
-    {
-        Method m = Arrays.class.getMethod("sort", Object[].class);
-
-        assertEquals(InternalUtils.asString(m), "java.util.Arrays.sort(Object[])");
-    }
-
-    @Test
-    public void array_size_when_null()
-    {
-        Object[] array = null;
-
-        assertEquals(InternalUtils.size(array), 0);
-    }
-
-    @Test
-    public void array_size_when_non_null()
-    {
-        Object[] array =
-                {1, 2, 3};
-
-        assertEquals(InternalUtils.size(array), 3);
-    }
-
-    @Test(dataProvider = "memberNameData")
-    public void strip_member_name(String input, String expected)
-    {
-        assertEquals(InternalUtils.stripMemberName(input), expected);
-    }
-
-    @DataProvider
-    public Object[][] memberNameData()
-    {
-        return new Object[][]
-                {
-                        {"simple", "simple"},
-                        {"_name", "name"},
-                        {"$name", "name"},
-                        {"ruby_style", "ruby_style"},
-                        {"__$ruby_style_", "ruby_style"},
-                        {"$_$__$__$_$___$_$_$_$$name$", "name"},
-                        {"foo_", "foo"},
-                        {"_foo_", "foo"}};
-    }
-
-    @Test
-    public void strip_illegal_member_name()
-    {
-        try
-        {
-            InternalUtils.stripMemberName("!foo");
-            unreachable();
-        } catch (IllegalArgumentException ex)
-        {
-            assertEquals(ex.getMessage(), "Input '!foo' is not a valid Java identifier.");
-        }
-    }
-
-    @Test
-    public void enumeration_to_list()
-    {
-        List<String> input = Arrays.asList("wilma", "fred", "barney");
-        Enumeration e = Collections.enumeration(input);
-
-        List<String> output = toList(e);
-
-        assertEquals(output, Arrays.asList("barney", "fred", "wilma"));
-    }
-
-    @Test
-    public void join_empty_list()
-    {
-        List<String> empty = CollectionFactory.newList();
-
-        assertEquals(InternalUtils.join(empty), "");
-    }
-
-    @Test
-    public void join_single()
-    {
-        List<String> single = Arrays.asList("barney");
-
-        assertEquals(InternalUtils.join(single), "barney");
-    }
-
-    @Test
-    public void join_multiple()
-    {
-        List<String> many = Arrays.asList("fred", "barney", "wilma");
-        assertEquals(InternalUtils.join(many), "fred, barney, wilma");
-    }
-
-    @Test
-    public void join_with_blank()
-    {
-        List<String> many = Arrays.asList("fred", "barney", "", "wilma");
-        assertEquals(InternalUtils.join(many), "fred, barney, (blank), wilma");
-    }
-
-    @Test
-    public void join_sorted()
-    {
-        List<String> unsorted = Arrays.asList("betty", "fred", "barney", "wilma");
-        List<String> copy = CollectionFactory.newList(unsorted);
-
-        assertEquals(InternalUtils.joinSorted(copy), "barney, betty, fred, wilma");
-
-        // Make sure that joinSorted() doesn't change the input list
-
-        assertEquals(copy, unsorted);
-    }
-
-    @Test
-    public void join_sorted_with_blank()
-    {
-        List<String> unsorted = Arrays.asList("betty", "fred", "barney", "", "wilma");
-
-        assertEquals(InternalUtils.joinSorted(unsorted), "(blank), barney, betty, fred, wilma");
-    }
-
-    @Test(dataProvider = "capitalize_inputs")
-    public void capitalize(String input, String expected)
-    {
-        assertEquals(InternalUtils.capitalize(input), expected);
-    }
-
-    @DataProvider(name = "capitalize_inputs")
-    public Object[][] capitalize_inputs()
-    {
-        return new Object[][]
-                {
-                        {"hello", "Hello"},
-                        {"Goodbye", "Goodbye"},
-                        {"", ""},
-                        {"a", "A"},
-                        {"A", "A"}};
-    }
-
-    @Test
-    public void location_of_not_found()
-    {
-        assertNull(InternalUtils.locationOf(null));
-        assertNull(InternalUtils.locationOf("La! La!"));
-    }
-
-    @Test
-    public void location_of_location()
-    {
-        Location l = mockLocation();
-
-        replay();
-
-        assertSame(l, InternalUtils.locationOf(l));
-
-        verify();
-    }
-
-    @Test
-    public void location_of_locatable()
-    {
-        Location l = mockLocation();
-        Locatable locatable = newMock(Locatable.class);
-
-        expect(locatable.getLocation()).andReturn(l);
-
-        replay();
-
-        assertSame(l, InternalUtils.locationOf(locatable));
-
-        verify();
-    }
-
-    @Test
-    public void sorted_keys_from_null_map()
-    {
-        List<String> list = InternalUtils.sortedKeys(null);
-
-        assertTrue(list.isEmpty());
-    }
-
-    @Test
-    public void sorted_keys_from_map()
-    {
-        Map<String, String> map = newMap();
-
-        map.put("fred", "flintstone");
-        map.put("barney", "rubble");
-
-        assertEquals(InternalUtils.sortedKeys(map), Arrays.asList("barney", "fred"));
-    }
-
-    @Test
-    public void get_from_null_map()
-    {
-        assertNull(InternalUtils.get(null, null));
-    }
-
-    @Test
-    public void get_from_map()
-    {
-        Map<String, String> map = newMap();
-
-        map.put("fred", "flintstone");
-
-        assertEquals("flintstone", InternalUtils.get(map, "fred"));
-    }
-
-    @Test
-    public void reverse_iterator()
-    {
-        List<String> list = Arrays.asList("a", "b", "c");
-
-        Iterator<String> i = InternalUtils.reverseIterator(list);
-
-        assertTrue(i.hasNext());
-        assertEquals(i.next(), "c");
-
-        assertTrue(i.hasNext());
-        assertEquals(i.next(), "b");
-
-        assertTrue(i.hasNext());
-        assertEquals(i.next(), "a");
-
-        assertFalse(i.hasNext());
-    }
-
-    @Test
-    public void reverse_iterator_does_not_support_remove()
-    {
-        List<String> list = Arrays.asList("a", "b", "c");
-
-        Iterator<String> i = InternalUtils.reverseIterator(list);
-
-        try
-        {
-            i.remove();
-            unreachable();
-        } catch (UnsupportedOperationException ex)
-        {
-
-        }
-    }
-
-    @Test
-    public void last_term()
-    {
-        String input = "SimpleInput";
-
-        assertSame(InternalUtils.lastTerm(input), input);
-
-        assertEquals(InternalUtils.lastTerm("fie.fie.foe.fum"), "fum");
-    }
-
-    @Test
-    public void add_to_list_map()
-    {
-        Map<String, List<Integer>> map = CollectionFactory.newMap();
-
-        InternalUtils.addToMapList(map, "fred", 1);
-
-        assertEquals(map.get("fred"), Arrays.asList(1));
-
-        InternalUtils.addToMapList(map, "fred", 2);
-
-        assertEquals(map.get("fred"), Arrays.asList(1, 2));
-    }
-
-    // Test the check for runtime annotation. This is all well and good, we actually don't have a proper test
-    // that this code is used (ideally we should have tests for @Marker on a module, on a service impl, and passed
-    // to ServiceBindingOptions.withMarker(), to prove that those are wired for checks.
-
-    @Test
-    public void validate_marker_annotation()
-    {
-        InternalUtils.validateMarkerAnnotation(Inject.class);
-
-        try
-        {
-            InternalUtils.validateMarkerAnnotations(new Class[]
-                    {Inject.class, NotRetainedRuntime.class});
-            unreachable();
-        } catch (IllegalArgumentException ex)
-        {
-            assertEquals(
-                    ex.getMessage(),
-                    "Marker annotation class org.apache.tapestry5.ioc.internal.util.NotRetainedRuntime is not valid because it is not visible at runtime. Add a @Retention(RetentionPolicy.RUNTIME) to the class.");
-        }
-    }
-
-    @Test
-    public void join_sorted_null()
-    {
-        assertEquals(InternalUtils.joinSorted(null), "(none)");
-    }
-
-    @Test
-    public void join_sorted_empty()
-    {
-        assertEquals(InternalUtils.joinSorted(Collections.emptyList()), "(none)");
-    }
-
-    @Test
-    public void close_null_is_noop()
-    {
-        InternalUtils.close(null);
-    }
-
-    @Test
-    public void close_success() throws Exception
-    {
-        Closeable c = newMock(Closeable.class);
-
-        c.close();
-
-        replay();
-
-        InternalUtils.close(c);
-
-        verify();
-    }
-
-    @Test
-    public void close_ignores_exceptions() throws Exception
-    {
-        Closeable c = newMock(Closeable.class);
-
-        c.close();
-        setThrowable(new IOException());
-
-        replay();
-
-        InternalUtils.close(c);
-
-        verify();
-    }
-
-    @Test
-    public void constructor_with_inject_annotation()
-    {
-        Constructor c = InternalUtils.findAutobuildConstructor(InjectoBean.class);
-
-        assertEquals(c.getParameterTypes().length, 1);
-        assertEquals(c.getParameterTypes()[0], String.class);
-    }
-
-    @Test
-    public void constructor_with_javax_inject_annotation()
-    {
-        Constructor c = InternalUtils.findAutobuildConstructor(JavaxInjectBean.class);
-
-        assertEquals(c.getParameterTypes().length, 1);
-        assertEquals(c.getParameterTypes()[0], String.class);
-    }
-
-    @Test
-    public void too_many_autobuild_constructors()
-    {
-        try
-        {
-            InternalUtils.findAutobuildConstructor(TooManyAutobuildConstructorsBean.class);
-        } catch (IllegalArgumentException ex)
-        {
-            assertEquals(
-                    ex.getMessage(),
-                    "Too many autobuilt constructors found. Please use either '@org.apache.tapestry5.ioc.annotations' or '@javax.inject.Inject' annotation to mark a constructor for autobuilding.");
-        }
-    }
-
-    @Test
-    public void validate_constructor_class_not_public()
-    {
-        Class clazz = PrivateInnerClass.class;
-        Constructor cons = clazz.getConstructors()[0];
-
-        try
-        {
-            InternalUtils.validateConstructorForAutobuild(cons);
-            unreachable();
-        } catch (IllegalArgumentException ex)
-        {
-            assertEquals(
-                    ex.getMessage(),
-                    "Class org.apache.tapestry5.ioc.internal.util.InternalUtilsTest$PrivateInnerClass is not a public class and may not be autobuilt.");
-        }
-    }
-
-    @Test
-    public void validate_constructor_check_for_public()
-    {
-        Class clazz = PublicInnerClass.class;
-        Constructor cons = clazz.getDeclaredConstructors()[0];
-
-        try
-        {
-            InternalUtils.validateConstructorForAutobuild(cons);
-            unreachable();
-        } catch (IllegalArgumentException ex)
-        {
-            assertMessageContains(
-                    ex,
-                    "Constructor protected org.apache.tapestry5.ioc.internal.util.InternalUtilsTest$PublicInnerClass() is not public and may not be used for autobuilding an instance of the class.");
-        }
-    }
-
-    @Test
-    public void inject_service_annotation_on_field()
-    {
-        ObjectLocator ol = mockObjectLocator();
-        FieldInjectionViaInjectService target = new FieldInjectionViaInjectService();
-        Runnable fred = mockRunnable();
-
-        train_getService(ol, "FredService", Runnable.class, fred);
-
-        replay();
-
-        InternalUtils.injectIntoFields(target, ol, null, tracker);
-
-        assertSame(target.getFred(), fred);
-
-        verify();
-    }
-
-    @Test
-    public void javax_inject_named_annotation_on_field()
-    {
-        ObjectLocator ol = mockObjectLocator();
-        FieldInjectionViaJavaxNamed target = new FieldInjectionViaJavaxNamed();
-        Runnable fred = mockRunnable();
-
-        train_getService(ol, "BarneyService", Runnable.class, fred);
-
-        replay();
-
-        InternalUtils.injectIntoFields(target, ol, null, tracker);
-
-        assertSame(target.getFred(), fred);
-
-        verify();
-    }
-
-
-    @Test
-    public void javax_inject_annotation_on_field()
-    {
-        ObjectLocator ol = mockObjectLocator();
-        FieldInjectionViaInject target = new FieldInjectionViaInject();
-        final SymbolSource ss = mockSymbolSource();
-        InjectionResources ir = newMock(InjectionResources.class);
-
-        IAnswer answer = new IAnswer()
-        {
-            public Object answer() throws Throwable
-            {
-                Object[] args = EasyMock.getCurrentArguments();
-
-                AnnotationProvider ap = (AnnotationProvider) args[1];
-
-                // Verify that annotations on the field are accessible.
-
-                assertNotNull(ap.getAnnotation(Builtin.class));
-
-                return ss;
-            }
-        };
-
-        expect(ir.findResource(SymbolSource.class, SymbolSource.class)).andReturn(null);
-
-        expect(ol.getObject(eq(SymbolSource.class), isA(AnnotationProvider.class))).andAnswer(answer);
-
-        replay();
-
-        InternalUtils.injectIntoFields(target, ol, ir, tracker);
-
-        assertSame(target.getSymbolSource(), ss);
-
-        verify();
-    }
-
-    @Test
-    public void inject_annotation_on_field()
-    {
-        ObjectLocator ol = mockObjectLocator();
-        FieldInjectionViaInject target = new FieldInjectionViaInject();
-        final SymbolSource ss = mockSymbolSource();
-        InjectionResources ir = newMock(InjectionResources.class);
-
-        IAnswer answer = new IAnswer()
-        {
-            public Object answer() throws Throwable
-            {
-                Object[] args = EasyMock.getCurrentArguments();
-
-                AnnotationProvider ap = (AnnotationProvider) args[1];
-
-                // Verify that annotations on the field are accessible.
-
-                assertNotNull(ap.getAnnotation(Builtin.class));
-
-                return ss;
-            }
-        };
-
-        expect(ir.findResource(SymbolSource.class, SymbolSource.class)).andReturn(null);
-
-        expect(ol.getObject(eq(SymbolSource.class), isA(AnnotationProvider.class))).andAnswer(answer);
-
-        replay();
-
-        InternalUtils.injectIntoFields(target, ol, ir, tracker);
-
-        assertSame(target.getSymbolSource(), ss);
-
-        verify();
-    }
-
-    @Test
-    public void exception_injecting_into_field()
-    {
-        ObjectLocator ol = mockObjectLocator();
-        FieldInjectionViaInjectService target = new FieldInjectionViaInjectService();
-
-        // It's very hard to come up with a value that causes an error when assigned. We have to break
-        // a lot of rules.
-
-        ol.getService("FredService", Runnable.class);
-        EasyMock.expectLastCall().andReturn("NotTheRightType");
-
-        replay();
-
-        try
-        {
-            InternalUtils.injectIntoFields(target, ol, null, tracker);
-
-            unreachable();
-        } catch (Exception ex)
-        {
-            assertMessageContains(ex,
-                    "Unable to set field 'fred' of <FieldInjectionViaInjectService> to NotTheRightType");
-        }
-
-        verify();
-    }
-
-    @Test
-    public void keys_on_null_is_empty()
-    {
-        assertTrue(InternalUtils.keys(null).isEmpty());
-    }
-
-    @Test
-    public void keys_on_actual_map()
-    {
-        Map<String, Integer> map = CollectionFactory.newMap();
-
-        map.put("frobozz", 41);
-        map.put("gnip", 97);
-
-        assertSame(InternalUtils.keys(map), map.keySet());
-    }
-
-    @Test
-    public void collection_size()
-    {
-        Collection c = null;
-
-        assertEquals(InternalUtils.size(c), 0);
-
-        c = Arrays.asList("moe", "larry", "curly");
-
-        assertEquals(InternalUtils.size(c), 3);
-    }
-
-    @Test
-    public void servicedef_to_servicedef2()
-    {
-        final ObjectCreator oc = mockObjectCreator();
-        final String serviceId = "RocketLauncher";
-        final Set<Class> markers = Collections.emptySet();
-        final Class serviceInterface = Runnable.class;
-
-        ServiceDef sd = new ServiceDef()
-        {
-            public ObjectCreator createServiceCreator(ServiceBuilderResources resources)
-            {
-                return oc;
-            }
-
-            public String getServiceId()
-            {
-                return serviceId;
-            }
-
-            public Set<Class> getMarkers()
-            {
-                return markers;
-            }
-
-            public Class getServiceInterface()
-            {
-                return serviceInterface;
-            }
-
-            public String getServiceScope()
-            {
-                return ScopeConstants.PERTHREAD;
-            }
-
-            public boolean isEagerLoad()
-            {
-                return true;
-            }
-        };
-
-        replay();
-
-        ServiceDef2 sd2 = InternalUtils.toServiceDef2(sd);
-
-        assertSame(sd2.createServiceCreator(null), oc);
-        assertSame(sd2.getServiceId(), serviceId);
-        assertSame(sd2.getMarkers(), markers);
-        assertSame(sd2.getServiceInterface(), serviceInterface);
-        assertSame(sd2.getServiceScope(), ScopeConstants.PERTHREAD);
-        assertTrue(sd2.isEagerLoad());
-        assertFalse(sd2.isPreventDecoration());
-
-        verify();
-    }
-
-    @Test
-    public void match_and_sort()
-    {
-        List<String> input = CollectionFactory.newList("Fred", "Barney", "..", ".hidden", "Wilma");
-
-        List<String> output = InternalUtils.matchAndSort(input, new Predicate<String>()
-        {
-            public boolean accept(String object)
-            {
-                return !object.startsWith(".");
-            }
-        });
-
-        assertListsEquals(output, "Barney", "Fred", "Wilma");
-    }
-
-    @Test
-    public void wrap_coercion_as_mapper()
-    {
-        Coercion<String, String> toUpper = new Coercion<String, String>()
-        {
-            public String coerce(String input)
-            {
-                return input.toUpperCase();
-            }
-        };
-
-        assertListsEquals(F.flow("Mary", "had", "a", "little", "lamb").map(InternalUtils.toMapper(toUpper)).toList(),
-                "MARY", "HAD", "A", "LITTLE", "LAMB");
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/01ce2a45/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/util/TooManyAutobuildConstructorsBean.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/util/TooManyAutobuildConstructorsBean.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/util/TooManyAutobuildConstructorsBean.java
index 6bd7a13..cd998ef 100644
--- a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/util/TooManyAutobuildConstructorsBean.java
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/util/TooManyAutobuildConstructorsBean.java
@@ -1,21 +1,7 @@
-// Copyright 2008 The Apache Software Foundation
-//
-// Licensed 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.tapestry5.ioc.internal.util;
 
-import javax.inject.Inject;
 
+import org.apache.tapestry5.ioc.annotations.Inject;
 
 public class TooManyAutobuildConstructorsBean
 {