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
+
+ }
+
+}