You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/08/06 18:33:48 UTC

[2/4] incubator-brooklyn git commit: Test lifecycle phases of BasicStartable

Test lifecycle phases of BasicStartable


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/379d6a1d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/379d6a1d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/379d6a1d

Branch: refs/heads/master
Commit: 379d6a1d5908dd25cccaf82e853ff9d7693734ed
Parents: 614cbb2
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Thu Aug 6 16:01:36 2015 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Thu Aug 6 16:01:57 2015 +0100

----------------------------------------------------------------------
 .../entity/basic/ServiceStateLogic.java         |   7 +-
 .../entity/basic/BasicStartableTest.java        |  33 +++++-
 .../basic/RecordingSensorEventListener.java     | 115 +++++++++++++++++++
 3 files changed, 148 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/379d6a1d/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java b/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
index eff8e2d..3b1efbe 100644
--- a/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
+++ b/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
@@ -149,8 +149,11 @@ public class ServiceStateLogic {
             if (!Boolean.TRUE.equals(up) && !Boolean.TRUE.equals(Entities.isReadOnly(entity))) {
                 // pause briefly to allow any recent problem-clearing processing to complete
                 Stopwatch timer = Stopwatch.createStarted();
-                boolean nowUp = Repeater.create().every(ValueResolver.REAL_QUICK_PERIOD).limitTimeTo(ValueResolver.PRETTY_QUICK_WAIT).until(entity, 
-                    EntityPredicates.attributeEqualTo(Attributes.SERVICE_UP, true)).run();
+                boolean nowUp = Repeater.create()
+                        .every(ValueResolver.REAL_QUICK_PERIOD)
+                        .limitTimeTo(ValueResolver.PRETTY_QUICK_WAIT)
+                        .until(entity, EntityPredicates.attributeEqualTo(Attributes.SERVICE_UP, true))
+                        .run();
                 if (nowUp) {
                     log.debug("Had to wait "+Duration.of(timer)+" for "+entity+" "+Attributes.SERVICE_UP+" to be true before setting "+state);
                 } else {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/379d6a1d/core/src/test/java/brooklyn/entity/basic/BasicStartableTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/BasicStartableTest.java b/core/src/test/java/brooklyn/entity/basic/BasicStartableTest.java
index b7d47e5..2f8db0c 100644
--- a/core/src/test/java/brooklyn/entity/basic/BasicStartableTest.java
+++ b/core/src/test/java/brooklyn/entity/basic/BasicStartableTest.java
@@ -21,13 +21,20 @@ package brooklyn.entity.basic;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNull;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.apache.brooklyn.entity.basic.RecordingSensorEventListener;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
 import brooklyn.entity.Entity;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.location.Location;
@@ -40,11 +47,6 @@ import brooklyn.test.entity.TestApplication;
 import brooklyn.test.entity.TestEntity;
 import brooklyn.util.collections.MutableSet;
 
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
 public class BasicStartableTest {
 
     private ManagementContext managementContext;
@@ -141,6 +143,27 @@ public class BasicStartableTest {
         assertEqualsIgnoringOrder(entity.getLocations(), ImmutableSet.of());
         assertNull(called.get());
     }
+
+    @Test
+    public void testTransitionsThroughLifecycles() throws Exception {
+        startable = app.addChild(EntitySpec.create(BasicStartable.class));
+        RecordingSensorEventListener<Lifecycle> listener = new RecordingSensorEventListener<Lifecycle>(true);
+        managementContext.getSubscriptionContext(startable)
+                .subscribe(startable, Attributes.SERVICE_STATE_ACTUAL, listener);
+
+        Entities.startManagement(startable);
+        app.start(ImmutableList.of(loc1));
+        app.stop();
+
+        ArrayList<Lifecycle> expected = Lists.newArrayList(
+                Lifecycle.STARTING,
+                Lifecycle.RUNNING,
+                Lifecycle.STOPPING,
+                Lifecycle.STOPPED);
+        Iterable<Lifecycle> actual = listener.getEventValuesSortedByTimestamp();
+        assertEquals(actual, expected,
+                "Expected=" + Iterables.toString(expected) + ", actual=" + Iterables.toString(actual));
+    }
     
     private void assertEqualsIgnoringOrder(Iterable<? extends Object> col1, Iterable<? extends Object> col2) {
         assertEquals(Iterables.size(col1), Iterables.size(col2), "col2="+col1+"; col2="+col2);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/379d6a1d/core/src/test/java/org/apache/brooklyn/entity/basic/RecordingSensorEventListener.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/entity/basic/RecordingSensorEventListener.java b/core/src/test/java/org/apache/brooklyn/entity/basic/RecordingSensorEventListener.java
new file mode 100644
index 0000000..067b7d4
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/entity/basic/RecordingSensorEventListener.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.brooklyn.entity.basic;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Longs;
+
+import brooklyn.event.SensorEvent;
+import brooklyn.event.SensorEventListener;
+
+/**
+ * An event listener that records each event and allows callers to access all values and
+ * all values sorted by event timestamp.
+ */
+public class RecordingSensorEventListener<T> implements SensorEventListener<T>, Iterable<SensorEvent<T>> {
+
+    private final List<SensorEvent<T>> events = Lists.newCopyOnWriteArrayList();
+    private final boolean suppressDuplicates;
+    private T lastValue;
+
+    public RecordingSensorEventListener() {
+        this(false);
+    }
+
+    public RecordingSensorEventListener(boolean suppressDuplicates) {
+        this.suppressDuplicates = suppressDuplicates;
+    }
+
+    @Override
+    public void onEvent(SensorEvent<T> event) {
+        if (!suppressDuplicates || events.isEmpty() || !Objects.equals(lastValue, event.getValue())) {
+            events.add(event);
+            lastValue = event.getValue();
+        }
+    }
+
+    /**
+     * @return An immutable iterable of the recorded events.
+     */
+    public Iterable<SensorEvent<T>> getEvents() {
+        return ImmutableList.copyOf(events);
+    }
+
+    /**
+     * @return A live read-only view of recorded events.
+     */
+    public Iterable<T> getEventValues() {
+        return FluentIterable.from(events)
+                .transform(new GetValueFunction<T>());
+    }
+
+    /**
+     * @return A static read-only view of event values sorted by the time at which they occurred.
+     */
+    public Iterable<T> getEventValuesSortedByTimestamp() {
+        List<SensorEvent<T>> copy = Lists.newArrayList(events);
+        Collections.sort(copy, new EventTimestampComparator());
+        return FluentIterable.from(copy)
+                .transform(new GetValueFunction<T>());
+    }
+
+    /**
+     * Clears all events recorded by the listener.
+     */
+    public void clearEvents() {
+        this.events.clear();
+        lastValue = null;
+    }
+
+    @Override
+    public Iterator<SensorEvent<T>> iterator() {
+        return getEvents().iterator();
+    }
+
+    private static class GetValueFunction<T> implements Function<SensorEvent<T>, T> {
+        @Override
+        public T apply(SensorEvent<T> input) {
+            return input.getValue();
+        }
+    }
+
+    private static class EventTimestampComparator implements Comparator<SensorEvent<?>> {
+        @Override
+        public int compare(SensorEvent<?> o1, SensorEvent<?> o2) {
+            return Longs.compare(o1.getTimestamp(), o2.getTimestamp());
+        }
+    }
+
+}