brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject [1/2] brooklyn-server git commit: Test framework: support backoffToPeriod config
Date Wed, 04 Jan 2017 13:21:27 GMT
Repository: brooklyn-server
Updated Branches:
  refs/heads/master 41939158a -> 4e69fef10


Test framework: support backoffToPeriod config


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/8add7142
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/8add7142
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/8add7142

Branch: refs/heads/master
Commit: 8add71424ca010ad65355f7a7dacb74533cbc332
Parents: b629f1b
Author: Aled Sage <aled.sage@gmail.com>
Authored: Thu Dec 1 09:52:48 2016 +0000
Committer: Aled Sage <aled.sage@gmail.com>
Committed: Thu Dec 22 20:21:48 2016 +0000

----------------------------------------------------------------------
 .../brooklyn/test/framework/BaseTest.java       |   6 ++
 .../test/framework/TestEffectorImpl.java        |   5 +-
 .../framework/TestEndpointReachableImpl.java    |   5 +-
 .../test/framework/TestFrameworkAssertions.java |  13 +--
 .../test/framework/TestHttpCallImpl.java        |   4 +-
 .../brooklyn/test/framework/TestSensorImpl.java |   4 +-
 .../brooklyn/test/framework/TestSshCommand.java |   4 +
 .../test/framework/TestSshCommandImpl.java      |   6 +-
 .../test/framework/TestWinrmCommand.java        |   4 +
 .../test/framework/TestWinrmCommandImpl.java    |   5 +-
 .../framework/TestFrameworkAssertionsTest.java  | 102 +++++++++++++++++--
 .../brooklyn/test/framework/TestSensorTest.java |   1 +
 12 files changed, 137 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
