Author: ivol
Date: Tue Oct 19 09:57:11 2010
New Revision: 187

Log:
[AMDATU-107] Implemented tenant integration test as unit test

Added:
   
trunk/libraries/amdatu-utilities/src/main/java/org/amdatu/libraries/utilities/TestUtil.java
   
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantDAO.java
      - copied, changed from r179, 
/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 r179, 
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.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/test/
   trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/
   
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/InMemoryTenantDAO.java
   
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/TenantManagementServiceTest.java
Modified:
   trunk/integration-tests/pom.xml
   trunk/platform-bundles/tenant-service/pom.xml

Modified: trunk/integration-tests/pom.xml
==============================================================================
--- trunk/integration-tests/pom.xml     (original)
+++ trunk/integration-tests/pom.xml     Tue Oct 19 09:57:11 2010
@@ -115,6 +115,7 @@
       <plugin>
         <groupId>org.apache.servicemix.tooling</groupId>
         <artifactId>depends-maven-plugin</artifactId>
+        <version>1.2</version>
         <executions>
           <execution>
             <phase>integration-test</phase>
@@ -129,6 +130,7 @@
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>
+        <version>1.2.0</version>
         <executions>
           <execution>
             <phase>integration-test</phase>
@@ -136,12 +138,13 @@
             <goals>
               <goal>generate-config</goal>
             </goals>
-          </execution>
+          </execution>        
         </executions>
         <configuration>
           <options>
             <platform>${target-framework}</platform>
           </options>
+                  
         </configuration>
       </plugin>
       
@@ -165,7 +168,7 @@
           <skip>true</skip>
         </configuration>
       </plugin>
-
+   
     </plugins>
   </build> 
 </project>

Added: 
trunk/libraries/amdatu-utilities/src/main/java/org/amdatu/libraries/utilities/TestUtil.java
==============================================================================
--- (empty file)
+++ 
trunk/libraries/amdatu-utilities/src/main/java/org/amdatu/libraries/utilities/TestUtil.java
 Tue Oct 19 09:57:11 2010
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.amdatu.libraries.utilities;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/**
+ * Utility class that injects dependencies. Can be used to unit test service 
implementations.
+ */
+public class TestUtil {
+    public static final String UNIT = "unit";
+    public static final String INTEGRATION = "integration";
+    public static final String SMOKE = "smoke";
+    public static final String PERFORMANCE = "performance";
+    public static final String UI = "ui";
+    public static final String BROKEN = "broken";
+    /**
+     * Configures an object to use a null object for the specified service 
interface.
+     *
+     * @param object the object
+     * @param iface the service interface
+     */
+    public static <T> void configureObject(Object object, Class<T> iface) {
+        configureObject(object, iface, createNullObject(iface));
+    }
+
+    /**
+     * Creates a null object for a service interface.
+     *
+     * @param iface the service interface
+     * @return a null object
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T createNullObject(Class<T> iface) {
+        return (T) Proxy.newProxyInstance(iface.getClassLoader(), new Class[] 
{ iface }, new NullObject());
+    }
+
+    /**
+     * Wraps the given handler in an adapter that will try to pass on received 
invocations to the hander if that has
+     * an applicable methods else it defaults to a NullObject.
+     *
+     * @param iface the service interface
+     * @param handler the handler to pass invocations to.
+     * @return an adapter that will try to pass on received invocations to the 
given handler
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T createMockObjectAdapter(Class<T> iface, final Object 
handler) {
+        return (T) Proxy.newProxyInstance(iface.getClassLoader(), new Class[] 
{ iface }, new NullObject() {
+
+            @Override
+            public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable {
+                try {
+                    Method bridge = 
handler.getClass().getMethod(method.getName(), method.getParameterTypes());
+                    bridge.setAccessible(true);
+                    return bridge.invoke(handler, args);
+                }
+                catch (NoSuchMethodException ex) {
+                    return super.invoke(proxy, method, args);
+                }
+                catch (InvocationTargetException ex) {
+                    throw ex.getCause();
+                }
+            }
+        });
+    }
+
+    /**
+     * Configures an object to use a specific implementation for the specified 
service interface.
+     *
+     * @param object the object
+     * @param iface the service interface
+     * @param instance the implementation
+     */
+    @SuppressWarnings("unchecked")
+    public static void configureObject(Object object, Class iface, Object 
instance) {
+        Class serviceClazz = object.getClass();
+
+        while (serviceClazz != null) {
+            Field[] fields = serviceClazz.getDeclaredFields();
+            AccessibleObject.setAccessible(fields, true);
+            for (int j = 0; j < fields.length; j++) {
+                if (fields[j].getType().equals(iface)) {
+                    try {
+                        // synchronized makes sure the field is actually 
written to immediately
+                        synchronized (new Object()) {
+                            fields[j].set(object, instance);
+                        }
+                    }
+                    catch (Exception e) {
+                        throw new IllegalStateException("Could not set field " 
+ fields[j].getName() + " on " + object);
+                    }
+                }
+            }
+            serviceClazz = serviceClazz.getSuperclass();
+        }
+    }
+
+    static class NullObject implements InvocationHandler {
+        private static final Boolean DEFAULT_BOOLEAN = Boolean.FALSE;
+
+        private static final Byte DEFAULT_BYTE = new Byte((byte) 0);
+
+        private static final Short DEFAULT_SHORT = new Short((short) 0);
+
+        private static final Integer DEFAULT_INT = new Integer(0);
+
+        private static final Long DEFAULT_LONG = new Long(0);
+
+        private static final Float DEFAULT_FLOAT = new Float(0.0f);
+
+        private static final Double DEFAULT_DOUBLE = new Double(0.0);
+
+        /**
+         * Invokes a method on this null object. The method will return a 
default value without doing anything.
+         */
+        @SuppressWarnings("unchecked")
+        public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable {
+            Class returnType = method.getReturnType();
+            if (returnType.equals(Boolean.class) || 
returnType.equals(Boolean.TYPE)) {
+                return DEFAULT_BOOLEAN;
+            }
+            else if (returnType.equals(Byte.class) || 
returnType.equals(Byte.TYPE)) {
+                return DEFAULT_BYTE;
+            }
+            else if (returnType.equals(Short.class) || 
returnType.equals(Short.TYPE)) {
+                return DEFAULT_SHORT;
+            }
+            else if (returnType.equals(Integer.class) || 
returnType.equals(Integer.TYPE)) {
+                return DEFAULT_INT;
+            }
+            else if (returnType.equals(Long.class) || 
returnType.equals(Long.TYPE)) {
+                return DEFAULT_LONG;
+            }
+            else if (returnType.equals(Float.class) || 
returnType.equals(Float.TYPE)) {
+                return DEFAULT_FLOAT;
+            }
+            else if (returnType.equals(Double.class) || 
returnType.equals(Double.TYPE)) {
+                return DEFAULT_DOUBLE;
+            }
+            else {
+                return null;
+            }
+        }
+    }
+}

