public void LinkAddAddDeleteLinkTest() { // add a work item on source side int sourceIdA = SourceAdapter.AddWorkItem("Bug", "A", "A"); int sourceIdB = SourceAdapter.AddWorkItem("Task", "B", "B"); int sourceIdC = SourceAdapter.AddWorkItem("Scenario", "C", "C"); RunAndNoValidate(); // link A-B and A-C TfsSourceAdapter.AddRelatedWorkItemLink(sourceIdA, sourceIdB); WITChangeAction action = new WITChangeAction() { Title = "added AB link", }; TfsSourceAdapter.UpdateWorkItem(sourceIdA, action); TfsSourceAdapter.UpdateWorkItem(sourceIdB, action); TfsSourceAdapter.AddRelatedWorkItemLink(sourceIdA, sourceIdC); action = new WITChangeAction() { Title = "added AC link", }; TfsSourceAdapter.UpdateWorkItem(sourceIdA, action); TfsSourceAdapter.UpdateWorkItem(sourceIdC, action); // delete A-B link TfsSourceAdapter.DeleteRelatedWorkItemLink(sourceIdA, sourceIdB); action = new WITChangeAction() { Title = "deleted AB link", }; TfsSourceAdapter.UpdateWorkItem(sourceIdA, action); TfsSourceAdapter.UpdateWorkItem(sourceIdB, action); RunAndNoValidate(true); // verify no conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be no conflict"); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdA)); Assert.AreEqual(0, TfsSourceAdapter.GetRelatedLinkCount(sourceIdB)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdC)); int targetIdA = QueryTargetWorkItemID(sourceIdA); int targetIdB = QueryTargetWorkItemID(sourceIdB); int targetIdC = QueryTargetWorkItemID(sourceIdC); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetIdA)); Assert.AreEqual(0, TfsTargetAdapter.GetRelatedLinkCount(targetIdB)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetIdC)); }
public void Link_TwoParentsInHistoryTest() { TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_DisableContextSync); TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_SetOneWayNoContextSync); // Legend: x->y (y is a parent of x) // T1: Source: b->c // T2: Sync // T3: Target: b->c // T4: Source: delete b->c, add b->a // T5: Sync // add a work item on source side string title1 = string.Format("A {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdA = SourceAdapter.AddWorkItem("Bug", title1, "A"); string title2 = string.Format("B {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdB = SourceAdapter.AddWorkItem("Bug", title2, "B"); string title3 = string.Format("C {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdC = SourceAdapter.AddWorkItem("Bug", title3, "C"); TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(SetTargetFilterString); RunAndNoValidate(); // T1 TfsSourceAdapter.AddParentChildLink(workitemIdC, workitemIdB); RunAndNoValidate(true); // T4: // Source: delete c->b, add a->c ==> b->a->c (a is the child of c) TfsSourceAdapter.DeleteParentChildLink(workitemIdC, workitemIdB); TfsSourceAdapter.AddParentChildLink(workitemIdA, workitemIdB); RunAndNoValidate(true); // verify the expected conflict ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be no conflict"); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(workitemIdA)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(workitemIdB)); Assert.AreEqual(0, TfsSourceAdapter.GetRelatedLinkCount(workitemIdC)); // Target: delete b->a, add a->b ==> a->b, c->b (a is the child of b) int mirroredIdA = QueryMirroredWorkItemID(workitemIdA); int mirroredIdB = QueryMirroredWorkItemID(workitemIdB); int mirroredIdC = QueryMirroredWorkItemID(workitemIdC); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdA)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdB)); Assert.AreEqual(0, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdC)); }
public void Link_DeleteRelatedLinkFromBothSideTest() { TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_DisableContextSync); TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_SetBidirectionalNoContextSync); // add a work item on source side string title1 = string.Format("{0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemId1 = SourceAdapter.AddWorkItem("Bug", title1, "description1"); string title2 = string.Format("{0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemId2 = SourceAdapter.AddWorkItem("Bug", title1, "description2"); TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(SetTargetFilterString); RunAndNoValidate(); int mirroredId1 = QueryMirroredWorkItemID(workitemId1); int mirroredId2 = QueryMirroredWorkItemID(workitemId2); // source: add a related link TfsSourceAdapter.AddRelatedWorkItemLink(workitemId1, workitemId2); RunAndNoValidate(true); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(mirroredId1), "RelatedLink count on target system is wrong"); // source: delete the link TfsSourceAdapter.DeleteRelatedWorkItemLink(workitemId1, workitemId2); // target: delete the same link TfsTargetAdapter.DeleteRelatedWorkItemLink(mirroredId1, mirroredId2); RunAndNoValidate(true); // now both sides shouldn't have a link Assert.AreEqual(0, TfsSourceAdapter.GetRelatedLinkCount(workitemId1), "RelatedLink count on source system is wrong"); Assert.AreEqual(0, TfsTargetAdapter.GetRelatedLinkCount(workitemId1), "RelatedLink count on target system is wrong"); // verify there's no conflicts raised ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be no conflicts"); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); }
public void Link_TwoParentsInHistoryTest() { // Legend: x->y (y is a parent of x) // T1: Source: b->c // T2: Sync // T3: Target: b->c // T4: Source: delete b->c, add b->a // T5: Sync // add a work item on source side int sourceIdA = SourceAdapter.AddWorkItem("Bug", "A", "A"); int sourceIdB = SourceAdapter.AddWorkItem("Bug", "B", "B"); int sourceIdC = SourceAdapter.AddWorkItem("Bug", "C", "C"); RunAndNoValidate(); // T1 TfsSourceAdapter.AddParentChildLink(sourceIdC, sourceIdB); RunAndNoValidate(true); // T4: // Source: delete c->b, add a->c ==> b->a->c (a is the child of c) TfsSourceAdapter.DeleteParentChildLink(sourceIdC, sourceIdB); TfsSourceAdapter.AddParentChildLink(sourceIdA, sourceIdB); RunAndNoValidate(true); // verify the expected conflict ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be no conflict"); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdA)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdB)); Assert.AreEqual(0, TfsSourceAdapter.GetRelatedLinkCount(sourceIdC)); // Target: delete b->a, add a->b ==> a->b, c->b (a is the child of b) int targetId1 = QueryTargetWorkItemID(sourceIdA); int targetId2 = QueryTargetWorkItemID(sourceIdB); int targetIdC = QueryTargetWorkItemID(sourceIdC); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetId1)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetId2)); Assert.AreEqual(0, TfsTargetAdapter.GetRelatedLinkCount(targetIdC)); }
public void Link_DeleteRelatedLinkFromTargetTest() { TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_DisableContextSync); // add a work item on source side int sourceId1 = TfsSourceAdapter.AddWorkItem("Bug", "title1", "description1"); int sourceId2 = TfsSourceAdapter.AddWorkItem("Bug", "title2", "description2"); RunAndNoValidate(); int targetId1 = QueryTargetWorkItemID(sourceId1); Console.WriteLine(String.Format("SourceId1: {0}, TargetId1: {1}", sourceId1, targetId1)); int targetId2 = QueryTargetWorkItemID(sourceId2); Console.WriteLine(String.Format("SourceId2: {0}, TargetId2: {1}", sourceId2, targetId2)); // source: add a related link TfsSourceAdapter.AddRelatedWorkItemLink(sourceId1, sourceId2); RunAndNoValidate(true); // source side should have one link int sourceLinkCount = TfsSourceAdapter.GetRelatedLinkCount(sourceId1); Assert.AreEqual(1, sourceLinkCount, "RelatedLink count on source system should be 1"); int targetLinkCount = TfsTargetAdapter.GetRelatedLinkCount(targetId1); Assert.AreEqual(1, targetLinkCount, "RelatedLink count on target system should be 1"); // target: delete the mirrored link TfsTargetAdapter.DeleteRelatedWorkItemLink(targetId1, targetId2); RunAndNoValidate(true); // now target side shouldn't have any links targetLinkCount = TfsTargetAdapter.GetRelatedLinkCount(targetId1); Assert.AreEqual(0, targetLinkCount, "RelatedLink count on target system should be 0"); // verify there's no conflicts raised ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be no conflicts"); sourceLinkCount = TfsSourceAdapter.GetRelatedLinkCount(sourceId1); if (TestEnvironment.MigrationTestType == MigrationTestType.OneWay) { // source side should still have the original link Assert.AreEqual(1, sourceLinkCount, "source side link should still exist"); } else { // now source side shouldn't have any links Assert.AreEqual(0, sourceLinkCount, "source side link should be deleted"); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); } }
public void Link_TwoParentsTest() { // Legend: x->y (y is a parent of x) // T1: Source: c->b->a // T2: Sync // T3: Target: c->b->a // T4: Source: delete c->b, add a->c ==> b->a->c // Target: delete b->a, add a->b ==> a->b, c->b (b has two children) // T5: Sync // add a work item on source side int sourceIdA = SourceAdapter.AddWorkItem("Bug", "A", "A"); int sourceIdB = SourceAdapter.AddWorkItem("Bug", "B", "B"); int sourceIdC = SourceAdapter.AddWorkItem("Bug", "C", "C"); RunAndNoValidate(); // T1-T3: c->b->a TfsSourceAdapter.AddParentChildLink(sourceIdB, sourceIdC); TfsSourceAdapter.AddParentChildLink(sourceIdA, sourceIdB); RunAndNoValidate(true); // T4: // Source: delete c->b, add a->c ==> b->a->c (a is the child of c) TfsSourceAdapter.DeleteParentChildLink(sourceIdB, sourceIdC); TfsSourceAdapter.AddParentChildLink(sourceIdC, sourceIdA); // Target: delete b->a, add a->b ==> a->b, c->b (a is the child of b) int targetId1 = QueryTargetWorkItemID(sourceIdA); int targetId2 = QueryTargetWorkItemID(sourceIdB); int targetIdC = QueryTargetWorkItemID(sourceIdC); TfsTargetAdapter.DeleteParentChildLink(targetId1, targetId2); TfsTargetAdapter.AddParentChildLink(targetId2, targetId1); // after sync: // source: b->a->c // target: a->b (adding a->c is conflicted) RunAndNoValidate(true); // verify the expected conflict ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Guid TFSMulitpleParentLinkConflictTypeReferenceName = new Guid("ADCE870C-33C0-46bc-9350-31660A463F9A"); // Workaround for Bug 529648: Accept 1 or more conflicts. We should only generate 1 conflict, but for Two-way scenarios we generate 2. Assert.IsTrue(conflicts.Count > 0, "There should be 1 or more conflicts"); foreach (RTConflict conflict in conflicts) { Assert.IsTrue(TFSMulitpleParentLinkConflictTypeReferenceName.Equals(conflict.ConflictTypeReference.Value.ReferenceName), "It should be a TFSMultipleParentLinkConflict"); } // fix the hierarchy on target, delete a->b // target: a, b, c TfsTargetAdapter.DeleteParentChildLink(targetId2, targetId1); foreach (RTConflict conflict in conflicts) { // resolve the conflict(s) by taking source side changes conflictResolver.TryResolveConflict(conflict, new ManualConflictResolutionAction(), "/"); } // restart the migration tool, after sync // source: b->a->c // target: a->c RunAndNoValidate(true); conflicts = conflictResolver.GetConflicts(); if (TestEnvironment.MigrationTestType == MigrationTestType.OneWay) { Assert.IsTrue(conflicts.Count == 0, "There should be no conflict"); // One way migration should have source/target out of sync Assert.AreEqual(2, TfsSourceAdapter.GetRelatedLinkCount(sourceIdA)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdB)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdC)); } else { // In two-way case, add a->b on Target at T4 above causes multi-parent conflict // when migrated back to source because a->c already exists on source. Assert.IsTrue(conflicts.Count == 1, "There should be one conflict"); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdA)); Assert.AreEqual(0, TfsSourceAdapter.GetRelatedLinkCount(sourceIdB)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdC)); } Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetId1)); Assert.AreEqual(0, TfsTargetAdapter.GetRelatedLinkCount(targetId2)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetIdC)); }
public void Link_CyclicLinkTest() { // Legend: x->y (y is a parent of x) // T1: Source: a->b->c d // T2: Sync // T3: Target: a->b->c d // T4: Source: delete b->c, add c->a ==> a->b c->a d // Target: delete b->c, add b->d , d->c ==> a->b->d->c // T5: Sync // We should detect cyclic link and raise a conflict // add a work item on source side int sourceIdA = SourceAdapter.AddWorkItem("Bug", "A", "A"); int sourceIdB = SourceAdapter.AddWorkItem("Bug", "B", "B"); int sourceIdC = SourceAdapter.AddWorkItem("Bug", "C", "C"); int sourceIdD = SourceAdapter.AddWorkItem("Bug", "D", "D"); RunAndNoValidate(); // add b->c TfsSourceAdapter.AddParentChildLink(sourceIdC, sourceIdB); // add a->b TfsSourceAdapter.AddParentChildLink(sourceIdB, sourceIdA); // after sync, // Source: a->b->c d // Target: a->b->c d RunAndNoValidate(true); int targetIdA = QueryTargetWorkItemID(sourceIdA); int targetIdB = QueryTargetWorkItemID(sourceIdB); int targetIdC = QueryTargetWorkItemID(sourceIdC); int targetIdD = QueryTargetWorkItemID(sourceIdD); // Source: delete b->c, add c->a, now source is c->a->b d TfsSourceAdapter.DeleteParentChildLink(sourceIdC, sourceIdB); TfsSourceAdapter.AddParentChildLink(sourceIdA, sourceIdC); // Target: delete b->c, add b->d , d->c, now target is a->b->d->c TfsTargetAdapter.DeleteParentChildLink(targetIdC, targetIdB); TfsTargetAdapter.AddParentChildLink(targetIdD, targetIdB); TfsTargetAdapter.AddParentChildLink(targetIdC, targetIdD); // c->a from source will create cyclic link on target RunAndNoValidate(true); // verify the expected conflict ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Guid TFSCyclicLinkConflictTypeReferenceName = new Guid("BF1277E9-A218-4a2d-8C3C-A9501D30ECD5"); // Workaround for Bug 529648: Accept 1 or more conflicts. We should only generate 1 conflict, but for Two-way scenarios we generate 2. Assert.IsTrue(conflicts.Count > 0, "There should be 1 or more conflicts"); foreach (RTConflict conflict in conflicts) { Assert.IsTrue(TFSCyclicLinkConflictTypeReferenceName.Equals(conflict.ConflictTypeReference.Value.ReferenceName), "Conflict should be a TFS cyclic link reference conflict"); } // fix the hierarchy on target, delete d->c => a->b->d c TfsTargetAdapter.DeleteParentChildLink(targetIdC, targetIdD); foreach (RTConflict rtConflict in conflicts) { // resolve the conflict by retrying conflictResolver.TryResolveConflict(rtConflict, new ManualConflictResolutionAction(), "/"); // restart the migration tool, after sync, RunAndNoValidate(true); } conflicts = conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count == 0, "There should be no conflict"); // hiearchy should be c->a->b->d Assert.AreEqual(2, TfsTargetAdapter.GetRelatedLinkCount(targetIdA)); Assert.AreEqual(2, TfsTargetAdapter.GetRelatedLinkCount(targetIdB)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetIdC)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetIdD)); if (TestEnvironment.MigrationTestType == MigrationTestType.OneWay) { // for one-way migration the source should be out of sync with the target now Assert.AreEqual(2, TfsSourceAdapter.GetRelatedLinkCount(sourceIdA)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdB)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdC)); Assert.AreEqual(0, TfsSourceAdapter.GetRelatedLinkCount(sourceIdD)); } else { // Two-way sync should be in sync with target now // TODO: why does this work for TwoWayLeft but not TwoWayRight? Assert.AreEqual(2, TfsSourceAdapter.GetRelatedLinkCount(sourceIdA)); Assert.AreEqual(2, TfsSourceAdapter.GetRelatedLinkCount(sourceIdB)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdC)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdD)); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); } }
public void Link_CyclicLinkSamePairTest() { // Legend: x->y (y is a parent of x) // T1: Source: a b // T2: Sync // T3: Target: a b // T4: Source: add a->b ==> a->b // Target: add b->a ==> b->a // T5: Sync // We should detect cyclic link and raise a conflict // add a work item on source side int sourceIdA = SourceAdapter.AddWorkItem("Bug", "A", "A"); int sourceIdB = SourceAdapter.AddWorkItem("Bug", "B", "B"); RunAndNoValidate(); int targetId1 = QueryTargetWorkItemID(sourceIdA); int targetId2 = QueryTargetWorkItemID(sourceIdB); TfsSourceAdapter.AddParentChildLink(sourceIdB, sourceIdA); TfsTargetAdapter.AddParentChildLink(targetId1, targetId2); RunAndNoValidate(true); // verify the expected conflict ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Guid TFSCyclicLinkConflictTypeReferenceName = new Guid("BF1277E9-A218-4a2d-8C3C-A9501D30ECD5"); // Workaround for Bug 529648: Accept 1 or more conflicts. We should only generate 1 conflict, but for Two-way scenarios we generate 2. Assert.IsTrue(conflicts.Count > 0, "There should be 1 or more conflicts"); foreach (RTConflict conflict in conflicts) { Assert.IsTrue(TFSCyclicLinkConflictTypeReferenceName.Equals(conflict.ConflictTypeReference.Value.ReferenceName), "Conflict should be a TFS cyclic link reference conflict"); } // fix the hierarchy on target, delete b->a ==> a b TfsTargetAdapter.DeleteParentChildLink(targetId1, targetId2); foreach (RTConflict conflict in conflicts) { // resolve the conflict by retrying conflictResolver.TryResolveConflict(conflict, new ManualConflictResolutionAction(), "/"); // restart the session RunAndNoValidate(true); } conflicts = conflictResolver.GetConflicts(); if (TestEnvironment.MigrationTestType == MigrationTestType.OneWay) { Assert.IsTrue(conflicts.Count == 0, "There should be no conflict"); } else { // In two-way cases, migration back from target to source will still generate a conflict // because we have not deleted a->b on the source Assert.IsTrue(conflicts.Count == 1, "There should be one conflict"); } Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdA)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(sourceIdB)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetId1)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetId2)); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); }
public void LinkScenarioExperienceTest() { const int ExperienceCount = 10; // On Left add 1 Scenario and a bunch of Experiences int sourceScenarioId = SourceAdapter.AddWorkItem("Scenario", "scenario title", "source scenario description"); Console.WriteLine("Source Scenario ID = {0}", sourceScenarioId); int[] sourceExperienceIDs = new int[ExperienceCount]; int[] targetExperienceIDs = new int[ExperienceCount]; for (int index = 0; index < ExperienceCount; index++) { string title = string.Format("Experience {0}", index); sourceExperienceIDs[index] = SourceAdapter.AddWorkItem("Experience", title, title); } // sync RunAndNoValidate(); // get the migrated target ID int targetScenarioId = QueryTargetWorkItemID(sourceScenarioId); Console.WriteLine("Target Scenario ID = {0}", targetScenarioId); // Modify some field of the scenario: this should create a revision of the work item that has no link changes to get migrated WITChangeAction sourceAction = new WITChangeAction() { History = "Adding scenario-experience links on the source side", }; SourceAdapter.UpdateWorkItem(sourceScenarioId, sourceAction); // Link source scenario to all the experiences for (int index = 0; index < ExperienceCount; index++) { TfsSourceAdapter.AddScenarioExperienceLink(sourceScenarioId, sourceExperienceIDs[index]); } // Modify the history again forcing the above links to get migrated WITChangeAction sourceAction2 = new WITChangeAction() { AssignedTo = "billbar", }; SourceAdapter.UpdateWorkItem(sourceScenarioId, sourceAction2); for (int index = 0; index < ExperienceCount; index++) { Console.WriteLine("Getting mirrored TargetWorkItemID for target experience: " + sourceExperienceIDs[index].ToString()); targetExperienceIDs[index] = QueryTargetWorkItemID(sourceExperienceIDs[index]); Console.WriteLine("Mirrored TargetWorkItemID: " + targetExperienceIDs[index].ToString()); } /* * // on target modify field of the mirrored Ids of each of the Experience * // This should cause them to get sync'd back to the source side * WITChangeAction targetAction = new WITChangeAction() * { * History = "Touch the target experience work item", * }; * foreach (int targetExperienceID in targetExperienceIDs) * { * TargetAdapter.UpdateWorkItem(targetExperienceID, targetAction); * } */ // sync RunAndNoValidate(true); ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be no conflicts"); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); Assert.AreEqual(ExperienceCount, TfsSourceAdapter.GetRelatedLinkCount(sourceScenarioId)); Assert.AreEqual(ExperienceCount, TfsSourceAdapter.GetRelatedLinkCount(targetScenarioId)); }
public void Link_MultiAddDeleteRelatedLinkTest() { for (int i = 0; i < 7; ++i) { // add a work item on source side string title = "title " + i.ToString(); int id = SourceAdapter.AddWorkItem("Bug", title, "description1"); SourceWorkItemIdList[i] = id; } TfsSourceAdapter.AddRelatedWorkItemLink(SourceWorkItemIdList[1], SourceWorkItemIdList[0]); TfsSourceAdapter.AddRelatedWorkItemLink(SourceWorkItemIdList[1], SourceWorkItemIdList[2]); TfsSourceAdapter.AddRelatedWorkItemLink(SourceWorkItemIdList[1], SourceWorkItemIdList[3]); RunAndNoValidate(); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[0])); Assert.AreEqual(3, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[1])); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[2])); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[3])); TfsSourceAdapter.DeleteRelatedWorkItemLink(SourceWorkItemIdList[1], SourceWorkItemIdList[0]); TfsSourceAdapter.DeleteRelatedWorkItemLink(SourceWorkItemIdList[1], SourceWorkItemIdList[2]); TfsSourceAdapter.DeleteRelatedWorkItemLink(SourceWorkItemIdList[1], SourceWorkItemIdList[3]); TfsSourceAdapter.AddRelatedWorkItemLink(SourceWorkItemIdList[1], SourceWorkItemIdList[4]); TfsSourceAdapter.AddRelatedWorkItemLink(SourceWorkItemIdList[1], SourceWorkItemIdList[5]); TfsSourceAdapter.AddRelatedWorkItemLink(SourceWorkItemIdList[1], SourceWorkItemIdList[6]); RunAndNoValidate(true); RunAndNoValidate(true); // verify there's no conflicts raised ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be no conflicts"); //// verify sync result //WitDiffResult result = GetDiffResult(); //// ignore Area/Iteration path mismatches //VerifySyncResult(result, new List<string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); Assert.AreEqual(0, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[0])); Assert.AreEqual(3, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[1])); Assert.AreEqual(0, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[2])); Assert.AreEqual(0, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[3])); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[4])); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[5])); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(SourceWorkItemIdList[6])); int[] targetWorkItemIds = new int[SourceWorkItemIdList.Count]; for (int i = 0; i < SourceWorkItemIdList.Count; ++i) { targetWorkItemIds[i] = QueryTargetWorkItemID(SourceWorkItemIdList[i]); } Assert.AreEqual(0, TfsTargetAdapter.GetRelatedLinkCount(targetWorkItemIds[0])); Assert.AreEqual(3, TfsTargetAdapter.GetRelatedLinkCount(targetWorkItemIds[1])); Assert.AreEqual(0, TfsTargetAdapter.GetRelatedLinkCount(targetWorkItemIds[2])); Assert.AreEqual(0, TfsTargetAdapter.GetRelatedLinkCount(targetWorkItemIds[3])); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetWorkItemIds[4])); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetWorkItemIds[5])); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(targetWorkItemIds[6])); }
public void Link_TwoParentsTest() { TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_DisableContextSync); TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_SetOneWayNoContextSync); // Legend: x->y (y is a parent of x) // T1: Source: c->b->a // T2: Sync // T3: Target: c->b->a // T4: Source: delete c->b, add a->c ==> b->a->c // Target: delete b->a, add a->b ==> a->b, c->b (b has two children) // T5: Sync // add a work item on source side string title1 = string.Format("A {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdA = SourceAdapter.AddWorkItem("Bug", title1, "A"); string title2 = string.Format("B {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdB = SourceAdapter.AddWorkItem("Bug", title2, "B"); string title3 = string.Format("C {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdC = SourceAdapter.AddWorkItem("Bug", title3, "C"); TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(SetTargetFilterString); RunAndNoValidate(); // T1-T3: c->b->a TfsSourceAdapter.AddParentChildLink(workitemIdB, workitemIdC); TfsSourceAdapter.AddParentChildLink(workitemIdA, workitemIdB); RunAndNoValidate(true); // T4: // Source: delete c->b, add a->c ==> b->a->c (a is the child of c) TfsSourceAdapter.DeleteParentChildLink(workitemIdB, workitemIdC); TfsSourceAdapter.AddParentChildLink(workitemIdC, workitemIdA); // Target: delete b->a, add a->b ==> a->b, c->b (a is the child of b) int mirroredIdA = QueryMirroredWorkItemID(workitemIdA); int mirroredIdB = QueryMirroredWorkItemID(workitemIdB); int mirroredIdC = QueryMirroredWorkItemID(workitemIdC); TfsTargetAdapter.DeleteParentChildLink(mirroredIdA, mirroredIdB); TfsTargetAdapter.AddParentChildLink(mirroredIdB, mirroredIdA); // after sync: // source: b->a->c // target: a->b (adding a->c is conflicted) RunAndNoValidate(true); // verify the expected conflict ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); Guid TFSMulitpleParentLinkConflictTypeReferenceName = new Guid("ADCE870C-33C0-46bc-9350-31660A463F9A"); Assert.IsTrue(TFSMulitpleParentLinkConflictTypeReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be a TFSMulitpleParentLinkConflict"); // fix the hierarchy on target, delete a->b // target: a, b, c TfsTargetAdapter.DeleteParentChildLink(mirroredIdB, mirroredIdA); // resolve the conflict by taking source side changes conflictResolver.TryResolveConflict(conflicts[0], new ManualConflictResolutionAction(), "/"); // restart the migration tool, after sync // source: b->a->c // target: a->c RunAndNoValidate(true); conflicts = conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count == 0, "There should be no conflict"); Assert.AreEqual(2, TfsSourceAdapter.GetRelatedLinkCount(workitemIdA)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(workitemIdB)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(workitemIdC)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdA)); Assert.AreEqual(0, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdB)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdC)); }
private void Link_CyclicLinkScenarioTwoWay() { // Legend: x->y (y is a parent of x) // T1: Source: a->b->c d // T2: Sync // T3: Target: a->b->c d // T4: Source: delete b->c, add c->a ==> a->b c->a d // Target: delete b->c, add b->d , d->c ==> a->b->d->c // T5: Sync // We should detect cyclic link and raise a conflict // add a work item on source side string titleA = string.Format("A {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdA = SourceAdapter.AddWorkItem("Bug", titleA, "A"); string titleB = string.Format("B {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdB = SourceAdapter.AddWorkItem("Bug", titleB, "B"); string titleC = string.Format("C {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdC = SourceAdapter.AddWorkItem("Bug", titleC, "C"); string titleD = string.Format("C {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdD = SourceAdapter.AddWorkItem("Bug", titleD, "D"); TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(SetTargetFilterString); RunAndNoValidate(); TfsSourceAdapter.AddParentChildLink(workitemIdC, workitemIdB); TfsSourceAdapter.AddParentChildLink(workitemIdB, workitemIdA); // after sync, // Source: a->b->c d // Target: a->b->c d RunAndNoValidate(true); // Source: delete b->c, add c->a => c->a->b d TfsSourceAdapter.DeleteParentChildLink(workitemIdC, workitemIdB); TfsSourceAdapter.AddParentChildLink(workitemIdA, workitemIdC); // Target: delete b->c, add b->d , d->c => a->b->d->c int mirroredIdA = QueryMirroredWorkItemID(workitemIdA); int mirroredIdB = QueryMirroredWorkItemID(workitemIdB); int mirroredIdC = QueryMirroredWorkItemID(workitemIdC); int mirroredIdD = QueryMirroredWorkItemID(workitemIdD); TfsTargetAdapter.DeleteParentChildLink(mirroredIdC, mirroredIdB); TfsTargetAdapter.AddParentChildLink(mirroredIdD, mirroredIdB); TfsTargetAdapter.AddParentChildLink(mirroredIdC, mirroredIdD); // c->a from source will create cyclic link on target RunAndNoValidate(true); // verify the expected conflict ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(2, conflicts.Count, "There should be 2 conflicts"); Guid TFSCyclicLinkConflictTypeReferenceName = new Guid("BF1277E9-A218-4a2d-8C3C-A9501D30ECD5"); Assert.IsTrue(TFSCyclicLinkConflictTypeReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be a TFS cyclic link reference conflict"); Assert.IsTrue(TFSCyclicLinkConflictTypeReferenceName.Equals(conflicts[1].ConflictTypeReference.Value.ReferenceName), "It should be a TFS cyclic link reference conflict"); // fix the hierarchy on target, delete a->b => a b->d->c TfsTargetAdapter.DeleteParentChildLink(mirroredIdB, mirroredIdA); // resolve the conflict by retrying conflictResolver.TryResolveConflict(conflicts[0], new ManualConflictResolutionAction(), "/"); // restart the migration tool, after sync, RunAndNoValidate(true); // resolve the conflict by retrying conflictResolver.TryResolveConflict(conflicts[1], new ManualConflictResolutionAction(), "/"); RunAndNoValidate(true); conflicts = conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count == 0, "There should be no conflict"); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(workitemIdA)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(workitemIdB)); Assert.AreEqual(2, TfsSourceAdapter.GetRelatedLinkCount(workitemIdC)); Assert.AreEqual(2, TfsSourceAdapter.GetRelatedLinkCount(workitemIdD)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdA)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdB)); Assert.AreEqual(2, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdC)); Assert.AreEqual(2, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdD)); }
public void Link_CyclicLinkSamePairBidirectionalTest() { TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_DisableContextSync); TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_SetBidirectionalNoContextSync); // Legend: x->y (y is a parent of x) // T1: Source: a b // T2: Sync // T3: Target: a b // T4: Source: add a->b ==> a->b // Target: add b->a ==> b->a // T5: Sync // We should detect cyclic link and raise a conflict // add a work item on source side string titleA = string.Format("A {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdA = SourceAdapter.AddWorkItem("Bug", titleA, "A"); string titleB = string.Format("B {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemIdB = SourceAdapter.AddWorkItem("Bug", titleB, "B"); TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(SetTargetFilterString); RunAndNoValidate(); int mirroredIdA = QueryMirroredWorkItemID(workitemIdA); int mirroredIdB = QueryMirroredWorkItemID(workitemIdB); TfsSourceAdapter.AddParentChildLink(workitemIdB, workitemIdA); TfsTargetAdapter.AddParentChildLink(mirroredIdA, mirroredIdB); RunAndNoValidate(true); // verify the expected conflict ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(2, conflicts.Count, "There should be 2 conflicts"); Guid TFSCyclicLinkConflictTypeReferenceName = new Guid("BF1277E9-A218-4a2d-8C3C-A9501D30ECD5"); Assert.IsTrue(TFSCyclicLinkConflictTypeReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be a TFS cyclic link reference conflict"); Assert.IsTrue(TFSCyclicLinkConflictTypeReferenceName.Equals(conflicts[1].ConflictTypeReference.Value.ReferenceName), "It should be a TFS cyclic link reference conflict"); // fix the hierarchy on target, delete b->a ==> a b TfsTargetAdapter.DeleteParentChildLink(mirroredIdA, mirroredIdB); // resolve the conflict by retrying conflictResolver.TryResolveConflict(conflicts[0], new ManualConflictResolutionAction(), "/"); // restart the session RunAndNoValidate(true); // resolve the conflict by retrying conflictResolver.TryResolveConflict(conflicts[1], new ManualConflictResolutionAction(), "/"); // restart the session RunAndNoValidate(true); conflicts = conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count == 0, "There should be no conflict"); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(workitemIdA)); Assert.AreEqual(1, TfsSourceAdapter.GetRelatedLinkCount(workitemIdB)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdA)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(mirroredIdB)); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); }