diff --git a/src/test/java/com/fanruan/api/session/MockSession.java b/src/test/java/com/fanruan/api/session/MockSession.java new file mode 100644 index 0000000..0568c87 --- /dev/null +++ b/src/test/java/com/fanruan/api/session/MockSession.java @@ -0,0 +1,47 @@ +package com.fanruan.api.session; + +import com.fr.stable.script.CalculatorProvider; +import com.fr.stable.web.WebContextProvider; +import com.fr.web.session.SessionIDInfo; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-08-30 + */ +class MockSession extends SessionIDInfo { + + MockSession(String sessionID) { + this.sessionID = sessionID; + } + + @Override + public String getWebTitle() { + return null; + } + + @Override + public String getRelativePath() { + return null; + } + + @Override + public WebContextProvider getWebContext() { + return null; + } + + @Override + public Object resolveVariable(Object var, CalculatorProvider cal) { + return null; + } + + @Override + public Object getParameterValue(String parameterName) { + return null; + } + + @Override + public void release() { + + } +} diff --git a/src/test/java/com/fanruan/api/session/SessionKitTest.java b/src/test/java/com/fanruan/api/session/SessionKitTest.java index 3e486cb..275d52d 100644 --- a/src/test/java/com/fanruan/api/session/SessionKitTest.java +++ b/src/test/java/com/fanruan/api/session/SessionKitTest.java @@ -1,18 +1,186 @@ 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 getSession() throws Exception { - Assert.assertNull(SessionKit.getSession("abc")); + 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(); } } \ No newline at end of file