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/08/20 00:53:54 UTC
[06/36] incubator-brooklyn git commit: Rename o.a.b.effector.core to
o.a.b.core.effector
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/core/effector/EffectorSayHiTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/EffectorSayHiTest.java b/core/src/test/java/org/apache/brooklyn/core/effector/EffectorSayHiTest.java
new file mode 100644
index 0000000..76dcdba
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/effector/EffectorSayHiTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.core.effector;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.effector.Effector;
+import org.apache.brooklyn.api.effector.ParameterType;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.mgmt.ExecutionContext;
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.core.annotation.EffectorParam;
+import org.apache.brooklyn.core.effector.MethodEffector;
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
+import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.task.BasicTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+/**
+ * Test the operation of the {@link Effector} implementations.
+ *
+ * TODO clarify test purpose
+ */
+public class EffectorSayHiTest extends BrooklynAppUnitTestSupport {
+
+ //TODO test edge/error conditions
+ //(missing parameters, wrong number of params, etc)
+
+ private static final Logger log = LoggerFactory.getLogger(EffectorSayHiTest.class);
+
+ private MyEntity e;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ e = app.createAndManageChild(EntitySpec.create(MyEntity.class));
+ }
+
+ @Test
+ public void testFindEffectorMetaData() {
+ assertEquals("sayHi1", e.SAY_HI_1.getName());
+ assertEquals("says hello", e.SAY_HI_1.getDescription());
+
+ assertEquals(ImmutableList.of("name", "greeting"), getParameterNames(e.SAY_HI_1));
+ assertEquals(MutableMap.of("name", null, "greeting", "what to say"), getParameterDescriptions(e.SAY_HI_1));
+ }
+
+ @Test
+ public void testFindTraitEffectors() {
+ assertEquals(ImmutableList.of("locations"), getParameterNames(Startable.START));
+ }
+
+ @Test
+ public void testInvokeEffectors1() throws Exception {
+ assertEquals("hi Bob", e.sayHi1("Bob", "hi"));
+
+ assertEquals("hi Bob", e.SAY_HI_1.call(e, ImmutableMap.of("name", "Bob", "greeting", "hi")) );
+ assertEquals("hi Bob", e.invoke(e.SAY_HI_1, ImmutableMap.of("name", "Bob", "greeting", "hi")).get() );
+
+ // and with default greeting param value
+ assertEquals("hi Bob", e.SAY_HI_1.call(e, ImmutableMap.of("name", "Bob", "greeting", "hi")) );
+ assertEquals("hello Bob", e.invoke(e.SAY_HI_1, ImmutableMap.of("name", "Bob")).get() );
+ }
+
+ @Test
+ public void testCanRetrieveTaskForEffector() {
+ e.sayHi1("Bob", "hi");
+
+ Set<Task<?>> tasks = mgmt.getExecutionManager().getTasksWithAllTags(ImmutableList.of(
+ BrooklynTaskTags.tagForContextEntity(e),ManagementContextInternal.EFFECTOR_TAG));
+ assertEquals(tasks.size(), 1);
+ assertTrue(tasks.iterator().next().getDescription().contains("sayHi1"));
+ }
+
+ @Test
+ public void testDelegatedNestedEffectorNotRepresentedAsTask() {
+ e.delegateSayHi1("Bob", "hi");
+
+ Set<Task<?>> tasks = mgmt.getExecutionManager().getTasksWithAllTags(ImmutableList.of(
+ BrooklynTaskTags.tagForContextEntity(e),ManagementContextInternal.EFFECTOR_TAG));
+ assertEquals(tasks.size(), 1);
+ assertTrue(tasks.iterator().next().getDescription().contains("delegateSayHi1"));
+ assertFalse(tasks.iterator().next().getDescription().contains("sayHi1"));
+ }
+
+ @Test
+ public void testCanExcludeNonEffectorTasks() throws Exception {
+ ExecutionContext executionContext = mgmt.getExecutionContext(e);
+ executionContext.submit(new BasicTask<Void>(new Runnable() { public void run() {} }));
+
+ Set<Task<?>> effectTasks = mgmt.getExecutionManager().getTasksWithAllTags(ImmutableList.of(
+ BrooklynTaskTags.tagForContextEntity(e),ManagementContextInternal.EFFECTOR_TAG));
+ assertEquals(effectTasks.size(), 0);
+ }
+
+ public interface CanSayHi {
+ static MethodEffector<String> SAY_HI_1 = new MethodEffector<String>(CanSayHi.class, "sayHi1");
+ static MethodEffector<String> DELEGATE_SAY_HI_1 = new MethodEffector<String>(CanSayHi.class, "delegateSayHi1");
+
+ @org.apache.brooklyn.core.annotation.Effector(description="says hello")
+ public String sayHi1(
+ @EffectorParam(name="name") String name,
+ @EffectorParam(name="greeting", defaultValue="hello", description="what to say") String greeting);
+
+ @org.apache.brooklyn.core.annotation.Effector(description="delegate says hello")
+ public String delegateSayHi1(
+ @EffectorParam(name="name") String name,
+ @EffectorParam(name="greeting") String greeting);
+ }
+
+ @ImplementedBy(MyEntityImpl.class)
+ public interface MyEntity extends Entity, CanSayHi {
+ }
+
+ public static class MyEntityImpl extends AbstractEntity implements MyEntity {
+ @Override
+ public String sayHi1(String name, String greeting) {
+ return greeting+" "+name;
+ }
+ @Override
+ public String delegateSayHi1(String name, String greeting) {
+ return sayHi1(name, greeting);
+ }
+ }
+
+ private List<String> getParameterNames(Effector<?> effector) {
+ return ImmutableList.copyOf(getParameterDescriptions(effector).keySet());
+ }
+
+ private Map<String, String> getParameterDescriptions(Effector<?> effector) {
+ Map<String,String> result = Maps.newLinkedHashMap();
+ for (ParameterType<?> parameter : effector.getParameters()) {
+ result.put(parameter.getName(), parameter.getDescription());
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/core/effector/EffectorTaskTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/EffectorTaskTest.java b/core/src/test/java/org/apache/brooklyn/core/effector/EffectorTaskTest.java
new file mode 100644
index 0000000..3e79aa9
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/effector/EffectorTaskTest.java
@@ -0,0 +1,437 @@
+/*
+ * 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.core.effector;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.brooklyn.api.effector.Effector;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.HasTaskChildren;
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.core.effector.EffectorBody;
+import org.apache.brooklyn.core.effector.EffectorTasks;
+import org.apache.brooklyn.core.effector.EffectorWithBody;
+import org.apache.brooklyn.core.effector.Effectors;
+import org.apache.brooklyn.core.effector.EffectorTasks.EffectorTaskFactory;
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.task.DynamicSequentialTask;
+import org.apache.brooklyn.util.core.task.DynamicTasks;
+import org.apache.brooklyn.util.core.task.TaskBuilder;
+import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+public class EffectorTaskTest extends BrooklynAppUnitTestSupport {
+
+ // ----------- syntax 1 -- effector with body in a class
+
+ public static final Effector<Integer> DOUBLE_1 = Effectors.effector(Integer.class, "double")
+ .description("doubles the given number")
+ .parameter(Integer.class, "numberToDouble")
+ .impl(new EffectorBody<Integer>() {
+ @Override
+ public Integer call(ConfigBag parameters) {
+ // do a sanity check
+ Assert.assertNotNull(entity());
+
+ // finally double the input
+ return 2*(Integer)parameters.getStringKey("numberToDouble");
+ }
+ })
+ .build();
+
+ public static class DoublingEntity extends AbstractEntity {
+ public static final Effector<Integer> DOUBLE = EffectorTaskTest.DOUBLE_1;
+ }
+
+ @Test
+ public void testSyntaxOneDouble1() throws Exception {
+ // just use "dynamic" support of effector
+ Assert.assertEquals(app.invoke(DOUBLE_1, MutableMap.of("numberToDouble", 3)).get(), (Integer)6);
+ }
+
+ @Test
+ public void testSyntaxOneTaggedCorrectly() throws Exception {
+ Task<Integer> t = app.invoke(DOUBLE_1, MutableMap.of("numberToDouble", 3));
+ t.get();
+ checkTags(t, app, DOUBLE_1, false);
+ }
+
+ @Test
+ // also assert it works when the effector is defined on an entity
+ public void testSimpleEffectorOnEntity() throws Exception {
+ Entity doubler = app.createAndManageChild(EntitySpec.create(Entity.class, DoublingEntity.class));
+
+ Assert.assertEquals(doubler.invoke(DOUBLE_1, MutableMap.of("numberToDouble", 3)).get(), (Integer)6);
+ }
+
+ @Test
+ // also assert it works when an abstract effector name is passed in to the entity
+ public void testSimpleEffectorNameMatching() throws Exception {
+ Entity doubler = app.createAndManageChild(EntitySpec.create(Entity.class, DoublingEntity.class));
+
+ Assert.assertEquals(doubler.invoke(Effectors.effector(Integer.class, "double").buildAbstract(), MutableMap.of("numberToDouble", 3)).get(), (Integer)6);
+ }
+
+
+ // ----------- syntax 2 -- effector with body built with fluent API
+
+ public static EffectorTaskFactory<Integer> times(final EffectorTaskFactory<Integer> x, final int y) {
+ return new EffectorTaskFactory<Integer>() {
+ @Override
+ public Task<Integer> newTask(final Entity entity, final Effector<Integer> effector, final ConfigBag parameters) {
+ return TaskBuilder.<Integer>builder().name("times").body(new Callable<Integer>() { public Integer call() {
+ return DynamicTasks.get( x.newTask(entity, effector, parameters) )*y;
+ } }).build();
+ }
+ };
+ }
+
+ public static final Effector<Integer> DOUBLE_2 = Effectors.effector(Integer.class, "double")
+ .description("doubles the given number")
+ .parameter(Integer.class, "numberToDouble")
+ .impl(times(EffectorTasks.parameter(Integer.class, "numberToDouble"), 2))
+ .build();
+
+ @Test
+ public void testSyntaxTwoDouble2() throws Exception {
+ Assert.assertEquals(app.invoke(DOUBLE_2, MutableMap.of("numberToDouble", 3)).get(), (Integer)6);
+ }
+
+ @Test
+ public void testEffectorImplTaggedCorrectly() throws Exception {
+ Task<Integer> t = app.invoke(DOUBLE_2, MutableMap.of("numberToDouble", 3));
+ t.get();
+ checkTags(t, app, DOUBLE_2, true);
+ }
+
+ public static final Effector<Integer> DOUBLE_CALL_ABSTRACT = Effectors.effector(Integer.class, "double_call")
+ .description("doubles the given number")
+ .parameter(Integer.class, "numberToDouble")
+ .buildAbstract();
+ public static final Effector<Integer> DOUBLE_CALL = Effectors.effector(DOUBLE_CALL_ABSTRACT)
+ .impl(new EffectorBody<Integer>() {
+ @Override
+ public Integer call(ConfigBag parameters) {
+ final Entity parent = entity();
+ final Entity child = Iterables.getOnlyElement(entity().getChildren());
+
+ final Effector<Integer> DOUBLE_CHECK_ABSTRACT = Effectors.effector(Integer.class, "double_check")
+ .description("doubles the given number and checks tags, assuming double exists as an effector here")
+ .parameter(Integer.class, "numberToDouble")
+ .buildAbstract();
+ Effector<Integer> DOUBLE_CHECK = Effectors.effector(DOUBLE_CHECK_ABSTRACT)
+ .impl(new EffectorBody<Integer>() {
+ @Override
+ public Integer call(ConfigBag parameters) {
+ Assert.assertTrue(BrooklynTaskTags.isInEffectorTask(Tasks.current(), child, null, false));
+ Assert.assertTrue(BrooklynTaskTags.isInEffectorTask(Tasks.current(), child, DOUBLE_CHECK_ABSTRACT, false));
+ Assert.assertFalse(BrooklynTaskTags.isInEffectorTask(Tasks.current(), child, DOUBLE_1, false));
+ Assert.assertTrue(BrooklynTaskTags.isInEffectorTask(Tasks.current(), parent, null, true));
+ Assert.assertFalse(BrooklynTaskTags.isInEffectorTask(Tasks.current(), parent, null, false));
+ Assert.assertTrue(BrooklynTaskTags.isInEffectorTask(Tasks.current(), parent, DOUBLE_CALL_ABSTRACT, true));
+ Assert.assertFalse(BrooklynTaskTags.isInEffectorTask(Tasks.current(), parent, DOUBLE_1, true));
+
+ return entity().invoke(DOUBLE_1, parameters.getAllConfig()).getUnchecked();
+ }
+ }).build();
+
+ return child.invoke(DOUBLE_CHECK, parameters.getAllConfig()).getUnchecked();
+ }
+ }).build();
+
+
+ @Test
+ // also assert it works when the effector is defined on an entity
+ public void testNestedEffectorTag() throws Exception {
+ app.createAndManageChild(EntitySpec.create(Entity.class, DoublingEntity.class));
+ Assert.assertEquals(app.invoke(DOUBLE_CALL, MutableMap.of("numberToDouble", 3)).get(), (Integer)6);
+ }
+
+
+ private void checkTags(Task<Integer> t, Entity entity, Effector<?> eff, boolean shouldHaveChild) {
+ Assert.assertEquals(BrooklynTaskTags.getContextEntity(t), app);
+ Assert.assertTrue(t.getTags().contains(BrooklynTaskTags.EFFECTOR_TAG), "missing effector tag; had: "+t.getTags());
+ Assert.assertTrue(t.getDescription().contains(eff.getName()), "description missing effector name: "+t.getDescription());
+ Assert.assertTrue(BrooklynTaskTags.isInEffectorTask(t, entity, eff, false));
+ Assert.assertTrue(BrooklynTaskTags.isInEffectorTask(t, null, null, false));
+ Assert.assertFalse(BrooklynTaskTags.isInEffectorTask(t, entity, Startable.START, false));
+
+ if (shouldHaveChild) {
+ Task<?> subtask = ((HasTaskChildren)t).getChildren().iterator().next();
+ Assert.assertTrue(BrooklynTaskTags.isInEffectorTask(subtask, entity, eff, false));
+ Assert.assertTrue(BrooklynTaskTags.isInEffectorTask(subtask, null, null, false));
+ }
+ }
+
+ // TEST parameter task missing
+
+ // ----------------- syntax for more complex -- an effector using subtasks
+
+ public static Task<Integer> add(final int x, final int y) {
+ return TaskBuilder.<Integer>builder().name("add").body(new Callable<Integer>() { public Integer call() { return x+y; } }).build();
+ }
+
+ public static Task<Integer> add(final Task<Integer> x, final int y) {
+ return TaskBuilder.<Integer>builder().name("add").body(new Callable<Integer>() { public Integer call() { return DynamicTasks.get(x)+y; } }).build();
+ }
+
+ public static Task<Integer> addBasic(final Task<Integer> x, final int y) {
+ return TaskBuilder.<Integer>builder().name("add (not dynamic)").dynamic(false).body(new Callable<Integer>() { public Integer call() {
+ Preconditions.checkState(x.isSubmitted());
+ return x.getUnchecked()+y;
+ } }).build();
+ }
+
+ public static Task<Integer> times(final int x, final int y) {
+ return TaskBuilder.<Integer>builder().name("times").body(new Callable<Integer>() { public Integer call() { return x*y; } }).build();
+ }
+
+ public static Task<Integer> times(final Task<Integer> x, final int y) {
+ return TaskBuilder.<Integer>builder().name("times").body(new Callable<Integer>() { public Integer call() { return DynamicTasks.get(x)*y; } }).build();
+ }
+
+ public static final Effector<Integer> TWO_X_PLUS_ONE = Effectors.effector(Integer.class, "twoXPlusOne")
+ .description("doubles the given number and adds one")
+ .parameter(Integer.class, "numberToStartWith")
+ .impl(new EffectorBody<Integer>() {
+ public Integer call(ConfigBag parameters) {
+ int input = (Integer)parameters.getStringKey("numberToStartWith");
+ queue( add(times(input, 2), 1) );
+ return last(Integer.class);
+ }
+ })
+ .build();
+
+ public static final Effector<Integer> TWO_X_PLUS_ONE_BASIC = Effectors.effector(Integer.class, "twoXPlusOne_Basic")
+ .description("doubles the given number and adds one, as a basic task")
+ .parameter(Integer.class, "numberToStartWith")
+ .impl(new EffectorBody<Integer>() {
+ public Integer call(ConfigBag parameters) {
+ int input = (Integer)parameters.getStringKey("numberToStartWith");
+ // note the subtasks must be queued explicitly with a basic task
+ // (but with the DynamicSequentialTask they can be resolved by the task itself; see above)
+ Task<Integer> product = queue(times(input, 2));
+ queue( addBasic(product, 1) );
+ return last(Integer.class);
+ }
+ })
+ .build();
+
+ // TODO a chaining style approach
+
+ public static class Txp1Entity extends AbstractEntity {
+ public static final Effector<Integer> TWO_X_P_1 = EffectorTaskTest.TWO_X_PLUS_ONE;
+ }
+
+ /** the composed effector should allow us to inspect its children */
+ @Test
+ public void testComposedEffector() throws Exception {
+ Entity txp1 = app.createAndManageChild(EntitySpec.create(Entity.class, Txp1Entity.class));
+
+ Task<Integer> e = txp1.invoke(TWO_X_PLUS_ONE, MutableMap.of("numberToStartWith", 3));
+ Assert.assertTrue(e instanceof DynamicSequentialTask);
+ Assert.assertEquals(e.get(), (Integer)7);
+ Assert.assertEquals( Iterables.size( ((HasTaskChildren)e).getChildren() ), 1);
+ Task<?> child = ((HasTaskChildren)e).getChildren().iterator().next();
+ Assert.assertEquals( Iterables.size( ((HasTaskChildren)child).getChildren() ), 1);
+ }
+
+ /** the composed effector should allow us to inspect its children */
+ @Test
+ public void testComposedEffectorBasic() throws Exception {
+ Entity txp1 = app.createAndManageChild(EntitySpec.create(Entity.class, Txp1Entity.class));
+
+ Task<Integer> e = txp1.invoke(TWO_X_PLUS_ONE_BASIC, MutableMap.of("numberToStartWith", 3));
+ Assert.assertTrue(e instanceof DynamicSequentialTask);
+ Assert.assertEquals(e.get(), (Integer)7);
+ Assert.assertEquals( Iterables.size( ((HasTaskChildren)e).getChildren() ), 2);
+ }
+
+ // --------- defining
+
+ @Test
+ public void testEffectorWithBodyWorksEvenIfNotOnEntity() throws Exception {
+ Entity doubler = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ Assert.assertEquals(doubler.invoke(DOUBLE_1, MutableMap.of("numberToDouble", 3)).get(), (Integer)6);
+ }
+
+ public static final Effector<Integer> DOUBLE_BODYLESS = Effectors.effector(Integer.class, "double")
+ .description("doubles the given number")
+ .parameter(Integer.class, "numberToDouble")
+ .buildAbstract();
+
+ @Test
+ public void testEffectorWithoutBodyFails() throws Exception {
+ Entity doubler = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ boolean failed = false;
+ try {
+ doubler.invoke(DOUBLE_BODYLESS, MutableMap.of("numberToDouble", 3));
+ } catch (Exception e) {
+ failed = true;
+ }
+ if (!failed) Assert.fail("doubling should have failed because it had no body");
+ }
+
+ @Test
+ public void testEffectorBodyAdded() throws Exception {
+ EntityInternal doubler = (EntityInternal) app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ // not yet present
+ Assert.assertNull( doubler.getEffector("double") );
+
+ // add it
+ doubler.getMutableEntityType().addEffector(DOUBLE_BODYLESS, new EffectorBody<Integer>() {
+ @Override
+ public Integer call(ConfigBag parameters) {
+ int input = (Integer)parameters.getStringKey("numberToDouble");
+ return queue(times(input, 2)).getUnchecked();
+ }
+ });
+ // now it is present
+ Assert.assertNotNull( doubler.getEffector("double") );
+
+ Assert.assertEquals(doubler.invoke(DOUBLE_BODYLESS, MutableMap.of("numberToDouble", 3)).get(), (Integer)6);
+ }
+
+ @Test
+ public void testEffectorBodyAddedImplicitlyButBodylessSignatureInvoked() throws Exception {
+ EntityInternal doubler = (EntityInternal) app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ // add it
+ doubler.getMutableEntityType().addEffector(DOUBLE_1);
+
+ // invoke it, but using something with equivalent name (and signature -- though only name is used currently)
+ // ensures that the call picks up the body by looking in the actual entity
+ Assert.assertEquals(doubler.invoke(DOUBLE_BODYLESS, MutableMap.of("numberToDouble", 3)).get(), (Integer)6);
+ }
+
+ @Test(dependsOnMethods={"testEffectorBodyAdded"})
+ public void testEntityNotPermanentlyChanged() throws Exception {
+ EntityInternal doubler = (EntityInternal) app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ // ensures that independent creations of the class previously modified do not have this effector
+ Assert.assertNull( doubler.getEffector("double") );
+ }
+
+ // --- overriding by using statics ---------
+
+ public static class BadDoublingEntity extends DoublingEntity {
+ public static final Effector<Integer> DOUBLE = Effectors.effector(DoublingEntity.DOUBLE).
+ impl( ((EffectorWithBody<Integer>)TWO_X_PLUS_ONE).getBody() ).build();
+ }
+
+ @Test
+ // also assert it works when the entity is defined on an entity
+ public void testOverriddenEffectorOnEntity() throws Exception {
+ Entity doubler = app.createAndManageChild(EntitySpec.create(Entity.class, BadDoublingEntity.class));
+
+ Assert.assertEquals(doubler.invoke(DoublingEntity.DOUBLE, MutableMap.of("numberToDouble", 3, "numberToStartWith", 3)).get(), (Integer)7);
+ }
+
+ public static final Effector<Void> DUMMY = Effectors.effector(Void.class, "dummy")
+ .impl(new EffectorBody<Void>() {
+ @Override
+ public Void call(ConfigBag parameters) {
+ return null;
+ }
+ })
+ .build();
+
+ public static final Effector<Void> STALL = Effectors.effector(Void.class, "stall")
+ .parameter(AtomicBoolean.class, "lock")
+ .impl(new EffectorBody<Void>() {
+ @Override
+ public Void call(ConfigBag parameters) {
+ AtomicBoolean lock = (AtomicBoolean)parameters.getStringKey("lock");
+ synchronized(lock) {
+ if (!lock.get()) {
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ Exceptions.propagate(e);
+ }
+ }
+ }
+ return null;
+ }
+ })
+ .build();
+
+ public static final Effector<Void> CONTEXT = Effectors.effector(Void.class, "stall_caller")
+ .parameter(AtomicBoolean.class, "lock")
+ .impl(new EffectorBody<Void>() {
+ @Override
+ public Void call(ConfigBag parameters) {
+ Entity child = Iterables.getOnlyElement(entity().getChildren());
+ AtomicBoolean lock = new AtomicBoolean();
+ Task<Void> dummyTask = null;
+
+ try {
+ // Queue a (DST secondary) task which waits until notified, so that tasks queued later will get blocked
+ queue(Effectors.invocation(entity(), STALL, ImmutableMap.of("lock", lock)));
+
+ // Start a new task - submitted directly to child's ExecutionContext, as well as added as a
+ // DST secondary of the current effector.
+ dummyTask = child.invoke(DUMMY, ImmutableMap.<String, Object>of());
+ dummyTask.getUnchecked();
+
+ // Execution completed in the child's ExecutionContext, but still queued as a secondary.
+ // Destroy the child entity so that no subsequent tasks can be executed in its context.
+ Entities.destroy(child);
+ } finally {
+ // Let STALL complete
+ synchronized(lock) {
+ lock.set(true);
+ lock.notifyAll();
+ }
+ // At this point DUMMY will be unblocked and the DST will try to execute it as a secondary.
+ // Submission will be ignored because DUMMY already executed.
+ // If it's not ignored then submission will fail because entity is already unmanaged.
+ }
+ return null;
+ }
+ })
+ .build();
+
+
+ @Test
+ public void testNestedEffectorExecutedAsSecondaryTask() throws Exception {
+ app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ Task<Void> effTask = app.invoke(CONTEXT, ImmutableMap.<String, Object>of());
+ effTask.get();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasksTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasksTest.java b/core/src/test/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasksTest.java
new file mode 100644
index 0000000..fce676a
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasksTest.java
@@ -0,0 +1,265 @@
+/*
+ * 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.core.effector.ssh;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.TaskAdaptable;
+import org.apache.brooklyn.api.mgmt.TaskFactory;
+import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks;
+import org.apache.brooklyn.core.effector.ssh.SshEffectorTasksTest;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.util.core.task.ssh.SshFetchTaskWrapper;
+import org.apache.brooklyn.util.core.task.ssh.SshPutTaskWrapper;
+import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
+import org.apache.brooklyn.util.net.Urls;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+
+import com.google.common.io.Files;
+
+public class SshEffectorTasksTest {
+
+ private static final Logger log = LoggerFactory.getLogger(SshEffectorTasksTest.class);
+
+ TestApplication app;
+ ManagementContext mgmt;
+ SshMachineLocation host;
+ File tempDir;
+
+ boolean failureExpected;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setup() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ mgmt = app.getManagementContext();
+
+ LocalhostMachineProvisioningLocation lhc = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class));
+ host = lhc.obtain();
+ app.start(Arrays.asList(host));
+ clearExpectedFailure();
+ tempDir = Files.createTempDir();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ mgmt = null;
+ FileUtils.deleteDirectory(tempDir);
+ checkExpectedFailure();
+ }
+
+ protected void checkExpectedFailure() {
+ if (failureExpected) {
+ clearExpectedFailure();
+ Assert.fail("Test should have thrown an exception but it did not.");
+ }
+ }
+
+ protected void clearExpectedFailure() {
+ failureExpected = false;
+ }
+
+ protected void setExpectingFailure() {
+ failureExpected = true;
+ }
+
+ public <T extends TaskAdaptable<?>> T submit(final TaskFactory<T> taskFactory) {
+ return Entities.submit(app, taskFactory);
+ }
+
+ // ------------------- basic ssh
+
+ @Test(groups="Integration")
+ public void testSshEchoHello() {
+ ProcessTaskWrapper<Integer> t = submit(SshEffectorTasks.ssh("sleep 1 ; echo hello world"));
+ Assert.assertFalse(t.isDone());
+ Assert.assertEquals(t.get(), (Integer)0);
+ Assert.assertEquals(t.getTask().getUnchecked(), (Integer)0);
+ Assert.assertEquals(t.getStdout().trim(), "hello world");
+ }
+
+ @Test(groups="Integration")
+ public void testSshPut() throws IOException {
+ String fn = Urls.mergePaths(tempDir.getPath(), "f1");
+ SshPutTaskWrapper t = submit(SshEffectorTasks.put(fn).contents("hello world"));
+ t.block();
+ Assert.assertEquals(FileUtils.readFileToString(new File(fn)), "hello world");
+ // and make sure this doesn't throw
+ Assert.assertTrue(t.isDone());
+ Assert.assertTrue(t.isSuccessful());
+ Assert.assertEquals(t.get(), null);
+ Assert.assertEquals(t.getExitCode(), (Integer)0);
+ }
+
+ @Test(groups="Integration")
+ public void testSshFetch() throws IOException {
+ String fn = Urls.mergePaths(tempDir.getPath(), "f2");
+ FileUtils.write(new File(fn), "hello fetched world");
+
+ SshFetchTaskWrapper t = submit(SshEffectorTasks.fetch(fn));
+ t.block();
+
+ Assert.assertTrue(t.isDone());
+ Assert.assertEquals(t.get(), "hello fetched world");
+ }
+
+ // ----------------- pid stuff
+
+ @Test(groups="Integration")
+ public void testNonRunningPid() {
+ ProcessTaskWrapper<Integer> t = submit(SshEffectorTasks.codePidRunning(99999));
+ Assert.assertNotEquals(t.getTask().getUnchecked(), (Integer)0);
+ Assert.assertNotEquals(t.getExitCode(), (Integer)0);
+ ProcessTaskWrapper<Boolean> t2 = submit(SshEffectorTasks.isPidRunning(99999));
+ Assert.assertFalse(t2.getTask().getUnchecked());
+ }
+
+ @Test(groups="Integration")
+ public void testNonRunningPidRequired() {
+ ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidRunning(99999));
+ setExpectingFailure();
+ try {
+ t.getTask().getUnchecked();
+ } catch (Exception e) {
+ log.info("The error if required PID is not found is: "+e);
+ clearExpectedFailure();
+ Assert.assertTrue(e.toString().contains("Process with PID"), "Expected nice clue in error but got: "+e);
+ }
+ checkExpectedFailure();
+ }
+
+ public static Integer getMyPid() {
+ try {
+ java.lang.management.RuntimeMXBean runtime =
+ java.lang.management.ManagementFactory.getRuntimeMXBean();
+ java.lang.reflect.Field jvm = runtime.getClass().getDeclaredField("jvm");
+ jvm.setAccessible(true);
+// sun.management.VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
+ Object mgmt = jvm.get(runtime);
+ java.lang.reflect.Method pid_method =
+ mgmt.getClass().getDeclaredMethod("getProcessId");
+ pid_method.setAccessible(true);
+
+ return (Integer) pid_method.invoke(mgmt);
+ } catch (Exception e) {
+ throw new PropagatedRuntimeException("Test depends on (fragile) getMyPid method which does not work here", e);
+ }
+ }
+
+ @Test(groups="Integration")
+ public void testRunningPid() {
+ ProcessTaskWrapper<Integer> t = submit(SshEffectorTasks.codePidRunning(getMyPid()));
+ Assert.assertEquals(t.getTask().getUnchecked(), (Integer)0);
+ ProcessTaskWrapper<Boolean> t2 = submit(SshEffectorTasks.isPidRunning(getMyPid()));
+ Assert.assertTrue(t2.getTask().getUnchecked());
+ }
+
+ @Test(groups="Integration")
+ public void testRunningPidFromFile() throws IOException {
+ File f = File.createTempFile("testBrooklynPid", ".pid");
+ Files.write( (""+getMyPid()).getBytes(), f );
+ ProcessTaskWrapper<Integer> t = submit(SshEffectorTasks.codePidFromFileRunning(f.getPath()));
+ Assert.assertEquals(t.getTask().getUnchecked(), (Integer)0);
+ ProcessTaskWrapper<Boolean> t2 = submit(SshEffectorTasks.isPidFromFileRunning(f.getPath()));
+ Assert.assertTrue(t2.getTask().getUnchecked());
+ }
+
+ @Test(groups="Integration")
+ public void testRequirePidFromFileOnFailure() throws IOException {
+ File f = File.createTempFile("testBrooklynPid", ".pid");
+ Files.write( "99999".getBytes(), f );
+ ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidFromFileRunning(f.getPath()));
+
+ setExpectingFailure();
+ try {
+ t.getTask().getUnchecked();
+ } catch (Exception e) {
+ log.info("The error if required PID is not found is: "+e);
+ clearExpectedFailure();
+ Assert.assertTrue(e.toString().contains("Process with PID"), "Expected nice clue in error but got: "+e);
+ Assert.assertEquals(t.getExitCode(), (Integer)1);
+ }
+ checkExpectedFailure();
+ }
+
+ @Test(groups="Integration")
+ public void testRequirePidFromFileOnFailureNoSuchFile() throws IOException {
+ ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidFromFileRunning("/path/does/not/exist/SADVQW"));
+
+ setExpectingFailure();
+ try {
+ t.getTask().getUnchecked();
+ } catch (Exception e) {
+ log.info("The error if required PID is not found is: "+e);
+ clearExpectedFailure();
+ Assert.assertTrue(e.toString().contains("Process with PID"), "Expected nice clue in error but got: "+e);
+ Assert.assertEquals(t.getExitCode(), (Integer)1);
+ }
+ checkExpectedFailure();
+ }
+
+ @Test(groups="Integration")
+ public void testRequirePidFromFileOnFailureTooManyFiles() throws IOException {
+ ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidFromFileRunning("/*"));
+
+ setExpectingFailure();
+ try {
+ t.getTask().getUnchecked();
+ } catch (Exception e) {
+ log.info("The error if required PID is not found is: "+e);
+ clearExpectedFailure();
+ Assert.assertTrue(e.toString().contains("Process with PID"), "Expected nice clue in error but got: "+e);
+ Assert.assertEquals(t.getExitCode(), (Integer)2);
+ }
+ checkExpectedFailure();
+ }
+
+ @Test(groups="Integration")
+ public void testRequirePidFromFileOnSuccess() throws IOException {
+ File f = File.createTempFile("testBrooklynPid", ".pid");
+ Files.write( (""+getMyPid()).getBytes(), f );
+ ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidFromFileRunning(f.getPath()));
+
+ t.getTask().getUnchecked();
+ }
+
+ @Test(groups="Integration")
+ public void testRequirePidFromFileOnSuccessAcceptsWildcards() throws IOException {
+ File f = File.createTempFile("testBrooklynPid", ".pid");
+ Files.write( (""+getMyPid()).getBytes(), f );
+ ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidFromFileRunning(f.getPath()+"*"));
+
+ t.getTask().getUnchecked();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/core/entity/DynamicEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/DynamicEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/DynamicEntityTest.java
index 885eb45..fb9276c 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/DynamicEntityTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/DynamicEntityTest.java
@@ -24,10 +24,10 @@ import static org.testng.Assert.assertFalse;
import org.apache.brooklyn.api.entity.EntityInitializer;
import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.effector.EffectorTaskTest;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.effector.core.EffectorTaskTest;
import org.apache.brooklyn.entity.stock.BasicEntity;
import org.apache.brooklyn.util.collections.MutableMap;
import org.testng.annotations.Test;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
index c01c5c9..cead05a 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
@@ -47,13 +47,13 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.api.sensor.Sensor;
+import org.apache.brooklyn.core.effector.MethodEffector;
import org.apache.brooklyn.core.entity.AbstractEntity;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.core.test.entity.TestEntityImpl;
-import org.apache.brooklyn.effector.core.MethodEffector;
import org.apache.brooklyn.sensor.core.BasicSensorEvent;
import org.apache.brooklyn.sensor.core.Sensors;
import org.apache.brooklyn.test.Asserts;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/core/entity/hello/HelloEntity.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/hello/HelloEntity.java b/core/src/test/java/org/apache/brooklyn/core/entity/hello/HelloEntity.java
index 9d14868..a217514 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/hello/HelloEntity.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/hello/HelloEntity.java
@@ -25,7 +25,7 @@ import org.apache.brooklyn.config.ConfigKey;
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.effector.core.MethodEffector;
+import org.apache.brooklyn.core.effector.MethodEffector;
import org.apache.brooklyn.entity.group.AbstractGroup;
import org.apache.brooklyn.sensor.core.BasicSensor;
import org.apache.brooklyn.sensor.core.Sensors;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
index f648419..1d50609 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
@@ -42,6 +42,7 @@ import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
import org.apache.brooklyn.core.catalog.internal.CatalogTestUtils;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.effector.Effectors;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
@@ -50,7 +51,6 @@ import org.apache.brooklyn.core.objs.proxy.InternalEntityFactory;
import org.apache.brooklyn.core.objs.proxy.InternalPolicyFactory;
import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.core.test.entity.TestApplication;
-import org.apache.brooklyn.effector.core.Effectors;
import org.apache.brooklyn.test.support.TestResourceUnavailableException;
import org.apache.brooklyn.util.core.osgi.Osgis;
import org.apache.brooklyn.util.guava.Maybe;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityDynamicTypeInfoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityDynamicTypeInfoTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityDynamicTypeInfoTest.java
index c25dd0e..3b9bbfb 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityDynamicTypeInfoTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityDynamicTypeInfoTest.java
@@ -29,10 +29,10 @@ import org.apache.brooklyn.api.effector.Effector;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.effector.EffectorBody;
+import org.apache.brooklyn.core.effector.Effectors;
import org.apache.brooklyn.core.test.entity.TestApplication;
import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.effector.core.EffectorBody;
-import org.apache.brooklyn.effector.core.Effectors;
import org.apache.brooklyn.util.core.config.ConfigBag;
import org.apache.brooklyn.util.stream.Streams;
import org.slf4j.Logger;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntity.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntity.java b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntity.java
index 2106f18..8c185a0 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntity.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntity.java
@@ -36,11 +36,11 @@ import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.config.ListConfigKey;
import org.apache.brooklyn.core.config.MapConfigKey;
import org.apache.brooklyn.core.config.SetConfigKey;
+import org.apache.brooklyn.core.effector.MethodEffector;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.trait.Startable;
-import org.apache.brooklyn.effector.core.MethodEffector;
import org.apache.brooklyn.sensor.core.BasicNotificationSensor;
import org.apache.brooklyn.sensor.core.Sensors;
import org.apache.brooklyn.util.collections.MutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/effector/core/EffectorBasicTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/effector/core/EffectorBasicTest.java b/core/src/test/java/org/apache/brooklyn/effector/core/EffectorBasicTest.java
deleted file mode 100644
index 786fe69..0000000
--- a/core/src/test/java/org/apache/brooklyn/effector/core/EffectorBasicTest.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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.effector.core;
-
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import org.apache.brooklyn.api.entity.EntityLocal;
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.mgmt.HasTaskChildren;
-import org.apache.brooklyn.api.mgmt.Task;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.trait.FailingEntity;
-import org.apache.brooklyn.core.entity.trait.Startable;
-import org.apache.brooklyn.core.location.SimulatedLocation;
-import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
-import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
-import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.test.TestUtils;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.core.task.Tasks;
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-public class EffectorBasicTest extends BrooklynAppUnitTestSupport {
-
- private static final Logger log = LoggerFactory.getLogger(EffectorBasicTest.class);
-
- // NB: more tests of effectors in EffectorSayHiTest and EffectorConcatenateTest
- // as well as EntityConfigMapUsageTest and others
-
- private List<SimulatedLocation> locs;
-
- @BeforeMethod(alwaysRun=true)
- @Override
- public void setUp() throws Exception {
- super.setUp();
- locs = ImmutableList.of(new SimulatedLocation());
- }
-
- @Test
- public void testInvokeEffectorStart() {
- app.start(locs);
- TestUtils.assertSetsEqual(locs, app.getLocations());
- // TODO above does not get registered as a task
- }
-
- @Test
- public void testInvokeEffectorStartWithMap() {
- app.invoke(Startable.START, MutableMap.of("locations", locs)).getUnchecked();
- TestUtils.assertSetsEqual(locs, app.getLocations());
- }
-
- @Test
- public void testInvokeEffectorStartWithArgs() {
- Entities.invokeEffectorWithArgs((EntityLocal)app, app, Startable.START, locs).getUnchecked();
- TestUtils.assertSetsEqual(locs, app.getLocations());
- }
-
- @Test
- public void testInvokeEffectorStartWithTwoEntities() {
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
- TestEntity entity2 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
- app.start(locs);
- TestUtils.assertSetsEqual(locs, app.getLocations());
- TestUtils.assertSetsEqual(locs, entity.getLocations());
- TestUtils.assertSetsEqual(locs, entity2.getLocations());
- }
-
- @Test
- public void testInvokeEffectorTaskHasTag() {
- Task<Void> starting = app.invoke(Startable.START, MutableMap.of("locations", locs));
-// log.info("TAGS: "+starting.getTags());
- Assert.assertTrue(starting.getTags().contains(ManagementContextInternal.EFFECTOR_TAG));
- }
-
- // check various failure situations
-
- private FailingEntity createFailingEntity() {
- FailingEntity entity = app.createAndManageChild(EntitySpec.create(FailingEntity.class)
- .configure(FailingEntity.FAIL_ON_START, true));
- return entity;
- }
-
- // uncaught failures are propagates
-
- @Test
- public void testInvokeEffectorStartFailing_Method() {
- FailingEntity entity = createFailingEntity();
- assertStartMethodFails(entity);
- }
-
- @Test
- public void testInvokeEffectorStartFailing_EntityInvoke() {
- FailingEntity entity = createFailingEntity();
- assertTaskFails( entity.invoke(Startable.START, MutableMap.of("locations", locs)) );
- }
-
- @Test
- public void testInvokeEffectorStartFailing_EntitiesInvoke() {
- FailingEntity entity = createFailingEntity();
-
- assertTaskFails( Entities.invokeEffectorWithArgs(entity, entity, Startable.START, locs) );
- }
-
- // caught failures are NOT propagated!
-
- @Test
- public void testInvokeEffectorStartFailing_MethodInDynamicTask() {
- Task<Void> task = app.getExecutionContext().submit(Tasks.<Void>builder().dynamic(true).body(new Callable<Void>() {
- @Override public Void call() throws Exception {
- testInvokeEffectorStartFailing_Method();
- return null;
- }
- }).build());
-
- assertTaskSucceeds(task);
- assertTaskHasFailedChild(task);
- }
-
- @Test
- public void testInvokeEffectorStartFailing_MethodInTask() {
- Task<Void> task = app.getExecutionContext().submit(Tasks.<Void>builder().dynamic(false).body(new Callable<Void>() {
- @Override public Void call() throws Exception {
- testInvokeEffectorStartFailing_Method();
- return null;
- }
- }).build());
-
- assertTaskSucceeds(task);
- }
-
- private void assertTaskSucceeds(Task<Void> task) {
- task.getUnchecked();
- Assert.assertFalse(task.isError());
- }
-
- private void assertTaskHasFailedChild(Task<Void> task) {
- Assert.assertTrue(Tasks.failed( ((HasTaskChildren)task).getChildren() ).iterator().hasNext());
- }
-
- private void assertStartMethodFails(FailingEntity entity) {
- try {
- entity.start(locs);
- Assert.fail("Should have failed");
- } catch (Exception e) {
- // expected
- }
- }
-
- protected void assertTaskFails(Task<?> t) {
- try {
- t.get();
- Assert.fail("Should have failed");
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- // expected
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/effector/core/EffectorConcatenateTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/effector/core/EffectorConcatenateTest.java b/core/src/test/java/org/apache/brooklyn/effector/core/EffectorConcatenateTest.java
deleted file mode 100644
index 9372e41..0000000
--- a/core/src/test/java/org/apache/brooklyn/effector/core/EffectorConcatenateTest.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * 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.effector.core;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.fail;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.mgmt.ExecutionManager;
-import org.apache.brooklyn.api.mgmt.Task;
-import org.apache.brooklyn.core.annotation.Effector;
-import org.apache.brooklyn.core.annotation.EffectorParam;
-import org.apache.brooklyn.core.entity.AbstractEntity;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.apache.brooklyn.core.test.entity.TestApplication;
-import org.apache.brooklyn.core.test.entity.TestApplicationImpl;
-import org.apache.brooklyn.effector.core.MethodEffector;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.core.task.BasicExecutionContext;
-import org.apache.brooklyn.util.core.task.Tasks;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-
-public class EffectorConcatenateTest {
-
-
- private static final Logger log = LoggerFactory.getLogger(EffectorConcatenateTest.class);
- private static final long TIMEOUT = 10*1000;
-
- public static class MyEntityImpl extends AbstractEntity {
-
- public static MethodEffector<String> CONCATENATE = new MethodEffector<String>(MyEntityImpl.class, "concatenate");
- public static MethodEffector<Void> WAIT_A_BIT = new MethodEffector<Void>(MyEntityImpl.class, "waitabit");
- public static MethodEffector<Void> SPAWN_CHILD = new MethodEffector<Void>(MyEntityImpl.class, "spawnchild");
-
- public MyEntityImpl() {
- super();
- }
- public MyEntityImpl(Entity parent) {
- super(parent);
- }
-
- /** The "current task" representing the effector currently executing */
- AtomicReference<Task<?>> waitingTask = new AtomicReference<Task<?>>();
-
- /** latch is .countDown'ed by the effector at the beginning of the "waiting" point */
- CountDownLatch nowWaitingLatch = new CountDownLatch(1);
-
- /** latch is await'ed on by the effector when it is in the "waiting" point */
- CountDownLatch continueFromWaitingLatch = new CountDownLatch(1);
-
- @Effector(description="sample effector concatenating strings")
- public String concatenate(@EffectorParam(name="first", description="first argument") String first,
- @EffectorParam(name="second", description="2nd arg") String second) throws Exception {
- return first+second;
- }
-
- @Effector(description="sample effector doing some waiting")
- public void waitabit() throws Exception {
- waitingTask.set(Tasks.current());
-
- Tasks.setExtraStatusDetails("waitabit extra status details");
-
- Tasks.withBlockingDetails("waitabit.blocking", new Callable<Void>() {
- public Void call() throws Exception {
- nowWaitingLatch.countDown();
- if (!continueFromWaitingLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
- fail("took too long to be told to continue");
- }
- return null;
- }});
- }
-
- @Effector(description="sample effector that spawns a child task that waits a bit")
- public void spawnchild() throws Exception {
- // spawn a child, then wait
- BasicExecutionContext.getCurrentExecutionContext().submit(
- MutableMap.of("displayName", "SpawnedChildName"),
- new Callable<Void>() {
- public Void call() throws Exception {
- log.info("beginning spawned child response "+Tasks.current()+", with tags "+Tasks.current().getTags());
- Tasks.setBlockingDetails("spawned child blocking details");
- nowWaitingLatch.countDown();
- if (!continueFromWaitingLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
- fail("took too long to be told to continue");
- }
- return null;
- }});
- }
- }
-
- private TestApplication app;
- private MyEntityImpl e;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() {
- app = new TestApplicationImpl();
- e = new MyEntityImpl(app);
- Entities.startManagement(app);
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() {
- if (app != null) Entities.destroyAll(app.getManagementContext());
- }
-
- @Test
- public void testCanInvokeEffector() throws Exception {
- // invocation map syntax
- Task<String> task = e.invoke(MyEntityImpl.CONCATENATE, ImmutableMap.of("first", "a", "second", "b"));
- assertEquals(task.get(TIMEOUT, TimeUnit.MILLISECONDS), "ab");
-
- // method syntax
- assertEquals("xy", e.concatenate("x", "y"));
- }
-
- @Test
- public void testReportsTaskDetails() throws Exception {
- final AtomicReference<String> result = new AtomicReference<String>();
-
- Thread bg = new Thread(new Runnable() {
- public void run() {
- try {
- // Expect "wait a bit" to tell us it's blocking
- if (!e.nowWaitingLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
- result.set("took too long for waitabit to be waiting");
- return;
- }
-
- // Expect "wait a bit" to have retrieved and set its task
- try {
- Task<?> t = e.waitingTask.get();
- String status = t.getStatusDetail(true);
- log.info("waitabit task says:\n"+status);
- if (!status.contains("waitabit extra status details")) {
- result.set("Status not in expected format: doesn't contain extra status details phrase 'My extra status details'\n"+status);
- return;
- }
- if (!status.startsWith("waitabit.blocking")) {
- result.set("Status not in expected format: doesn't start with blocking details 'waitabit.blocking'\n"+status);
- return;
- }
- } finally {
- e.continueFromWaitingLatch.countDown();
- }
- } catch (Throwable t) {
- log.warn("Failure: "+t, t);
- result.set("Failure: "+t);
- }
- }});
- bg.start();
-
- e.invoke(MyEntityImpl.WAIT_A_BIT, ImmutableMap.<String,Object>of())
- .get(TIMEOUT, TimeUnit.MILLISECONDS);
-
- bg.join(TIMEOUT*2);
- assertFalse(bg.isAlive());
-
- String problem = result.get();
- if (problem!=null) fail(problem);
- }
-
- @Test
- public void testReportsSpawnedTaskDetails() throws Exception {
- final AtomicReference<String> result = new AtomicReference<String>();
-
- Thread bg = new Thread(new Runnable() {
- public void run() {
- try {
- // Expect "spawned child" to tell us it's blocking
- if (!e.nowWaitingLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
- result.set("took too long for spawnchild's sub-task to be waiting");
- return;
- }
-
- // Expect spawned task to be have been tagged with entity
- ExecutionManager em = e.getManagementContext().getExecutionManager();
- Task<?> subtask = Iterables.find(BrooklynTaskTags.getTasksInEntityContext(em, e), new Predicate<Task<?>>() {
- public boolean apply(Task<?> input) {
- return "SpawnedChildName".equals(input.getDisplayName());
- }
- });
-
- // Expect spawned task to haev correct "blocking details"
- try {
- String status = subtask.getStatusDetail(true);
- log.info("subtask task says:\n"+status);
- if (!status.contains("spawned child blocking details")) {
- result.set("Status not in expected format: doesn't contain blocking details phrase 'spawned child blocking details'\n"+status);
- return;
- }
- } finally {
- e.continueFromWaitingLatch.countDown();
- }
- } catch (Throwable t) {
- log.warn("Failure: "+t, t);
- result.set("Failure: "+t);
- }
- }});
- bg.start();
-
- e.invoke(MyEntityImpl.SPAWN_CHILD, ImmutableMap.<String,Object>of())
- .get(TIMEOUT, TimeUnit.MILLISECONDS);
-
- bg.join(TIMEOUT*2);
- assertFalse(bg.isAlive());
-
- String problem = result.get();
- if (problem!=null) fail(problem);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/effector/core/EffectorMetadataTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/effector/core/EffectorMetadataTest.java b/core/src/test/java/org/apache/brooklyn/effector/core/EffectorMetadataTest.java
deleted file mode 100644
index b8b6bf4..0000000
--- a/core/src/test/java/org/apache/brooklyn/effector/core/EffectorMetadataTest.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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.effector.core;
-
-import static org.testng.Assert.assertEquals;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.brooklyn.api.effector.Effector;
-import org.apache.brooklyn.api.effector.ParameterType;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.entity.ImplementedBy;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.core.annotation.EffectorParam;
-import org.apache.brooklyn.core.entity.AbstractEntity;
-import org.apache.brooklyn.core.entity.trait.Startable;
-import org.apache.brooklyn.core.mgmt.internal.EffectorUtils;
-import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
-import org.apache.brooklyn.effector.core.BasicParameterType;
-import org.apache.brooklyn.effector.core.Effectors;
-import org.apache.brooklyn.effector.core.MethodEffector;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * Test the operation of the {@link Effector} implementations.
- *
- * TODO clarify test purpose
- */
-public class EffectorMetadataTest extends BrooklynAppUnitTestSupport {
-
- private MyAnnotatedEntity e1;
- private MyOverridingEntity e2;
-
- @BeforeMethod(alwaysRun=true)
- @Override
- public void setUp() throws Exception {
- super.setUp();
- e1 = app.createAndManageChild(EntitySpec.create(MyAnnotatedEntity.class));
- e2 = app.createAndManageChild(EntitySpec.create(MyOverridingEntity.class));
- }
-
- @Test
- public void testEffectorMetaDataFromAnnotationsWithConstant() {
- Effector<?> effector = EffectorUtils.findEffectorDeclared(e1, "effWithNewAnnotation").get();
- Assert.assertTrue(Effectors.sameSignature(effector, MyAnnotatedEntity.EFF_WITH_NEW_ANNOTATION));
- assertEquals(effector.getName(), "effWithNewAnnotation");
- assertEquals(effector.getDescription(), "my effector description");
- assertEquals(effector.getReturnType(), String.class);
- assertParametersEqual(
- effector.getParameters(),
- ImmutableList.<ParameterType<?>>of(
- new BasicParameterType<String>("param1", String.class, "my param description", "my default val")));
- }
-
- @Test
- public void testEffectorMetaDataFromAnnotationsWithoutConstant() {
- Effector<?> effector = EffectorUtils.findEffectorDeclared(e1, "effWithAnnotationButNoConstant").get();
- assertEquals(effector.getName(), "effWithAnnotationButNoConstant");
- assertEquals(effector.getDescription(), "my effector description");
- assertEquals(effector.getReturnType(), String.class);
- assertParametersEqual(
- effector.getParameters(),
- ImmutableList.<ParameterType<?>>of(
- new BasicParameterType<String>("param1", String.class, "my param description", "my default val")));
- }
-
- @SuppressWarnings("rawtypes")
- @Test
- public void testEffectorMetaDataFromOverriddenMethod() {
- // Overridden with new annotations
- Effector<?> startEffector = EffectorUtils.findEffectorDeclared(e2, "start").get();
- assertEquals(startEffector.getName(), "start");
- assertEquals(startEffector.getDescription(), "My overridden start description");
- assertEquals(startEffector.getReturnType(), void.class);
- assertParametersEqual(
- startEffector.getParameters(),
- ImmutableList.<ParameterType<?>>of(
- new BasicParameterType<Collection>("locations", Collection.class, "my overridden param description", null)));
- }
-
- private void assertParametersEqual(List<ParameterType<?>> actuals, List<ParameterType<?>> expecteds) {
- assertEquals(actuals.size(), expecteds.size(), "actual="+actuals);
- for (int i = 0; i < actuals.size(); i++) {
- ParameterType<?> actual = actuals.get(i);
- ParameterType<?> expected = expecteds.get(i);
- assertParameterEqual(actual, expected);
- }
- }
-
- private void assertParameterEqual(ParameterType<?> actual, ParameterType<?> expected) {
- assertEquals(actual.getName(), expected.getName(), "actual="+actual);
- assertEquals(actual.getDescription(), expected.getDescription(), "actual="+actual);
- assertEquals(actual.getParameterClass(), expected.getParameterClass(), "actual="+actual);
- assertEquals(actual.getParameterClassName(), expected.getParameterClassName(), "actual="+actual);
- }
-
- @ImplementedBy(MyAnnotatedEntityImpl.class)
- public interface MyAnnotatedEntity extends Entity {
- static MethodEffector<String> EFF_WITH_NEW_ANNOTATION = new MethodEffector<String>(MyAnnotatedEntity.class, "effWithNewAnnotation");
-
- @org.apache.brooklyn.core.annotation.Effector(description="my effector description")
- public String effWithNewAnnotation(
- @EffectorParam(name="param1", defaultValue="my default val", description="my param description") String param1);
-
- @org.apache.brooklyn.core.annotation.Effector(description="my effector description")
- public String effWithAnnotationButNoConstant(
- @EffectorParam(name="param1", defaultValue="my default val", description="my param description") String param1);
- }
-
- public static class MyAnnotatedEntityImpl extends AbstractEntity implements MyAnnotatedEntity {
- @Override
- public String effWithNewAnnotation(String param1) {
- return param1;
- }
-
- @Override
- public String effWithAnnotationButNoConstant(String param1) {
- return param1;
- }
- }
-
- @ImplementedBy(MyOverridingEntityImpl.class)
- public interface MyOverridingEntity extends Entity, Startable {
- org.apache.brooklyn.api.effector.Effector<Void> START = Effectors.effector(Startable.START)
- .description("My overridden start description")
- .parameter(Collection.class, "locations", "my overridden param description")
- .build();
- }
-
- public static class MyOverridingEntityImpl extends AbstractEntity implements MyOverridingEntity {
-
- @Override
- public void restart() {
- }
-
- @Override
- public void start(Collection<? extends Location> locations2) {
- }
-
- @Override
- public void stop() {
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/test/java/org/apache/brooklyn/effector/core/EffectorSayHiGroovyTest.groovy
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/effector/core/EffectorSayHiGroovyTest.groovy b/core/src/test/java/org/apache/brooklyn/effector/core/EffectorSayHiGroovyTest.groovy
deleted file mode 100644
index ec5c442..0000000
--- a/core/src/test/java/org/apache/brooklyn/effector/core/EffectorSayHiGroovyTest.groovy
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.effector.core
-
-import static org.testng.Assert.*
-
-import org.apache.brooklyn.api.effector.Effector
-import org.apache.brooklyn.api.entity.Entity
-import org.apache.brooklyn.api.entity.EntitySpec
-import org.apache.brooklyn.api.entity.ImplementedBy
-import org.apache.brooklyn.api.mgmt.ManagementContext
-import org.apache.brooklyn.api.mgmt.Task
-import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.apache.brooklyn.core.mgmt.internal.EffectorUtils
-import org.apache.brooklyn.core.test.entity.TestApplication
-import org.apache.brooklyn.core.annotation.EffectorParam
-import org.apache.brooklyn.core.entity.AbstractEntity
-import org.apache.brooklyn.core.entity.Entities
-import org.apache.brooklyn.core.entity.trait.Startable
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-import org.testng.annotations.AfterMethod
-import org.testng.annotations.BeforeMethod
-import org.testng.annotations.Test
-
-/**
- * Test the operation of the {@link Effector} implementations.
- *
- * TODO clarify test purpose
- */
-public class EffectorSayHiGroovyTest {
- private static final Logger log = LoggerFactory.getLogger(EffectorSayHiTest.class);
-
- private TestApplication app;
- private MyEntity e;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() {
- app = TestApplication.Factory.newManagedInstanceForTests();
- e = app.createAndManageChild(EntitySpec.create(MyEntity.class));
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() {
- if (app != null) Entities.destroyAll(app.getManagementContext());
- }
-
- @Test
- public void testFindEffectors() {
- assertEquals("sayHi1", e.SAY_HI_1.getName());
- assertEquals(["name", "greeting"], e.SAY_HI_1.getParameters()[0..1]*.getName());
- assertEquals("says hello", e.SAY_HI_1.getDescription());
-
- assertEquals("sayHi1", e.SAY_HI_1_ALT.getName());
- assertEquals(["name", "greeting"], e.SAY_HI_1_ALT.getParameters()[0..1]*.getName());
- assertEquals("says hello", e.SAY_HI_1_ALT.getDescription());
-
- assertEquals("sayHi2", e.SAY_HI_2.getName());
- assertEquals(["name", "greeting"], e.SAY_HI_2.getParameters()[0..1]*.getName());
- assertEquals("says hello", e.SAY_HI_2.getDescription());
- }
-
- @Test
- public void testFindTraitEffectors() {
- assertEquals("locations", Startable.START.getParameters()[0].getName());
- }
-
- @Test
- public void testInvokeEffectorMethod1BypassInterception() {
- String name = "sayHi1"
- def args = ["Bob", "hello"] as Object[]
-
- //try the alt syntax recommended from web
- def metaMethod = e.metaClass.getMetaMethod(name, args)
- if (metaMethod==null)
- throw new IllegalArgumentException("Invalid arguments (no method found) for method $name: "+args);
- assertEquals("hello Bob", metaMethod.invoke(e, args))
- }
-
- @Test
- public void testInvokeEffectorMethod2BypassInterception() {
- String name = "sayHi2"
- def args = ["Bob", "hello"] as Object[]
- assertEquals("hello Bob", e.metaClass.invokeMethod(e, name, args))
- }
-
- @Test
- public void testInvokeEffectors1() {
- assertEquals("hi Bob", e.sayHi1("Bob", "hi"))
-
- assertEquals("hello Bob", e.SAY_HI_1.call(e, [name:"Bob"]) )
- assertEquals("hello Bob", e.invoke(e.SAY_HI_1, [name:"Bob"]).get() );
-
- assertEquals("hello Bob", e.SAY_HI_1_ALT.call(e, [name:"Bob"]) )
- }
-
- @Test
- public void testInvokeEffectors2() {
- assertEquals("hi Bob", e.sayHi2("Bob", "hi"))
-
- assertEquals("hello Bob", e.SAY_HI_2.call(e, [name:"Bob"]) )
- assertEquals("hello Bob", e.invoke(e.SAY_HI_2, [name:"Bob"]).get() );
-
- }
-
- @Test
- public void testCanRetrieveTaskForEffector() {
- e.sayHi2("Bob", "hi")
-
- ManagementContext managementContext = e.getManagementContext()
-
- Set<Task> tasks = managementContext.getExecutionManager().getTasksWithAllTags([
- BrooklynTaskTags.tagForContextEntity(e),"EFFECTOR"])
- assertEquals(tasks.size(), 1)
- assertTrue(tasks.iterator().next().getDescription().contains("sayHi2"))
- }
-}
-public interface CanSayHi {
- //prefer following simple groovy syntax
- static Effector<String> SAY_HI_1 = new MethodEffector<String>(CanSayHi.&sayHi1);
- //slightly longer-winded pojo also supported
- static Effector<String> SAY_HI_1_ALT = new MethodEffector<String>(CanSayHi.class, "sayHi1");
-
- @org.apache.brooklyn.core.annotation.Effector(description="says hello")
- public String sayHi1(
- @EffectorParam(name="name") String name,
- @EffectorParam(name="greeting", defaultValue="hello", description="what to say") String greeting);
-
- //finally there is a way to provide a class/closure if needed or preferred for some odd reason
- static Effector<String> SAY_HI_2 =
-
- //groovy 1.8.2 balks at runtime during getCallSiteArray (bug 5122) if we use anonymous inner class
-// new ExplicitEffector<CanSayHi,String>(
-// "sayHi2", String.class, [
-// [ "name", String.class, "person to say hi to" ] as BasicParameterType<String>,
-// [ "greeting", String.class, "what to say as greeting", "hello" ] as BasicParameterType<String>
-// ],
-// "says hello to a person") {
-// public String invokeEffector(CanSayHi e, Map m) {
-// e.sayHi2(m)
-// }
-// };
- //following is a workaround, not greatly enamoured of it... but MethodEffector is generally preferred anyway
- ExplicitEffector.create("sayHi2", String.class, [
- new BasicParameterType<String>("name", String.class, "person to say hi to"),
- new BasicParameterType<String>("greeting", String.class, "what to say as greeting", "hello")
- ],
- "says hello", { e, m ->
- def args = EffectorUtils.prepareArgsForEffector(SAY_HI_2, m);
- e.sayHi2(args[0], args[1]) })
-
- public String sayHi2(String name, String greeting);
-
-}
-
-@ImplementedBy(MyEntityImpl.class)
-public interface MyEntity extends Entity, CanSayHi {
-}
-
-public class MyEntityImpl extends AbstractEntity implements MyEntity {
- public String sayHi1(String name, String greeting) { "$greeting $name" }
- public String sayHi2(String name, String greeting) { "$greeting $name" }
-}