From e664784ce5ee6fbcd42c68391185690fd7a33852 Mon Sep 17 00:00:00 2001 From: Tom Page Date: Thu, 20 Oct 2016 11:14:16 +0100 Subject: [PATCH 1/4] RM-2526 Integration test for linking record to longer schedule. --- .../disposition/DispositionTestSuite.java | 1 + .../disposition/MultipleSchedulesTest.java | 138 ++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/DispositionTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/DispositionTestSuite.java index a2bbacb70d..913b961fc1 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/DispositionTestSuite.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/DispositionTestSuite.java @@ -32,6 +32,7 @@ import org.junit.runners.Suite.SuiteClasses; @SuiteClasses( { CutOffTest.class, + MultipleSchedulesTest.class, UpdateDispositionScheduleTest.class, UpdateNextDispositionActionTest.class }) diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java new file mode 100644 index 0000000000..67bf854533 --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java @@ -0,0 +1,138 @@ +package org.alfresco.module.org_alfresco_module_rm.test.integration.disposition; + +import static org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest.test; + +import java.io.Serializable; +import java.util.Date; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; + +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.action.impl.CutOffAction; +import org.alfresco.module.org_alfresco_module_rm.action.impl.DestroyAction; +import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; +import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; +import org.alfresco.module.org_alfresco_module_rm.job.publish.DispositionActionDefinitionPublishExecutor; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; +import org.alfresco.module.org_alfresco_module_rm.test.util.CommonRMTestUtils; +import org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ApplicationContextHelper; +import org.springframework.extensions.webscripts.GUID; + +public class MultipleSchedulesTest extends BaseRMTestCase +{ + /** A unique prefix for the constants in this test. */ + protected static final String TEST_PREFIX = MultipleSchedulesTest.class.getName() + GUID.generate() + "_"; + /** The name to use for the first category. */ + protected static final String CATEGORY_A_NAME = TEST_PREFIX + "CategoryA"; + /** The name to use for the folder within the first category. */ + protected static final String FOLDER_A_NAME = TEST_PREFIX + "FolderA"; + /** The name to use for the second category. */ + protected static final String CATEGORY_B_NAME = TEST_PREFIX + "CategoryB"; + /** The name to use for the folder within the second category. */ + protected static final String FOLDER_B_NAME = TEST_PREFIX + "FolderB"; + /** The name to use for the record. */ + protected static final String RECORD_NAME = TEST_PREFIX + "Record"; + + /** The executor for the disposition update job. */ + private DispositionActionDefinitionPublishExecutor dispositionActionDefinitionPublishExecutor; + /** The internal disposition service is used to avoid permissions issues when updating the record. */ + private DispositionService internalDispositionService; + + /** The first category node. */ + private NodeRef categoryA; + /** The folder node within the first category. */ + private NodeRef folderA; + /** The second category node. */ + private NodeRef categoryB; + /** The folder node within the second category. */ + private NodeRef folderB; + /** The record node. */ + private NodeRef record; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + BehaviourTest.initBehaviourTests(retryingTransactionHelper); + + // Get the application context + applicationContext = ApplicationContextHelper.getApplicationContext(getConfigLocations()); + dispositionActionDefinitionPublishExecutor = applicationContext.getBean(DispositionActionDefinitionPublishExecutor.class); + internalDispositionService = (DispositionService) applicationContext.getBean("dispositionService"); + } + + /** + * RM-2526 + *

+     * Given a record subject to a disposition schedule
+     * And it is linked to a disposition schedule with the same step order, but a longer destroy step
+     * When the record is moved onto the destroy step
+     * Then the "as of" date is calculated using the longer period.
+     * 
+ */ + public void testLinkedToLongerSchedule() + { + test() + .given(() -> { + // Create two categories. + categoryA = filePlanService.createRecordCategory(filePlan, CATEGORY_A_NAME); + categoryB = filePlanService.createRecordCategory(filePlan, CATEGORY_B_NAME); + // Create a disposition schedule for category A (Cut off immediately, then Destroy immediately). + DispositionSchedule dispSchedA = utils.createBasicDispositionSchedule(categoryA, "instructions", "authority", true, false); + Map cutOffParamsA = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME, + PROP_DISPOSITION_DESCRIPTION, "description", + PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY); + dispositionService.addDispositionActionDefinition(dispSchedA, cutOffParamsA); + Map destroyParamsA = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME, + PROP_DISPOSITION_DESCRIPTION, "description", + PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY); + dispositionService.addDispositionActionDefinition(dispSchedA, destroyParamsA); + // Create a disposition schedule for category B (Cut off immediately, then Destroy one week after cutoff). + DispositionSchedule dispSchedB = utils.createBasicDispositionSchedule(categoryB, "instructions", "authority", true, false); + Map cutOffParamsB = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME, + PROP_DISPOSITION_DESCRIPTION, "description", + PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY); + dispositionService.addDispositionActionDefinition(dispSchedB, cutOffParamsB); + Map destroyParamsB = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME, + PROP_DISPOSITION_DESCRIPTION, "description", + PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_ONE_WEEK, + PROP_DISPOSITION_PERIOD_PROPERTY, PROP_CUT_OFF_DATE); + dispositionService.addDispositionActionDefinition(dispSchedB, destroyParamsB); + // Create a folder within each category. + folderA = recordFolderService.createRecordFolder(categoryA, FOLDER_A_NAME); + folderB = recordFolderService.createRecordFolder(categoryB, FOLDER_B_NAME); + // Create a record filed under category A and linked to category B. + record = fileFolderService.create(folderA, RECORD_NAME, ContentModel.TYPE_CONTENT).getNodeRef(); + recordService.link(record, folderB); + }) + .when(() -> { + // Cut off the record. + dispositionService.cutoffDisposableItem(record); + // Ensure the update has been applied to the record. + internalDispositionService.updateNextDispositionAction(record); + }) + .then() + .expect(7 * 24 * 60 * 60 * 1000L) + .from(() -> dispositionService.getNextDispositionAction(record).getAsOfDate().getTime() + - ((Date) nodeService.getProperty(record, PROP_CUT_OFF_DATE)).getTime()) + .because("Record should follow largest rentention schedule period, which is one week."); + } + + /** + * RM-2526 + *

+     * Given a record subject to a disposition schedule
+     * And it is linked to a disposition schedule with the same step order, but a shorter destroy step
+     * When the record is moved onto the destroy step
+     * Then the "as of" date is calculated using the longer period.
+     * 
+ */ + public void testLinkedToShorterSchedule() + { + } +} From 92ea5c3b58264d8d3a5f7ec954de4961d57085cc Mon Sep 17 00:00:00 2001 From: Tom Page Date: Thu, 20 Oct 2016 11:36:47 +0100 Subject: [PATCH 2/4] RM-2526 Add a second test for linking to a shorter schedule. --- .../disposition/MultipleSchedulesTest.java | 92 ++++++++++++------- 1 file changed, 61 insertions(+), 31 deletions(-) diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java index 67bf854533..dd0326670e 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java @@ -13,7 +13,6 @@ import org.alfresco.module.org_alfresco_module_rm.action.impl.CutOffAction; import org.alfresco.module.org_alfresco_module_rm.action.impl.DestroyAction; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; -import org.alfresco.module.org_alfresco_module_rm.job.publish.DispositionActionDefinitionPublishExecutor; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.module.org_alfresco_module_rm.test.util.CommonRMTestUtils; import org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest; @@ -37,8 +36,6 @@ public class MultipleSchedulesTest extends BaseRMTestCase /** The name to use for the record. */ protected static final String RECORD_NAME = TEST_PREFIX + "Record"; - /** The executor for the disposition update job. */ - private DispositionActionDefinitionPublishExecutor dispositionActionDefinitionPublishExecutor; /** The internal disposition service is used to avoid permissions issues when updating the record. */ private DispositionService internalDispositionService; @@ -62,8 +59,51 @@ public class MultipleSchedulesTest extends BaseRMTestCase // Get the application context applicationContext = ApplicationContextHelper.getApplicationContext(getConfigLocations()); - dispositionActionDefinitionPublishExecutor = applicationContext.getBean(DispositionActionDefinitionPublishExecutor.class); internalDispositionService = (DispositionService) applicationContext.getBean("dispositionService"); + + // Set up the file plan if it hasn't already been done. + if (categoryA == null) + { + setUpFilePlan(); + } + // Ensure different records are used for each test. + record = null; + } + + /** + * Create two categories each containing a folder. Set up a schedule on category A that applies to records (cutoff + * immediately, destroy immediately). Set up a schedule on category B that is the same, but with a week delay before + * destroy becomes eligible. + */ + private void setUpFilePlan() + { + // Create two categories. + categoryA = filePlanService.createRecordCategory(filePlan, CATEGORY_A_NAME); + categoryB = filePlanService.createRecordCategory(filePlan, CATEGORY_B_NAME); + // Create a disposition schedule for category A (Cut off immediately, then Destroy immediately). + DispositionSchedule dispSchedA = utils.createBasicDispositionSchedule(categoryA, "instructions", "authority", true, false); + Map cutOffParamsA = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME, + PROP_DISPOSITION_DESCRIPTION, "description", + PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY); + dispositionService.addDispositionActionDefinition(dispSchedA, cutOffParamsA); + Map destroyParamsA = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME, + PROP_DISPOSITION_DESCRIPTION, "description", + PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY); + dispositionService.addDispositionActionDefinition(dispSchedA, destroyParamsA); + // Create a disposition schedule for category B (Cut off immediately, then Destroy one week after cutoff). + DispositionSchedule dispSchedB = utils.createBasicDispositionSchedule(categoryB, "instructions", "authority", true, false); + Map cutOffParamsB = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME, + PROP_DISPOSITION_DESCRIPTION, "description", + PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY); + dispositionService.addDispositionActionDefinition(dispSchedB, cutOffParamsB); + Map destroyParamsB = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME, + PROP_DISPOSITION_DESCRIPTION, "description", + PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_ONE_WEEK, + PROP_DISPOSITION_PERIOD_PROPERTY, PROP_CUT_OFF_DATE); + dispositionService.addDispositionActionDefinition(dispSchedB, destroyParamsB); + // Create a folder within each category. + folderA = recordFolderService.createRecordFolder(categoryA, FOLDER_A_NAME); + folderB = recordFolderService.createRecordFolder(categoryB, FOLDER_B_NAME); } /** @@ -79,33 +119,6 @@ public class MultipleSchedulesTest extends BaseRMTestCase { test() .given(() -> { - // Create two categories. - categoryA = filePlanService.createRecordCategory(filePlan, CATEGORY_A_NAME); - categoryB = filePlanService.createRecordCategory(filePlan, CATEGORY_B_NAME); - // Create a disposition schedule for category A (Cut off immediately, then Destroy immediately). - DispositionSchedule dispSchedA = utils.createBasicDispositionSchedule(categoryA, "instructions", "authority", true, false); - Map cutOffParamsA = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME, - PROP_DISPOSITION_DESCRIPTION, "description", - PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY); - dispositionService.addDispositionActionDefinition(dispSchedA, cutOffParamsA); - Map destroyParamsA = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME, - PROP_DISPOSITION_DESCRIPTION, "description", - PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY); - dispositionService.addDispositionActionDefinition(dispSchedA, destroyParamsA); - // Create a disposition schedule for category B (Cut off immediately, then Destroy one week after cutoff). - DispositionSchedule dispSchedB = utils.createBasicDispositionSchedule(categoryB, "instructions", "authority", true, false); - Map cutOffParamsB = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME, - PROP_DISPOSITION_DESCRIPTION, "description", - PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY); - dispositionService.addDispositionActionDefinition(dispSchedB, cutOffParamsB); - Map destroyParamsB = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME, - PROP_DISPOSITION_DESCRIPTION, "description", - PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_ONE_WEEK, - PROP_DISPOSITION_PERIOD_PROPERTY, PROP_CUT_OFF_DATE); - dispositionService.addDispositionActionDefinition(dispSchedB, destroyParamsB); - // Create a folder within each category. - folderA = recordFolderService.createRecordFolder(categoryA, FOLDER_A_NAME); - folderB = recordFolderService.createRecordFolder(categoryB, FOLDER_B_NAME); // Create a record filed under category A and linked to category B. record = fileFolderService.create(folderA, RECORD_NAME, ContentModel.TYPE_CONTENT).getNodeRef(); recordService.link(record, folderB); @@ -134,5 +147,22 @@ public class MultipleSchedulesTest extends BaseRMTestCase */ public void testLinkedToShorterSchedule() { + test() + .given(() -> { + // Create a record filed under category B and linked to category A. + record = fileFolderService.create(folderB, RECORD_NAME, ContentModel.TYPE_CONTENT).getNodeRef(); + recordService.link(record, folderA); + }) + .when(() -> { + // Cut off the record. + dispositionService.cutoffDisposableItem(record); + // Ensure the update has been applied to the record. + internalDispositionService.updateNextDispositionAction(record); + }) + .then() + .expect(7 * 24 * 60 * 60 * 1000L) + .from(() -> dispositionService.getNextDispositionAction(record).getAsOfDate().getTime() + - ((Date) nodeService.getProperty(record, PROP_CUT_OFF_DATE)).getTime()) + .because("Record should follow largest rentention schedule period, which is one week."); } } From 66def3bd88bf7b840c40bd65a2529d9938b94b92 Mon Sep 17 00:00:00 2001 From: Tom Page Date: Thu, 20 Oct 2016 12:35:32 +0100 Subject: [PATCH 3/4] RM-2526 Make sure we set up the file plan from within a transaction. --- .../disposition/MultipleSchedulesTest.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java index dd0326670e..7dae0fd715 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java @@ -61,11 +61,6 @@ public class MultipleSchedulesTest extends BaseRMTestCase applicationContext = ApplicationContextHelper.getApplicationContext(getConfigLocations()); internalDispositionService = (DispositionService) applicationContext.getBean("dispositionService"); - // Set up the file plan if it hasn't already been done. - if (categoryA == null) - { - setUpFilePlan(); - } // Ensure different records are used for each test. record = null; } @@ -77,6 +72,12 @@ public class MultipleSchedulesTest extends BaseRMTestCase */ private void setUpFilePlan() { + // Only set up the file plan if it hasn't already been done. + if (categoryA == null) + { + return; + } + // Create two categories. categoryA = filePlanService.createRecordCategory(filePlan, CATEGORY_A_NAME); categoryB = filePlanService.createRecordCategory(filePlan, CATEGORY_B_NAME); @@ -119,6 +120,7 @@ public class MultipleSchedulesTest extends BaseRMTestCase { test() .given(() -> { + setUpFilePlan(); // Create a record filed under category A and linked to category B. record = fileFolderService.create(folderA, RECORD_NAME, ContentModel.TYPE_CONTENT).getNodeRef(); recordService.link(record, folderB); @@ -149,6 +151,7 @@ public class MultipleSchedulesTest extends BaseRMTestCase { test() .given(() -> { + setUpFilePlan(); // Create a record filed under category B and linked to category A. record = fileFolderService.create(folderB, RECORD_NAME, ContentModel.TYPE_CONTENT).getNodeRef(); recordService.link(record, folderA); From f4874eb118412a44ef70fc8665393b880e65c6e8 Mon Sep 17 00:00:00 2001 From: Tom Page Date: Thu, 20 Oct 2016 14:06:52 +0100 Subject: [PATCH 4/4] RM-2526 Fix typo. --- .../test/integration/disposition/MultipleSchedulesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java index 7dae0fd715..f97a7fee3a 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/disposition/MultipleSchedulesTest.java @@ -73,7 +73,7 @@ public class MultipleSchedulesTest extends BaseRMTestCase private void setUpFilePlan() { // Only set up the file plan if it hasn't already been done. - if (categoryA == null) + if (categoryA != null) { return; }