mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged BRANCHES/V4.1 to HEAD:
40010: Enhancement to TemporaryNodes JUnit @Rule so that it gracefully handles checked-out nodes during test code. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@40012 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -31,6 +31,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
@@ -41,12 +42,13 @@ import org.alfresco.service.namespace.QName;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.junit.rules.ExternalResource;
|
import org.junit.rules.ExternalResource;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JUnit rule designed to help with the automatic cleanup of temporary test nodes.
|
* A JUnit rule designed to help with the automatic cleanup of temporary test nodes.
|
||||||
*
|
*
|
||||||
* @author Neil Mc Erlean
|
* @author Neil Mc Erlean
|
||||||
* @since Odin
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public class TemporaryNodes extends ExternalResource
|
public class TemporaryNodes extends ExternalResource
|
||||||
{
|
{
|
||||||
@@ -73,8 +75,11 @@ public class TemporaryNodes extends ExternalResource
|
|||||||
|
|
||||||
@Override protected void after()
|
@Override protected void after()
|
||||||
{
|
{
|
||||||
final RetryingTransactionHelper transactionHelper = (RetryingTransactionHelper) appContextRule.getApplicationContext().getBean("retryingTransactionHelper");
|
final ApplicationContext springContext = appContextRule.getApplicationContext();
|
||||||
final NodeService nodeService = (NodeService) appContextRule.getApplicationContext().getBean("nodeService");
|
|
||||||
|
final RetryingTransactionHelper transactionHelper = springContext.getBean("retryingTransactionHelper", RetryingTransactionHelper.class);
|
||||||
|
final CheckOutCheckInService cociService = springContext.getBean("CheckOutCheckInService", CheckOutCheckInService.class);
|
||||||
|
final NodeService nodeService = springContext.getBean("NodeService", NodeService.class);
|
||||||
|
|
||||||
// Run as admin to ensure all non-system nodes can be deleted irrespecive of which user created them.
|
// Run as admin to ensure all non-system nodes can be deleted irrespecive of which user created them.
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||||
@@ -88,8 +93,16 @@ public class TemporaryNodes extends ExternalResource
|
|||||||
// Although we loop through all nodes, this is a cascade-delete and so we may only need to delete the first node.
|
// Although we loop through all nodes, this is a cascade-delete and so we may only need to delete the first node.
|
||||||
for (NodeRef node : temporaryNodeRefs)
|
for (NodeRef node : temporaryNodeRefs)
|
||||||
{
|
{
|
||||||
|
// If it's already been deleted, don't worry about it.
|
||||||
if (nodeService.exists(node))
|
if (nodeService.exists(node))
|
||||||
{
|
{
|
||||||
|
// If it has been checked out, cancel the checkout before deletion.
|
||||||
|
if (cociService.isCheckedOut(node))
|
||||||
|
{
|
||||||
|
log.debug("Cancelling checkout of temporary node " + nodeService.getProperty(node, ContentModel.PROP_NAME));
|
||||||
|
NodeRef workingCopy = cociService.getWorkingCopy(node);
|
||||||
|
cociService.cancelCheckout(workingCopy);
|
||||||
|
}
|
||||||
log.debug("Deleting temporary node " + nodeService.getProperty(node, ContentModel.PROP_NAME));
|
log.debug("Deleting temporary node " + nodeService.getProperty(node, ContentModel.PROP_NAME));
|
||||||
nodeService.deleteNode(node);
|
nodeService.deleteNode(node);
|
||||||
}
|
}
|
||||||
@@ -100,7 +113,7 @@ public class TemporaryNodes extends ExternalResource
|
|||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, AuthenticationUtil.getAdminUserName());
|
}, AuthenticationUtil.getSystemUserName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -22,8 +22,11 @@ package org.alfresco.util.test.junitrules;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
@@ -31,6 +34,7 @@ import org.alfresco.repo.model.Repository;
|
|||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
@@ -46,8 +50,8 @@ import org.junit.rules.RuleChain;
|
|||||||
/**
|
/**
|
||||||
* Test class for {@link TemporaryNodes}.
|
* Test class for {@link TemporaryNodes}.
|
||||||
*
|
*
|
||||||
* @author Neil McErlean
|
* @author Neil Mc Erlean
|
||||||
* @since Odin
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public class TemporaryNodesTest
|
public class TemporaryNodesTest
|
||||||
{
|
{
|
||||||
@@ -74,6 +78,7 @@ public class TemporaryNodesTest
|
|||||||
@Rule public RunAsFullyAuthenticatedRule runAsRule = new RunAsFullyAuthenticatedRule(AuthenticationUtil.getAdminUserName());
|
@Rule public RunAsFullyAuthenticatedRule runAsRule = new RunAsFullyAuthenticatedRule(AuthenticationUtil.getAdminUserName());
|
||||||
|
|
||||||
// Various services
|
// Various services
|
||||||
|
private static CheckOutCheckInService COCI_SERVICE;
|
||||||
private static ContentService CONTENT_SERVICE;
|
private static ContentService CONTENT_SERVICE;
|
||||||
private static NodeService NODE_SERVICE;
|
private static NodeService NODE_SERVICE;
|
||||||
private static RetryingTransactionHelper TRANSACTION_HELPER;
|
private static RetryingTransactionHelper TRANSACTION_HELPER;
|
||||||
@@ -85,6 +90,7 @@ public class TemporaryNodesTest
|
|||||||
|
|
||||||
@BeforeClass public static void initStaticData() throws Exception
|
@BeforeClass public static void initStaticData() throws Exception
|
||||||
{
|
{
|
||||||
|
COCI_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("checkOutCheckInService", CheckOutCheckInService.class);
|
||||||
CONTENT_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("contentService", ContentService.class);
|
CONTENT_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("contentService", ContentService.class);
|
||||||
NODE_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("nodeService", NodeService.class);
|
NODE_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("nodeService", NodeService.class);
|
||||||
TRANSACTION_HELPER = APP_CONTEXT_INIT.getApplicationContext().getBean("retryingTransactionHelper", RetryingTransactionHelper.class);
|
TRANSACTION_HELPER = APP_CONTEXT_INIT.getApplicationContext().getBean("retryingTransactionHelper", RetryingTransactionHelper.class);
|
||||||
@@ -131,4 +137,57 @@ public class TemporaryNodesTest
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void ensureCheckedOutNodesAreCleanedUp() throws Throwable
|
||||||
|
{
|
||||||
|
// Note that because we need to test that the Rule's 'after' behaviour has worked correctly, we cannot
|
||||||
|
// use the Rule that has been declared in the normal way - otherwise nothing would be cleaned up until
|
||||||
|
// after our test method.
|
||||||
|
// Therefore we have to manually poke the Rule to get it to cleanup during test execution.
|
||||||
|
// NOTE! This is *not* how a JUnit Rule would normally be used.
|
||||||
|
TemporaryNodes myTemporaryNodes = new TemporaryNodes(APP_CONTEXT_INIT);
|
||||||
|
|
||||||
|
// Currently this is a no-op, but just in case that changes.
|
||||||
|
myTemporaryNodes.before();
|
||||||
|
|
||||||
|
|
||||||
|
// Create some test nodes.
|
||||||
|
final List<NodeRef> nodesThatShouldBeDeletedByRule = new ArrayList<NodeRef>();
|
||||||
|
|
||||||
|
nodesThatShouldBeDeletedByRule.add(myTemporaryNodes.createNode(COMPANY_HOME, "normal node", ContentModel.TYPE_CONTENT, TEST_USER1.getUsername()));
|
||||||
|
final NodeRef checkedoutNode = myTemporaryNodes.createNode(COMPANY_HOME, "checkedout node", ContentModel.TYPE_CONTENT, TEST_USER1.getUsername());
|
||||||
|
nodesThatShouldBeDeletedByRule.add(checkedoutNode);
|
||||||
|
|
||||||
|
// and check one of them out.
|
||||||
|
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
NodeRef workingCopy = COCI_SERVICE.checkout(checkedoutNode);
|
||||||
|
|
||||||
|
// Ensure that the working copy is cleaned up too.
|
||||||
|
nodesThatShouldBeDeletedByRule.add(workingCopy);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now trigger the Rule's cleanup behaviour.
|
||||||
|
myTemporaryNodes.after();
|
||||||
|
|
||||||
|
// and ensure that the nodes are all gone.
|
||||||
|
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
for (NodeRef node : nodesThatShouldBeDeletedByRule)
|
||||||
|
{
|
||||||
|
if (NODE_SERVICE.exists(node))
|
||||||
|
{
|
||||||
|
fail("Node '" + NODE_SERVICE.getProperty(node, ContentModel.PROP_NAME) + "' still exists.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user