blob: 6427e5284b50f0d806abe94621fe69b5cecf6aec [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2012 Boeing
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Boeing - initial API and implementation
**********************************************************************/
package org.eclipse.osee.client.integration.tests.integration.ui.skynet;
import static org.eclipse.osee.client.demo.DemoChoice.OSEE_CLIENT_DEMO;
import static org.eclipse.osee.framework.core.enums.DemoBranches.SAW_Bld_1;
import static org.eclipse.osee.framework.core.enums.RelationSorter.LEXICOGRAPHICAL_ASC;
import static org.eclipse.osee.framework.core.enums.RelationSorter.LEXICOGRAPHICAL_DESC;
import static org.eclipse.osee.framework.core.enums.RelationSorter.USER_DEFINED;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.osee.client.test.framework.OseeClientIntegrationRule;
import org.eclipse.osee.client.test.framework.OseeLogMonitorRule;
import org.eclipse.osee.framework.core.data.ArtifactId;
import org.eclipse.osee.framework.core.data.ArtifactTypeToken;
import org.eclipse.osee.framework.core.data.AttributeId;
import org.eclipse.osee.framework.core.data.BranchId;
import org.eclipse.osee.framework.core.data.BranchToken;
import org.eclipse.osee.framework.core.data.RelationTypeSide;
import org.eclipse.osee.framework.core.enums.CoreArtifactTypes;
import org.eclipse.osee.framework.core.enums.CoreAttributeTypes;
import org.eclipse.osee.framework.core.enums.CoreRelationTypes;
import org.eclipse.osee.framework.core.enums.DeletionFlag;
import org.eclipse.osee.framework.core.enums.RelationSorter;
import org.eclipse.osee.framework.core.operation.Operations;
import org.eclipse.osee.framework.jdk.core.util.GUID;
import org.eclipse.osee.framework.skynet.core.OseeSystemArtifacts;
import org.eclipse.osee.framework.skynet.core.artifact.Artifact;
import org.eclipse.osee.framework.skynet.core.artifact.ArtifactTypeManager;
import org.eclipse.osee.framework.skynet.core.artifact.Attribute;
import org.eclipse.osee.framework.skynet.core.artifact.BranchManager;
import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactQuery;
import org.eclipse.osee.framework.skynet.core.change.Change;
import org.eclipse.osee.framework.skynet.core.httpRequests.PurgeBranchHttpRequestOperation;
import org.eclipse.osee.framework.skynet.core.relation.RelationManager;
import org.eclipse.osee.framework.skynet.core.revision.ChangeManager;
import org.eclipse.osee.framework.skynet.core.transaction.SkynetTransaction;
import org.eclipse.osee.framework.skynet.core.transaction.TransactionManager;
import org.eclipse.osee.framework.ui.skynet.blam.operation.ReplaceArtifactWithBaselineOperation;
import org.eclipse.osee.framework.ui.skynet.blam.operation.ReplaceAttributeWithBaselineOperation;
import org.eclipse.osee.framework.ui.skynet.update.InterArtifactExplorerDropHandlerOperation;
import org.junit.After;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/**
* <pre>
* New | Deleted | Modified | Moved | Introduced | RelationOrderAttr
* -------------------------------------------------------------------------
* Artifact | 0 1 3 2
* Attribute | 4 5 6
* Relation | 7 8 9* **
* -------------------------------------------------------------------------
*
*
* Legend:
* * - artifact will be left with a DELETED attribute change and a SYNTHETIC
* modified artifact change. CASE_10_EXPECTED. i.e.:
*
* A C-
* `- B -> `- B B is moved to C
* C gets a new user defined order attribute
*
* Revert on B causes A to have a new relation order attribute because
* B was the only child of A and when the link was deleted the relation order
* attribute was also deleted. (link.deleteEmptyRelationOrder()) After the B
* link is added back from the revert of B. A will get a new relation order attribute.
*
* ** - creates a parent artifact A on the baseline branch and adds 5 children. On the working branch
* the same artifact A gets additional 5 children. The revert is called A.
* Which will set the parent (A) back to the baseline state but leaves
* the new artifacts orphaned on the working branch.
*
* Case 10 is a collection of 1-9, all cases.
* </pre>
*
* @author Ryan D. Brooks
*/
@RunWith(Parameterized.class)
public final class ReplaceWithBaselineTest {
@Rule
public OseeClientIntegrationRule integration = new OseeClientIntegrationRule(OSEE_CLIENT_DEMO);
@Rule
public OseeLogMonitorRule monitorRule = new OseeLogMonitorRule();
private static final RelationSorter ascOrder = LEXICOGRAPHICAL_ASC;
private static final RelationSorter descOrder = LEXICOGRAPHICAL_DESC;
/**
* Refer to table for Case 10*
*/
private static final int CASE_10_EXPECTED = 2;
private static final int CASE_0_EXPECTED = 10;
private static final ArtifactTypeToken DOC = CoreArtifactTypes.GeneralDocument;
private static final IProgressMonitor MONITOR = new NullProgressMonitor();
//@formatter:off
private static enum Item { ARTIFACT, ATTRBUTE, RELATION, };
private static enum ChangeItem { NEW, DELETED, MODIFIED, MOVED, INTRODUCED, RELATION_ORDER_ATTR };
//@formatter:on
private BranchToken workingBranch;
private BranchToken baselineBranch;
private final String testName;
private final int expectedChangesLeft;
private final List<TestData> testDatas;
public ReplaceWithBaselineTest(String testCaseName, List<TestData> testDatas, int expectedChangesLeft) {
this.testName = String.format("%s : %s", ReplaceWithBaselineTest.class.getSimpleName(), testCaseName);
this.testDatas = testDatas;
this.expectedChangesLeft = expectedChangesLeft;
}
@After
public void tearDown() throws Exception {
Operations.executeWorkAndCheckStatus(new PurgeBranchHttpRequestOperation(workingBranch, true));
}
@Test
public void testReplaceWithBaselineVersion() throws Exception {
runTest();
Collection<Change> changes = getBranchChanges(workingBranch);
switch (expectedChangesLeft) {
case CASE_10_EXPECTED:
Assert.assertTrue(changes.size() == CASE_10_EXPECTED);
break;
case CASE_0_EXPECTED:
Assert.assertTrue(changes.size() == CASE_0_EXPECTED);
break;
case CASE_0_EXPECTED + CASE_10_EXPECTED:
Assert.assertTrue(changes.size() == CASE_0_EXPECTED + CASE_10_EXPECTED);
break;
default:
Assert.assertTrue(changes.isEmpty());
break;
}
}
@Parameters
public static List<Object[]> getData() {
List<Object[]> data = new LinkedList<>();
data.add(new Object[] {"Case 0", Arrays.asList(new TestData(Item.ARTIFACT, ChangeItem.NEW, false)), 0});
data.add(new Object[] {"Case 1", Arrays.asList(new TestData(Item.ARTIFACT, ChangeItem.DELETED, true)), 0});
data.add(new Object[] {"Case 2", Arrays.asList(new TestData(Item.ARTIFACT, ChangeItem.INTRODUCED, false)), 0});
data.add(new Object[] {"Case 3", Arrays.asList(new TestData(Item.ARTIFACT, ChangeItem.MODIFIED, true)), 0});
data.add(new Object[] {"Case 4", Arrays.asList(new TestData(Item.ATTRBUTE, ChangeItem.NEW, true)), 0});
data.add(new Object[] {"Case 5", Arrays.asList(new TestData(Item.ATTRBUTE, ChangeItem.DELETED, true)), 0});
data.add(new Object[] {"Case 6", Arrays.asList(new TestData(Item.ATTRBUTE, ChangeItem.MODIFIED, true)), 0});
List<TestData> combinedCases = new ArrayList<>(data.size());
for (Object[] objects : data) {
@SuppressWarnings("unchecked")
List<TestData> caseTestDatas = (List<TestData>) objects[1];
combinedCases.addAll(caseTestDatas);
}
data.add(new Object[] {"Case 7", combinedCases, 0});
Collections.reverse(combinedCases);
data.add(new Object[] {"Case 8", combinedCases, 0});
return data;
}
/**
* Sets up the test based on <code>ReplaceWithBaselineTest.testItem</code> and performs a revert.
*/
private void runTest() throws Exception {
setupBackgroundForScenario();
makeChange(testDatas);
Collection<Change> changesAfterRevert = getBranchChanges(workingBranch);
List<Artifact> artifactsToRevert = new ArrayList<>();
Artifact artifactToRevert;
for (TestData testData : testDatas) {
artifactToRevert =
ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch, DeletionFlag.INCLUDE_DELETED);
switch (testData.item) {
case ARTIFACT:
artifactsToRevert.add(artifactToRevert);
break;
case ATTRBUTE:
revertAttributes(changesAfterRevert, artifactToRevert.getAttributeById(testData.getAttrId(), true));
break;
case RELATION:
artifactsToRevert.add(artifactToRevert);
break;
}
}
revertArtifacts(changesAfterRevert, artifactsToRevert); //Only if not attributes
}
@SuppressWarnings("incomplete-switch")
private void setupBackgroundForScenario() throws Exception {
baselineBranch = SAW_Bld_1;
//Setup data before the working branch has been created
for (TestData testData : this.testDatas) {
if (testData.isBaseline) {
testData.setArtifactId(createNewArtifact(baselineBranch, GUID.create()));
}
switch (testData.item) {
case ARTIFACT:
break;
case ATTRBUTE:
break;
case RELATION:
switch (testData.changeItem) {
case NEW:
//setup a and b artifacts so a new relation can be created.
testData.setbArtifactId(createNewArtifact(baselineBranch, GUID.create()).getArtId());
testData.setRelationType(CoreRelationTypes.SupportingInfo_SupportingInfo);
break;
case DELETED:
//set up relation to be deleted
Artifact c = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), baselineBranch);
Artifact d = createNewArtifact(baselineBranch, GUID.create());
testData.setbArtifactId(d.getArtId());
RelationManager.addRelation(CoreRelationTypes.SupportingInfo_SupportingInfo, c, d,
"Supporting info for c to d");
testData.setRelationType(CoreRelationTypes.SupportingInfo_SupportingInfo);
c.persist(testName);
break;
case MOVED:
//setup parent child relation so it can be moved on the working branch
Artifact parent = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), baselineBranch);
Artifact child = createNewArtifact(baselineBranch, GUID.create());
Artifact newParent = createNewArtifact(baselineBranch, GUID.create());
testData.setbArtifactId(child.getArtId());
testData.setcArtId(newParent.getArtId());
parent.addChild(USER_DEFINED, child);
parent.persist(testName);
testData.setRelationType(CoreRelationTypes.DefaultHierarchical_Child);
break;
case RELATION_ORDER_ATTR:
Artifact parentArtifact = createNewArtifact(baselineBranch, "parent");
int numOfChildren = 5;
for (int i = 0; i < numOfChildren; i++) {
parentArtifact.addRelation(ascOrder, CoreRelationTypes.DefaultHierarchical_Child,
createNewArtifact(baselineBranch, GUID.create()));
}
parentArtifact.persist(testName);
testData.setArtifactId(parentArtifact);
break;
}
break;
}
}
workingBranch = BranchManager.createWorkingBranch(baselineBranch, "working branch", ArtifactId.SENTINEL);
SkynetTransaction workingBranchTransaction = TransactionManager.createTransaction(workingBranch, testName);
workingBranchTransaction.execute();
//Setup data on the working branch for testing
for (TestData testData : testDatas) {
switch (testData.item) {
case ATTRBUTE:
if (testData.changeItem == ChangeItem.NEW) {
Artifact newArtifact = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
newArtifact.addAttributeFromString(CoreAttributeTypes.ParagraphNumber, "1.0");
newArtifact.persist(testName);
testData.setAttrId(newArtifact.getSoleAttribute(CoreAttributeTypes.ParagraphNumber));
}
break;
case ARTIFACT:
switch (testData.changeItem) {
case NEW:
testData.setArtifactId(createNewArtifact(workingBranch, GUID.create()));
break;
case INTRODUCED:
BranchToken anotherBranch =
BranchManager.createWorkingBranch(workingBranch, "another working branch", ArtifactId.SENTINEL);
Artifact artifactToIntroduce = createNewArtifact(anotherBranch, "introduce artifact");
InterArtifactExplorerDropHandlerOperation dropHandler =
new InterArtifactExplorerDropHandlerOperation(
OseeSystemArtifacts.getDefaultHierarchyRootArtifact(workingBranch),
new Artifact[] {artifactToIntroduce}, false);
Operations.executeWork(dropHandler);
testData.setArtifactId(artifactToIntroduce);
}
break;
case RELATION:
if (testData.changeItem == ChangeItem.NEW) {
Artifact a = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
Artifact b = ArtifactQuery.getArtifactFromId(testData.getbArtifactId(), workingBranch);
RelationManager.addRelation(testData.getRelationType(), a, b, "Link add for testing");
a.persist(testName);
}
break;
}
}
}
@SuppressWarnings("incomplete-switch")
private void makeChange(List<TestData> datas) throws Exception {
Artifact artifact = null;
Attribute<?> attribute = null;
for (TestData testData : testDatas) {
switch (testData.item) {
case ATTRBUTE:
switch (testData.changeItem) {
case NEW:
artifact = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
attribute = artifact.getAttributeById(testData.getAttrId(), true);
artifact.persist(testName);
break;
case DELETED:
artifact = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
attribute = artifact.getSoleAttribute(CoreAttributeTypes.Name);
attribute.delete();
artifact.persist(testName);
testData.setAttrId(attribute);
break;
case MODIFIED:
artifact = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
attribute = artifact.getSoleAttribute(CoreAttributeTypes.Name);
attribute.setFromString("I am changed");
artifact.persist(testName);
testData.setAttrId(attribute);
break;
}
break;
case ARTIFACT:
switch (testData.changeItem) {
case DELETED:
artifact = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
artifact.deleteAndPersist(testName);
break;
case NEW:
artifact = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
artifact.persist(testName);
break;
case INTRODUCED:
artifact = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
artifact.persist(testName);
break;
case MODIFIED:
artifact = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
artifact.addAttribute(CoreAttributeTypes.Active, true);
artifact.persist(testName);
break;
}
break;
case RELATION:
switch (testData.changeItem) {
case NEW:
Artifact a = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
Artifact b = ArtifactQuery.getArtifactFromId(testData.getbArtifactId(), workingBranch);
RelationManager.addRelation(testData.getRelationType(), a, b, "This is a new relation");
a.persist(testName);
break;
case DELETED:
Artifact c = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
Artifact d = ArtifactQuery.getArtifactFromId(testData.getbArtifactId(), workingBranch);
RelationManager.deleteRelation(testData.getRelationType(), c, d);
c.persist(testName);
break;
case MOVED:
Artifact parent = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
Artifact child = ArtifactQuery.getArtifactFromId(testData.getbArtifactId(), workingBranch);
Artifact newParent = ArtifactQuery.getArtifactFromId(testData.getcArtId(), workingBranch);
parent.deleteRelations(CoreRelationTypes.DefaultHierarchical_Child);
parent.persist(testName);
newParent.addChild(USER_DEFINED, child);
newParent.persist(testName);
//This is to revert the child artifact
testData.setArtifactId(child);
child.persist(testName);
break;
case RELATION_ORDER_ATTR:
Artifact parentArtifact = ArtifactQuery.getArtifactFromId(testData.getArtifactId(), workingBranch);
int numOfChildren = 5;
for (int i = 0; i < numOfChildren; i++) {
parentArtifact.addRelation(descOrder, CoreRelationTypes.DefaultHierarchical_Child,
createNewArtifact(workingBranch, GUID.create()));
}
parentArtifact.persist(testName);
break;
}
break;
}
}
}
private Artifact createNewArtifact(BranchToken branch, String name) throws Exception {
Artifact artifact = ArtifactTypeManager.addArtifact(DOC, branch, name);
artifact.persist(testName + name);
return artifact;
}
private void revertArtifacts(Collection<Change> changes, Collection<Artifact> artifactsToRevert) {
Operations.executeWorkAndCheckStatus(new ReplaceArtifactWithBaselineOperation(changes, artifactsToRevert));
}
private void revertAttributes(Collection<Change> changes, Attribute<?> attributeToRevert) {
List<Change> attrChanges = new ArrayList<>(1);
for (Change change : changes) {
if (change.getChangeType().isAttributeChange() && change.getItemId().getId().intValue() == attributeToRevert.getId()) {
attrChanges.add(change);
}
}
Operations.executeWorkAndCheckStatus(new ReplaceAttributeWithBaselineOperation(attrChanges));
}
private List<Change> getBranchChanges(BranchId branch) {
List<Change> changes = new ArrayList<>();
Operations.executeWorkAndCheckStatus(ChangeManager.comparedToParent(branch, changes), MONITOR);
return changes;
}
void createArtifact(String name) {
ArtifactTypeManager.addArtifact(DOC, workingBranch, name);
}
private static class TestData {
public final Item item;
public final ChangeItem changeItem;
public final boolean isBaseline;
private ArtifactId artifactId;
private RelationTypeSide relationType;
private int bArtifactId;
private AttributeId attrId;
private int cArtId;
public TestData(Item item, ChangeItem changeItem, boolean isBaseline) {
this.item = item;
this.changeItem = changeItem;
this.isBaseline = isBaseline;
}
public int getcArtId() {
return cArtId;
}
public void setcArtId(int cArtId) {
this.cArtId = cArtId;
}
public AttributeId getAttrId() {
return attrId;
}
public void setAttrId(AttributeId attrId) {
this.attrId = attrId;
}
public RelationTypeSide getRelationType() {
return relationType;
}
public void setRelationType(RelationTypeSide relationType) {
this.relationType = relationType;
}
public int getbArtifactId() {
return bArtifactId;
}
public void setbArtifactId(int bArtifactId) {
this.bArtifactId = bArtifactId;
}
public ArtifactId getArtifactId() {
return artifactId;
}
public void setArtifactId(ArtifactId artId) {
artifactId = artId;
}
@Override
public String toString() {
String message =
"Item: %s ChangeItem %s isBaseline %s ArtifactId %s RelationTypeToken %s artifactId %s bArtifactId %s";
return String.format(message, item, changeItem, isBaseline, artifactId, relationType, artifactId, bArtifactId);
}
}
}