/*
* $Id$
*
* Copyright 2008-2014 Glencoe Software, Inc. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.services.blitz.test.mock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.sf.ehcache.CacheManager;
import ome.model.meta.Experimenter;
import ome.model.meta.ExperimenterGroup;
import ome.model.meta.Session;
import ome.security.basic.CurrentDetails;
import ome.services.ThumbnailBean;
import ome.services.messages.DestroySessionMessage;
import ome.services.messages.GlobalMulticaster;
import ome.services.sessions.SessionManagerImpl;
import ome.services.sessions.events.UserGroupUpdateEvent;
import ome.services.sessions.state.SessionCache;
import ome.services.util.Executor;
import ome.system.Roles;
import omero.api.ServiceFactoryPrx;
import org.jmock.Mock;
import org.jmock.MockObjectTestCase;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.target.HotSwappableTargetSource;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
/**
* Creates sessions and tests the various ways they can be destroyed. Initially
* (Oct. 2008) this was used to manually inspect in a profiler whether or not
* all related instances were being properly cleaned up.
*/
public class SessionDestructionTest extends MockObjectTestCase {
MockFixture fixture;
@AfterMethod(groups = "integration")
public void shutdownFixture() {
if (fixture != null) {
fixture.tearDown();
}
}
@Test(groups = "integration")
public void testOneSessionGlacierDestruction() throws Exception {
fixture = new MockFixture(this);
ServiceFactoryPrx sf = fixture.createServiceFactory();
sf.closeOnDestroy();
sf.getAdminService();
fixture.mock("sessionsMock").expects(once()).method("detach").will(
returnValue(0));
fixture.mock("sessionsMock").expects(once()).method("close").will(
returnValue(-2));
sf.destroy();
}
@Test(groups = "integration")
public void testOneSessionNotificationDestruction() throws Exception {
fixture = new MockFixture(this);
ServiceFactoryPrx sf = fixture.createServiceFactory();
sf.closeOnDestroy();
sf.getAdminService();
fixture.mock("sessionsMock").expects(once()).method("detach").will(
returnValue(0));
fixture.mock("sessionsMock").expects(once()).method("close").will(
returnValue(-2));
fixture.getSessionManager().onApplicationEvent(
new DestroySessionMessage(this, "my-session-uuid"));
}
@Test(groups = "integration")
public void testOneSessionDetachNotificationDestruction() throws Exception {
fixture = new MockFixture(this);
ServiceFactoryPrx sf = fixture.createServiceFactory();
sf.detachOnDestroy();
sf.getAdminService();
fixture.mock("sessionsMock").expects(once()).method("detach").will(
returnValue(0));
fixture.mock("sessionsMock").expects(once()).method("close").will(
returnValue(-2));
fixture.getSessionManager().onApplicationEvent(
new DestroySessionMessage(this, "my-session-uuid"));
}
@Test(groups = "integration")
public void testTwoClientsSessionGlacierDestruction() throws Exception {
fixture = new MockFixture(this);
Session s = fixture.session();
net.sf.ehcache.Cache c = fixture.cache();
ServiceFactoryPrx sf1 = fixture.createServiceFactory(s, c, "sf1");
ServiceFactoryPrx sf2 = fixture.createServiceFactory(s, c, "sf2");
sf1.closeOnDestroy();
sf2.closeOnDestroy();
sf1.getAdminService();
sf2.getAdminService();
fixture.mock("sessionsMock").expects(once()).method("detach").will(
returnValue(1));
sf1.destroy();
fixture.mock("sessionsMock").expects(once()).method("detach").will(
returnValue(0));
fixture.mock("sessionsMock").expects(once()).method("close").will(
returnValue(-2));
sf2.destroy();
}
@Test(groups = "integration")
public void testTwoClientsSessionNotificationDestruction() throws Exception {
fixture = new MockFixture(this);
Session s = fixture.session();
net.sf.ehcache.Cache c = fixture.cache();
ServiceFactoryPrx sf1 = fixture.createServiceFactory(s, c, "sf1");
ServiceFactoryPrx sf2 = fixture.createServiceFactory(s, c, "sf2");
sf1.closeOnDestroy();
sf2.closeOnDestroy();
sf1.getAdminService();
sf2.getAdminService();
fixture.getSessionManager().onApplicationEvent(
new DestroySessionMessage(this, "my-session-uuid"));
}
@Test(groups = "integration")
public void testTwoClientsSessionDetachedNotificationDestruction()
throws Exception {
fixture = new MockFixture(this);
Session s = fixture.session();
net.sf.ehcache.Cache c = fixture.cache();
ServiceFactoryPrx sf1 = fixture.createServiceFactory(s, c, "sf1");
ServiceFactoryPrx sf2 = fixture.createServiceFactory(s, c, "sf2");
sf1.detachOnDestroy();
sf2.detachOnDestroy();
sf1.getAdminService();
sf2.getAdminService();
fixture.getSessionManager().onApplicationEvent(
new DestroySessionMessage(this, "my-session-uuid"));
}
@Test(groups = "integration")
public void testSessionClosesStatefulService() throws Exception {
fixture = new MockFixture(this);
Session s = fixture.session();
ServiceFactoryPrx sf = fixture.createServiceFactory();
sf.createThumbnailStore();
//
// Here we want to set up a proxy around a real ThumbnailBean
// rather than a mock, in order to test that IceMethodInvoker
// unwraps proxies.
//
HotSwappableTargetSource swap = (HotSwappableTargetSource)
fixture.getContext().getBean("swappable-ome.api.ThumbnailStore");
final boolean called[] = new boolean[]{false};
ThumbnailBean bean = new ThumbnailBean() {
public void close() {
called[0] = true;
}
};
ProxyFactory proxy = new ProxyFactory(bean);
/* With #1106 bltiz migration destroy has been removed.
proxy.addAdvice(new MethodInterceptor(){
public Object invoke(MethodInvocation arg0) throws Throwable {
if (arg0.getMethod().getName().equals("destroy")) {
fail("Should not be called");
}
return null;
}
});
*/
swap.swap(proxy.getProxy());
fixture.getSessionManager().onApplicationEvent(
new DestroySessionMessage(this, "my-session-uuid"));
assertTrue(called[0]);
}
@Test(groups = "integration")
public void testTwoSessionsClosedConcurrently() throws Exception {
fail("NYI");
}
@Test(groups = "integration")
@SuppressWarnings( { "unchecked" })
public void testSessionTimeoutWithRealSessionCache() throws Exception {
// Manual configuration of some lower-level objects
fixture = new MockFixture(this);
SessionCache cache = new SessionCache();
cache.setApplicationContext(fixture.getContext());
cache.setCacheManager(CacheManager.getInstance());
cache.setUpdateInterval(1000L); // Every second check for chanages
SessionManagerImpl manager = new SessionManagerImpl();
manager.setApplicationContext(fixture.getContext());
manager
.setExecutor((Executor) fixture.getContext()
.getBean("executor"));
manager.setRoles(new Roles());
manager.setDefaultTimeToLive(1000L); // Only lives one second.
manager.setSessionCache(cache);
manager.setPrincipalHolder(new CurrentDetails());
// Now insert that into our context
HotSwappableTargetSource ts = (HotSwappableTargetSource) fixture
.getContext().getBean("swappableSessionManagerSource");
ts.swap(manager);
// We also want to receive the callback about session destruction
class Listener implements ApplicationListener {
List<String> killed = new ArrayList<String>();
public void onApplicationEvent(ApplicationEvent arg0) {
if (arg0 instanceof DestroySessionMessage) {
DestroySessionMessage dsm = (DestroySessionMessage) arg0;
killed.add(dsm.getSessionId());
}
}
}
Listener listener = new Listener();
((GlobalMulticaster) fixture.getContext().getBean(
"applicationEventMulticaster"))
.addApplicationListener(listener);
// Setup all the necessary expectations
Experimenter exp = new Experimenter("joe", "joe", "blow", false);
ExperimenterGroup grp = new ExperimenterGroup("cool", false);
List<Long> grps = Arrays.asList(0L, 1L, 2L);
List rv = new ArrayList();
rv.add(exp);
rv.add(grp);
rv.add(grps);
rv.add(grps);
rv.add(Arrays.asList("user", "system", "cool"));
Session s = fixture.session();
s.setTimeToLive(1000L); // Actually have to set here because of mocking.
Mock ex = fixture.mock("executorMock");
ex.expects(atLeastOnce()).method("execute").will(
onConsecutiveCalls(returnValue(new ExperimenterGroup("group", false)),
returnValue(s), returnValue(rv)));
// Now create the session and wait for it to time out.
ServiceFactoryPrx sf1 = fixture.createServiceFactory(s);
long start = System.currentTimeMillis();
ex.expects(atLeastOnce()).method("execute").will(returnValue(rv));
while (System.currentTimeMillis() < (start + 1000L)) {
Thread.sleep(500L);
cache.updateEvent(new UserGroupUpdateEvent(this));
}
assertTrue(s.getUuid(), listener.killed.contains(s.getUuid()));
}
}