You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2012/06/21 19:28:19 UTC
[6/9] Refactor all the tapestry-ioc Spock specifications into the
ioc.specs package Convert some package-private classes and constructors to
public
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/ServiceLookupSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/ServiceLookupSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/ServiceLookupSpec.groovy
new file mode 100644
index 0000000..c976a73
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/ServiceLookupSpec.groovy
@@ -0,0 +1,118 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.services.Builtin
+import org.apache.tapestry5.ioc.services.TypeCoercer
+
+import java.sql.PreparedStatement
+
+import org.apache.tapestry5.ioc.*
+
+class ServiceLookupSpec extends AbstractRegistrySpecification {
+
+ def "access to services by id is case insensitive"() {
+
+ buildRegistry FredModule
+
+ when:
+
+ def r1 = getService "Fred", Runnable
+ def r2 = getService "FRED", Runnable
+
+ then:
+
+ r1.is r2
+
+ }
+
+ def "verify exception when accessing service by unknown id"() {
+
+ buildRegistry()
+
+ when:
+
+ getService "PeekABoo", Runnable
+
+ then:
+
+ RuntimeException e = thrown()
+
+ e.message.contains "Service id 'PeekABoo' is not defined by any module."
+ }
+
+ def "verify exception when accessing a service by type and there are no matching services"() {
+
+ buildRegistry()
+
+ when:
+
+ getService PreparedStatement
+
+ then:
+
+ RuntimeException e = thrown()
+
+ e.message == "No service implements the interface java.sql.PreparedStatement."
+ }
+
+ def "verify exception when accessing a service by type and there are multiple matches"() {
+ buildRegistry DuplicateServiceTypeModule
+
+ when:
+
+ getService Pingable
+
+ then:
+
+ RuntimeException e = thrown()
+
+ e.message == "Service interface org.apache.tapestry5.ioc.Pingable is matched by 2 services: Barney, Fred. Automatic dependency resolution requires that exactly one service implement the interface."
+ }
+
+ def "access to builtin service via marker annotation"() {
+ Builtin annotation = Mock()
+ AnnotationProvider ap = Mock()
+
+ buildRegistry()
+
+ def tc1 = getService "TypeCoercer", TypeCoercer
+
+ when:
+
+ def tc2 = getObject TypeCoercer, ap
+
+ then:
+
+ 1 * ap.getAnnotation(Builtin) >> annotation
+
+ tc2.is tc1
+ }
+
+ def "lookup service by type and markers"() {
+ buildRegistry GreeterModule
+
+ when:
+
+ def blue = getService Greeter, BlueMarker
+
+ then:
+
+ blue.greeting == "Blue"
+ }
+
+ def "use of the @Local annotation disambiguates from multiple services"() {
+ buildRegistry GreeterModule, LocalModule
+
+
+ when:
+
+ // The implementation of this class relies on a @Local injection to find
+ // a specific Greeter implementation
+
+ StringHolder holder = getService "LocalGreeterHolder", StringHolder
+
+ then:
+
+ holder.value == "Hello, y'all!"
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/ServiceProxySpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/ServiceProxySpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/ServiceProxySpec.groovy
new file mode 100644
index 0000000..91a05be
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/ServiceProxySpec.groovy
@@ -0,0 +1,98 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.*
+
+class ServiceProxySpec extends AbstractRegistrySpecification {
+
+ def "shutdown deactivaties proxies"() {
+ buildRegistry FredModule, BarneyModule
+
+ def fred = getService "Fred", Runnable
+
+ fred.run()
+
+ shutdown()
+
+ when:
+
+ fred.run()
+
+ then:
+
+ RuntimeException ex = thrown()
+
+ ex.message.contains "Proxy for service Fred is no longer active because the IOC Registry has been shut down."
+
+ fred.toString() == "<Proxy for Fred(java.lang.Runnable)>"
+
+ cleanup:
+
+ registry = null
+ }
+
+ def "show that services defined without a implementation are instantiated immediately"() {
+ buildRegistry NonProxiedServiceModule
+
+ when:
+
+ def holder = getService StringHolder
+
+ then:
+
+ holder instanceof StringHolderImpl // and not some proxy
+ }
+
+ def "service builder methods with a class (not interface) return type are not proxied, but are cached"() {
+
+ buildRegistry ConcreteServiceBuilderModule
+
+ when:
+
+ def h1 = getService StringHolder
+
+ then: "not proxied"
+
+ h1 instanceof StringHolderImpl
+
+ when:
+
+ def h2 = getService StringHolder
+
+ then: "cached"
+
+ h2.is h1
+ }
+
+ def "verify that a proxy for an autobuilt object lazily instantiates the implementation"() {
+
+ buildRegistry()
+
+ expect:
+ IntegrationTestFixture.countingGreeterInstantiationCount == 0
+
+ when: "obtaining the proxy"
+
+ def g = proxy Greeter, CountingGreeterImpl
+
+ then: "the implementation is not yet instantiated"
+
+ IntegrationTestFixture.countingGreeterInstantiationCount == 0
+
+ when: "invoking toString() on the proxy"
+
+ assert g.toString() == "<Autoreload proxy org.apache.tapestry5.ioc.CountingGreeterImpl(org.apache.tapestry5.ioc.Greeter)>"
+
+ then: "the implementation is not yet instantiated"
+
+ IntegrationTestFixture.countingGreeterInstantiationCount == 0
+
+ when: "invoking other methods on the proxy"
+
+ assert g.greeting == "Hello"
+
+ then: "the implementation is now instantiated"
+
+ IntegrationTestFixture.countingGreeterInstantiationCount == 1
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/StackSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/StackSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/StackSpec.groovy
new file mode 100644
index 0000000..29116c9
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/StackSpec.groovy
@@ -0,0 +1,113 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.util.Stack
+import spock.lang.Specification
+
+class StackSpec extends Specification {
+
+ def stack = new Stack()
+
+ def "peek in empty stack is failure"() {
+
+ when:
+
+ stack.peek()
+
+ then:
+
+ IllegalStateException e = thrown()
+
+ e.message == "Stack is empty."
+ }
+
+ def "pop in empty stack is failure"() {
+
+ when:
+
+ stack.pop()
+
+ then:
+
+ IllegalStateException e = thrown()
+
+ e.message == "Stack is empty."
+ }
+
+ def "simple stack operations"() {
+
+ def fred = "fred"
+ def barney = "barney"
+
+ expect:
+
+ stack.empty
+
+ when:
+
+ stack.push fred
+
+ then:
+
+ stack.peek().is(fred)
+ !stack.empty
+
+ when:
+
+ stack.push barney
+
+ then:
+
+ stack.peek().is(barney)
+
+ stack.toString() == "Stack[barney, fred]"
+
+ stack.depth == 2
+
+ stack.snapshot.equals([fred, barney])
+
+ when:
+
+ def popped = stack.pop()
+
+ then:
+
+ popped.is barney
+ stack.peek().is(fred)
+ !stack.empty
+
+ when:
+
+ popped = stack.pop()
+
+ then:
+
+ popped.is fred
+ stack.empty
+ }
+
+ def "force the expansion of the inner data"() {
+
+ def limit = 1000
+
+ when:
+
+ limit.times { stack.push it }
+
+ then:
+
+ limit.downto(1) { stack.pop() == it - 1}
+ }
+
+ def "clear the stack"() {
+
+ 10.times { stack.push it }
+
+ when:
+
+ stack.clear()
+
+ then:
+
+ stack.empty
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/StrategyBuilderImplSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/StrategyBuilderImplSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/StrategyBuilderImplSpec.groovy
new file mode 100644
index 0000000..9f24309
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/StrategyBuilderImplSpec.groovy
@@ -0,0 +1,69 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.services.StrategyBuilder
+import spock.lang.Shared
+
+
+interface KindOf {
+
+ String kindOf(Object value);
+}
+
+class KindOfImpl implements KindOf {
+
+ private final String value;
+
+ KindOfImpl(String value) { this.value = value; }
+
+ @Override
+ String kindOf(Object value) {
+ return this.value;
+ }
+
+}
+
+class StrategyBuilderImplSpec extends AbstractSharedRegistrySpecification {
+
+ @Shared
+ KindOf service
+
+
+ def setup() {
+
+ StrategyBuilder builder = getService StrategyBuilder
+
+ service = builder.build KindOf, [
+ (Map): new KindOfImpl("MAP"),
+ (List): new KindOfImpl("LIST")
+ ]
+ }
+
+ def "generated class implements a useful toString()"() {
+
+ expect:
+
+ service.toString() == "<Strategy for ioc.specs.KindOf>"
+ }
+
+ def "ensure implementation inputs map to interface definitions"() {
+
+ expect:
+
+ service.kindOf(Collections.EMPTY_MAP) == "MAP"
+ service.kindOf(Collections.EMPTY_LIST) == "LIST"
+ }
+
+ def "mapping null with no void mapping is a failure"() {
+
+ when:
+
+ service.kindOf null
+
+ then:
+
+ RuntimeException e = thrown()
+
+ e.message == "No adapter from type void to type ioc.specs.KindOf is available."
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/StrategyRegistrySpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/StrategyRegistrySpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/StrategyRegistrySpec.groovy
new file mode 100644
index 0000000..821cbab
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/StrategyRegistrySpec.groovy
@@ -0,0 +1,148 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.util.StrategyRegistry
+import org.apache.tapestry5.ioc.util.UnknownValueException
+import spock.lang.Specification
+
+class StrategyRegistrySpec extends Specification {
+
+ def "check exception when an adaptor is not found"() {
+ Runnable r1 = Mock()
+ Runnable r2 = Mock()
+
+ StrategyRegistry reg = StrategyRegistry.newInstance(Runnable, [
+ (List): r1,
+ (Map): r2
+ ])
+
+ when:
+
+ reg.get(Set)
+
+ then:
+
+ UnknownValueException e = thrown()
+
+ e.message == "No adapter from type java.util.Set to type java.lang.Runnable is available."
+ e.availableValues.toString() == "AvailableValues[registered types: interface java.util.List, interface java.util.Map]"
+
+ }
+
+ def "access to types registered"() {
+ Runnable r1 = Mock()
+ Runnable r2 = Mock()
+
+ when:
+
+ StrategyRegistry sr = StrategyRegistry.newInstance(Runnable, [
+ (List): r1,
+ (Map): r2
+ ])
+
+ then:
+
+ sr.types.size == 2
+ sr.types.containsAll(List, Map)
+ }
+
+ def "locate an adapter based on interface inheritance"() {
+
+ Runnable r1 = Mock()
+ Runnable r2 = Mock()
+
+ when:
+
+ StrategyRegistry sr = StrategyRegistry.newInstance(Runnable, [
+ (List): r1,
+ (Map): r2
+ ])
+
+ def arrayListAdapter = sr.get(ArrayList)
+
+ then:
+
+ arrayListAdapter.is r1
+
+ when:
+
+ def adapter2 = sr.get(ArrayList)
+
+ then:
+
+ adapter2.is r1
+
+ when:
+
+ sr.clearCache()
+
+ def adapter3 = sr.get(ArrayList)
+
+ then:
+
+ adapter3.is r1
+ }
+
+ def "the registration map passed to the constructor is copied"() {
+
+ Runnable r1 = Mock()
+ Runnable r2 = Mock()
+
+ def registrations = [
+ (List): r1,
+ (Map): r2
+ ]
+
+ when:
+
+ StrategyRegistry sr = StrategyRegistry.newInstance(Runnable, registrations)
+
+ registrations.clear()
+
+ then:
+
+ sr.get(ArrayList).is(r1)
+ }
+
+ def "adapter found from an instance"() {
+
+ Runnable r1 = Mock()
+ Runnable r2 = Mock()
+
+ when:
+
+ StrategyRegistry sr = StrategyRegistry.newInstance(Runnable, [
+ (List): r1,
+ (Map): r2
+ ])
+
+ then:
+
+ sr.getByInstance([]).is(r1)
+ sr.getByInstance([:]).is(r2)
+
+ when:
+
+ sr.clearCache()
+
+ then:
+
+ sr.getByInstance([]).is(r1)
+ }
+
+ def "null instances matches against void.class"() {
+
+ Runnable r1 = Mock()
+ Runnable r2 = Mock()
+
+ when:
+
+ def sr = StrategyRegistry.newInstance(Runnable, [
+ (void): r1,
+ (Map): r2])
+
+
+ then:
+
+ sr.getByInstance(null).is(r1)
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/StringToEnumCoercionSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/StringToEnumCoercionSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/StringToEnumCoercionSpec.groovy
new file mode 100644
index 0000000..ce8a473
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/StringToEnumCoercionSpec.groovy
@@ -0,0 +1,53 @@
+package ioc.specs
+
+import org.apache.tapestry5.util.Stooge
+import org.apache.tapestry5.util.StringToEnumCoercion
+import spock.lang.Specification
+
+class StringToEnumCoercionSpec extends Specification {
+
+ def "searches are case-insensitive"() {
+ def coercion = new StringToEnumCoercion(Stooge)
+
+ expect:
+
+ coercion.coerce("moe").is(Stooge.MOE)
+ coercion.coerce("MOE").is(Stooge.MOE)
+ coercion.coerce("CURLY_Joe").is(Stooge.CURLY_JOE)
+ }
+
+ def "blank input returns null"() {
+ def coercion = new StringToEnumCoercion(Stooge)
+
+ expect:
+
+ coercion.coerce("") == null
+ coercion.coerce("\t\n") == null
+ }
+
+ def "enum value can be found by an added alias"() {
+ def coercion = new StringToEnumCoercion(Stooge)
+
+ coercion.addAlias("shemp", Stooge.CURLY_JOE)
+
+ expect:
+
+ coercion.coerce("curly_joe").is(Stooge.CURLY_JOE)
+ coercion.coerce("shemp").is(Stooge.CURLY_JOE)
+ coercion.coerce("Shemp").is(Stooge.CURLY_JOE)
+ }
+
+ def "a failed search by name throws an exception"() {
+ def coercion = new StringToEnumCoercion(Stooge)
+
+ when:
+
+ coercion.coerce("shemp")
+
+ then:
+
+ RuntimeException e = thrown()
+
+ e.message == /Input 'shemp' does not identify a value from enumerated type ${Stooge.name}./
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/SystemEnvSymbolProviderSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/SystemEnvSymbolProviderSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/SystemEnvSymbolProviderSpec.groovy
new file mode 100644
index 0000000..d9f72d0
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/SystemEnvSymbolProviderSpec.groovy
@@ -0,0 +1,21 @@
+package ioc.specs
+
+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/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/TimeIntervalSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/TimeIntervalSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/TimeIntervalSpec.groovy
new file mode 100644
index 0000000..992f692
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/TimeIntervalSpec.groovy
@@ -0,0 +1,72 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.util.TimeInterval
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class TimeIntervalSpec extends Specification {
+
+ @Unroll
+ def "constructor usage '#input' parses to #milliseconds ms and '#units'"() {
+ when:
+
+ TimeInterval ti = new TimeInterval(input)
+
+ then:
+
+ ti.milliseconds() == milliseconds
+ ti.toString() == "TimeInterval[$units]"
+
+ ti.toDescription() == description
+
+ where:
+
+ input | milliseconds | units | description
+
+ "30 s" | 30000 | "30000 ms" | "30s"
+ "1h 30m" | 90 * 60 * 1000 | "5400000 ms" | "1h 30m"
+ "2d" | 2 * 24 * 60 * 60 * 1000 | "172800000 ms" | "2d"
+ "23ms" | 23 | "23 ms" | "23ms"
+ "62s" | 62 * 1000 | "62000 ms" | "1m 2s"
+ }
+
+ def "invalid units"() {
+
+ when:
+
+ TimeInterval.parseMilliseconds "30s 500mz"
+
+ then:
+
+ RuntimeException e = thrown()
+
+ e.message == "Unknown time interval unit 'mz' (in '30s 500mz'). Defined units: d, h, m, ms, s, y."
+ }
+
+ def "unrecognized input"() {
+
+ when:
+
+ TimeInterval.parseMilliseconds "30s z 500ms"
+
+ then:
+
+ RuntimeException e = thrown()
+
+ e.message.contains "Unexpected string 'z'"
+ }
+
+ def "unrecognized input at end"() {
+
+ when:
+
+ TimeInterval.parseMilliseconds "30s 500ms xyz"
+
+ then:
+
+ RuntimeException e = thrown()
+
+ e.message.contains "Unexpected string 'xyz'"
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/ToString.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/ToString.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/ToString.groovy
new file mode 100644
index 0000000..b432ee0
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/ToString.groovy
@@ -0,0 +1,7 @@
+package ioc.specs
+
+/** An interface that includes toString() */
+interface ToString {
+
+ String toString();
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/URLChangeTrackerSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/URLChangeTrackerSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/URLChangeTrackerSpec.groovy
new file mode 100644
index 0000000..a5a8c56
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/URLChangeTrackerSpec.groovy
@@ -0,0 +1,187 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.internal.services.ClasspathURLConverterImpl
+import org.apache.tapestry5.ioc.internal.util.URLChangeTracker
+import org.apache.tapestry5.ioc.services.ClasspathURLConverter
+import spock.lang.Shared
+import spock.lang.Specification
+
+class URLChangeTrackerSpec extends Specification {
+
+ @Shared
+ ClasspathURLConverter converter = new ClasspathURLConverterImpl()
+
+ def tracker = new URLChangeTracker(converter)
+
+ def "new instance does not contain changes"() {
+ expect:
+
+ !tracker.containsChanges()
+ }
+
+ def "adding a null URL returns 0"() {
+
+ expect:
+ tracker.add(null) == 0l
+ }
+
+ def touch(file) {
+
+ def initial = file.lastModified()
+ def index = 0
+
+ while (true) {
+
+ file.lastModified = System.currentTimeMillis()
+
+ if (file.lastModified() != initial) { return }
+
+ Thread.sleep(50 * 2 ^ index++)
+ }
+ }
+
+ def "add a file, touch it, and ensure that the change is noticed"() {
+ def f = newFile()
+
+ when:
+
+ tracker.add(f.toURL())
+
+ then:
+
+ // one for the file, one for its directory
+
+ tracker.trackedFileCount() == 2
+ !tracker.containsChanges()
+
+ when:
+
+ touch(f)
+
+ then:
+
+ tracker.containsChanges()
+ }
+
+ def File newFile() {
+ File.createTempFile("changetracker0", ".tmp")
+ }
+
+ def "creating a new file in an existing tracker folder is a change"() {
+
+ def first = newFile()
+ def dir = first.getParentFile()
+
+ when:
+
+ tracker.add(first.toURL())
+
+ then:
+
+ !tracker.containsChanges()
+
+ when:
+
+ def initial = dir.lastModified()
+ def index = 0
+
+ while (true) {
+ newFile()
+
+ if (dir.lastModified() != initial) { break; }
+ Thread.sleep(50 * 2 ^ index++)
+ }
+
+ then:
+
+ tracker.containsChanges()
+ }
+
+ def "non-file URLs are ignored"() {
+
+ when:
+
+ tracker.add(new URL("http://google.com"))
+
+ then:
+
+ tracker.trackedFileCount() == 0
+ }
+
+ def "caching of URLs and timestamps"() {
+
+ def file = newFile()
+ def url = file.toURL()
+
+ def initial = tracker.add(url)
+
+ when:
+
+ touch(file)
+
+ then:
+
+ tracker.add(url) == initial
+
+ tracker.containsChanges()
+
+ when:
+
+ tracker.clear()
+
+ then:
+
+ tracker.add(url) != initial
+ }
+
+ def "deleting a file shows as changes"() {
+ def file = newFile()
+ def url = file.toURL()
+
+ when:
+
+ def initial = tracker.add(url)
+
+ then:
+
+ initial > 0
+ !tracker.containsChanges()
+
+ when:
+
+ file.delete()
+
+ then:
+
+ tracker.containsChanges()
+ }
+
+ def "can track changes at a 1-second granularity (rather than millisecond)"() {
+ tracker = new URLChangeTracker(converter, true, true)
+
+ def file = newFile()
+
+ when:
+
+ long initial = tracker.add(file.toURL())
+
+ then:
+
+ initial % 1000 == 0
+
+ when:
+
+ Thread.sleep 1500
+
+ touch(file)
+
+ then:
+
+ tracker.containsChanges()
+
+ def updated = tracker.add(file.toURL())
+
+ updated % 1000 == 0
+ updated != initial
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingConfigurationWrapperSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingConfigurationWrapperSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingConfigurationWrapperSpec.groovy
new file mode 100644
index 0000000..c76cb3c
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingConfigurationWrapperSpec.groovy
@@ -0,0 +1,80 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.Configuration
+import org.apache.tapestry5.ioc.ObjectLocator
+import org.apache.tapestry5.ioc.internal.TypeCoercerProxy
+import org.apache.tapestry5.ioc.internal.ValidatingConfigurationWrapper
+import spock.lang.Specification
+
+class ValidatingConfigurationWrapperSpec extends Specification {
+
+ TypeCoercerProxy tc = Mock()
+ ObjectLocator locator = Mock()
+
+ def collection = []
+
+ def "valid contribution"() {
+ Runnable value = Mock()
+
+ Configuration config = new ValidatingConfigurationWrapper(Runnable, null, tc, collection, "Baz")
+
+ when:
+
+ config.add(value)
+
+ then:
+
+ tc.coerce(value, Runnable) >> value
+
+ collection == [value]
+ }
+
+ def "contributed value may be coerced"() {
+ Runnable value = Mock()
+ Runnable coerced = Mock()
+
+ Configuration config = new ValidatingConfigurationWrapper(Runnable, null, tc, collection, "Baz")
+
+ when:
+
+ config.add(value)
+
+ then:
+
+ tc.coerce(value, Runnable) >> coerced
+
+ collection == [coerced]
+ }
+
+ def "an instance of a class may be contributed"() {
+ HashMap contributed = new HashMap()
+ Map coerced = Mock()
+
+ Configuration config = new ValidatingConfigurationWrapper(Map, locator, tc, collection, "Baz")
+
+ when:
+
+ config.addInstance(HashMap)
+
+ then:
+
+ locator.autobuild(HashMap) >> contributed
+ tc.coerce(contributed, Map) >> coerced
+
+ collection == [coerced]
+ }
+
+ def "null may not be contributed"() {
+ Configuration config = new ValidatingConfigurationWrapper(Runnable, null, tc, collection, "Baz")
+
+ when:
+
+ config.add(null)
+
+ then:
+
+ NullPointerException e = thrown()
+
+ e.message == "Service contribution (to service 'Baz') was null."
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingMappedConfigurationWrapperSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingMappedConfigurationWrapperSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingMappedConfigurationWrapperSpec.groovy
new file mode 100644
index 0000000..60241a7
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingMappedConfigurationWrapperSpec.groovy
@@ -0,0 +1,154 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.MappedConfiguration
+import org.apache.tapestry5.ioc.ObjectLocator
+import org.apache.tapestry5.ioc.def.ContributionDef
+import org.apache.tapestry5.ioc.internal.ContributionDefImpl
+import org.apache.tapestry5.ioc.internal.TypeCoercerProxy
+import org.apache.tapestry5.ioc.internal.ValidatingMappedConfigurationWrapper
+import org.apache.tapestry5.ioc.services.PlasticProxyFactory
+
+import java.sql.SQLException
+
+class ValidatingMappedConfigurationWrapperSpec extends AbstractSharedRegistrySpecification {
+
+ static String SERVICE_ID = "Baz"
+
+ ObjectLocator locator = Mock()
+ TypeCoercerProxy tc = Mock()
+ Map keyToContribution = [:]
+ Map map = [:]
+
+ def "contribute a property key and value"() {
+ ContributionDef cd = Mock()
+ def keyToContribution = [:]
+ ObjectLocator locator = Mock()
+ def map = [:]
+ TypeCoercerProxy tc = Mock()
+ Runnable value = Mock()
+
+ MappedConfiguration config = new ValidatingMappedConfigurationWrapper(Runnable, locator, tc, map, null, SERVICE_ID, cd, Class, keyToContribution)
+
+ when:
+
+ config.add(Integer, value)
+
+ then:
+
+ tc.coerce(value, Runnable) >> value
+
+ map[Integer].is(value)
+ keyToContribution[Integer].is(cd)
+ }
+
+ def "an added value may be coerced to the correct type"() {
+
+ ContributionDef cd = Mock()
+ def value = "coerce-me"
+ Runnable coerced = Mock()
+
+ MappedConfiguration config = new ValidatingMappedConfigurationWrapper(Runnable, locator, tc, map, null, SERVICE_ID, cd, Class, keyToContribution)
+
+ when:
+
+ config.add(Integer, value)
+
+ then:
+
+ tc.coerce(value, Runnable) >> coerced
+
+ map[Integer].is(coerced)
+ keyToContribution[Integer].is(cd)
+ }
+
+ def ContributionDef newContributionDef(methodName) {
+
+ def proxyFactory = getService PlasticProxyFactory
+
+ return new ContributionDefImpl(SERVICE_ID, findMethod(methodName), false, proxyFactory, null, null);
+ }
+
+ def findMethod(name) {
+ return this.class.methods.find() { it.name == name }
+ }
+
+
+ public void contributionPlaceholder1() {
+
+ }
+
+ public void contributionPlaceholder2() {
+
+ }
+
+ def "may not contribute a duplicate key"() {
+ ContributionDef def1 = newContributionDef "contributionPlaceholder1"
+ ContributionDef def2 = newContributionDef "contributionPlaceholder2"
+
+ keyToContribution[Integer] = def1
+
+ MappedConfiguration config = new ValidatingMappedConfigurationWrapper(Runnable, locator, tc, map, null, SERVICE_ID, def2, Class, keyToContribution)
+
+ when:
+
+ config.add(Integer, "does-not-matter")
+
+ then:
+
+ IllegalArgumentException e = thrown()
+
+ e.message.contains "Service contribution (to service 'Baz') conflicts with existing contribution"
+
+ keyToContribution[Integer].is(def1)
+ map.isEmpty()
+ }
+
+ def "the contributed key may not be null"() {
+ ContributionDef cd = newContributionDef "contributionPlaceholder1"
+
+ MappedConfiguration config = new ValidatingMappedConfigurationWrapper(Runnable, locator, tc, map, null, SERVICE_ID, cd, Class, keyToContribution)
+
+ when:
+
+ config.add(null, "does-not-matter")
+
+ then:
+
+ NullPointerException e = thrown()
+
+ e.message == "Key for service contribution (to service '$SERVICE_ID') was null."
+ }
+
+ def "adding a key of the wrong type is an exception"() {
+ ContributionDef cd = newContributionDef "contributionPlaceholder1"
+
+ MappedConfiguration config = new ValidatingMappedConfigurationWrapper(Runnable, locator, tc, map, null, SERVICE_ID, cd, Class, keyToContribution)
+
+ when:
+
+ config.add("java.util.List", "does-not-matter")
+
+ then:
+
+ IllegalArgumentException e = thrown()
+
+ e.message == "Key for service contribution (to service 'Baz') was an instance of java.lang.String, but the expected key type was java.lang.Class."
+ }
+
+ def "contributing a null value is an exception"() {
+ ContributionDef cd = newContributionDef "contributionPlaceholder1"
+
+ MappedConfiguration config = new ValidatingMappedConfigurationWrapper(Runnable, locator, tc, map, null, SERVICE_ID, cd, Class, keyToContribution)
+
+ when:
+
+ config.add(SQLException, null)
+
+ then:
+
+ NullPointerException e = thrown()
+
+ e.message == "Service contribution (to service 'Baz') was null."
+ map.isEmpty()
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingOrderedConfigurationWrapperSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingOrderedConfigurationWrapperSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingOrderedConfigurationWrapperSpec.groovy
new file mode 100644
index 0000000..3255c49
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/ValidatingOrderedConfigurationWrapperSpec.groovy
@@ -0,0 +1,82 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.ObjectLocator
+import org.apache.tapestry5.ioc.OrderedConfiguration
+import org.apache.tapestry5.ioc.internal.TypeCoercerProxy
+import org.apache.tapestry5.ioc.internal.ValidatingOrderedConfigurationWrapper
+import org.apache.tapestry5.ioc.internal.util.Orderer
+import org.slf4j.Logger
+import spock.lang.Specification
+
+class ValidatingOrderedConfigurationWrapperSpec extends Specification {
+
+ def "contribution of a coerceable instance"() {
+ Runnable contribution = Mock()
+ Runnable coerced = Mock()
+ Runnable pre = Mock()
+ Runnable post = Mock()
+ Logger logger = Mock()
+ TypeCoercerProxy tc = Mock()
+
+ def orderer = new Orderer(logger)
+
+ orderer.add "pre", pre
+ orderer.add "post", post
+
+ OrderedConfiguration config = new ValidatingOrderedConfigurationWrapper(Runnable, null, tc, orderer, null, null)
+
+ when:
+
+ config.add("id", contribution, "after:pre", "before:post")
+
+ then:
+
+ 1 * tc.coerce(contribution, Runnable) >> coerced
+
+ orderer.ordered == [pre, coerced, post]
+ }
+
+ def "contribution of a valid type"() {
+ Map instance = new HashMap()
+ Map pre = Mock()
+ Map post = Mock()
+ ObjectLocator locator = Mock()
+ TypeCoercerProxy tc = Mock()
+ Logger logger = Mock()
+
+ def orderer = new Orderer(logger)
+
+ orderer.add "pre", pre
+ orderer.add "post", post
+
+ OrderedConfiguration config = new ValidatingOrderedConfigurationWrapper(Map, locator, tc, orderer, null, null)
+
+ when:
+
+ config.addInstance("id", HashMap, "after:pre", "before:post")
+
+ then:
+
+ 1 * locator.autobuild(HashMap) >> instance
+ 1 * tc.coerce(instance, Map) >> instance
+
+ orderer.ordered == [pre, instance, post]
+ }
+
+ def "null objected passed through"() {
+ Logger logger = Mock()
+
+ Orderer orderer = new Orderer(logger)
+ OrderedConfiguration config = new ValidatingOrderedConfigurationWrapper(Runnable, null, null, orderer, null, null)
+
+ when:
+
+ config.add("id", null)
+
+ then:
+
+ orderer.ordered.empty
+
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/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
deleted file mode 100644
index 25dc3f9..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AbstractRegistrySpecification.groovy
+++ /dev/null
@@ -1,31 +0,0 @@
-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;
-
- /**
- * Constructs a new {@link Registry} using the indicated module classes.
- * The Registry will be shutdown after each feature method.
- *
- * @param moduleClasses classes to include when building the 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/a1bef869/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
deleted file mode 100644
index 7115ae9..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AbstractSharedRegistrySpecification.groovy
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.apache.tapestry5.ioc
-
-import spock.lang.Specification
-
-import java.lang.reflect.Method
-
-/**
- * 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.
-
- protected Method findMethod(Object subject, String methodName) {
- def method = subject.class.methods.find { it.name == methodName }
-
- assert method != null
-
- return method
- }
-
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AdvisorsSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AdvisorsSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AdvisorsSpec.groovy
deleted file mode 100644
index d4abc93..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AdvisorsSpec.groovy
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.apache.tapestry5.ioc
-
-import org.apache.tapestry5.ioc.internal.AdviseByMarkerModule
-import org.apache.tapestry5.ioc.internal.AdviseByMarkerModule2
-
-
-class AdvisorsSpec extends AbstractRegistrySpecification {
-
- def "advisor methods must return void"() {
- when:
-
- buildRegistry NonVoidAdvisorMethodModule
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Advise method org.apache.tapestry5.ioc.NonVoidAdvisorMethodModule.adviseFoo(MethodAdviceReceiver)"
- e.message.contains "does not return void"
- }
-
- def "advisor methods must take a MethodAdviceReceiver parameter"() {
- when:
-
- buildRegistry AdviceMethodMissingAdvisorParameterModule
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Advise method org.apache.tapestry5.ioc.AdviceMethodMissingAdvisorParameterModule.adviseBar()"
- e.message.contains "must take a parameter of type org.apache.tapestry5.ioc.MethodAdviceReceiver."
- }
-
- def "adding advice to services"() {
- buildRegistry AdviceDemoModule
-
- when:
-
- def g = getService Greeter
-
- then:
-
- g.greeting == "ADVICE IS EASY!"
- }
-
- def "methods marked with @Advise are advisor methods"() {
-
- buildRegistry GreeterModule2, AdviseByMarkerModule
-
- when:
-
- def green = getService "GreenGreeter", Greeter
-
- then:
-
- green.greeting == "gamma[beta[alpha[Green]]]"
- }
-
- def "@Advise with @Local only advises services in the same module"() {
- buildRegistry GreeterModule2, AdviseByMarkerModule
-
- when:
-
- def red = getService "RedGreeter", Greeter
-
- then:
-
- red.greeting == "delta[Red]"
- }
-
- def "@Advise with id attribute"() {
- buildRegistry AdviseByMarkerModule2
-
- when:
-
- def red = getService "RedGreeter", Greeter
-
- then:
-
- red.greeting == "beta[alpha[Red]]"
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AutobuildSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AutobuildSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AutobuildSpec.groovy
deleted file mode 100644
index d5aa6a5..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/AutobuildSpec.groovy
+++ /dev/null
@@ -1,171 +0,0 @@
-package org.apache.tapestry5.ioc
-
-import org.apache.tapestry5.ioc.internal.ExceptionInConstructorModule
-
-class AutobuildSpec extends AbstractRegistrySpecification {
-
- def "ensure that services defined with bind() are automatically built"() {
- buildRegistry AutobuildModule
-
- def sh = getService StringHolder
-
- when:
-
- sh.value = "Foo"
-
- then:
-
- sh.value == "Foo"
- }
-
- def "check reporting of exception in autobuilt service constructor"() {
- buildRegistry ExceptionInConstructorModule
-
- def pingable = getService Pingable
-
- when:
-
- pingable.ping()
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Error invoking constructor"
- e.message.contains "ExceptionInConstructorServiceImpl()"
- e.message.contains "Yes, we have no tomatoes."
- }
-
- def "bind() finds the default Impl class"() {
- buildRegistry ConventionModule
-
- def holder = getService StringHolder
-
- when:
-
- // This proves we can invoke methods, meaning that an implementation was found.
-
- holder.value = "Bar"
-
- then:
-
- holder.value == "Bar"
- }
-
- def "validate exception reporting for no default implementation found"() {
- when:
-
- buildRegistry ConventionModuleImplementationNotFound
-
- then:
-
- RuntimeException e = thrown()
- e.message.contains "Could not find default implementation class org.apache.tapestry5.ioc.StringTransformerImpl."
- e.message.contains "Please provide this class, or bind the service interface to a specific implementation class."
- }
-
- def "validate exception reporting for incorrect implementation (that does not implement service interface)"() {
- when:
-
- buildRegistry ConventionFailureModule
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "No service implements the interface ${Pingable.name}"
- }
-
- def "service builder method can use ServiceResources.autobuild()"() {
- buildRegistry ServiceBuilderAutobuilderModule
-
- def holder = getService StringHolder
-
- when:
-
- holder.value = "Foo"
-
- then:
-
- holder.value == "Foo"
- }
-
- def "ensure that Registry.autobuild() works"() {
-
- buildRegistry()
-
- when:
-
- def holder = autobuild StringHolderImpl
-
- // This test should go further and verify that injections into StringHolderImpl work.
-
- then:
-
- holder.class == StringHolderImpl
-
- when:
-
- holder.value = "Foo"
-
- then:
-
- holder.value == "Foo"
- }
-
- def "ensure that Registry.autobuild() works (with a description)"() {
- buildRegistry()
-
- when:
-
- def holder = autobuild "Building StringHolderImpl", StringHolderImpl
-
- // This test should go further and verify that injections into StringHolderImpl work.
-
- then:
-
- holder.class == StringHolderImpl
- }
-
- def "verify exception when autobuild service implementation is not valid"() {
- buildRegistry ServiceBuilderAutobuilderModule
-
- def pingable = getService Pingable
-
- when:
-
- pingable.ping()
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Class org.apache.tapestry5.ioc.UnbuildablePingable does not contain a public constructor needed to autobuild."
- }
-
- def "verify exception when autobuild class has not valid constructor"() {
- buildRegistry()
-
- when:
-
- autobuild UnbuildablePingable
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Class org.apache.tapestry5.ioc.UnbuildablePingable does not contain a public constructor needed to autobuild."
- }
-
- def "a service build method may include a parameter with @Autobuild"() {
- buildRegistry AutobuildInjectionModule
-
- when:
-
- def tx = getService StringTransformer
-
- then:
-
- tx.transform('Hello, ${fred}') == "Hello, flintstone"
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/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
deleted file mode 100644
index 9344b13..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/BaseLocatableSpec.groovy
+++ /dev/null
@@ -1,33 +0,0 @@
-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/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ConfigurationsSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ConfigurationsSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ConfigurationsSpec.groovy
deleted file mode 100644
index d0db942..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ConfigurationsSpec.groovy
+++ /dev/null
@@ -1,316 +0,0 @@
-package org.apache.tapestry5.ioc
-
-import org.apache.tapestry5.ioc.internal.AlphabetModule
-import org.apache.tapestry5.ioc.internal.AlphabetModule2
-import org.apache.tapestry5.ioc.services.SymbolSource
-import org.apache.tapestry5.ioc.util.NonmatchingMappedConfigurationOverrideModule
-
-/** Integration tests for various types of service configurations. */
-class ConfigurationsSpec extends AbstractRegistrySpecification {
-
- def "all contributions to unordered configuration are collected"() {
-
- buildRegistry FredModule, BarneyModule
-
- when:
-
- def holder = getService "UnorderedNames", NameListHolder
-
- then:
-
- // We don't know the actual contribution order, the impl sorts them. Just
- // check they are all present.
-
- holder.names == ["Beta", "Gamma", "UnorderedNames"]
- }
-
- def "all contributions to order configuration are collected"() {
- buildRegistry FredModule, BarneyModule
-
- when:
-
- def holder = getService "OrderedNames", NameListHolder
-
- then:
-
- holder.names == ["BARNEY", "FRED"]
- }
-
- def "all contribution to mapped configuration are collected"() {
-
- buildRegistry FredModule, BarneyModule
-
- def sizer = getService "Sizer", Sizer
-
- expect:
-
- // The contributions map different Classes to strategies; this demonstrates
- // that all contributions have been mapped and provided to Sizer service impl.
-
- sizer.size(null) == 0
-
- sizer.size([1, 2, 3]) == 3
-
- sizer.size([fred: "flintstone", barney: "rubble"]) == 2
-
- sizer.size(this) == 1
- }
-
- def "can contribute a class to an unordered configuration"() {
- buildRegistry ContributeByClassModule
-
- when:
-
- def tx = getService "MasterStringTransformer", StringTransformer
-
- then:
-
- tx.transform("Tapestry") == "TAPESTRY"
- }
-
- def "can contribute a class to an ordered configuration"() {
- buildRegistry ContributeByClassModule
-
- when:
-
- def tx = getService "StringTransformerChain", StringTransformer
-
- then:
-
- tx.transform("Tapestry") == "TAPESTRY"
- }
-
- def "can contribute class to a mapped configuration"() {
- buildRegistry ContributeByClassModule
-
- when:
-
- def tx = getService "MappedStringTransformer", StringTransformer
-
- then:
-
- tx.transform("Tapestry") == "TAPESTRY"
- }
-
- def "contribution to an unknown configuration is detected as an exception"() {
- when:
- buildRegistry InvalidContributeDefModule
- then:
- IllegalArgumentException e = thrown()
-
- e.message.contains "Contribution org.apache.tapestry5.ioc.InvalidContributeDefModule.contributeDoesNotExist(Configuration)"
- e.message.contains "is for service 'DoesNotExist', which does not exist."
- }
-
- def "a value in an ordered configuration may be overridden"() {
- buildRegistry FredModule, BarneyModule, ConfigurationOverrideModule
-
- when:
-
- def holder = getService "OrderedNames", NameListHolder
-
- then:
-
- holder.names == ["BARNEY", "WILMA", "Mr. Flintstone"]
- }
-
- def "an override value in an ordered configuration must match a normally contributed value"() {
- buildRegistry FredModule, BarneyModule, FailedConfigurationOverrideModule
-
- def holder = getService "OrderedNames", NameListHolder
-
- when:
-
-
- holder.names
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Failure processing override from org.apache.tapestry5.ioc.FailedConfigurationOverrideModule.contributeOrderedNames(OrderedConfiguration)"
- e.message.contains "Override for object 'wilma' is invalid as it does not match an existing object."
- }
-
- def "a contribution to an ordered configuration may only be overridden once"() {
- buildRegistry FredModule, BarneyModule, ConfigurationOverrideModule, DuplicateConfigurationOverrideModule
-
- def holder = getService "OrderedNames", NameListHolder
-
- when:
-
-
- holder.names
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Error invoking service contribution method"
- e.message.contains "Contribution 'fred' has already been overridden"
- }
-
- def "contributions to mapped configurations may be overridden"() {
- buildRegistry FredModule, BarneyModule, ConfigurationOverrideModule
-
- when:
-
- def sl = getService StringLookup
-
- then:
-
- sl.keys() == ["barney", "betty", "fred"]
- sl.lookup("fred") == "Mr. Flintstone"
- }
-
- def "mapped configuration overrides must match an existing value"() {
- buildRegistry FredModule, BarneyModule, NonmatchingMappedConfigurationOverrideModule
-
- def sl = getService StringLookup
-
- when:
-
- sl.keys()
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Override for key alley cat (at org.apache.tapestry5.ioc.util.NonmatchingMappedConfigurationOverrideModule.contributeStringLookup(MappedConfiguration)"
- e.message.contains "does not match an existing key"
- }
-
- def "a contribution to a mapped configuration may only be overridden once"() {
- buildRegistry FredModule, BarneyModule, ConfigurationOverrideModule, DuplicateConfigurationOverrideModule
-
- def sl = getService StringLookup
-
- when:
-
- sl.keys()
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Error invoking service contribution method"
- e.message.contains "Contribution key fred has already been overridden"
- }
-
- def "support for @Contribute annotation"() {
-
- buildRegistry AlphabetModule, AlphabetModule2
-
- when:
-
- def greek = getService "Greek", NameListHolder
-
- then:
-
- greek.names == ["Alpha", "Beta", "Gamma", "Delta"]
-
- when:
-
- def anotherGreek = getService "AnotherGreek", NameListHolder
-
- then:
-
- anotherGreek.names == ["Alpha", "Beta", "Gamma", "Delta", "Epsilon"]
-
- when:
-
- def hebrew = getService "Hebrew", NameListHolder
-
- then:
-
- hebrew.names == ["Alef", "Bet", "Gimel", "Dalet", "He", "Vav"]
-
- when:
-
- def holder = getService "ServiceWithEmptyConfiguration", NameListHolder2
-
- then:
-
- holder.names.empty
- }
-
- def "contribute by @Contribute annotation to non-existent service"() {
- when:
-
- buildRegistry InvalidContributeDefModule2
-
- then:
-
- RuntimeException e = thrown()
-
- ["Contribution org.apache.tapestry5.ioc.InvalidContributeDefModule2.provideConfiguration(OrderedConfiguration)",
- "is for service 'interface org.apache.tapestry5.ioc.NameListHolder'",
- "qualified with marker annotations [",
- "interface org.apache.tapestry5.ioc.BlueMarker",
- "interface org.apache.tapestry5.ioc.RedMarker",
- "], which does not exist."].every { e.message.contains it}
- }
-
- def "contribute using @Contribute using invalid marker annotation is an exception"() {
- when:
- buildRegistry InvalidContributeDefModule3
- then:
- RuntimeException e = thrown()
-
- ["Contribution org.apache.tapestry5.ioc.InvalidContributeDefModule3.provideConfiguration(OrderedConfiguration)",
- "is for service 'interface org.apache.tapestry5.ioc.NameListHolder'",
- "qualified with marker annotations [interface org.apache.tapestry5.ioc.BlueMarker], which does not exist."].every
- { e.message.contains it}
- }
-
- def "ServiceResources are available to contribution methods"() {
- buildRegistry InjectionCheckModule
-
- when:
-
- def s = getService InjectionCheck
- def il = s.getValue "indirect-resources"
-
- then:
-
- s.logger.is(s.getValue("logger"))
-
- s.logger.is il.logger
- s.logger.is il.resources.logger
- }
-
-
- def "service id in contribute method is matched caselessly"() {
- buildRegistry CaseInsensitiveContributeMethodModule
-
- when:
-
- def ss = getService SymbolSource
-
- then:
-
- ss.valueForSymbol("it") == "works"
- }
-
- def "contributed values may be coerced to the correct type"() {
- buildRegistry ContributedValueCoercionModule
-
- when:
-
- def ss = getService SymbolSource
-
- then:
-
- ss.valueForSymbol("bool-true") == "true"
- ss.valueForSymbol("bool-false") == "false"
- ss.valueForSymbol("num-12345") == "12345"
- }
-
- def "@Optional contribution to an unknown service is not an error"() {
- when:
- buildRegistry OptionalContributionModule
-
- then:
- noExceptionThrown()
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/DecoratorsSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/DecoratorsSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/DecoratorsSpec.groovy
deleted file mode 100644
index 8dfa727..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/DecoratorsSpec.groovy
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.apache.tapestry5.ioc
-
-import org.apache.tapestry5.ioc.internal.DecorateByMarkerModule
-import org.apache.tapestry5.ioc.internal.DecorateByMarkerModule2
-
-/** Integration tests for service decorators and some related behaviors. */
-class DecoratorsSpec extends AbstractRegistrySpecification {
-
- def "verify order of service decorators"() {
- buildRegistry FredModule, BarneyModule
-
- def fred = getService "Fred", Runnable
- def list = getService DecoratorList
-
- when:
-
- fred.run()
-
- then:
-
- list.names == ["gamma", "beta", "alpha"]
- }
-
- def "decorators receive the delegate by the specific type"() {
-
- buildRegistry GreeterModule, SpecificDecoratorModule
-
- when:
-
- def g = getService "HelloGreeter", Greeter
-
- then:
-
- g.greeting == "HELLO"
- }
-
- def "a service builder method with @PreventServiceDecoration is not decorated"() {
- buildRegistry PreventDecorationModule
-
- when:
-
- def st = getService StringTransformer
-
- then:
-
- st.transform("tapestry") == "TAPESTRY"
- }
-
- def "Binding a service with explicit no decorations will ensure that the implementation is not decorated"() {
- buildRegistry PreventDecorationModule
-
- when:
-
- def g = getService Greeter
-
- then:
-
- g.greeting == "Greetings from ServiceIdGreeter."
- }
-
- def "@PreventServiceDecoration on a service implementation class ensures that the implementation is not decorated"() {
- buildRegistry PreventDecorationModule
-
- when:
-
- def rocket = getService Rocket
-
- then:
-
- rocket.countdown == "3, 2, 1, Launch!"
- }
-
- def "@Decorate marks a module method as a decorator method"() {
- buildRegistry GreeterModule2, DecorateByMarkerModule
-
- when:
-
- def green = getService "GreenGreeter", Greeter
-
- then:
-
- green.greeting == "Decorated by foo[Decorated by baz[Decorated by bar[Green]]]"
- }
-
- def "@Decorate with @Local only decorates services from the same module"() {
- buildRegistry GreeterModule2, DecorateByMarkerModule
-
- when:
-
- def red = getService "RedGreeter", Greeter
-
- then:
-
- red.greeting == "Decorated by barney[Red]"
- }
-
- def "@Decorate with id attribute"() {
- buildRegistry DecorateByMarkerModule2
-
- when:
-
- def green = getService "RedGreeter", Greeter
-
- then:
-
- green.greeting == "Decorated by beta[Decorated by alpha[Red]]"
- }
-
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/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
deleted file mode 100644
index 7175751..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/EagerLoadSpec.groovy
+++ /dev/null
@@ -1,20 +0,0 @@
-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/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/InjectionSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/InjectionSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/InjectionSpec.groovy
deleted file mode 100644
index 24952ac..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/InjectionSpec.groovy
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.apache.tapestry5.ioc
-
-class InjectionSpec extends AbstractRegistrySpecification {
-
- def "symbol in @Inject is expanded"() {
-
- buildRegistry GreeterModule
-
- when:
-
- def greeter = getService "Greeter", Greeter
-
- then:
-
- greeter.greeting == "Hello"
- greeter.toString() == "<Proxy for Greeter(org.apache.tapestry5.ioc.Greeter)>"
- }
-
- def "injection by marker with single match"() {
-
- buildRegistry GreeterModule
-
- when:
-
- def greeter = getService "InjectedBlueGreeter", Greeter
-
- then:
-
- greeter.greeting == "Blue"
- }
-
- def "verify exception for inject by marker with multiple matches"() {
- buildRegistry GreeterModule
-
- def greeter = getService "InjectedRedGreeter", Greeter
-
- when:
-
- greeter.greeting
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Unable to locate a single service assignable to type org.apache.tapestry5.ioc.Greeter with marker annotation(s) org.apache.tapestry5.ioc.RedMarker"
- e.message.contains "org.apache.tapestry5.ioc.GreeterModule.buildRedGreeter1()"
- e.message.contains "org.apache.tapestry5.ioc.GreeterModule.buildRedGreeter2()"
- }
-
- def "verify exception for injection by marker and no matches"() {
- buildRegistry GreeterModule
-
- def greeter = getService "InjectedYellowGreeter", Greeter
-
- when:
-
- greeter.greeting
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Exception constructing service"
- e.message.contains "Unable to locate any service assignable to type org.apache.tapestry5.ioc.Greeter with marker annotation(s) org.apache.tapestry5.ioc.YellowMarker."
- }
-
- def "recursion handling injections (due to MasterObjectProvider) is detected"() {
-
- buildRegistry CyclicMOPModule
-
- def trigger = getService "Trigger", Runnable
-
- when:
-
- trigger.run()
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Construction of service 'TypeCoercer' has failed due to recursion"
- }
-
- def "A field may be annotated with @InjectResource to receive resources"() {
-
- buildRegistry FieldResourceInjectionModule
-
- when:
-
- def s = getService FieldResourceService
-
- then:
-
- s.serviceId == "FieldResourceService"
-
- s.labels == ["Barney", "Betty", "Fred", "Wilma"]
- }
-
- def "methods with @PostInjection are invoked and can be passed further injections"() {
- buildRegistry PostInjectionMethodModule
-
- when:
-
- def g = getService Greeter
-
- then:
-
- g.greeting == "Greetings from ServiceIdGreeter."
- }
-
- def "a service may be overridden by contributing to ServiceOverride"() {
- buildRegistry GreeterServiceOverrideModule
-
- when:
-
- def g = getObject Greeter, null
-
- then:
-
- g.greeting == "Override Greeting"
- }
-
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ManifestProcessingSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ManifestProcessingSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ManifestProcessingSpec.groovy
deleted file mode 100644
index d466772..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ManifestProcessingSpec.groovy
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.apache.tapestry5.ioc
-
-import spock.lang.Specification
-
-
-class ManifestProcessingSpec extends Specification {
-
- def "invalid class in manifest"() {
-
- File fakejar = new File("src/test/fakejar")
-
- expect:
-
- // This is more to verify the module execution environment
- fakejar.exists()
- fakejar.isDirectory()
-
- when:
-
- URL url = fakejar.toURL()
- URLClassLoader loader = new URLClassLoader([url] as URL[], Thread.currentThread().contextClassLoader)
-
- RegistryBuilder builder = new RegistryBuilder(loader)
-
- IOCUtilities.addDefaultModules(builder)
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Exception loading module(s) from manifest"
- e.message.contains "Failure loading Tapestry IoC module class does.not.exist.Module"
-
-
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ModuleInstantiationSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ModuleInstantiationSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ModuleInstantiationSpec.groovy
deleted file mode 100644
index 4b5f40b..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ModuleInstantiationSpec.groovy
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.apache.tapestry5.ioc
-
-
-class ModuleInstantiationSpec extends AbstractRegistrySpecification {
-
- def setup() {
- StaticModule.reset()
- }
-
- def "module class is not instantiated when invoking static builder method"() {
- buildRegistry StaticModule
-
- def fred = getService "Fred", Runnable
-
- when:
-
- fred.run()
-
- then:
-
- !StaticModule.instantiated
- StaticModule.fredRan
- }
-
- def "module class is not instantiated when invoking static decorator method"() {
- buildRegistry StaticModule
-
- def barney = getService "Barney", Runnable
-
- when:
-
- barney.run()
-
- then:
-
- !StaticModule.instantiated
- StaticModule.decoratorRan
- }
-
- def "module class is not instantiated when invoking a static contributor method"() {
- buildRegistry StaticModule
-
- def holder = getService "Names", NameListHolder
-
- when:
-
- assert holder.names == ["Fred"]
-
- then:
-
- !StaticModule.instantiated
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/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
deleted file mode 100644
index 18c0cbe..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/OrderedConstraintBuilderSpec.groovy
+++ /dev/null
@@ -1,30 +0,0 @@
-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/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/PerThreadScopeSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/PerThreadScopeSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/PerThreadScopeSpec.groovy
deleted file mode 100644
index 9533862..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/PerThreadScopeSpec.groovy
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.apache.tapestry5.ioc
-
-
-class PerThreadScopeSpec extends AbstractRegistrySpecification {
-
- def "ensure that different threads see different implementations"() {
- def threadExecuted = false
-
- buildRegistry PerThreadModule
-
- def holder = getService StringHolder
-
- when:
-
- holder.value = "fred"
-
- then:
-
- holder.value == "fred"
-
- when:
-
- Thread t = new Thread({
- assert holder.value == null
-
- holder.value = "barney"
-
- assert holder.value == "barney"
-
- threadExecuted = true
-
- cleanupThread()
- })
-
- t.start()
- t.join()
-
- then:
-
- threadExecuted
- holder.value == "fred"
- }
-
- def "services with out a service interface must use the default scope"() {
-
- buildRegistry ScopeMismatchModule
-
- when:
-
- getService StringBuilder
-
- then:
-
- Exception e = thrown()
-
- e.message.contains "Error building service proxy for service 'ScopeRequiresAProxyAndNoInterfaceIsProvided'"
- e.message.contains "Service scope 'perthread' requires a proxy"
- }
-
- def "ensure that perthread services are discarded by cleanupThread()"() {
- buildRegistry PerThreadModule
-
- when:
-
- def holder = getService StringHolder
-
- then:
-
- holder.value == null
-
- when:
-
- holder.value = "fred"
-
- then:
-
- holder.value == "fred"
-
- when:
-
- cleanupThread()
-
- then:
-
- holder.value == null
-
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/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
deleted file mode 100644
index fd3acad..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistryBuilderSpec.groovy
+++ /dev/null
@@ -1,95 +0,0 @@
-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:
-
- 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/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistryConstructionAndRuntimeErrorsSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistryConstructionAndRuntimeErrorsSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistryConstructionAndRuntimeErrorsSpec.groovy
deleted file mode 100644
index 70da305..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistryConstructionAndRuntimeErrorsSpec.groovy
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.apache.tapestry5.ioc
-
-import org.apache.tapestry5.ioc.internal.ExtraPublicConstructorsModule
-import org.apache.tapestry5.ioc.internal.PrivateConstructorModule
-import org.apache.tapestry5.ioc.internal.UpcaseService
-
-/**
- * A few tests that are easiest (or even just possible) by building a Registry and trying out a few
- * things.
- */
-class RegistryConstructionAndRuntimeErrorsSpec extends AbstractRegistrySpecification {
-
- def "duplicate service names are a failure"() {
- when:
-
- buildRegistry FredModule, DuplicateFredModule
-
- then:
-
- RuntimeException ex = thrown()
-
- ex.message.startsWith "Service id 'Fred' has already been defined by"
-
- // Can't check entire message, can't guarantee what order modules will be processed in
- }
-
- def "service with unknown scope fails at service proxy creation"() {
- buildRegistry UnknownScopeModule
-
- when:
-
- getService "UnknownScope", Runnable
-
- then:
-
- Exception e = thrown()
-
- e.message.contains "Error building service proxy for service 'UnknownScope'"
- e.message.contains "Unknown service scope 'magic'"
- }
-
- def "ensure that recursive module construction is detected"() {
-
- buildRegistry RecursiveConstructorModule
-
- def runnable = getService "Runnable", Runnable
-
- when:
-
- // We can get the proxy, but invoking a method causes
- // the module to be instantiated ... but that also invokes a method on
- // the proxy.
-
- runnable.run()
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "has failed due to recursion"
- }
-
- def "a module class must have a public constructor"() {
-
- buildRegistry PrivateConstructorModule
-
- def trigger = getService "Trigger", Runnable
-
- when:
-
- trigger.run()
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Module class org.apache.tapestry5.ioc.internal.PrivateConstructorModule does not contain any public constructors."
- }
-
- def "extra public constructors on a module class are ignored"() {
-
- buildRegistry ExtraPublicConstructorsModule
-
- when: "forcing the module to be instantiated"
-
- def upcase = getService UpcaseService
-
- then: "no exception when instantiating the module"
-
- upcase.upcase('Hello, ${fred}') == "HELLO, FLINTSTONE"
- }
-
- def "extra public methods on module classes are exceptions"() {
- when:
- buildRegistry ExtraMethodsModule
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Module class org.apache.tapestry5.ioc.ExtraMethodsModule contains unrecognized public methods: "
- e.message.contains "thisMethodIsInvalid()"
- e.message.contains "soIsThisMethod()"
- }
-
- def "can not use withSimpleId() when binding a service interface to a ServiceBuilder callback"() {
- when:
-
- buildRegistry NoImplementationClassForSimpleIdModule
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "No defined implementation class to generate simple id from"
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistrySpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistrySpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistrySpec.groovy
deleted file mode 100644
index d8432cc..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/RegistrySpec.groovy
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.apache.tapestry5.ioc
-
-import org.apache.tapestry5.ioc.internal.services.StartupModule2
-
-class RegistrySpec extends AbstractRegistrySpecification {
-
- def "symbol in Registry.getService() is expanded"() {
-
- buildRegistry GreeterModule
-
- when:
-
- def greeter = getService '${greeter}', Greeter
-
- then:
-
- greeter.greeting == "Hello"
- greeter.toString() == "<Proxy for HelloGreeter(org.apache.tapestry5.ioc.Greeter)>"
- }
-
- def "circular module references are ignored"() {
- buildRegistry HelterModule
-
- when:
-
- def helter = getService "Helter", Runnable
- def skelter = getService "Skelter", Runnable
-
- then:
-
- !helter.is(skelter)
- }
-
- def "@Startup annotation support"() {
- when:
-
- buildRegistry StartupModule2
-
- then:
-
- !StartupModule2.staticStartupInvoked
- !StartupModule2.instanceStartupInvoked
-
- when:
-
- performRegistryStartup()
-
- then:
-
- StartupModule2.staticStartupInvoked
- StartupModule2.instanceStartupInvoked
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/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
deleted file mode 100644
index 6838d81..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ReloadSpec.groovy
+++ /dev/null
@@ -1,401 +0,0 @@
-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/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceActivityScoreboardSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceActivityScoreboardSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceActivityScoreboardSpec.groovy
deleted file mode 100644
index 98a4914..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceActivityScoreboardSpec.groovy
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.apache.tapestry5.ioc
-
-import org.apache.tapestry5.ioc.services.ServiceActivityScoreboard
-import org.apache.tapestry5.ioc.services.Status
-import org.apache.tapestry5.ioc.services.TypeCoercer
-
-class ServiceActivityScoreboardSpec extends AbstractRegistrySpecification {
-
- def "general cursory test"() {
- buildRegistry GreeterModule
-
- def scoreboard = getService ServiceActivityScoreboard
-
- when:
-
- def tc = getService TypeCoercer
-
- tc.coerce "123", Integer
-
- getService "BlueGreeter", Greeter
-
- then:
-
- def activity = scoreboard.serviceActivity
-
- !activity.empty
-
- activity.find({ it.serviceId == "TypeCoercer" }).status == Status.REAL
-
- def ppf = activity.find { it.serviceId == "PlasticProxyFactory" }
- ppf.status == Status.BUILTIN
-
-
- def rg = activity.find { it.serviceId == "RedGreeter1" }
- rg.status == Status.DEFINED
- rg.markers.contains RedMarker
- !rg.markers.contains(BlueMarker)
-
- def bg = activity.find { it.serviceId == "BlueGreeter"}
-
- bg.status == Status.VIRTUAL
- bg.markers.contains BlueMarker
- !bg.markers.contains(RedMarker)
- }
-
- def "scoreboard entry for perthread services is itself perthread"() {
-
- buildRegistry GreeterModule, PerThreadModule
-
- def scoreboard = getService ServiceActivityScoreboard
-
- def holder = getService StringHolder
-
- when:
-
- Thread t = new Thread({
- holder.value = "barney"
- assert holder.value == "barney"
-
- assert scoreboard.serviceActivity.find({ it.serviceId == "StringHolder"}).status == Status.REAL
-
- cleanupThread()
- })
-
- t.start()
- t.join()
-
- then:
-
- scoreboard.serviceActivity.find({ it.serviceId == "StringHolder"}).status == Status.VIRTUAL
-
-
- }
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceBinderSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceBinderSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceBinderSpec.groovy
deleted file mode 100644
index 30448fc..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceBinderSpec.groovy
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.apache.tapestry5.ioc
-
-
-class ServiceBinderSpec extends AbstractRegistrySpecification {
-
- def "a service implementation may be created via a ServiceBuilder callback"() {
- buildRegistry ServiceBuilderModule
-
- when:
-
- def g = getService "Greeter", Greeter
-
- then:
- g.greeting == "Greetings from service Greeter."
- }
-
- def "verify exception reporting for ServiceBuilder that throws an exception"() {
-
- buildRegistry ServiceBuilderModule
-
- def g = getService "BrokenGreeter", Greeter
-
- when:
-
- g.greeting
-
- then:
-
- Exception e = thrown()
-
- e.message.contains "Exception constructing service 'BrokenGreeter'"
- e.message.contains "Failure inside ServiceBuilder callback."
- }
-
-}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a1bef869/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceLookupSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceLookupSpec.groovy b/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceLookupSpec.groovy
deleted file mode 100644
index 5a9828a..0000000
--- a/tapestry-ioc/src/test/groovy/org/apache/tapestry5/ioc/ServiceLookupSpec.groovy
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.apache.tapestry5.ioc
-
-import org.apache.tapestry5.ioc.services.Builtin
-import org.apache.tapestry5.ioc.services.TypeCoercer
-
-import java.sql.PreparedStatement
-
-class ServiceLookupSpec extends AbstractRegistrySpecification {
-
- def "access to services by id is case insensitive"() {
-
- buildRegistry FredModule
-
- when:
-
- def r1 = getService "Fred", Runnable
- def r2 = getService "FRED", Runnable
-
- then:
-
- r1.is r2
-
- }
-
- def "verify exception when accessing service by unknown id"() {
-
- buildRegistry()
-
- when:
-
- getService "PeekABoo", Runnable
-
- then:
-
- RuntimeException e = thrown()
-
- e.message.contains "Service id 'PeekABoo' is not defined by any module."
- }
-
- def "verify exception when accessing a service by type and there are no matching services"() {
-
- buildRegistry()
-
- when:
-
- getService PreparedStatement
-
- then:
-
- RuntimeException e = thrown()
-
- e.message == "No service implements the interface java.sql.PreparedStatement."
- }
-
- def "verify exception when accessing a service by type and there are multiple matches"() {
- buildRegistry DuplicateServiceTypeModule
-
- when:
-
- getService Pingable
-
- then:
-
- RuntimeException e = thrown()
-
- e.message == "Service interface org.apache.tapestry5.ioc.Pingable is matched by 2 services: Barney, Fred. Automatic dependency resolution requires that exactly one service implement the interface."
- }
-
- def "access to builtin service via marker annotation"() {
- Builtin annotation = Mock()
- AnnotationProvider ap = Mock()
-
- buildRegistry()
-
- def tc1 = getService "TypeCoercer", TypeCoercer
-
- when:
-
- def tc2 = getObject TypeCoercer, ap
-
- then:
-
- 1 * ap.getAnnotation(Builtin) >> annotation
-
- tc2.is tc1
- }
-
- def "lookup service by type and markers"() {
- buildRegistry GreeterModule
-
- when:
-
- def blue = getService Greeter, BlueMarker
-
- then:
-
- blue.greeting == "Blue"
- }
-
- def "use of the @Local annotation disambiguates from multiple services"() {
- buildRegistry GreeterModule, LocalModule
-
-
- when:
-
- // The implementation of this class relies on a @Local injection to find
- // a specific Greeter implementation
-
- StringHolder holder = getService "LocalGreeterHolder", StringHolder
-
- then:
-
- holder.value == "Hello, y'all!"
- }
-
-}