You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2015/11/11 18:21:32 UTC
[05/21] incubator-brooklyn git commit: Moved
sandbox/brooklyn-sandbox-test-framework to usage/test-framework
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/813bba02/usage/test-framework/etc/exampl-catalog.bom
----------------------------------------------------------------------
diff --git a/usage/test-framework/etc/exampl-catalog.bom b/usage/test-framework/etc/exampl-catalog.bom
new file mode 100644
index 0000000..ab7e54b
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/etc/example-catalog-test.bom
----------------------------------------------------------------------
diff --git a/usage/test-framework/etc/example-catalog-test.bom b/usage/test-framework/etc/example-catalog-test.bom
new file mode 100644
index 0000000..0605f9d
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/etc/nginx-test-examples.yml
----------------------------------------------------------------------
diff --git a/usage/test-framework/etc/nginx-test-examples.yml b/usage/test-framework/etc/nginx-test-examples.yml
new file mode 100644
index 0000000..f1711ea
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/etc/testhttpcall-examples.yml
----------------------------------------------------------------------
diff --git a/usage/test-framework/etc/testhttpcall-examples.yml b/usage/test-framework/etc/testhttpcall-examples.yml
new file mode 100644
index 0000000..a418fd8
--- /dev/null
+++ b/usage/test-framework/etc/testhttpcall-examples.yml
@@ -0,0 +1,124 @@
+---
+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("webapp.url")
+ assert:
+ status: 200
+ - type: org.apache.brooklyn.test.framework.TestHttpCall
+ name: Status Code 404
+ url: $brooklyn:formatString("%s/invalidpath/", component("tomcat").attributeWhenReady("webapp.url"))
+ timeout: 10s
+ assert:
+ status: 404
+ - type: org.apache.brooklyn.test.framework.TestHttpCall
+ name: String match
+ url: $brooklyn:component("tomcat").attributeWhenReady("webapp.url")
+ assert:
+ string: Sample Brooklyn Deployed
+ - type: org.apache.brooklyn.test.framework.TestHttpCall
+ name: Regex match
+ url: $brooklyn:component("tomcat").attributeWhenReady("webapp.url")
+ # 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.*"
+...
+
+---
+name: HTTP Call Test with Effector
+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("webapp.url")
+ assert:
+ status: 200
+ - type: org.apache.brooklyn.test.framework.TestHttpCall
+ name: /newcontext Status Code 404
+ url: $brooklyn:formatString("%s/newcontext/", component("tomcat").attributeWhenReady("webapp.url"))
+ assert:
+ status: 404
+ - type: org.apache.brooklyn.test.framework.TestEffector
+ name: Deploy WAR in /newcontext
+ target: $brooklyn:component("tomcat")
+ effector: deploy
+ params:
+ url: 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
+ targetName: newcontext
+ - type: org.apache.brooklyn.test.framework.TestHttpCall
+ name: /newcontext Status Code 200
+ url: $brooklyn:formatString("%s/newcontext/", component("tomcat").attributeWhenReady("webapp.url"))
+ # Give Tomcat time to make the newly deployed War accessible
+ timeout: 10s
+ assert:
+ status: 200
+...
+
+---
+name: HTTP Call Test with Eventual String and Regex Matches
+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.TestEffector
+ name: Deploy WAR in /newcontext
+ target: $brooklyn:component("tomcat")
+ effector: deploy
+ params:
+ url: 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
+ targetName: newcontext
+ - type: org.apache.brooklyn.test.framework.TestHttpCall
+ name: Regex match
+ url: $brooklyn:formatString("%s/newcontext/", component("tomcat").attributeWhenReady("webapp.url"))
+ timeout: 10s
+ assert:
+ regex: "(?s).*illustrate(\\s)*how(\\s)*web(\\s)*applications.*"
+ - type: org.apache.brooklyn.test.framework.TestEffector
+ name: Deploy WAR in /newcontext2
+ target: $brooklyn:component("tomcat")
+ effector: deploy
+ params:
+ url: 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
+ targetName: newcontext2
+ - type: org.apache.brooklyn.test.framework.TestHttpCall
+ name: String match
+ url: $brooklyn:formatString("%s/newcontext2/", component("tomcat").attributeWhenReady("webapp.url"))
+ timeout: 10s
+ assert:
+ string: Sample Brooklyn Deployed
+ assert:
+ status: 404
+ - type: org.apache.brooklyn.test.framework.TestHttpCall
+ name: String match
+ url: $brooklyn:component("tomcat").attributeWhenReady("webapp.url")
+ assert:
+ string: Sample Brooklyn Deployed
+ - type: org.apache.brooklyn.test.framework.TestHttpCall
+ name: Regex match
+ url: $brooklyn:component("tomcat").attributeWhenReady("webapp.url")
+ # 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/813bba02/usage/test-framework/etc/tomcat-test-examples.yml
----------------------------------------------------------------------
diff --git a/usage/test-framework/etc/tomcat-test-examples.yml b/usage/test-framework/etc/tomcat-test-examples.yml
new file mode 100644
index 0000000..37d7f4d
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/pom.xml
----------------------------------------------------------------------
diff --git a/usage/test-framework/pom.xml b/usage/test-framework/pom.xml
new file mode 100644
index 0000000..5606a8d
--- /dev/null
+++ b/usage/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>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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/AbstractTest.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/AbstractTest.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/AbstractTest.java
new file mode 100644
index 0000000..2194286
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
new file mode 100644
index 0000000..b0f347d
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCase.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCase.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCase.java
new file mode 100644
index 0000000..b5dc1ea
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCaseImpl.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCaseImpl.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/ParallelTestCaseImpl.java
new file mode 100644
index 0000000..67e972a
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCase.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCase.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCase.java
new file mode 100644
index 0000000..6d2ae11
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCaseImpl.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCaseImpl.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestCaseImpl.java
new file mode 100644
index 0000000..1b443fb
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java
new file mode 100644
index 0000000..e9ec832
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java
new file mode 100644
index 0000000..442797e
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
new file mode 100644
index 0000000..5dfa1c8
--- /dev/null
+++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
@@ -0,0 +1,33 @@
+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 org.apache.brooklyn.util.time.Duration;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 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());
+
+ ConfigKey<Duration> TIMEOUT = ConfigKeys.newConfigKey(Duration.class, "timeout",
+ "The duration to wait for assertion result", new Duration(1L, TimeUnit.SECONDS));
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
new file mode 100644
index 0000000..7413066
--- /dev/null
+++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
@@ -0,0 +1,107 @@
+package org.apache.brooklyn.test.framework;
+
+import com.google.api.client.util.Objects;
+import com.google.common.collect.ImmutableMap;
+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.apache.brooklyn.util.time.Duration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.Map;
+
+import static org.apache.brooklyn.util.http.HttpAsserts.assertContentEventuallyContainsText;
+import static org.apache.brooklyn.util.http.HttpAsserts.assertContentEventuallyMatches;
+import static org.apache.brooklyn.util.http.HttpAsserts.assertHttpStatusCodeEventuallyEquals;
+
+/**
+ * {@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);
+ final Duration timeout = getConfig(TIMEOUT);
+ try {
+ checkAssertions(url.toString(), ImmutableMap.of("timeout", timeout), 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.HttpAsserts} immediate assertion methods.
+ * <p>
+ * See the test/resources directory for examples.
+ *
+ * @param url The target URL to be tested
+ * @param flags Passed to {@link org.apache.brooklyn.util.http.HttpAsserts#assertContentEventuallyContainsText(Map, String, String, String...)},
+ * {@link org.apache.brooklyn.util.http.HttpAsserts#assertContentEventuallyMatches(Map, String, String)},
+ * {@link org.apache.brooklyn.util.http.HttpAsserts#assertHttpStatusCodeEventuallyEquals(Map, String, int)}
+ *
+ * @param assertions The map of assertions
+ */
+ private void checkAssertions(final String url, final Map<String,?> flags, 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()});
+ assertContentEventuallyMatches( flags, 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()});
+ assertContentEventuallyContainsText(flags, 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()});
+ assertHttpStatusCodeEventuallyEquals(flags, 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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensor.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensor.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensor.java
new file mode 100644
index 0000000..c6303eb
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
new file mode 100644
index 0000000..94151c6
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java
new file mode 100644
index 0000000..b43c76b
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntity.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntity.java b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntity.java
new file mode 100644
index 0000000..933b227
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntityImpl.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntityImpl.java b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEntityImpl.java
new file mode 100644
index 0000000..b3386f2
--- /dev/null
+++ b/usage/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/813bba02/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
new file mode 100644
index 0000000..0b653eb
--- /dev/null
+++ b/usage/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);
+ }
+ }
+
+}