diff --git a/core/src/main/java/org/keycloak/Config.java b/core/src/main/java/org/keycloak/Config.java
index d0edf4516e..111b42ddb4 100755
--- a/core/src/main/java/org/keycloak/Config.java
+++ b/core/src/main/java/org/keycloak/Config.java
@@ -75,7 +75,7 @@ public class Config {
public static class SystemPropertiesScope implements Scope {
- private String prefix;
+ protected String prefix;
public SystemPropertiesScope(String prefix) {
this.prefix = prefix;
diff --git a/testsuite/model/pom.xml b/testsuite/model/pom.xml
index 6131c66614..c5a3b4770c 100644
--- a/testsuite/model/pom.xml
+++ b/testsuite/model/pom.xml
@@ -30,7 +30,7 @@
junit
junit
- test
+ compile
org.hamcrest
@@ -111,6 +111,26 @@
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ process-test-resources
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
@@ -174,7 +194,14 @@
map+infinispan
- Infinispan,Map,ConcurrentHashMapStorage
+ Infinispan,Jpa,Map,ConcurrentHashMapStorage
+
+
+
+
+ map
+
+ Jpa,Map,ConcurrentHashMapStorage
diff --git a/testsuite/model/src/main/java/org/keycloak/testsuite/model/Config.java b/testsuite/model/src/main/java/org/keycloak/testsuite/model/Config.java
new file mode 100644
index 0000000000..a85af08f6e
--- /dev/null
+++ b/testsuite/model/src/main/java/org/keycloak/testsuite/model/Config.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2021 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 org.keycloak.Config.ConfigProvider;
+import org.keycloak.Config.Scope;
+import org.keycloak.Config.SystemPropertiesScope;
+import org.keycloak.common.util.StringPropertyReplacer;
+import org.keycloak.common.util.SystemEnvProperties;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * @author hmlnarik
+ */
+public class Config implements ConfigProvider {
+
+ private final Properties systemProperties = new SystemEnvProperties();
+
+ private final Map properties = new HashMap<>();
+
+ public class SpiConfig {
+
+ private final String prefix;
+
+ public SpiConfig(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public ProviderConfig provider(String provider) {
+ return new ProviderConfig(this, prefix + provider + ".");
+ }
+
+ public SpiConfig defaultProvider(String defaultProviderId) {
+ return config("provider", defaultProviderId);
+ }
+
+ public SpiConfig config(String key, String value) {
+ if (value == null) {
+ properties.remove(prefix + key);
+ } else {
+ properties.put(prefix + key, value);
+ }
+ return this;
+ }
+
+ public SpiConfig spi(String spiName) {
+ return new SpiConfig(spiName + ".");
+ }
+ }
+
+ public class ProviderConfig {
+
+ private final SpiConfig spiConfig;
+ private final String prefix;
+
+ public ProviderConfig(SpiConfig spiConfig, String prefix) {
+ this.spiConfig = spiConfig;
+ this.prefix = prefix;
+ }
+
+ public ProviderConfig config(String key, String value) {
+ if (value == null) {
+ properties.remove(prefix + key);
+ } else {
+ properties.put(prefix + key, value);
+ }
+ return this;
+ }
+
+ public ProviderConfig provider(String provider) {
+ return spiConfig.provider(provider);
+ }
+
+ public SpiConfig spi(String spiName) {
+ return new SpiConfig(spiName + ".");
+ }
+
+ }
+
+ private class MapConfigScope extends SystemPropertiesScope {
+
+ public MapConfigScope(String prefix) {
+ super(prefix);
+ }
+
+ @Override
+ public String get(String key, String defaultValue) {
+ String v = replaceProperties(properties.get(prefix + key));
+ if (v == null || v.isEmpty()) {
+ v = System.getProperty("keycloak." + prefix + key, defaultValue);
+ }
+ return v != null && ! v.isEmpty() ? v : null;
+ }
+
+ @Override
+ public Scope scope(String... scope) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(prefix).append(".");
+ for (String s : scope) {
+ sb.append(s);
+ sb.append(".");
+ }
+ return new MapConfigScope(sb.toString());
+ }
+ }
+
+ @Override
+ public String getProvider(String spiName) {
+ return properties.get(spiName + ".provider");
+ }
+
+ private String replaceProperties(String value) {
+ return StringPropertyReplacer.replaceProperties(value, systemProperties);
+ }
+
+ @Override
+ public Scope scope(String... scope) {
+ StringBuilder sb = new StringBuilder();
+ for (String s : scope) {
+ sb.append(s);
+ sb.append(".");
+ }
+ return new MapConfigScope(sb.toString());
+ }
+
+ public SpiConfig spi(String spiName) {
+ return new SpiConfig(spiName + ".");
+ }
+
+ @Override
+ public String toString() {
+ return properties.entrySet().stream()
+ .sorted((e1, e2) -> e1.getKey().compareTo(e2.getKey()))
+ .map(e -> e.getKey() + " = " + e.getValue())
+ .collect(Collectors.joining("\n "));
+ }
+}
diff --git a/testsuite/model/src/main/java/org/keycloak/testsuite/model/KeycloakModelParameters.java b/testsuite/model/src/main/java/org/keycloak/testsuite/model/KeycloakModelParameters.java
new file mode 100644
index 0000000000..2d90095074
--- /dev/null
+++ b/testsuite/model/src/main/java/org/keycloak/testsuite/model/KeycloakModelParameters.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2020 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 org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ *
+ * @author hmlnarik
+ */
+public class KeycloakModelParameters {
+
+ private final Set> allowedSpis;
+ private final Set> allowedFactories;
+
+ public KeycloakModelParameters(Set> allowedSpis, Set> allowedFactories) {
+ this.allowedSpis = allowedSpis;
+ this.allowedFactories = allowedFactories;
+ }
+
+ boolean isSpiAllowed(Spi s) {
+ return allowedSpis.contains(s.getClass());
+ }
+
+ boolean isFactoryAllowed(ProviderFactory factory) {
+ return allowedFactories.stream().anyMatch((c) -> c.isAssignableFrom(factory.getClass()));
+ }
+
+ /**
+ * Returns stream of parameters of the given type, or an empty stream if no parameters of the given type are supplied
+ * by this clazz.
+ * @param
+ * @param clazz
+ * @return
+ */
+ public Stream getParameters(Class clazz) {
+ return Stream.empty();
+ }
+
+ public Statement classRule(Statement base, Description description) {
+ return base;
+ }
+
+ public Statement instanceRule(Statement base, Description description) {
+ return base;
+ }
+
+}
diff --git a/testsuite/model/src/main/java/org/keycloak/testsuite/model/RequireProvider.java b/testsuite/model/src/main/java/org/keycloak/testsuite/model/RequireProvider.java
new file mode 100644
index 0000000000..d0975b3d38
--- /dev/null
+++ b/testsuite/model/src/main/java/org/keycloak/testsuite/model/RequireProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2020 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 org.keycloak.provider.Provider;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Identifies a requirement for a given provider to be present in the session factory.
+ * If the provider is not available, the test is skipped.
+ *
+ * @author hmlnarik
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Repeatable(RequireProviders.class)
+public @interface RequireProvider {
+ Class extends Provider> value() default Provider.class;
+
+}
diff --git a/testsuite/model/src/main/java/org/keycloak/testsuite/model/RequireProviders.java b/testsuite/model/src/main/java/org/keycloak/testsuite/model/RequireProviders.java
new file mode 100644
index 0000000000..335c0f6027
--- /dev/null
+++ b/testsuite/model/src/main/java/org/keycloak/testsuite/model/RequireProviders.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2020 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.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * @author hmlnarik
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface RequireProviders {
+ RequireProvider[] value();
+}
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/ClientScopeStorageTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/ClientScopeStorageTest.java
index 857924c4cf..73372fb054 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/ClientScopeStorageTest.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/ClientScopeStorageTest.java
@@ -61,6 +61,7 @@ public class ClientScopeStorageTest extends KeycloakModelTest {
ComponentModel res = realm.addComponentModel(federatedStorage);
clientScopeFederationId = res.getId();
log.infof("Added %s client scope federation provider: %s", federatedStorage.getName(), clientScopeFederationId);
+ return null;
}));
inComittedTransaction(1, (session, i) -> {
@@ -68,6 +69,7 @@ public class ClientScopeStorageTest extends KeycloakModelTest {
StorageId storageId = new StorageId(clientScopeFederationId, "scope_name");
ClientScopeModel hardcoded = session.clientScopes().getClientScopeById(realm, storageId.getId());
Assert.assertNotNull(hardcoded);
+ return null;
});
}
}
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/KeycloakModelParameters.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/KeycloakModelParameters.java
index 2d90095074..29740dfef0 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/KeycloakModelParameters.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/KeycloakModelParameters.java
@@ -18,6 +18,10 @@ package org.keycloak.testsuite.model;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
+import org.keycloak.testsuite.model.Config.SpiConfig;
+import org.keycloak.util.JsonSerialization;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.Set;
import java.util.stream.Stream;
import org.junit.runner.Description;
@@ -56,6 +60,9 @@ public class KeycloakModelParameters {
return Stream.empty();
}
+ public void updateConfig(Config cf) {
+ }
+
public Statement classRule(Statement base, Description description) {
return base;
}
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/KeycloakModelTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/KeycloakModelTest.java
index 5508abbf0a..1d16c312e8 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/KeycloakModelTest.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/KeycloakModelTest.java
@@ -30,6 +30,7 @@ import org.keycloak.models.ClientSpi;
import org.keycloak.models.GroupSpi;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmSpi;
import org.keycloak.models.RoleSpi;
import org.keycloak.models.UserSpi;
@@ -47,8 +48,11 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.hamcrest.Matchers;
@@ -92,8 +96,11 @@ public abstract class KeycloakModelTest {
st = Stream.concat(Stream.of(testClass.getAnnotationsByType(RequireProvider.class)), st);
testClass = testClass.getSuperclass();
}
- List> notFound = st.map(RequireProvider::value)
- .filter(pClass -> FACTORY.getProviderFactory(pClass) == null)
+ List> notFound = st
+ .filter(rp -> rp.only().length == 0
+ ? FACTORY.getProviderFactory(rp.value()) == null
+ : Stream.of(rp.only()).allMatch(provider -> FACTORY.getProviderFactory(rp.value(), provider) == null))
+ .map(RequireProvider::value)
.collect(Collectors.toList());
Assume.assumeThat("Some required providers not found", notFound, Matchers.empty());
@@ -119,16 +126,30 @@ public abstract class KeycloakModelTest {
st = Stream.concat(st, Stream.of(rp));
}
- for (Iterator> iterator = st.map(RequireProvider::value).iterator(); iterator.hasNext();) {
- Class extends Provider> providerClass = iterator.next();
+ for (Iterator iterator = st.iterator(); iterator.hasNext();) {
+ RequireProvider rpInner = iterator.next();
+ Class extends Provider> providerClass = rpInner.value();
+ String[] only = rpInner.only();
- if (FACTORY.getProviderFactory(providerClass) == null) {
- return new Statement() {
- @Override
- public void evaluate() throws Throwable {
- throw new AssumptionViolatedException("Provider must exist: " + providerClass);
- }
- };
+ if (only.length == 0) {
+ if (FACTORY.getProviderFactory(providerClass) == null) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ throw new AssumptionViolatedException("Provider must exist: " + providerClass);
+ }
+ };
+ }
+ } else {
+ boolean notFoundAny = Stream.of(only).allMatch(provider -> FACTORY.getProviderFactory(providerClass, provider) == null);
+ if (notFoundAny) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ throw new AssumptionViolatedException("Provider must exist: " + providerClass + " one of [" + String.join(",", only) + "]");
+ }
+ };
+ }
}
}
@@ -160,7 +181,8 @@ public abstract class KeycloakModelTest {
.build();
protected static final List MODEL_PARAMETERS;
- protected static final DefaultKeycloakSessionFactory FACTORY;
+ protected static Config CONFIG;
+ protected static DefaultKeycloakSessionFactory FACTORY;
static {
KeycloakModelParameters basicParameters = new KeycloakModelParameters(ALLOWED_SPIS, ALLOWED_FACTORIES);
@@ -170,13 +192,22 @@ public abstract class KeycloakModelTest {
.filter(s -> s != null && ! s.trim().isEmpty())
.map(cn -> { try { return Class.forName(cn.indexOf('.') >= 0 ? cn : ("org.keycloak.testsuite.model.parameters." + cn)); } catch (Exception e) { LOG.error("Cannot find " + cn); return null; }})
.filter(Objects::nonNull)
- .map(c -> { try { return c.newInstance(); } catch (Exception e) { LOG.error("Cannot instantiate " + c); return null; }} )
+ .map(c -> { try { return c.getDeclaredConstructor().newInstance(); } catch (Exception e) { LOG.error("Cannot instantiate " + c); return null; }} )
.filter(KeycloakModelParameters.class::isInstance)
.map(KeycloakModelParameters.class::cast)
)
.collect(Collectors.toList());
- FACTORY = new DefaultKeycloakSessionFactory() {
+ reinitializeKeycloakSessionFactory();
+ }
+
+ public static DefaultKeycloakSessionFactory createKeycloakSessionFactory() {
+ CONFIG = new Config();
+ MODEL_PARAMETERS.forEach(m -> m.updateConfig(CONFIG));
+ LOG.debug("Using the following configuration:\n " + CONFIG);
+ org.keycloak.Config.init(CONFIG);
+
+ DefaultKeycloakSessionFactory res = new DefaultKeycloakSessionFactory() {
@Override
protected boolean isEnabled(ProviderFactory factory, Scope scope) {
return super.isEnabled(factory, scope) && isFactoryAllowed(factory);
@@ -196,7 +227,16 @@ public abstract class KeycloakModelTest {
return MODEL_PARAMETERS.stream().anyMatch(p -> p.isFactoryAllowed(factory));
}
};
- FACTORY.init();
+ res.init();
+ return res;
+ }
+
+ public static void reinitializeKeycloakSessionFactory() {
+ DefaultKeycloakSessionFactory f = createKeycloakSessionFactory();
+ if (FACTORY != null) {
+ FACTORY.close();
+ }
+ FACTORY = f;
}
@BeforeClass
@@ -237,11 +277,20 @@ public abstract class KeycloakModelTest {
session.getTransactionManager().rollback();
}
- protected void inComittedTransaction(T parameter, BiConsumer what) {
- inComittedTransaction(parameter, what, (a,b) -> {}, (a,b) -> {});
+ protected R inComittedTransaction(T parameter, BiFunction what) {
+ return inComittedTransaction(parameter, what, null, null);
}
- protected void inComittedTransaction(T parameter, BiConsumer what, BiConsumer onCommit, BiConsumer onRollback) {
+ protected void inComittedTransaction(Consumer what) {
+ inComittedTransaction(a -> { what.accept(a); return null; });
+ }
+
+ protected R inComittedTransaction(Function what) {
+ return inComittedTransaction(1, (a,b) -> what.apply(a));
+ }
+
+ protected R inComittedTransaction(T parameter, BiFunction what, BiConsumer onCommit, BiConsumer onRollback) {
+ AtomicReference res = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(FACTORY, session -> {
session.getTransactionManager().enlistAfterCompletion(new AbstractKeycloakTransaction() {
@Override
@@ -254,7 +303,16 @@ public abstract class KeycloakModelTest {
if (onRollback != null) { onRollback.accept(session, parameter); }
}
});
- what.accept(session, parameter);
+ res.set(what.apply(session, parameter));
+ });
+ return res.get();
+ }
+
+ protected R withRealm(String realmId, BiFunction what) {
+ return inComittedTransaction(session -> {
+ final RealmModel realm = session.realms().getRealm(realmId);
+ session.getContext().setRealm(realm);
+ return what.apply(session, realm);
});
}
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/RequireProvider.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/RequireProvider.java
index d0975b3d38..5787145788 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/RequireProvider.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/RequireProvider.java
@@ -35,4 +35,10 @@ import java.lang.annotation.Target;
public @interface RequireProvider {
Class extends Provider> value() default Provider.class;
+ /**
+ * Specifies provider IDs of mandatory provider. There must be at least one provider available
+ * from those in {@code only} array to fulfil this requirement.
+ */
+ String[] only() default {};
+
}
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/UserModelTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
index f480c45703..e5bbff0dc1 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
@@ -81,7 +81,7 @@ public class UserModelTest extends KeycloakModelTest {
s.realms().removeRealm(realmId);
}
- private void addRemoveUser(KeycloakSession session, int i) {
+ private Void addRemoveUser(KeycloakSession session, int i) {
RealmModel realm = session.realms().getRealmByName("realm");
UserModel user = session.users().addUser(realm, "user-" + i);
@@ -102,6 +102,8 @@ public class UserModelTest extends KeycloakModelTest {
assertTrue(session.users().removeUser(realm, user));
assertFalse(session.users().removeUser(realm, user));
assertNull(session.users().getUserByUsername(realm, user.getUsername()));
+
+ return null;
}
@Test
@@ -125,9 +127,10 @@ public class UserModelTest extends KeycloakModelTest {
final UserModel user = session.users().addUser(realm, "user-" + i);
user.joinGroup(session.groups().getGroupById(realm, groupId));
userIds.add(user.getId());
+ return null;
}));
- inComittedTransaction(1, (session, i) -> {
+ inComittedTransaction(session -> {
final RealmModel realm = session.realms().getRealm(realmId);
final GroupModel group = session.groups().getGroupById(realm, groupId);
assertThat(session.users().getGroupMembersStream(realm, group).count(), is(100L));
@@ -140,6 +143,7 @@ public class UserModelTest extends KeycloakModelTest {
final RealmModel realm = session.realms().getRealm(realmId);
final UserModel user = session.users().getUserById(realm, userId);
log.debugf("Remove user %s: %s", userId, session.users().removeUser(realm, user));
+ return null;
}, null, (session, userId) -> remainingUserIds.add(userId) ));
userIds.clear();
@@ -147,7 +151,7 @@ public class UserModelTest extends KeycloakModelTest {
remainingUserIds.clear();
} while (! userIds.isEmpty());
- inComittedTransaction(1, (session, i) -> {
+ inComittedTransaction(session -> {
final RealmModel realm = session.realms().getRealm(realmId);
final GroupModel group = session.groups().getGroupById(realm, groupId);
assertThat(session.users().getGroupMembersStream(realm, group).collect(Collectors.toList()), Matchers.empty());
@@ -159,27 +163,24 @@ public class UserModelTest extends KeycloakModelTest {
public void testAddDirtyRemoveFederationUser() {
registerUserFederationWithRealm();
- inComittedTransaction(1, (session, i) -> {
- final RealmModel realm = session.realms().getRealm(realmId);
- final UserModel user = session.users().addUser(realm, "user-A");
- });
+ withRealm(realmId, (session, realm) -> session.users().addUser(realm, "user-A"));
// Remove user _from the federation_, simulates eg. user being removed from LDAP without Keycloak knowing
- inComittedTransaction(1, (session, i) -> {
- final RealmModel realm = session.realms().getRealm(realmId);
+ withRealm(realmId, (session, realm) -> {
final UserStorageProvider instance = getUserFederationInstance(session, realm);
log.debugf("Removing selected users from backend");
final UserModel user = session.users().getUserByUsername(realm, "user-A");
((UserRegistrationProvider) instance).removeUser(realm, user);
+ return null;
});
- inComittedTransaction(1, (session, i) -> {
- final RealmModel realm = session.realms().getRealm(realmId);
+ withRealm(realmId, (session, realm) -> {
if (session.userCache() != null) {
session.userCache().clear();
}
final UserModel user = session.users().getUserByUsername(realm, "user-A");
assertThat("User should not be found in the main store", user, Matchers.nullValue());
+ return null;
});
}
@@ -198,26 +199,27 @@ public class UserModelTest extends KeycloakModelTest {
user.joinGroup(session.groups().getGroupById(realm, groupId));
log.infof("Created user with id: %s", user.getId());
userIds.add(user.getId());
+ return null;
}));
// Remove users _from the federation_, simulates eg. user being removed from LDAP without Keycloak knowing
- inComittedTransaction(1, (session, i) -> {
- final RealmModel realm = session.realms().getRealm(realmId);
+ withRealm(realmId, (session, realm) -> {
UserStorageProvider instance = getUserFederationInstance(session, realm);
log.debugf("Removing selected users from backend");
IntStream.range(FIRST_DELETED_USER_INDEX, LAST_DELETED_USER_INDEX).forEach(j -> {
final UserModel user = session.users().getUserByUsername(realm, "user-" + j);
((UserRegistrationProvider) instance).removeUser(realm, user);
});
+ return null;
});
- IntStream.range(0, 7).parallel().forEach(index -> inComittedTransaction(index, (session, i) -> {
- final RealmModel realm = session.realms().getRealm(realmId);
+ IntStream.range(0, 7).parallel().forEach(index -> withRealm(realmId, (session, realm) -> {
final GroupModel group = session.groups().getGroupById(realm, groupId);
assertThat(session.users().getGroupMembersStream(realm, group).count(), is(100L - DELETED_USER_COUNT));
+ return null;
}));
- inComittedTransaction(1, (session, i) -> {
+ inComittedTransaction(session -> {
// If we are using cache, we need to invalidate all users because after removing users from external
// provider cache may not be cleared and it may be the case, that cache is the only place that is having
// a reference to removed users. Our importValidation method won't be called at all for removed users
@@ -227,6 +229,7 @@ public class UserModelTest extends KeycloakModelTest {
if (session.userCache() != null) {
session.userCache().clear();
}
+ return null;
});
// Now delete the users, and count those that were not found to be deleted. This should be equal to the number
@@ -245,6 +248,7 @@ public class UserModelTest extends KeycloakModelTest {
log.debugf("Failed deleting user: %s", userId);
notFoundUsers.incrementAndGet();
}
+ return null;
}, null, (session, userId) -> {
log.debugf("Could not delete user %s", userId);
remainingUserIds.add(userId);
@@ -257,22 +261,22 @@ public class UserModelTest extends KeycloakModelTest {
assertThat(notFoundUsers.get(), is(DELETED_USER_COUNT));
- inComittedTransaction(1, (session, i) -> {
- final RealmModel realm = session.realms().getRealm(realmId);
+ withRealm(realmId, (session, realm) -> {
final GroupModel group = session.groups().getGroupById(realm, groupId);
assertThat(session.users().getGroupMembersStream(realm, group).collect(Collectors.toList()), Matchers.empty());
+ return null;
});
}
private void registerUserFederationWithRealm() {
- getParameters(UserStorageProviderModel.class).forEach(fs -> inComittedTransaction(fs, (session, federatedStorage) -> {
+ getParameters(UserStorageProviderModel.class).forEach(fs -> inComittedTransaction(session -> {
assumeThat("Cannot handle more than 1 user federation provider", userFederationId, Matchers.nullValue());
RealmModel realm = session.realms().getRealm(realmId);
- federatedStorage.setParentId(realmId);
- federatedStorage.setImportEnabled(true);
- ComponentModel res = realm.addComponentModel(federatedStorage);
+ fs.setParentId(realmId);
+ fs.setImportEnabled(true);
+ ComponentModel res = realm.addComponentModel(fs);
userFederationId = res.getId();
- log.infof("Added %s user federation provider: %s", federatedStorage.getName(), userFederationId);
+ log.infof("Added %s user federation provider: %s", fs.getName(), userFederationId);
}));
}
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/ConcurrentHashMapStorage.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/ConcurrentHashMapStorage.java
index 559233c5c2..864c1771f3 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/ConcurrentHashMapStorage.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/ConcurrentHashMapStorage.java
@@ -16,15 +16,12 @@
*/
package org.keycloak.testsuite.model.parameters;
-import org.keycloak.testsuite.model.KeycloakModelParameters;
-import org.keycloak.models.map.client.MapClientProviderFactory;
-import org.keycloak.models.map.group.MapGroupProviderFactory;
-import org.keycloak.models.map.role.MapRoleProviderFactory;
-import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProvider;
-import org.keycloak.models.map.storage.MapStorageProvider;
import org.keycloak.models.map.storage.MapStorageSpi;
+import org.keycloak.testsuite.model.KeycloakModelParameters;
+import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProvider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
+import org.keycloak.testsuite.model.Config;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
@@ -41,8 +38,12 @@ public class ConcurrentHashMapStorage extends KeycloakModelParameters {
.add(ConcurrentHashMapStorageProvider.class)
.build();
- static {
- System.setProperty("keycloak.mapStorage.concurrenthashmap.dir", System.getProperty("keycloak.mapStorage.concurrenthashmap.dir", "${project.build.directory:target}"));
+ @Override
+ public void updateConfig(Config cf) {
+ cf.spi(MapStorageSpi.NAME)
+ .defaultProvider(ConcurrentHashMapStorageProvider.PROVIDER_ID)
+ .provider(ConcurrentHashMapStorageProvider.PROVIDER_ID)
+ .config("dir", "${project.build.directory:target}");
}
public ConcurrentHashMapStorage() {
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Infinispan.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Infinispan.java
index ecc8117413..0db5599c09 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Infinispan.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Infinispan.java
@@ -26,6 +26,7 @@ import org.keycloak.models.cache.infinispan.InfinispanCacheRealmProviderFactory;
import org.keycloak.models.cache.infinispan.InfinispanUserCacheProviderFactory;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
+import org.keycloak.testsuite.model.Config;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
@@ -49,8 +50,11 @@ public class Infinispan extends KeycloakModelParameters {
.add(InfinispanUserCacheProviderFactory.class)
.build();
- static {
- System.setProperty("keycloak.connectionsInfinispan.default.embedded", System.getProperty("keycloak.connectionsInfinispan.default.embedded", "true"));
+ @Override
+ public void updateConfig(Config cf) {
+ cf.spi("connectionsInfinispan")
+ .provider("default")
+ .config("embedded", "true");
}
public Infinispan() {
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Jpa.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Jpa.java
index e788d70320..733db26e3f 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Jpa.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Jpa.java
@@ -35,6 +35,7 @@ import org.keycloak.models.jpa.JpaRoleProviderFactory;
import org.keycloak.models.jpa.JpaUserProviderFactory;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
+import org.keycloak.testsuite.model.Config;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
@@ -73,4 +74,14 @@ public class Jpa extends KeycloakModelParameters {
super(ALLOWED_SPIS, ALLOWED_FACTORIES);
}
+
+ @Override
+ public void updateConfig(Config cf) {
+ cf.spi("client").defaultProvider("jpa")
+ .spi("clientScope").defaultProvider("jpa")
+ .spi("group").defaultProvider("jpa")
+ .spi("role").defaultProvider("jpa")
+ .spi("user").defaultProvider("jpa")
+ ;
+ }
}
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Map.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Map.java
index 9c4707a4ca..43debcd43d 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Map.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Map.java
@@ -18,12 +18,15 @@ package org.keycloak.testsuite.model.parameters;
import org.keycloak.testsuite.model.KeycloakModelParameters;
import org.keycloak.models.map.client.MapClientProviderFactory;
+import org.keycloak.models.map.clientscope.MapClientScopeProviderFactory;
import org.keycloak.models.map.group.MapGroupProviderFactory;
import org.keycloak.models.map.role.MapRoleProviderFactory;
import org.keycloak.models.map.storage.MapStorageProvider;
import org.keycloak.models.map.storage.MapStorageSpi;
+import org.keycloak.models.map.user.MapUserProviderFactory;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
+import org.keycloak.testsuite.model.Config;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
@@ -40,12 +43,24 @@ public class Map extends KeycloakModelParameters {
static final Set> ALLOWED_FACTORIES = ImmutableSet.>builder()
.add(MapClientProviderFactory.class)
+ .add(MapClientScopeProviderFactory.class)
.add(MapGroupProviderFactory.class)
.add(MapRoleProviderFactory.class)
+ .add(MapUserProviderFactory.class)
.add(MapStorageProvider.class)
.build();
public Map() {
super(ALLOWED_SPIS, ALLOWED_FACTORIES);
}
+
+ @Override
+ public void updateConfig(Config cf) {
+ cf.spi("client").defaultProvider(MapClientProviderFactory.PROVIDER_ID)
+ .spi("clientScope").defaultProvider(MapClientScopeProviderFactory.PROVIDER_ID)
+ .spi("group").defaultProvider(MapGroupProviderFactory.PROVIDER_ID)
+ .spi("role").defaultProvider(MapRoleProviderFactory.PROVIDER_ID)
+ .spi("user").defaultProvider(MapUserProviderFactory.PROVIDER_ID)
+ ;
+ }
}
diff --git a/testsuite/model/src/test/resources/log4j.properties b/testsuite/model/src/test/resources/log4j.properties
index 9107af6188..41ffffd503 100644
--- a/testsuite/model/src/test/resources/log4j.properties
+++ b/testsuite/model/src/test/resources/log4j.properties
@@ -32,8 +32,8 @@ log4j.logger.org.keycloak.testsuite=${keycloak.testsuite.logging.level}
# log4j.logger.org.hibernate=debug
# Enable to view loaded SPI and Providers
-# log4j.logger.org.keycloak.services.DefaultKeycloakSessionFactory=debug
-# log4j.logger.org.keycloak.provider.ProviderManager=debug
+ log4j.logger.org.keycloak.services.DefaultKeycloakSessionFactory=debug
+ log4j.logger.org.keycloak.provider.ProviderManager=debug
# log4j.logger.org.keycloak.provider.FileSystemProviderLoaderFactory=debug
# Liquibase updates logged with "info" by default. Logging level can be changed by system property "keycloak.liquibase.logging.level"
diff --git a/testsuite/model/test-all-profiles.sh b/testsuite/model/test-all-profiles.sh
index f606a5ecf5..fd620efcc9 100755
--- a/testsuite/model/test-all-profiles.sh
+++ b/testsuite/model/test-all-profiles.sh
@@ -1,6 +1,7 @@
#!/bin/bash
cd "$(dirname $0)"
+mvn -version
EXIT_CODE=0
mvn clean