package com.constellio.app.services.recovery;
import static com.constellio.app.modules.rm.model.enums.CopyType.PRINCIPAL;
import static com.constellio.app.services.recovery.UpdateRecoveryImpossibleCause.TOO_SHORT_MEMORY;
import static com.constellio.app.services.recovery.UpdateRecoveryImpossibleCause.TOO_SHORT_SPACE;
import static com.constellio.app.services.recovery.UpgradeAppRecoveryServiceImpl.REQUIRED_MEMORY_IN_MO;
import static com.constellio.app.services.recovery.UpgradeAppRecoveryServiceImpl.REQUIRED_SPACE_IN_GIG;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import org.joda.time.LocalDateTime;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import com.constellio.app.modules.rm.RMTestRecords;
import com.constellio.app.modules.rm.services.RMSchemasRecordsServices;
import com.constellio.app.modules.rm.wrappers.Folder;
import com.constellio.data.dao.managers.config.values.TextConfiguration;
import com.constellio.data.dao.services.records.RecordDao;
import com.constellio.model.conf.FoldersLocator;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.records.Transaction;
import com.constellio.model.entities.schemas.Schemas;
import com.constellio.model.services.records.RecordServices;
import com.constellio.model.services.records.RecordServicesException;
import com.constellio.model.services.records.RecordServicesRuntimeException.NoSuchRecordWithId;
import com.constellio.model.services.schemas.MetadataSchemasManager;
import com.constellio.model.services.schemas.MetadataSchemasManagerException.OptimisticLocking;
import com.constellio.model.services.schemas.builders.MetadataSchemaTypesBuilder;
import com.constellio.sdk.tests.ConstellioTest;
import com.constellio.sdk.tests.SolrSDKToolsServices;
import com.constellio.sdk.tests.SolrSDKToolsServices.VaultSnapshot;
public class UpgradeAppRecoveryServiceImplAcceptanceTest extends ConstellioTest {
RMTestRecords records = new RMTestRecords(zeCollection);
RecordServices recordServices;
@Rule
public TemporaryFolder folder = new TemporaryFolder();
UpgradeAppRecoveryServiceImpl upgradeAppRecoveryService;
String recordNotModifiedId, existingRecordToBeDeletedLogicallyId, existingRecordToBeDeletedPhysicallyId,
recordCreatedId, recordCreatedToBeDeletedLogicallyId,
recordCreatedToBeDeletedPhysicallyId, recordModifiedId;
private RMSchemasRecordsServices rm;
private LocalDateTime beforeStartRollBack = LocalDateTime.now().plusDays(7);
private String addedSchemaTypeCode = "UpgradeAppRecoveryServiceImplAcceptanceTestLol";
@Before
public void setUp()
throws Exception {
withSpiedServices(FoldersLocator.class);
givenTransactionLogIsEnabled();
givenDisabledAfterTestValidations();
prepareSystem(
withZeCollection().withConstellioRMModule().withAllTestUsers().withRMTest(records)
.withFoldersAndContainersOfEveryStatus()
);
upgradeAppRecoveryService = new UpgradeAppRecoveryServiceImpl(getAppLayerFactory(), getIOLayerFactory().newIOServices());
rm = new RMSchemasRecordsServices(zeCollection, getAppLayerFactory());
recordServices = getModelLayerFactory().newRecordServices();
}
@Test
public void whenIsValidWarThenBehavesAsExpected()
throws Exception {
REQUIRED_MEMORY_IN_MO = 1;
REQUIRED_SPACE_IN_GIG = 1;
assertThat(upgradeAppRecoveryService.isUpdateWithRecoveryPossible()).isNull();
REQUIRED_MEMORY_IN_MO = 1000 * 1024;
assertThat(upgradeAppRecoveryService.isUpdateWithRecoveryPossible()).isEqualTo(TOO_SHORT_MEMORY);
REQUIRED_MEMORY_IN_MO = 1;
REQUIRED_SPACE_IN_GIG = 500 * 1024 * 1024;
assertThat(upgradeAppRecoveryService.isUpdateWithRecoveryPossible()).isEqualTo(TOO_SHORT_SPACE);
}
@Test
public void givenRollBackStartedAndSomeModificationWhenRollbackThenSameStateAsBeforeStartingRollback()
throws Exception {
givenTimeIs(beforeStartRollBack);
initTestRecords();
RecordDao recordDao = getDataLayerFactory().newRecordDao();
SolrSDKToolsServices tools = new SolrSDKToolsServices(recordDao);
givenTimeIs(beforeStartRollBack.plusDays(1));
VaultSnapshot snapshotBeforeReplay = tools.snapshot();
upgradeAppRecoveryService.startRollbackMode();
someModification();
upgradeAppRecoveryService.rollback(null);
VaultSnapshot currentSnapShot = tools.snapshot();
tools.ensureSameSnapshots("", snapshotBeforeReplay, currentSnapShot);
TextConfiguration schemas = getDataLayerFactory().getConfigManager()
.getText(zeCollection + "/schemas.xml");
assertThat(schemas.getText().contains(addedSchemaTypeCode)).isFalse();
}
@Test
public void givenRollBackStartedAndSomeModificationWhenStopRollbackThenAllModificationsSaved()
throws Exception {
givenTimeIs(beforeStartRollBack);
initTestRecords();
givenTimeIs(beforeStartRollBack.plusDays(1));
upgradeAppRecoveryService.startRollbackMode();
someModification();
upgradeAppRecoveryService.stopRollbackMode();
validateRecordsModifiedAsExpected();
TextConfiguration schemas = getDataLayerFactory().getConfigManager()
.getText(zeCollection + "/schemas.xml");
assertThat(schemas.getText().contains(addedSchemaTypeCode)).isTrue();
}
//afterWarUpload
//prepareNextStartup
//deletePreviousWarCausingFailure
//afterWarUpload
//getTransactionLogFileSize
private void someModification()
throws RecordServicesException {
modifyRecord(recordModifiedId);
createNewRecords();
modifyRecord(recordCreatedId);
deleteLogically(recordCreatedToBeDeletedLogicallyId);
deletePhysically(recordCreatedToBeDeletedPhysicallyId);
deleteLogically(existingRecordToBeDeletedLogicallyId);
deletePhysically(existingRecordToBeDeletedPhysicallyId);
addSchema(zeCollection, addedSchemaTypeCode);
}
private void initTestRecords()
throws RecordServicesException {
initTestRecordsIds();
Folder folderNotModified = rm.getFolder(recordNotModifiedId);
execute(folderNotModified.setTitle("mm").setModifiedOn(beforeStartRollBack).getWrappedRecord());
}
private void initTestRecordsIds() {
recordNotModifiedId = records.getFolder_A01().getId();
existingRecordToBeDeletedLogicallyId = records.getFolder_A02().getId();
existingRecordToBeDeletedPhysicallyId = records.getFolder_A05().getId();
recordModifiedId = records.getFolder_A04().getId();
}
private void addSchema(String collection, String schemaCode) {
MetadataSchemasManager schemaManager = getAppLayerFactory()
.getModelLayerFactory().getMetadataSchemasManager();
MetadataSchemaTypesBuilder types = schemaManager.modify(collection);
types.createNewSchemaType(schemaCode);
try {
schemaManager.saveUpdateSchemaTypes(types);
} catch (OptimisticLocking optimistickLocking) {
throw new java.lang.RuntimeException(optimistickLocking);
}
getModelLayerFactory().getMetadataSchemasManager().getSchemaTypes(zeCollection).getSchemaType(addedSchemaTypeCode);
}
private void deletePhysically(String recordId) {
recordServices.logicallyDelete(recordServices.getDocumentById(recordId), null);
recordServices.physicallyDelete(recordServices.getDocumentById(recordId), null);
}
private void deleteLogically(String recordId) {
recordServices.logicallyDelete(recordServices.getDocumentById(recordId), null);
}
private void createNewRecords()
throws RecordServicesException {
Folder recordCreated = rm.newFolder();
recordCreatedId = recordCreated.getId();
Folder recordCreatedToBeDeletedLogically = rm.newFolder();
recordCreatedToBeDeletedLogicallyId = recordCreatedToBeDeletedLogically.getId();
Folder recordCreatedToBeDeletedPhysically = rm.newFolder();
recordCreatedToBeDeletedPhysicallyId = recordCreatedToBeDeletedPhysically.getId();
Transaction transaction = new Transaction();
transaction.add(recordCreated.setTitle("created")
.setAdministrativeUnitEntered(records.unitId_10a)
.setCategoryEntered(records.categoryId_X).setRetentionRuleEntered(records.ruleId_2)
.setMediumTypes(rm.PA(), rm.DM()).setCopyStatusEntered(PRINCIPAL).setOpenDate(date(2000, 10, 4))
.getWrappedRecord());
transaction.add(recordCreatedToBeDeletedLogically.setTitle("to be deleted l")
.setAdministrativeUnitEntered(records.unitId_10a)
.setCategoryEntered(records.categoryId_X).setRetentionRuleEntered(records.ruleId_2)
.setMediumTypes(rm.PA(), rm.DM()).setCopyStatusEntered(PRINCIPAL).setOpenDate(date(2000, 10, 4))
.getWrappedRecord());
transaction.add(recordCreatedToBeDeletedPhysically.setTitle("to be deleted p")
.setAdministrativeUnitEntered(records.unitId_10a)
.setCategoryEntered(records.categoryId_X).setRetentionRuleEntered(records.ruleId_2)
.setMediumTypes(rm.PA(), rm.DM()).setCopyStatusEntered(PRINCIPAL).setOpenDate(date(2000, 10, 4))
.getWrappedRecord());
recordServices.execute(transaction);
}
private void modifyRecord(String recordId)
throws RecordServicesException {
execute(recordServices.getDocumentById(recordId).set(Schemas.TITLE, getClass().getName() + recordId));
}
private void execute(Record folder)
throws RecordServicesException {
Transaction transaction = new Transaction();
transaction.add(folder);
recordServices.execute(transaction);
}
private void validateRecordsModifiedAsExpected() {
Folder folderNotModified = rm.getFolder(recordNotModifiedId);
assertThat(folderNotModified.getModifiedOn()).isEqualTo(beforeStartRollBack);
Folder modifiedRecord = rm.getFolder(recordModifiedId);
assertThat(modifiedRecord.getTitle()).isEqualTo(getClass().getName() + recordModifiedId);
Folder createdRecord = rm.getFolder(recordCreatedId);
assertThat(createdRecord.getTitle()).isEqualTo(getClass().getName() + recordCreatedId);
Folder folderDeltedLogically = rm.getFolder(recordCreatedToBeDeletedLogicallyId);
assertThat(folderDeltedLogically.isLogicallyDeletedStatus()).isTrue();
try {
rm.getFolder(recordCreatedToBeDeletedPhysicallyId);
fail("Expecting record to be deleted physically " + recordCreatedToBeDeletedPhysicallyId);
} catch (NoSuchRecordWithId e) {
//ok
}
Folder existingFolderDeltedLogically = rm.getFolder(existingRecordToBeDeletedLogicallyId);
assertThat(existingFolderDeltedLogically.isLogicallyDeletedStatus()).isTrue();
try {
rm.getFolder(existingRecordToBeDeletedPhysicallyId);
fail("Expecting record to be deleted physically " + existingRecordToBeDeletedPhysicallyId);
} catch (NoSuchRecordWithId e) {
//ok
}
}
}