You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by dr...@apache.org on 2017/04/10 11:43:49 UTC
[1/4] brooklyn-server git commit: TestEffector: fix assertion timeouts
Repository: brooklyn-server
Updated Branches:
refs/heads/master 61dfee320 -> b539b110e
TestEffector: fix assertion timeouts
Timeout applies to the effector call.
Assertion of the effector result done exactly once
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/23392d4e
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/23392d4e
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/23392d4e
Branch: refs/heads/master
Commit: 23392d4e43e85855668b935a049ff157852c0cc3
Parents: 1599d7a
Author: Aled Sage <al...@gmail.com>
Authored: Wed Apr 5 17:22:01 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Apr 5 17:22:01 2017 +0100
----------------------------------------------------------------------
.../brooklyn/test/framework/TestEffector.java | 18 +++++----
.../test/framework/TestEffectorImpl.java | 2 +-
.../test/framework/TestFrameworkAssertions.java | 4 ++
.../test/framework/TestEffectorTest.java | 40 ++++++++++++++++++++
.../test/framework/entity/TestEntity.java | 29 ++++++++++----
.../test/framework/entity/TestEntityImpl.java | 7 ++++
6 files changed, 85 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23392d4e/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java
index 1101741..5c996d6 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java
@@ -18,15 +18,16 @@
*/
package org.apache.brooklyn.test.framework;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.reflect.TypeToken;
+import java.util.Map;
+
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 java.util.Map;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
/**
* Entity that invokes an effector on another entity
@@ -37,9 +38,12 @@ 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());
+ @SuppressWarnings("serial")
+ ConfigKey<Map<String, ?>> EFFECTOR_PARAMS = ConfigKeys.newConfigKey(
+ new TypeToken<Map<String, ?>>() {},
+ "params",
+ "The parameters to pass to the effector",
+ ImmutableMap.<String, Object>of());
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/brooklyn-server/blob/23392d4e/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java
index 7afe134..8a08086 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java
@@ -88,8 +88,8 @@ public class TestEffectorImpl extends TargetableTestComponentImpl implements Tes
if(assertions != null && !assertions.isEmpty()){
Supplier<?> supplier = Suppliers.ofInstance(effectorResult);
TestFrameworkAssertions.checkAssertionsEventually(new AssertionOptions(effectorName, supplier)
+ .maxAttempts(1)
.timeout(timeout)
- .backoffToPeriod(backoffToPeriod)
.assertions(assertions));
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23392d4e/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java
index 9484ab5..ff9c1c5 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java
@@ -84,6 +84,10 @@ public class TestFrameworkAssertions {
this.flags.put("timeout", val);
return this;
}
+ public AssertionOptions maxAttempts(Integer val) {
+ this.flags.put("maxAttempts", val);
+ return this;
+ }
public AssertionOptions backoffToPeriod(Duration val) {
this.flags.put("backoffToPeriod", val);
return this;
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23392d4e/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java
----------------------------------------------------------------------
diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java
index ad1b6da..022effd 100644
--- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java
+++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java
@@ -21,6 +21,8 @@ package org.apache.brooklyn.test.framework;
import static org.apache.brooklyn.core.entity.trait.Startable.SERVICE_UP;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
import java.util.List;
import java.util.Map;
@@ -44,6 +46,7 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.base.Predicates;
+import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
@@ -191,6 +194,43 @@ public class TestEffectorTest extends BrooklynAppUnitTestSupport {
}
@Test
+ public void testEffectorTimeoutAppliesOnlyToCallAndNotToAssertionCheck() throws Exception {
+ String stringToReturn = "Goodbye World!";
+
+ Map<String, String> effectorParams = ImmutableMap.of("stringToReturn", stringToReturn);
+
+ List<Map<String, Object>> assertions = ImmutableList.<Map<String, Object>>of(
+ ImmutableMap.<String, Object>of(TestFrameworkAssertions.EQUAL_TO, "Not the string I expected")
+ );
+
+ testCase.addChild(EntitySpec.create(TestEffector.class)
+ .configure(TestEffector.TIMEOUT, Duration.minutes(1))
+ .configure(TestEffector.TARGET_ENTITY, testEntity)
+ .configure(TestEffector.EFFECTOR_NAME, "effectorReturnsString")
+ .configure(TestEffector.EFFECTOR_PARAMS, effectorParams)
+ .configure(TestEffector.ASSERTIONS, assertions));
+
+ Stopwatch stopwatch = Stopwatch.createStarted();
+
+ assertStartFails(app, AssertionError.class, Asserts.DEFAULT_LONG_TIMEOUT);
+
+ Duration duration = Duration.of(stopwatch);
+ assertTrue(duration.isShorterThan(Asserts.DEFAULT_LONG_TIMEOUT), "duration="+duration);
+ }
+
+ @Test
+ public void testEffectorFailureNotRetried() throws Exception {
+ testCase.addChild(EntitySpec.create(TestEffector.class)
+ .configure(TestEffector.TIMEOUT, Duration.minutes(1))
+ .configure(TestEffector.TARGET_ENTITY, testEntity)
+ .configure(TestEffector.EFFECTOR_NAME, "effectorFails"));
+
+ assertStartFails(app, TestEntity.EffectorFailureException.class, Asserts.DEFAULT_LONG_TIMEOUT);
+
+ assertEquals(testEntity.sensors().get(TestEntity.FAILING_EFFECTOR_INVOCATION_COUNT), Integer.valueOf(1));
+ }
+
+ @Test
public void testFailFastIfNoTargetEntity() throws Exception {
testCase.addChild(EntitySpec.create(TestEffector.class)
.configure(TestEffector.EFFECTOR_NAME, "simpleEffector"));
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23392d4e/test-framework/src/test/java/org/apache/brooklyn/test/framework/entity/TestEntity.java
----------------------------------------------------------------------
diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/entity/TestEntity.java b/test-framework/src/test/java/org/apache/brooklyn/test/framework/entity/TestEntity.java
index 83b0052..88bed45 100644
--- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/entity/TestEntity.java
+++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/entity/TestEntity.java
@@ -21,20 +21,21 @@ package org.apache.brooklyn.test.framework.entity;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
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;
+import org.apache.brooklyn.core.sensor.Sensors;
@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", "");
+ AttributeSensor<Boolean> SIMPLE_EFFECTOR_INVOKED = Sensors.newBooleanSensor("simple-effector-invoked");
+ AttributeSensor<Boolean> COMPLEX_EFFECTOR_INVOKED = Sensors.newBooleanSensor("complex-effector-invoked");
+ AttributeSensor<String> COMPLEX_EFFECTOR_STRING = Sensors.newStringSensor("complex-effector-string");
+ AttributeSensor<Boolean> COMPLEX_EFFECTOR_BOOLEAN = Sensors.newBooleanSensor("complex-effector-boolean");
+ AttributeSensor<Long> COMPLEX_EFFECTOR_LONG = Sensors.newLongSensor("complex-effector-long");
+ AttributeSensor<Integer> FAILING_EFFECTOR_INVOCATION_COUNT = Sensors.newIntegerSensor("failing-effector-count");
@Effector
void simpleEffector();
@@ -53,6 +54,20 @@ public interface TestEntity extends Entity, Startable {
@Effector
void effectorHangs();
+ @Effector
+ void effectorFails() throws EffectorFailureException;
+
+ class EffectorFailureException extends Exception {
+ private static final long serialVersionUID = -8996475930661355402L;
+
+ public EffectorFailureException(String msg) {
+ super(msg);
+ }
+ public EffectorFailureException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+ }
+
class TestPojo {
private final String stringValue;
private final Boolean booleanValue;
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23392d4e/test-framework/src/test/java/org/apache/brooklyn/test/framework/entity/TestEntityImpl.java
----------------------------------------------------------------------
diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/entity/TestEntityImpl.java b/test-framework/src/test/java/org/apache/brooklyn/test/framework/entity/TestEntityImpl.java
index a6c41a4..439c0ce 100644
--- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/entity/TestEntityImpl.java
+++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/entity/TestEntityImpl.java
@@ -68,4 +68,11 @@ public class TestEntityImpl extends AbstractEntity implements TestEntity {
public void effectorHangs() {
Time.sleep(Duration.minutes(5));
}
+
+ @Override
+ public void effectorFails() throws EffectorFailureException {
+ Integer count = sensors().get(FAILING_EFFECTOR_INVOCATION_COUNT);
+ sensors().set(FAILING_EFFECTOR_INVOCATION_COUNT, (count == null ? 0 : count) + 1);
+ throw new EffectorFailureException("Simulating effector failure");
+ }
}
[3/4] brooklyn-server git commit: Adds TestSshCommand.maxAttempts
Posted by dr...@apache.org.
Adds TestSshCommand.maxAttempts
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/2c1547ce
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/2c1547ce
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/2c1547ce
Branch: refs/heads/master
Commit: 2c1547ce3e3e0689d95f3f84558b13897fc186d8
Parents: 2b3c241
Author: Aled Sage <al...@gmail.com>
Authored: Wed Apr 5 21:24:44 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Apr 5 21:24:44 2017 +0100
----------------------------------------------------------------------
.../brooklyn/test/framework/TestSshCommand.java | 4 +
.../test/framework/TestSshCommandImpl.java | 2 +
.../test/framework/TestSshCommandTest.java | 78 +++++++++++++++++++-
3 files changed, 81 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2c1547ce/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommand.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommand.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommand.java
index 85d402c..df6df72 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommand.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommand.java
@@ -106,4 +106,8 @@ public interface TestSshCommand extends BaseTest {
ConfigKey<Object> ASSERT_ERR = ConfigKeys.newConfigKey(Object.class, "assert.err", "Assertions on command standard error",
ImmutableList.<Map<String, Object>>of());
+ /**
+ * The maximum number of times to execute the ssh command, before throwing an exception.
+ */
+ ConfigKey<Integer> MAX_ATTEMPTS = ConfigKeys.newIntegerConfigKey("maxAttempts", "Maximum number of attempts");
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2c1547ce/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommandImpl.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommandImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommandImpl.java
index 3f0f116..b8b0e1d 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommandImpl.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommandImpl.java
@@ -125,6 +125,7 @@ public class TestSshCommandImpl extends TargetableTestComponentImpl implements T
final SshMachineLocation machineLocation =
Machines.findUniqueMachineLocation(resolveTarget().getLocations(), SshMachineLocation.class).get();
final Duration timeout = getRequiredConfig(TIMEOUT);
+ final Integer maxAttempts = getConfig(MAX_ATTEMPTS);
final Duration backoffToPeriod = getRequiredConfig(BACKOFF_TO_PERIOD);
// TODO use TestFrameworkAssertions (or use Repeater in the same way as that does)?
@@ -132,6 +133,7 @@ public class TestSshCommandImpl extends TargetableTestComponentImpl implements T
// for limitTimeTo, backoffTo, etc?
ReferenceWithError<Boolean> result = Repeater.create("Running ssh-command tests")
.limitTimeTo(timeout)
+ .limitIterationsTo((maxAttempts != null) ? maxAttempts : Integer.MAX_VALUE)
.backoffTo((backoffToPeriod != null) ? backoffToPeriod : Duration.millis(500))
.until(new Callable<Boolean>() {
@Override
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2c1547ce/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSshCommandTest.java
----------------------------------------------------------------------
diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSshCommandTest.java b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSshCommandTest.java
index 344c53d..094433f 100644
--- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSshCommandTest.java
+++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSshCommandTest.java
@@ -18,6 +18,8 @@
*/
package org.apache.brooklyn.test.framework;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertEntityFailed;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertEntityHealthy;
import static org.apache.brooklyn.test.framework.BaseTest.TIMEOUT;
import static org.apache.brooklyn.test.framework.TargetableTestComponent.TARGET_ENTITY;
import static org.apache.brooklyn.test.framework.TestFrameworkAssertions.CONTAINS;
@@ -25,18 +27,21 @@ import static org.apache.brooklyn.test.framework.TestFrameworkAssertions.EQUALS;
import static org.apache.brooklyn.test.framework.TestSshCommand.ASSERT_ERR;
import static org.apache.brooklyn.test.framework.TestSshCommand.ASSERT_OUT;
import static org.apache.brooklyn.test.framework.TestSshCommand.ASSERT_STATUS;
+import static org.apache.brooklyn.test.framework.TestSshCommand.BACKOFF_TO_PERIOD;
import static org.apache.brooklyn.test.framework.TestSshCommand.COMMAND;
import static org.apache.brooklyn.test.framework.TestSshCommand.DOWNLOAD_URL;
+import static org.apache.brooklyn.test.framework.TestSshCommand.MAX_ATTEMPTS;
import static org.apache.brooklyn.test.framework.TestSshCommand.SHELL_ENVIRONMENT;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.apache.brooklyn.core.entity.EntityAsserts.assertEntityFailed;
-import static org.apache.brooklyn.core.entity.EntityAsserts.assertEntityHealthy;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
@@ -46,7 +51,10 @@ import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.CustomResponse;
import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.ExecCmd;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.ExecCmdPredicates;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.ExecParams;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.text.Identifiers;
import org.apache.brooklyn.util.time.Duration;
@@ -58,6 +66,7 @@ import org.testng.annotations.Test;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
public class TestSshCommandTest extends BrooklynAppUnitTestSupport {
@@ -140,6 +149,7 @@ public class TestSshCommandTest extends BrooklynAppUnitTestSupport {
RecordingSshTool.setCustomResponse(cmd, new RecordingSshTool.CustomResponse(1, null, null));
TestSshCommand test = app.createAndManageChild(EntitySpec.create(TestSshCommand.class)
+ .configure(MAX_ATTEMPTS, 1)
.configure(TARGET_ENTITY, testEntity)
.configure(COMMAND, cmd));
@@ -176,6 +186,7 @@ public class TestSshCommandTest extends BrooklynAppUnitTestSupport {
RecordingSshTool.setCustomResponse(cmd, new RecordingSshTool.CustomResponse(0, "wrongstdout", null));
TestSshCommand test = app.createAndManageChild(EntitySpec.create(TestSshCommand.class)
+ .configure(MAX_ATTEMPTS, 1)
.configure(TARGET_ENTITY, testEntity)
.configure(COMMAND, cmd)
.configure(ASSERT_OUT, makeAssertions(ImmutableMap.of(CONTAINS, "mystdout"))));
@@ -196,6 +207,7 @@ public class TestSshCommandTest extends BrooklynAppUnitTestSupport {
RecordingSshTool.setCustomResponse(cmd, new RecordingSshTool.CustomResponse(0, null, "wrongstderr"));
TestSshCommand test = app.createAndManageChild(EntitySpec.create(TestSshCommand.class)
+ .configure(MAX_ATTEMPTS, 1)
.configure(TARGET_ENTITY, testEntity)
.configure(COMMAND, cmd)
.configure(ASSERT_ERR, makeAssertions(ImmutableMap.of(CONTAINS, "mystderr"))));
@@ -211,12 +223,13 @@ public class TestSshCommandTest extends BrooklynAppUnitTestSupport {
}
@Test
- public void shouldNotBeUpIfAssertionsFail() {
+ public void shouldFailOnUnmatchedExitCode() {
Map<String, ?> equalsOne = ImmutableMap.of(EQUALS, 1);
Map<String, ?> equals255 = ImmutableMap.of(EQUALS, 255);
TestSshCommand test = app.createAndManageChild(EntitySpec.create(TestSshCommand.class)
+ .configure(MAX_ATTEMPTS, 1)
.configure(TARGET_ENTITY, testEntity)
.configure(COMMAND, "uptime")
.configure(ASSERT_STATUS, makeAssertions(equalsOne, equals255)));
@@ -315,6 +328,65 @@ public class TestSshCommandTest extends BrooklynAppUnitTestSupport {
assertThat(cmdExecuted.env).isEqualTo(env);
}
+ @Test
+ public void testRetries() {
+ String cmd = "commandExpectedToFail-" + Identifiers.randomLong();
+ RecordingSshTool.setCustomResponse(cmd, new RecordingSshTool.CustomResponseGenerator() {
+ final AtomicInteger counter = new AtomicInteger();
+ @Override public CustomResponse generate(ExecParams execParams) throws Exception {
+ // First call fails; subsequent calls succeed
+ int code = (counter.incrementAndGet() > 1) ? 0 : 1;
+ return new RecordingSshTool.CustomResponse(code, null, null);
+ }
+ });
+
+ TestSshCommand test = app.createAndManageChild(EntitySpec.create(TestSshCommand.class)
+ .configure(BACKOFF_TO_PERIOD, Duration.millis(1))
+ .configure(TIMEOUT, Duration.minutes(1))
+ .configure(TARGET_ENTITY, testEntity)
+ .configure(COMMAND, cmd));
+
+ Stopwatch stopwatch = Stopwatch.createStarted();
+
+ app.start(ImmutableList.<Location>of());
+ assertEntityHealthy(test);
+
+ Iterable<ExecCmd> calls = Iterables.filter(RecordingSshTool.getExecCmds(), ExecCmdPredicates.containsCmd(cmd));
+ assertEquals(Iterables.size(calls), 2, "matchingCalls="+calls);
+
+ Duration duration = Duration.of(stopwatch);
+ assertTrue(duration.isShorterThan(Asserts.DEFAULT_LONG_TIMEOUT), "duration="+duration);
+ }
+
+ @Test
+ public void testMaxAttempts() {
+ String cmd = "commandExpectedToFail-" + Identifiers.randomLong();
+ RecordingSshTool.setCustomResponse(cmd, new RecordingSshTool.CustomResponse(1, null, null));
+
+ TestSshCommand test = app.createAndManageChild(EntitySpec.create(TestSshCommand.class)
+ .configure(MAX_ATTEMPTS, 2)
+ .configure(BACKOFF_TO_PERIOD, Duration.millis(1))
+ .configure(TIMEOUT, Duration.minutes(1))
+ .configure(TARGET_ENTITY, testEntity)
+ .configure(COMMAND, cmd));
+
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ try {
+ app.start(ImmutableList.<Location>of());
+ Asserts.shouldHaveFailedPreviously();
+ } catch (Throwable t) {
+ Asserts.expectedFailureContains(t, "exit code expected equals 0 but found 1");
+ }
+
+ assertEntityFailed(test);
+
+ Iterable<ExecCmd> calls = Iterables.filter(RecordingSshTool.getExecCmds(), ExecCmdPredicates.containsCmd(cmd));
+ assertEquals(Iterables.size(calls), 2, "matchingCalls="+calls);
+
+ Duration duration = Duration.of(stopwatch);
+ assertTrue(duration.isShorterThan(Asserts.DEFAULT_LONG_TIMEOUT), "duration="+duration);
+ }
+
private Path createTempScript(String filename, String contents) {
try {
Path tempFile = Files.createTempFile("TestSshCommandTest-" + filename, ".sh");
[2/4] brooklyn-server git commit: Adds TestEffector.maxAttempts
Posted by dr...@apache.org.
Adds TestEffector.maxAttempts
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/2b3c2411
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/2b3c2411
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/2b3c2411
Branch: refs/heads/master
Commit: 2b3c24110f9a53986f92e2fea30e1a5070eb6870
Parents: 23392d4
Author: Aled Sage <al...@gmail.com>
Authored: Wed Apr 5 18:27:39 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Apr 5 18:27:39 2017 +0100
----------------------------------------------------------------------
.../brooklyn/test/framework/TestEffector.java | 5 ++
.../test/framework/TestEffectorImpl.java | 87 +++++++++++++++++---
.../brooklyn/test/framework/TestHttpCall.java | 2 +-
.../test/framework/TestEffectorTest.java | 17 ++++
.../org/apache/brooklyn/util/time/TimeTest.java | 30 +++++++
5 files changed, 127 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2b3c2411/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java
index 5c996d6..dc38256 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffector.java
@@ -45,5 +45,10 @@ public interface TestEffector extends BaseTest {
"The parameters to pass to the effector",
ImmutableMap.<String, Object>of());
+ /**
+ * The maximum number of times to execute the http call, before throwing an exception.
+ */
+ ConfigKey<Integer> MAX_ATTEMPTS = ConfigKeys.newIntegerConfigKey("maxAttempts", "Maximum number of attempts");
+
AttributeSensorAndConfigKey<Object, Object> EFFECTOR_RESULT = ConfigKeys.newSensorAndConfigKey(Object.class, "result", "The result of invoking the effector");
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2b3c2411/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java
index 8a08086..074dedf 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java
@@ -23,7 +23,10 @@ import static org.apache.brooklyn.test.framework.TestFrameworkAssertions.getAsse
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.brooklyn.api.effector.Effector;
import org.apache.brooklyn.api.entity.Entity;
@@ -33,15 +36,21 @@ 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.mgmt.internal.EffectorUtils;
+import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.test.framework.TestFrameworkAssertions.AssertionOptions;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.exceptions.RuntimeInterruptedException;
import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.repeat.Repeater;
import org.apache.brooklyn.util.time.Duration;
+import org.apache.brooklyn.util.time.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
public class TestEffectorImpl extends TargetableTestComponentImpl implements TestEffector {
@@ -60,6 +69,7 @@ public class TestEffectorImpl extends TargetableTestComponentImpl implements Tes
final String effectorName = getRequiredConfig(EFFECTOR_NAME);
final Map<String, ?> effectorParams = getConfig(EFFECTOR_PARAMS);
final Duration timeout = getConfig(TIMEOUT);
+ final Integer maxAttempts = getConfig(MAX_ATTEMPTS);
final Duration backoffToPeriod = getConfig(BACKOFF_TO_PERIOD);
if (!getChildren().isEmpty()) {
throw new RuntimeException(String.format("The entity [%s] cannot have child entities", getClass().getName()));
@@ -69,20 +79,8 @@ public class TestEffectorImpl extends TargetableTestComponentImpl implements Tes
if (effector.isAbsentOrNull()) {
throw new AssertionError(String.format("No effector with name [%s]", effectorName));
}
- final Task<?> effectorTask;
- if (effectorParams == null || effectorParams.isEmpty()) {
- effectorTask = Entities.invokeEffector(this, targetEntity, effector.get());
- } else {
- effectorTask = Entities.invokeEffector(this, targetEntity, effector.get(), effectorParams);
- }
- final Object effectorResult;
- try {
- effectorResult = effectorTask.get(timeout);
- } catch (TimeoutException e) {
- effectorTask.cancel(true);
- throw new AssertionError("Effector "+effectorName+" timed out after "+timeout, e);
- }
+ Object effectorResult = invokeEffector(targetEntity, effector.get(), effectorParams, maxAttempts, timeout, backoffToPeriod);
final List<Map<String, Object>> assertions = getAssertions(this, ASSERTIONS);
if(assertions != null && !assertions.isEmpty()){
@@ -119,4 +117,67 @@ public class TestEffectorImpl extends TargetableTestComponentImpl implements Tes
stop();
start(locations);
}
+
+ /**
+ * Invokes the effector. On failure, it repeats the invocation up to a maximum of
+ * {@code maxAttempts} times (defaulting to one attempt if that parameter is null).
+ *
+ * The total invocation time is capped at {@code timeout} (if multiple attempts are
+ * permitted, this is the total time for all attempts).
+ *
+ * @throws AssertionError if the invocation times out
+ * @throws ExecutionException if the last invocation attempt fails
+ */
+ protected Object invokeEffector(final Entity targetEntity, final Effector<?> effector, final Map<String, ?> effectorParams,
+ Integer maxAttempts, final Duration timeout, Duration backoffToPeriod) {
+
+ Duration timeLimit = (timeout != null) ? timeout : (maxAttempts == null ? Asserts.DEFAULT_LONG_TIMEOUT : Duration.PRACTICALLY_FOREVER);
+ int iterationLimit = (maxAttempts != null) ? maxAttempts : 1;
+ final Long startTime = System.currentTimeMillis();
+ final AtomicReference<Object> effectorResult = new AtomicReference<Object>();
+
+ Repeater.create()
+ .until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws ExecutionException {
+ try {
+ long timeRemaining = Time.timeRemaining(startTime, timeout.toMilliseconds());
+ Object result = invokeEffector(targetEntity, effector, effectorParams, Duration.millis(timeRemaining));
+ effectorResult.set(result);
+ return true;
+ } catch (TimeoutException e) {
+ throw new AssertionError("Effector "+effector.getName()+" timed out after "+timeout, e);
+ }
+ }})
+ .limitIterationsTo(iterationLimit)
+ .limitTimeTo(timeLimit)
+ .backoffTo(backoffToPeriod)
+ .rethrowExceptionImmediately(Predicates.or(ImmutableList.of(
+ Predicates.instanceOf(TimeoutException.class),
+ Predicates.instanceOf(AbortError.class),
+ Predicates.instanceOf(InterruptedException.class),
+ Predicates.instanceOf(RuntimeInterruptedException.class))))
+ .runRequiringTrue();
+
+ return effectorResult.get();
+ }
+
+ protected Object invokeEffector(Entity targetEntity, Effector<?> effector, Map<String, ?> effectorParams, Duration timeout) throws ExecutionException, TimeoutException {
+ Task<?> task;
+ if (effectorParams == null || effectorParams.isEmpty()) {
+ task = Entities.invokeEffector(TestEffectorImpl.this, targetEntity, effector);
+ } else {
+ task = Entities.invokeEffector(TestEffectorImpl.this, targetEntity, effector, effectorParams);
+ }
+
+ try {
+ return task.get(timeout);
+ } catch (InterruptedException e) {
+ task.cancel(true);
+ throw Exceptions.propagate(e);
+ } catch (TimeoutException e) {
+ task.cancel(true);
+ throw e;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2b3c2411/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
index 3e4867b..e71e506 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
@@ -65,7 +65,7 @@ public interface TestHttpCall extends BaseTest {
"The HTTP field to apply the assertion to [body,status]", HttpAssertionTarget.body);
/**
- * The duration to wait for an assertion to succeed or fail before throwing an exception.
+ * The maximum number of times to execute the http call, before throwing an exception.
*/
ConfigKey<Integer> MAX_ATTEMPTS = ConfigKeys.newIntegerConfigKey("maxAttempts", "Maximum number of attempts");
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2b3c2411/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java
----------------------------------------------------------------------
diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java
index 022effd..c100c0d 100644
--- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java
+++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java
@@ -231,6 +231,23 @@ public class TestEffectorTest extends BrooklynAppUnitTestSupport {
}
@Test
+ public void testEffectorFailureRetriedUpToMaxAttempts() throws Exception {
+ testCase.addChild(EntitySpec.create(TestEffector.class)
+ .configure(TestEffector.MAX_ATTEMPTS, 2)
+ .configure(TestEffector.TIMEOUT, Duration.minutes(1))
+ .configure(TestEffector.TARGET_ENTITY, testEntity)
+ .configure(TestEffector.EFFECTOR_NAME, "effectorFails"));
+ Stopwatch stopwatch = Stopwatch.createStarted();
+
+ assertStartFails(app, TestEntity.EffectorFailureException.class, Asserts.DEFAULT_LONG_TIMEOUT);
+
+ Duration duration = Duration.of(stopwatch);
+ assertTrue(duration.isShorterThan(Asserts.DEFAULT_LONG_TIMEOUT), "duration="+duration);
+
+ assertEquals(testEntity.sensors().get(TestEntity.FAILING_EFFECTOR_INVOCATION_COUNT), Integer.valueOf(2));
+ }
+
+ @Test
public void testFailFastIfNoTargetEntity() throws Exception {
testCase.addChild(EntitySpec.create(TestEffector.class)
.configure(TestEffector.EFFECTOR_NAME, "simpleEffector"));
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2b3c2411/utils/common/src/test/java/org/apache/brooklyn/util/time/TimeTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/time/TimeTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/time/TimeTest.java
index e3c8167..fc9fd9f 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/time/TimeTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/time/TimeTest.java
@@ -18,7 +18,10 @@
*/
package org.apache.brooklyn.util.time;
+import static org.testng.Assert.assertTrue;
+
import java.util.Date;
+import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
@@ -28,10 +31,27 @@ import org.testng.annotations.Test;
import com.google.common.base.Stopwatch;
import com.google.common.base.Ticker;
+import com.google.common.collect.ImmutableList;
@Test
public class TimeTest {
+ public void testTimeRemaining() {
+ long gracePeriod = 5000;
+ long maxTime = 30000;
+ long now = System.currentTimeMillis();
+ long remaining = Time.timeRemaining(now, maxTime);
+ assertOrdered(ImmutableList.<Long>of(maxTime-gracePeriod, remaining, maxTime), "");
+ }
+
+ public void testTimeRemainingMaxLong() {
+ long gracePeriod = 5000;
+ long maxTime = Long.MAX_VALUE;
+ long now = System.currentTimeMillis();
+ long remaining = Time.timeRemaining(now, maxTime);
+ assertOrdered(ImmutableList.<Long>of(maxTime-gracePeriod, remaining, maxTime), "");
+ }
+
public void testMakeStringExact_secondsAndMillis() {
check(1, "1ms");
check(1000, "1s");
@@ -370,4 +390,14 @@ public class TimeTest {
private void assertDatesParseToEqual(String input, String expected) {
Assert.assertEquals(Time.parseDate(input).toString(), Time.parseDate(expected).toString(), "for: "+input+" ("+expected+")");
}
+
+ private <T extends Comparable<T>> void assertOrdered(List<? extends T> vals, String errMsg) {
+ T prev = null;
+ for (T val : vals) {
+ if (prev != null) {
+ assertTrue(prev.compareTo(val) <= 0, errMsg);
+ }
+ prev = val;
+ }
+ }
}
[4/4] brooklyn-server git commit: This closes #620
Posted by dr...@apache.org.
This closes #620
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/b539b110
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/b539b110
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/b539b110
Branch: refs/heads/master
Commit: b539b110ebf7a8cbcbf138e20a9e1707688f50a6
Parents: 61dfee3 2c1547c
Author: Duncan Godwin <dr...@googlemail.com>
Authored: Mon Apr 10 12:43:28 2017 +0100
Committer: Duncan Godwin <dr...@googlemail.com>
Committed: Mon Apr 10 12:43:28 2017 +0100
----------------------------------------------------------------------
.../brooklyn/test/framework/TestEffector.java | 23 +++--
.../test/framework/TestEffectorImpl.java | 89 +++++++++++++++++---
.../test/framework/TestFrameworkAssertions.java | 4 +
.../brooklyn/test/framework/TestHttpCall.java | 2 +-
.../brooklyn/test/framework/TestSshCommand.java | 4 +
.../test/framework/TestSshCommandImpl.java | 2 +
.../test/framework/TestEffectorTest.java | 57 +++++++++++++
.../test/framework/TestSshCommandTest.java | 78 ++++++++++++++++-
.../test/framework/entity/TestEntity.java | 29 +++++--
.../test/framework/entity/TestEntityImpl.java | 7 ++
.../org/apache/brooklyn/util/time/TimeTest.java | 30 +++++++
11 files changed, 293 insertions(+), 32 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b539b110/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java
----------------------------------------------------------------------