package com.fanruan.api.session; import com.fanruan.api.Prepare; import com.fr.general.web.ParameterConstants; import com.fr.invoke.Reflect; import com.fr.stable.StringUtils; import com.fr.stable.web.SessionProvider; import com.fr.stable.web.SessionSource; import com.fr.stable.web.Weblet; import com.fr.web.core.RemoteAddressManager; import com.fr.web.core.SessionPoolManager; import com.fr.web.session.SessionIDInfo; import com.fr.web.utils.WebUtils; import org.easymock.EasyMock; import org.easymock.IAnswer; import org.easymock.IMocksControl; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.easymock.PowerMock; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** * @author richie * @version 10.0 * Created by richie on 2019-08-09 */ @RunWith(PowerMockRunner.class) @PrepareForTest({SessionPoolManager.class, WebUtils.class}) @SuppressStaticInitializationFor({"com.fr.web.core.SessionPoolManager"}) public class SessionKitTest extends Prepare { private static final long MIN_ACCESS_INTERVAL = 900; private int taskCount = 0; private Map sessions = new HashMap(); @Test public void testGenerateSession() throws Exception { final SessionIDInfo sessionInfo = new MockSession("session"); final Map params = new HashMap(); PowerMock.mockStatic(SessionPoolManager.class); PowerMock.mockStatic(WebUtils.class); IMocksControl control = EasyMock.createControl(); final HttpServletRequest request = control.createMock(HttpServletRequest.class); EasyMock.expect(WebUtils.getIpAddr(request)).andReturn("127.0.0.1").anyTimes(); EasyMock.expect(WebUtils.getHTTPRequestParameter(request, ParameterConstants.OP)).andReturn("view").anyTimes(); EasyMock.expect(WebUtils.parameters4SessionIDInforContainMPCache(request)).andReturn(params).anyTimes(); final Weblet weblet = control.createMock(Weblet.class); EasyMock.expect(weblet.isSessionOccupy()).andReturn(false).anyTimes(); EasyMock.expect(weblet.createSessionIDInfor(request, "127.0.0.1", params)).andReturn(sessionInfo).anyTimes(); EasyMock.expect(addSessionIDInfo(sessionInfo)).andReturn(sessionInfo.getSessionID()).anyTimes(); EasyMock.expect(SessionPoolManager.generateSessionID(request, null, weblet)).andAnswer(new IAnswer() { @Override public String answer() throws Throwable { SessionProvider sessionIDInfor = weblet.createSessionIDInfor(request, "127.0.0.1", params); String sessionID = addSessionIDInfo(sessionIDInfor); if (weblet.isSessionOccupy()) { assert sessionID != null; RemoteAddressManager.add("127.0.0.1", sessionID); } return sessionID; } }).anyTimes(); control.replay(); PowerMock.replayAll(); sessionInfo.setSource(SessionSource.SINGLE); SessionPoolManager.generateSessionID(request, null, weblet); Assert.assertSame(sessionInfo.getSource(), SessionSource.SINGLE); sessionInfo.setSource(SessionSource.INTEGRATION); SessionPoolManager.generateSessionID(request, null, weblet); Assert.assertSame(sessionInfo.getSource(), SessionSource.INTEGRATION); } @Test public void testAddDelayTask() { String sessionID = "test"; sessions.put("test", new MockSession("test")); for (int i = 0; i < 100; i++) { accessSession(sessionID); } Assert.assertEquals(1, this.taskCount); for (int i = 0; i < 2; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { //do nothing } accessSession(sessionID); } Assert.assertEquals(3, this.taskCount); } private void accessSession(String sessionId) { if (StringUtils.isBlank(sessionId)) { return; } SessionProvider sessionIDInfor = sessions.get(sessionId); if (sessionIDInfor != null) { long accessInterval = System.currentTimeMillis() - sessionIDInfor.getLastAccessTime(); sessionIDInfor.updateTime(); if (accessInterval > MIN_ACCESS_INTERVAL) { taskCount++; } } } @Test public void testGetAllSession() { Whitebox.setInternalState( SessionPoolManager.class, "sessionIDMap", new ConcurrentHashMap() ); Whitebox.setInternalState(SessionPoolManager.class, "sessionToDelete", new HashSet()); Map sessionIDMap = Reflect.on(SessionPoolManager.class).get("sessionIDMap"); String sessionID1 = "Test1"; sessionIDMap.put(sessionID1, new MockSession(sessionID1)); sessionIDMap.put("Test2", new MockSession("Test2")); closeSession(sessionID1); List list = SessionPoolManager.getAllSession(SessionProvider.class); assertEquals(1, list.size()); assertEquals("Test2", list.get(0).getSessionID()); assertNotNull(SessionKit.getSession("Test2")); } @Test public void testHasSessionID() { Whitebox.setInternalState( SessionPoolManager.class, "sessionIDMap", new ConcurrentHashMap() ); Whitebox.setInternalState(SessionPoolManager.class, "sessionToDelete", new HashSet()); Map sessionIDMap = Reflect.on(SessionPoolManager.class).get("sessionIDMap"); String sessionID1 = "Test1"; sessionIDMap.put(sessionID1, new MockSession(sessionID1)); sessionIDMap.put("Test2", new MockSession("Test2")); closeSession(sessionID1); assertFalse(SessionPoolManager.hasSessionID(sessionID1)); assertTrue(SessionPoolManager.hasSessionID("Test2")); } private void closeSession(final String sessionID) { final Set sessionToDelete = Reflect.on(SessionPoolManager.class).get("sessionToDelete"); sessionToDelete.add(sessionID); ExecutorService closeSessionPool = Executors.newFixedThreadPool(1); closeSessionPool.submit(new Runnable() { @Override public void run() { try { //模拟删除session对象的过程 Thread.sleep(1000); } catch (InterruptedException e) { //do nothing } synchronized (SessionPoolManager.class) { sessionToDelete.remove(sessionID); } } }); } private String addSessionIDInfo(SessionProvider sessionIDInfo) { return Reflect.on(SessionPoolManager.class).call("addSessionIDInfor", sessionIDInfo).get(); } }