Author: ivol
Date: Fri Oct 15 11:48:48 2010
New Revision: 173

Log:
[AMDATU-107] Initial draft version of a Unit test (for Tenant management 
service) using Pax Exam framework

Added:
   
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantDAO.java
   
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java
      - copied, changed from r155, 
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/domain/TenantImpl.java
   
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/
   
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/TenantDAOCassandraImpl.java
   trunk/platform-bundles/tenant-service/src/test/
   trunk/platform-bundles/tenant-service/src/test/java/
   trunk/platform-bundles/tenant-service/src/test/java/org/
   trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/
   trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/platform/
   
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/platform/tenant/
   
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/platform/tenant/test/
   
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/platform/tenant/test/TenantManagementServiceTest.java
   
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/platform/tenant/test/mock/
   
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/platform/tenant/test/mock/TenantDAOMock.java
Removed:
   
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/domain/TenantImpl.java
Modified:
   trunk/platform-bundles/tenant-service/pom.xml
   
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/osgi/Activator.java
   
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantManagementServiceImpl.java
   trunk/pom.xml

Modified: trunk/platform-bundles/tenant-service/pom.xml
==============================================================================
--- trunk/platform-bundles/tenant-service/pom.xml       (original)
+++ trunk/platform-bundles/tenant-service/pom.xml       Fri Oct 15 11:48:48 2010
@@ -13,10 +13,40 @@
   <name>Amdatu Platform - Tenant Service</name>
   <description>This bundle provides a tenant management service with tenant 
CRUD operations</description>
 
+
+  <!-- See issues:
+    http://issues.ops4j.org/browse/PAXEXAM-81
+    http://svn.apache.org/repos/asf/felix/releases/karaf-1.0.0/itests/pom.xml
+    http://pastebin.com/nUjAZENT
+  -->
+  
+  
   <dependencies>
+      <!-- This is required to be first so that pax-exam classloader is not 
messed up with a newer version of felix
+              which would lead to java.lang.NoSuchMethodError: 
org.apache.felix.framework.Logger.<init>(I)V --> 
+      <dependency>
+        <groupId>org.ops4j.pax.exam</groupId>
+        <artifactId>pax-exam</artifactId>
+        <version>${pax.exam.version}</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.ops4j.pax.exam</groupId>
+        <artifactId>pax-exam-junit</artifactId>
+        <version>${pax.exam.version}</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.ops4j.pax.exam</groupId>
+        <artifactId>pax-exam-container-default</artifactId>
+        <version>${pax.exam.version}</version>
+        <scope>test</scope>
+    </dependency>  
+    
     <dependency>
       <groupId>org.amdatu.platform</groupId>
       <artifactId>cassandra-application</artifactId>
+      <version>0.0.5-SNAPSHOT</version>
       <scope>provided</scope>
       <type>bundle</type>
     </dependency>
@@ -31,7 +61,7 @@
       <artifactId>cassandra-listener</artifactId>
       <scope>provided</scope>
       <type>bundle</type>
-    </dependency>   
+    </dependency>  
   </dependencies>
   
   <build>
@@ -54,7 +84,7 @@
       <plugin>
         <artifactId>maven-antrun-plugin</artifactId>
       </plugin>   
-        
+              
     </plugins>
     
   </build> 

Added: 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantDAO.java
==============================================================================
--- (empty file)
+++ 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantDAO.java
       Fri Oct 15 11:48:48 2010
