keycloak-memoizeit

Support MongoDB in unit tests. Added parameterized test, so

9/13/2013 9:50:24 AM

Details

pom.xml 5(+5 -0)

diff --git a/pom.xml b/pom.xml
index 99a90cd..c2a58bc 100755
--- a/pom.xml
+++ b/pom.xml
@@ -254,6 +254,11 @@
                 <artifactId>mongo-java-driver</artifactId>
                 <version>2.11.2</version>
             </dependency>
+            <dependency>
+                <groupId>de.flapdoodle.embed</groupId>
+                <artifactId>de.flapdoodle.embed.mongo</artifactId>
+                <version>1.27</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 

services/pom.xml 5(+5 -0)

diff --git a/services/pom.xml b/services/pom.xml
index 7c38f45..8696a5d 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -153,6 +153,11 @@
             <artifactId>mongo-java-driver</artifactId>
         </dependency>
         <dependency>
+            <groupId>de.flapdoodle.embed</groupId>
+            <artifactId>de.flapdoodle.embed.mongo</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/impl/MongoDBImpl.java b/services/src/main/java/org/keycloak/services/models/nosql/impl/MongoDBImpl.java
index 6862a0c..44a340a 100644
--- a/services/src/main/java/org/keycloak/services/models/nosql/impl/MongoDBImpl.java
+++ b/services/src/main/java/org/keycloak/services/models/nosql/impl/MongoDBImpl.java
@@ -48,7 +48,7 @@ public class MongoDBImpl implements NoSQL {
             new ConcurrentHashMap<Class<? extends NoSQLObject>, ObjectInfo>();
 
 
-    public MongoDBImpl(DB database, boolean removeAllObjectsAtStartup, Class<? extends NoSQLObject>[] managedDataTypes) {
+    public MongoDBImpl(DB database, boolean dropDatabaseOnStartup, Class<? extends NoSQLObject>[] managedDataTypes) {
         this.database = database;
 
         typeConverter = new TypeConverter();
@@ -70,20 +70,9 @@ public class MongoDBImpl implements NoSQL {
             typeConverter.addDBObjectConverter(new BasicDBObjectConverter(this, typeConverter, type));
         }
 
-        if (removeAllObjectsAtStartup) {
-            for (Class<? extends NoSQLObject> type : managedDataTypes) {
-                ObjectInfo objectInfo = getObjectInfo(type);
-                String collectionName = objectInfo.getDbCollectionName();
-                if (collectionName != null) {
-                    logger.debug("Dropping collection " + collectionName);
-
-                    DBCollection dbCollection = this.database.getCollection(collectionName);
-                    dbCollection.drop();
-                }  else {
-                    logger.debug("Skip removing objects of type " + type + " as it doesn't have it's own collection");
-                }
-            }
-            logger.info("All objects successfully removed from MongoDB");
+        if (dropDatabaseOnStartup) {
+            this.database.dropDatabase();
+            logger.info("Database " + this.database.getName() + " dropped in MongoDB");
         }
     }
 
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/keycloak/adapters/MongoDBSessionFactory.java b/services/src/main/java/org/keycloak/services/models/nosql/keycloak/adapters/MongoDBSessionFactory.java
index 114f7b7..73ba461 100644
--- a/services/src/main/java/org/keycloak/services/models/nosql/keycloak/adapters/MongoDBSessionFactory.java
+++ b/services/src/main/java/org/keycloak/services/models/nosql/keycloak/adapters/MongoDBSessionFactory.java
@@ -43,14 +43,14 @@ public class MongoDBSessionFactory implements KeycloakSessionFactory {
     private final MongoClient mongoClient;
     private final NoSQL mongoDB;
 
-    public MongoDBSessionFactory(String host, int port, String dbName, boolean removeAllObjectsAtStartup) {
-        logger.info(String.format("Going to use MongoDB database. host: %s, port: %d, databaseName: %s, removeAllObjectsAtStartup: %b", host, port, dbName, removeAllObjectsAtStartup));
+    public MongoDBSessionFactory(String host, int port, String dbName, boolean dropDatabaseOnStartup) {
+        logger.info(String.format("Going to use MongoDB database. host: %s, port: %d, databaseName: %s, removeAllObjectsAtStartup: %b", host, port, dbName, dropDatabaseOnStartup));
         try {
             // TODO: authentication support
             mongoClient = new MongoClient(host, port);
 
             DB db = mongoClient.getDB(dbName);
-            mongoDB = new MongoDBImpl(db, removeAllObjectsAtStartup, MANAGED_DATA_TYPES);
+            mongoDB = new MongoDBImpl(db, dropDatabaseOnStartup, MANAGED_DATA_TYPES);
 
         } catch (UnknownHostException e) {
             throw new RuntimeException(e);
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index dabba40..fc82975 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -37,6 +37,16 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class KeycloakApplication extends Application {
+
+    public static final String SESSION_FACTORY = "keycloak.sessionFactory";
+    public static final String SESSION_FACTORY_PICKETLINK = "picketlink";
+    public static final String SESSION_FACTORY_MONGO = "mongo";
+    public static final String MONGO_HOST = "keycloak.mongodb.host";
+    public static final String MONGO_PORT = "keycloak.mongodb.port";
+    public static final String MONGO_DB_NAME = "keycloak.mongodb.databaseName";
+    public static final String MONGO_DROP_DB_ON_STARTUP = "keycloak.mongodb.dropDatabaseOnStartup";
+
+
     protected Set<Object> singletons = new HashSet<Object>();
     protected Set<Class<?>> classes = new HashSet<Class<?>>();
 
@@ -62,8 +72,8 @@ public class KeycloakApplication extends Application {
     }
 
     public static KeycloakSessionFactory buildSessionFactory() {
-        String sessionFactoryType = System.getProperty("keycloak.sessionFactory", "picketlink");
-        if ("mongo".equals(sessionFactoryType)) {
+        String sessionFactoryType = System.getProperty(SESSION_FACTORY, SESSION_FACTORY_PICKETLINK);
+        if (SESSION_FACTORY_MONGO.equals(sessionFactoryType)) {
             return buildMongoDBSessionFactory();
         } else {
             return buildPicketlinkSessionFactory();
@@ -76,11 +86,11 @@ public class KeycloakApplication extends Application {
     }
 
     private static KeycloakSessionFactory buildMongoDBSessionFactory() {
-        String host = System.getProperty("keycloak.mongodb.host", "localhost");
-        int port = Integer.parseInt(System.getProperty("keycloak.mongodb.port", "27017"));
-        String dbName = System.getProperty("keycloak.mongodb.databaseName", "keycloak");
-        boolean removeAllObjectsOnStartup = Boolean.parseBoolean(System.getProperty("keycloak.mongodb.removeAllObjectsOnStartup", "true"));
-        return new MongoDBSessionFactory(host, port, dbName, removeAllObjectsOnStartup);
+        String host = System.getProperty(MONGO_HOST, "localhost");
+        int port = Integer.parseInt(System.getProperty(MONGO_PORT, "27017"));
+        String dbName = System.getProperty(MONGO_DB_NAME, "keycloak");
+        boolean dropDatabaseOnStartup = Boolean.parseBoolean(System.getProperty(MONGO_DROP_DB_ON_STARTUP, "true"));
+        return new MongoDBSessionFactory(host, port, dbName, dropDatabaseOnStartup);
     }
 
     public KeycloakSessionFactory getFactory() {
diff --git a/services/src/test/java/org/keycloak/test/AdapterTest.java b/services/src/test/java/org/keycloak/test/AdapterTest.java
index 1bdaa82..0842036 100755
--- a/services/src/test/java/org/keycloak/test/AdapterTest.java
+++ b/services/src/test/java/org/keycloak/test/AdapterTest.java
@@ -12,6 +12,8 @@ import org.keycloak.services.managers.OAuthClientManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.models.UserModel.RequiredAction;
 import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.test.common.AbstractKeycloakTest;
+import org.keycloak.test.common.SessionFactoryTestContext;
 
 
 import java.util.HashSet;
@@ -24,30 +26,16 @@ import java.util.StringTokenizer;
  * @version $Revision: 1 $
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class AdapterTest {
-    private KeycloakSessionFactory factory;
-    private KeycloakSession identitySession;
-    private RealmManager adapter;
+public class AdapterTest extends AbstractKeycloakTest {
     private RealmModel realmModel;
 
-    @Before
-    public void before() throws Exception {
-        factory = KeycloakApplication.buildSessionFactory();
-        identitySession = factory.createSession();
-        identitySession.getTransaction().begin();
-        adapter = new RealmManager(identitySession);
-    }
-
-    @After
-    public void after() throws Exception {
-        identitySession.getTransaction().commit();
-        identitySession.close();
-        factory.close();
+    public AdapterTest(SessionFactoryTestContext testContext) {
+        super(testContext);
     }
 
     @Test
     public void installTest() throws Exception {
-        new InstallationManager().install(adapter);
+        new InstallationManager().install(getRealmManager());
 
     }
 
@@ -63,7 +51,7 @@ public class AdapterTest {
 
     @Test
     public void test1CreateRealm() throws Exception {
-        realmModel = adapter.createRealm("JUGGLER");
+        realmModel = getRealmManager().createRealm("JUGGLER");
         realmModel.setAccessCodeLifespan(100);
         realmModel.setAccessCodeLifespanUserAction(600);
         realmModel.setCookieLoginAllowed(true);
@@ -76,7 +64,7 @@ public class AdapterTest {
         realmModel.addDefaultRole("foo");
 
         System.out.println(realmModel.getId());
-        realmModel = adapter.getRealm(realmModel.getId());
+        realmModel = getRealmManager().getRealm(realmModel.getId());
         Assert.assertNotNull(realmModel);
         Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
         Assert.assertEquals(600, realmModel.getAccessCodeLifespanUserAction());
diff --git a/services/src/test/java/org/keycloak/test/common/AbstractKeycloakTest.java b/services/src/test/java/org/keycloak/test/common/AbstractKeycloakTest.java
new file mode 100644
index 0000000..0e9b692
--- /dev/null
+++ b/services/src/test/java/org/keycloak/test/common/AbstractKeycloakTest.java
@@ -0,0 +1,96 @@
+package org.keycloak.test.common;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.models.KeycloakSession;
+import org.keycloak.services.models.KeycloakSessionFactory;
+import org.keycloak.services.resources.KeycloakApplication;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+@RunWith(Parameterized.class)
+public abstract class AbstractKeycloakTest {
+
+    protected static final SessionFactoryTestContext[] TEST_CONTEXTS;
+
+    private final SessionFactoryTestContext testContext;
+    private KeycloakSessionFactory factory;
+    private KeycloakSession identitySession;
+    private RealmManager realmManager;
+
+    // STATIC METHODS
+
+    static
+    {
+        // TODO: Disable MongoDB by default and enable it just for some specific maven profile (system property)?
+        TEST_CONTEXTS = new SessionFactoryTestContext[] {
+                new PicketlinkSessionFactoryTestContext(),
+                new MongoDBSessionFactoryTestContext()
+        };
+    }
+
+    @Parameterized.Parameters
+    public static Iterable<Object[]> parameters() {
+        List<Object[]> params = new ArrayList<Object[]>();
+
+        for (SessionFactoryTestContext testContext : TEST_CONTEXTS) {
+            params.add(new Object[] {testContext});
+        }
+        return params;
+    }
+
+    @BeforeClass
+    public static void baseBeforeClass() {
+        for (SessionFactoryTestContext testContext : TEST_CONTEXTS) {
+            testContext.beforeTestClass();
+        }
+    }
+
+    @AfterClass
+    public static void baseAfterClass() {
+        for (SessionFactoryTestContext testContext : TEST_CONTEXTS) {
+            testContext.afterTestClass();
+        }
+    }
+
+    // NON-STATIC METHODS
+
+    public AbstractKeycloakTest(SessionFactoryTestContext testContext) {
+        this.testContext = testContext;
+    }
+
+    @Before
+    public void before() throws Exception {
+        testContext.initEnvironment();
+        factory = KeycloakApplication.buildSessionFactory();
+        identitySession = factory.createSession();
+        identitySession.getTransaction().begin();
+        realmManager = new RealmManager(identitySession);
+    }
+
+    @After
+    public void after() throws Exception {
+        identitySession.getTransaction().commit();
+        identitySession.close();
+        factory.close();
+    }
+
+    protected RealmManager getRealmManager() {
+        return realmManager;
+    }
+
+    protected KeycloakSession getIdentitySession() {
+        return identitySession;
+    }
+
+}
diff --git a/services/src/test/java/org/keycloak/test/common/MongoDBSessionFactoryTestContext.java b/services/src/test/java/org/keycloak/test/common/MongoDBSessionFactoryTestContext.java
new file mode 100644
index 0000000..fc723a2
--- /dev/null
+++ b/services/src/test/java/org/keycloak/test/common/MongoDBSessionFactoryTestContext.java
@@ -0,0 +1,60 @@
+package org.keycloak.test.common;
+
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.MongodConfig;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.runtime.Network;
+import org.jboss.resteasy.logging.Logger;
+import org.keycloak.services.models.KeycloakSessionFactory;
+import org.keycloak.services.resources.KeycloakApplication;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MongoDBSessionFactoryTestContext implements SessionFactoryTestContext {
+
+    protected static final Logger logger = Logger.getLogger(MongoDBSessionFactoryTestContext.class);
+    private static final int PORT = 27777;
+
+    private MongodExecutable mongodExe;
+    private MongodProcess mongod;
+
+    @Override
+    public void beforeTestClass() {
+        logger.info("Bootstrapping MongoDB on localhost, port " + PORT);
+        try {
+            mongodExe = MongodStarter.getDefaultInstance().prepare(new MongodConfig(Version.V2_0_5, PORT, Network.localhostIsIPv6()));
+            mongod = mongodExe.start();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        logger.info("MongoDB bootstrapped successfully");
+    }
+
+    @Override
+    public void afterTestClass() {
+        if (mongodExe != null) {
+            if (mongod != null) {
+                mongod.stop();
+            }
+            mongodExe.stop();
+        }
+        logger.info("MongoDB stopped successfully");
+
+        // Null this, so other tests are not affected
+        System.setProperty(KeycloakApplication.SESSION_FACTORY, "");
+    }
+
+    @Override
+    public void initEnvironment() {
+        System.setProperty(KeycloakApplication.SESSION_FACTORY, KeycloakApplication.SESSION_FACTORY_MONGO);
+        System.setProperty(KeycloakApplication.MONGO_HOST, "localhost");
+        System.setProperty(KeycloakApplication.MONGO_PORT, String.valueOf(PORT));
+        System.setProperty(KeycloakApplication.MONGO_DB_NAME, "keycloakTest");
+        System.setProperty(KeycloakApplication.MONGO_DROP_DB_ON_STARTUP, "true");
+    }
+}
diff --git a/services/src/test/java/org/keycloak/test/common/PicketlinkSessionFactoryTestContext.java b/services/src/test/java/org/keycloak/test/common/PicketlinkSessionFactoryTestContext.java
new file mode 100644
index 0000000..7ffbbf3
--- /dev/null
+++ b/services/src/test/java/org/keycloak/test/common/PicketlinkSessionFactoryTestContext.java
@@ -0,0 +1,25 @@
+package org.keycloak.test.common;
+
+import org.keycloak.services.models.KeycloakSessionFactory;
+import org.keycloak.services.resources.KeycloakApplication;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class PicketlinkSessionFactoryTestContext implements SessionFactoryTestContext {
+
+    @Override
+    public void beforeTestClass() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void afterTestClass() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void initEnvironment() {
+        System.setProperty(KeycloakApplication.SESSION_FACTORY, KeycloakApplication.SESSION_FACTORY_PICKETLINK);
+    }
+}
diff --git a/services/src/test/java/org/keycloak/test/common/SessionFactoryTestContext.java b/services/src/test/java/org/keycloak/test/common/SessionFactoryTestContext.java
new file mode 100644
index 0000000..3bbc4bd
--- /dev/null
+++ b/services/src/test/java/org/keycloak/test/common/SessionFactoryTestContext.java
@@ -0,0 +1,19 @@
+package org.keycloak.test.common;
+
+import org.keycloak.services.models.KeycloakSessionFactory;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface SessionFactoryTestContext {
+
+    void beforeTestClass();
+
+    void afterTestClass();
+
+    /**
+     * Init system properties (or other configuration) to ensure that KeycloakApplication.buildSessionFactory() will return correct
+     * instance of KeycloakSessionFactory for our test
+     */
+    void initEnvironment();
+}
diff --git a/services/src/test/java/org/keycloak/test/ImportTest.java b/services/src/test/java/org/keycloak/test/ImportTest.java
index d426d4e..33348ed 100755
--- a/services/src/test/java/org/keycloak/test/ImportTest.java
+++ b/services/src/test/java/org/keycloak/test/ImportTest.java
@@ -19,6 +19,8 @@ import org.keycloak.models.SocialLinkModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.services.resources.KeycloakApplication;
 import org.keycloak.services.resources.SaasService;
+import org.keycloak.test.common.AbstractKeycloakTest;
+import org.keycloak.test.common.SessionFactoryTestContext;
 
 import java.util.List;
 import java.util.Set;
@@ -28,29 +30,15 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class ImportTest {
-    private KeycloakSessionFactory factory;
-    private KeycloakSession identitySession;
-    private RealmManager manager;
-    private RealmModel realmModel;
-
-    @Before
-    public void before() throws Exception {
-        factory = KeycloakApplication.buildSessionFactory();
-        identitySession = factory.createSession();
-        identitySession.getTransaction().begin();
-        manager = new RealmManager(identitySession);
-    }
+public class ImportTest extends AbstractKeycloakTest {
 
-    @After
-    public void after() throws Exception {
-        identitySession.getTransaction().commit();
-        identitySession.close();
-        factory.close();
+    public ImportTest(SessionFactoryTestContext testContext) {
+        super(testContext);
     }
 
     @Test
     public void install() throws Exception {
+        RealmManager manager = getRealmManager();
         RealmModel defaultRealm = manager.createRealm(RealmModel.DEFAULT_REALM, RealmModel.DEFAULT_REALM);
         defaultRealm.setName(RealmModel.DEFAULT_REALM);
         defaultRealm.setEnabled(true);
@@ -93,7 +81,7 @@ public class ImportTest {
 
         List<ApplicationModel> resources = realm.getApplications();
         Assert.assertEquals(2, resources.size());
-        List<RealmModel> realms = identitySession.getRealms(admin);
+        List<RealmModel> realms = getIdentitySession().getRealms(admin);
         Assert.assertEquals(1, realms.size());
 
         // Test scope relationship
@@ -129,6 +117,7 @@ public class ImportTest {
 
     @Test
     public void install2() throws Exception {
+        RealmManager manager = getRealmManager();
         RealmModel defaultRealm = manager.createRealm(RealmModel.DEFAULT_REALM, RealmModel.DEFAULT_REALM);
         defaultRealm.setName(RealmModel.DEFAULT_REALM);
         defaultRealm.setEnabled(true);
diff --git a/services/src/test/java/org/keycloak/test/RealmCreationTest.java b/services/src/test/java/org/keycloak/test/RealmCreationTest.java
index a99042f..725a0d1 100755
--- a/services/src/test/java/org/keycloak/test/RealmCreationTest.java
+++ b/services/src/test/java/org/keycloak/test/RealmCreationTest.java
@@ -11,6 +11,11 @@ import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
+import org.keycloak.services.models.KeycloakSession;
+import org.keycloak.services.models.RealmModel;
+import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.test.common.AbstractKeycloakTest;
+import org.keycloak.test.common.SessionFactoryTestContext;
 
 import javax.ws.rs.NotAuthorizedException;
 import javax.ws.rs.client.Entity;