Disable unstable scenario for testOfflineSessionLazyLoadingPropagationBetweenNodes

This only fails when CrossDC and preloadOfflineSessionsFromDatabase are enabled after the upgrade to Infinispan 13.x

Relates to #14020
This commit is contained in:
Alexander Schwartz 2022-08-26 10:46:51 +02:00 committed by Hynek Mlnařík
parent bf13827282
commit a364a05cfa

View file

@ -17,8 +17,10 @@
package org.keycloak.testsuite.model.session; package org.keycloak.testsuite.model.session;
import org.hamcrest.Matchers;
import org.infinispan.Cache; import org.infinispan.Cache;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test; import org.junit.Test;
import org.keycloak.common.util.Time; import org.keycloak.common.util.Time;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider; import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
@ -40,11 +42,13 @@ import org.keycloak.services.managers.UserSessionManager;
import org.keycloak.testsuite.model.infinispan.InfinispanTestUtil; import org.keycloak.testsuite.model.infinispan.InfinispanTestUtil;
import org.keycloak.timer.TimerProvider; import org.keycloak.timer.TimerProvider;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -308,8 +312,9 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
@Test @Test
public void testOfflineSessionLazyLoading() throws InterruptedException { public void testOfflineSessionLazyLoading() throws InterruptedException {
AtomicReference<List<UserSessionModel>> offlineUserSessions = new AtomicReference<>(new LinkedList<>()); // as one thread fills this list and the others read it, ensure that it is synchronized to avoid side effects
AtomicReference<List<AuthenticatedClientSessionModel>> offlineClientSessions = new AtomicReference<>(new LinkedList<>()); List<UserSessionModel> offlineUserSessions = Collections.synchronizedList(new LinkedList<>());
List<AuthenticatedClientSessionModel> offlineClientSessions = Collections.synchronizedList(new LinkedList<>());
createOfflineSessions("user1", 10, offlineUserSessions, offlineClientSessions); createOfflineSessions("user1", 10, offlineUserSessions, offlineClientSessions);
closeKeycloakSessionFactory(); closeKeycloakSessionFactory();
@ -326,8 +331,16 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
@Test @Test
public void testOfflineSessionLazyLoadingPropagationBetweenNodes() throws InterruptedException { public void testOfflineSessionLazyLoadingPropagationBetweenNodes() throws InterruptedException {
AtomicReference<List<UserSessionModel>> offlineUserSessions = new AtomicReference<>(new LinkedList<>()); // This test is only unstable after setting "keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase" to "true" and
AtomicReference<List<AuthenticatedClientSessionModel>> offlineClientSessions = new AtomicReference<>(new LinkedList<>()); // CrossDC is enabled.
// This is tracked in https://github.com/keycloak/keycloak/issues/14020 to be resolved.
Assume.assumeFalse(Objects.equals(CONFIG.scope("userSessions.infinispan").get("preloadOfflineSessionsFromDatabase"), "true") &&
Objects.equals(CONFIG.scope("connectionsInfinispan.default").get("remoteStoreEnabled"), "true"));
// as one thread fills this list and the others read it, ensure that it is synchronized to avoid side effects
List<UserSessionModel> offlineUserSessions = Collections.synchronizedList(new LinkedList<>());
List<AuthenticatedClientSessionModel> offlineClientSessions = Collections.synchronizedList(new LinkedList<>());
AtomicInteger index = new AtomicInteger(); AtomicInteger index = new AtomicInteger();
CountDownLatch afterFirstNodeLatch = new CountDownLatch(1); CountDownLatch afterFirstNodeLatch = new CountDownLatch(1);
@ -375,7 +388,7 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
return offlineSessions; return offlineSessions;
} }
private void createOfflineSessions(String username, int sessionsPerUser, AtomicReference<List<UserSessionModel>> offlineUserSessions, AtomicReference<List<AuthenticatedClientSessionModel>> offlineClientSessions) { private void createOfflineSessions(String username, int sessionsPerUser, List<UserSessionModel> offlineUserSessions, List<AuthenticatedClientSessionModel> offlineClientSessions) {
withRealm(realmId, (session, realm) -> { withRealm(realmId, (session, realm) -> {
final UserModel user = session.users().getUserByUsername(realm, username); final UserModel user = session.users().getUserByUsername(realm, username);
ClientModel testAppClient = realm.getClientByClientId("test-app"); ClientModel testAppClient = realm.getClientByClientId("test-app");
@ -387,19 +400,34 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
AuthenticatedClientSessionModel testAppClientSession = session.sessions().createClientSession(realm, testAppClient, userSession); AuthenticatedClientSessionModel testAppClientSession = session.sessions().createClientSession(realm, testAppClient, userSession);
AuthenticatedClientSessionModel thirdPartyClientSession = session.sessions().createClientSession(realm, thirdPartyClient, userSession); AuthenticatedClientSessionModel thirdPartyClientSession = session.sessions().createClientSession(realm, thirdPartyClient, userSession);
UserSessionModel offlineUserSession = session.sessions().createOfflineUserSession(userSession); UserSessionModel offlineUserSession = session.sessions().createOfflineUserSession(userSession);
offlineUserSessions.get().add(offlineUserSession); offlineUserSessions.add(offlineUserSession);
offlineClientSessions.get().add(session.sessions().createOfflineClientSession(testAppClientSession, offlineUserSession)); offlineClientSessions.add(session.sessions().createOfflineClientSession(testAppClientSession, offlineUserSession));
offlineClientSessions.get().add(session.sessions().createOfflineClientSession(thirdPartyClientSession, offlineUserSession)); offlineClientSessions.add(session.sessions().createOfflineClientSession(thirdPartyClientSession, offlineUserSession));
}); });
return null; return null;
}); });
} }
private boolean assertOfflineSession(AtomicReference<List<UserSessionModel>> expectedUserSessions, List<UserSessionModel> actualUserSessions) { private boolean assertOfflineSession(List<UserSessionModel> expectedUserSessions, List<UserSessionModel> actualUserSessions) {
boolean result = expectedUserSessions.get().size() == actualUserSessions.size(); boolean result = true;
for (UserSessionModel userSession: expectedUserSessions.get()) { // User sessions are compared by their ID given the
result = result && actualUserSessions.contains(userSession); for (UserSessionModel userSession: expectedUserSessions) {
if (!actualUserSessions.contains(userSession)) {
log.warnf("missing session %s", userSession);
result = false;
}
}
for (UserSessionModel userSession: actualUserSessions) {
if (!expectedUserSessions.contains(userSession)) {
log.warnf("seeing an additional session %s by user %s", userSession.getId(), userSession.getUser().getId());
result = false;
}
}
if (!result) {
log.warnf("all expected sessions: %s, all actual sessions: %s",
expectedUserSessions.stream().map(UserSessionModel::getId).collect(Collectors.toList()),
actualUserSessions.stream().map(UserSessionModel::getId).collect(Collectors.toList()));
} }
return result; return result;
} }