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

[20/44] git commit: Fix incorrect package name

Fix incorrect package name


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

Branch: refs/heads/master
Commit: 6329fbf72bedf54b6d73da8b30ad8f0262bbcb0b
Parents: 2343afb
Author: Howard M. Lewis Ship <hl...@gmail.com>
Authored: Wed May 2 08:19:08 2012 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Wed May 16 11:50:13 2012 -0700

----------------------------------------------------------------------
 .../ioc/AbstractRegistrySpecification.groovy       |   28 -
 .../ioc/AbstractSharedRegistrySpecification.groovy |   36 --
 .../apache/tapestry/ioc/BaseLocatableSpec.groovy   |   35 --
 .../org/apache/tapestry/ioc/EagerLoadSpec.groovy   |   24 -
 .../ioc/OrderedConstraintBuilderSpec.groovy        |   31 --
 .../apache/tapestry/ioc/RegistryBuilderSpec.groovy |   99 ----
 .../org/apache/tapestry/ioc/ReloadSpec.groovy      |  403 ---------------
 .../ioc/services/PeriodicExecutorSpec.groovy       |   30 --
 .../services/SystemEnvSymbolProviderSpec.groovy    |   21 -
 .../ioc/AbstractRegistrySpecification.groovy       |   26 +
 .../ioc/AbstractSharedRegistrySpecification.groovy |   34 ++
 .../apache/tapestry5/ioc/BaseLocatableSpec.groovy  |   32 ++
 .../org/apache/tapestry5/ioc/EagerLoadSpec.groovy  |   21 +
 .../ioc/OrderedConstraintBuilderSpec.groovy        |   30 ++
 .../tapestry5/ioc/RegistryBuilderSpec.groovy       |   98 ++++
 .../org/apache/tapestry5/ioc/ReloadSpec.groovy     |  401 ++++++++++++++
 .../AspectInterceptorBuilderImplSpec.groovy        |    2 +-
 .../internal/services/ChainBuilderImplSpec.groovy  |    2 +-
 .../DefaultImplementationBuilderImplSpec.groovy    |    2 +-
 .../services/ExceptionAnalyzerImplSpec.groovy      |    2 +-
 .../ioc/services/PeriodicExecutorSpec.groovy       |   30 ++
 .../services/SystemEnvSymbolProviderSpec.groovy    |   20 +
 22 files changed, 696 insertions(+), 711 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/AbstractRegistrySpecification.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/AbstractRegistrySpecification.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/AbstractRegistrySpecification.groovy
