public void LockedLink_BasicSyncTest() { // add a work item on source side int workitemId1 = SourceAdapter.AddWorkItem("Bug", "parent", "description1"); int workitemId2 = SourceAdapter.AddWorkItem("Bug", "child", "description2"); RunAndNoValidate(); TfsSourceAdapter.AddParentChildLink(workitemId1, workitemId2, 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 }); int mirroredId1 = QueryTargetWorkItemID(workitemId1); int mirroredId2 = QueryTargetWorkItemID(workitemId2); Assert.IsTrue(TfsTargetAdapter.IsLinkLocked(mirroredId1, mirroredId2), "migrated link is not locked"); }
public void LockedLink_BasicSyncTest() { TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_DisableContextSync); // add a work item on source side string title1 = string.Format("Parent {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemId1 = SourceAdapter.AddWorkItem("Bug", title1, "description1"); string title2 = string.Format("Child {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemId2 = SourceAdapter.AddWorkItem("Bug", title2, "description2"); RunAndNoValidate(); TfsSourceAdapter.AddParentChildLink(workitemId1, workitemId2, 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 }); int mirroredId1 = QueryMirroredWorkItemID(workitemId1); int mirroredId2 = QueryMirroredWorkItemID(workitemId2); Assert.IsTrue(TfsTargetAdapter.IsLinkLocked(mirroredId1, mirroredId2), "migrated link is not locked"); }
public void Link_AddParentTest() { // add a work item on source side int workitemId1 = SourceAdapter.AddWorkItem("Bug", "title", "description1"); int workitemId2 = SourceAdapter.AddWorkItem("Bug", "title2", "description2"); Console.WriteLine(String.Format("Source work item Ids: Parent: {0}, Child: {1}", workitemId1, workitemId2)); RunAndNoValidate(); TfsSourceAdapter.AddParentChildLink(workitemId1, workitemId2); 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 }); int mirroredId1 = QueryTargetWorkItemID(workitemId1); int mirroredId2 = QueryTargetWorkItemID(workitemId2); Console.WriteLine(String.Format("Target work item Ids: Parent: {0}, Child: {1}", mirroredId1, mirroredId2)); Assert.AreEqual(1, TfsTargetAdapter.GetRelatedLinkCount(mirroredId1)); Assert.AreEqual(false, TfsTargetAdapter.IsLinkLocked(mirroredId1, mirroredId2)); }
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_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 LockedLink_RemoveLockAndDeleteLinkSyncTest() { TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_DisableContextSync); // add a work item on source side string title1 = string.Format("Parent {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemId1 = SourceAdapter.AddWorkItem("Bug", title1, "description1"); string title2 = string.Format("Child {0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemId2 = SourceAdapter.AddWorkItem("Bug", title2, "description2"); RunAndNoValidate(); TfsSourceAdapter.AddParentChildLink(workitemId1, workitemId2, 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"); TfsSourceAdapter.UpdateLinkLockOption(workitemId1, workitemId2, false); TfsSourceAdapter.DeleteParentChildLink(workitemId1, workitemId2); RunAndNoValidate(true); // verify there's a conflict raised conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); conflictResolver.TryResolveConflict(conflicts[0], ConflictConstant.TFSModifyLockedWorkItemLinkConflict_ResolveByForceDeleteAction, conflicts[0].ScopeHint); RunAndNoValidate(true); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); }
public void LockedLink_SkipDeleteLinkSyncTest() { // add a work item on source side int workitemId1 = SourceAdapter.AddWorkItem("Bug", "parent", "description1"); int workitemId2 = SourceAdapter.AddWorkItem("Bug", "child", "description2"); RunAndNoValidate(); TfsSourceAdapter.AddParentChildLink(workitemId1, workitemId2, 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"); TfsSourceAdapter.UpdateLinkLockOption(workitemId1, workitemId2, false); TfsSourceAdapter.DeleteParentChildLink(workitemId1, workitemId2); RunAndNoValidate(true); // verify there's a conflict raised conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); conflictResolver.TryResolveConflict(conflicts[0], new SkipConflictedActionResolutionAction().ReferenceName, conflicts[0].ScopeHint); RunAndNoValidate(true); // verify sync result WitDiffResult result = GetDiffResult(); //// ignore Area/Iteration path mismatches //VerifySyncResult(result, new List<string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); // TODO: Why does TwoWayRight have only one link mismatch, but the others have 2? Assert.AreEqual(2, result.LinkMismatchCount); }
public void LockedLink_RemoveLockAndDeleteLinkSyncTest() { // add a work item on source side int workitemId1 = SourceAdapter.AddWorkItem("Bug", "parent", "description1"); int workitemId2 = SourceAdapter.AddWorkItem("Bug", "child", "description2"); RunAndNoValidate(); TfsSourceAdapter.AddParentChildLink(workitemId1, workitemId2, 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"); TfsSourceAdapter.UpdateLinkLockOption(workitemId1, workitemId2, false); TfsSourceAdapter.DeleteParentChildLink(workitemId1, workitemId2); RunAndNoValidate(true); // verify there's a conflict raised conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); conflictResolver.TryResolveConflict(conflicts[0], ConflictConstant.TFSModifyLockedWorkItemLinkConflict_ResolveByForceDeleteAction, conflicts[0].ScopeHint); RunAndNoValidate(true); // 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 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 }); }