@@ -0,0 +1,65 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.platform.tenant;
+
+import java.util.List;
+
+
+/**
+ * Interface for the Tenant DAO. The DAO contains CRUD operations for tenants. 
The DAO is decoupled from the Tenant
+ * Management service for unit testing purposes.
+ * @author ivol
+ */
+public interface TenantDAO {
+    /**
+     * Creates a new Tenant with the specified id and name.
+     * @param id The id of the tenant
+     * @param name the name of the tenant
+     * @return The created tenant
+     * @throws TenantException In case creation of the Tenant failed
+     */
+    Tenant create(String id, String name) throws TenantException;
+
+    /**
+     * Reads all existing Tenants and returns them.
+     * @return All existing Tenants
+     * @throws TenantException In case loading all Tenants failed
+     */
+    List<Tenant> readAll() throws TenantException;
+
+    /**
+     * Reads a Tenant with the specified id and returns it.
+     * @param id The identifier of the Tenant to read
+     * @return The Tenant with the specified id
+     * @throws TenantException In case the Tenant could not be read from the 
Cassandra database
+     */
+    Tenant read(String id) throws TenantException;
+
+    /**
+     * Updates a Tenant.
+     * @param tenant the Tenant containing the updates, the Tenant that 
matches the id of this Tenant is updated.
+     * @throws TenantException In case the Tenant could not be updated
+     */
+    void update(Tenant tenant) throws TenantException;
+
+    /**
+     * Deletes the specified Tenant from the Cassandra database.
+     * @param tenant The Tenant to delete
+     * @throws TenantException In case the Tenant could not be deleted from 
the Cassandra database.
+     */
+    void delete(Tenant tenant) throws TenantException;
+}

Copied: 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java
 (from r155, 
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/domain/TenantImpl.java)
==============================================================================
--- 
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/domain/TenantImpl.java
      (original)
+++ 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java
      Fri Oct 15 11:48:48 2010
@@ -15,11 +15,10 @@
     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-package org.amdatu.platform.tenant.domain;
+package org.amdatu.platform.tenant;
 
 import java.util.Map;
 
