You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2012/05/16 20:50:31 UTC

[1/44] git commit: Convert TestNG to Spock

Updated Branches:
  refs/heads/master a84ac7bc2 -> 6bd952865


Convert TestNG to Spock


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

Branch: refs/heads/master
Commit: a824b8df6215aee64ad4dc86db1c8153f966a370
Parents: 63ad333
Author: Howard M. Lewis Ship <hl...@gmail.com>
Authored: Tue May 15 10:08:09 2012 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Wed May 16 11:50:15 2012 -0700

----------------------------------------------------------------------
 .../ioc/internal/DefaultModuleDefImpl.java         |   33 +-
 .../apache/tapestry5/ioc/internal/IOCMessages.java |   14 +-
 .../tapestry5/ioc/internal/IOCStrings.properties   |    6 +-
 .../ioc/internal/DefaultModuleDefImplSpec.groovy   |  449 ++++++++++
 .../ioc/internal/ComplexAutobuildModule.java       |    4 +-
 .../ioc/internal/DefaultModuleDefImplTest.java     |  679 ---------------
 6 files changed, 476 insertions(+), 709 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a824b8df/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
index 0bae285..f2f408b 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012 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.
@@ -90,9 +90,12 @@ public class DefaultModuleDefImpl implements ModuleDef2, ServiceDefAccumulator
     }
 
     /**
-     * @param moduleClass  the class that is responsible for building services, etc.
-     * @param logger       based on the class name of the module
-     * @param proxyFactory factory used to create proxy classes at runtime
+     * @param moduleClass
+     *         the class that is responsible for building services, etc.
+     * @param logger
+     *         based on the class name of the module
+     * @param proxyFactory
+     *         factory used to create proxy classes at runtime
      */
     public DefaultModuleDefImpl(Class<?> moduleClass, Logger logger, PlasticProxyFactory proxyFactory)
     {
@@ -294,7 +297,13 @@ public class DefaultModuleDefImpl implements ModuleDef2, ServiceDefAccumulator
         Class returnType = method.getReturnType();
 
         if (returnType.isPrimitive() || returnType.isArray())
-            throw new RuntimeException(IOCMessages.decoratorMethodWrongReturnType(method));
+        {
+            throw new RuntimeException(String.format(
+                    "Method %s is named like a service decorator method, but the return type (%s) is not acceptable (try Object).",
+                    InternalUtils.asString(method),
+                    method.getReturnType().getCanonicalName()));
+        }
+
 
         Set<Class> markers = extractMarkers(method, Decorate.class);
 
@@ -409,7 +418,10 @@ public class DefaultModuleDefImpl implements ModuleDef2, ServiceDefAccumulator
         Class returnType = method.getReturnType();
 
         if (returnType.isPrimitive() || returnType.isArray())
-            throw new RuntimeException(IOCMessages.buildMethodWrongReturnType(method));
+            throw new RuntimeException(
+                    String.format("Method %s is named like a service builder method, but the return type (%s) is not acceptable (try an interface).",
+                            InternalUtils.asString(method),
+                            method.getReturnType().getCanonicalName()));
 
         String scope = extractServiceScope(method);
         boolean eagerLoad = method.isAnnotationPresent(EagerLoad.class);
@@ -513,11 +525,12 @@ public class DefaultModuleDefImpl implements ModuleDef2, ServiceDefAccumulator
     /**
      * See if the build class defined a bind method and invoke it.
      *
-     * @param remainingMethods set of methods as yet unaccounted for
+     * @param remainingMethods
+     *         set of methods as yet unaccounted for
      * @param modulePreventsServiceDecoration
-     *                         true if {@link org.apache.tapestry5.ioc.annotations.PreventServiceDecoration} on
-     *                         module
-     *                         class
+     *         true if {@link org.apache.tapestry5.ioc.annotations.PreventServiceDecoration} on
+     *         module
+     *         class
      */
     private void bind(Set<Method> remainingMethods, boolean modulePreventsServiceDecoration)
     {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a824b8df/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/IOCMessages.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/IOCMessages.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/IOCMessages.java
index 385b489..7584702 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/IOCMessages.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/IOCMessages.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2011 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2011, 2012 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.
@@ -42,18 +42,6 @@ final class IOCMessages
         return MESSAGES.format("build-method-conflict", serviceId, conflict, existing);
     }
 
-    static String buildMethodWrongReturnType(Method method)
-    {
-        return MESSAGES.format("build-method-wrong-return-type", asString(method), method
-                .getReturnType().getCanonicalName());
-    }
-
-    static String decoratorMethodWrongReturnType(Method method)
-    {
-        return MESSAGES.format("decorator-method-wrong-return-type", asString(method), method
-                .getReturnType().getCanonicalName());
-    }
-
     static String serviceWrongInterface(String serviceId, Class actualInterface, Class requestedInterface)
     {
         return MESSAGES.format("service-wrong-interface", serviceId, actualInterface.getName(),

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a824b8df/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties b/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties
index 066e9d5..73fe7e7 100644
--- a/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties
+++ b/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties
@@ -1,4 +1,4 @@
- # Copyright 2006, 2007, 2008, 2009, 2011 The Apache Software Foundation
+ # Copyright 2006, 2007, 2008, 2009, 2011, 2012 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.
@@ -13,10 +13,6 @@
 # limitations under the License.
 
 build-method-conflict=Service %s (defined by %s) conflicts with previously defined service defined by %s.
-build-method-wrong-return-type=Method %s is named like a service builder method, \
- but the return type (%s) is not acceptable (try an interface).
-decorator-method-wrong-return-type=Method %s is named like a service decorator method, \
-  but the return type (%s) is not acceptable (try Object).
 service-wrong-interface=Service '%s' implements interface %s, which is not compatible with the requested type %s.
 instantiate-builder-error=Unable to instantiate class %s as a module: %s
 no-service-matches-type=No service implements the interface %s.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a824b8df/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplSpec.groovy
new file mode 100644
index 0000000..c79ad3a
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplSpec.groovy
@@ -0,0 +1,449 @@
+package org.apache.tapestry5.ioc.internal
+
+import org.apache.tapestry5.internal.plastic.PlasticClassLoader
+import org.apache.tapestry5.internal.plastic.PlasticInternalUtils
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter
+import org.apache.tapestry5.ioc.def.ServiceDef3
+import org.apache.tapestry5.ioc.internal.services.PlasticProxyFactoryImpl
+import org.apache.tapestry5.ioc.services.PlasticProxyFactory
+import org.slf4j.Logger
+import spock.lang.Shared
+import spock.lang.Specification
+import spock.lang.Unroll
+import org.apache.tapestry5.ioc.*
+
+import static org.apache.tapestry5.internal.plastic.asm.Opcodes.*
+
+class DefaultModuleDefImplSpec extends Specification {
+
+  @Shared
+  PlasticProxyFactory proxyFactory = new PlasticProxyFactoryImpl(Thread.currentThread().contextClassLoader, null)
+
+  @Shared
+  OperationTracker tracker = new QuietOperationTracker()
+
+  Logger logger = Mock()
+
+  def "toString() of module lists services in the module"() {
+    when:
+
+    def md = module SimpleModule
+
+    then:
+
+    md.toString() == "ModuleDef[$SimpleModule.name Barney, Fred, Wilma]"
+  }
+
+  def "serviceIds contains all service ids"() {
+    def md = module SimpleModule
+
+    expect:
+
+    md.serviceIds == ["Fred", "Barney", "Wilma"] as Set
+  }
+
+  def "ServiceDef obtainable by service id"() {
+    def md = module SimpleModule
+
+    when:
+
+    def sd = md.getServiceDef "fred"
+
+    then:
+
+    sd.serviceId == "Fred"
+    sd.serviceInterface == FieService
+    sd.toString().contains "${SimpleModule.name}.buildFred()"
+    sd.serviceScope == ScopeConstants.DEFAULT
+    !sd.eagerLoad
+    sd.markers.empty
+
+    when:
+
+    sd = md.getServiceDef("Wilma")
+
+    then:
+
+    sd.eagerLoad
+  }
+
+  def "ModuleDef exposes decorator methods as DecoratorDefs"() {
+    def md = module SimpleModule
+
+    when:
+
+    def decos = md.decoratorDefs
+
+    then:
+
+    decos.size() == 1
+
+    def deco = decos.find()
+
+    deco.decoratorId == "Logging"
+    deco.toString().contains "${SimpleModule.name}.decorateLogging(Class, Object)"
+  }
+
+  def "@ServiceId annotation on service builder method overrides naming convention"() {
+    when:
+
+    def md = module ServiceIdViaAnnotationModule
+
+    then:
+
+    md.getServiceDef("FooService") != null
+  }
+
+  def "@ServiceId on implementation class overrides default id from ServiceBinder.bind() default"() {
+    when:
+
+    def md = module ServiceIdViaAnnotationModule
+
+    then:
+
+    md.getServiceDef("BarneyService") != null
+  }
+
+  def "@Named annotation on service builder method overrides naming convention"() {
+    when:
+
+    def md = module NamedServiceModule
+
+    then:
+
+    md.getServiceDef("BazService") != null
+  }
+
+  def "@Named annotation on service implementation class overrides ServiceBinder.bind() default"() {
+    when:
+
+    def md = module NamedServiceModule
+
+    then:
+
+    md.getServiceDef("QuuxService") != null
+  }
+
+  def "naming convention for a service builder method named build() is derived from the return type"() {
+    when:
+
+    def md = module DefaultServiceIdModule
+
+    then:
+
+    md.getServiceDef("FieService") != null
+  }
+
+  def "conflicting service ids result in an exception"() {
+    when:
+
+    module ServiceIdConflictMethodModule
+
+    then:
+
+    RuntimeException ex = thrown()
+
+    ex.message.contains "Service Fred (defined by ${ServiceIdConflictMethodModule.name}.buildFred()"
+    ex.message.contains "conflicts with previously defined service defined by ${ServiceIdConflictMethodModule.name}.buildFred(Object)"
+  }
+
+  def "a service builder method may not return void"() {
+    when:
+
+    module VoidBuilderMethodModule
+
+    then:
+
+    RuntimeException ex = thrown()
+
+    ex.message.contains "${VoidBuilderMethodModule.name}.buildNull()"
+    ex.message.contains "but the return type (void) is not acceptable"
+  }
+
+  def "a service builder method may not return an array"() {
+    when:
+
+    module BuilderMethodModule
+
+    then:
+
+    RuntimeException ex = thrown()
+
+    ex.message.contains "${BuilderMethodModule.name}.buildStringArray()"
+    ex.message.contains "but the return type (java.lang.String[])"
+  }
+
+  @Unroll
+  def "A decorator method #desc"() {
+    when:
+
+    module moduleClass
+
+    then:
+
+    RuntimeException e = thrown()
+
+    e.message.contains expectedText
+
+    where:
+
+    moduleClass                    | expectedText        | desc
+    PrimitiveDecoratorMethodModule | "decoratePrimitive" | "may not return a primitive type"
+    ArrayDecoratorMethodModule     | "decorateArray"     | "may not return an array"
+  }
+
+  @Unroll
+  def "#desc"() {
+    when:
+
+    def md = module moduleClass
+
+    then:
+
+    def defs = md.contributionDefs
+
+    defs.size() == 1
+
+    def cd = defs.find()
+
+    cd.serviceId == serviceId
+
+    cd.toString().contains "${moduleClass.name}.$methodSignature"
+
+    where:
+
+    moduleClass                | serviceId | methodSignature                           | desc
+    SimpleModule               | "Barney"  | "contributeBarney(Configuration)"         | "contribution without annotation to configuration"
+    OrderedConfigurationModule | "Ordered" | "contributeOrdered(OrderedConfiguration)" | "contribution to ordered configuration"
+    MappedConfigurationModule  | "Mapped"  | "contributeMapped(MappedConfiguration)"   | "contribution to mapped configuration"
+  }
+
+  @Unroll
+  def "service contribution method that #desc throws an exception"() {
+
+    when:
+
+    module moduleClass
+
+    then:
+
+    RuntimeException e = thrown()
+
+    e.message.contains message
+
+    where:
+
+    moduleClass                         | message                                                                                                | desc
+
+    NoUsableContributionParameterModule | "does not contain a parameter of type Configuration, OrderedConfiguration or MappedConfiguration"      | "does not include configuration parameter"
+    TooManyContributionParametersModule | "contains more than one parameter of type Configuration, OrderedConfiguration, or MappedConfiguration" | "includes more than one configuration parameter"
+  }
+
+  def "using defaults for ServiceBinder.bind()"() {
+
+    when:
+
+    def md = module AutobuildModule
+    ServiceDef3 sd = md.getServiceDef "stringholder"
+
+    then:
+
+    sd.serviceInterface == StringHolder
+    sd.serviceId == "StringHolder"
+    sd.serviceScope == ScopeConstants.DEFAULT
+    !sd.isEagerLoad()
+    sd.markers.empty
+    !sd.preventDecoration
+  }
+
+  def "overriding defaults for ServiceBinder.bind()"() {
+
+    when:
+
+    def md = module ComplexAutobuildModule
+    ServiceDef3 sd = md.getServiceDef "sh"
+
+    then:
+
+    sd.serviceInterface == StringHolder
+    sd.serviceId == "SH"
+    sd.serviceScope == "magic"
+    sd.eagerLoad
+    sd.preventDecoration
+  }
+
+  def "implementation class for ServiceBinder.bind() must have a public constructor"() {
+    when:
+
+    module UninstantiableAutobuildServiceModule
+
+    then:
+
+    RuntimeException e = thrown()
+
+    e.message.contains "Class org.apache.tapestry5.ioc.internal.RunnableServiceImpl (implementation of service 'Runnable') does not contain any public constructors."
+  }
+
+  def "the bind() method of a module class must be a static method"() {
+    when:
+
+    module NonStaticBindMethodModule
+
+    then:
+
+    RuntimeException e = thrown()
+
+    e.message.contains "Method org.apache.tapestry5.ioc.internal.NonStaticBindMethodModule.bind(ServiceBinder)"
+    e.message.contains "appears to be a service binder method, but is an instance method, not a static method"
+  }
+
+  def "when autobuilding a service implementation, the constructor with the most parameters is chosen"() {
+    ServiceBuilderResources resources = Mock()
+
+    when:
+
+    def md = module MutlipleAutobuildServiceConstructorsModule
+
+    def sd = md.getServiceDef "stringholder"
+
+    then:
+
+    sd != null
+
+    0 * _
+
+    when:
+
+    def oc = sd.createServiceCreator(resources)
+    def holder = oc.createObject()
+
+    holder.value = "foo"
+
+    then:
+
+    holder instanceof StringHolder
+    holder.value == "FOO"
+
+    _ * resources.serviceId >> "StringHolder"
+    _ * resources.logger >> logger
+    _ * resources.serviceInterface >> StringHolder
+    1 * resources.getService("ToUpperCaseStringHolder", StringHolder) >> new ToUpperCaseStringHolder()
+    _ * resources.tracker >> tracker
+
+    1 * logger.debug(_) >> { args ->
+      assert args[0].contains(
+          "Invoking constructor org.apache.tapestry5.ioc.internal.MultipleConstructorsAutobuildService(StringHolder)")
+    }
+
+    0 * _
+  }
+
+  def "an exception inside a bind() method bubbles up"() {
+    when:
+
+    module ExceptionInBindMethod
+
+    then:
+
+    RuntimeException e = thrown()
+
+    e.message.contains "Error invoking service binder method org.apache.tapestry5.ioc.internal.ExceptionInBindMethod.bind(ServiceBinder)"
+    e.message.contains "at ExceptionInBindMethod.java"
+    e.message.contains "Really, how often is this going to happen?"
+  }
+
+  def "@EagerLoad annotation on service implementation class is reflected in the ServiceDef"() {
+    when:
+
+    def md = module EagerLoadViaAnnotationModule
+    def sd = md.getServiceDef "runnable"
+
+    then:
+
+    sd.eagerLoad
+  }
+
+  private DefaultModuleDefImpl module(moduleClass) {
+    new DefaultModuleDefImpl(moduleClass, logger, proxyFactory)
+  }
+
+  def "marker annotations on the service builder method are available in the ServiceDef"() {
+
+    when:
+
+    def md = module MarkerModule
+    def sd = md.getServiceDef "greeter"
+
+    then:
+
+    sd.markers == [BlueMarker] as Set
+  }
+
+  def "marker annotations specified via ServiceBinder is available in the ServiceDef"() {
+    when:
+
+    def md = module MarkerModule
+    def sd = md.getServiceDef "redgreeter"
+
+    then:
+
+    sd.markers == [RedMarker] as Set
+  }
+
+  def "marker annotation on the implementation class is available in the ServiceDef"() {
+    when:
+
+    def md = module MarkerModule
+    def sd = md.getServiceDef "SecondRedGreeter"
+
+    then:
+
+    sd.markers == [RedMarker] as Set
+  }
+
+  def "marker annotation from ServiceBinder and implementation class are merged"() {
+    when:
+
+    def md = module MarkerModule
+    def sd = md.getServiceDef "SurprisinglyBlueGreeter"
+
+    then:
+
+    sd.markers == [RedMarker, BlueMarker] as Set
+  }
+
+  def "public synthetic methods on module class are ignored"() {
+    def moduleClass = createSyntheticModuleClass()
+
+    when:
+
+    def md = module moduleClass
+
+    then:
+
+    md.serviceIds.size() == 1
+  }
+
+  private createSyntheticModuleClass() {
+
+    def cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES)
+
+    cw.visit(V1_5, ACC_PUBLIC, "EnhancedSyntheticMethodModule", null,
+        PlasticInternalUtils.toInternalName(SyntheticMethodModule.name), null);
+
+    def mv = cw.visitMethod ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, "synth", "()V", null, null
+    mv.visitCode()
+    mv.visitInsn RETURN
+    mv.visitEnd()
+
+    cw.visitEnd()
+
+    def bytecode = cw.toByteArray()
+
+    ClassLoader loader = Thread.currentThread().contextClassLoader
+
+    PlasticClassLoader plasticLoader = new PlasticClassLoader(loader, new NoopClassLoaderDelegate())
+
+    return plasticLoader.defineClassWithBytecode("EnhancedSyntheticMethodModule", bytecode)
+  }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a824b8df/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ComplexAutobuildModule.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ComplexAutobuildModule.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ComplexAutobuildModule.java
index 0302bdb..cc578fa 100644
--- a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ComplexAutobuildModule.java
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ComplexAutobuildModule.java
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2012 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.
@@ -22,6 +22,6 @@ public class ComplexAutobuildModule
 {
     public static void bind(ServiceBinder binder)
     {
-        binder.bind(StringHolder.class, StringHolderImpl.class).eagerLoad().scope("magic").withId("SH");
+        binder.bind(StringHolder.class, StringHolderImpl.class).eagerLoad().scope("magic").withId("SH").preventDecoration();
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a824b8df/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java
deleted file mode 100644
index 0fff1dc..0000000
--- a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java
+++ /dev/null
@@ -1,679 +0,0 @@
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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;
-
-import org.apache.tapestry5.internal.plastic.PlasticClassLoader;
-import org.apache.tapestry5.internal.plastic.PlasticInternalUtils;
-import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.ioc.*;
-import org.apache.tapestry5.ioc.def.ContributionDef;
-import org.apache.tapestry5.ioc.def.DecoratorDef;
-import org.apache.tapestry5.ioc.def.ModuleDef;
-import org.apache.tapestry5.ioc.def.ServiceDef;
-import org.apache.tapestry5.ioc.internal.services.PlasticProxyFactoryImpl;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-import org.apache.tapestry5.ioc.internal.util.InternalUtils;
-import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
-import org.apache.tapestry5.ioc.test.IOCTestCase;
-import org.slf4j.Logger;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import java.lang.reflect.Method;
-import java.util.Set;
-
-import static org.apache.tapestry5.internal.plastic.asm.Opcodes.*;
-import static org.easymock.EasyMock.contains;
-
-public class DefaultModuleDefImplTest extends IOCTestCase
-{
-    private PlasticProxyFactory proxyFactory;
-
-    private final OperationTracker tracker = new QuietOperationTracker();
-
-    @BeforeClass
-    public void setup()
-    {
-        proxyFactory = new PlasticProxyFactoryImpl(Thread.currentThread().getContextClassLoader(), null);
-    }
-
-    @AfterClass
-    public void cleanup()
-    {
-        proxyFactory = null;
-    }
-
-    @Test
-    public void simple_module() throws Exception
-    {
-        String className = SimpleModule.class.getName();
-
-        Logger logger = mockLogger();
-
-        replay();
-
-        // BigDecimal is arbitrary, any class would do.
-
-        ModuleDef md = new DefaultModuleDefImpl(SimpleModule.class, logger, proxyFactory);
-
-        assertEquals(md.toString(), "ModuleDef[" + className + " Barney, Fred, Wilma]");
-
-        Set<String> ids = md.getServiceIds();
-
-        assertEquals(ids.size(), 3);
-        assertTrue(ids.contains("Fred"));
-        assertTrue(ids.contains("Barney"));
-        assertTrue(ids.contains("Wilma"));
-
-        ServiceDef sd = md.getServiceDef("Fred");
-
-        assertEquals(sd.getServiceId(), "Fred");
-
-        assertEquals(sd.getServiceInterface(), FieService.class);
-
-        assertTrue(sd.toString().contains(className + ".buildFred()"));
-        assertEquals(sd.getServiceScope(), ScopeConstants.DEFAULT);
-        assertEquals(sd.isEagerLoad(), false);
-        assertTrue(sd.getMarkers().isEmpty());
-
-        sd = md.getServiceDef("Wilma");
-        assertEquals(sd.isEagerLoad(), true);
-
-        // Now the decorator method.
-
-        Set<DecoratorDef> defs = md.getDecoratorDefs();
-
-        assertEquals(defs.size(), 1);
-
-        DecoratorDef dd = defs.iterator().next();
-
-        assertEquals(dd.getDecoratorId(), "Logging");
-        assertTrue(dd.toString().contains(className + ".decorateLogging(Class, Object)"));
-
-        verify();
-    }
-
-    @Test
-    public void default_service_id_from_method_annotation()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef def = new DefaultModuleDefImpl(ServiceIdViaAnnotationModule.class, logger, null);
-
-        assertEquals(def.getServiceIds().size(), 2);
-
-        ServiceDef sd = def.getServiceDef("FooService");
-
-        assertEquals(sd.getServiceId(), "FooService");
-
-        verify();
-    }
-
-    @Test
-    public void default_service_id_from_annotation()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef def = new DefaultModuleDefImpl(ServiceIdViaAnnotationModule.class, logger, null);
-
-        assertEquals(def.getServiceIds().size(), 2);
-
-        ServiceDef sd = def.getServiceDef("BarneyService");
-
-        assertEquals(sd.getServiceId(), "BarneyService");
-
-        verify();
-    }
-
-    @Test
-    public void default_service_id_from_method_named_annotation()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef def = new DefaultModuleDefImpl(NamedServiceModule.class, logger, null);
-
-        assertEquals(def.getServiceIds().size(), 2);
-
-        ServiceDef sd = def.getServiceDef("BazService");
-
-        assertEquals(sd.getServiceId(), "BazService");
-
-        verify();
-    }
-
-    @Test
-    public void default_service_id_from_named_annotation()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef def = new DefaultModuleDefImpl(NamedServiceModule.class, logger, null);
-
-        assertEquals(def.getServiceIds().size(), 2);
-
-        ServiceDef sd = def.getServiceDef("QuuxService");
-
-        assertEquals(sd.getServiceId(), "QuuxService");
-
-        verify();
-    }
-
-    @Test
-    public void default_service_id_from_return_type()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef def = new DefaultModuleDefImpl(DefaultServiceIdModule.class, logger, null);
-
-        assertEquals(def.getServiceIds().size(), 1);
-
-        ServiceDef sd = def.getServiceDef("FieService");
-
-        assertEquals(sd.getServiceId(), "FieService");
-
-        verify();
-    }
-
-    /**
-     * Two different methods both claim to build the same service.
-     */
-    @Test
-    public void service_id_conflict() throws Exception
-    {
-        Method conflictMethod = ServiceIdConflictMethodModule.class.getMethod("buildFred");
-        String conflictMethodString = InternalUtils.asString(conflictMethod, proxyFactory);
-
-        String expectedMethod = InternalUtils.asString(
-                ServiceIdConflictMethodModule.class.getMethod("buildFred", Object.class), proxyFactory);
-
-        Logger logger = mockLogger();
-
-        replay();
-
-        // BigDecimal is arbitrary, any class would do.
-
-        try
-        {
-            new DefaultModuleDefImpl(ServiceIdConflictMethodModule.class, logger, proxyFactory);
-
-            unreachable();
-        } catch (RuntimeException ex)
-        {
-            assertMessageContains(
-                    ex,
-                    "Service Fred (defined by org.apache.tapestry5.ioc.internal.ServiceIdConflictMethodModule.buildFred()",
-                    "conflicts with previously defined service defined by org.apache.tapestry5.ioc.internal.ServiceIdConflictMethodModule.buildFred(Object)");
-        }
-
-        verify();
-    }
-
-    @Test
-    public void builder_method_returns_void() throws Exception
-    {
-        Method m = VoidBuilderMethodModule.class.getMethod("buildNull");
-
-        Logger logger = mockLogger();
-
-        replay();
-
-        try
-        {
-            new DefaultModuleDefImpl(VoidBuilderMethodModule.class, logger, null);
-            unreachable();
-        } catch (RuntimeException ex)
-        {
-            assertEquals(ex.getMessage(), IOCMessages.buildMethodWrongReturnType(m));
-        }
-
-        verify();
-    }
-
-    @Test
-    public void builder_method_returns_array() throws Exception
-    {
-        Method m = BuilderMethodModule.class.getMethod("buildStringArray");
-
-        Logger logger = mockLogger();
-
-        replay();
-
-        try
-        {
-            new DefaultModuleDefImpl(BuilderMethodModule.class, logger, null);
-            unreachable();
-        } catch (RuntimeException ex)
-        {
-            assertEquals(ex.getMessage(), IOCMessages.buildMethodWrongReturnType(m));
-        }
-
-        verify();
-    }
-
-    @Test
-    public void decorator_method_returns_void() throws Exception
-    {
-        invalidDecoratorMethod(VoidDecoratorMethodModule.class, "decorateVoid");
-    }
-
-    private void invalidDecoratorMethod(Class moduleClass, String methodName) throws NoSuchMethodException
-    {
-        Method m = moduleClass.getMethod(methodName, Object.class);
-
-        Logger logger = mockLogger();
-
-        replay();
-
-        try
-        {
-            new DefaultModuleDefImpl(moduleClass, logger, null);
-            unreachable();
-        } catch (RuntimeException ex)
-        {
-            assertEquals(ex.getMessage(), IOCMessages.decoratorMethodWrongReturnType(m));
-        }
-
-        verify();
-    }
-
-    @Test
-    public void decorator_method_returns_primitive() throws Exception
-    {
-        invalidDecoratorMethod(PrimitiveDecoratorMethodModule.class, "decoratePrimitive");
-    }
-
-    @Test
-    public void decorator_method_returns_array() throws Exception
-    {
-        invalidDecoratorMethod(ArrayDecoratorMethodModule.class, "decorateArray");
-    }
-
-    @Test
-    public void contribution_without_annotation()
-    {
-        attemptConfigurationMethod(SimpleModule.class, "Barney", "contributeBarney(Configuration)");
-    }
-
-    @Test
-    public void ordered_contribution_method()
-    {
-        attemptConfigurationMethod(OrderedConfigurationModule.class, "Ordered",
-                "contributeOrdered(OrderedConfiguration)");
-    }
-
-    @Test
-    public void mapped_contribution_method()
-    {
-        attemptConfigurationMethod(MappedConfigurationModule.class, "Mapped", "contributeMapped(MappedConfiguration)");
-    }
-
-    private void attemptConfigurationMethod(Class moduleClass, String expectedServiceId, String expectedMethodSignature)
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef md = new DefaultModuleDefImpl(moduleClass, logger, proxyFactory);
-
-        Set<ContributionDef> defs = md.getContributionDefs();
-
-        assertEquals(defs.size(), 1);
-
-        ContributionDef cd = defs.iterator().next();
-
-        // The target service id is derived from the method name
-
-        assertEquals(cd.getServiceId(), expectedServiceId);
-
-        // Can't be exact, because the source file & line number are probably attached (and those
-        // can change)
-
-        assertTrue(cd.toString().contains(moduleClass.getName() + "." + expectedMethodSignature));
-
-        verify();
-    }
-
-    @Test
-    public void contribution_with_too_many_parameters() throws Exception
-    {
-        Class moduleClass = TooManyContributionParametersModule.class;
-        Method m = findMethod(moduleClass, "contributeTooMany");
-
-        Logger logger = mockLogger();
-
-        replay();
-
-        try
-        {
-            new DefaultModuleDefImpl(moduleClass, logger, null);
-            unreachable();
-        } catch (RuntimeException ex)
-        {
-            assertEquals(
-                    ex.getMessage(),
-                    "Service contribution method org.apache.tapestry5.ioc.internal.TooManyContributionParametersModule.contributeTooMany(Configuration, OrderedConfiguration) contains more than one parameter of type Configuration, OrderedConfiguration, or MappedConfiguration. Exactly one such parameter is required for a service contribution method.");
-        }
-
-        verify();
-    }
-
-    @Test
-    public void contribution_with_no_contribution_parameter() throws Exception
-    {
-        Class moduleClass = NoUsableContributionParameterModule.class;
-        Method m = findMethod(moduleClass, "contributeNoParameter");
-
-        Logger logger = mockLogger();
-
-        replay();
-
-        try
-        {
-            new DefaultModuleDefImpl(moduleClass, logger, null);
-            unreachable();
-        } catch (RuntimeException ex)
-        {
-            assertEquals(
-                    ex.getMessage(),
-                    "Service contribution method org.apache.tapestry5.ioc.internal.NoUsableContributionParameterModule.contributeNoParameter(UpcaseService) does not contain a parameter of type Configuration, OrderedConfiguration or MappedConfiguration. This parameter is how the method make contributions into the service's configuration.");
-        }
-
-        verify();
-    }
-
-    @Test
-    public void simple_binder_method()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef md = new DefaultModuleDefImpl(AutobuildModule.class, logger, null);
-
-        ServiceDef sd = md.getServiceDef("StringHolder");
-
-        assertEquals(sd.getServiceInterface(), StringHolder.class);
-        assertEquals(sd.getServiceId(), "StringHolder");
-        assertEquals(sd.getServiceScope(), ScopeConstants.DEFAULT);
-        assertFalse(sd.isEagerLoad());
-
-        verify();
-    }
-
-    @Test
-    public void bind_service_with_all_options()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef md = new DefaultModuleDefImpl(ComplexAutobuildModule.class, logger, null);
-
-        ServiceDef sd = md.getServiceDef("SH");
-
-        assertEquals(sd.getServiceInterface(), StringHolder.class);
-        assertEquals(sd.getServiceId(), "SH");
-        assertEquals(sd.getServiceScope(), "magic");
-        assertTrue(sd.isEagerLoad());
-
-        verify();
-    }
-
-    @Test
-    public void attempt_to_bind_a_service_with_no_public_constructor()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        try
-        {
-            new DefaultModuleDefImpl(UninstantiableAutobuildServiceModule.class, logger, null);
-            unreachable();
-        } catch (RuntimeException ex)
-        {
-            assertMessageContains(
-                    ex,
-                    "Class org.apache.tapestry5.ioc.internal.RunnableServiceImpl (implementation of service \'Runnable\') does not contain any public constructors.");
-        }
-
-        verify();
-    }
-
-    @Test
-    public void instance_method_bind_is_error()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        try
-        {
-            new DefaultModuleDefImpl(NonStaticBindMethodModule.class, logger, proxyFactory);
-            unreachable();
-        } catch (RuntimeException ex)
-        {
-            assertMessageContains(ex,
-                    "Method org.apache.tapestry5.ioc.internal.NonStaticBindMethodModule.bind(ServiceBinder)",
-                    "appears to be a service binder method, but is an instance method, not a static method.");
-        }
-
-        verify();
-    }
-
-    @Test
-    public void multiple_constructors_on_autobuild_service_implementation()
-    {
-        Logger logger = mockLogger();
-        ServiceBuilderResources resources = mockServiceBuilderResources();
-
-        train_getTracker(resources, tracker);
-
-        // The point is, we're choosing the constructor with the largest number of parameters.
-
-        logger.debug(contains("org.apache.tapestry5.ioc.internal.MultipleConstructorsAutobuildService(StringHolder)"));
-
-        train_getServiceId(resources, "StringHolder");
-        train_getLogger(resources, logger);
-        train_getServiceInterface(resources, StringHolder.class);
-        train_getService(resources, "ToUpperCaseStringHolder", StringHolder.class, new ToUpperCaseStringHolder());
-
-        replay();
-
-        ModuleDef def = new DefaultModuleDefImpl(MutlipleAutobuildServiceConstructorsModule.class, logger, proxyFactory);
-
-        ServiceDef sd = def.getServiceDef("StringHolder");
-
-        assertNotNull(sd);
-
-        ObjectCreator oc = sd.createServiceCreator(resources);
-
-        StringHolder holder = (StringHolder) oc.createObject();
-
-        holder.setValue("foo");
-        assertEquals(holder.getValue(), "FOO");
-
-        verify();
-    }
-
-    @Test
-    public void exception_from_inside_bind_method()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        try
-        {
-            new DefaultModuleDefImpl(ExceptionInBindMethod.class, logger, proxyFactory);
-            unreachable();
-        } catch (RuntimeException ex)
-        {
-            assertTrue(ex.getMessage().matches(
-                    "Error invoking service binder method org.apache.tapestry5.ioc.internal.ExceptionInBindMethod.bind\\(ServiceBinder\\) "
-                            + "\\(at ExceptionInBindMethod.java:\\d+\\): Really, how often is this going to happen\\?"));
-        }
-
-        verify();
-    }
-
-    @Test
-    public void autoload_service_is_eager_load_via_annotation()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef md = new DefaultModuleDefImpl(EagerLoadViaAnnotationModule.class, logger, null);
-
-        ServiceDef sd = md.getServiceDef("Runnable");
-
-        assertTrue(sd.isEagerLoad());
-
-        verify();
-    }
-
-    @Test
-    public void service_builder_method_has_marker_annotation()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef md = new DefaultModuleDefImpl(MarkerModule.class, logger, null);
-
-        ServiceDef sd = md.getServiceDef("Greeter");
-
-        assertListsEquals(CollectionFactory.newList(sd.getMarkers()), BlueMarker.class);
-
-        verify();
-    }
-
-    @Test
-    public void bound_service_has_marker_annotation()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef md = new DefaultModuleDefImpl(MarkerModule.class, logger, null);
-
-        ServiceDef sd = md.getServiceDef("RedGreeter");
-
-        assertListsEquals(CollectionFactory.newList(sd.getMarkers()), RedMarker.class);
-
-        verify();
-    }
-
-    @Test
-    public void bound_service_explicit_marker()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef md = new DefaultModuleDefImpl(MarkerModule.class, logger, null);
-
-        ServiceDef sd = md.getServiceDef("SecondRedGreeter");
-
-        assertListsEquals(CollectionFactory.newList(sd.getMarkers()), RedMarker.class);
-
-        verify();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void explicit_marker_overrides_marker_annotation()
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef md = new DefaultModuleDefImpl(MarkerModule.class, logger, null);
-
-        ServiceDef sd = md.getServiceDef("SurprisinglyBlueGreeter");
-
-        // BlueMarker from ServiceBindingOptions, RedMarker from @Marker on class
-
-        Set<Class> markers = sd.getMarkers();
-
-        assertTrue(markers.contains(RedMarker.class));
-        assertTrue(markers.contains(BlueMarker.class));
-        assertEquals(markers.size(), 2);
-
-        verify();
-    }
-
-    /**
-     * TAP5-839
-     */
-    @Test
-    public void public_synthetic_methods_are_ignored() throws NoSuchMethodException
-    {
-        Class moduleClass = createSyntheticMethodModuleClass();
-
-        Logger logger = mockLogger();
-
-        replay();
-
-        ModuleDef md = new DefaultModuleDefImpl(moduleClass, logger, null);
-
-        // reality check that a service was found
-
-        assertEquals(md.getServiceIds().size(), 1);
-
-        verify();
-    }
-
-    private Class createSyntheticMethodModuleClass() throws NoSuchMethodException
-    {
-
-        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
-
-        cw.visit(V1_5, ACC_PUBLIC, "EnhancedSyntheticMethodModule", null,
-                PlasticInternalUtils.toInternalName(SyntheticMethodModule.class.getName()), null);
-
-        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, "synth", "()V", null, null);
-        mv.visitCode();
-        mv.visitInsn(RETURN);
-        mv.visitEnd();
-
-        cw.visitEnd();
-
-        byte[] bytecode = cw.toByteArray();
-
-        ClassLoader loader = Thread.currentThread().getContextClassLoader();
-
-        PlasticClassLoader plasticLoader = new PlasticClassLoader(loader, new NoopClassLoaderDelegate());
-
-        return plasticLoader.defineClassWithBytecode("EnhancedSyntheticMethodModule", bytecode);
-    }
-
-    // TODO: We're short on tests that ensure that marker annotation are additive (i.e., module
-    // marker annotation are
-    // merged into the set specific to the service).
-
-}