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;
import org.hamcrest.Matchers;
import org.infinispan.Cache;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
import org.keycloak.common.util.Time;
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.timer.TimerProvider;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
@ -308,8 +312,9 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
@Test
public void testOfflineSessionLazyLoading() throws InterruptedException {
AtomicReference<List<UserSessionModel>> offlineUserSessions = new AtomicReference<>(new LinkedList<>());
AtomicReference<List<AuthenticatedClientSessionModel>> offlineClientSessions = new AtomicReference<>(new LinkedList<>());
// 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<>());
createOfflineSessions("user1", 10, offlineUserSessions, offlineClientSessions);
closeKeycloakSessionFactory();
@ -326,8 +331,16 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
@Test
public void testOfflineSessionLazyLoadingPropagationBetweenNodes() throws InterruptedException {
AtomicReference<List<UserSessionModel>> offlineUserSessions = new AtomicReference<>(new LinkedList<>());
AtomicReference<List<AuthenticatedClientSessionModel>> offlineClientSessions = new AtomicReference<>(new LinkedList<>());
// This test is only unstable after setting "keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase" to "true" and
// 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();
CountDownLatch afterFirstNodeLatch = new CountDownLatch(1);
@ -353,7 +366,7 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
withRealm(realmId, (session, realm) -> {
final UserModel user = session.users().getUserByUsername(realm, "user1");
// it might take a moment to propagate, therefore loop
while (! assertOfflineSession(offlineUserSessions, session.sessions().getOfflineUserSessionsStream(realm, user).collect(Collectors.toList()))) {
while (!assertOfflineSession(offlineUserSessions, session.sessions().getOfflineUserSessionsStream(realm, user).collect(Collectors.toList()))) {
sleep(1000);
}
return null;
@ -375,7 +388,7 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
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) -> {
final UserModel user = session.users().getUserByUsername(realm, username);
ClientModel testAppClient = realm.getClientByClientId("test-app");
@ -387,19 +400,34 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
AuthenticatedClientSessionModel testAppClientSession = session.sessions().createClientSession(realm, testAppClient, userSession);
AuthenticatedClientSessionModel thirdPartyClientSession = session.sessions().createClientSession(realm, thirdPartyClient, userSession);
UserSessionModel offlineUserSession = session.sessions().createOfflineUserSession(userSession);
offlineUserSessions.get().add(offlineUserSession);
offlineClientSessions.get().add(session.sessions().createOfflineClientSession(testAppClientSession, offlineUserSession));
offlineClientSessions.get().add(session.sessions().createOfflineClientSession(thirdPartyClientSession, offlineUserSession));
offlineUserSessions.add(offlineUserSession);
offlineClientSessions.add(session.sessions().createOfflineClientSession(testAppClientSession, offlineUserSession));
offlineClientSessions.add(session.sessions().createOfflineClientSession(thirdPartyClientSession, offlineUserSession));
});
return null;
});
}
private boolean assertOfflineSession(AtomicReference<List<UserSessionModel>> expectedUserSessions, List<UserSessionModel> actualUserSessions) {
boolean result = expectedUserSessions.get().size() == actualUserSessions.size();
for (UserSessionModel userSession: expectedUserSessions.get()) {
result = result && actualUserSessions.contains(userSession);
private boolean assertOfflineSession(List<UserSessionModel> expectedUserSessions, List<UserSessionModel> actualUserSessions) {
boolean result = true;
// User sessions are compared by their ID given the
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;
}