/*
* $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.services.jdk.contextspace;
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;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.UUID;
import com.google.inject.Injector;
import io.janusproject.kernel.services.jdk.contextspace.Context;
import io.janusproject.kernel.services.jdk.contextspace.ContextFactory;
import io.janusproject.kernel.services.jdk.contextspace.SpaceRepositoryFactory;
import io.janusproject.kernel.services.jdk.contextspace.StandardContextSpaceService;
import io.janusproject.kernel.services.jdk.distributeddata.DMapView;
import io.janusproject.services.contextspace.ContextRepositoryListener;
import io.janusproject.services.contextspace.ContextSpaceService;
import io.janusproject.services.contextspace.SpaceRepositoryListener;
import io.janusproject.services.distributeddata.DMap;
import io.janusproject.services.distributeddata.DistributedDataStructureService;
import io.janusproject.services.kerneldiscovery.KernelDiscoveryService;
import io.janusproject.services.logging.LogService;
import io.janusproject.services.network.NetworkService;
import io.janusproject.tests.testutils.AbstractDependentServiceTest;
import io.janusproject.tests.testutils.AvoidServiceStartForTest;
import io.janusproject.tests.testutils.StartServiceForTest;
import io.janusproject.util.TwoStepConstruction;
import javassist.Modifier;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.internal.verification.Times;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import io.sarl.lang.core.AgentContext;
import io.sarl.lang.core.EventSpace;
import io.sarl.lang.core.SpaceID;
import io.sarl.tests.api.Nullable;
import io.sarl.util.OpenEventSpace;
import io.sarl.util.OpenEventSpaceSpecification;
/**
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
@SuppressWarnings("all")
@StartServiceForTest(startAfterSetUp = true)
public class StandardContextSpaceServiceTest extends AbstractDependentServiceTest<StandardContextSpaceService> {
@Nullable
private UUID contextId;
@Nullable
private SpaceID spaceId;
@Nullable
private DMap<Object, Object> innerData;
@Mock
private DistributedDataStructureService dds;
@Mock
private LogService logger;
@Mock
private Injector injector;
@Mock
private EventSpace defaultSpace;
@Mock
private Context context;
@Mock
private ContextFactory contextFactory;
@Mock
private ContextRepositoryListener contextListener;
/**
*/
public StandardContextSpaceServiceTest() {
super(ContextSpaceService.class);
}
@Override
public StandardContextSpaceService newService() {
return new StandardContextSpaceService();
}
@Override
public void getServiceDependencies() {
assertContains(this.service.getServiceDependencies(), DistributedDataStructureService.class, NetworkService.class,
KernelDiscoveryService.class);
}
@Override
public void getServiceWeakDependencies() {
assertContains(this.service.getServiceWeakDependencies());
}
@Before
public void setUp() throws Exception {
this.contextId = UUID.randomUUID();
this.innerData = new DMapView<>(UUID.randomUUID().toString(), new HashMap<>());
this.spaceId = new SpaceID(this.contextId, UUID.randomUUID(), OpenEventSpaceSpecification.class);
Mockito.when(this.reflect.invoke(this.context, "postConstruction")).thenReturn(this.defaultSpace);
Mockito.when(this.context.getID()).thenReturn(this.contextId);
Mockito.when(this.defaultSpace.getSpaceID()).thenReturn(this.spaceId);
Mockito.when(this.contextFactory.newInstance(ArgumentMatchers.any(), ArgumentMatchers.any(),
ArgumentMatchers.any(), ArgumentMatchers.any()))
.thenAnswer(new Answer<Context>() {
@Override
public Context answer(InvocationOnMock invocation) throws Throwable {
Context ctx = Mockito.mock(Context.class);
OpenEventSpace mock = Mockito.mock(OpenEventSpace.class);
SpaceID spaceId = new SpaceID((UUID) invocation.getArguments()[0], (UUID) invocation.getArguments()[1],
OpenEventSpaceSpecification.class);
Mockito.when(ctx.getID()).thenReturn(spaceId.getContextID());
Mockito.when(reflect.invoke(ctx, "postConstruction")).thenReturn(mock);
Mockito.when(ctx.getDefaultSpace()).thenReturn(mock);
Mockito.when(mock.getSpaceID()).thenReturn(spaceId);
return ctx;
}
});
Mockito.when(this.dds.getMap(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(this.innerData);
Mockito.when(this.dds.getMap(ArgumentMatchers.any())).thenReturn(this.innerData);
this.reflect.invoke(this.service, "postConstruction", this.contextId, this.dds, this.logger, this.injector);
this.reflect.invoke(this.service, "setContextFactory", this.contextFactory);
this.service.addContextRepositoryListener(this.contextListener);
}
private AgentContext createOneTestingContext(UUID id) {
return createOneTestingContext(id, UUID.randomUUID());
}
private AgentContext createOneTestingContext(UUID id, UUID spaceId) {
return this.service.createContext(id, spaceId);
}
@Test
public void twoStepConstruction() throws Exception {
TwoStepConstruction annotation = StandardContextSpaceService.class.getAnnotation(TwoStepConstruction.class);
assertNotNull(annotation);
for (String name : annotation.names()) {
for (Method method : StandardContextSpaceService.class.getMethods()) {
if (name.equals(method.getName())) {
assertTrue(Modifier.isPackage(method.getModifiers()) || Modifier.isPublic(method.getModifiers()));
break;
}
}
}
}
@Test
public void mutex() {
Object mutex = this.service.mutex();
assertNotNull(mutex);
assertSame(mutex, this.service.mutex());
}
@Test
public void getContextFactory() throws Exception {
assertSame(this.contextFactory,
this.reflect.invoke(this.service, "getContextFactory"));
}
@Test
public void setContextFactory() throws Exception {
assertSame(this.contextFactory,
this.reflect.invoke(this.service, "getContextFactory"));
this.reflect.invoke(this.service, "setContextFactory", null);
assertSame(this.contextFactory,
this.reflect.invoke(this.service, "getContextFactory"));
ContextFactory mock = Mockito.mock(ContextFactory.class);
this.reflect.invoke(this.service, "setContextFactory", mock);
assertSame(mock, this.reflect.invoke(this.service, "getContextFactory"));
}
@Test
public void containsContext() {
UUID id = UUID.randomUUID();
assertFalse(this.service.containsContext(id));
createOneTestingContext(id);
assertTrue(this.service.containsContext(id));
}
@Test
public void createContext() {
UUID cid = UUID.randomUUID();
UUID sid = UUID.randomUUID();
AgentContext ctx = this.service.createContext(cid, sid);
//
assertNotNull(ctx);
assertTrue(this.service.containsContext(cid));
assertEquals(cid, ctx.getID());
assertEquals(sid, ctx.getDefaultSpace().getSpaceID().getID());
//
ArgumentCaptor<AgentContext> argument = ArgumentCaptor.forClass(AgentContext.class);
Mockito.verify(this.contextListener, new Times(1)).contextCreated(argument.capture());
assertSame(ctx, argument.getValue());
}
@Test
public void ensureDefaultSpaceDefinition() throws Exception {
SpaceID spaceId = new SpaceID(UUID.randomUUID(), UUID.randomUUID(), OpenEventSpaceSpecification.class);
assertFalse(this.service.containsContext(spaceId.getContextID()));
//
// First call
this.reflect.invoke(this.service, "ensureDefaultSpaceDefinition", spaceId);
//
assertTrue(this.service.containsContext(spaceId.getContextID()));
//
ArgumentCaptor<AgentContext> argument1 = ArgumentCaptor.forClass(AgentContext.class);
Mockito.verify(this.contextListener, new Times(1)).contextCreated(argument1.capture());
assertSame(this.service.getContext(spaceId.getContextID()), argument1.getValue());
//
// Second call
this.reflect.invoke(this.service, "ensureDefaultSpaceDefinition", spaceId);
//
assertTrue(this.service.containsContext(spaceId.getContextID()));
//
ArgumentCaptor<AgentContext> argument2 = ArgumentCaptor.forClass(AgentContext.class);
Mockito.verify(this.contextListener, new Times(1)).contextCreated(argument2.capture());
}
@Test
public void removeDefaultSpaceDefinition() throws Exception {
SpaceID spaceId = new SpaceID(UUID.randomUUID(), UUID.randomUUID(), OpenEventSpaceSpecification.class);
assertFalse(this.service.containsContext(spaceId.getContextID()));
//
// First call
this.reflect.invoke(this.service, "removeDefaultSpaceDefinition", spaceId);
//
assertFalse(this.service.containsContext(spaceId.getContextID()));
Mockito.verifyZeroInteractions(this.contextListener);
//
AgentContext ctx = createOneTestingContext(spaceId.getContextID(), spaceId.getID());
assertTrue(this.service.containsContext(spaceId.getContextID()));
//
// Second call
this.reflect.invoke(this.service, "removeDefaultSpaceDefinition", spaceId);
//
assertFalse(this.service.containsContext(spaceId.getContextID()));
//
ArgumentCaptor<AgentContext> argument2 = ArgumentCaptor.forClass(AgentContext.class);
Mockito.verify(this.contextListener, new Times(1)).contextDestroyed(argument2.capture());
assertSame(ctx, argument2.getValue());
}
@Test
public void isEmptyContextRepository() {
assertTrue(this.service.isEmptyContextRepository());
AgentContext ctx = createOneTestingContext(UUID.randomUUID());
assertFalse(this.service.isEmptyContextRepository());
this.service.removeContext(ctx);
assertTrue(this.service.isEmptyContextRepository());
}
@Test
public void getNumberOfContexts() {
assertEquals(0, this.service.getNumberOfContexts());
AgentContext ctx1 = createOneTestingContext(UUID.randomUUID());
assertEquals(1, this.service.getNumberOfContexts());
AgentContext ctx2 = createOneTestingContext(UUID.randomUUID());
assertEquals(2, this.service.getNumberOfContexts());
this.service.removeContext(ctx2);
assertEquals(1, this.service.getNumberOfContexts());
this.service.removeContext(ctx2);
assertEquals(1, this.service.getNumberOfContexts());
this.service.removeContext(ctx1);
assertEquals(0, this.service.getNumberOfContexts());
}
@Test
public void removeContextAgentContext() {
AgentContext ctx1 = createOneTestingContext(UUID.randomUUID());
AgentContext ctx2 = createOneTestingContext(UUID.randomUUID());
//
// First call
this.service.removeContext(ctx2);
//
assertTrue(this.service.containsContext(ctx1.getID()));
assertFalse(this.service.containsContext(ctx2.getID()));
ArgumentCaptor<AgentContext> argument1 = ArgumentCaptor.forClass(AgentContext.class);
Mockito.verify(this.contextListener, new Times(1)).contextDestroyed(argument1.capture());
assertSame(ctx2, argument1.getValue());
//
// Second call
this.service.removeContext(ctx2);
//
assertTrue(this.service.containsContext(ctx1.getID()));
assertFalse(this.service.containsContext(ctx2.getID()));
ArgumentCaptor<AgentContext> argument3 = ArgumentCaptor.forClass(AgentContext.class);
Mockito.verify(this.contextListener, new Times(1)).contextDestroyed(argument3.capture());
}
@Test
public void removeContextUUID() {
AgentContext ctx1 = createOneTestingContext(UUID.randomUUID());
AgentContext ctx2 = createOneTestingContext(UUID.randomUUID());
//
// First call
this.service.removeContext(ctx2.getID());
//
assertTrue(this.service.containsContext(ctx1.getID()));
assertFalse(this.service.containsContext(ctx2.getID()));
ArgumentCaptor<AgentContext> argument1 = ArgumentCaptor.forClass(AgentContext.class);
Mockito.verify(this.contextListener, new Times(1)).contextDestroyed(argument1.capture());
assertSame(ctx2, argument1.getValue());
//
// Second call
this.service.removeContext(ctx2.getID());
//
assertTrue(this.service.containsContext(ctx1.getID()));
assertFalse(this.service.containsContext(ctx2.getID()));
ArgumentCaptor<AgentContext> argument3 = ArgumentCaptor.forClass(AgentContext.class);
Mockito.verify(this.contextListener, new Times(1)).contextDestroyed(argument3.capture());
}
@Test
public void getContexts() {
Collection<AgentContext> c;
//
c = this.service.getContexts();
assertNotNull(c);
assertTrue(c.isEmpty());
//
AgentContext ctx1 = createOneTestingContext(UUID.randomUUID());
AgentContext ctx2 = createOneTestingContext(UUID.randomUUID());
//
c = this.service.getContexts();
assertNotNull(c);
assertFalse(c.isEmpty());
assertEquals(2, c.size());
assertTrue(c.contains(ctx1));
assertTrue(c.contains(ctx2));
}
@Test
public void getContextIDs() {
Collection<UUID> c;
//
c = this.service.getContextIDs();
assertNotNull(c);
assertTrue(c.isEmpty());
//
AgentContext ctx1 = createOneTestingContext(UUID.randomUUID());
AgentContext ctx2 = createOneTestingContext(UUID.randomUUID());
//
c = this.service.getContextIDs();
assertNotNull(c);
assertFalse(c.isEmpty());
assertEquals(2, c.size());
assertTrue(c.contains(ctx1.getID()));
assertTrue(c.contains(ctx2.getID()));
}
@Test
public void getContextUUID() {
UUID cid1 = UUID.randomUUID();
UUID cid2 = UUID.randomUUID();
UUID cid3 = UUID.randomUUID();
//
assertNull(this.service.getContext(cid1));
assertNull(this.service.getContext(cid2));
assertNull(this.service.getContext(cid3));
//
AgentContext ctx1 = createOneTestingContext(cid1);
AgentContext ctx2 = createOneTestingContext(cid2);
//
assertSame(ctx1, this.service.getContext(cid1));
assertSame(ctx2, this.service.getContext(cid2));
assertNull(this.service.getContext(cid3));
}
@Test
public void getContextsCollection() {
Collection<AgentContext> c;
UUID cid1 = UUID.randomUUID();
UUID cid2 = UUID.randomUUID();
UUID cid3 = UUID.randomUUID();
//
c = this.service.getContexts(Arrays.asList(cid1, cid3));
assertNotNull(c);
assertTrue(c.isEmpty());
//
AgentContext ctx1 = createOneTestingContext(cid1);
createOneTestingContext(cid2);
//
c = this.service.getContexts(Arrays.asList(cid1, cid3));
assertNotNull(c);
assertFalse(c.isEmpty());
assertEquals(1, c.size());
assertTrue(c.contains(ctx1));
}
@AvoidServiceStartForTest
@Test
public void doStop_noinit() throws Exception {
try {
this.reflect.invoke(this.service, "doStop");
fail("Expecting IllegalStateException"); //$NON-NLS-1$
} catch (InvocationTargetException exception) {
Throwable ex = exception.getCause();
if (!(ex instanceof IllegalStateException)) {
fail("Expecting IllegalStateException"); //$NON-NLS-1$
}
}
Mockito.verifyNoMoreInteractions(this.contextListener);
}
@Test
public void doStop_init() throws Exception {
AgentContext ctx1 = createOneTestingContext(UUID.randomUUID());
AgentContext ctx2 = createOneTestingContext(UUID.randomUUID());
//
this.reflect.invoke(this.service, "doStop");
ArgumentCaptor<AgentContext> argument = ArgumentCaptor.forClass(AgentContext.class);
Mockito.verify(this.contextListener, new Times(2)).contextDestroyed(argument.capture());
if (ctx1.getID().compareTo(ctx2.getID()) <= 0) {
assertSame(ctx1, argument.getAllValues().get(0));
assertSame(ctx2, argument.getAllValues().get(1));
} else {
assertSame(ctx1, argument.getAllValues().get(1));
assertSame(ctx2, argument.getAllValues().get(0));
}
}
}