-import org.amdatu.platform.tenant.Tenant;
 
 public class TenantImpl implements Tenant {
     // The id of the tenant

Added: 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/TenantDAOCassandraImpl.java
==============================================================================
--- (empty file)
+++ 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/dao/TenantDAOCassandraImpl.java
      Fri Oct 15 11:48:48 2010
@@ -0,0 +1,143 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.platform.tenant.dao;
+
+import static 
org.amdatu.platform.tenant.service.TenantColumnFamilyProvider.CF_TENANT;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.amdatu.platform.cassandra.persistencemanager.CassandraException;
+import 
org.amdatu.platform.cassandra.persistencemanager.CassandraPersistenceManager;
+import org.amdatu.platform.tenant.Tenant;
+import org.amdatu.platform.tenant.TenantDAO;
+import org.amdatu.platform.tenant.TenantException;
+import org.amdatu.platform.tenant.TenantImpl;
+
+/**
+ * Cassandra implementation of the Tenant DAO.
+ * @author ivol
+ */
+public class TenantDAOCassandraImpl implements TenantDAO {
+    // Name of the supercolumns
+    private static final String SC_BASIC = "Basic";
+    private static final String SC_PROPERTIES = "Properties";
+
+    // Name of the columns
+    private static final String C_NAME = "name";
+
+    // Services injected by the Felix dependency manager
+    private volatile CassandraPersistenceManager m_pm;
+
+    /**
+     * @see TenantDAO#create(String, String)
+     */
+    public Tenant create(String id, String name) throws TenantException {
+        synchronized (this) {
+            try {
+                if (m_pm.exists(CF_TENANT, id)) {
+                    throw new TenantException("Tenant with id '" + id + "' 
already exists");
+                }
+                m_pm.setStringValue(CF_TENANT, id, SC_BASIC, C_NAME, name);
+                return new TenantImpl(id, name, new HashMap<String, String>());
+            }
+            catch (CassandraException e) {
+                throw new TenantException(e);
+            }
+        }
+    }
+
+    /**
+     * @see TenantDAO#readAll()
+     */
+    public List<Tenant> readAll() throws TenantException {
+        synchronized (this) {
+            try {
+                List<Tenant> tenants = new ArrayList<Tenant>();
+                List<String> rowKeys = m_pm.getRowKeys(CF_TENANT);
+                if (rowKeys != null) {
+                    for (String rowKey : rowKeys) {
+                        Tenant tenant = read(rowKey);
+                        tenants.add(tenant);
+                    }
+                }
+                return tenants;
+            }
+            catch (CassandraException e) {
+                throw new TenantException(e);
+            }
+        }
+    }
+
+    /**
+     * @see TenantDAO#read(String)
+     */
+    public Tenant read(String rowKey) throws TenantException {
+        synchronized (this) {
+            try {
+                if (!m_pm.exists(CF_TENANT, rowKey)) {
+                    throw new TenantException("Tenant to be loaded with id '" 
+ rowKey + "' doesn't exist");
+                }
+                Map<String, Map<String, String>> values = 
m_pm.getSuperStringValues(CF_TENANT, rowKey);
+                Map<String, String> basic = values.get(SC_BASIC);
+                Map<String, String> properties = values.get(SC_PROPERTIES);
+                String name = basic.get(C_NAME);
+                return new TenantImpl(rowKey, name, properties);
+            }
+            catch (CassandraException e) {
+                throw new TenantException(e);
+            }
+        }
+    }
+
+    /**
+     * @see TenantDAO#update(Tenant)
+     */
+    public void update(Tenant tenant) throws TenantException {
+        synchronized (this) {
+            try {
+                String id = tenant.getId();
+                m_pm.setStringValue(CF_TENANT, id, SC_BASIC, C_NAME, 
tenant.getName());
+                for (String key : tenant.getProperties().keySet()) {
+                    m_pm.setStringValue(CF_TENANT, id, SC_PROPERTIES, key, 
tenant.getProperties().get(key));
+                }
+            }
+            catch (CassandraException e) {
+                throw new TenantException(e);
+            }
+        }
+    }
+
+    /**
+     * @see TenantDAO#delete(Tenant)
+     */
+    public void delete(Tenant tenant) throws TenantException {
+        synchronized (this) {
+            try {
+                if (!m_pm.exists(CF_TENANT, tenant.getId())) {
+                    throw new TenantException("Tenant to be removed with id '" 
+ tenant.getId() + "' doesn't exist");
+                }
+                m_pm.deleteRow(CF_TENANT, tenant.getId());
+            }
+            catch (CassandraException e) {
+                throw new TenantException(e);
+            }
+        }
+    }
+}

Modified: 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/osgi/Activator.java
==============================================================================
--- 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/osgi/Activator.java
  (original)
+++ 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/osgi/Activator.java
  Fri Oct 15 11:48:48 2010
@@ -22,7 +22,9 @@
 import org.amdatu.platform.cassandra.listener.ColumnFamilyProvider;
 import 
org.amdatu.platform.cassandra.persistencemanager.CassandraPersistenceManager;
 import org.amdatu.platform.tenant.TenantAwareServiceAdapter;
+import org.amdatu.platform.tenant.TenantDAO;
 import org.amdatu.platform.tenant.TenantManagementService;
+import org.amdatu.platform.tenant.dao.TenantDAOCassandraImpl;
 import org.amdatu.platform.tenant.service.TenantAwareServiceAdapterImpl;
 import org.amdatu.platform.tenant.service.TenantColumnFamilyProvider;
 import org.amdatu.platform.tenant.service.TenantManagementServiceImpl;
@@ -48,22 +50,28 @@
                 .setImplementation(TenantColumnFamilyProvider.class)
                 .setInterface(ColumnFamilyProvider.class.getName(), null)
                 
.add(createServiceDependency().setService(CassandraDaemonService.class).setRequired(true)));
- 
+
         // The filter for the Tenant ColumnFamily being available
         String tenantFilter = 
TenantColumnFamilyProvider.TENANT_AVAILABLE_FILTER;
         String keyspaceFilter =
             "(" + CassandraPersistenceManager.KEYSPACE_AWARE_KEY + "="
                     + CassandraPersistenceManager.DEFAULT_KEYSPACE + ")";
         
-        // Create and register the tenant service, which depends on the 
availability of the Tenant
-        // ColumnFamily 
+        // Create and register the Cassandra Tenant DAO
         manager.add(
                 createComponent()
-                .setImplementation(TenantManagementServiceImpl.class)
-                .setInterface(TenantManagementService.class.getName(), null)
+                .setImplementation(TenantDAOCassandraImpl.class)
+                .setInterface(TenantDAO.class.getName(), null)
                 
.add(createServiceDependency().setService(CassandraPersistenceManager.class, 
keyspaceFilter).setRequired(true))
-                
.add(createServiceDependency().setService(LogService.class).setRequired(true))
                 
.add(createServiceDependency().setService(ColumnFamilyAvailable.class, 
tenantFilter).setRequired(true)));
+        
+        // Create and register the Tenant management service
+        manager.add(
+                createComponent()
+                .setImplementation(TenantManagementServiceImpl.class)
+                .setInterface(TenantManagementService.class.getName(), null)
+                
.add(createServiceDependency().setService(TenantDAO.class).setRequired(true))
+                
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
 
         // Create and register a tenant aware service adapter
         manager.add(

Modified: 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantManagementServiceImpl.java
==============================================================================
--- 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantManagementServiceImpl.java
     (original)
+++ 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/service/TenantManagementServiceImpl.java
     Fri Oct 15 11:48:48 2010
@@ -16,34 +16,27 @@
  */
 package org.amdatu.platform.tenant.service;
 
-import static 
org.amdatu.platform.tenant.service.TenantColumnFamilyProvider.CF_TENANT;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.amdatu.platform.cassandra.persistencemanager.CassandraException;
-import 
org.amdatu.platform.cassandra.persistencemanager.CassandraPersistenceManager;
 import org.amdatu.platform.tenant.Tenant;
+import org.amdatu.platform.tenant.TenantDAO;
 import org.amdatu.platform.tenant.TenantException;
 import org.amdatu.platform.tenant.TenantManagementService;
-import org.amdatu.platform.tenant.domain.TenantImpl;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.osgi.service.log.LogService;
 
+/**
+ * Implementation of the Tenant management service.
+ * @author ivol
+ */
 public class TenantManagementServiceImpl implements TenantManagementService {
-    // Name of the supercolumns
-    private static final String SC_BASIC = "Basic";
-    private static final String SC_PROPERTIES = "Properties";
-
-    // Name of the columns
-    private static final String C_NAME = "name";
-
     // Injected by the Felix dependency manager
     private volatile DependencyManager m_manager;
-    private volatile CassandraPersistenceManager m_pm;
+    private volatile TenantDAO m_tenantDAO;
     private volatile LogService m_logService;
 
     // Instance variables
@@ -56,20 +49,16 @@
     public void start() {
         try {
             // Upon starting this bundle, we load the available tenants into 
memory
-            List<String> rowKeys = m_pm.getRowKeys(CF_TENANT);
-            for (String rowKey : rowKeys) {
-                Tenant tenant = loadTenant(rowKey);
-                m_tenants.add(tenant);
-            }
+            System.out.println("Loading tenants");
+            m_tenants = m_tenantDAO.readAll();
 
             // Register all tenants as service
             for (Tenant tenant : getAllTenants()) {
-                
m_manager.add(m_manager.createComponent().setImplementation(tenant).setInterface(Tenant.class.getName(),
-                        null));
+                
m_manager.add(m_manager.createComponent().setImplementation(tenant).setInterface(
+                        Tenant.class.getName(), null));
             }
-        } catch (CassandraException e) {
-            m_logService.log(LogService.LOG_ERROR, "Could not load tenants", 
e);
-        } catch (TenantException e) {
+        }
+        catch (TenantException e) {
             m_logService.log(LogService.LOG_ERROR, "Could not load tenants", 
e);
         }
     }
@@ -111,55 +100,13 @@
      */
     public Tenant createTentant(String id, String name) throws TenantException 
{
         synchronized (this) {
-            try {
-                if (m_pm.exists(CF_TENANT, id)) {
-                    throw new TenantException("Tenant with id '" + id + "' 
already exists");
-                }
-                m_pm.setStringValue(CF_TENANT, id, SC_BASIC, C_NAME, name);
-                boolean succes = false;
-                Tenant tenant = null;
-                try {
-                    tenant = new TenantImpl(id, name, new HashMap<String, 
String>());
-                    Component tenantComponent =
-                            
m_manager.createComponent().setImplementation(tenant).setInterface(Tenant.class.getName(),
-                                    null);
-                    m_tenantComponents.put(tenant, tenantComponent);
-                    m_manager.add(tenantComponent);
-                    m_tenants.add(tenant);
-                    succes = true;
-                    return tenant;
-                } finally {
-                    if (!succes) {
-                        rollbackCreate(id, tenant);
-                    }
-                }
-
-            } catch (CassandraException e) {
-                throw new TenantException(e);
-            }
-        }
-    }
-
-    // Implementation of rollback for the create
-    private void rollbackCreate(String id, Tenant tenant) throws 
CassandraException {
-        // If we come here the row was inserted in Cassandra but after that 
something
-        // failed so we will need to perform a rollback
-        try {
-            m_pm.deleteRow(CF_TENANT, id);
-        } finally {
-            if (tenant != null) {
-                try {
-                    m_tenants.remove(tenant);
-                } finally {
-                    if (m_tenantComponents.containsKey(tenant)) {
-                        try {
-                            m_manager.remove(m_tenantComponents.get(tenant));
-                        } finally {
-                            m_tenantComponents.remove(tenant);
-                        }
-                    }
-                }
-            }
+            Tenant tenant = m_tenantDAO.create(id, name);
+            Component tenantComponent =
+                    
m_manager.createComponent().setImplementation(tenant).setInterface(Tenant.class.getName(),
 null);
+            m_tenantComponents.put(tenant, tenantComponent);
+            m_manager.add(tenantComponent);
+            m_tenants.add(tenant);
+            return tenant;
         }
     }
 
@@ -167,15 +114,7 @@
      * @see TenantManagementService#updateTenant(Tenant)
      */
     public void updateTenant(Tenant tenant) throws TenantException {
-        try {
-            String id = tenant.getId();
-            m_pm.setStringValue(CF_TENANT, id, SC_BASIC, C_NAME, 
tenant.getName());
-            for (String key : tenant.getProperties().keySet()) {
-                m_pm.setStringValue(CF_TENANT, id, SC_PROPERTIES, key, 
tenant.getProperties().get(key));
-            }
-        } catch (CassandraException e) {
-            throw new TenantException(e);
-        }
+        m_tenantDAO.update(tenant);
     }
 
     /**
@@ -183,33 +122,10 @@
      */
     public void deleteTenant(Tenant tenant) throws TenantException {
         synchronized (this) {
-            try {
-                if (!m_pm.exists(CF_TENANT, tenant.getId())) {
-                    throw new TenantException("Tenant to be removed with id '" 
+ tenant.getId() + "' doesn't exist");
-                }
-                m_pm.deleteRow(CF_TENANT, tenant.getId());
-                m_tenants.remove(tenant);
-                m_manager.remove(m_tenantComponents.get(tenant));
-                m_tenantComponents.remove(tenant);
-            } catch (CassandraException e) {
-                throw new TenantException(e);
-            }
-        }
-    }
-
-    // Loads a tenant from Cassandra
-    private Tenant loadTenant(String rowKey) throws TenantException {
-        try {
-            if (!m_pm.exists(CF_TENANT, rowKey)) {
-                throw new TenantException("Tenant to be loaded with id '" + 
rowKey + "' doesn't exist");
-            }
-            Map<String, Map<String, String>> values = 
m_pm.getSuperStringValues(CF_TENANT, rowKey);
-            Map<String, String> basic = values.get(SC_BASIC);
-            Map<String, String> properties = values.get(SC_PROPERTIES);
-            String name = basic.get(C_NAME);
-            return new TenantImpl(rowKey, name, properties);
-        } catch (CassandraException e) {
-            throw new TenantException(e);
+            m_tenantDAO.delete(tenant);
+            m_tenants.remove(tenant);
+            m_manager.remove(m_tenantComponents.get(tenant));
+            m_tenantComponents.remove(tenant);
         }
     }
 }

Added: 
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/platform/tenant/test/TenantManagementServiceTest.java
==============================================================================
--- (empty file)
+++ 
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/platform/tenant/test/TenantManagementServiceTest.java
        Fri Oct 15 11:48:48 2010
@@ -0,0 +1,195 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.platform.tenant.test;
+
+import static org.ops4j.pax.exam.CoreOptions.felix;
+import static org.ops4j.pax.exam.CoreOptions.frameworks;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.provision;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import junit.framework.Assert;
+
+import org.amdatu.platform.tenant.Tenant;
+import org.amdatu.platform.tenant.TenantDAO;
+import org.amdatu.platform.tenant.TenantException;
+import org.amdatu.platform.tenant.TenantManagementService;
+import org.amdatu.platform.tenant.test.mock.TenantDAOMock;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Inject;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * This class provides a Unit test for testing the Tenant Management Service.
+ * @author ivol
+ */
+// TODO: version number are still hard coded since for some reason 
versionAsInProject() doesn't work (causes exception)
+// TODO: although not effecting the test, several errors appear in the log 
booting Felix, these must be fixed
+// TODO: using this test framework must be generalized, move dependencies to 
root pom
+// TODO: service ranking mechanism to enforce that mock dao is used must be 
tested after solving other issues
+// TODO: TenantImpl and TenantDAO has to be moved temporarily to the exported 
package in order for this test to use them
+// TODO: provisioning the bundle to be tested from a maven repository doesn't 
make sense, you would test the previous
+// version
+ at RunWith(JUnit4TestRunner.class)
+public class TenantManagementServiceTest {
+    @Inject
+    protected BundleContext m_bundleContext;
+
+    @Configuration
+    public Option[] configure() {
+
+        String version = "0.0.5-SNAPSHOT";
+        return options(
+        // Run test in a Felix container
+                frameworks(felix()),
+
+                // Setting this system property unfortunately is necessary 
with the current Cassandra implementation
+                
systemProperty("org.osgi.framework.system.packages.extra").value("sun.misc,com.sun.management"),
+
+                // I doubt if using mavenBundle is correct. Using mavenBundle 
the bundle is loaded from the online
+                // maven repository.
+
+                // Install bundles we need to execute our test
+                
provision(mavenBundle().groupId("org.osgi").artifactId("org.osgi.compendium").version("4.1.0"),
+                        
mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.dependencymanager")
+                                .version("3.0.0-SNAPSHOT"),
+                        
mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.configadmin").version(
+                                "1.2.4"),
+                        
mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.log").version("1.0.0"),
+                        
mavenBundle().groupId("org.ops4j.pax.web").artifactId("pax-web-jetty-bundle").version("0.7.1"),
+                        
mavenBundle().groupId("org.ops4j.pax.web").artifactId("pax-web-jsp").version("0.7.1"),
+                        
mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.commons.mime").version(
+                                "2.1.4"),
+
+                        // Amdatu platform bundles
+                        
mavenBundle().groupId("org.amdatu.platform").artifactId("httpcontext").version(version),
+                        
mavenBundle().groupId("org.amdatu.platform").artifactId("loghandler").version(version),
+                        
mavenBundle().groupId("org.amdatu.platform").artifactId("config-template-manager").version(version),
 
+                        
mavenBundle().groupId("org.amdatu.platform").artifactId("cassandra-application").version(version),
+                        
mavenBundle().groupId("org.amdatu.platform").artifactId("shindig-application").version(version),
+                        
mavenBundle().groupId("org.amdatu.platform").artifactId("cassandra-listener").version(version),
+                        
mavenBundle().groupId("org.amdatu.platform").artifactId("cassandra-persistencemanager").version(version)),
+                        
+                        
mavenBundle().groupId("org.amdatu.platform").artifactId("tenant-service").version(version));
+
+    }
+
+    @Test
+    public void crudTest() {
+        System.out.println(">  TESTING:  ************ Running Tenant CRUD test 
************");
+
+        // First we register a new Mocked TenantDAO service and register it 
with a higher service rank then the default
+        // Cassandra DAO such that our test framework will pick it up
+        DependencyManager depMgr = new DependencyManager(m_bundleContext);
+        Hashtable<String, Integer> ht = new Hashtable<String, Integer>();
+        ht.put(Constants.SERVICE_RANKING, 1);
+        
depMgr.add(depMgr.createComponent().setImplementation(TenantDAOMock.class).setInterface(
+                TenantDAO.class.getName(), ht));
+        System.out.println(">  TESTING:  TenantDAOMock service registered");
+
+        ServiceReference tenantMgrSR = 
m_bundleContext.getServiceReference(TenantManagementService.class.getName());
+        TenantManagementService tenantManagementService =
+                (TenantManagementService) 
m_bundleContext.getService(tenantMgrSR);
+        System.out.println(">  TESTING:  Testing " + tenantManagementService);
+
+        /*try {
+            run(tenantManagementService);
+        }
+        catch (TenantException e) {
+            Assert.fail("An error has occurred: " + e.toString());
+            e.printStackTrace();
+        }*/
+    }
+
+    /**
+     * @throws TenantException
+     * @see IntegrationTest#run
+     */
+    private void run(TenantManagementService tenantManagementService) throws 
TenantException {
+        Tenant[] allTenants = tenantManagementService.getAllTenants();
+        Assert.assertTrue("There are already tenants", 
tenantManagementService.getAllTenants().length == 0);
+
+        int tenantCount = allTenants.length;
+        System.out.println(">  TESTING:  
"+tenantManagementService.getAllTenants().length);
+
+        Tenant tenant = 
tenantManagementService.createTentant("org.amdatu.test.integration.tests.testtenant",
 "TEST");
+        for (Tenant t : tenantManagementService.getAllTenants()) {
+            System.out.println(t.getId() + " " + t.getName());
+        }
+        tenantManagementService.updateTenant(tenant);
+        
+        
+        Assert.assertTrue(tenantManagementService.getAllTenants().length + " 
should have been equal to "
+                + (tenantCount + 1), 
tenantManagementService.getAllTenants().length == tenantCount + 1);
+
+        // Try to add a tenant with the same id, should throw an exception
+        try {
+            
tenantManagementService.createTentant("org.amdatu.test.integration.tests.testtenant",
 "sdfsdfd");
+            Assert.assertTrue("Tenant with the same id could be created 
twice", false);
+        }
+        catch (TenantException e) {
+        }
+
+        tenantManagementService.deleteTenant(tenant);
+
+        Assert.assertTrue(tenantManagementService.getAllTenants().length == 
tenantCount);
+
+        Tenant tenant1 =
+                
tenantManagementService.createTentant("org.amdatu.test.integration.tests.testtenant.1",
 "TEST 1");
+        Tenant tenant2 =
+                
tenantManagementService.createTentant("org.amdatu.test.integration.tests.testtenant.2",
 "TEST 2");
+        Tenant tenant3 =
+                
tenantManagementService.createTentant("org.amdatu.test.integration.tests.testtenant.3",
 "TEST 3");
+        tenant1.getProperties().put("hostname", "localhost");
+        tenant2.getProperties().put("hostname", "localhost");
+        tenant3.getProperties().put("hostname", "amdatu.org");
+        tenantManagementService.updateTenant(tenant1);
+        tenantManagementService.updateTenant(tenant2);
+        tenantManagementService.updateTenant(tenant3);
+
+        Map<String, String> filter = new HashMap<String, String>();
+        filter.put("hostname", "localhost");
+        Assert.assertTrue(tenantManagementService.getTenants(filter).length == 
2);
+
+        filter.put("hostname", "amdatu.org");
+        Assert.assertTrue(tenantManagementService.getTenants(filter).length == 
1);
+
+        tenantManagementService.deleteTenant(tenant1);
+        tenantManagementService.deleteTenant(tenant2);
+        tenantManagementService.deleteTenant(tenant3);
+
+        // What happens if I remove a tenant that was already removed?
+        try {
+            tenantManagementService.deleteTenant(tenant);
+            Assert.assertTrue("Tenant with the same id could be deleted 
twice", false);
+        }
+        catch (TenantException e) {
+        }
+    }
+}

Added: 
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/platform/tenant/test/mock/TenantDAOMock.java
==============================================================================
--- (empty file)
+++ 
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/platform/tenant/test/mock/TenantDAOMock.java
 Fri Oct 15 11:48:48 2010
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.platform.tenant.test.mock;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.amdatu.platform.tenant.Tenant;
+import org.amdatu.platform.tenant.TenantDAO;
+import org.amdatu.platform.tenant.TenantException;
+import org.amdatu.platform.tenant.TenantImpl;
+
+/**
+ * This service mocks the TenantDAO, implementing an in-memory DAO.
+ * @author ivol
+ */
+public class TenantDAOMock implements TenantDAO {
+    private List<Tenant> m_tenants = new ArrayList<Tenant>();
+
+    public Tenant create(String id, String name) throws TenantException {
+        try {
+            read(id);
+            throw new TenantException("Tenant with id " + id + " already 
exists");
+        }
+        catch (TenantException e) {
+            TenantImpl tenant = new TenantImpl(id, name, new HashMap<String, 
String>());
+            m_tenants.add(tenant);
+            System.out.println(">  TESTING:  "+tenant.getId() + " added");
+            return tenant;
+        }
+    }
+
+    public List<Tenant> readAll() throws TenantException {
+        return m_tenants;
+    }
+
+    public Tenant read(String id) throws TenantException {
+        for (Tenant tenant : m_tenants) {
+            if (id.equals(tenant.getId())) {
+                return tenant;
+            }
+        }
+        throw new TenantException("Tenant with id '" + id + "' does not 
exist");
+    }
+
+    public void update(Tenant tenant) throws TenantException {
+        Tenant t = read(tenant.getId());
+        t.setName(tenant.getName());
+    }
+
+    public void delete(Tenant tenant) throws TenantException {
+        for (Tenant t : m_tenants) {
+            if (tenant.getId().equals(t.getId())) {
+                m_tenants.remove(tenant);
+                return;
+            }
+        }
+        throw new TenantException("Tenant with id '" + tenant.getId() + "' 
could not be removed");
+    }
+}

Modified: trunk/pom.xml
==============================================================================
--- trunk/pom.xml       (original)
+++ trunk/pom.xml       Fri Oct 15 11:48:48 2010
@@ -168,6 +168,7 @@
     <pax.useradmin.version>0.0.1-SNAPSHOT</pax.useradmin.version>
     <junit.version>4.8.1</junit.version>
     <jmock.version>2.5.1</jmock.version>
+    <pax.exam.version>1.2.2</pax.exam.version>
     
     <!-- Version numbers of platform bundles -->
     <shindig.version>1.1-BETA5-incubating</shindig.version>
@@ -220,6 +221,15 @@
   </repositories>
   
   <dependencies>
+    <!-- This is required to be first so that pax-exam classloader is not 
messed up with a newer version of felix
+              which would lead to java.lang.NoSuchMethodError: 
org.apache.felix.framework.Logger.<init>(I)V -->
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.framework</artifactId>
+      <version>${org.apache.felix.main.version}</version>
+      <scope>test</scope>
+    </dependency>
+    
     <!-- The main Felix framework -->
     <dependency>
       <groupId>org.apache.felix</groupId>
@@ -528,7 +538,7 @@
         <groupId>org.jmock</groupId>
         <artifactId>jmock-junit4</artifactId>
         <version>${jmock.version}</version>
-      </dependency> 
+      </dependency>     
     </dependencies>
   </dependencyManagement>
 
@@ -782,7 +792,6 @@
         <artifactId>maven-site-plugin</artifactId>
         <version>2.1.1</version>
       </plugin>
-            
     </plugins>
     
     <!-- Here we manage the plugins of all child projects -->
@@ -806,7 +815,7 @@
           <version>2.3.1</version>
         </plugin>       
       </plugins>
-    </pluginManagement>       
+    </pluginManagement>
   </build>
   
   <reporting>

Reply via email to