Exemplo n.º 1
0
        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));
        }
Exemplo n.º 2
0
        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
                });
            }
        }
Exemplo n.º 3
0
        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
            });
        }
Exemplo n.º 4
0
        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));
        }
Exemplo n.º 5
0
        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));
        }
Exemplo n.º 6
0
        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
            });
        }