/* * $Id$ * * Janus platform is an open-source multiagent platform. * More details on http://www.janusproject.io * * Copyright (C) 2014-2015 Sebastian RODRIGUEZ, Nicolas GAUD, Stéphane GALLAND. * * Licensed 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 io.janusproject.tests.kernel.bic; 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.mockito.Mockito.*; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.UUID; import io.janusproject.kernel.bic.ExternalContextAccessSkill; import io.janusproject.kernel.bic.InternalEventBusCapacity; import io.janusproject.services.contextspace.ContextSpaceService; import io.janusproject.tests.testutils.AbstractJanusTest; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.internal.verification.Times; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import io.sarl.core.Behaviors; import io.sarl.core.ContextJoined; import io.sarl.core.ContextLeft; 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.BuiltinCapacitiesProvider; import io.sarl.lang.core.Capacity; import io.sarl.lang.core.Event; import io.sarl.lang.core.EventListener; import io.sarl.lang.core.EventSpaceSpecification; import io.sarl.lang.core.Skill; import io.sarl.lang.core.Skill.UninstallationStage; import io.sarl.lang.core.Space; import io.sarl.lang.core.SpaceID; import io.sarl.lang.util.ClearableReference; import io.sarl.tests.api.ManualMocking; import io.sarl.tests.api.Nullable; import io.sarl.util.OpenEventSpace; /** * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ @SuppressWarnings("all") @ManualMocking public class ExternalContextAccessSkillTest extends AbstractJanusTest { private static final Object MUTEX = new Object(); @Nullable private List<AgentContext> contexts; @Mock private ContextSpaceService contextRepository; @InjectMocks private ExternalContextAccessSkill skill; @Nullable private InternalEventBusCapacity busCapacity; @Nullable private Behaviors behaviorCapacity; @Nullable private OpenEventSpace defaultSpace; @Nullable private Agent agent; @Nullable private EventListener eventListener; @Before public void setUp() throws Exception { UUID parentId = UUID.randomUUID(); this.eventListener = mock(EventListener.class); this.behaviorCapacity = mock(Behaviors.class); this.busCapacity = mock(InternalEventBusCapacity.class); when(this.busCapacity.asEventListener()).thenReturn(this.eventListener); this.contexts = new ArrayList<>(); for (int i = 0; i < 10; ++i) { UUID contextId = i == 0 ? parentId : UUID.randomUUID(); OpenEventSpace defaultSpace = mock(OpenEventSpace.class); if (i == 0) { this.defaultSpace = defaultSpace; } when(defaultSpace.getSpaceID()).thenReturn(new SpaceID(contextId, UUID.randomUUID(), EventSpaceSpecification.class)); AgentContext c = mock(AgentContext.class); when(c.getID()).thenReturn(contextId); when(c.getDefaultSpace()).thenReturn(defaultSpace); this.contexts.add(c); } this.agent = new TestAgent(this); this.agent = spy(this.agent); when(this.agent.getParentID()).thenReturn(parentId); this.skill = this.reflect.newInstance(ExternalContextAccessSkill.class, this.agent); MockitoAnnotations.initMocks(this); when(this.contextRepository.mutex()).thenReturn(MUTEX); when(this.contextRepository.getContexts()).thenReturn(this.contexts); when(this.contextRepository.getContexts(ArgumentMatchers.anyCollection())).then(new Answer<Collection>() { @Override public Collection answer(InvocationOnMock invocation) throws Throwable { Collection<UUID> ids = (Collection<UUID>) invocation.getArguments()[0]; List<AgentContext> l = new ArrayList<>(); for (AgentContext ctx : ExternalContextAccessSkillTest.this.contexts) { if (ids.contains(ctx.getID())) { l.add(ctx); } } return l; } }); when(this.contextRepository.getContext(ArgumentMatchers.any(UUID.class))).then(new Answer<AgentContext>() { @Override public AgentContext answer(InvocationOnMock invocation) throws Throwable { UUID id = (UUID) invocation.getArguments()[0]; for (AgentContext ctx : ExternalContextAccessSkillTest.this.contexts) { if (id.equals(ctx.getID())) { return ctx; } } return null; } }); } @Test public void getAllContexts() { Collection<AgentContext> c = this.skill.getAllContexts(); assertTrue(c.isEmpty()); } @Test(expected = IllegalArgumentException.class) public void getContext() { for (AgentContext c : this.contexts) { this.skill.getContext(c.getID()); } } @Test public void join() { int nb = 0; for (AgentContext c : this.contexts) { this.skill.join(c.getID(), c.getDefaultSpace().getSpaceID().getID()); // AgentContext ctx = this.skill.getContext(c.getID()); assertSame(c, ctx); // ArgumentCaptor<Event> argument1 = ArgumentCaptor.forClass(Event.class); verify(c.getDefaultSpace(), new Times(1)).emit(argument1.capture()); Event evt = argument1.getValue(); assertNotNull(evt); assertTrue(evt instanceof MemberJoined); assertEquals(c.getID(), ((MemberJoined) evt).parentContextID); assertEquals(this.agent.getID(), ((MemberJoined) evt).agentID); // ArgumentCaptor<Event> argument2 = ArgumentCaptor.forClass(Event.class); ++nb; verify(this.behaviorCapacity, new Times(nb)).wake(argument2.capture()); evt = argument2.getValue(); assertNotNull(evt); assertTrue(evt instanceof ContextJoined); assertEquals(c.getID(), ((ContextJoined) evt).holonContextID); assertEquals(c.getDefaultSpace().getSpaceID().getID(), ((ContextJoined) evt).defaultSpaceID); } Collection<AgentContext> c = this.skill.getAllContexts(); assertEquals(this.contexts.size(), c.size()); for (AgentContext ctx : c) { assertTrue(this.contexts.contains(ctx)); } } @Test public void leave() { int nb = 0; for (AgentContext c : this.contexts) { this.skill.join(c.getID(), c.getDefaultSpace().getSpaceID().getID()); ++nb; } // List<AgentContext> remaining = new ArrayList<>(this.contexts); for (AgentContext c : this.contexts) { this.skill.leave(c.getID()); // remaining.remove(c); Collection<AgentContext> in = this.skill.getAllContexts(); assertEquals(remaining.size(), in.size()); for (AgentContext ctx : in) { assertTrue(remaining.contains(ctx)); } // ArgumentCaptor<Event> argument1 = 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(); assertNotNull(evt); assertTrue(evt instanceof MemberLeft); assertEquals(this.agent.getID(), ((MemberLeft) evt).agentID); // ArgumentCaptor<Event> argument2 = 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(); assertNotNull(evt); assertTrue(evt instanceof ContextLeft); assertEquals(c.getID(), ((ContextLeft) evt).holonContextID); } assertTrue(remaining.isEmpty()); } @Test public void install() throws Exception { assertNull(this.defaultSpace.getAddress(this.agent.getID())); this.reflect.invoke(this.skill, "install"); ArgumentCaptor<EventListener> argument = ArgumentCaptor.forClass(EventListener.class); verify(this.defaultSpace, new Times(1)).register(argument.capture()); assertSame(this.eventListener, argument.getValue()); } @Test public void uninstall_Pre() throws Exception { this.reflect.invoke(this.skill, "install"); this.reflect.invoke(this.skill, "uninstall", UninstallationStage.PRE_DESTROY_EVENT); ArgumentCaptor<EventListener> argument = ArgumentCaptor.forClass(EventListener.class); verify(this.defaultSpace, never()).unregister(argument.capture()); } @Test public void uninstall_Post() throws Exception { this.reflect.invoke(this.skill, "install"); this.reflect.invoke(this.skill, "uninstall", UninstallationStage.POST_DESTROY_EVENT); ArgumentCaptor<EventListener> argument = ArgumentCaptor.forClass(EventListener.class); verify(this.defaultSpace, new Times(1)).unregister(argument.capture()); assertSame(this.eventListener, argument.getValue()); } @Test(expected = NullPointerException.class) public void isInSpaceEventSpace_null_null() throws Exception { this.reflect.invoke(this.skill, "install"); this.skill.isInSpace(null, (Space) null); } @Test(expected = NullPointerException.class) public void isInSpaceEventSpace_notNull_null() throws Exception { this.reflect.invoke(this.skill, "install"); this.skill.isInSpace(mock(Event.class), (Space) null); } @Test(expected = NullPointerException.class) public void isInSpaceEventSpace_null_notNull() throws Exception { this.reflect.invoke(this.skill, "install"); this.skill.isInSpace(null, mock(Space.class)); } @Test public void isInSpaceEventSpace_inside() throws Exception { this.reflect.invoke(this.skill, "install"); UUID id = UUID.randomUUID(); SpaceID spaceID = mock(SpaceID.class); when(spaceID.getID()).thenReturn(id); Space space = mock(Space.class); when(space.getSpaceID()).thenReturn(spaceID); Event event = mock(Event.class); Address address = mock(Address.class); when(address.getSpaceId()).thenReturn(spaceID); when(event.getSource()).thenReturn(address); // assertTrue(this.skill.isInSpace(event, space)); } @Test public void isInSpaceEventSpace_outside() throws Exception { this.reflect.invoke(this.skill, "install"); UUID id = UUID.randomUUID(); SpaceID spaceID = mock(SpaceID.class); when(spaceID.getID()).thenReturn(id); Space space = mock(Space.class); when(space.getSpaceID()).thenReturn(spaceID); Event event = mock(Event.class); SpaceID spaceID2 = mock(SpaceID.class); when(spaceID2.getID()).thenReturn(UUID.randomUUID()); Address address = mock(Address.class); when(address.getSpaceId()).thenReturn(spaceID2); when(event.getSource()).thenReturn(address); // assertFalse(this.skill.isInSpace(event, space)); } @Test(expected = NullPointerException.class) public void isInSpaceEventSpaceID_null_null() throws Exception { this.reflect.invoke(this.skill, "install"); this.skill.isInSpace(null, (SpaceID) null); } @Test(expected = NullPointerException.class) public void isInSpaceEventSpaceID_notNull_null() throws Exception { this.reflect.invoke(this.skill, "install"); this.skill.isInSpace(mock(Event.class), (SpaceID) null); } @Test(expected = NullPointerException.class) public void isInSpaceEventSpaceID_null_notNull() throws Exception { this.reflect.invoke(this.skill, "install"); this.skill.isInSpace(null, mock(SpaceID.class)); } @Test public void isInSpaceEventSpaceID_inside() throws Exception { this.reflect.invoke(this.skill, "install"); UUID id = UUID.randomUUID(); SpaceID spaceID = mock(SpaceID.class); when(spaceID.getID()).thenReturn(id); Event event = mock(Event.class); Address address = mock(Address.class); when(address.getSpaceId()).thenReturn(spaceID); when(event.getSource()).thenReturn(address); // assertTrue(this.skill.isInSpace(event, spaceID)); } @Test public void isInSpaceEventSpaceID_outside() throws Exception { this.reflect.invoke(this.skill, "install"); UUID id = UUID.randomUUID(); SpaceID spaceID = mock(SpaceID.class); when(spaceID.getID()).thenReturn(id); Event event = mock(Event.class); SpaceID spaceID2 = mock(SpaceID.class); when(spaceID2.getID()).thenReturn(UUID.randomUUID()); Address address = mock(Address.class); when(address.getSpaceId()).thenReturn(spaceID2); when(event.getSource()).thenReturn(address); // assertFalse(this.skill.isInSpace(event, spaceID)); } @Test(expected = NullPointerException.class) public void isInSpaceEventUUID_null_null() throws Exception { this.reflect.invoke(this.skill, "install"); this.skill.isInSpace(null, (UUID) null); } @Test(expected = NullPointerException.class) public void isInSpaceEventUUID_notNull_null() throws Exception { this.reflect.invoke(this.skill, "install"); this.skill.isInSpace(mock(Event.class), (UUID) null); } @Test(expected = NullPointerException.class) public void isInSpaceEventUUID_null_notNull() throws Exception { this.reflect.invoke(this.skill, "install"); this.skill.isInSpace(null, UUID.randomUUID()); } @Test public void isInSpaceEventUUID_inside() throws Exception { this.reflect.invoke(this.skill, "install"); UUID id = UUID.randomUUID(); SpaceID spaceID = mock(SpaceID.class); when(spaceID.getID()).thenReturn(id); Event event = mock(Event.class); Address address = mock(Address.class); when(address.getSpaceId()).thenReturn(spaceID); when(event.getSource()).thenReturn(address); // assertTrue(this.skill.isInSpace(event, id)); } @Test public void isInSpaceEventUUID_outside() throws Exception { this.reflect.invoke(this.skill, "install"); UUID id = UUID.randomUUID(); Event event = mock(Event.class); SpaceID spaceID2 = mock(SpaceID.class); when(spaceID2.getID()).thenReturn(UUID.randomUUID()); Address address = mock(Address.class); when(address.getSpaceId()).thenReturn(spaceID2); when(event.getSource()).thenReturn(address); // assertFalse(this.skill.isInSpace(event, id)); } public static class TestAgent extends Agent { private final ExternalContextAccessSkillTest test; public TestAgent(ExternalContextAccessSkillTest test) { super(Mockito.mock(BuiltinCapacitiesProvider.class), UUID.randomUUID(), null); this.test = test; } @Override protected ClearableReference<Skill> $getSkill(Class<? extends Capacity> capacity) { if (Behaviors.class.equals(capacity)) return new ClearableReference(this.test.behaviorCapacity); return new ClearableReference(this.test.busCapacity); } } }