RM-2562: Deleting records from versions produces inconsistent behaviour

* Versions are not deleted from collab version history, rather marked as destroyed (prevents inconsistencies since we don't support deleting versions well)
 * Share UI updated to acomadate above
 * Version relationship reorganised based on changes to version record history
 * Unit tests and integration tests for above
 * some unit tests relating to RM-2194
 * Hover message on version record icon in version history

+review RM



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.3@119284 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2015-12-02 02:09:43 +00:00
parent 11e59543bd
commit f142e7647b
24 changed files with 1405 additions and 160 deletions

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2005-2015 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
import static org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel.PROP_VERSIONED_NODEREF;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionService;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
/**
* Version record aspect unit tests
*
* @author Roy Wetherall
* @since 2.3.1
*/
public class VersionRecordAspectUnitTest extends BaseUnitTest
{
/** service mocks */
private @Mock VersionHistory mockedVersionHistory;
private @Mock Version mockedVersion;
private @Mock VersionService mockedVersionService;
private @Mock RelationshipService mockedRelationshipService;
/** test object */
private @InjectMocks VersionRecordAspect versionRecordAspect;
/**
* given that version node ref is null
* before delete of record
* then nothing happens
*/
@Test
public void beforeDeleteNoVersionNodeRef()
{
NodeRef nodeRef = generateNodeRef();
when(mockedNodeService.getProperty(nodeRef, PROP_VERSIONED_NODEREF))
.thenReturn(null);
versionRecordAspect.beforeDeleteNode(nodeRef);
verify(mockedNodeService, never()).getProperty(nodeRef, RecordableVersionModel.PROP_VERSION_LABEL);
verify(mockedRecordableVersionService, never()).destroyRecordedVersion(any(Version.class));
}
/**
* given that version node ref is not null
* and version label is null
* before delete of record
* then nothing happens
*/
@Test
public void beforeDeleteNoVersionLabel()
{
NodeRef nodeRef = generateNodeRef();
NodeRef versionedNodeRef = generateNodeRef();
when(mockedNodeService.getProperty(nodeRef, PROP_VERSIONED_NODEREF))
.thenReturn(versionedNodeRef);
when(mockedNodeService.getProperty(nodeRef, RecordableVersionModel.PROP_VERSION_LABEL))
.thenReturn(null);
versionRecordAspect.beforeDeleteNode(nodeRef);
verify(mockedVersionService, never()).getVersionHistory(versionedNodeRef);
verify(mockedRecordableVersionService, never()).destroyRecordedVersion(any(Version.class));
}
/**
* given that version node ref is not null
* and version label is not null
* and version history is null
* before delete of record
* then nothing happens
*/
@Test
public void beforeDeleteNoVersionHistory()
{
NodeRef nodeRef = generateNodeRef();
NodeRef versionedNodeRef = generateNodeRef();
when(mockedNodeService.getProperty(nodeRef, PROP_VERSIONED_NODEREF))
.thenReturn(versionedNodeRef);
when(mockedNodeService.getProperty(nodeRef, RecordableVersionModel.PROP_VERSION_LABEL))
.thenReturn(generateText());
when(mockedVersionService.getVersionHistory(versionedNodeRef))
.thenReturn(null);
versionRecordAspect.beforeDeleteNode(nodeRef);
verify(mockedRecordableVersionService, never()).destroyRecordedVersion(any(Version.class));
}
/**
* given that version node ref is not null
* and version label is not null
* and version history is not null
* and the version relating to the version label is null
* before delete of record
* then nothing happens
*/
@Test
public void beforeDeleteNoVersionForLabel()
{
NodeRef nodeRef = generateNodeRef();
NodeRef versionedNodeRef = generateNodeRef();
String versionLabel = generateText();
when(mockedNodeService.getProperty(nodeRef, PROP_VERSIONED_NODEREF))
.thenReturn(versionedNodeRef);
when(mockedNodeService.getProperty(nodeRef, RecordableVersionModel.PROP_VERSION_LABEL))
.thenReturn(versionLabel);
when(mockedVersionService.getVersionHistory(versionedNodeRef))
.thenReturn(mockedVersionHistory);
when(mockedVersionHistory.getVersion(versionLabel))
.thenReturn(null);
versionRecordAspect.beforeDeleteNode(nodeRef);
verify(mockedRecordableVersionService, never()).destroyRecordedVersion(any(Version.class));
}
/**
* given that version node ref is not null
* and version label is not null
* and version history is not null
* and the version relating to the version label is not null
* before delete of record
* then the version is marked as destroyed
*/
@Test
public void beforeDeleteMarkVersionDestroyed()
{
NodeRef nodeRef = generateNodeRef();
NodeRef versionedNodeRef = generateNodeRef();
String versionLabel = generateText();
when(mockedNodeService.getProperty(nodeRef, PROP_VERSIONED_NODEREF))
.thenReturn(versionedNodeRef);
when(mockedNodeService.getProperty(nodeRef, RecordableVersionModel.PROP_VERSION_LABEL))
.thenReturn(versionLabel);
when(mockedVersionService.getVersionHistory(versionedNodeRef))
.thenReturn(mockedVersionHistory);
when(mockedVersionHistory.getVersion(versionLabel))
.thenReturn(mockedVersion);
versionRecordAspect.beforeDeleteNode(nodeRef);
verify(mockedRecordableVersionService).destroyRecordedVersion(mockedVersion);
}
}

View File

@@ -18,33 +18,9 @@
*/
package org.alfresco.module.org_alfresco_module_rm.test;
import org.alfresco.module.org_alfresco_module_rm.action.dm.DeclareAsVersionRecordActionUnitTest;
import org.alfresco.module.org_alfresco_module_rm.action.impl.FileReportActionUnitTest;
import org.alfresco.module.org_alfresco_module_rm.action.impl.UnlinkFromActionUnitTest;
import org.alfresco.module.org_alfresco_module_rm.bootstrap.BootstrapImporterModuleComponentUnitTest;
import org.alfresco.module.org_alfresco_module_rm.bootstrap.RecordContributorsGroupBootstrapComponentUnitTest;
import org.alfresco.module.org_alfresco_module_rm.capability.RMEntryVoterUnitTest;
import org.alfresco.module.org_alfresco_module_rm.capability.declarative.condition.CapabilityDeclarativeConditionSuite;
import org.alfresco.module.org_alfresco_module_rm.capability.impl.EditNonRecordsMetadataCapabilityUnitTest;
import org.alfresco.module.org_alfresco_module_rm.forms.RecordsManagementTypeFormFilterUnitTest;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldServiceImplUnitTest;
import org.alfresco.module.org_alfresco_module_rm.job.DispositionLifecycleJobExecuterUnitTest;
import org.alfresco.module.org_alfresco_module_rm.jscript.app.evaluator.FrozenEvaluatorUnitTest;
import org.alfresco.module.org_alfresco_module_rm.jscript.app.evaluator.TransferEvaluatorUnitTest;
import org.alfresco.module.org_alfresco_module_rm.model.compatibility.DictionaryBootstrapPostProcessorUnitTest;
import org.alfresco.module.org_alfresco_module_rm.patch.v22.PatchV22Suite;
import org.alfresco.module.org_alfresco_module_rm.record.RecordMetadataBootstrapUnitTest;
import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImplUnitTest;
import org.alfresco.module.org_alfresco_module_rm.recorded.version.config.RecordedVersionConfigGetTest;
import org.alfresco.module.org_alfresco_module_rm.recorded.version.config.RecordedVersionConfigPostTest;
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPostUnitTest;
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPutUnitTest;
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldsGetUnitTest;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImplUnitTest;
import org.alfresco.repo.action.parameter.DateParameterProcessorUnitTest;
import org.junit.extensions.cpsuite.ClasspathSuite;
import org.junit.extensions.cpsuite.ClasspathSuite.ClassnameFilters;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
/**
* All unit test suite.
@@ -52,51 +28,12 @@ import org.junit.runners.Suite.SuiteClasses;
* @author Roy Wetherall
* @since 2.2
*/
@RunWith(Suite.class)
@SuiteClasses(
{
RecordMetadataBootstrapUnitTest.class,
RecordsManagementTypeFormFilterUnitTest.class,
DispositionLifecycleJobExecuterUnitTest.class,
DictionaryBootstrapPostProcessorUnitTest.class,
DateParameterProcessorUnitTest.class,
RMEntryVoterUnitTest.class,
// services
RecordServiceImplUnitTest.class,
HoldServiceImplUnitTest.class,
// FilePlanPermissionServiceImplUnitTest.class, // removed because test unreliable on Bamboo
RecordableVersionServiceImplUnitTest.class,
// evaluators
TransferEvaluatorUnitTest.class,
FrozenEvaluatorUnitTest.class,
// capabilities
EditNonRecordsMetadataCapabilityUnitTest.class,
// web scripts
HoldsGetUnitTest.class,
HoldPostUnitTest.class,
HoldPutUnitTest.class,
// action implementations
FileReportActionUnitTest.class,
UnlinkFromActionUnitTest.class,
DeclareAsVersionRecordActionUnitTest.class,
// recorded version config
RecordedVersionConfigGetTest.class,
RecordedVersionConfigPostTest.class,
// bootstrap
BootstrapImporterModuleComponentUnitTest.class,
RecordContributorsGroupBootstrapComponentUnitTest.class,
// suites by package
CapabilityDeclarativeConditionSuite.class,
PatchV22Suite.class
@RunWith(ClasspathSuite.class)
@ClassnameFilters({
// Execute all test classes ending with "UnitTest"
".*UnitTest",
// Put the test classes you want to exclude here
"!.*FilePlanPermissionServiceImplUnitTest"
})
public class AllUnitTestSuite
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -18,6 +18,8 @@
*/
package org.alfresco.module.org_alfresco_module_rm.version;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
@@ -27,6 +29,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.Serializable;
import java.util.Collections;
@@ -419,9 +422,16 @@ public class RecordableVersionServiceImplUnitTest extends BaseUnitTest
{
// latest version is already recorded
Version mockedVersion = mock(VersionImpl.class);
doReturn(Collections.singletonMap(RecordableVersionServiceImpl.PROP_VERSION_RECORD, generateNodeRef())).when(mockedVersion).getVersionProperties();
doReturn(true).when(mockedNodeService).hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE);
doReturn(mockedVersion).when(recordableVersionService).getCurrentVersion(nodeRef);
NodeRef versionNodeRef = generateNodeRef();
when(mockedVersion.getFrozenStateNodeRef())
.thenReturn(versionNodeRef);
when(mockedNodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE))
.thenReturn(true);
when(mockedDbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION))
.thenReturn(true);
doReturn(mockedVersion)
.when(recordableVersionService).getCurrentVersion(nodeRef);
// create record from version
recordableVersionService.createRecordFromLatestVersion(filePlan, nodeRef);
@@ -495,4 +505,157 @@ public class RecordableVersionServiceImplUnitTest extends BaseUnitTest
RecordableVersionModel.ASPECT_RECORDED_VERSION,
Collections.singletonMap(RecordableVersionModel.PROP_RECORD_NODE_REF, (Serializable)newRecordNodeRef));
}
/**
* given the destroyed prop isn't set
* when I ask if the version is destroyed
* then the result is false
*/
@Test
public void propNotSetVersionNotDestroyed()
{
// set up version
Version mockedVersion = mock(VersionImpl.class);
NodeRef versionNodeRef = generateNodeRef();
when(mockedVersion.getFrozenStateNodeRef())
.thenReturn(versionNodeRef);
// set prop not set
when(mockedDbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED))
.thenReturn(null);
// is version destroyed
assertFalse(recordableVersionService.isRecordedVersionDestroyed(mockedVersion));
}
/**
* given the destroyed prop is set
* when I ask if the version is destroyed
* then the result matches the value set in the destroy property
*/
@Test
public void propSetVersionDestroyed()
{
// set up version
Version mockedVersion = mock(VersionImpl.class);
NodeRef versionNodeRef = generateNodeRef();
when(mockedVersion.getFrozenStateNodeRef())
.thenReturn(versionNodeRef);
// set prop
when(mockedDbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED))
.thenReturn(Boolean.TRUE);
// is version destroyed
assertTrue(recordableVersionService.isRecordedVersionDestroyed(mockedVersion));
// set prop
when(mockedDbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED))
.thenReturn(Boolean.FALSE);
// is version destroyed
assertFalse(recordableVersionService.isRecordedVersionDestroyed(mockedVersion));
}
/**
* given that the version node doesn't have the recorded version aspect applied
* when I mark the version as destroyed
* then nothing happens
*/
@Test
public void noAspectMarkAsDestroyed()
{
// set up version
Version mockedVersion = mock(VersionImpl.class);
NodeRef versionNodeRef = generateNodeRef();
when(mockedVersion.getFrozenStateNodeRef())
.thenReturn(versionNodeRef);
// indicate that the version doesn't have the aspect
when(mockedDbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION))
.thenReturn(false);
// mark as destroyed
recordableVersionService.destroyRecordedVersion(mockedVersion);
// verify nothing happened
verify(mockedDbNodeService, never())
.setProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED, Boolean.TRUE);
}
/**
* given that the version node ref has the recorded version aspect applied
* and the record version reference exists
* when I mark the version as destroyed
* then the version is marked as destroyed
*/
@Test
public void markAsDestroyed()
{
// set up version
Version mockedVersion = mock(VersionImpl.class);
NodeRef versionNodeRef = generateNodeRef();
NodeRef versionRecordNodeRef = generateNodeRef();
when(mockedVersion.getFrozenStateNodeRef())
.thenReturn(versionNodeRef);
when(mockedDbNodeService.exists(versionRecordNodeRef))
.thenReturn(true);
// indicate that the version doesn't have the aspect
when(mockedDbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION))
.thenReturn(true);
// indicate that the associated version record exists
when(mockedDbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_RECORD_NODE_REF))
.thenReturn(versionRecordNodeRef);
// mark as destroyed
recordableVersionService.destroyRecordedVersion(mockedVersion);
// verify that the version was marked as destroyed
verify(mockedDbNodeService)
.setProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED, Boolean.TRUE);
// and the reference to the version record was cleared
verify(mockedDbNodeService)
.setProperty(versionNodeRef, RecordableVersionModel.PROP_RECORD_NODE_REF, null);
}
/**
* given that the version node ref has the recorded version aspect applied
* and the associated version record has been deleted
* when I mark the version as destroyed
* then the version is marked as destroyed
* and the reference to the deleted version record is removed
*/
@Test
public void markAsDestroyedClearNodeRef()
{
// set up version
Version mockedVersion = mock(VersionImpl.class);
NodeRef versionNodeRef = generateNodeRef();
NodeRef versionRecordNodeRef = generateNodeRef();
when(mockedVersion.getFrozenStateNodeRef())
.thenReturn(versionNodeRef);
when(mockedDbNodeService.exists(versionRecordNodeRef))
.thenReturn(false);
// indicate that the version doesn't have the aspect
when(mockedDbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION))
.thenReturn(true);
// indicate that the associated version record exists
when(mockedDbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_RECORD_NODE_REF))
.thenReturn(versionRecordNodeRef);
// mark as destroyed
recordableVersionService.destroyRecordedVersion(mockedVersion);
// verify that the version was marked as destroyed
verify(mockedDbNodeService)
.setProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED, Boolean.TRUE);
// and the reference to the version record was cleared
verify(mockedDbNodeService)
.setProperty(versionNodeRef, RecordableVersionModel.PROP_RECORD_NODE_REF, null);
}
}