Modified: trunk/platform-bundles/tenant-service/pom.xml
==============================================================================
--- trunk/platform-bundles/tenant-service/pom.xml       (original)
+++ trunk/platform-bundles/tenant-service/pom.xml       Tue Oct 19 09:57:11 2010
@@ -18,7 +18,7 @@
     <dependency>
       <groupId>org.amdatu.platform</groupId>
       <artifactId>cassandra-application</artifactId>
-      <version>0.0.5-SNAPSHOT</version>
+      <version>${platform.version}</version>
       <scope>provided</scope>
       <type>bundle</type>
     </dependency>
@@ -34,6 +34,13 @@
       <scope>provided</scope>
       <type>bundle</type>
     </dependency>
+    <dependency>
+      <groupId>org.amdatu.libraries</groupId>
+      <artifactId>amdatu-utilities</artifactId>
+      <version>${platform.version}</version>
+      <scope>compile</scope>
+      <type>jar</type>
+    </dependency>    
   </dependencies>
   
   <build>

Copied: 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantDAO.java
 (from r179, 
/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/TenantDAO.java
      (original)
+++ 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantDAO.java
       Tue Oct 19 09:57:11 2010
@@ -19,6 +19,7 @@
 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.

Copied: 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java
 (from r179, 
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java)
==============================================================================
--- 
/trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java
     (original)
+++ 
trunk/platform-bundles/tenant-service/src/main/java/org/amdatu/platform/tenant/TenantImpl.java
      Tue Oct 19 09:57:11 2010
@@ -20,6 +20,7 @@
 import java.util.Map;
 
 
+
 public class TenantImpl implements Tenant {
     // The id of the tenant
     private String m_id;

Added: 
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/InMemoryTenantDAO.java
==============================================================================
--- (empty file)
+++ 
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/InMemoryTenantDAO.java
     Tue Oct 19 09:57:11 2010
@@ -0,0 +1,103 @@
+/*
+ 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.test.unit;
+
+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 provided an in-memory implementation of the TenantDAO, used 
for unit testing.
+ * @author ivol
+ */
+public class InMemoryTenantDAO implements TenantDAO {
+    // list of in-moemory tenants
+    private List<Tenant> m_tenants = new ArrayList<Tenant>();
+
+    /**
+     * @see TenantDAO#create(String, String)
+     */
+    public Tenant create(String id, String name) throws TenantException {
+        try {
+            read(id);
+        }
+        catch (TenantException e) {
+            TenantImpl tenant = new TenantImpl(id, name, new HashMap<String, 
String>());
+            m_tenants.add(tenant);
+            return copy(tenant);
+        }
+        throw new TenantException("Tenant with id " + id + " already exists");
+    }
+
+    /**
+     * @see TenantDAO#readAll()
+     */
+    public List<Tenant> readAll() throws TenantException {
+        List<Tenant> tenantCopy = new ArrayList<Tenant>();
+        for (Tenant tenant : m_tenants) {
+            tenantCopy.add(copy(tenant));
+        }
+        return tenantCopy;
+    }
+
+    /**
+     * @see TenantDAO#read(String)
+     */
+    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");
+    }
+
+    /**
+     * @see TenantDAO#update(Tenant)
+     */
+    public void update(Tenant tenant) throws TenantException {
+        Tenant t = read(tenant.getId());
+        t.setName(tenant.getName());
+    }
+
+    /**
+     * @see TenantDAO#delete(Tenant)
+     */
+    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");
+    }
+
+    /**
+     * Copies a tenant.
+     * @param tenant The tenant to copy
+     * @return the copied tenant
+     */
+    private Tenant copy(Tenant tenant) {
+        return new TenantImpl(tenant.getId(), tenant.getName(), 
tenant.getProperties());
+    }
+}

