/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* 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 org.keycloak.testsuite.model;
import java.util.List;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
import org.keycloak.common.util.Time;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.testsuite.KeycloakServer;
import org.keycloak.testsuite.rule.KeycloakRule;
/**
* Run test with shared MySQL DB and in cluster:
*
* -Dkeycloak.connectionsJpa.url=jdbc:mysql://localhost/keycloak -Dkeycloak.connectionsJpa.driver=com.mysql.jdbc.Driver -Dkeycloak.connectionsJpa.user=keycloak
* -Dkeycloak.connectionsJpa.password=keycloak -Dkeycloak.connectionsInfinispan.clustered=true
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@Ignore
public class ClusterSessionCleanerTest {
protected static final Logger logger = Logger.getLogger(ClusterSessionCleanerTest.class);
private static final String REALM_NAME = "test";
@ClassRule
public static KeycloakRule server1 = new KeycloakRule();
@ClassRule
public static KeycloakRule server2 = new KeycloakRule() {
@Override
protected void configureServer(KeycloakServer server) {
server.getConfig().setPort(8082);
}
@Override
protected void importRealm() {
}
@Override
protected void removeTestRealms() {
}
};
@Test
public void testClusterPeriodicSessionCleanups() throws Exception {
// Add some userSessions on server1
KeycloakSession session1 = server1.startSession();
RealmModel realm1 = session1.realms().getRealmByName(REALM_NAME);
UserModel user1 = session1.users().getUserByUsername("test-user@localhost", realm1);
for (int i=0 ; i<15 ; i++) {
session1.sessions().createUserSession("123", realm1, user1, user1.getUsername(), "127.0.0.1", "form", true, null, null);
}
session1 = commit(server1, session1);
// Add some userSessions on server2
KeycloakSession session2 = server2.startSession();
RealmModel realm2 = session2.realms().getRealmByName(REALM_NAME);
UserModel user2 = session2.users().getUserByUsername("test-user@localhost", realm2);
// Check we are really in cluster (same user ids)
Assert.assertEquals(user2.getId(), user1.getId());
for (int i=0 ; i<15 ; i++) {
session2.sessions().createUserSession("456", realm2, user2, user2.getUsername(), "127.0.0.1", "form", true, null, null);
}
session2 = commit(server2, session2);
// Assert sessions on both nodes
List<UserSessionModel> sessions1 = getSessions(session1);
List<UserSessionModel> sessions2 = getSessions(session2);
Assert.assertEquals(30, sessions1.size());
Assert.assertEquals(30, sessions2.size());
logger.info("Before offset: sessions1 : " + sessions1.size());
logger.info("Before offset: sessions2 : " + sessions2.size());
// set Time offset and run periodic cleaner on server1
Time.setOffset(999999);
realm1 = session1.realms().getRealmByName(REALM_NAME);
session1.sessions().removeExpired(realm1);
session1 = commit(server1, session1);
// Ensure some sessions still there
sessions1 = getSessions(session1);
sessions2 = getSessions(session2);
logger.info("After server1 periodic clean: sessions1 : " + sessions1.size());
logger.info("After server1 periodic clean: sessions2 : " + sessions2.size());
// Run periodic cleaner on server2
realm2 = session2.realms().getRealmByName(REALM_NAME);
session2.sessions().removeExpired(realm2);
session2 = commit(server1, session2);
// Ensure there are no sessions on server1 or server2
sessions1 = getSessions(session1);
sessions2 = getSessions(session2);
Assert.assertTrue(sessions1.isEmpty());
Assert.assertTrue(sessions2.isEmpty());
logger.info("After both periodic cleans: sessions1 : " + sessions1.size());
logger.info("After both periodic cleans: sessions2 : " + sessions2.size());
}
private List<UserSessionModel> getSessions(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName(REALM_NAME);
UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
return session.sessions().getUserSessions(realm, user);
}
private KeycloakSession commit(KeycloakRule rule, KeycloakSession session) throws Exception {
session.getTransactionManager().commit();
session.close();
return rule.startSession();
}
}