Implementation of proposed Test Entities to allow testing directly from blueprints
Proposal :: http://mail-archives.apache.org/mod_mbox/incubator-brooklyn-dev/201510.mbox/%3CE185CA37-E693-4733-8DE1-208872BC1978%40cloudsoftcorp.com%3E Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/0e8c31df Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/0e8c31df Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/0e8c31df Branch: refs/heads/master Commit: 0e8c31dfaf5d2a3a1c2e90102b739d46142d91fe Parents: 6c4b517 Author: Mark McKenna <[email protected]> Authored: Mon Nov 2 17:17:07 2015 +0000 Committer: Mark McKenna <[email protected]> Committed: Mon Nov 9 20:56:21 2015 +0000 ---------------------------------------------------------------------- .../brooklyn-sandbox-test-framework/README.md | 57 ++++ .../etc/exampl-catalog.bom | 15 ++ .../etc/example-catalog-test.bom | 22 ++ .../etc/nginx-test-examples.yml | 98 +++++++ .../etc/testhttpcall-examples.yml | 34 +++ .../etc/tomcat-test-examples.yml | 45 ++++ sandbox/brooklyn-sandbox-test-framework/pom.xml | 75 ++++++ .../brooklyn/test/framework/AbstractTest.java | 50 ++++ .../brooklyn/test/framework/BaseTest.java | 34 +++ .../test/framework/ParallelTestCase.java | 13 + .../test/framework/ParallelTestCaseImpl.java | 130 +++++++++ .../brooklyn/test/framework/TestCase.java | 12 + .../brooklyn/test/framework/TestCaseImpl.java | 61 +++++ .../brooklyn/test/framework/TestEffector.java | 33 +++ .../test/framework/TestEffectorImpl.java | 91 +++++++ .../brooklyn/test/framework/TestHttpCall.java | 28 ++ .../test/framework/TestHttpCallImpl.java | 98 +++++++ .../brooklyn/test/framework/TestSensor.java | 27 ++ .../brooklyn/test/framework/TestSensorImpl.java | 144 ++++++++++ .../test/framework/TestEffectorTest.java | 106 ++++++++ .../brooklyn/test/framework/TestEntity.java | 55 ++++ .../brooklyn/test/framework/TestEntityImpl.java | 39 +++ .../brooklyn/test/framework/TestSensorTest.java | 270 +++++++++++++++++++ 23 files changed, 1537 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/README.md ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/README.md b/sandbox/brooklyn-sandbox-test-framework/README.md new file mode 100644 index 0000000..991ec48 --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/README.md @@ -0,0 +1,57 @@ +# Entities + +## TestCase +A logical grouping for tests eg Restart tests +``` +type: org.apache.brooklyn.test.framework.TestCase + name: Stop Test + brooklyn.children: + - *** + - *** +``` + +## TestSensor +Entity that tests a sensor value on another entity eg service.isUp == TRUE + +#### Configuration +| Key | Description | Required | +| --- | ----------- | -------- | +| target | The target entity to test | yes (no if *targetId* is supplied) | +| targetId | The id of the target entity to test | yes (no if *target* is supplied) | +| assert | Assertions to be evaluated | yes | +| timeout | The duration to wait on a result | no | + +``` +type: org.apache.brooklyn.test.framework.TestSensor +target: $brooklyn:component("nginx1") +sensor: service.isUp +equals: true +timeout: 5m +``` + +## TestEffector +Entity that invokes an effector on another entity eg restart + +#### Configuration +| Key | Description | Required | +| --- | ----------- | -------- | +| target | The target entity to effect | yes (no if *targetId* is supplied) | +| targetId | The id of the target entity to effect | yes (no if *target* is supplied) | +| effector | The name of the effector to invoke | yes | +| params | Parameters to pass to the effector | no | +| timeout | The duration to wait on a response from an effector | no | + +#### Sensors +| Key | Description | +| --- | ----------- | +| result | The result of invoking the effector (null if no result) | + +``` +type: org.apache.brooklyn.test.framework.TestEffector +name: Deploy WAR +target: $brooklyn:component("tomcat") +effector: deploy +params: + url: https://tomcat.apache.org/tomcat-6.0-doc/appdev/sample/sample.war + targetName: sample1 +``` \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/etc/exampl-catalog.bom ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/etc/exampl-catalog.bom b/sandbox/brooklyn-sandbox-test-framework/etc/exampl-catalog.bom new file mode 100644 index 0000000..ab7e54b --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/etc/exampl-catalog.bom @@ -0,0 +1,15 @@ +brooklyn.catalog: + id: simple-tomcat + version: 1.0 + itemType: template + iconUrl: http://tomcat.apache.org/images/tomcat.png + name: Simple Tomcat + license: Apache-2.0 + item: + brooklyn.config: + simple.confg: someValue + services: + - type: org.apache.brooklyn.entity.webapp.tomcat.TomcatServer + id: tomcat + name: Tomcat + war: https://tomcat.apache.org/tomcat-6.0-doc/appdev/sample/sample.war \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/etc/example-catalog-test.bom ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/etc/example-catalog-test.bom b/sandbox/brooklyn-sandbox-test-framework/etc/example-catalog-test.bom new file mode 100644 index 0000000..0605f9d --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/etc/example-catalog-test.bom @@ -0,0 +1,22 @@ +brooklyn.catalog: + id: simple-tomcat-test + version: 1.0 + itemType: template + iconUrl: http://tomcat.apache.org/images/tomcat.png + name: Simple Tomcat Test + license: Apache-2.0 + item: + brooklyn.config: + simple.confg: someValue + services: + - type: org.apache.brooklyn.test.framework.TestCase + name: Simple Tomcat Tests + brooklyn.children: + - type: simple-tomcat + id: tomcat + - type: org.apache.brooklyn.test.framework.TestSensor + target: $brooklyn:component("tomcat") + sensor: service.isUp + timeout: 10m + assert: + equals: true \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/etc/nginx-test-examples.yml ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/etc/nginx-test-examples.yml b/sandbox/brooklyn-sandbox-test-framework/etc/nginx-test-examples.yml new file mode 100644 index 0000000..f1711ea --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/etc/nginx-test-examples.yml @@ -0,0 +1,98 @@ +--- +# 1. Start an nginx +# 2. Test it is running +# 3. Stop it +# 4. Test it stopped +# Note there are two alternative forms to look up target - either just provide the 'targetId' to do an implicit DSL lookup, +# or look it up with explicit DSL and provide it as 'target'. +name: NGINX Test +location: localhost +services: +- type: org.apache.brooklyn.test.framework.TestCase + name: Stop Test + brooklyn.children: + - type: org.apache.brooklyn.entity.proxy.nginx.NginxController + id: nginx1 + - type: org.apache.brooklyn.test.framework.TestSensor + target: $brooklyn:component("nginx1") + sensor: service.isUp + equals: true + timeout: 5m + - type: org.apache.brooklyn.test.framework.TestEffector + target: $brooklyn:component("nginx1") + effector: stop + - type: org.apache.brooklyn.test.framework.TestSensor + target: $brooklyn:component("nginx1") + sensor: service.isUp + assert: + equals: false +... + +--- +name: NGINX Test +location: localhost +services: +- type: org.apache.brooklyn.test.framework.TestCase + name: Stop Test + targetId: nginx1 + brooklyn.children: + - type: org.apache.brooklyn.entity.proxy.nginx.NginxController + id: nginx1 + - type: org.apache.brooklyn.test.framework.TestSensor + sensor: service.isUp + equals: true + timeout: 5m + - type: org.apache.brooklyn.test.framework.TestEffector + effector: stop + - type: org.apache.brooklyn.test.framework.TestSensor + sensor: service.isUp + equals: false + + + +--- +name: NGINX Test +location: localhost +services: +- type: org.apache.brooklyn.test.framework.TestCase + name: Stop Test + brooklyn.children: + - type: org.apache.brooklyn.entity.proxy.nginx.NginxController + id: nginx1 + - type: org.apache.brooklyn.test.framework.TestSensor + target: $brooklyn:component("nginx1") + sensor: service.isUp + timeout: 5m + assert: + equals: true + - type: org.apache.brooklyn.test.framework.TestEffector + target: $brooklyn:component("nginx1") + effector: stop + - type: org.apache.brooklyn.test.framework.TestSensor + target: $brooklyn:component("nginx1") + sensor: service.isUp + assert: + equals: false + regex: .* +... + +--- +name: NGINX Test +location: localhost +services: +- type: org.apache.brooklyn.entity.proxy.nginx.NginxController + id: nginx1 +- type: org.apache.brooklyn.test.framework.TestSensor + target: $brooklyn:component("nginx1") + sensor: service.isUp + timeout: 5m + assert: + equals: true +- type: org.apache.brooklyn.test.framework.TestSensor + name: Test Regex + target: $brooklyn:component("nginx1") + sensor: service.isUp + timeout: 5m + assert: + regex: .* +... \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/etc/testhttpcall-examples.yml ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/etc/testhttpcall-examples.yml b/sandbox/brooklyn-sandbox-test-framework/etc/testhttpcall-examples.yml new file mode 100644 index 0000000..0ada000 --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/etc/testhttpcall-examples.yml @@ -0,0 +1,34 @@ +--- +name: Basic HTTP Call Tests +location: localhost +services: +- type: org.apache.brooklyn.test.framework.TestCase + brooklyn.children: + - type: org.apache.brooklyn.entity.webapp.tomcat.TomcatServer + id: tomcat + brooklyn.config: + war: "http://search.maven.org/remotecontent?filepath=io/brooklyn/example/brooklyn-example-hello-world-sql-webapp/0.6.0/brooklyn-example-hello-world-sql-webapp-0.6.0.war" + - type: org.apache.brooklyn.test.framework.TestHttpCall + name: Status Code 200 + url: $brooklyn:component("tomcat").attributeWhenReady("main.uri") + assert: + status: 200 + - type: org.apache.brooklyn.test.framework.TestHttpCall + name: Status Code 404 + url: $brooklyn:formatString("%s/invalidpath/", component("tomcat").attributeWhenReady("main.uri")) + assert: + status: 404 + - type: org.apache.brooklyn.test.framework.TestHttpCall + name: String match + url: $brooklyn:component("tomcat").attributeWhenReady("main.uri") + assert: + string: Sample Brooklyn Deployed + - type: org.apache.brooklyn.test.framework.TestHttpCall + name: Regex match + url: $brooklyn:component("tomcat").attributeWhenReady("main.uri") + # the regex assert uses java.lang.String under the hood so if the url is expected to returns + # a multi-line response you should use the embedded dotall flag expression `(?s)` in your regex. + # See: http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html + assert: + regex: "(?s).*illustrate(\\s)*how(\\s)*web(\\s)*applications.*" +... \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/etc/tomcat-test-examples.yml ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/etc/tomcat-test-examples.yml b/sandbox/brooklyn-sandbox-test-framework/etc/tomcat-test-examples.yml new file mode 100644 index 0000000..37d7f4d --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/etc/tomcat-test-examples.yml @@ -0,0 +1,45 @@ +--- +name: Tomcat Multi-War Test +location: localhost +services: +- type: org.apache.brooklyn.entity.webapp.tomcat.TomcatServer + id: tomcat + name: Tomcat + brooklyn.config: + wars.by.context: + hello1: "http://search.maven.org/remotecontent?filepath=io/brooklyn/example/brooklyn-example-hello-world-sql-webapp/0.6.0/brooklyn-example-hello-world-sql-webapp-0.6.0.war" + hello2: "http://search.maven.org/remotecontent?filepath=io/brooklyn/example/brooklyn-example-hello-world-sql-webapp/0.6.0/brooklyn-example-hello-world-sql-webapp-0.6.0.war" + start.timeout: 10m +- type: org.apache.brooklyn.test.framework.TestSensor + target: $brooklyn:component("tomcat") + sensor: service.isUp + assert: + equals: true + timeout: 10m +... + +--- +name: Tomcat Tests +location: BYON 1 +services: + - type: org.apache.brooklyn.test.framework.TestCase + name: Effector - Deploy Test + brooklyn.children: + - type: org.apache.brooklyn.entity.webapp.tomcat.TomcatServer + id: tomcat + name: Tomcat + war: https://tomcat.apache.org/tomcat-6.0-doc/appdev/sample/sample.war + - type: org.apache.brooklyn.test.framework.TestEffector + name: Deploy Another WAR + target: $brooklyn:component("tomcat") + effector: deploy + params: + url: https://tomcat.apache.org/tomcat-6.0-doc/appdev/sample/sample.war + targetName: sample1 +# - type: org.apache.brooklyn.test.framework.TestSensor +# target: $brooklyn:component("tomcat") +# sensor: webapp.deployedWars +# assert: +# regex: .*sample1.* +# timeout: 1m +... \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/pom.xml ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/pom.xml b/sandbox/brooklyn-sandbox-test-framework/pom.xml new file mode 100644 index 0000000..ba9430f --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/pom.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>brooklyn</artifactId> + <groupId>org.apache.brooklyn</groupId> + <version>0.9.0-SNAPSHOT</version> + <relativePath>../../pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>brooklyn-sandbox-test-framework</artifactId> + <name>Brooklyn Test Framework</name> + + <properties> + <assertj.version>3.2.0</assertj.version> + </properties> + + <dependencies> + + <dependency> + <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-core</artifactId> + <version>${brooklyn.version}</version> + </dependency> + <dependency> + <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-camp</artifactId> + <version>${brooklyn.version}</version> + </dependency> + + <!--TEST SCOPE :: START--> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <version>${testng.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-test-support</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-core</artifactId> + <version>${brooklyn.version}</version> + <scope>test</scope> + <classifier>tests</classifier> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>${assertj.version}</version> + <scope>test</scope> + </dependency> + <!--TEST SCOPE :: END--> + + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.3</version> + <configuration> + <source>${java.version}</source> + <target>${java.version}</target> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/AbstractTest.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/AbstractTest.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/AbstractTest.java new file mode 100644 index 0000000..2194286 --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/AbstractTest.java @@ -0,0 +1,50 @@ +package org.apache.brooklyn.test.framework; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.mgmt.Task; +import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent; +import org.apache.brooklyn.core.entity.AbstractEntity; +import org.apache.brooklyn.util.core.task.Tasks; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ExecutionException; + +/** + * Abstract base class for tests, providing common target lookup. + */ +public abstract class AbstractTest extends AbstractEntity implements BaseTest { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractTest.class); + + /** + * Find the target entity using "target" config key, if entity provided directly in config, or by doing an implicit + * lookup using DSL ($brooklyn:component("myNginX")), if id of entity provided as "targetId" config key. + * + * @return The target entity. + * + * @throws @RuntimeException if no target can be determined. + */ + public Entity resolveTarget() { + Entity entity = getConfig(TARGET_ENTITY); + if (null == entity) { + entity = getTargetById(); + } + return entity; + } + + private Entity getTargetById() { + String targetId = getConfig(TARGET_ID); + final Task<Entity> targetLookup = new DslComponent(targetId).newTask(); + Entity entity = null; + try { + entity = Tasks.resolveValue(targetLookup, Entity.class, getExecutionContext(), "Finding entity " + targetId); + LOG.debug("Found target by id {}", targetId); + } catch (final ExecutionException | InterruptedException e) { + LOG.error("Error finding target {}", targetId); + Exceptions.propagate(e); + } + return entity; + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java new file mode 100644 index 0000000..b0f347d --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java @@ -0,0 +1,34 @@ +package org.apache.brooklyn.test.framework; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.entity.trait.Startable; +import org.apache.brooklyn.util.core.flags.SetFromFlag; + +/** + * A base interface for all tests. + */ +public interface BaseTest extends Entity, Startable { + + /** + * The target entity to test (optional, use either this or targetId). + */ + @SetFromFlag(nullable = false) + ConfigKey<Entity> TARGET_ENTITY = ConfigKeys.newConfigKey(Entity.class, "target", "Entity under test"); + + /** + * Id of the target entity to test (optional, use either this or target). + */ + @SetFromFlag(nullable = false) + ConfigKey<String> TARGET_ID = ConfigKeys.newStringConfigKey("targetId", "Id of the entity under test"); + + /** + * Get the target of the test. + * + * @return The target. + * + * @throws IllegalArgumentException if the target cannot be found. + */ + Entity resolveTarget(); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCase.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCase.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCase.java new file mode 100644 index 0000000..b5dc1ea --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCase.java @@ -0,0 +1,13 @@ +package org.apache.brooklyn.test.framework; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.ImplementedBy; +import org.apache.brooklyn.core.entity.trait.Startable; + +/** + * + * @author Chris Burke + */ +@ImplementedBy(value = ParallelTestCaseImpl.class) +public interface ParallelTestCase extends Entity, Startable { +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCaseImpl.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCaseImpl.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCaseImpl.java new file mode 100644 index 0000000..67e972a --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCaseImpl.java @@ -0,0 +1,130 @@ +package org.apache.brooklyn.test.framework; + +import java.util.Collection; +import java.util.concurrent.ExecutionException; + +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.mgmt.Task; +import org.apache.brooklyn.api.mgmt.TaskAdaptable; +import org.apache.brooklyn.core.entity.AbstractEntity; +import org.apache.brooklyn.core.entity.Attributes; +import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; +import org.apache.brooklyn.core.entity.trait.StartableMethods; +import org.apache.brooklyn.util.core.task.DynamicTasks; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This implementation will start all child entities in parallel. + * + * @author Chris Burke + */ +public class ParallelTestCaseImpl extends AbstractEntity implements ParallelTestCase { + + private static final Logger logger = LoggerFactory.getLogger(ParallelTestCaseImpl.class); + + /** + * {@inheritDoc} + */ + public void start(Collection<? extends Location> locations) { + // Let everyone know we're starting up (so that the GUI shows the correct icon). + sensors().set(Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STARTING); + try { + // Get an unsubmitted task for starting all the children of this entity in parallel, + // at the same location as this entity. + final TaskAdaptable<?> taskAdaptable = StartableMethods.startingChildren(this); + logger.trace("{}, TaskAdaptable: {}", this, taskAdaptable); + + // Submit the task to the ExecutionManager so that they actually get started + // and then wait until all the parallel child entities have completed. + submitTaskAndWait(taskAdaptable); + + // Let everyone know we've started up successfully (changes the icon in the GUI). + logger.debug("Tasks successfully run. Update state of {} to RUNNING.", this); + setServiceState(true, Lifecycle.RUNNING); + } catch (Throwable t) { + logger.debug("Tasks NOT successfully run. Update state of {} to ON_FIRE.", this); + setServiceState(false, Lifecycle.ON_FIRE); + throw Exceptions.propagate(t); + } + } + + /** + * {@inheritDoc} + */ + public void stop() { + // Let everyone know we're stopping (so that the GUI shows the correct icon). + sensors().set(Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPING); + + // Get an unsubmitted task for stopping all the children of this entity in parallel. + final TaskAdaptable<?> taskAdaptable = StartableMethods.stoppingChildren(this); + logger.trace("{}, TaskAdaptable: {}", this, taskAdaptable); + try { + // Submit the task to the ExecutionManager so that they actually get stopped + // and then wait until all the parallel entities have completed. + submitTaskAndWait(taskAdaptable); + // Let everyone know we've stopped successfully (changes the icon in the GUI). + logger.debug("Tasks successfully run. Update state of {} to STOPPED.", this); + setServiceState(false, Lifecycle.STOPPED); + } catch (Throwable t) { + logger.debug("Tasks NOT successfully run. Update state of {} to ON_FIRE.", this); + setServiceState(false, Lifecycle.ON_FIRE); + throw Exceptions.propagate(t); + } + } + + /** + * {@inheritDoc} + */ + public void restart() { + // Let everyone know we're restarting (so that the GUI shows the correct icon). + setServiceState(false, Lifecycle.STARTING); + + // Get an unsubmitted task for restarting all the children of this entity in parallel. + final TaskAdaptable<?> taskAdaptable = StartableMethods.restartingChildren(this); + logger.trace("{}, TaskAdaptable: {}", this, taskAdaptable); + + try { + // Submit the task to the ExecutionManager so that they actually get stopped + // and then wait until all the parallel entities have completed. + submitTaskAndWait(taskAdaptable); + + // Let everyone know we've started up successfully (changes the icon in the GUI). + logger.debug("Tasks successfully run. Update state of {} to RUNNING.", this); + setServiceState(true, Lifecycle.RUNNING); + } catch (Throwable t) { + logger.debug("Tasks NOT successfully run. Update state of {} to ON_FIRE.", this); + setServiceState(false, Lifecycle.ON_FIRE); + throw Exceptions.propagate(t); + } + } + + /** + * Submits the task to the ExecutionManager and then waits until the task has completed. + * + * @param taskAdaptable the TaskAdaptable to submit for execution. + * @throws ExecutionException if the task threw an exception + * @throws InterruptedException if the current thread was interrupted while waiting + */ + private void submitTaskAndWait(final TaskAdaptable<?> taskAdaptable) + throws InterruptedException, ExecutionException { + logger.debug("{}, Submitting taskAdaptable: {}", this, taskAdaptable); + // Submit the task to the ExecutionManager. + final Task<?> task = DynamicTasks.submit(taskAdaptable, this); + + // Block until the task has completed. + logger.debug("{}, Blocking until task complete.", this); + task.blockUntilEnded(); + logger.debug("{}, Task complete.", this); + + // Get the result of the task. We don't really care about the + // actual result but this will throw an exception if the task failed. + task.get(); + } + + private void setServiceState(final boolean serviceUpState, final Lifecycle serviceStateActual) { + sensors().set(SERVICE_UP, serviceUpState); + sensors().set(Attributes.SERVICE_STATE_ACTUAL, serviceStateActual); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCase.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCase.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCase.java new file mode 100644 index 0000000..6d2ae11 --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCase.java @@ -0,0 +1,12 @@ +package org.apache.brooklyn.test.framework; + +import org.apache.brooklyn.api.entity.ImplementedBy; + +/** + * Entity that logically groups other test entities + * + * @author m4rkmckenna + */ +@ImplementedBy(value = TestCaseImpl.class) +public interface TestCase extends BaseTest { +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCaseImpl.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCaseImpl.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCaseImpl.java new file mode 100644 index 0000000..1b443fb --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCaseImpl.java @@ -0,0 +1,61 @@ +package org.apache.brooklyn.test.framework; + +import com.google.common.collect.Lists; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; +import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic; +import org.apache.brooklyn.core.entity.trait.Startable; +import org.apache.brooklyn.util.exceptions.Exceptions; + +import java.util.Collection; + +/** + * {@inheritDoc} + */ +public class TestCaseImpl extends AbstractTest implements TestCase { + + /** + * {@inheritDoc} + */ + public void start(Collection<? extends Location> locations) { + ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); + try { + for (final Entity childEntity : getChildren()) { + if (childEntity instanceof Startable) ((Startable) childEntity).start(locations); + } + sensors().set(SERVICE_UP, true); + ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); + } catch (Throwable t) { + sensors().set(SERVICE_UP, false); + ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); + throw Exceptions.propagate(t); + } + } + + /** + * {@inheritDoc} + */ + public void stop() { + ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING); + sensors().set(SERVICE_UP, false); + try { + for (Entity child : getChildren()) { + if (child instanceof Startable) ((Startable) child).stop(); + } + ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED); + } catch (Exception e) { + ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); + throw Exceptions.propagate(e); + } + } + + /** + * {@inheritDoc} + */ + public void restart() { + final Collection<Location> locations = Lists.newArrayList(getLocations()); + stop(); + start(locations); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java new file mode 100644 index 0000000..e9ec832 --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java @@ -0,0 +1,33 @@ +package org.apache.brooklyn.test.framework; + +import com.google.common.collect.ImmutableMap; +import com.google.common.reflect.TypeToken; +import org.apache.brooklyn.api.entity.ImplementedBy; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey; +import org.apache.brooklyn.util.core.flags.SetFromFlag; +import org.apache.brooklyn.util.time.Duration; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * Entity that invokes an effector on another entity + * + * @author m4rkmckenna + */ +@ImplementedBy(value = TestEffectorImpl.class) +public interface TestEffector extends BaseTest { + + @SetFromFlag(nullable = false) + ConfigKey<String> EFFECTOR_NAME = ConfigKeys.newConfigKey(String.class, "effector", "The name of the effector to invoke"); + + ConfigKey<Map<String, ?>> EFFECTOR_PARAMS = ConfigKeys.newConfigKey(new TypeToken<Map<String, ?>>() { + }, "params", "The parameters to pass to the effector", ImmutableMap.<String, Object>of()); + + ConfigKey<Duration> TIMEOUT = ConfigKeys.newConfigKey(Duration.class, "timeout", "Time to wait on sensor result", new Duration(5L, TimeUnit.SECONDS)); + + AttributeSensorAndConfigKey<Object, Object> EFFECTOR_RESULT = ConfigKeys.newSensorAndConfigKey(Object.class, "result", "The result of invoking the effector"); + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java new file mode 100644 index 0000000..442797e --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java @@ -0,0 +1,91 @@ +package org.apache.brooklyn.test.framework; + +import com.google.common.collect.Lists; +import org.apache.brooklyn.api.effector.Effector; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.mgmt.Task; +import org.apache.brooklyn.core.entity.Entities; +import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; +import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic; +import org.apache.brooklyn.core.entity.trait.Startable; +import org.apache.brooklyn.core.mgmt.internal.EffectorUtils; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.guava.Maybe; +import org.apache.brooklyn.util.time.Duration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.Map; + +/** + * + */ +public class TestEffectorImpl extends AbstractTest implements TestEffector { + private static final Logger LOG = LoggerFactory.getLogger(TestEffectorImpl.class); + + + /** + * {@inheritDoc} + */ + public void start(Collection<? extends Location> locations) { + ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); + final Entity targetEntity = resolveTarget(); + final String effectorName = getConfig(EFFECTOR_NAME); + final Map<String, ?> effectorParams = getConfig(EFFECTOR_PARAMS); + final Duration timeout = getConfig(TIMEOUT); + try { + Maybe<Effector<?>> effector = EffectorUtils.findEffectorDeclared(targetEntity, effectorName); + if (effector.isAbsentOrNull()) { + throw new AssertionError(String.format("No effector with name [%s]", effectorName)); + } + final Task<?> effectorResult; + if (effectorParams == null || effectorParams.isEmpty()) { + effectorResult = Entities.invokeEffector(this, targetEntity, effector.get()); + } else { + effectorResult = Entities.invokeEffector(this, targetEntity, effector.get(), effectorParams); + } + + //Add result of effector to sensor + sensors().set(EFFECTOR_RESULT, effectorResult.get(timeout)); + + //Start Children + for (Entity childEntity : getChildren()) { + if (childEntity instanceof Startable) ((Startable) childEntity).start(locations); + } + sensors().set(SERVICE_UP, true); + ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); + } catch (Throwable t) { + sensors().set(SERVICE_UP, false); + ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); + throw Exceptions.propagate(t); + } + } + + /** + * {@inheritDoc} + */ + public void stop() { + ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING); + sensors().set(SERVICE_UP, false); + try { + for (Entity child : getChildren()) { + if (child instanceof Startable) ((Startable) child).stop(); + } + ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED); + } catch (Exception e) { + ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); + throw Exceptions.propagate(e); + } + } + + /** + * {@inheritDoc} + */ + public void restart() { + final Collection<Location> locations = Lists.newArrayList(getLocations()); + stop(); + start(locations); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java new file mode 100644 index 0000000..04d551f --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java @@ -0,0 +1,28 @@ +package org.apache.brooklyn.test.framework; + +import com.google.common.collect.Maps; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.ImplementedBy; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.entity.trait.Startable; +import org.apache.brooklyn.util.core.flags.SetFromFlag; + +import java.util.Map; + +/** + * Entity that makes a HTTP Request and tests the respose + * + * @author johnmccabe + */ +@ImplementedBy(value = TestHttpCallImpl.class) +public interface TestHttpCall extends Entity, Startable { + + @SetFromFlag(nullable = false) + ConfigKey<String> TARGET_URL = ConfigKeys.newStringConfigKey("url", "Url to test"); + + @SetFromFlag(nullable = false) + ConfigKey<Map> ASSERTIONS = ConfigKeys.newConfigKey(Map.class, "assert", + "Assertions to be evaluated", Maps.newLinkedHashMap()); + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java new file mode 100644 index 0000000..c0fd608 --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java @@ -0,0 +1,98 @@ +package org.apache.brooklyn.test.framework; + +import com.google.api.client.util.Objects; +import com.google.common.collect.Lists; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.core.entity.AbstractEntity; +import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; +import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic; +import org.apache.brooklyn.util.core.flags.TypeCoercions; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.Map; + +import static org.apache.brooklyn.util.http.HttpUtils.*; + +/** + * {@inheritDoc} + */ +public class TestHttpCallImpl extends AbstractEntity implements TestHttpCall { + + private static final Logger LOG = LoggerFactory.getLogger(TestHttpCallImpl.class); + + /** + * {@inheritDoc} + */ + public void start(Collection<? extends Location> locations) { + ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); + final String url = getConfig(TARGET_URL); + final Map assertions = getConfig(ASSERTIONS); + try { + checkAssertions(url, assertions); + sensors().set(SERVICE_UP, true); + ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); + } catch (Throwable t) { + LOG.info("Url [{}] test failed", url); + sensors().set(SERVICE_UP, false); + ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); + throw Exceptions.propagate(t); + } + } + + /** + * Tests HTTP Request reponse matches assertions + * <p> + * Supported keys in the <code>assertions</code> {@link Map} include: + * <ul> + * <li>string - simple string match + * <li>regex - uses {@link java.lang.String#matches(String)}, if the url returns a multi-line response you should + * use the embedded dotall flag expression <code>(?s)</code> in your regex. + * <li>status - HTTP status code + * </ul> + * Wraps the {@link org.apache.brooklyn.util.http.HttpUtils} immediate assertion methods. + * <p> + * See the test/resources directory for examples. + * + * @param url The target URL to be tested + * @param assertions The map of assertions + */ + private void checkAssertions(final String url, final Map<?, ?> assertions) { + + for (final Map.Entry<?, ?> entry : assertions.entrySet()) { + if (Objects.equal(entry.getKey(), "regex")) { + LOG.info("Testing if url [{}] matches regex [{}]", + new Object[]{url, entry.getValue()}); + assertContentMatches(url, TypeCoercions.coerce(entry.getValue(), String.class)); + } else if (Objects.equal(entry.getKey(), "string")) { + LOG.debug("Testing if url [{}] contains string [{}]", + new Object[]{url, entry.getValue()}); + assertContentContainsText(url, TypeCoercions.coerce(entry.getValue(), String.class)); + } else if (Objects.equal(entry.getKey(), "status")) { + LOG.debug("Testing if url [{}] returns status code [{}]", + new Object[]{url, entry.getValue()}); + assertHttpStatusCodeEquals(url, TypeCoercions.coerce(entry.getValue(), Integer.class)); + } + } + } + + /** + * {@inheritDoc} + */ + public void stop() { + ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING); + sensors().set(SERVICE_UP, false); + } + + /** + * {@inheritDoc} + */ + public void restart() { + final Collection<Location> locations = Lists.newArrayList(getLocations()); + stop(); + start(locations); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensor.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensor.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensor.java new file mode 100644 index 0000000..c6303eb --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensor.java @@ -0,0 +1,27 @@ +package org.apache.brooklyn.test.framework; + +import com.google.common.collect.Maps; +import org.apache.brooklyn.api.entity.ImplementedBy; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.util.core.flags.SetFromFlag; +import org.apache.brooklyn.util.time.Duration; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * Entity that tests a sensor value on another entity + * + * @author m4rkmckenna + */ +@ImplementedBy(value = TestSensorImpl.class) +public interface TestSensor extends BaseTest { + + @SetFromFlag(nullable = false) + ConfigKey<String> SENSOR_NAME = ConfigKeys.newConfigKey(String.class, "sensor", "Sensor to evaluate"); + + ConfigKey<Map> ASSERTIONS = ConfigKeys.newConfigKey(Map.class, "assert", "Assertions to be evaluated", Maps.newLinkedHashMap()); + + ConfigKey<Duration> TIMEOUT = ConfigKeys.newConfigKey(Duration.class, "timeout", "Time to wait on sensor result", new Duration(1L, TimeUnit.SECONDS)); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java new file mode 100644 index 0000000..94151c6 --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java @@ -0,0 +1,144 @@ +package org.apache.brooklyn.test.framework; + +import com.google.api.client.util.Objects; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.sensor.AttributeSensor; +import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; +import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic; +import org.apache.brooklyn.core.entity.trait.Startable; +import org.apache.brooklyn.core.sensor.Sensors; +import org.apache.brooklyn.util.core.flags.TypeCoercions; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.time.Duration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.Map; +import java.util.regex.Pattern; + +import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEventually; + +/** + * {@inheritDoc} + */ +public class TestSensorImpl extends AbstractTest implements TestSensor { + + private static final Logger LOG = LoggerFactory.getLogger(TestSensorImpl.class); + + /** + * {@inheritDoc} + */ + public void start(Collection<? extends Location> locations) { + ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); + final Entity target = resolveTarget(); + final String sensor = getConfig(SENSOR_NAME); + final Duration timeout = getConfig(TIMEOUT); + final Map assertions = getConfig(ASSERTIONS); + try { + checkAssertions(target, Sensors.newSensor(Object.class, sensor), ImmutableMap.of("timeout", timeout), + assertions); + sensors().set(SERVICE_UP, true); + ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); + } catch (Throwable t) { + LOG.info("Sensor [{}] test failed", sensor); + sensors().set(SERVICE_UP, false); + ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); + throw Exceptions.propagate(t); + } + } + + /** + * Tests sensor values match assertions + * + * @param target The {@link Entity} that has the sensor under test + * @param sensor The sensor to test + * @param flags Passed to {@link org.apache.brooklyn.core.entity.EntityAsserts#assertAttributeEventually(Map, Entity, AttributeSensor, Predicate)} + * @param assertions The map of assertions + */ + private void checkAssertions(final Entity target, final AttributeSensor<Object> sensor, final Map<?, ?> flags, final Map<?, ?> assertions) { + for (final Map.Entry<?, ?> entry : assertions.entrySet()) { + if (Objects.equal(entry.getKey(), "equals")) { + assertAttributeEventually(flags, target, sensor, isEqualTo(entry.getValue())); + } else if (Objects.equal(entry.getKey(), "regex")) { + assertAttributeEventually(flags, target, sensor, regexMatches(entry.getValue())); + } else if (Objects.equal(entry.getKey(), "isNull")) { + assertAttributeEventually(flags, target, sensor, isNull(entry.getValue())); + } + } + } + + /** + * {@inheritDoc} + */ + public void stop() { + ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING); + sensors().set(SERVICE_UP, false); + try { + for (Entity child : getChildren()) { + if (child instanceof Startable) ((Startable) child).stop(); + } + ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED); + } catch (Exception e) { + ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); + throw Exceptions.propagate(e); + } + } + + /** + * {@inheritDoc} + */ + public void restart() { + final Collection<Location> locations = Lists.newArrayList(getLocations()); + stop(); + start(locations); + } + + /** + * Predicate to check the equality of object + * + * @param value + * @return The created {@link Predicate} + */ + private Predicate<Object> isEqualTo(final Object value) { + return new Predicate<Object>() { + public boolean apply(final Object input) { + return (input != null) && Objects.equal(TypeCoercions.coerce(value, input.getClass()), input); + } + }; + } + + /** + * Predicate to check if a sensor matches a regex pattern + * + * @param patternValue + * @return + */ + private Predicate<Object> regexMatches(final Object patternValue) { + final Pattern pattern = Pattern.compile(TypeCoercions.coerce(patternValue, String.class)); + return new Predicate<Object>() { + public boolean apply(final Object input) { + return (input != null) && pattern.matcher(input.toString()).matches(); + } + }; + } + + /** + * Predicate to check if a sensor value is null + * + * @param isNullValue + * @return + */ + private Predicate<Object> isNull(final Object isNullValue) { + return new Predicate<Object>() { + public boolean apply(final Object input) { + return (input == null) == TypeCoercions.coerce(isNullValue, Boolean.class); + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java b/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java new file mode 100644 index 0000000..b43c76b --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java @@ -0,0 +1,106 @@ +package org.apache.brooklyn.test.framework; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.core.entity.Entities; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author m4rkmckenna on 27/10/2015. + */ +public class TestEffectorTest { + + private TestApplication app; + private ManagementContext managementContext; + private LocalhostMachineProvisioningLocation loc; + private String testId; + + @BeforeMethod + public void setup() { + testId = UUID.randomUUID().toString(); + app = TestApplication.Factory.newManagedInstanceForTests(); + managementContext = app.getManagementContext(); + + loc = managementContext.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class) + .configure("name", testId)); + + } + + + @AfterMethod(alwaysRun = true) + public void tearDown() throws Exception { + if (app != null) Entities.destroyAll(app.getManagementContext()); + } + + + @Test + public void testSimpleEffector() { + final TestCase testCase = app.createAndManageChild(EntitySpec.create(TestCase.class)); + final TestEntity testEntity = testCase.addChild(EntitySpec.create(TestEntity.class)); + + + final TestEffector testEffector = testCase.addChild(EntitySpec.create(TestEffector.class) + .configure(TestEffector.TARGET_ENTITY, testEntity) + .configure(TestEffector.EFFECTOR_NAME, "simpleEffector")); + + app.start(ImmutableList.of(app.newSimulatedLocation())); + + assertThat(testEntity.sensors().get(TestEntity.SIMPLE_EFFECTOR_INVOKED)).isNotNull(); + assertThat(testEntity.sensors().get(TestEntity.SIMPLE_EFFECTOR_INVOKED)).isTrue(); + + assertThat(testEffector.sensors().get(TestEffector.EFFECTOR_RESULT)).isNull(); + } + + @Test + public void testComplexffector() { + final TestCase testCase = app.createAndManageChild(EntitySpec.create(TestCase.class)); + final TestEntity testEntity = testCase.addChild(EntitySpec.create(TestEntity.class)); + + final long expectedLongValue = System.currentTimeMillis(); + final boolean expectedBooleanValue = expectedLongValue % 2 == 0; + + final TestEffector testEffector = testCase.addChild(EntitySpec.create(TestEffector.class) + .configure(TestEffector.TARGET_ENTITY, testEntity) + .configure(TestEffector.EFFECTOR_NAME, "complexEffector") + .configure(TestEffector.EFFECTOR_PARAMS, ImmutableMap.of( + "stringValue", testId, + "booleanValue", expectedBooleanValue, + "longValue", expectedLongValue))); + + app.start(ImmutableList.of(app.newSimulatedLocation())); + + assertThat(testEntity.sensors().get(TestEntity.SIMPLE_EFFECTOR_INVOKED)).isNull(); + assertThat(testEntity.sensors().get(TestEntity.COMPLEX_EFFECTOR_INVOKED)).isNotNull(); + assertThat(testEntity.sensors().get(TestEntity.COMPLEX_EFFECTOR_INVOKED)).isTrue(); + + assertThat(testEntity.sensors().get(TestEntity.COMPLEX_EFFECTOR_STRING)).isNotNull(); + assertThat(testEntity.sensors().get(TestEntity.COMPLEX_EFFECTOR_STRING)).isEqualTo(testId); + + assertThat(testEntity.sensors().get(TestEntity.COMPLEX_EFFECTOR_BOOLEAN)).isNotNull(); + assertThat(testEntity.sensors().get(TestEntity.COMPLEX_EFFECTOR_BOOLEAN)).isEqualTo(expectedBooleanValue); + + assertThat(testEntity.sensors().get(TestEntity.COMPLEX_EFFECTOR_LONG)).isNotNull(); + assertThat(testEntity.sensors().get(TestEntity.COMPLEX_EFFECTOR_LONG)).isEqualTo(expectedLongValue); + + assertThat(testEffector.sensors().get(TestEffector.EFFECTOR_RESULT)).isNotNull(); + assertThat(testEffector.sensors().get(TestEffector.EFFECTOR_RESULT)).isInstanceOf(TestEntity.TestPojo.class); + + final TestEntity.TestPojo effectorResult = (TestEntity.TestPojo) testEffector.sensors().get(TestEffector.EFFECTOR_RESULT); + assertThat(effectorResult.getBooleanValue()).isEqualTo(expectedBooleanValue); + assertThat(effectorResult.getStringValue()).isEqualTo(testId); + assertThat(effectorResult.getLongValue()).isEqualTo(expectedLongValue); + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntity.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntity.java b/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntity.java new file mode 100644 index 0000000..933b227 --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntity.java @@ -0,0 +1,55 @@ +package org.apache.brooklyn.test.framework; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.ImplementedBy; +import org.apache.brooklyn.core.annotation.Effector; +import org.apache.brooklyn.core.annotation.EffectorParam; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.entity.trait.Startable; +import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey; + +/** + * @author m4rkmckenna on 27/10/2015. + */ + +@ImplementedBy(TestEntityImpl.class) +public interface TestEntity extends Entity, Startable { + + AttributeSensorAndConfigKey<Boolean, Boolean> SIMPLE_EFFECTOR_INVOKED = ConfigKeys.newSensorAndConfigKey(Boolean.class, "simple-effector-invoked", ""); + AttributeSensorAndConfigKey<Boolean, Boolean> COMPLEX_EFFECTOR_INVOKED = ConfigKeys.newSensorAndConfigKey(Boolean.class, "complex-effector-invoked", ""); + AttributeSensorAndConfigKey<String, String> COMPLEX_EFFECTOR_STRING = ConfigKeys.newSensorAndConfigKey(String.class, "complex-effector-string", ""); + AttributeSensorAndConfigKey<Boolean, Boolean> COMPLEX_EFFECTOR_BOOLEAN = ConfigKeys.newSensorAndConfigKey(Boolean.class, "complex-effector-boolean", ""); + AttributeSensorAndConfigKey<Long, Long> COMPLEX_EFFECTOR_LONG = ConfigKeys.newSensorAndConfigKey(Long.class, "complex-effector-long", ""); + + @Effector + void simpleEffector(); + + @Effector + TestPojo complexEffector(@EffectorParam(name = "stringValue") final String stringValue, + @EffectorParam(name = "booleanValue") final Boolean booleanValue, + @EffectorParam(name = "longValue") final Long longValue); + + class TestPojo { + private final String stringValue; + private final Boolean booleanValue; + private final Long longValue; + + public TestPojo(final String stringValue, final Boolean booleanValue, final Long longValue) { + this.stringValue = stringValue; + this.booleanValue = booleanValue; + this.longValue = longValue; + } + + public String getStringValue() { + return stringValue; + } + + public Boolean getBooleanValue() { + return booleanValue; + } + + public Long getLongValue() { + return longValue; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntityImpl.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntityImpl.java b/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntityImpl.java new file mode 100644 index 0000000..b3386f2 --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntityImpl.java @@ -0,0 +1,39 @@ +package org.apache.brooklyn.test.framework; + +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.core.annotation.EffectorParam; +import org.apache.brooklyn.core.entity.AbstractEntity; + +import java.util.Collection; + +/** + * @author m4rkmckenna on 27/10/2015. + */ +public class TestEntityImpl extends AbstractEntity implements TestEntity { + @Override + public void start(final Collection<? extends Location> locations) { + } + + @Override + public void stop() { + + } + + @Override + public void restart() { + } + + @Override + public void simpleEffector() { + sensors().set(SIMPLE_EFFECTOR_INVOKED, Boolean.TRUE); + } + + @Override + public TestPojo complexEffector(@EffectorParam(name = "stringValue") final String stringValue, @EffectorParam(name = "booleanValue") final Boolean booleanValue, @EffectorParam(name = "longValue") final Long longValue) { + sensors().set(COMPLEX_EFFECTOR_INVOKED, Boolean.TRUE); + sensors().set(COMPLEX_EFFECTOR_STRING, stringValue); + sensors().set(COMPLEX_EFFECTOR_BOOLEAN, booleanValue); + sensors().set(COMPLEX_EFFECTOR_LONG, longValue); + return new TestPojo(stringValue, booleanValue, longValue); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0e8c31df/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java ---------------------------------------------------------------------- diff --git a/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java b/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java new file mode 100644 index 0000000..0b653eb --- /dev/null +++ b/sandbox/brooklyn-sandbox-test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java @@ -0,0 +1,270 @@ +package org.apache.brooklyn.test.framework; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.entity.Entities; +import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author m4rkmckenna on 27/10/2015. + */ +public class TestSensorTest { + + private static final AttributeSensorAndConfigKey<Boolean, Boolean> BOOLEAN_SENSOR = ConfigKeys.newSensorAndConfigKey(Boolean.class, "boolean-sensor", "Boolean Sensor"); + private static final AttributeSensorAndConfigKey<String, String> STRING_SENSOR = ConfigKeys.newSensorAndConfigKey(String.class, "string-sensor", "String Sensor"); + private static final AttributeSensorAndConfigKey<Object, Object> OBJECT_SENSOR = ConfigKeys.newSensorAndConfigKey(Object.class, "object-sensor", "Object Sensor"); + + private TestApplication app; + private ManagementContext managementContext; + private LocalhostMachineProvisioningLocation loc; + private String testId; + + @BeforeMethod + public void setup() { + testId = UUID.randomUUID().toString(); + app = TestApplication.Factory.newManagedInstanceForTests(); + managementContext = app.getManagementContext(); + loc = managementContext.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class) + .configure("name", testId)); + } + + @AfterMethod(alwaysRun = true) + public void tearDown() throws Exception { + if (app != null) Entities.destroyAll(app.getManagementContext()); + } + + @Test + public void testAssertEqual() { + //Add Sensor Test for BOOLEAN sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, BOOLEAN_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("equals", true))); + //Add Sensor Test for STRING sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("equals", testId))); + + //Set BOOLEAN Sensor to true + app.sensors().set(BOOLEAN_SENSOR, Boolean.TRUE); + //Set STRING sensor to random string + app.sensors().set(STRING_SENSOR, testId); + + + app.start(ImmutableList.of(loc)); + + } + + @Test + public void testAssertEqualFailure() { + boolean booleanAssertFailed = false; + + //Add Sensor Test for BOOLEAN sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, BOOLEAN_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("equals", true))); + + //Set BOOLEAN Sensor to false + app.sensors().set(BOOLEAN_SENSOR, Boolean.FALSE); + + try { + app.start(ImmutableList.of(loc)); + } catch (final PropagatedRuntimeException pre) { + final AssertionError assertionError = Exceptions.getFirstThrowableOfType(pre, AssertionError.class); + assertThat(assertionError).isNotNull(); + booleanAssertFailed = true; + } finally { + assertThat(booleanAssertFailed).isTrue(); + } + } + + @Test + public void testAssertEqualOnNullSenor() { + boolean booleanAssertFailed = false; + + //Add Sensor Test for BOOLEAN sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, BOOLEAN_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("equals", false))); + + try { + app.start(ImmutableList.of(loc)); + } catch (final PropagatedRuntimeException pre) { + final AssertionError assertionError = Exceptions.getFirstThrowableOfType(pre, AssertionError.class); + assertThat(assertionError).isNotNull().as("An assertion error should have been thrown"); + booleanAssertFailed = true; + } finally { + assertThat(booleanAssertFailed).isTrue().as("Equals assert should have failed as the sensor is NULL"); + } + } + + @Test + public void testAssertNull() { + //Add Sensor Test for BOOLEAN sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, BOOLEAN_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("isNull", true))); + //Add Sensor Test for STRING sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("isNull", false))); + + //Set STRING sensor to random string + app.sensors().set(STRING_SENSOR, testId); + + app.start(ImmutableList.of(loc)); + + } + + + @Test + public void testAssertNullFail() { + boolean sensorTestFail = false; + //Add Sensor Test for STRING sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("isNull", true))); + + //Set STRING sensor to random string + app.sensors().set(STRING_SENSOR, testId); + + + try { + app.start(ImmutableList.of(loc)); + } catch (final PropagatedRuntimeException pre) { + final AssertionError assertionError = Exceptions.getFirstThrowableOfType(pre, AssertionError.class); + assertThat(assertionError).isNotNull().as("An assertion error should have been thrown"); + sensorTestFail = true; + } finally { + assertThat(sensorTestFail).isTrue().as("isNull assert should have failed as the sensor has been set"); + } + + } + + @Test + public void testAssertRegex() { + final long time = System.currentTimeMillis(); + final String sensorValue = String.format("%s%s%s", UUID.randomUUID().toString(), time, UUID.randomUUID().toString()); + + //Add Sensor Test for STRING sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("regex", String.format(".*%s.*", time)))); + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, BOOLEAN_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("regex", "true"))); + + //Set STRING sensor + app.sensors().set(STRING_SENSOR, sensorValue); + app.sensors().set(BOOLEAN_SENSOR, true); + + + app.start(ImmutableList.of(loc)); + } + + @Test + public void testAssertRegexFail() { + boolean sensorTestFail = false; + final String sensorValue = String.format("%s%s%s", UUID.randomUUID().toString(), System.currentTimeMillis(), UUID.randomUUID().toString()); + + //Add Sensor Test for STRING sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("regex", String.format(".*%s.*", UUID.randomUUID().toString())))); + + //Set STRING sensor + app.sensors().set(STRING_SENSOR, sensorValue); + + + try { + app.start(ImmutableList.of(loc)); + } catch (final PropagatedRuntimeException pre) { + final AssertionError assertionError = Exceptions.getFirstThrowableOfType(pre, AssertionError.class); + assertThat(assertionError).isNotNull().as("An assertion error should have been thrown"); + sensorTestFail = true; + } finally { + assertThat(sensorTestFail).isTrue().as("regex assert should have failed"); + } + } + + @Test + public void testAssertRegexOnNullSensor() { + boolean sensorTestFail = false; + final String sensorValue = String.format("%s%s%s", UUID.randomUUID().toString(), System.currentTimeMillis(), UUID.randomUUID().toString()); + + //Add Sensor Test for STRING sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("regex", String.format(".*%s.*", UUID.randomUUID().toString())))); + + try { + app.start(ImmutableList.of(loc)); + } catch (final PropagatedRuntimeException pre) { + final AssertionError assertionError = Exceptions.getFirstThrowableOfType(pre, AssertionError.class); + assertThat(assertionError).isNotNull().as("An assertion error should have been thrown"); + sensorTestFail = true; + } finally { + assertThat(sensorTestFail).isTrue().as("regex assert should have failed"); + } + } + + + @Test + public void testAssertRegexOnNonStringSensor() { + //Add Sensor Test for OBJECT sensor + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.SENSOR_NAME, OBJECT_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, ImmutableMap.of("regex", ".*TestObject.*id=.*"))); + + app.sensors().set(OBJECT_SENSOR, new TestObject()); + + app.start(ImmutableList.of(loc)); + + } + + + class TestObject { + private final String id; + + public TestObject() { + id = UUID.randomUUID().toString(); + } + + public String getId() { + return id; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + } + +}
