/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.shiro.session.mgt;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.SessionListenerAdapter;
import org.apache.shiro.session.UnknownSessionException;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.*;
/**
* Unit tests for the {@link org.apache.shiro.session.mgt.AbstractValidatingSessionManager} class.
*/
public class AbstractValidatingSessionManagerTest {
/**
* Tests that both SessionListeners are called and that invalid sessions are deleted by default.
* Verifies <a href="https://issues.apache.org/jira/browse/SHIRO-199">SHIRO-199</a>.
*/
@Test
public void testValidateSessions() {
final SimpleSession validSession = new SimpleSession();
validSession.setId(1);
final SimpleSession invalidSession = new SimpleSession();
//set to a time in the past:
Calendar cal = Calendar.getInstance();
Long expiredTimeout = AbstractSessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT + 1;
cal.add(Calendar.MILLISECOND, -(expiredTimeout.intValue()) );
Date past = cal.getTime();
invalidSession.setStartTimestamp(past);
invalidSession.setLastAccessTime(past);
invalidSession.setId(2);
final AtomicInteger expirationCount = new AtomicInteger();
SessionListener sessionListener = new SessionListenerAdapter() {
@Override
public void onExpiration(Session session) {
expirationCount.incrementAndGet();
}
};
AbstractValidatingSessionManager sessionManager = new AbstractValidatingSessionManager() {
@Override
protected Session retrieveSession(SessionKey key) throws UnknownSessionException {
throw new UnsupportedOperationException("Should not be called in this test.");
}
@Override
protected Session doCreateSession(SessionContext initData) throws AuthorizationException {
throw new UnsupportedOperationException("Should not be called in this test.");
}
@Override
protected Collection<Session> getActiveSessions() {
Collection<Session> sessions = new ArrayList<Session>(2);
sessions.add(validSession);
sessions.add(invalidSession);
return sessions;
}
};
sessionManager.setSessionListeners(Arrays.asList(sessionListener));
sessionManager.validateSessions();
assertEquals(1, expirationCount.intValue());
}
/**
* Tests that no memory leak exists on invalid sessions: expired or stopped
* Verifies <a href="https://issues.apache.org/jira/browse/SHIRO-399">SHIRO-399</a>.
*/
@Test
public void testNoMemoryLeakOnInvalidSessions() throws Exception {
SessionListener sessionListener = new SessionListener() {
public void onStart(Session session) {
session.setAttribute("I love", "Romania");
}
public void onStop(Session session) {
tryToCleanSession(session);
}
public void onExpiration(Session session) {
tryToCleanSession(session);
}
private void tryToCleanSession(Session session) {
Collection<Object> keys = session.getAttributeKeys();
for (Object key : keys) {
session.removeAttribute(key);
}
}
};
DefaultSessionManager sessionManager = new DefaultSessionManager();
sessionManager.setSessionListeners(Arrays.asList(sessionListener));
Session session = sessionManager.start(null);
assertEquals(1, sessionManager.getActiveSessions().size());
session.setTimeout(0L);
//last access timestamp needs to be older than the current timestamp when validating, so ensure a delay:
Thread.sleep(1);
sessionManager.validateSessions();
assertEquals(0, sessionManager.getActiveSessions().size());
}
}