deleted file mode 100644
index 41f328b..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/AbstractRegistrySpecification.groovy
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.apache.tapestry.ioc
-
-import org.apache.tapestry5.ioc.Registry
-import org.apache.tapestry5.ioc.RegistryBuilder
-import spock.lang.AutoCleanup
-import spock.lang.Specification
-
-/**
- * Base class for Spock specifications that use a new {@link Registry} for each feature method.
- */
-abstract class AbstractRegistrySpecification extends Specification {
-
-    @AutoCleanup("shutdown")
-    protected Registry registry;
-
-    protected final void buildRegistry(Class... moduleClasses) {
-
-        registry =
-            new RegistryBuilder().add(moduleClasses).build()
-    }
-
-    /** Any unrecognized methods are evaluated against the registry. */
-    def methodMissing(String name, args) {
-        registry."$name"(* args)
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/AbstractSharedRegistrySpecification.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/AbstractSharedRegistrySpecification.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/AbstractSharedRegistrySpecification.groovy
deleted file mode 100644
index 348d84e..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/AbstractSharedRegistrySpecification.groovy
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.apache.tapestry.ioc
-
-import org.apache.tapestry5.ioc.IOCUtilities
-import org.apache.tapestry5.ioc.Registry
-import spock.lang.Specification
-
-/**
- * Uses a static, shared instance of the {@link org.apache.tapestry5.ioc.Registry}.
- * All specifications that extend from this class will share
- * a single instance of the Registry; The Registry is created by whatever specification is created first.
- * Missing method invocations are forwarded to the registry instance. */
-abstract class AbstractSharedRegistrySpecification extends Specification {
-
-  static Registry registry
-
-  /** Any unrecognized methods are evaluated against the shared Registry instance. */
-  def methodMissing(String name, args) {
-    registry."$name"(* args)
-  }
-
-  /** Creates the Registry if it does not already exist. */
-  def setupSpec() {
-    if (registry == null) {
-      registry = IOCUtilities.buildDefaultRegistry()
-    }
-  }
-
-  /** Invokes {@link Registry#cleanupThread()}. */
-  def cleanupSpec() {
-    registry.cleanupThread();
-  }
-
-  // TODO: the Registry is never shutdown, since there's no notification
-  // that all tests are completing.
-
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/BaseLocatableSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/BaseLocatableSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/BaseLocatableSpec.groovy
deleted file mode 100644
index 21e60ab..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/BaseLocatableSpec.groovy
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.apache.tapestry.ioc
-
-import org.apache.tapestry5.ioc.BaseLocatable
-import org.apache.tapestry5.ioc.Locatable
-import org.apache.tapestry5.ioc.Location
-import spock.lang.Specification
-
-class LocatableFixture extends BaseLocatable {
-    LocatableFixture(Location location) {
-        super(location)
-    }
-}
-
-class BaseLocatableSpec extends Specification {
-
-    def "location property is readable"() {
-        Location location = Mock()
-
-        Locatable locatable = new LocatableFixture(location)
-
-        expect:
-
-        locatable.location.is location
-    }
-
-    def "location may be null"() {
-        Locatable locatable = new LocatableFixture(null);
-
-
-        expect:
-
-        locatable.location == null
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/EagerLoadSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/EagerLoadSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/EagerLoadSpec.groovy
deleted file mode 100644
index cd8338f..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/EagerLoadSpec.groovy
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.apache.tapestry.ioc
-
-import org.apache.tapestry5.ioc.EagerProxyReloadModule
-
-
-class EagerLoadSpec extends AbstractRegistrySpecification {
-
-    def "proxied service does eager load"()
-    {
-        expect:
-
-        EagerProxyReloadModule.eagerLoadServiceDidLoad == false
-
-        when:
-
-        buildRegistry EagerProxyReloadModule
-
-        performRegistryStartup()
-
-        then:
-
-        EagerProxyReloadModule.eagerLoadServiceDidLoad == true
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/OrderedConstraintBuilderSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/OrderedConstraintBuilderSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/OrderedConstraintBuilderSpec.groovy
deleted file mode 100644
index 224cd0b..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/OrderedConstraintBuilderSpec.groovy
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.apache.tapestry.ioc
-
-import org.apache.tapestry5.ioc.OrderConstraintBuilder
-import spock.lang.Specification
-
-class OrderedConstraintBuilderSpec extends Specification {
-
-    /** Any unrecognized methods are evaluated against {@link OrderConstraintBuilder}. */
-    def methodMissing(String name, args) {
-        OrderConstraintBuilder."$name"(* args)
-    }
-
-    def "constraint ordering"() {
-        expect:
-
-        constraint.build() == values
-
-        where:
-
-        constraint || values
-
-        after("A") || ["after:A"]
-        afterAll() || ["after:*"]
-        before("B") || ["before:B"]
-        beforeAll() || ["before:*"]
-
-        before("A").after("B") || ["before:A", "after:B"]
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/RegistryBuilderSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/RegistryBuilderSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/RegistryBuilderSpec.groovy
deleted file mode 100644
index 2b3ff7c..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/RegistryBuilderSpec.groovy
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.apache.tapestry.ioc
-
-import org.apache.tapestry5.ioc.def.ModuleDef
-import org.apache.tapestry5.ioc.internal.DefaultModuleDefImpl
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-import spock.lang.Specification
-import org.apache.tapestry5.ioc.*
-
-class RegistryBuilderSpec extends Specification {
-
-    def "@SubModule annotation is honored"() {
-        when:
-
-        // Borrowed from IntegrationTest, this will only work if both FredModule and BarneyModule
-        // are loaded.
-
-        Registry r = new RegistryBuilder().add(MasterModule).build()
-
-        def service = r.getService("UnorderedNames", NameListHolder)
-
-        then:
-
-        service.names == ["Beta", "Gamma", "UnorderedNames"]
-
-        cleanup:
-
-        r.shutdown()
-    }
-
-    def "adding modules by name, in comma seperated list, as from a manifest"() {
-        when:
-
-        RegistryBuilder builder = new RegistryBuilder()
-
-        IOCUtilities.addModulesInList builder,
-                "${FredModule.class.name}, ${BarneyModule.class.name}, ${RegistryBuilderTestModule.class.name}"
-
-        Registry registry = builder.build()
-
-        Square service = registry.getService(Square)
-
-        then:
-
-        service.square(4) == 16
-
-        service.toString() == "<Proxy for Square(${Square.class.name})>"
-
-        cleanup:
-
-        registry.shutdown()
-    }
-
-    def "exercise RegistryBuilder.buildAndStartupRegistry()"() {
-        when:
-
-        Registry r = RegistryBuilder.buildAndStartupRegistry(MasterModule);
-
-        NameListHolder service = r.getService("UnorderedNames", NameListHolder);
-
-        then:
-
-        service.names == ["Beta", "Gamma", "UnorderedNames"]
-
-        cleanup:
-
-        r.shutdown();
-    }
-
-    def "use explicit ModuleDef with buildAndStartupRegistry()"() {
-        when:
-
-        Logger logger = LoggerFactory.getLogger(getClass());
-
-        ModuleDef module = new DefaultModuleDefImpl(ServiceBuilderModule,
-                logger, null);
-
-        Registry r = RegistryBuilder.buildAndStartupRegistry(module, MasterModule);
-
-        NameListHolder nameListHolder = r.getService("UnorderedNames", NameListHolder);
-
-        then:
-
-        nameListHolder.names == ["Beta", "Gamma", "UnorderedNames"]
-
-        when:
-
-        Greeter greeter = r.getService("Greeter", Greeter)
-
-        then:
-
-        greeter.greeting == "Greetings from service Greeter."
-
-        cleanup:
-
-        r.shutdown();
-
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/ReloadSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/ReloadSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/ReloadSpec.groovy
deleted file mode 100644
index a9ca812..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/ReloadSpec.groovy
+++ /dev/null
@@ -1,403 +0,0 @@
-package org.apache.tapestry.ioc
-
-import org.apache.tapestry5.internal.plastic.PlasticInternalUtils
-import org.apache.tapestry5.internal.plastic.asm.ClassWriter
-import org.apache.tapestry5.ioc.Registry
-import org.apache.tapestry5.ioc.RegistryBuilder
-import org.apache.tapestry5.services.UpdateListenerHub
-import spock.lang.AutoCleanup
-import spock.lang.Specification
-import com.example.*
-
-import static org.apache.tapestry5.internal.plastic.asm.Opcodes.*
-
-class ReloadSpec extends Specification {
-
-    private static final String PACKAGE = "com.example";
-
-    private static final String CLASS = PACKAGE + ".ReloadableServiceImpl";
-
-    private static final String BASE_CLASS = PACKAGE + ".BaseReloadableServiceImpl";
-
-
-    @AutoCleanup("shutdown")
-    Registry registry
-
-    @AutoCleanup("deleteDir")
-    File classesDir
-
-    ClassLoader classLoader
-
-    File classFile;
-
-    def createRegistry() {
-        registry = new RegistryBuilder(classLoader).add(ReloadModule).build()
-    }
-
-    /** Any unrecognized methods are evaluated against the registry. */
-    def methodMissing(String name, args) {
-        registry."$name"(* args)
-    }
-
-
-    def setup() {
-        def uid = UUID.randomUUID().toString()
-
-        classesDir = new File(System.getProperty("java.io.tmpdir"), uid)
-
-        def classesURL = new URL("file:" + classesDir.getCanonicalPath() + "/")
-
-        classLoader = new URLClassLoader([classesURL] as URL[],
-                Thread.currentThread().contextClassLoader)
-
-        classFile = new File(classesDir, PlasticInternalUtils.toClassPath(CLASS))
-    }
-
-    def createImplementationClass(String status) {
-        createImplementationClass CLASS, status
-    }
-
-    def createImplementationClass(String className, String status) {
-
-        String internalName = PlasticInternalUtils.toInternalName className
-
-        createClassWriter(internalName, "java/lang/Object", ACC_PUBLIC).with {
-
-            // Add default constructor
-
-            visitMethod(ACC_PUBLIC, "<init>", "()V", null, null).with {
-                visitCode()
-                visitVarInsn ALOAD, 0
-                visitMethodInsn INVOKESPECIAL, "java/lang/Object", "<init>", "()V"
-                visitInsn RETURN
-                visitMaxs 1, 1
-                visitEnd()
-            }
-
-
-            visitMethod(ACC_PUBLIC, "getStatus", "()Ljava/lang/String;", null, null).with {
-                visitCode()
-                visitLdcInsn status
-                visitInsn ARETURN
-                visitMaxs 1, 1
-                visitEnd()
-            }
-
-            visitEnd()
-
-            writeBytecode it, internalName
-        }
-
-    }
-
-    def createClassWriter(String internalName, String baseClassInternalName, int classModifiers) {
-        ClassWriter cw = new ClassWriter(0);
-
-        cw.visit V1_5, classModifiers, internalName, null,
-                baseClassInternalName, [
-                        PlasticInternalUtils.toInternalName(ReloadableService.name)
-                ] as String[]
-
-
-        return cw
-    }
-
-
-    def writeBytecode(ClassWriter cw, String internalName) {
-        byte[] bytecode = cw.toByteArray();
-
-        writeBytecode(bytecode, pathForInternalName(internalName))
-    }
-
-    def writeBytecode(byte[] bytecode, String path) {
-        File file = new File(path)
-
-        file.parentFile.mkdirs()
-
-        file.withOutputStream { it.write bytecode }
-    }
-
-
-    def pathForInternalName(String internalName) {
-        return String.format("%s/%s.class",
-                classesDir.getAbsolutePath(),
-                internalName)
-    }
-
-    def update() {
-        getService(UpdateListenerHub).fireCheckForUpdates()
-    }
-
-    def "reload a service implementation"() {
-
-        when:
-
-        createImplementationClass "initial"
-
-        createRegistry()
-
-        ReloadableService reloadable = getService(ReloadableService);
-
-        update()
-
-        then:
-
-        reloadable.status == "initial"
-
-        when:
-
-        update()
-
-        touch classFile
-
-        createImplementationClass "updated"
-
-        then:
-
-        // Changes do not take effect until after update check
-
-        reloadable.status == "initial"
-
-        when:
-
-        update()
-
-        then:
-
-        reloadable.status == "updated"
-    }
-
-    def "reload a base class"() {
-
-        setup:
-
-        def baseClassInternalName = PlasticInternalUtils.toInternalName BASE_CLASS
-        def internalName = PlasticInternalUtils.toInternalName CLASS
-
-        createImplementationClass BASE_CLASS, "initial from base"
-
-        createClassWriter(internalName, baseClassInternalName, ACC_PUBLIC).with {
-
-            visitMethod(ACC_PUBLIC, "<init>", "()V", null, null).with {
-                visitCode()
-                visitVarInsn ALOAD, 0
-                visitMethodInsn INVOKESPECIAL, baseClassInternalName, "<init>", "()V"
-                visitInsn RETURN
-                visitMaxs 1, 1
-                visitEnd()
-            }
-
-            visitEnd()
-
-            writeBytecode it, internalName
-        }
-
-        createRegistry()
-
-        when:
-
-        ReloadableService reloadable = getService(ReloadableService)
-
-        update()
-
-        then:
-
-        reloadable.status == "initial from base"
-
-        when:
-
-        touch(new File(pathForInternalName(baseClassInternalName)))
-
-        createImplementationClass BASE_CLASS, "updated from base"
-
-        update()
-
-        then:
-
-        reloadable.status == "updated from base"
-    }
-
-    def "deleting an implementation class results in a runtime exception when reloading"() {
-
-        when:
-
-        createImplementationClass "before delete"
-
-        createRegistry()
-
-        ReloadableService reloadable = getService ReloadableService
-
-        then:
-
-        reloadable.status == "before delete"
-
-        assert classFile.exists()
-
-        when:
-
-        classFile.delete()
-
-        update()
-
-        reloadable.getStatus()
-
-        then:
-
-        RuntimeException e = thrown()
-
-        e.message.contains "Unable to reload class $CLASS"
-    }
-
-
-    def "reload a proxy object"() {
-        when:
-
-        createImplementationClass "initial proxy"
-
-        createRegistry()
-
-        def clazz = classLoader.loadClass CLASS
-
-        ReloadableService reloadable = proxy(ReloadableService, clazz)
-
-        then:
-
-        reloadable.status == "initial proxy"
-
-        when:
-
-        touch classFile
-
-        createImplementationClass "updated proxy"
-
-        update()
-
-        then:
-
-        reloadable.status == "updated proxy"
-
-        when:
-
-        touch classFile
-
-        createImplementationClass "re-updated proxy"
-
-        update()
-
-        then:
-
-        reloadable.status == "re-updated proxy"
-    }
-
-    def "check exception message for invalid service implementation (lacking a public constructor)"() {
-
-        when:
-
-        createImplementationClass "initial"
-
-        createRegistry()
-
-        ReloadableService reloadable = getService ReloadableService
-
-        touch classFile
-
-        createInvalidImplementationClass()
-
-        update()
-
-        reloadable.getStatus()
-
-        then:
-
-        Exception e = thrown()
-
-        e.message == "Service implementation class com.example.ReloadableServiceImpl does not have a suitable public constructor."
-    }
-
-    def "ensure ReloadAware services are notified when services are reloaded"() {
-
-        when:
-
-        registry = new RegistryBuilder().add(ReloadAwareModule).build()
-
-        then:
-
-        ReloadAwareModule.counterInstantiations == 0
-        ReloadAwareModule.counterReloads == 0
-
-        when:
-
-        Counter counter = proxy(Counter, CounterImpl)
-
-        then:
-
-        ReloadAwareModule.counterInstantiations == 0
-
-        expect:
-
-        counter.increment() == 1
-        counter.increment() == 2
-
-        ReloadAwareModule.counterInstantiations == 1
-
-        when:
-
-        def classURL = CounterImpl.getResource("CounterImpl.class")
-        def classFile = new File(classURL.toURI())
-
-        touch classFile
-
-        update()
-
-        // Check that the internal state has reset
-
-        assert counter.increment() == 1
-
-        then:
-
-        ReloadAwareModule.counterInstantiations == 2
-        ReloadAwareModule.counterReloads == 1
-    }
-
-    def createInvalidImplementationClass() {
-        def internalName = PlasticInternalUtils.toInternalName CLASS
-
-        createClassWriter(internalName, "java/lang/Object", ACC_PUBLIC).with {
-
-            visitMethod(ACC_PROTECTED, "<init>", "()V", null, null).with {
-                visitVarInsn ALOAD, 0
-                visitMethodInsn INVOKESPECIAL, "java/lang/Object", "<init>", "()V"
-                visitInsn RETURN
-                visitMaxs 1, 1
-                visitEnd()
-            }
-
-            visitEnd()
-
-            writeBytecode it, internalName
-        }
-    }
-
-
-    def touch(File f) {
-        long startModified = f.lastModified();
-
-        int index = 0;
-
-        while (true) {
-            f.setLastModified System.currentTimeMillis()
-
-            long newModified = f.lastModified()
-
-            if (newModified != startModified) {
-                return;
-            }
-
-            // Sleep an ever increasing amount, to ensure that the filesystem
-            // catches the change to the file. The Ubuntu CI Server appears
-            // to need longer waits.
-
-            Thread.sleep 50 * (2 ^ index++)
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/services/PeriodicExecutorSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/services/PeriodicExecutorSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/services/PeriodicExecutorSpec.groovy
deleted file mode 100644
index 535e399..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/services/PeriodicExecutorSpec.groovy
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.apache.tapestry.ioc.services
-
-import org.apache.tapestry.ioc.AbstractRegistrySpecification
-import org.apache.tapestry5.ioc.services.cron.IntervalSchedule
-import org.apache.tapestry5.ioc.services.cron.PeriodicExecutor
-
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
-
-class PeriodicExecutorSpec extends AbstractRegistrySpecification {
-
-    def "execution intervals"() {
-
-        buildRegistry()
-
-        def countDownLatch = new CountDownLatch(5);
-
-        def schedule = new IntervalSchedule(10)
-
-        def job = getService(PeriodicExecutor).addJob(schedule, "count incrementer", { countDownLatch.countDown(); })
-
-        countDownLatch.await 30, TimeUnit.SECONDS
-
-        cleanup:
-
-        job && job.cancel()
-
-
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/services/SystemEnvSymbolProviderSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/services/SystemEnvSymbolProviderSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/services/SystemEnvSymbolProviderSpec.groovy
deleted file mode 100644
index a81d20d..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry/ioc/services/SystemEnvSymbolProviderSpec.groovy
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.apache.tapestry.ioc.services
-
-import org.apache.tapestry5.ioc.internal.services.SystemEnvSymbolProvider
-import org.apache.tapestry5.ioc.services.SymbolProvider
-import spock.lang.Specification
-
-class SystemEnvSymbolProviderSpec extends Specification {
-
-    SymbolProvider provider = new SystemEnvSymbolProvider()
-
-    def "key exists"() {
-        expect:
-        provider.valueForSymbol("env.home") == System.getenv("HOME")
-    }
-
-    def "key missing"() {
-        expect: provider.valueForSymbol("env.does-not-exist") == null
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AbstractRegistrySpecification.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AbstractRegistrySpecification.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AbstractRegistrySpecification.groovy
new file mode 100644
index 0000000..cff3db7
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AbstractRegistrySpecification.groovy
@@ -0,0 +1,26 @@
+package org.apache.tapestry5.ioc
+
+import spock.lang.AutoCleanup
+import spock.lang.Specification
+
+/**
+ * Base class for Spock specifications that use a new {@link Registry} for each feature method.
+ */
+abstract class AbstractRegistrySpecification extends Specification {
+
+    @AutoCleanup("shutdown")
+    protected Registry registry;
+
+    protected final void buildRegistry(Class... moduleClasses) {
+
+        registry =
+            new RegistryBuilder().add(moduleClasses).build()
+    }
+
+    /** Any unrecognized methods are evaluated against the registry. */
+    def methodMissing(String name, args) {
+        registry."$name"(* args)
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AbstractSharedRegistrySpecification.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AbstractSharedRegistrySpecification.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AbstractSharedRegistrySpecification.groovy
new file mode 100644
index 0000000..8f61051
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AbstractSharedRegistrySpecification.groovy
@@ -0,0 +1,34 @@
+package org.apache.tapestry5.ioc
+
+import spock.lang.Specification
+
+/**
+ * Uses a static, shared instance of the {@link org.apache.tapestry5.ioc.Registry}.
+ * All specifications that extend from this class will share
+ * a single instance of the Registry; The Registry is created by whatever specification is created first.
+ * Missing method invocations are forwarded to the registry instance. */
+abstract class AbstractSharedRegistrySpecification extends Specification {
+
+  static Registry registry
+
+  /** Any unrecognized methods are evaluated against the shared Registry instance. */
+  def methodMissing(String name, args) {
+    registry."$name"(* args)
+  }
+
+  /** Creates the Registry if it does not already exist. */
+  def setupSpec() {
+    if (registry == null) {
+      registry = IOCUtilities.buildDefaultRegistry()
+    }
+  }
+
+  /** Invokes {@link Registry#cleanupThread()}. */
+  def cleanupSpec() {
+    registry.cleanupThread();
+  }
+
+  // TODO: the Registry is never shutdown, since there's no notification
+  // that all tests are completing.
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/BaseLocatableSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/BaseLocatableSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/BaseLocatableSpec.groovy
new file mode 100644
index 0000000..7dcc0a5
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/BaseLocatableSpec.groovy
@@ -0,0 +1,32 @@
+package org.apache.tapestry5.ioc
+
+import spock.lang.Specification
+
+class LocatableFixture extends BaseLocatable {
+    LocatableFixture(Location location) {
+        super(location)
+    }
+}
+
+class BaseLocatableSpec extends Specification {
+
+    def "location property is readable"() {
+        Location location = Mock()
+
+        Locatable locatable = new LocatableFixture(location)
+
+        expect:
+
+        locatable.location.is location
+    }
+
+    def "location may be null"() {
+        Locatable locatable = new LocatableFixture(null);
+
+
+        expect:
+
+        locatable.location == null
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/EagerLoadSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/EagerLoadSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/EagerLoadSpec.groovy
new file mode 100644
index 0000000..a04bd61
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/EagerLoadSpec.groovy
@@ -0,0 +1,21 @@
+package org.apache.tapestry5.ioc
+
+class EagerLoadSpec extends AbstractRegistrySpecification {
+
+    def "proxied service does eager load"()
+    {
+        expect:
+
+        EagerProxyReloadModule.eagerLoadServiceDidLoad == false
+
+        when:
+
+        buildRegistry EagerProxyReloadModule
+
+        performRegistryStartup()
+
+        then:
+
+        EagerProxyReloadModule.eagerLoadServiceDidLoad == true
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/OrderedConstraintBuilderSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/OrderedConstraintBuilderSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/OrderedConstraintBuilderSpec.groovy
new file mode 100644
index 0000000..02ea9ae
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/OrderedConstraintBuilderSpec.groovy
@@ -0,0 +1,30 @@
+package org.apache.tapestry5.ioc
+
+import spock.lang.Specification
+
+class OrderedConstraintBuilderSpec extends Specification {
+
+    /** Any unrecognized methods are evaluated against {@link OrderConstraintBuilder}. */
+    def methodMissing(String name, args) {
+        OrderConstraintBuilder."$name"(* args)
+    }
+
+    def "constraint ordering"() {
+        expect:
+
+        constraint.build() == values
+
+        where:
+
+        constraint || values
+
+        after("A") || ["after:A"]
+        afterAll() || ["after:*"]
+        before("B") || ["before:B"]
+        beforeAll() || ["before:*"]
+
+        before("A").after("B") || ["before:A", "after:B"]
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistryBuilderSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistryBuilderSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistryBuilderSpec.groovy
new file mode 100644
index 0000000..5fb91b7
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistryBuilderSpec.groovy
@@ -0,0 +1,98 @@
+package org.apache.tapestry5.ioc
+
+import org.apache.tapestry5.ioc.def.ModuleDef
+import org.apache.tapestry5.ioc.internal.DefaultModuleDefImpl
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import spock.lang.Specification
+
+class RegistryBuilderSpec extends Specification {
+
+    def "@SubModule annotation is honored"() {
+        when:
+
+        // Borrowed from IntegrationTest, this will only work if both FredModule and BarneyModule
+        // are loaded.
+
+        Registry r = new RegistryBuilder().add(MasterModule).build()
+
+        def service = r.getService("UnorderedNames", NameListHolder)
+
+        then:
+
+        service.names == ["Beta", "Gamma", "UnorderedNames"]
+
+        cleanup:
+
+        r.shutdown()
+    }
+
+    def "adding modules by name, in comma seperated list, as from a manifest"() {
+        when:
+
+        RegistryBuilder builder = new RegistryBuilder()
+
+        IOCUtilities.addModulesInList builder,
+                "${FredModule.class.name}, ${BarneyModule.class.name}, ${RegistryBuilderTestModule.class.name}"
+
+        Registry registry = builder.build()
+
+        Square service = registry.getService(Square)
+
+        then:
+
+        service.square(4) == 16
+
+        service.toString() == "<Proxy for Square(${Square.class.name})>"
+
+        cleanup:
+
+        registry.shutdown()
+    }
+
+    def "exercise RegistryBuilder.buildAndStartupRegistry()"() {
+        when:
+
+        Registry r = RegistryBuilder.buildAndStartupRegistry(MasterModule);
+
+        NameListHolder service = r.getService("UnorderedNames", NameListHolder);
+
+        then:
+
+        service.names == ["Beta", "Gamma", "UnorderedNames"]
+
+        cleanup:
+
+        r.shutdown();
+    }
+
+    def "use explicit ModuleDef with buildAndStartupRegistry()"() {
+        when:
+
+        Logger logger = LoggerFactory.getLogger(getClass());
+
+        ModuleDef module = new DefaultModuleDefImpl(ServiceBuilderModule,
+                logger, null);
+
+        Registry r = RegistryBuilder.buildAndStartupRegistry(module, MasterModule);
+
+        NameListHolder nameListHolder = r.getService("UnorderedNames", NameListHolder);
+
+        then:
+
+        nameListHolder.names == ["Beta", "Gamma", "UnorderedNames"]
+
+        when:
+
+        Greeter greeter = r.getService("Greeter", Greeter)
+
+        then:
+
+        greeter.greeting == "Greetings from service Greeter."
+
+        cleanup:
+
+        r.shutdown();
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ReloadSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ReloadSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ReloadSpec.groovy
new file mode 100644
index 0000000..763df6d
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ReloadSpec.groovy
@@ -0,0 +1,401 @@
+package org.apache.tapestry5.ioc
+
+import org.apache.tapestry5.internal.plastic.PlasticInternalUtils
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter
+import org.apache.tapestry5.services.UpdateListenerHub
+import spock.lang.AutoCleanup
+import spock.lang.Specification
+import com.example.*
+
+import static org.apache.tapestry5.internal.plastic.asm.Opcodes.*
+
+class ReloadSpec extends Specification {
+
+    private static final String PACKAGE = "com.example";
+
+    private static final String CLASS = PACKAGE + ".ReloadableServiceImpl";
+
+    private static final String BASE_CLASS = PACKAGE + ".BaseReloadableServiceImpl";
+
+
+    @AutoCleanup("shutdown")
+    Registry registry
+
+    @AutoCleanup("deleteDir")
+    File classesDir
+
+    ClassLoader classLoader
+
+    File classFile;
+
+    def createRegistry() {
+        registry = new RegistryBuilder(classLoader).add(ReloadModule).build()
+    }
+
+    /** Any unrecognized methods are evaluated against the registry. */
+    def methodMissing(String name, args) {
+        registry."$name"(* args)
+    }
+
+
+    def setup() {
+        def uid = UUID.randomUUID().toString()
+
+        classesDir = new File(System.getProperty("java.io.tmpdir"), uid)
+
+        def classesURL = new URL("file:" + classesDir.getCanonicalPath() + "/")
+
+        classLoader = new URLClassLoader([classesURL] as URL[],
+                Thread.currentThread().contextClassLoader)
+
+        classFile = new File(classesDir, PlasticInternalUtils.toClassPath(CLASS))
+    }
+
+    def createImplementationClass(String status) {
+        createImplementationClass CLASS, status
+    }
+
+    def createImplementationClass(String className, String status) {
+
+        String internalName = PlasticInternalUtils.toInternalName className
+
+        createClassWriter(internalName, "java/lang/Object", ACC_PUBLIC).with {
+
+            // Add default constructor
+
+            visitMethod(ACC_PUBLIC, "<init>", "()V", null, null).with {
+                visitCode()
+                visitVarInsn ALOAD, 0
+                visitMethodInsn INVOKESPECIAL, "java/lang/Object", "<init>", "()V"
+                visitInsn RETURN
+                visitMaxs 1, 1
+                visitEnd()
+            }
+
+
+            visitMethod(ACC_PUBLIC, "getStatus", "()Ljava/lang/String;", null, null).with {
+                visitCode()
+                visitLdcInsn status
+                visitInsn ARETURN
+                visitMaxs 1, 1
+                visitEnd()
+            }
+
+            visitEnd()
+
+            writeBytecode it, internalName
+        }
+
+    }
+
+    def createClassWriter(String internalName, String baseClassInternalName, int classModifiers) {
+        ClassWriter cw = new ClassWriter(0);
+
+        cw.visit V1_5, classModifiers, internalName, null,
+                baseClassInternalName, [
+                        PlasticInternalUtils.toInternalName(ReloadableService.name)
+                ] as String[]
+
+
+        return cw
+    }
+
+
+    def writeBytecode(ClassWriter cw, String internalName) {
+        byte[] bytecode = cw.toByteArray();
+
+        writeBytecode(bytecode, pathForInternalName(internalName))
+    }
+
+    def writeBytecode(byte[] bytecode, String path) {
+        File file = new File(path)
+
+        file.parentFile.mkdirs()
+
+        file.withOutputStream { it.write bytecode }
+    }
+
+
+    def pathForInternalName(String internalName) {
+        return String.format("%s/%s.class",
+                classesDir.getAbsolutePath(),
+                internalName)
+    }
+
+    def update() {
+        getService(UpdateListenerHub).fireCheckForUpdates()
+    }
+
+    def "reload a service implementation"() {
+
+        when:
+
+        createImplementationClass "initial"
+
+        createRegistry()
+
+        ReloadableService reloadable = getService(ReloadableService);
+
+        update()
+
+        then:
+
+        reloadable.status == "initial"
+
+        when:
+
+        update()
+
+        touch classFile
+
+        createImplementationClass "updated"
+
+        then:
+
+        // Changes do not take effect until after update check
+
+        reloadable.status == "initial"
+
+        when:
+
+        update()
+
+        then:
+
+        reloadable.status == "updated"
+    }
+
+    def "reload a base class"() {
+
+        setup:
+
+        def baseClassInternalName = PlasticInternalUtils.toInternalName BASE_CLASS
+        def internalName = PlasticInternalUtils.toInternalName CLASS
+
+        createImplementationClass BASE_CLASS, "initial from base"
+
+        createClassWriter(internalName, baseClassInternalName, ACC_PUBLIC).with {
+
+            visitMethod(ACC_PUBLIC, "<init>", "()V", null, null).with {
+                visitCode()
+                visitVarInsn ALOAD, 0
+                visitMethodInsn INVOKESPECIAL, baseClassInternalName, "<init>", "()V"
+                visitInsn RETURN
+                visitMaxs 1, 1
+                visitEnd()
+            }
+
+            visitEnd()
+
+            writeBytecode it, internalName
+        }
+
+        createRegistry()
+
+        when:
+
+        ReloadableService reloadable = getService(ReloadableService)
+
+        update()
+
+        then:
+
+        reloadable.status == "initial from base"
+
+        when:
+
+        touch(new File(pathForInternalName(baseClassInternalName)))
+
+        createImplementationClass BASE_CLASS, "updated from base"
+
+        update()
+
+        then:
+
+        reloadable.status == "updated from base"
+    }
+
+    def "deleting an implementation class results in a runtime exception when reloading"() {
+
+        when:
+
+        createImplementationClass "before delete"
+
+        createRegistry()
+
+        ReloadableService reloadable = getService ReloadableService
+
+        then:
+
+        reloadable.status == "before delete"
+
+        assert classFile.exists()
+
+        when:
+
+        classFile.delete()
+
+        update()
+
+        reloadable.getStatus()
+
+        then:
+
+        RuntimeException e = thrown()
+
+        e.message.contains "Unable to reload class $CLASS"
+    }
+
+
+    def "reload a proxy object"() {
+        when:
+
+        createImplementationClass "initial proxy"
+
+        createRegistry()
+
+        def clazz = classLoader.loadClass CLASS
+
+        ReloadableService reloadable = proxy(ReloadableService, clazz)
+
+        then:
+
+        reloadable.status == "initial proxy"
+
+        when:
+
+        touch classFile
+
+        createImplementationClass "updated proxy"
+
+        update()
+
+        then:
+
+        reloadable.status == "updated proxy"
+
+        when:
+
+        touch classFile
+
+        createImplementationClass "re-updated proxy"
+
+        update()
+
+        then:
+
+        reloadable.status == "re-updated proxy"
+    }
+
+    def "check exception message for invalid service implementation (lacking a public constructor)"() {
+
+        when:
+
+        createImplementationClass "initial"
+
+        createRegistry()
+
+        ReloadableService reloadable = getService ReloadableService
+
+        touch classFile
+
+        createInvalidImplementationClass()
+
+        update()
+
+        reloadable.getStatus()
+
+        then:
+
+        Exception e = thrown()
+
+        e.message == "Service implementation class com.example.ReloadableServiceImpl does not have a suitable public constructor."
+    }
+
+    def "ensure ReloadAware services are notified when services are reloaded"() {
+
+        when:
+
+        registry = new RegistryBuilder().add(ReloadAwareModule).build()
+
+        then:
+
+        ReloadAwareModule.counterInstantiations == 0
+        ReloadAwareModule.counterReloads == 0
+
+        when:
+
+        Counter counter = proxy(Counter, CounterImpl)
+
+        then:
+
+        ReloadAwareModule.counterInstantiations == 0
+
+        expect:
+
+        counter.increment() == 1
+        counter.increment() == 2
+
+        ReloadAwareModule.counterInstantiations == 1
+
+        when:
+
+        def classURL = CounterImpl.getResource("CounterImpl.class")
+        def classFile = new File(classURL.toURI())
+
+        touch classFile
+
+        update()
+
+        // Check that the internal state has reset
+
+        assert counter.increment() == 1
+
+        then:
+
+        ReloadAwareModule.counterInstantiations == 2
+        ReloadAwareModule.counterReloads == 1
+    }
+
+    def createInvalidImplementationClass() {
+        def internalName = PlasticInternalUtils.toInternalName CLASS
+
+        createClassWriter(internalName, "java/lang/Object", ACC_PUBLIC).with {
+
+            visitMethod(ACC_PROTECTED, "<init>", "()V", null, null).with {
+                visitVarInsn ALOAD, 0
+                visitMethodInsn INVOKESPECIAL, "java/lang/Object", "<init>", "()V"
+                visitInsn RETURN
+                visitMaxs 1, 1
+                visitEnd()
+            }
+
+            visitEnd()
+
+            writeBytecode it, internalName
+        }
+    }
+
+
+    def touch(File f) {
+        long startModified = f.lastModified();
+
+        int index = 0;
+
+        while (true) {
+            f.setLastModified System.currentTimeMillis()
+
+            long newModified = f.lastModified()
+
+            if (newModified != startModified) {
+                return;
+            }
+
+            // Sleep an ever increasing amount, to ensure that the filesystem
+            // catches the change to the file. The Ubuntu CI Server appears
+            // to need longer waits.
+
+            Thread.sleep 50 * (2 ^ index++)
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImplSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImplSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImplSpec.groovy
index a477a14..b58ecb8 100644
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImplSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImplSpec.groovy
@@ -1,7 +1,7 @@
 package org.apache.tapestry5.ioc.internal.services
 
 import org.apache.commons.lang.StringUtils
-import org.apache.tapestry.ioc.AbstractSharedRegistrySpecification
+import org.apache.tapestry5.ioc.AbstractSharedRegistrySpecification
 import org.apache.tapestry5.ioc.services.AspectDecorator
 import org.apache.tapestry5.plastic.MethodAdvice
 import org.apache.tapestry5.plastic.MethodInvocation

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/ChainBuilderImplSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/ChainBuilderImplSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/ChainBuilderImplSpec.groovy
index a2b5a3a..febcc9e 100644
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/ChainBuilderImplSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/ChainBuilderImplSpec.groovy
@@ -1,6 +1,6 @@
 package org.apache.tapestry5.ioc.internal.services
 
-import org.apache.tapestry.ioc.AbstractSharedRegistrySpecification
+import org.apache.tapestry5.ioc.AbstractSharedRegistrySpecification
 import org.apache.tapestry5.ioc.services.ChainBuilder
 
 interface ChainCommand {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/DefaultImplementationBuilderImplSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/DefaultImplementationBuilderImplSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/DefaultImplementationBuilderImplSpec.groovy
index ea2ed27..9cdfa3d 100644
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/DefaultImplementationBuilderImplSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/DefaultImplementationBuilderImplSpec.groovy
@@ -1,6 +1,6 @@
 package org.apache.tapestry5.ioc.internal.services
 
-import org.apache.tapestry.ioc.AbstractSharedRegistrySpecification
+import org.apache.tapestry5.ioc.AbstractSharedRegistrySpecification
 import org.apache.tapestry5.ioc.services.DefaultImplementationBuilder
 
 /** An interface that includes toString() */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/ExceptionAnalyzerImplSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/ExceptionAnalyzerImplSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/ExceptionAnalyzerImplSpec.groovy
index f5f63b0..4133e74 100644
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/ExceptionAnalyzerImplSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/internal/services/ExceptionAnalyzerImplSpec.groovy
@@ -1,6 +1,6 @@
 package org.apache.tapestry5.ioc.internal.services
 
-import org.apache.tapestry.ioc.AbstractSharedRegistrySpecification
+import org.apache.tapestry5.ioc.AbstractSharedRegistrySpecification
 import org.apache.tapestry5.ioc.Location
 import org.apache.tapestry5.ioc.internal.util.TapestryException
 import org.apache.tapestry5.ioc.services.ExceptionAnalyzer

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/services/PeriodicExecutorSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/services/PeriodicExecutorSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/services/PeriodicExecutorSpec.groovy
new file mode 100644
index 0000000..993c6b6
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/services/PeriodicExecutorSpec.groovy
@@ -0,0 +1,30 @@
+package org.apache.tapestry5.ioc.services
+
+import org.apache.tapestry5.ioc.AbstractRegistrySpecification
+import org.apache.tapestry5.ioc.services.cron.IntervalSchedule
+import org.apache.tapestry5.ioc.services.cron.PeriodicExecutor
+
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+
+class PeriodicExecutorSpec extends AbstractRegistrySpecification {
+
+    def "execution intervals"() {
+
+        buildRegistry()
+
+        def countDownLatch = new CountDownLatch(5);
+
+        def schedule = new IntervalSchedule(10)
+
+        def job = getService(PeriodicExecutor).addJob(schedule, "count incrementer", { countDownLatch.countDown(); })
+
+        countDownLatch.await 30, TimeUnit.SECONDS
+
+        cleanup:
+
+        job && job.cancel()
+
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6329fbf7/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/services/SystemEnvSymbolProviderSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/services/SystemEnvSymbolProviderSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/services/SystemEnvSymbolProviderSpec.groovy
new file mode 100644
index 0000000..b308f5d
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/services/SystemEnvSymbolProviderSpec.groovy
@@ -0,0 +1,20 @@
+package org.apache.tapestry5.ioc.services
+
+import org.apache.tapestry5.ioc.internal.services.SystemEnvSymbolProvider
+import spock.lang.Specification
+
+class SystemEnvSymbolProviderSpec extends Specification {
+
+    SymbolProvider provider = new SystemEnvSymbolProvider()
+
+    def "key exists"() {
+        expect:
+        provider.valueForSymbol("env.home") == System.getenv("HOME")
+    }
+
+    def "key missing"() {
+        expect: provider.valueForSymbol("env.does-not-exist") == null
+
+    }
+
+}