/* * Copyright (C) 2005-2010 Alfresco Software Limited. * * This file is part of Alfresco * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ package org.alfresco; import java.lang.reflect.Field; import net.sf.ehcache.CacheManager; import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.BaseApplicationContextHelper; import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import junit.framework.TestCase; /** * A unit test that verifies it's possible to start up the main * Alfresco context, stop it, start a different context, * stop that, and finally return to the main context. * To do a basic check of if the repository works, use * {@link RepositoryStartupTest}. * This test allows you to verify that your context * is able to shut down cleanly, as well as that the * minimal context is able to do the same. * * As this test opens and closes lots of contexts, * it is rather slow.... * * @author Nick Burch */ public class RepositoryStartStopTest extends TestCase { private ServiceRegistry serviceRegistry; private TransactionService transactionService; private boolean writeTestWorked; public void setUp() throws Exception { // Ensure there's nothing kicking about ApplicationContextHelper.closeApplicationContext(); } public void tearDown() throws Exception { AuthenticationUtil.clearCurrentSecurityContext(); } /** * Checks that the ApplicationContext cache on the * ApplicationContextHelper is empty */ public static void assertNoCachedApplicationContext() throws Exception { Field instanceF = BaseApplicationContextHelper.class.getDeclaredField("instance"); instanceF.setAccessible(true); assertNull( "Instance cache on ApplicationContextHelper was populated instead of empty", instanceF.get(null) ); } /** * Checks that all our EHCache instances have been shutdown */ public static void assertAllCachesShutdown() throws Exception { assertEquals( "All Caches should have been shut down, but some remained", 0, CacheManager.ALL_CACHE_MANAGERS.size() ); } private ApplicationContext getMinimalContext() { ApplicationContextHelper.setUseLazyLoading(false); ApplicationContextHelper.setNoAutoStart(true); return ApplicationContextHelper.getApplicationContext( new String[] { "classpath:alfresco/minimal-context.xml" } ); } private ApplicationContext getFullContext() { ApplicationContextHelper.setUseLazyLoading(false); ApplicationContextHelper.setNoAutoStart(false); return ApplicationContextHelper.getApplicationContext( new String[] { "classpath:alfresco/application-context.xml" } ); } /** * Tests that we can open a context, use * it, and then close it again without error */ public void testOpenClose() throws Exception { assertNoCachedApplicationContext(); ApplicationContext ctx = getMinimalContext(); assertNotNull(ctx); doTestBasicWriteOperations(ctx); ApplicationContextHelper.closeApplicationContext(); assertNoCachedApplicationContext(); assertAllCachesShutdown(); } /** * Using a minimal no-autostart context: * Test that we can bring up and close down * a context twice without error, using it * when running. */ public void testOpenCloseOpenCloseNoAutostart() throws Exception { assertNoCachedApplicationContext(); // Open it, and use it ApplicationContext ctx = getMinimalContext(); assertNotNull(ctx); doTestBasicWriteOperations(ctx); // Close it down ApplicationContextHelper.closeApplicationContext(); assertNoCachedApplicationContext(); assertAllCachesShutdown(); // Re-open it, we get a fresh copy ApplicationContext ctx2 = getMinimalContext(); assertNotNull(ctx2); doTestBasicWriteOperations(ctx2); assertNotSame(ctx, ctx2); // Ask for it again, will be no change this time ctx = getMinimalContext(); assertEquals(ctx, ctx2); // And finally close it ApplicationContextHelper.closeApplicationContext(); assertNoCachedApplicationContext(); assertAllCachesShutdown(); } /** * Using a full autostarting context: * Test that we can bring up and close down * a context twice without error, using it * when running. */ public void testOpenCloseOpenCloseFull() throws Exception { assertNoCachedApplicationContext(); // Open it, and use it ApplicationContext ctx = getFullContext(); assertNotNull(ctx); doTestBasicWriteOperations(ctx); // Close it down ApplicationContextHelper.closeApplicationContext(); assertNoCachedApplicationContext(); assertAllCachesShutdown(); // Re-open it, we get a fresh copy ApplicationContext ctx2 = getFullContext(); assertNotNull(ctx2); doTestBasicWriteOperations(ctx2); // Ask for it again, will be no change this time ctx = getFullContext(); assertEquals(ctx, ctx2); // Refresh it, shouldn't break anything ((AbstractApplicationContext)ctx).refresh(); // And finally close it ApplicationContextHelper.closeApplicationContext(); assertNoCachedApplicationContext(); assertAllCachesShutdown(); } /** * Tests that we can open a context, use it, * close it, and open a different one. * Does this by opening and closing contexts * 4 different times, sometimes full ones, * sometimes minimal ones with no autostart. */ public void testOpenCloseRepeatedly() throws Exception { assertNoCachedApplicationContext(); // Open the minimal one and test ApplicationContext ctx = getMinimalContext(); assertNotNull(ctx); doTestBasicWriteOperations(ctx); // Close ApplicationContextHelper.closeApplicationContext(); assertNoCachedApplicationContext(); assertAllCachesShutdown(); // Now open the full one ctx = getFullContext(); assertNotNull(ctx); doTestBasicWriteOperations(ctx); // Ask for it again, will get the same thing ApplicationContext ctxSav = ctx; ctx = getFullContext(); assertEquals(ctx, ctxSav); // Close it ApplicationContextHelper.closeApplicationContext(); assertNoCachedApplicationContext(); assertAllCachesShutdown(); // Back to the minimal one ctx = getMinimalContext(); assertNotNull(ctx); doTestBasicWriteOperations(ctx); // Close ApplicationContextHelper.closeApplicationContext(); assertNoCachedApplicationContext(); assertAllCachesShutdown(); // And finally we want the full one again ctx = getFullContext(); assertNotNull(ctx); doTestBasicWriteOperations(ctx); // Close and we're done ApplicationContextHelper.closeApplicationContext(); assertNoCachedApplicationContext(); assertAllCachesShutdown(); } public void doTestBasicWriteOperations(ApplicationContext ctx) throws Exception { // Grab the beans we need serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); transactionService = serviceRegistry.getTransactionService(); // So we can write test nodes AuthenticationUtil.setRunAsUserSystem(); // Check it looks fine assertFalse("The transaction is read-only - further unit tests are pointless.", transactionService.isReadOnly()); // A basic write operation on a node RetryingTransactionCallback addPropertyCallback = new RetryingTransactionCallback() { public Void execute() throws Throwable { NodeService nodeService = serviceRegistry.getNodeService(); NodeRef rootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); nodeService.setProperty(rootNodeRef, ContentModel.PROP_NAME, "SanityCheck"); writeTestWorked = true; return null; } }; // Now do a write operation, and ensure it worked writeTestWorked = false; transactionService.getRetryingTransactionHelper().doInTransaction(addPropertyCallback, false, true); assertTrue("The Node Write didn't occur or failed with an error", writeTestWorked); } }