From e5aa681fbd2db0faf2edd4c8479505392255a0e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Galland?= Date: Sun, 30 Jul 2017 11:08:16 +0200 Subject: [PATCH] [lang][core] Event source should be specified when firing in EventSpace. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit see #78 Signed-off-by: Stéphane Galland --- .../io.sarl.core/src/io/sarl/core/bic.sarl | 12 ++ .../src/io/sarl/lang/core/EventSpace.java | 63 ++++++++- .../kernel/bic/BehaviorsSkill.java | 3 +- .../bic/DefaultContextInteractionsSkill.java | 6 +- .../bic/ExternalContextAccessSkill.java | 14 +- .../kernel/bic/InternalEventBusSkill.java | 8 +- .../services/jdk/contextspace/Context.java | 10 +- .../jdk/spawn/StandardSpawnService.java | 10 +- .../kernel/space/AbstractEventSpace.java | 24 +++- .../io/janusproject/tests/bugs/Issue224.java | 3 +- .../tests/kernel/bic/BehaviorsSkillTest.java | 49 ++++--- .../DefaultContextInteractionsSkillTest.java | 33 +++-- .../bic/ExternalContextAccessSkillTest.java | 28 ++-- .../jdk/contextspace/ContextTest.java | 30 ++-- .../jdk/spawn/StandardSpawnServiceTest.java | 21 +-- .../kernel/space/AbstractEventSpaceTest.java | 130 ++++++++++++++++-- .../core/tests/ExternalContextAccessTest.java | 2 +- 17 files changed, 343 insertions(+), 103 deletions(-) diff --git a/main/apiplugins/io.sarl.core/src/io/sarl/core/bic.sarl b/main/apiplugins/io.sarl.core/src/io/sarl/core/bic.sarl index fc0580d59a..ed4bff44fa 100644 --- a/main/apiplugins/io.sarl.core/src/io/sarl/core/bic.sarl +++ b/main/apiplugins/io.sarl.core/src/io/sarl/core/bic.sarl @@ -34,6 +34,7 @@ import io.sarl.lang.core.AgentContext import io.sarl.lang.core.Behavior import io.sarl.lang.core.Event import io.sarl.lang.core.EventListener +import io.sarl.lang.core.EventSpace import io.sarl.lang.core.Scope import io.sarl.lang.core.Space import io.sarl.lang.core.SpaceID @@ -133,6 +134,17 @@ capacity ExternalContextAccess { @Pure def isInSpace(^event : Event, spaceID : UUID) : boolean + /** + * Emits a given event with the provided scope in the given space. + * Equivalent to space.emit(getID,event,scope) + * + * @param space the space in which the event should be fired. + * @param event the event to emit. + * @param scope the definition of the scope that will be used for selected the receivers of the events. If null, all the agents in the space will receive the event. + * @since 0.6 + */ + def emit(^space : EventSpace, ^event : Event, scope : Scope
= null) + } /** diff --git a/main/coreplugins/io.sarl.lang.core/src/io/sarl/lang/core/EventSpace.java b/main/coreplugins/io.sarl.lang.core/src/io/sarl/lang/core/EventSpace.java index c7160af59d..eba5d3b11b 100644 --- a/main/coreplugins/io.sarl.lang.core/src/io/sarl/lang/core/EventSpace.java +++ b/main/coreplugins/io.sarl.lang.core/src/io/sarl/lang/core/EventSpace.java @@ -30,6 +30,7 @@ * Event driven Interaction {@link Space} for agents. * * @author $Author: srodriguez$ + * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ @@ -49,19 +50,73 @@ public interface EventSpace extends Space { * Emits the event inside this space with the given scope. Only agents * matching the scope will receive the event. * + *

This function does not change the source of the event if it was set. + * + *

If the given event has no specified source, the caller of the emit function is assumed + * to set the source's address to the address of the "current" agent. The concept of "current" + * agent depends on the capabilities of the run-time platform. Usually, it is the + * agent that is the cause of the emit. + * * @param event - the event to emit in the space. - * @param scope - the definition of the list of receiviers of the event. + * @param scope - the definition of the list of receivers of the event. + * @deprecated see {@link #emit(UUID, Event, Scope)}, since 0.6 */ - void emit(Event event, Scope

scope); + @Deprecated + @Inline(value = "emit(null, $1, $2)") + default void emit(Event event, Scope
scope) { + emit(null, event, scope); + } /** * Emits the event inside this space. All registered agents will receive the event. * + *

This function does not change the source of the event if it was set. + * + *

If the given event has no specified source, the caller of the emit function is assumed + * to set the source's address to the address of the "current" agent. The concept of "current" + * agent depends on the capabilities of the run-time platform. Usually, it is the + * agent that is the cause of the emit. + * * @param event - the event to emit in the space. + * @deprecated see {@link #emit(UUID, Event)}, since 0.6 */ - @Inline(value = "emit($1, null)") + @Inline(value = "emit(null, $1, null)") + @Deprecated default void emit(Event event) { - emit(event, null); + emit(null, event, null); + } + + /** + * Emits the event inside this space with the given scope. Only agents + * matching the scope will receive the event. + * + *

This function does not change the source of the event if it was set. + * + *

If the given event has no specified source, the emit function uses the + * {@code eventSource} parameter to set the source's address. + * + * @param eventSource - the sender of the event. + * @param event - the event to emit in the space. + * @param scope - the definition of the list of receivers of the event. + * @since 0.6 + */ + void emit(UUID eventSource, Event event, Scope

scope); + + /** + * Emits the event inside this space. All registered agents will receive the event. + * + *

This function does not change the source of the event if it was set. + * + *

If the given event has no specified source, the emit function uses the + * {@code eventSource} parameter to set the source's address. + * + * @param eventSource - the sender of the event. + * @param event - the event to emit in the space. + * @since 0.6 + */ + @Inline(value = "emit($1, $2, null)") + default void emit(UUID eventSource, Event event) { + emit(eventSource, event, null); } } diff --git a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/BehaviorsSkill.java b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/BehaviorsSkill.java index 805a5b5b24..357ac92987 100644 --- a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/BehaviorsSkill.java +++ b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/BehaviorsSkill.java @@ -160,8 +160,7 @@ public synchronized void wake(Event evt, Scope

scope) { if ((!(context instanceof InnerContextSkill)) || ((InnerContextSkill) context).hasInnerContext()) { final EventSpace defSpace = context.getInnerContext().getDefaultSpace(); - evt.setSource(defSpace.getAddress(getOwner().getID())); - defSpace.emit(evt, scope); + defSpace.emit(getID(), evt, scope); } else { // Do not call getInnerContext(), which is creating the inner context automatically. // In place, try to send the event inside the agent only (and its behaviors). diff --git a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/DefaultContextInteractionsSkill.java b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/DefaultContextInteractionsSkill.java index 139cba41f3..e116c7ddd9 100644 --- a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/DefaultContextInteractionsSkill.java +++ b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/DefaultContextInteractionsSkill.java @@ -101,14 +101,12 @@ protected void install() { @Override public void emit(Event event) { - event.setSource(getDefaultAddress()); - this.defaultSpace.emit(event); + this.defaultSpace.emit(getOwner().getID(), event, null); } @Override public void emit(Event event, Scope
scope) { - event.setSource(getDefaultAddress()); - this.defaultSpace.emit(event, scope); + this.defaultSpace.emit(getOwner().getID(), event, scope); } @Override diff --git a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/ExternalContextAccessSkill.java b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/ExternalContextAccessSkill.java index 67d70ffc30..2a0eba6d73 100644 --- a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/ExternalContextAccessSkill.java +++ b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/ExternalContextAccessSkill.java @@ -37,10 +37,12 @@ import io.sarl.core.ExternalContextAccess; import io.sarl.core.MemberJoined; import io.sarl.core.MemberLeft; +import io.sarl.lang.core.Address; import io.sarl.lang.core.Agent; import io.sarl.lang.core.AgentContext; import io.sarl.lang.core.Event; import io.sarl.lang.core.EventSpace; +import io.sarl.lang.core.Scope; import io.sarl.lang.core.Skill; import io.sarl.lang.core.Space; import io.sarl.lang.core.SpaceID; @@ -189,7 +191,10 @@ protected final void fireContextJoined(UUID futureContext, UUID futureContextDef */ protected final void fireMemberJoined(AgentContext newJoinedContext) { final EventSpace defSpace = newJoinedContext.getDefaultSpace(); - defSpace.emit(new MemberJoined(defSpace.getAddress(getOwner().getID()), newJoinedContext.getID(), getOwner().getID(), + defSpace.emit( + // No need to give an event source because the event's source is explicitly set below. + null, + new MemberJoined(defSpace.getAddress(getOwner().getID()), newJoinedContext.getID(), getOwner().getID(), getOwner().getClass().getName())); } @@ -233,6 +238,8 @@ protected final void fireContextLeft(UUID contextID) { protected final void fireMemberLeft(AgentContext leftContext) { final EventSpace defSpace = leftContext.getDefaultSpace(); defSpace.emit( + // No need to give an event source because the event's source is explicitly set below. + null, new MemberLeft(defSpace.getAddress(getOwner().getID()), getOwner().getID(), getOwner().getClass().getName())); } @@ -251,4 +258,9 @@ public boolean isInSpace(Event event, UUID spaceID) { return spaceID.equals(event.getSource().getSpaceId().getID()); } + @Override + public void emit(EventSpace space, Event event, Scope
scope) { + space.emit(getID(), event, scope); + } + } diff --git a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/InternalEventBusSkill.java b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/InternalEventBusSkill.java index d92667f2d3..8960a32e1f 100644 --- a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/InternalEventBusSkill.java +++ b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/bic/InternalEventBusSkill.java @@ -291,21 +291,25 @@ public int getRegisteredEventListeners(Class type, Collection @Override public void selfEvent(Event event) { - // Ensure that the event source is the agent itself! - event.setSource(getInnerDefaultSpaceAddress()); // If the event must be fired only by the // agent itself, it is treated in this function. // Otherwise, it is given to the asynchronous // listener. final Class eventType = event.getClass(); if (Initialize.class.equals(eventType)) { + // Ensure that the event source is the agent itself! + event.setSource(getInnerDefaultSpaceAddress()); runInitializationStage(event); } else if (Destroy.class.equals(eventType)) { + // Ensure that the event source is the agent itself! + event.setSource(getInnerDefaultSpaceAddress()); runDestructionStage(event); } else if (AsynchronousAgentKillingEvent.class.equals(eventType)) { // Asynchronous kill of the event. this.agentAsEventListener.killOrMarkAsKilled(); } else if (getOwnerState().isEventHandling()) { + // Ensure that the event source is the agent itself! + event.setSource(getInnerDefaultSpaceAddress()); // Asynchronous parallel dispatching of this event this.agentAsEventListener.receiveEvent(event); } diff --git a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/services/jdk/contextspace/Context.java b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/services/jdk/contextspace/Context.java index 45dd0abf18..5df945699d 100644 --- a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/services/jdk/contextspace/Context.java +++ b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/services/jdk/contextspace/Context.java @@ -218,7 +218,10 @@ public void spaceCreated(Space space, boolean isLocalCreation) { final EventSpace defSpace = this.context.getDefaultSpace(); // defSpace may be null if the created space is the default space. if (defSpace != null) { - defSpace.emit(new SpaceCreated(new Address(defSpace.getSpaceID(), this.context.getID()), space.getSpaceID())); + defSpace.emit( + // No need to give an event source because it is explicitly set below. + null, + new SpaceCreated(new Address(defSpace.getSpaceID(), this.context.getID()), space.getSpaceID())); } } } @@ -231,7 +234,10 @@ public void spaceDestroyed(Space space, boolean isLocalDestruction) { final EventSpace defSpace = this.context.getDefaultSpace(); // defSpace may be null if the created space is the default space. if (defSpace != null) { - defSpace.emit(new SpaceDestroyed(new Address(defSpace.getSpaceID(), this.context.getID()), space.getSpaceID())); + defSpace.emit( + // No need to give an event source because it is explicitly set below. + null, + new SpaceDestroyed(new Address(defSpace.getSpaceID(), this.context.getID()), space.getSpaceID())); } } // Notify the relays (other services) diff --git a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/services/jdk/spawn/StandardSpawnService.java b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/services/jdk/spawn/StandardSpawnService.java index f82e7f396d..e03eae984f 100644 --- a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/services/jdk/spawn/StandardSpawnService.java +++ b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/services/jdk/spawn/StandardSpawnService.java @@ -248,7 +248,10 @@ protected void fireAgentSpawnedOutsideAgent(UUID spawningAgent, AgentContext con assert source != null; final AgentSpawned event = new AgentSpawned(source, agentClazz.getName(), Collections2.transform(agents, (it) -> it.getID())); - defSpace.emit(event); + defSpace.emit( + // No need to give an event source because it is explicitly set above. + null, + event); } /** Notify the agent's listeners about its spawning. @@ -471,7 +474,10 @@ protected void fireAgentDestroyed(Agent agent) { synchronized (sc.mutex()) { for (final AgentContext context : sc) { final EventSpace defSpace = context.getDefaultSpace(); - defSpace.emit(new AgentKilled(defSpace.getAddress(agent.getID()), agent.getID(), agent.getClass().getName())); + defSpace.emit( + // No need to give an event source because it is explicitly set below. + null, + new AgentKilled(defSpace.getAddress(agent.getID()), agent.getID(), agent.getClass().getName())); } } } catch (RuntimeException e) { diff --git a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/space/AbstractEventSpace.java b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/space/AbstractEventSpace.java index f2adb80392..03eb47278d 100644 --- a/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/space/AbstractEventSpace.java +++ b/sre/io.janusproject/io.janusproject.plugin/src/io/janusproject/kernel/space/AbstractEventSpace.java @@ -121,13 +121,15 @@ public Address getAddress(UUID id) { * *

This function emits on the internal event bus of the agent (call to {@link #doEmit(Event, Scope)}), and on the network. * + * @param eventSource - the source of the event. * @param event - the event to emit. * @param scope - description of the scope of the event, i.e. the receivers of the event. + * @since 2.0.6.0 */ - public final void emit(Event event, Scope

scope) { + public final void emit(UUID eventSource, Event event, Scope
scope) { assert event != null; - assert event.getSource() != null : "Every event must have a source"; //$NON-NLS-1$ - assert this.getSpaceID().equals(event.getSource().getSpaceId()) : "The source address must belong to this space"; //$NON-NLS-1$ + ensureEventSource(eventSource, event); + assert getSpaceID().equals(event.getSource().getSpaceId()) : "The source address must belong to this space"; //$NON-NLS-1$ try { final Scope
scopeInstance = (scope == null) ? Scopes.
allParticipants() : scope; this.network.publish(scopeInstance, event); @@ -138,6 +140,22 @@ public final void emit(Event event, Scope
scope) { } + /** Ensure that the given event has a source. + * + * @param eventSource - the source of the event. + * @param event - the event to emit. + * @since 2.0.6.0 + */ + protected void ensureEventSource(UUID eventSource, Event event) { + if (event.getSource() == null) { + if (eventSource != null) { + event.setSource(new Address(getSpaceID(), eventSource)); + } else { + throw new AssertionError("Every event must have a source"); //$NON-NLS-1$ + } + } + } + /** * Do the emission of the event. * diff --git a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/bugs/Issue224.java b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/bugs/Issue224.java index 4b6e6e6615..9a1d7a3afd 100644 --- a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/bugs/Issue224.java +++ b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/bugs/Issue224.java @@ -154,7 +154,8 @@ public RegisteredInInitializeAgent(BuiltinCapacitiesProvider provider, UUID pare protected boolean runAgentTest() { addResult(this); getSkill(Behaviors.class).registerBehavior(this.behavior); - getSkill(Schedules.class).in(TIMEOUT, (agent) -> getSkill(Lifecycle.class).killMe()); + getSkill(Schedules.class).in(TIMEOUT, (agent) -> + getSkill(Lifecycle.class).killMe()); return false; } diff --git a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/BehaviorsSkillTest.java b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/BehaviorsSkillTest.java index 7ff1ab18b5..d221926f04 100644 --- a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/BehaviorsSkillTest.java +++ b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/BehaviorsSkillTest.java @@ -221,29 +221,27 @@ public void getRegisteredBehaviors() { public void wake_noScope() { Event event = mock(Event.class); this.skill.wake(event); - ArgumentCaptor argument1 = ArgumentCaptor.forClass(Event.class); - ArgumentCaptor> argument2 = ArgumentCaptor.forClass(Scope.class); - Mockito.verify(this.innerSpace).emit(argument1.capture(), argument2.capture()); - assertSame(event, argument1.getValue()); - assertNull(argument2.getValue()); - ArgumentCaptor
argument3 = ArgumentCaptor.forClass(Address.class); - Mockito.verify(event).setSource(argument3.capture()); - assertEquals(this.address, argument3.getValue()); + ArgumentCaptor argument1 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument2 = ArgumentCaptor.forClass(Event.class); + ArgumentCaptor> argument3 = ArgumentCaptor.forClass(Scope.class); + Mockito.verify(this.innerSpace).emit(argument1.capture(), argument2.capture(), argument3.capture()); + assertEquals(this.agent.getID(), argument1.getValue()); + assertSame(event, argument2.getValue()); + assertNull(argument3.getValue()); } @Test public void wake_scope_all() { Event event = mock(Event.class); this.skill.wake(event, Scopes.allParticipants()); - ArgumentCaptor argument1 = ArgumentCaptor.forClass(Event.class); - ArgumentCaptor> argument2 = ArgumentCaptor.forClass(Scope.class); - Mockito.verify(this.innerSpace).emit(argument1.capture(), argument2.capture()); - assertSame(event, argument1.getValue()); - assertNotNull(argument2.getValue()); - assertSame(Scopes.allParticipants(), argument2.getValue()); - ArgumentCaptor
argument3 = ArgumentCaptor.forClass(Address.class); - Mockito.verify(event).setSource(argument3.capture()); - assertEquals(this.address, argument3.getValue()); + ArgumentCaptor argument1 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument2 = ArgumentCaptor.forClass(Event.class); + ArgumentCaptor> argument3 = ArgumentCaptor.forClass(Scope.class); + Mockito.verify(this.innerSpace).emit(argument1.capture(), argument2.capture(), argument3.capture()); + assertEquals(this.agent.getID(), argument1.getValue()); + assertSame(event, argument2.getValue()); + assertNotNull(argument3.getValue()); + assertSame(Scopes.allParticipants(), argument3.getValue()); } @Test @@ -252,15 +250,14 @@ public void wake_scope_any() { SpaceID spaceID = new SpaceID(UUID.randomUUID(), UUID.randomUUID(), null); Scope
scope = Scopes.addresses(new Address(spaceID, UUID.randomUUID())); this.skill.wake(event, scope); - ArgumentCaptor argument1 = ArgumentCaptor.forClass(Event.class); - ArgumentCaptor> argument2 = ArgumentCaptor.forClass(Scope.class); - Mockito.verify(this.innerSpace).emit(argument1.capture(), argument2.capture()); - assertSame(event, argument1.getValue()); - assertNotNull(argument2.getValue()); - assertSame(scope, argument2.getValue()); - ArgumentCaptor
argument3 = ArgumentCaptor.forClass(Address.class); - Mockito.verify(event).setSource(argument3.capture()); - assertEquals(this.address, argument3.getValue()); + ArgumentCaptor argument1 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument2 = ArgumentCaptor.forClass(Event.class); + ArgumentCaptor> argument3 = ArgumentCaptor.forClass(Scope.class); + Mockito.verify(this.innerSpace).emit(argument1.capture(), argument2.capture(), argument3.capture()); + assertEquals(this.agent.getID(), argument1.getValue()); + assertSame(event, argument2.getValue()); + assertNotNull(argument3.getValue()); + assertSame(scope, argument3.getValue()); } @Test diff --git a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/DefaultContextInteractionsSkillTest.java b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/DefaultContextInteractionsSkillTest.java index e3d391fb0d..195a0a077f 100644 --- a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/DefaultContextInteractionsSkillTest.java +++ b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/DefaultContextInteractionsSkillTest.java @@ -66,6 +66,9 @@ @SuppressWarnings("all") public class DefaultContextInteractionsSkillTest extends AbstractJanusTest { + @Nullable + private Agent agent; + @Nullable private EventSpace defaultSpace; @@ -109,7 +112,7 @@ public void setUp() throws Exception { this.lifeCapacity = mock(Lifecycle.class); - Agent agent = new Agent(Mockito.mock(BuiltinCapacitiesProvider.class), UUID.randomUUID(), null) { + this.agent = new Agent(Mockito.mock(BuiltinCapacitiesProvider.class), UUID.randomUUID(), null) { @Override protected ClearableReference $getSkill(Class capacity) { return new ClearableReference(DefaultContextInteractionsSkillTest.this.lifeCapacity); @@ -149,14 +152,13 @@ public void emitEventScope() throws Exception { Event event = mock(Event.class); Scope
scope = Scopes.allParticipants(); this.skill.emit(event, scope); - ArgumentCaptor argument1 = ArgumentCaptor.forClass(Event.class); - ArgumentCaptor argument2 = ArgumentCaptor.forClass(Scope.class); - verify(this.defaultSpace, new Times(1)).emit(argument1.capture(), argument2.capture()); - assertSame(event, argument1.getValue()); - assertSame(scope, argument2.getValue()); - ArgumentCaptor
argument3 = ArgumentCaptor.forClass(Address.class); - verify(event).setSource(argument3.capture()); - assertEquals(this.address, argument3.getValue()); + ArgumentCaptor argument1 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument2 = ArgumentCaptor.forClass(Event.class); + ArgumentCaptor argument3 = ArgumentCaptor.forClass(Scope.class); + verify(this.defaultSpace, new Times(1)).emit(argument1.capture(), argument2.capture(), argument3.capture()); + assertEquals(this.agent.getID(), argument1.getValue()); + assertSame(event, argument2.getValue()); + assertSame(scope, argument3.getValue()); } @Test @@ -164,12 +166,13 @@ public void emitEvent() throws Exception { this.reflect.invoke(this.skill, "install"); Event event = mock(Event.class); this.skill.emit(event); - ArgumentCaptor argument1 = ArgumentCaptor.forClass(Event.class); - verify(this.defaultSpace, new Times(1)).emit(argument1.capture()); - assertSame(event, argument1.getValue()); - ArgumentCaptor
argument2 = ArgumentCaptor.forClass(Address.class); - verify(event).setSource(argument2.capture()); - assertEquals(this.address, argument2.getValue()); + ArgumentCaptor argument1 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument2 = ArgumentCaptor.forClass(Event.class); + ArgumentCaptor argument3 = ArgumentCaptor.forClass(Scope.class); + verify(this.defaultSpace, new Times(1)).emit(argument1.capture(), argument2.capture(), argument3.capture()); + assertEquals(this.agent.getID(), argument1.getValue()); + assertSame(event, argument2.getValue()); + assertNull(argument3.getValue()); } @Test diff --git a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/ExternalContextAccessSkillTest.java b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/ExternalContextAccessSkillTest.java index 8ea41190db..cc1546ac27 100644 --- a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/ExternalContextAccessSkillTest.java +++ b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/bic/ExternalContextAccessSkillTest.java @@ -188,18 +188,20 @@ public void join() { AgentContext ctx = this.skill.getContext(c.getID()); assertSame(c, ctx); // - ArgumentCaptor argument1 = ArgumentCaptor.forClass(Event.class); - verify(c.getDefaultSpace(), new Times(1)).emit(argument1.capture()); - Event evt = argument1.getValue(); + ArgumentCaptor argument1 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument2 = ArgumentCaptor.forClass(Event.class); + verify(c.getDefaultSpace(), new Times(1)).emit(argument1.capture(), argument2.capture()); + assertNull(argument1.getValue()); + Event evt = argument2.getValue(); assertNotNull(evt); assertTrue(evt instanceof MemberJoined); assertEquals(c.getID(), ((MemberJoined) evt).parentContextID); assertEquals(this.agent.getID(), ((MemberJoined) evt).agentID); // - ArgumentCaptor argument2 = ArgumentCaptor.forClass(Event.class); + ArgumentCaptor argument3 = ArgumentCaptor.forClass(Event.class); ++nb; - verify(this.behaviorCapacity, new Times(nb)).wake(argument2.capture()); - evt = argument2.getValue(); + verify(this.behaviorCapacity, new Times(nb)).wake(argument3.capture()); + evt = argument3.getValue(); assertNotNull(evt); assertTrue(evt instanceof ContextJoined); assertEquals(c.getID(), ((ContextJoined) evt).holonContextID); @@ -231,19 +233,21 @@ public void leave() { assertTrue(remaining.contains(ctx)); } // - ArgumentCaptor argument1 = ArgumentCaptor.forClass(Event.class); + ArgumentCaptor argument1 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument2 = ArgumentCaptor.forClass(Event.class); // 2 times: 1 for MemberJoined, 1 for MemberLeft - verify(c.getDefaultSpace(), new Times(2)).emit(argument1.capture()); - Event evt = argument1.getValue(); + verify(c.getDefaultSpace(), new Times(2)).emit(argument1.capture(), argument2.capture()); + assertNull(argument1.getValue()); + Event evt = argument2.getValue(); assertNotNull(evt); assertTrue(evt instanceof MemberLeft); assertEquals(this.agent.getID(), ((MemberLeft) evt).agentID); // - ArgumentCaptor argument2 = ArgumentCaptor.forClass(Event.class); + ArgumentCaptor argument3 = ArgumentCaptor.forClass(Event.class); ++nb; // Nb times includes the joins and the leaves - verify(this.behaviorCapacity, new Times(nb)).wake(argument2.capture()); - evt = argument2.getValue(); + verify(this.behaviorCapacity, new Times(nb)).wake(argument3.capture()); + evt = argument3.getValue(); assertNotNull(evt); assertTrue(evt instanceof ContextLeft); assertEquals(c.getID(), ((ContextLeft) evt).holonContextID); diff --git a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/services/jdk/contextspace/ContextTest.java b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/services/jdk/contextspace/ContextTest.java index 40a834382b..db4ee683de 100644 --- a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/services/jdk/contextspace/ContextTest.java +++ b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/services/jdk/contextspace/ContextTest.java @@ -253,10 +253,12 @@ public void createSpace() { // OpenEventSpace defSpace = this.spaces.get(this.spaceId); assertNotNull(defSpace); - ArgumentCaptor argument3 = ArgumentCaptor.forClass(Event.class); - Mockito.verify(defSpace, new Times(1)).emit(argument3.capture()); - assertThat(argument3.getValue(), new IsInstanceOf(SpaceCreated.class)); - assertEquals(id, ((SpaceCreated) argument3.getValue()).spaceID.getID()); + ArgumentCaptor argument3 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument4 = ArgumentCaptor.forClass(Event.class); + Mockito.verify(defSpace, new Times(1)).emit(argument3.capture(), argument4.capture()); + assertNull(argument3.getValue()); + assertThat(argument4.getValue(), new IsInstanceOf(SpaceCreated.class)); + assertEquals(id, ((SpaceCreated) argument4.getValue()).spaceID.getID()); } @Test @@ -288,10 +290,12 @@ public void getOrCreateSpaceWithSpec() { // OpenEventSpace defSpace = this.spaces.get(this.spaceId); assertNotNull(defSpace); - ArgumentCaptor argument3 = ArgumentCaptor.forClass(Event.class); - Mockito.verify(defSpace, new Times(1)).emit(argument3.capture()); - assertThat(argument3.getValue(), new IsInstanceOf(SpaceCreated.class)); - assertEquals(id, ((SpaceCreated) argument3.getValue()).spaceID.getID()); + ArgumentCaptor argument3 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument4 = ArgumentCaptor.forClass(Event.class); + Mockito.verify(defSpace, new Times(1)).emit(argument3.capture(), argument4.capture()); + assertNull(argument3.getValue()); + assertThat(argument4.getValue(), new IsInstanceOf(SpaceCreated.class)); + assertEquals(id, ((SpaceCreated) argument4.getValue()).spaceID.getID()); // OpenEventSpace space2 = this.context.getOrCreateSpaceWithSpec(OpenEventSpaceSpecification.class, id); assertSame(space, space2); @@ -326,10 +330,12 @@ public void getOrCreateSpaceWithID() { // OpenEventSpace defSpace = this.spaces.get(this.spaceId); assertNotNull(defSpace); - ArgumentCaptor argument3 = ArgumentCaptor.forClass(Event.class); - Mockito.verify(defSpace, new Times(1)).emit(argument3.capture()); - assertThat(argument3.getValue(), new IsInstanceOf(SpaceCreated.class)); - assertEquals(id, ((SpaceCreated) argument3.getValue()).spaceID.getID()); + ArgumentCaptor argument3 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument4 = ArgumentCaptor.forClass(Event.class); + Mockito.verify(defSpace, new Times(1)).emit(argument3.capture(), argument4.capture()); + assertNull(argument3.getValue()); + assertThat(argument4.getValue(), new IsInstanceOf(SpaceCreated.class)); + assertEquals(id, ((SpaceCreated) argument4.getValue()).spaceID.getID()); // OpenEventSpace space2 = this.context.getOrCreateSpaceWithID(id, OpenEventSpaceSpecification.class); assertSame(space, space2); diff --git a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/services/jdk/spawn/StandardSpawnServiceTest.java b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/services/jdk/spawn/StandardSpawnServiceTest.java index 41000bec3b..afedfc13a8 100644 --- a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/services/jdk/spawn/StandardSpawnServiceTest.java +++ b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/services/jdk/spawn/StandardSpawnServiceTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -238,10 +239,12 @@ public void spawn_1agent() throws Exception { assertEquals("a", argument3.getValue()[0]); //$NON-NLS-1$ assertEquals("b", argument3.getValue()[1]); //$NON-NLS-1$ // - ArgumentCaptor argument4 = ArgumentCaptor.forClass(Event.class); - Mockito.verify(this.defaultSpace, new Times(1)).emit(argument4.capture()); - assertTrue(argument4.getValue() instanceof AgentSpawned); - assertContainsCollection(((AgentSpawned) argument4.getValue()).agentIdentifiers, agentIds); + ArgumentCaptor argument4 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument5 = ArgumentCaptor.forClass(Event.class); + Mockito.verify(this.defaultSpace, new Times(1)).emit(argument4.capture(), argument5.capture()); + assertNull(argument4.getValue()); + assertTrue(argument5.getValue() instanceof AgentSpawned); + assertContainsCollection(((AgentSpawned) argument5.getValue()).agentIdentifiers, agentIds); } @AvoidServiceStartForTest @@ -289,10 +292,12 @@ public void killAgent() throws Exception { Mockito.verify(this.serviceListener, new Times(1)).agentDestroy(argument4.capture()); assertSame(ag, argument4.getValue()); // - ArgumentCaptor argument5 = ArgumentCaptor.forClass(Event.class); - Mockito.verify(this.defaultSpace, new Times(2)).emit(argument5.capture()); - assertTrue(argument5.getValue() instanceof AgentKilled); - assertEquals(agentIds.get(0), ((AgentKilled) argument5.getValue()).agentID); + ArgumentCaptor argument5 = ArgumentCaptor.forClass(UUID.class); + ArgumentCaptor argument6 = ArgumentCaptor.forClass(Event.class); + Mockito.verify(this.defaultSpace, new Times(2)).emit(argument5.capture(), argument6.capture()); + assertNull(argument5.getValue()); + assertTrue(argument6.getValue() instanceof AgentKilled); + assertEquals(agentIds.get(0), ((AgentKilled) argument6.getValue()).agentID); // Mockito.verify(this.kernelListener, new Times(1)).kernelAgentDestroy(); } diff --git a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/space/AbstractEventSpaceTest.java b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/space/AbstractEventSpaceTest.java index a73eb1b818..0803198b47 100644 --- a/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/space/AbstractEventSpaceTest.java +++ b/sre/io.janusproject/io.janusproject.tests/src/test/java/io/janusproject/tests/kernel/space/AbstractEventSpaceTest.java @@ -287,7 +287,7 @@ public void doEmit_scopebothaddresses() throws Exception { } @Test - public void emitEventScope_fullscope() throws Exception { + public void emitUUIDEventScope_fullscope() throws Exception { Event event; Scope
scope = Scopes.
allParticipants(); @@ -295,7 +295,8 @@ public void emitEventScope_fullscope() throws Exception { event = Mockito.mock(Event.class); Mockito.when(event.getSource()).thenReturn(this.address); - this.space.emit(event, scope); + // No need to give an event source because is it explicitly defined above. + this.space.emit(null, event, scope); ArgumentCaptor argument = ArgumentCaptor.forClass(Event.class); Mockito.verify(this.listener).receiveEvent(argument.capture()); @@ -310,7 +311,7 @@ public void emitEventScope_fullscope() throws Exception { } @Test - public void emitEventScope_scopeaddress() throws Exception { + public void emitUUIDEventScope_scopeaddress() throws Exception { Event event; Scope
scope = Scopes.addresses(this.address); @@ -318,7 +319,8 @@ public void emitEventScope_scopeaddress() throws Exception { event = Mockito.mock(Event.class); Mockito.when(event.getSource()).thenReturn(this.address); - this.space.emit(event, scope); + // No need to give an event source because is it explicitly defined above. + this.space.emit(null, event, scope); ArgumentCaptor argument = ArgumentCaptor.forClass(Event.class); Mockito.verify(this.listener).receiveEvent(argument.capture()); @@ -333,7 +335,7 @@ public void emitEventScope_scopeaddress() throws Exception { } @Test - public void emitEventScope_scopeotheraddress() throws Exception { + public void emitUUIDEventScope_scopeotheraddress() throws Exception { Address otherAddress = new Address(new SpaceID(UUID.randomUUID(), UUID.randomUUID(), OpenEventSpaceSpecification.class), UUID.randomUUID()); @@ -344,7 +346,8 @@ public void emitEventScope_scopeotheraddress() throws Exception { event = Mockito.mock(Event.class); Mockito.when(event.getSource()).thenReturn(this.address); - this.space.emit(event, scope); + // No need to give an event source because is it explicitly defined above. + this.space.emit(null, event, scope); Mockito.verify(this.listener, new Times(0)).receiveEvent(Mockito.any()); { ArgumentCaptor netscope = ArgumentCaptor.forClass(Scope.class); @@ -356,7 +359,7 @@ public void emitEventScope_scopeotheraddress() throws Exception { } @Test - public void emitEventScope_scopebothaddresses() throws Exception { + public void emitUUIDEventScope_scopebothaddresses() throws Exception { Address otherAddress = new Address(new SpaceID(UUID.randomUUID(), UUID.randomUUID(), OpenEventSpaceSpecification.class), UUID.randomUUID()); @@ -367,7 +370,118 @@ public void emitEventScope_scopebothaddresses() throws Exception { event = Mockito.mock(Event.class); Mockito.when(event.getSource()).thenReturn(this.address); - this.space.emit(event, scope); + // No need to give an event source because is it explicitly defined above. + this.space.emit(null, event, scope); + + ArgumentCaptor argument = ArgumentCaptor.forClass(Event.class); + Mockito.verify(this.listener).receiveEvent(argument.capture()); + assertSame(event, argument.getValue()); + { + ArgumentCaptor netscope = ArgumentCaptor.forClass(Scope.class); + ArgumentCaptor netarg = ArgumentCaptor.forClass(Event.class); + Mockito.verify(this.network).publish(netscope.capture(), netarg.capture()); + assertSame(scope, netscope.getValue()); + assertSame(event, netarg.getValue()); + } + } + + @Test(expected = AssertionError.class) + public void emitUUIDEventScope_noSource_noEventSource() throws Exception { + final Event event = Mockito.mock(Event.class); + // No need to give an event source because is it explicitly defined above. + this.space.emit(null, event, null); + } + + @Test + public void emitUUIDEventScope_fullscope_noSource() throws Exception { + Event event; + Scope
scope = Scopes.
allParticipants(); + + register(); + + event = Mockito.mock(Event.class); + Mockito.doCallRealMethod().when(event).setSource(Mockito.any()); + Mockito.doCallRealMethod().when(event).getSource(); + // No need to give an event source because is it explicitly defined above. + this.space.emit(this.address.getUUID(), event, scope); + + ArgumentCaptor argument = ArgumentCaptor.forClass(Event.class); + Mockito.verify(this.listener).receiveEvent(argument.capture()); + assertSame(event, argument.getValue()); + { + ArgumentCaptor netscope = ArgumentCaptor.forClass(Scope.class); + ArgumentCaptor netarg = ArgumentCaptor.forClass(Event.class); + Mockito.verify(this.network).publish(netscope.capture(), netarg.capture()); + assertSame(scope, netscope.getValue()); + assertSame(event, netarg.getValue()); + } + } + + @Test + public void emitUUIDEventScope_scopeaddress_noSource() throws Exception { + Event event; + Scope
scope = Scopes.addresses(this.address); + + register(); + + event = Mockito.mock(Event.class); + Mockito.doCallRealMethod().when(event).setSource(Mockito.any()); + Mockito.doCallRealMethod().when(event).getSource(); + // No need to give an event source because is it explicitly defined above. + this.space.emit(this.address.getUUID(), event, scope); + + ArgumentCaptor argument = ArgumentCaptor.forClass(Event.class); + Mockito.verify(this.listener).receiveEvent(argument.capture()); + assertSame(event, argument.getValue()); + { + ArgumentCaptor netscope = ArgumentCaptor.forClass(Scope.class); + ArgumentCaptor netarg = ArgumentCaptor.forClass(Event.class); + Mockito.verify(this.network).publish(netscope.capture(), netarg.capture()); + assertSame(scope, netscope.getValue()); + assertSame(event, netarg.getValue()); + } + } + + @Test + public void emitUUIDEventScope_scopeotheraddress_noSource() throws Exception { + Address otherAddress = new Address(new SpaceID(UUID.randomUUID(), UUID.randomUUID(), OpenEventSpaceSpecification.class), + UUID.randomUUID()); + + Event event; + Scope
scope = Scopes.addresses(otherAddress); + + register(); + + event = Mockito.mock(Event.class); + Mockito.doCallRealMethod().when(event).setSource(Mockito.any()); + Mockito.doCallRealMethod().when(event).getSource(); + // No need to give an event source because is it explicitly defined above. + this.space.emit(this.address.getUUID(), event, scope); + Mockito.verify(this.listener, new Times(0)).receiveEvent(Mockito.any()); + { + ArgumentCaptor netscope = ArgumentCaptor.forClass(Scope.class); + ArgumentCaptor netarg = ArgumentCaptor.forClass(Event.class); + Mockito.verify(this.network).publish(netscope.capture(), netarg.capture()); + assertSame(scope, netscope.getValue()); + assertSame(event, netarg.getValue()); + } + } + + @Test + public void emitUUIDEventScope_scopebothaddresses_noSource() throws Exception { + Address otherAddress = new Address(new SpaceID(UUID.randomUUID(), UUID.randomUUID(), OpenEventSpaceSpecification.class), + UUID.randomUUID()); + + Event event; + Scope
scope = Scopes.addresses(this.address, otherAddress); + + register(); + + event = Mockito.mock(Event.class); + Mockito.doCallRealMethod().when(event).setSource(Mockito.any()); + Mockito.doCallRealMethod().when(event).getSource(); + // No need to give an event source because is it explicitly defined above. + this.space.emit(this.address.getUUID(), event, scope); ArgumentCaptor argument = ArgumentCaptor.forClass(Event.class); Mockito.verify(this.listener).receiveEvent(argument.capture()); diff --git a/tests/io.sarl.core.tests/src/test/java/io/sarl/core/tests/ExternalContextAccessTest.java b/tests/io.sarl.core.tests/src/test/java/io/sarl/core/tests/ExternalContextAccessTest.java index e0bce22bf4..af21afa8f8 100644 --- a/tests/io.sarl.core.tests/src/test/java/io/sarl/core/tests/ExternalContextAccessTest.java +++ b/tests/io.sarl.core.tests/src/test/java/io/sarl/core/tests/ExternalContextAccessTest.java @@ -48,7 +48,7 @@ public void setUp() { */ @Test public void memberCount() { - assertEquals(7, this.type.getDeclaredMethods().length); + assertEquals(9, this.type.getDeclaredMethods().length); } /**