Added: 
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/TenantManagementServiceTest.java
==============================================================================
--- (empty file)
+++ 
trunk/platform-bundles/tenant-service/src/test/java/org/amdatu/test/unit/TenantManagementServiceTest.java
   Tue Oct 19 09:57:11 2010
@@ -0,0 +1,116 @@
+/*
+ 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.test.unit;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.Assert;
+
+import org.amdatu.libraries.utilities.TestUtil;
+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.service.TenantManagementServiceImpl;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+
+/**
+ * This class provides a Unit test for testing the Tenant Management Service.
+ * @author ivol
+ */
+public class TenantManagementServiceTest {
+    /**
+     * Run the unit test.
+     */
+    @Test
+    public void run() {
+        // Instantiate the Tenant management service to test
+        TenantDAO tenantDAO = new InMemoryTenantDAO();
+        TenantManagementService tenantService = new 
TenantManagementServiceImpl();
+        TestUtil.configureObject(tenantService, LogService.class, 
TestUtil.createNullObject(LogService.class));
+        TestUtil.configureObject(tenantService, TenantDAO.class, tenantDAO);
+        TestUtil.configureObject(tenantService, DependencyManager.class, new 
DependencyManager(TestUtil.createNullObject(BundleContext.class)));
+        
+        try {
+            // Verify that there are no tenants available right now
+            Tenant[] allTenants = tenantService.getAllTenants();
+            Assert
+            .assertTrue("There are already tenants present in the storage",
+                tenantService.getAllTenants().length == 0);
+
+            // Create and update a tenant and verify that it has been added
+            int tenantCount = allTenants.length;
+            Tenant tenant = 
tenantService.createTentant("org.amdatu.test.integration.tests.testtenant", 
"TEST");
+            tenantService.updateTenant(tenant);
+            Assert.assertTrue("Added and updated 1 tenant, but the Tenant 
service now holds "
+                + tenantService.getAllTenants().length + " tenants, expected: 
" + (tenantCount + 1), tenantService
+                .getAllTenants().length == tenantCount + 1);
+
+            // Try to add a tenant with the same id, this should throw an 
exception
+            try {
+                
tenantService.createTentant("org.amdatu.test.integration.tests.testtenant", 
"sdfsdfd");
+                Assert.assertTrue("Tenant with the same id could be created 
twice", false);
+            }
+            catch (TenantException e) {
+            }
+
+            // Delete the tenant and check if it has been removed
+            tenantService.deleteTenant(tenant);
+            Assert.assertTrue(tenantService.getAllTenants().length == 
tenantCount);
+
+            // Create and update three tenants
+            Tenant tenant1 = 
tenantService.createTentant("org.amdatu.test.integration.tests.testtenant.1", 
"TEST 1");
+            Tenant tenant2 = 
tenantService.createTentant("org.amdatu.test.integration.tests.testtenant.2", 
"TEST 2");
+            Tenant tenant3 = 
tenantService.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");
+            tenantService.updateTenant(tenant1);
+            tenantService.updateTenant(tenant2);
+            tenantService.updateTenant(tenant3);
+
+            // Check if the filter works correct
+            Map<String, String> filter = new HashMap<String, String>();
+            filter.put("hostname", "localhost");
+            Assert.assertTrue(tenantService.getTenants(filter).length == 2);
+            filter.put("hostname", "amdatu.org");
+            Assert.assertTrue(tenantService.getTenants(filter).length == 1);
+
+            // Delete the tenants, now all tenants should be removed
+            tenantService.deleteTenant(tenant1);
+            tenantService.deleteTenant(tenant2);
+            tenantService.deleteTenant(tenant3);
+            Assert.assertTrue(tenantService.getAllTenants().length == 0);
+            
+            // What happens if I remove a tenant that was already removed? 
This should throw an exception
+            try {
+                tenantService.deleteTenant(tenant);
+                Assert.fail("Tenant with the same id could be deleted twice");
+            }
+            catch (TenantException e) {
+            }
+        }
+        catch (TenantException e) {
+            Assert.fail("An error has occurred: " + e.toString());
+            e.printStackTrace();
+        }
+    }   
+}

Reply via email to