From 9fbba5a5e0668e1ecc65cbb48cf9ee4b3dc5fabf Mon Sep 17 00:00:00 2001 From: Neil McErlean Date: Thu, 29 Aug 2013 13:15:35 +0000 Subject: [PATCH] Merged BRANCHES/DEV/V4.1-BUG-FIX to HEAD: 54638: As part of work investigating ALF-19783 I have created a test case. I'm checking this in on 4.1 bugfix (where the issue is not reported) Merged BRANCHES/DEV/V4.1-BUG-FIX to HEAD: 54640: (RECORD ONLY) (Part of prep work for ALF-19783) Moving a test class to the correct source tree. Note that in doing the record-only merge above, the file ScriptNodeTest had been created on V4.1-BUG-FIX *and* on HEAD independently. So I got a tree conflict in merging 54640 to HEAD as this attempted to svn mv ScriptNodeTest on top of HEAD's existing copy of that file. So instead, I manually resolved the conflict by merging the two files. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@54646 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../version/common/VersionHistoryImpl.java | 20 ++ .../alfresco/repo/jscript/ScriptNodeTest.java | 200 +++++++++++++++++- 2 files changed, 213 insertions(+), 7 deletions(-) diff --git a/source/java/org/alfresco/repo/version/common/VersionHistoryImpl.java b/source/java/org/alfresco/repo/version/common/VersionHistoryImpl.java index c5d8a03b5c..52ae444826 100644 --- a/source/java/org/alfresco/repo/version/common/VersionHistoryImpl.java +++ b/source/java/org/alfresco/repo/version/common/VersionHistoryImpl.java @@ -273,4 +273,24 @@ public class VersionHistoryImpl implements VersionHistory this.versionComparatorDesc = (Comparator) fields.get("versionComparatorDesc", null); } } + + /** + * @since 4.1.7 + */ + @Override public String toString() + { + // The toString result looks something like: "VersionHistoryImpl [1] , { '0.1', tail... }" + final Collection allVersions = getAllVersions(); + + final StringBuilder msg = new StringBuilder(); + + msg.append(VersionHistoryImpl.class.getSimpleName()) + .append(" [") .append(allVersions.size()) .append("] "); + if ( !allVersions.isEmpty()) + { + msg.append(", { '") .append(getHeadVersion().getVersionLabel()) .append("', tail... }"); + } + + return msg.toString(); + } } diff --git a/source/test-java/org/alfresco/repo/jscript/ScriptNodeTest.java b/source/test-java/org/alfresco/repo/jscript/ScriptNodeTest.java index c4d0106344..4a86747256 100644 --- a/source/test-java/org/alfresco/repo/jscript/ScriptNodeTest.java +++ b/source/test-java/org/alfresco/repo/jscript/ScriptNodeTest.java @@ -20,19 +20,32 @@ package org.alfresco.repo.jscript; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import java.util.List; + +import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.model.Repository; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.security.permissions.PermissionServiceSPI; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.version.VersionableAspect; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.service.cmr.version.Version; +import org.alfresco.service.cmr.version.VersionHistory; +import org.alfresco.service.cmr.version.VersionService; import org.alfresco.util.GUID; import org.alfresco.util.test.junitrules.AlfrescoPerson; import org.alfresco.util.test.junitrules.ApplicationContextInit; @@ -41,19 +54,26 @@ import org.alfresco.util.test.junitrules.RunAsFullyAuthenticatedRule.RunAsUser; import org.alfresco.util.test.junitrules.TemporaryNodes; import org.alfresco.util.test.junitrules.TemporarySites; import org.alfresco.util.test.junitrules.TemporarySites.TestSiteAndMemberInfo; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.RuleChain; +import org.junit.rules.TestName; /** * @author Neil Mc Erlean - * @since 4.2 + * @since 4.1.7, 4.2 */ public class ScriptNodeTest { + private static Log log = LogFactory.getLog(ScriptNodeTest.class); + // Rule to initialise the default Alfresco spring configuration public static ApplicationContextInit APP_CONTEXT_INIT = new ApplicationContextInit(); @@ -76,27 +96,64 @@ public class ScriptNodeTest .around(TEST_USER1) .around(TEST_USER2); + @Rule public final TestName testName = new TestName(); + + // A JUnit Rule to manage test nodes use in each test method + public TemporaryNodes testNodes = new TemporaryNodes(APP_CONTEXT_INIT); + // A rule to allow individual test methods all to be run as "UserOne". @Rule public RunAsFullyAuthenticatedRule runAsRule = new RunAsFullyAuthenticatedRule(TEST_USER1); - + + // Tie them together in a non-static rule chain. + @Rule public RuleChain ruleChain = RuleChain.outerRule(runAsRule) + .around(testNodes); + // Various services + private static ContentService CONTENT_SERVICE; private static NodeService NODE_SERVICE; + private static ServiceRegistry SERVICE_REGISTRY; private static RetryingTransactionHelper TRANSACTION_HELPER; private static PermissionServiceSPI PERMISSION_SERVICE; private static Search SEARCH_SCRIPT; + private static VersionableAspect VERSIONABLE_ASPECT; + private static VersionService VERSION_SERVICE; private static TestSiteAndMemberInfo USER_ONES_TEST_SITE; private static NodeRef USER_ONES_TEST_FILE; + private List excludedOnUpdateProps; + private NodeRef testNode; + @BeforeClass public static void initStaticData() throws Exception { - NODE_SERVICE = (NodeService) APP_CONTEXT_INIT.getApplicationContext().getBean("NodeService"); - TRANSACTION_HELPER = (RetryingTransactionHelper) APP_CONTEXT_INIT.getApplicationContext().getBean("retryingTransactionHelper"); - PERMISSION_SERVICE = (PermissionServiceSPI) APP_CONTEXT_INIT.getApplicationContext().getBean("permissionService"); - SEARCH_SCRIPT = (Search) APP_CONTEXT_INIT.getApplicationContext().getBean("searchScript"); + CONTENT_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("ContentService", ContentService.class); + NODE_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("NodeService", NodeService.class); + SERVICE_REGISTRY = APP_CONTEXT_INIT.getApplicationContext().getBean("ServiceRegistry", ServiceRegistry.class); + TRANSACTION_HELPER = APP_CONTEXT_INIT.getApplicationContext().getBean("retryingTransactionHelper", RetryingTransactionHelper.class); + PERMISSION_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("permissionService", PermissionServiceSPI.class); + SEARCH_SCRIPT = APP_CONTEXT_INIT.getApplicationContext().getBean("searchScript", Search.class); + VERSIONABLE_ASPECT = APP_CONTEXT_INIT.getApplicationContext().getBean("versionableAspect", VersionableAspect.class); + VERSION_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("VersionService", VersionService.class); USER_ONES_TEST_SITE = STATIC_TEST_SITES.createTestSiteWithUserPerRole(GUID.generate(), "sitePreset", SiteVisibility.PRIVATE, USER_ONE_NAME); - USER_ONES_TEST_FILE = STATIC_TEST_NODES.createQuickFile(MimetypeMap.MIMETYPE_TEXT_PLAIN, USER_ONES_TEST_SITE.doclib, "test.txt", USER_ONE_NAME); + USER_ONES_TEST_FILE = STATIC_TEST_NODES.createQuickFile(MimetypeMap.MIMETYPE_TEXT_PLAIN, USER_ONES_TEST_SITE.doclib, "test.txt", USER_ONE_NAME); + } + + @Before public void createTestContent() + { + Repository repositoryHelper = (Repository) APP_CONTEXT_INIT.getApplicationContext().getBean("repositoryHelper"); + NodeRef companyHome = repositoryHelper.getCompanyHome(); + + // Create some test content + testNode = testNodes.createQuickFile(MimetypeMap.MIMETYPE_TEXT_PLAIN, companyHome, "userOnesDoc", TEST_USER1.getUsername(), true); + + excludedOnUpdateProps = VERSIONABLE_ASPECT.getExcludedOnUpdateProps(); + } + + @After public void versionableAspectTearDown() + { + VERSIONABLE_ASPECT.setExcludedOnUpdateProps(excludedOnUpdateProps); + VERSIONABLE_ASPECT.afterDictionaryInit(); } @Test(expected=AccessDeniedException.class) @@ -160,4 +217,133 @@ public class ScriptNodeTest AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); PERMISSION_SERVICE.clearPermission(USER_ONES_TEST_FILE, USER_TWO_NAME); } + + /** See ALF-19783. */ + @Test public void versionNumberShouldIncrementOnNodeRevert() + { + log.debug(testName.getMethodName() + "()"); + + // We've already got a test node set up. Let's see what its content is so we can ensure that the revert works. + final String originalContent = TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() + { + public String execute() throws Throwable + { + return CONTENT_SERVICE.getReader(testNode, ContentModel.PROP_CONTENT).getContentString(); + } + }); + log.debug("Test node's original content is: '" + originalContent + "'"); + + + // This is the content we'll be updating it with. + final String updatedContent = "If a tree falls in a forest and there is no one there to hear it, will it make a sound?"; + + // Let's do some basic sanity checking on this initial version. + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + VersionHistory history = VERSION_SERVICE.getVersionHistory(testNode); + log.debug("Node version history: " + history); + + Version version1_0 = history.getHeadVersion(); + + assertEquals("Incorrect version label", version1_0.getVersionLabel(), history.getHeadVersion().getVersionLabel()); + assertEquals("Incorrect head version node", version1_0.getVersionedNodeRef(), history.getHeadVersion().getVersionedNodeRef()); + assertEquals("Incorrect history size", 1, history.getAllVersions().size()); + + Version[] versions = history.getAllVersions().toArray(new Version[0]); + assertEquals("Incorrect version label", "1.0", versions[0].getVersionLabel()); + assertEquals("Incorrect version label", "1.0", NODE_SERVICE.getProperty(testNode, ContentModel.PROP_VERSION_LABEL)); + + return null; + } + }); + + final Version version1_1 = TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() + { + public Version execute() throws Throwable + { + // Now let's change the content value... + ContentWriter contentWriter = CONTENT_SERVICE.getWriter(testNode, ContentModel.PROP_CONTENT, true); + assertNotNull(contentWriter); + contentWriter.putContent(updatedContent); + + // ... and record this as a new version of the node + return VERSION_SERVICE.createVersion(testNode, null); + } + }); + log.debug("Stored next version of node: " + version1_1.getVersionLabel()); + + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + // Check we're now seeing both versions in the history + VersionHistory history = VERSION_SERVICE.getVersionHistory(testNode); + log.debug("Node version history: " + history); + assertEquals(version1_1.getVersionLabel(), history.getHeadVersion().getVersionLabel()); + assertEquals(version1_1.getVersionedNodeRef(), history.getHeadVersion().getVersionedNodeRef()); + assertEquals(2, history.getAllVersions().size()); + + Version[] versions = history.getAllVersions().toArray(new Version[0]); + assertEquals("1.1", versions[0].getVersionLabel()); + assertEquals("1.0", versions[1].getVersionLabel()); + assertEquals("1.1", NODE_SERVICE.getProperty(testNode, ContentModel.PROP_VERSION_LABEL)); + + return null; + } + }); + + // Now we'll revert the node to a specific, named previous version. + // Note: we're doing this through a call to scriptNode.revert(...) as that is what Share does via revert.post.desc.xml + // A straight call to VERSION_SERVICE.revert(testNode, version1_0); would not work here as ScriptNode.revert also adds a checkout/checkin call to the revert. + // Rather than reproduce what ScriptNode does in this class, we'll just call ScriptNode.revert + + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + log.debug("Reverting versionable node to version 1.0 ..."); + + ScriptNode sn = new ScriptNode(testNode, SERVICE_REGISTRY); + sn.revert("", false, "1.0"); + + return null; + } + }); + + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + // Check that the version label is correct + assertEquals("1.2", NODE_SERVICE.getProperty(testNode, ContentModel.PROP_VERSION_LABEL)); + + // Check that the content is correct + ContentReader contentReader = CONTENT_SERVICE.getReader(testNode, ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals(originalContent, contentReader.getContentString()); + + // Check the history still has 3 versions + // The head version is now 1.2 + VersionHistory history = VERSION_SERVICE.getVersionHistory(testNode); + log.debug("Node version history: " + history); + for (Version v : history.getAllVersions()) { log.debug(v.getVersionLabel()); } + + final Version version1_2 = history.getHeadVersion(); + + assertEquals(version1_2.getVersionLabel(), history.getHeadVersion().getVersionLabel()); + assertEquals(version1_2.getVersionedNodeRef(), history.getHeadVersion().getVersionedNodeRef()); + assertEquals(3, history.getAllVersions().size()); + + Version[] versions = history.getAllVersions().toArray(new Version[0]); + assertEquals("1.2", versions[0].getVersionLabel()); + assertEquals("1.1", versions[1].getVersionLabel()); + assertEquals("1.0", versions[2].getVersionLabel()); + + assertEquals("1.2", history.getHeadVersion().getVersionLabel()); + return null; + } + }); + } }