b/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
index 5c313cd..2ae552d 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
@@ -44,5 +44,11 @@ public interface BaseTest extends TargetableTestComponent, Startable {
     ConfigKey<Duration> TIMEOUT = ConfigKeys.newConfigKey(Duration.class, "timeout",
"Time to wait on result",
         Duration.seconds(1));
 
+    /**
+     * Max time between checking the assertion (exponential backoff to this limit).
+     */
+    ConfigKey<Duration> BACKOFF_TO_PERIOD = ConfigKeys.newConfigKey(Duration.class,
"backoffToPeriod", 
+            "Max time between checking the assertion (exponential backoff to this limit)",
+            Duration.millis(500));
 
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/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 e757ca0..7381631 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
@@ -60,6 +60,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 Duration backoffToPeriod = getConfig(BACKOFF_TO_PERIOD);
             if (!getChildren().isEmpty()) {
                 throw new RuntimeException(String.format("The entity [%s] cannot have child
entities", getClass().getName()));
             }
@@ -87,7 +88,9 @@ public class TestEffectorImpl extends TargetableTestComponentImpl implements
Tes
             if(assertions != null && !assertions.isEmpty()){
                 Supplier<?> supplier = Suppliers.ofInstance(effectorResult);
                 TestFrameworkAssertions.checkAssertionsEventually(new AssertionOptions(effectorName,
supplier)
-                        .timeout(timeout).assertions(assertions));
+                        .timeout(timeout)
+                        .backoffToPeriod(backoffToPeriod)
+                        .assertions(assertions));
             }
 
             //Add result of effector to sensor

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEndpointReachableImpl.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEndpointReachableImpl.java
b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEndpointReachableImpl.java
index 7f4c6fe..c604540 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEndpointReachableImpl.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEndpointReachableImpl.java
@@ -68,6 +68,7 @@ public class TestEndpointReachableImpl extends TargetableTestComponentImpl
imple
         final String endpoint = getConfig(ENDPOINT);
         final Object endpointSensor = getConfig(ENDPOINT_SENSOR);
         final Duration timeout = getConfig(TIMEOUT);
+        final Duration backoffToPeriod = getConfig(BACKOFF_TO_PERIOD);
         final List<Map<String, Object>> assertions = getAssertions(this, ASSERTIONS);
         
         final Entity target = resolveTarget();
@@ -101,7 +102,9 @@ public class TestEndpointReachableImpl extends TargetableTestComponentImpl
imple
         }
 
         try {
-            Asserts.succeedsEventually(ImmutableMap.of("timeout", timeout), new Runnable()
{
+            // TODO use TestFrameworkAssertions (or use Repeater in the same way as that
does)?
+            ImmutableMap<String, Duration> flags = ImmutableMap.of("timeout", timeout,
"maxPeriod", backoffToPeriod);
+            Asserts.succeedsEventually(flags, new Runnable() {
                 @Override
                 public void run() {
                     HostAndPort val = supplier.get();

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/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 e1ed825..8210d7e 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 backoffToPeriod(Duration val) {
+            this.flags.put("backoffToPeriod", val);
+            return this;
+        }
         public AssertionOptions assertions(Map<String, ?> val) {
             this.assertions = ImmutableList.of(val);
             return this;
@@ -227,13 +231,10 @@ public class TestFrameworkAssertions {
         }
         Map<String, ?> flags = options.flags;
         
-        // To speed up tests, default is for the period to start small and increase...
-        // TODO ignoring "period" and "maxAttempts"
+        // To speed up tests, the period starts small and increases.
         Integer maxAttempts = (Integer) flags.get("maxAttempts");
         Duration timeout = toDuration(flags.get("timeout"), (maxAttempts == null ? Asserts.DEFAULT_LONG_TIMEOUT
: Duration.PRACTICALLY_FOREVER));
-        Duration fixedPeriod = toDuration(flags.get("period"), null);
-        Duration minPeriod = (fixedPeriod != null) ? fixedPeriod : toDuration(flags.get("minPeriod"),
Duration.millis(1));
-        Duration maxPeriod = (fixedPeriod != null) ? fixedPeriod : toDuration(flags.get("maxPeriod"),
Duration.millis(500));
+        Duration backoffToPeriod = toDuration(flags.get("backoffToPeriod"), Duration.millis(500));
         Predicate<Throwable> rethrowImmediatelyPredicate = Predicates.or(ImmutableList.of(
                 Predicates.instanceOf(AbortError.class), 
                 Predicates.instanceOf(InterruptedException.class), 
@@ -261,7 +262,7 @@ public class TestFrameworkAssertions {
                         }})
                     .limitIterationsTo(maxAttempts != null ? maxAttempts : Integer.MAX_VALUE)
                     .limitTimeTo(timeout)
-                    .backoff(minPeriod, 1.2, maxPeriod)
+                    .backoffTo(backoffToPeriod)
                     .rethrowExceptionImmediately(rethrowImmediatelyPredicate)
                     .runRequiringTrue();
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
index 87abe90..0422c7c 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
@@ -64,13 +64,15 @@ public class TestHttpCallImpl extends TargetableTestComponentImpl implements
Tes
             final String body = config().get(TARGET_BODY);
             final List<Map<String, Object>> assertions = getAssertions(this,
ASSERTIONS);
             final Duration timeout = getConfig(TIMEOUT);
+            final Duration backoffToPeriod = getConfig(BACKOFF_TO_PERIOD);
             final HttpAssertionTarget target = getRequiredConfig(ASSERTION_TARGET);
             final boolean trustAll = getRequiredConfig(TRUST_ALL);
             if (!getChildren().isEmpty()) {
                 throw new RuntimeException(String.format("The entity [%s] cannot have child
entities", getClass().getName()));
             }
             
-            doRequestAndCheckAssertions(ImmutableMap.of("timeout", timeout), assertions,
target, method, url, headers, trustAll, body);
+            doRequestAndCheckAssertions(ImmutableMap.of("timeout", timeout, "backoffToPeriod",
backoffToPeriod), 
+                    assertions, target, method, url, headers, trustAll, body);
             setUpAndRunState(true, Lifecycle.RUNNING);
 
         } catch (Throwable t) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
index db62103..08e9108 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
@@ -61,6 +61,7 @@ public class TestSensorImpl extends TargetableTestComponentImpl implements
TestS
             sensor.set(getRequiredConfig(SENSOR_NAME));
             final Entity target = resolveTarget();
             final Duration timeout = getConfig(TIMEOUT);
+            final Duration backoffToPeriod = getConfig(BACKOFF_TO_PERIOD);
             final List<Map<String, Object>> assertions = getAssertions(this,
ASSERTIONS);
             final List<Map<String, Object>> abortConditions = getAbortConditions(this,
ABORT_CONDITIONS);
             if (!getChildren().isEmpty()) {
@@ -74,7 +75,8 @@ public class TestSensorImpl extends TargetableTestComponentImpl implements
TestS
                     return sensorValue;
                 }
             };
-            TestFrameworkAssertions.checkAssertionsEventually(new AssertionOptions(sensor.get(),
supplier).timeout(timeout)
+            TestFrameworkAssertions.checkAssertionsEventually(new AssertionOptions(sensor.get(),
supplier)
+                    .timeout(timeout).backoffToPeriod(backoffToPeriod)
                     .assertions(assertions).abortConditions(abortConditions));
 
             setUpAndRunState(true, Lifecycle.RUNNING);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/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 6b5cf44..85d402c 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
@@ -32,6 +32,7 @@ import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
 import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
 import org.apache.brooklyn.entity.software.base.SoftwareProcess;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.apache.brooklyn.util.time.Duration;
 
 /**
  * Tests ssh command execution, against the {@link org.apache.brooklyn.location.ssh.SshMachineLocation}

@@ -45,6 +46,9 @@ public interface TestSshCommand extends BaseTest {
      */
     String TMP_DEFAULT = "/tmp";
 
+    // Change default period (backoff to 5 seconds, rather than default 500ms), because SSH
is expensive
+    ConfigKey<Duration> BACKOFF_TO_PERIOD = ConfigKeys.newConfigKeyWithDefault(BaseTest.BACKOFF_TO_PERIOD,
Duration.seconds(5));
+
     /**
      * Supply the command to invoke directly. Cannot be used together with {@link #DOWNLOAD_URL}.
      */

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/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 be7098a..9f4446f 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
@@ -126,10 +126,14 @@ public class TestSshCommandImpl extends TargetableTestComponentImpl
implements T
             final SshMachineLocation machineLocation =
                     Machines.findUniqueMachineLocation(resolveTarget().getLocations(), SshMachineLocation.class).get();
             final Duration timeout = getRequiredConfig(TIMEOUT);
+            final Duration backoffToPeriod = getRequiredConfig(BACKOFF_TO_PERIOD);
 
+            // TODO use TestFrameworkAssertions (or use Repeater in the same way as that
does)?
+            // Perhaps extract a helper method in TestFrameworkAssertions, so get consistent
behaviour
+            // for limitTimeTo, backoffTo, etc?
             ReferenceWithError<Boolean> result = Repeater.create("Running ssh-command
tests")
                     .limitTimeTo(timeout)
-                    .every(timeout.multiply(0.1))
+                    .backoffTo((backoffToPeriod != null) ? backoffToPeriod : Duration.millis(500))
                     .until(new Callable<Boolean>() {
                         @Override
                         public Boolean call() throws Exception {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestWinrmCommand.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestWinrmCommand.java
b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestWinrmCommand.java
index 3466796..5bcc808 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestWinrmCommand.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestWinrmCommand.java
@@ -26,6 +26,7 @@ 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 com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -37,6 +38,9 @@ import com.google.common.collect.ImmutableMap;
 @ImplementedBy(TestWinrmCommandImpl.class)
 public interface TestWinrmCommand extends BaseTest {
 
+    // Change default period (backoff to 5 seconds, rather than default 500ms), because WinRM
is expensive
+    ConfigKey<Duration> BACKOFF_TO_PERIOD = ConfigKeys.newConfigKeyWithDefault(BaseTest.BACKOFF_TO_PERIOD,
Duration.seconds(5));
+
     /**
      * Supply the PowerShell script to invoke directly.
      */

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestWinrmCommandImpl.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestWinrmCommandImpl.java
b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestWinrmCommandImpl.java
index f8b9e0d..f35163a 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestWinrmCommandImpl.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestWinrmCommandImpl.java
@@ -101,10 +101,13 @@ public class TestWinrmCommandImpl extends TargetableTestComponentImpl
implements
             final WinRmMachineLocation machineLocation =
                     Machines.findUniqueMachineLocation(resolveTarget().getLocations(), WinRmMachineLocation.class).get();
             final Duration timeout = getRequiredConfig(TIMEOUT);
+            final Duration backoffToPeriod = getRequiredConfig(BACKOFF_TO_PERIOD);
 
+            // TODO use TestFrameworkAssertions (or use Repeater in the same way as that
does)?
+            // See identical comment in `TestSshCommandImpl`.
             ReferenceWithError<Boolean> result = Repeater.create("Running winrm-command
tests")
                     .limitTimeTo(timeout)
-                    .every(timeout.multiply(0.1))
+                    .backoffTo((backoffToPeriod != null) ? backoffToPeriod : Duration.millis(500))
                     .until(new Callable<Boolean>() {
                         @Override
                         public Boolean call() throws Exception {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestFrameworkAssertionsTest.java
----------------------------------------------------------------------
diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestFrameworkAssertionsTest.java
b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestFrameworkAssertionsTest.java
index 9e79bfe..3999952 100644
--- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestFrameworkAssertionsTest.java
+++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestFrameworkAssertionsTest.java
@@ -18,8 +18,14 @@
  */
 package org.apache.brooklyn.test.framework;
 
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableMap;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.test.framework.TestFrameworkAssertions.AssertionOptions;
 import org.apache.brooklyn.util.text.Identifiers;
@@ -30,11 +36,11 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import com.google.common.base.Stopwatch;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
 
 public class TestFrameworkAssertionsTest {
     private static final Logger LOG = LoggerFactory.getLogger(TestFrameworkAssertionsTest.class);
@@ -79,7 +85,8 @@ public class TestFrameworkAssertionsTest {
             }
         };
         TestFrameworkAssertions.checkAssertionsEventually(new AssertionOptions(Objects.toString(data),
supplier)
-                .timeout(Asserts.DEFAULT_LONG_TIMEOUT).assertions(assertions));
+                .timeout(Asserts.DEFAULT_LONG_TIMEOUT)
+                .assertions(assertions));
     }
 
     @Test(dataProvider = "positiveTestsDP")
@@ -150,7 +157,8 @@ public class TestFrameworkAssertionsTest {
         Duration timeout = Duration.millis(1);
         
         try {
-            TestFrameworkAssertions.checkAssertionsEventually(new AssertionOptions(Objects.toString(data),
supplier).timeout(timeout).assertions(assertions));
+            TestFrameworkAssertions.checkAssertionsEventually(new AssertionOptions(Objects.toString(data),
supplier)
+                    .timeout(timeout).assertions(assertions));
             Asserts.shouldHaveFailedPreviously();
         } catch (AssertionError e) {
             Asserts.expectedFailureContains(e, Objects.toString(data), condition, expected.toString());
@@ -174,7 +182,8 @@ public class TestFrameworkAssertionsTest {
         // aborting.
         try {
             TestFrameworkAssertions.checkAssertionsEventually(new AssertionOptions(Objects.toString(data),
supplier)
-                    .timeout(timeout).abortConditions(assertions)
+                    .timeout(timeout)
+                    .abortConditions(assertions)
                     .assertions(assertions));
             Asserts.shouldHaveFailedPreviously();
         } catch (AssertionError e) {
@@ -205,5 +214,78 @@ public class TestFrameworkAssertionsTest {
         }
     }
 
+    // Integration because test is time-sensitive. May fail sometimes on highly contended
hardware.
+    // Also test takes a second to run.
+    @Test(groups="Integration")
+    public void testRetryBackoffs() {
+        final Stopwatch stopwatch = Stopwatch.createStarted();
+        final List<Duration> timestamps = Lists.newArrayList();
+        
+        final Supplier<Object> supplier = new Supplier<Object>() {
+            @Override
+            public Object get() {
+                timestamps.add(Duration.of(stopwatch));
+                return "myActualVal";
+            }
+        };
+        
+        try {
+            TestFrameworkAssertions.checkAssertionsEventually(new AssertionOptions("myTarget",
supplier)
+                    .timeout(Duration.seconds(1))
+                    .backoffToPeriod(Duration.millis(100))
+                    .assertions(Arrays.asList(ImmutableMap.of("isEqualTo", "myExpectedVal"))));
+            Asserts.shouldHaveFailedPreviously();
+        } catch (AssertionError e) {
+            Asserts.expectedFailureContains(e, "myTarget expected isEqualTo myExpectedVal
but found myActualVal");
+        }
 
+        List<Duration> timestampDiffs = getDiffsBetweenTimes(timestamps);
+        LOG.info("timestampDiffs="+timestampDiffs + "; timestamps="+timestamps);
+        
+        // Assert delays increase exponentially.
+        Duration initialDelay = Duration.millis(10);
+        Duration finalDelay = Duration.millis(100);
+        Duration earlyTollerance = Duration.millis(10);
+        Duration lateTollerance = Duration.millis(50);
+        Duration firstLateTollerance = Duration.millis(250); // first can cause class-loading
etc; accept slower
+        double multiplier = 1.2;
+        
+        for (int iteration = 1; iteration < timestampDiffs.size(); iteration++) {
+            Duration actualDelay = timestampDiffs.get(iteration);
+            Duration expectedDelay = initialDelay;
+            for (int i = 0; i < iteration; i++) {
+                expectedDelay = expectedDelay.multiply(multiplier);
+                if (finalDelay!=null && expectedDelay.compareTo(finalDelay) >
0) {
+                    expectedDelay = finalDelay;
+                    break;
+                }
+            }
+            Duration min = Duration.max(expectedDelay.subtract(earlyTollerance), Duration.ZERO);
+            Duration max = expectedDelay.add((iteration == 0) ? firstLateTollerance : lateTollerance);
+            String errMsg = "invalid time-diff at " + iteration+": " + timestampDiffs;
+            assertOrdered(ImmutableList.of(min, actualDelay, max), errMsg);
+        }
+    }
+    
+    private void assertOrdered(List<Duration> timestamps, String errMsg) {
+        Duration prev = null;
+        for (Duration timestamp : timestamps) {
+            if (prev != null) {
+                assertTrue(prev.toMilliseconds() <= timestamp.toMilliseconds(), errMsg);
+            }
+            prev = timestamp;
+        }
+    }
+    
+    private List<Duration> getDiffsBetweenTimes(List<Duration> timestamps) {
+        List<Duration> result = Lists.newArrayList();
+        Duration prev = null;
+        for (Duration timestamp : timestamps) {
+            if (prev != null) {
+                result.add(timestamp.subtract(prev));
+            }
+            prev = timestamp;
+        }
+        return result;
+    }
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8add7142/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
----------------------------------------------------------------------
diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
index 906b25f..97ed480 100644
--- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
+++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
@@ -352,6 +352,7 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport {
         // Then we'll let it complete by setting the sensor.
         TestSensor testCase = app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TIMEOUT, Asserts.DEFAULT_LONG_TIMEOUT)
+                .configure(TestSensor.BACKOFF_TO_PERIOD, Duration.millis(1))
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName())
                 .configure(TestSensor.ASSERTIONS, newListAssertion("matches", String.format(".*%s.*",
time))));


Mime
View raw message