public void EditEditConflictTakeSourceTest() { int sourceId; int targetId; EditEditConflictScenario(out sourceId, out targetId); string srcTitle = SourceAdapter.GetFieldValue(sourceId, FIELD_TITLE); string srcDesc = SourceAdapter.GetFieldValue(sourceId, FIELD_DESCRIPTION); string tarTitle = TargetAdapter.GetFieldValue(targetId, FIELD_TITLE); string tarDesc = TargetAdapter.GetFieldValue(targetId, FIELD_DESCRIPTION); Assert.AreNotEqual(srcTitle, tarTitle, "Title should not match due to conflict"); Assert.AreNotEqual(srcDesc, tarDesc, "Description should not match due to conflict"); // verify we have edit/edit conflict List <RTConflict> conflicts = m_conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count >= 1, "There should be edit/edit conflict"); WITEditEditConflictType contentConflict = new WITEditEditConflictType(); Assert.IsTrue(contentConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be WIT edit/edit conflict"); // resolve the conflict by taking source side changes bool isResolved = false; if (TestEnvironment.MigrationTestType == MigrationTestType.TwoWayRight) { isResolved = m_conflictResolver.TryResolveConflict(conflicts[0], new WITEditEditConflictTakeTargetChangesAction(), "/" + targetId); } else { isResolved = m_conflictResolver.TryResolveConflict(conflicts[0], new WITEditEditConflictTakeSourceChangesAction(), "/" + sourceId); } Assert.IsTrue(isResolved, "Conflict resolution should succeed"); // restart the migration tool RunAndNoValidate(true); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches due to test environments VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); srcDesc = SourceAdapter.GetFieldValue(sourceId, FIELD_DESCRIPTION); tarDesc = TargetAdapter.GetFieldValue(targetId, FIELD_DESCRIPTION); Assert.AreEqual(srcDesc, SOURCE_R1_DESC); Assert.AreEqual(tarDesc, SOURCE_R1_DESC); }
public void TwoWay_EditEditConflictTakeOtherTest() { // continuous manual, bi-directional sync TestEnvironment.WorkFlowType = new WorkFlowType(); TestEnvironment.WorkFlowType.DirectionOfFlow = DirectionOfFlow.Bidirectional; TestEnvironment.WorkFlowType.Frequency = Frequency.ContinuousManual; TestEnvironment.WorkFlowType.SyncContext = SyncContext.Disabled; // 1. migrate a.txt -> a.txt string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, null, TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, null, TestEnvironment, false); SourceAdapter.AddFile(sourceFile.LocalPath); RunAndValidate(); // 2. source system: a.txt -> edit SourceAdapter.EditFile(sourceFile.LocalPath); // 3. target system: a.txt -> edit TargetAdapter.EditFile(targetFile.LocalPath); // 4. Migration will detect a conflict Run(); // 5. resolve conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); VCContentConflictType contentConflict = new VCContentConflictType(); Assert.IsTrue(contentConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be vc content conflict"); conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictTakeOtherChangesAction(), conflicts[0].ScopeHint); // sync Run(true, true); // validation // no remaining conflicts conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be NO conflict"); // content should match Assert.IsTrue(VerifyContents(), "The latest content should match."); // 6. edit a.txt on source system SourceAdapter.EditFile(sourceFile.LocalPath); // 7. sync Run(true, true); // validation // no remaining conflicts conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be NO conflict"); // content should match Assert.IsTrue(VerifyContents(), "The latest content should match."); }
public void TFSHistoryNotFoundConflict() { MigrationItemStrings branch = new MigrationItemStrings("source/", "target/", TestEnvironment, true); MigrationItemStrings file1 = new MigrationItemStrings("source/file1.txt", null, TestEnvironment, true); MigrationItemStrings file2 = new MigrationItemStrings("source/file2.txt", null, TestEnvironment, true); int firstChangeset = SourceAdapter.AddFile(file1.LocalPath); int editBeforeSnapShot = SourceAdapter.EditFile(file1.LocalPath); int snapshotChangesetId = SourceAdapter.AddFile(file2.LocalPath); SourceAdapter.BranchItem(branch); TestEnvironment.SnapshotBatchSize = 10; TestEnvironment.SnapshotStartPoints = new Dictionary <string, string>(); TestEnvironment.SnapshotStartPoints.Add(TestEnvironment.SourceEndPoint.TeamProject, snapshotChangesetId.ToString()); Run(); // Resolve "Branch source path not found conflict" using "$/" scope. ConflictResolver conflictManager = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictManager.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be only 1 conflict"); conflictManager.TryResolveConflict(conflicts[0], ConflictConstant.TFSHistoryNotFoundSkipAction, string.Format("{0}-{1}", firstChangeset, snapshotChangesetId)); // Add on branch source not found Run(); Assert.IsTrue(VerifyContents()); }
public void RenameWithSourceNotMappedTest() { MigrationItemStrings folder = new MigrationItemStrings("rename-from", "rename-to", TestEnvironment, true); MigrationItemStrings file = new MigrationItemStrings("rename-from/fld/file.txt", "rename-to/fld/file.txt", TestEnvironment, true); // Add the child item SourceAdapter.AddFile(file.LocalPath); MappingPair mapping = new MappingPair(TestEnvironment.FirstSourceServerPath + SrcPathSeparator + "rename-from", TestEnvironment.FirstTargetServerPath + TarPathSeparator + "rename-from", true); // cloaked TestEnvironment.AddMapping(mapping); SourceWorkspace.Get(VersionSpec.Latest, GetOptions.Overwrite); SourceWorkspace.PendRename(folder.ServerPath, folder.NewServerPath); SourceAdapter.EditFile(file.NewLocalPath); Run(); VerifyHistory(3, 0); // Resolve "Branch source path not found conflict" using "$/" scope. ConflictResolver conflictManager = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictManager.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be only 1 conflict"); conflictManager.TryResolveConflict(conflicts[0], new VCChangeToAddOnBranchSourceNotMappedAction(), "$/"); // Add on branch source not found RunAndValidate(true, true); }
private void AssertConflictDetection(string fileName, RavenJObject localMetadata, RavenJObject sourceMetadata, ServerInfo sourceServer, out bool isConflictResolved) { var conflict = ConflictDetector.Check(fileName, localMetadata, sourceMetadata, sourceServer.FileSystemUrl); if (conflict == null) { isConflictResolved = false; return; } isConflictResolved = ConflictResolver.CheckIfResolvedByRemoteStrategy(localMetadata, conflict); if (isConflictResolved) { return; } ConflictResolutionStrategy strategy; if (ConflictResolver.TryResolveConflict(fileName, conflict, localMetadata, sourceMetadata, out strategy)) { switch (strategy) { case ConflictResolutionStrategy.RemoteVersion: Log.Debug("Conflict automatically resolved by choosing remote version of the file {0}", fileName); return; case ConflictResolutionStrategy.CurrentVersion: Storage.Batch(accessor => { accessor.UpdateFileMetadata(fileName, localMetadata); ConflictArtifactManager.Delete(fileName, accessor); }); Log.Debug("Conflict automatically resolved by choosing current version of the file {0}", fileName); throw new ConflictResolvedInFavourOfCurrentVersionException(); } } ConflictArtifactManager.Create(fileName, conflict); Publisher.Publish(new ConflictNotification { FileName = fileName, SourceServerUrl = sourceServer.FileSystemUrl, Status = ConflictStatus.Detected, RemoteFileHeader = new FileHeader(fileName, localMetadata) }); Log.Debug( "File '{0}' is in conflict with synchronized version from {1} ({2}). File marked as conflicted, conflict configuration item created", fileName, sourceServer.FileSystemUrl, sourceServer.Id); throw new SynchronizationException(string.Format("File {0} is conflicted", fileName)); }
public void EditEditConflictTakeLocalTest() { // 1. migrate a.txt -> a.txt string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, null, TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, null, TestEnvironment, false); SourceAdapter.AddFile(sourceFile.LocalPath); RunAndValidate(); // 2. source system: a.txt -> edit SourceAdapter.EditFile(sourceFile.LocalPath); // 3. target system: a.txt -> edit TargetAdapter.EditFile(targetFile.LocalPath); // 4. Migration will detect a conflict Run(); VerifyHistory(2, 1); // 5. resolve conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); VCContentConflictType contentConflict = new VCContentConflictType(); Assert.AreEqual(contentConflict.ReferenceName, conflicts[0].ConflictTypeReference.Value.ReferenceName, "It should be vc content conflict"); conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictTakeLocalChangeAction(), "$/"); // 6. restart Run(); // 7. validation // no remaining conflicts conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be NO conflict"); if (TestEnvironment.MigrationTestType == MigrationTestType.OneWay) { // content should not match for one-way sync Assert.IsFalse(VerifyContents(), "The latest content should be different as a.txt is not migrated."); SourceAdapter.EditFile(sourceFile.LocalPath); Run(); Assert.IsTrue(VerifyContents()); } else { Assert.IsTrue(VerifyContents()); } }
public void RenameRenameConflictUserMergeTest() { // 1. migrate a.txt -> a.txt string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, "b.txt", TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, "c.txt", TestEnvironment, false); MigrationItemStrings targetUserMergeFile = new MigrationItemStrings("c.txt", "b.txt", TestEnvironment, false); SourceAdapter.AddFile(sourceFile.LocalPath); RunAndValidate(); // 2. source system: a.txt -> b.txt int deltaChangeId = SourceAdapter.RenameItem(sourceFile.ServerPath, sourceFile.NewServerPath); // 3. target system: a.txt -> c.txt TargetAdapter.RenameItem(targetFile.ServerPath, targetFile.NewServerPath); // 4. migrate Run(); VerifyHistory(2, 1); // 5. resolve conflicts // 5.1 User merge actions // The user decided to accept other so he reverted the rename change on target system. c.txt -> a.txt int miChangeId = TargetAdapter.RenameItem(targetUserMergeFile.ServerPath, targetUserMergeFile.NewServerPath, "Rename target items to accept other side's renames **NOMIGRATION**"); // 5.2 resolve conflicts by VCContentConflictUserMergeChangeAction ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); VCNameSpaceContentConflictType nameSpaceContentConflict = new VCNameSpaceContentConflictType(); Assert.IsTrue(nameSpaceContentConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be vc namespace content conflict"); Dictionary <string, string> dataFields = new Dictionary <string, string>(); dataFields.Add(VCContentConflictUserMergeChangeAction.MigrationInstructionChangeId, miChangeId.ToString()); dataFields.Add(VCContentConflictUserMergeChangeAction.DeltaTableChangeId, deltaChangeId.ToString()); conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictUserMergeChangeAction(), string.Format("$/;{0}", deltaChangeId), dataFields); // 6. Migration will detect a conflict Run(true, true); Assert.IsTrue(VerifyContents()); SourceAdapter.EditFile(sourceFile.NewLocalPath); Run(true, true); Assert.IsTrue(VerifyContents()); }
public void EditEditConflictUserMergeTest() { // 1. migrate a.txt -> a.txt string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, null, TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, null, TestEnvironment, false); SourceAdapter.AddFile(sourceFile.LocalPath); RunAndValidate(); // 2. source system: a.txt -> edit int contentConflictChangeset = SourceAdapter.EditFile(sourceFile.LocalPath); // 3. target system: a.txt -> edit TargetAdapter.EditFile(targetFile.LocalPath); // 4. Migration will detect a conflict Run(); VerifyHistory(2, 1); // 5. resolve conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); VCContentConflictType contentConflict = new VCContentConflictType(); Assert.IsTrue(contentConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be vc content conflict"); int deltaChangeId = SourceAdapter.EditFile(sourceFile.LocalPath); int miChangeId = TargetAdapter.EditFile(targetFile.LocalPath, sourceFile.LocalPath); Dictionary <string, string> dataFields = new Dictionary <string, string>(); dataFields.Add(VCContentConflictUserMergeChangeAction.MigrationInstructionChangeId, miChangeId.ToString()); dataFields.Add(VCContentConflictUserMergeChangeAction.DeltaTableChangeId, deltaChangeId.ToString()); conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictUserMergeChangeAction(), string.Format("$/;{0}", contentConflictChangeset), dataFields); // 6. restart Run(true, true); // 7. validation // no remaining conflicts conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be NO conflict"); // content should match Assert.IsTrue(VerifyContents()); }
public void EditEditMultipleItemsTest() { // 1. migrate a.txt -> a.txt string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, null, TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, null, TestEnvironment, false); MigrationItemStrings nonConflictFile = new MigrationItemStrings("b.txt", null, TestEnvironment, true); SourceAdapter.AddFile(sourceFile.LocalPath); SourceAdapter.AddFile(nonConflictFile.LocalPath); RunAndValidate(); // 2. source system: a.txt -> edit SourceWorkspace.Get(VersionSpec.Latest, GetOptions.Overwrite); TestUtils.EditRandomFile(nonConflictFile.LocalPath); SourceWorkspace.PendEdit(nonConflictFile.LocalPath); // This will checkin both a.txt and b.txt int contentConflictChangeset = SourceAdapter.EditFile(sourceFile.LocalPath); // 3. target system: a.txt -> edit TargetAdapter.EditFile(targetFile.LocalPath); // 4. Migration will detect a conflict Run(); VerifyHistory(2, 1); // 5. resolve conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(2, conflicts.Count, "There should be 2 conflicts"); VCContentConflictType contentConflict = new VCContentConflictType(); Assert.IsTrue(contentConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be vc content conflict"); conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictTakeLocalChangeAction(), "$/"); // 6. restart Run(true, true); // TfsCheckinConflict needs to be resolved manually. Otherwise, this test will loop until time-out. // 7. validation // no remaining conflicts conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be NO conflict"); // content should not match Assert.IsFalse(VerifyContents(), "The latest content should be different as a.txt is not migrated."); }
public void InvalidFieldConflictUseFieldMapTest() { TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(SetInvalidFieldMap); // add a work item on source side string title = string.Format("{0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemId = SourceAdapter.AddWorkItem("Bug", title, "description1"); WITChangeAction action1 = new WITChangeAction(); action1.Priority = "3"; SourceAdapter.UpdateWorkItem(workitemId, action1); // sync RunAndNoValidate(); // verify we have InvalidField conflict m_conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = m_conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count >= 1, "There is no active conflict"); Assert.IsTrue(ConflictConstant.InvalidFieldConflictType.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "The first active conflict is not a WIT invalid field conflict"); Dictionary <string, string> dataFields = new Dictionary <string, string>(); dataFields.Add("MapFrom", InvalidFieldRefName); dataFields.Add("MapTo", FIELD_DESCRIPTION); dataFields.Add(Constants.DATAKEY_UPDATED_CONFIGURATION_ID, "1"); m_conflictResolver.TryResolveConflict(conflicts[0], ConflictConstant.InvalidFieldConflictUseFieldMapAction, conflicts[0].ScopeHint, dataFields); // restart the migration tool RunAndNoValidate(true); conflicts = m_conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count == 0, "There should be no conflict"); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches due to test environments VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); }
public void AddAddConflictTakeLocalTest() { // initial migration MigrationItemStrings file1 = new MigrationItemStrings("1.txt", "1.txt", TestEnvironment, true); SourceAdapter.AddFile(file1.LocalPath); RunAndValidate(); // add a same file on both ends string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, fileName, TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, fileName, TestEnvironment, false); int sourceAdd = SourceAdapter.AddFile(sourceFile.LocalPath); TargetAdapter.AddFile(targetFile.LocalPath); Run(); VerifyHistory(2, 1); // resolve conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); VCContentConflictType contentConflict = new VCContentConflictType(); Assert.IsTrue(contentConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be vc content conflict"); // resolve the vc content conflict. The chained conflict will be resolved automatically conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictTakeLocalChangeAction(), "$/"); // continue migration Run(true, true); conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be 0 conflict"); Assert.IsFalse(VerifyContents(), "Content should be different as we skip the add from source system."); SourceAdapter.EditFile(sourceFile.LocalPath); Run(true, true); Assert.IsTrue(VerifyContents()); }
public void InvalidFieldValueConflict_ResolveByDroppingFieldTest() { TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(SetInvalidFieldValueMap); TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_DisableBypassRulesOnTarget); // add a work item on source side string title = string.Format("{0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemId = SourceAdapter.AddWorkItem("Bug", title, "description1"); WITChangeAction action1 = new WITChangeAction(); action1.Priority = "1"; SourceAdapter.UpdateWorkItem(workitemId, action1); // sync RunAndNoValidate(); // verify we have InvalidField conflict m_conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = m_conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count >= 1, "There is no active conflict"); Assert.IsTrue(ConflictConstant.InvalidFieldValueConflictType.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "The first active conflict is not a WIT invalid field value conflict"); Dictionary <string, string> dataFields = new Dictionary <string, string>(); dataFields.Add("InvalidFieldReferenceName", FIELD_PRIORITY); dataFields.Add(Constants.DATAKEY_UPDATED_CONFIGURATION_ID, "1"); var rslvRslt = m_conflictResolver.TryResolveConflict( conflicts[0], new Guid("3C8FE19D-3D02-4a19-BC5A-77640B0F5904"), "/", dataFields); Assert.IsTrue(rslvRslt, "Conflict resolution failed"); // sync again RunAndNoValidate(true); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches due to test environments VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH, "Priority" /*FIELD_PRIORITY teyang: verification uses field name rather than ref name*/ }); }
public void HistoryNotFound_ResolveByUpdateConvHistory() { this.TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_EnableBypassRulesOnTarget); this.TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(ConfigCustomizer.CustomActions_DisableContextSync); // add a work item on source side string title = string.Format("{0} {1}", TestContext.TestName, DateTime.Now.ToString("HH'_'mm'_'ss")); int workitemId = SourceAdapter.AddWorkItem("Bug", title, "description1"); WITChangeAction action = new WITChangeAction(); action.Priority = "3"; SourceAdapter.UpdateWorkItem(workitemId, action); action = new WITChangeAction(); action.Priority = "2"; SourceAdapter.UpdateWorkItem(workitemId, action); // sync again and expect conflict RunAndNoValidate(); // check conflicts m_conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = m_conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count >= 1, "There is no active conflict"); Assert.IsTrue(ConflictConstant.WitHistoryNotFoundConflictType.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "The first active conflict is not a history-not-found conflict"); Dictionary <string, string> dataFields = new Dictionary <string, string>(); dataFields.Add("Source Item Id", workitemId.ToString()); dataFields.Add("Source Revisions", "1"); dataFields.Add("Target Item Id", "17526" /*"@@PLACE_HOLDER@@"*/); dataFields.Add("Target Revisions", "1"); m_conflictResolver.TryResolveConflict(conflicts[0], ConflictConstant.HistoryNotFoundUpdateConversionHistoryAction, conflicts[0].ScopeHint, dataFields); RunAndNoValidate(true); m_conflictResolver = new ConflictResolver(Configuration); conflicts = m_conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count == 0, "There is unresolved conflict"); }
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 InvalidFieldConflictUseFieldMapCaseInsensitiveTest() { // Same as InvalidFieldConflictUseFieldMappTest except testing // case-sensitivity of the resolution rule TestEnvironment.CustomActions += new MigrationTestEnvironment.Customize(SetInvalidFieldMap); // add a work item on source side int workitemId = SourceAdapter.AddWorkItem("Bug", "title", "description1"); // sync RunAndNoValidate(); // verify we have InvalidField conflict m_conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = m_conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count >= 1, "There is no active conflict"); Assert.IsTrue(ConflictConstant.InvalidFieldConflictType.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "The first active conflict is not a WIT invalid field conflict"); Dictionary <string, string> dataFields = new Dictionary <string, string>(); dataFields.Add("MapFrom", InvalidFieldRefName.ToUpper()); // use upper case dataFields.Add("MapTo", FIELD_DESCRIPTION.ToLower()); // use lower case dataFields.Add(Constants.DATAKEY_UPDATED_CONFIGURATION_ID, "1"); m_conflictResolver.TryResolveConflict(conflicts[0], ConflictConstant.InvalidFieldConflictUseFieldMapAction, conflicts[0].ScopeHint, dataFields); // restart the migration tool RunAndNoValidate(true); conflicts = m_conflictResolver.GetConflicts(); Assert.IsTrue(conflicts.Count == 0, "There should be no conflict"); // verify sync result WitDiffResult result = GetDiffResult(); // ignore Area/Iteration path mismatches due to test environments VerifySyncResult(result, new List <string> { FIELD_ITERATION_PATH, FIELD_AREA_PATH }); }
public void EditMultipleEditConflictTakeOtherTest() { // 1. migrate a.txt -> a.txt string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, null, TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, null, TestEnvironment, false); MigrationItemStrings targetFile2 = new MigrationItemStrings("b.txt", null, TestEnvironment, false); SourceAdapter.AddFile(sourceFile.LocalPath); RunAndValidate(); // 2. source system: a.txt -> edit SourceAdapter.EditFile(sourceFile.LocalPath); // 3. target system: a.txt -> edit TargetAdapter.EditFile(targetFile.LocalPath); TargetAdapter.EditFile(targetFile.LocalPath); // 4. Migration will detect a conflict Run(); VerifyHistory(2, 2); // 5. resolve conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); VCContentConflictType contentConflict = new VCContentConflictType(); Assert.IsTrue(contentConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be vc content conflict"); conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictTakeOtherChangesAction(), "$/"); // 6. restart Run(true, true); // 7. validation // no remaining conflicts conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be NO conflict"); // content should match Assert.IsTrue(VerifyContents()); }
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 AddAddConflictUserMergeTest() { string fileName = "file.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, fileName, TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, fileName, TestEnvironment, false); // Initial sync. Run(); int deltaChangeId = SourceAdapter.AddFile(sourceFile.LocalPath); TargetAdapter.AddFile(targetFile.LocalPath); // Don't check in extra.txt Run(false, false, false); VerifyHistory(1, 1); // User checkin files to make the system in sync. int miChangeId = TargetAdapter.EditFile(targetFile.LocalPath, sourceFile.LocalPath, "user: delete items on target to resolve add,add conflict **NOMIGRATION**"); // resolve conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); VCContentConflictType contentConflict = new VCContentConflictType(); Assert.IsTrue(contentConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be vc content conflict"); Dictionary <string, string> dataFields = new Dictionary <string, string>(); dataFields.Add(VCContentConflictUserMergeChangeAction.MigrationInstructionChangeId, miChangeId.ToString()); dataFields.Add(VCContentConflictUserMergeChangeAction.DeltaTableChangeId, deltaChangeId.ToString()); conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictUserMergeChangeAction(), string.Format("{0};{1}", "$/", (deltaChangeId - 1).ToString()), dataFields); Run(true, true, false); Assert.IsTrue(VerifyContents()); }
public void BranchMergeDeleteWithSourceNotMappedTest() { MigrationItemStrings branch = new MigrationItemStrings("source", "target", TestEnvironment, true); MigrationItemStrings file = new MigrationItemStrings("source/fld/file.txt", "target/fld/file.txt", TestEnvironment, true); // Add the parent folder at branch from place SourceAdapter.AddFolder(branch.LocalPath); MappingPair mapping = new MappingPair(TestEnvironment.FirstSourceServerPath + SrcPathSeparator + "source", TestEnvironment.FirstTargetServerPath + TarPathSeparator + "source", true); // cloaked TestEnvironment.AddMapping(mapping); // Branch the parent folder int branchChangeset = SourceAdapter.BranchItem(branch.ServerPath, branch.NewServerPath); // Add the child item SourceAdapter.AddFile(file.LocalPath); SourceWorkspace.Merge(branch.ServerPath, branch.NewServerPath, VersionSpec.ParseSingleSpec(branchChangeset.ToString(), Environment.UserName), VersionSpec.Latest, LockLevel.None, RecursionType.Full, MergeOptions.None); ResolveConflicts(Resolution.AcceptTheirs); SourceAdapter.DeleteItem(file.NewServerPath); Run(); VerifyHistory(4, 0); // Resolve "Branch source path not found conflict" using "$/" scope. ConflictResolver conflictManager = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictManager.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be only 1 conflict"); conflictManager.TryResolveConflict(conflicts[0], new VCChangeToAddOnBranchSourceNotMappedAction(), "$/"); // Add on branch source not found Run(true, true); Assert.IsTrue(VerifyContents()); }
public async Task <HttpResponseMessage> ResolutionStrategyFromServerResolvers() { var conflict = await ReadJsonObjectAsync <ConflictItem>(); var localMetadata = GetLocalMetadata(conflict.FileName); if (localMetadata == null) { throw new InvalidOperationException(string.Format("Could not find the medatada of the file: {0}", conflict.FileName)); } var sourceMetadata = GetFilteredMetadataFromHeaders(ReadInnerHeaders); ConflictResolutionStrategy strategy; if (ConflictResolver.TryResolveConflict(conflict.FileName, conflict, localMetadata, sourceMetadata, out strategy)) { return(GetMessageWithObject(strategy)); } return(GetMessageWithObject(ConflictResolutionStrategy.NoResolution)); }
public void AddAddConflictTakeOtherTest() { // 1. migrate a.txt -> a.txt string fileName1 = "a.txt"; string fileName2 = "b.txt"; string sameFileName = "same.txt"; MigrationItemStrings sourceFile1 = new MigrationItemStrings(fileName1, null, TestEnvironment, true); MigrationItemStrings sourceSameFile = new MigrationItemStrings(sameFileName, null, TestEnvironment, true); MigrationItemStrings targetFile1 = new MigrationItemStrings(fileName2, null, TestEnvironment, false); MigrationItemStrings targetSameFile = new MigrationItemStrings(sameFileName, null, TestEnvironment, false); SourceAdapter.AddFiles(new string[] { sourceFile1.LocalPath, sourceSameFile.LocalPath }); TargetAdapter.AddFiles(new string[] { targetFile1.LocalPath, targetSameFile.LocalPath }); // 4. Migration will detect a conflict Run(); // 5. resolve conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); VCContentConflictType contentConflict = new VCContentConflictType(); Assert.AreEqual(contentConflict.ReferenceName, conflicts[0].ConflictTypeReference.Value.ReferenceName, "It should be vc content conflict"); conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictTakeOtherChangesAction(), conflicts[0].ScopeHint); // sync Run(); // validation // no remaining conflicts conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be NO conflict"); // content should match Assert.IsTrue(VerifyContents(), "The latest content should match."); }
public void CloakedSourceMappingsTest() { MigrationItemStrings branch = new MigrationItemStrings("source", "target", TestEnvironment, true); MigrationItemStrings file = new MigrationItemStrings("source" + SourceAdapter.PathSeparator + "file.txt", "source" + SourceAdapter.PathSeparator + "renamedFile.txt", TestEnvironment, true); SourceAdapter.AddFile(file.LocalPath); MappingPair mapping = new MappingPair(TestEnvironment.FirstSourceServerPath + SrcPathSeparator + "source", TestEnvironment.FirstTargetServerPath + TarPathSeparator + "source", true); // cloaked TestEnvironment.AddMapping(mapping); int branchChangeset = SourceAdapter.BranchItem(branch.ServerPath, branch.NewServerPath); SourceAdapter.EditFile(m_extraFile.LocalPath); SourceAdapter.EditFile(file.LocalPath); SourceAdapter.RenameItem(file.ServerPath, file.NewServerPath); SourceWorkspace.Merge(branch.ServerPath, branch.NewServerPath, VersionSpec.ParseSingleSpec(branchChangeset.ToString(), Environment.UserName), VersionSpec.Latest, LockLevel.None, RecursionType.Full, MergeOptions.None); ResolveConflicts(Resolution.AcceptTheirs); SourceWorkspace.CheckIn(SourceWorkspace.GetPendingChanges(), MergeComment); Run(); VerifyHistory(5, 0); // Resolve "Branch source path not found conflict" using "$/" scope. ConflictResolver conflictManager = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictManager.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be only 1 conflict"); conflictManager.TryResolveConflict(conflicts[0], new VCChangeToAddOnBranchSourceNotMappedAction(), "$/"); // Add on branch source not found RunAndValidate(true, true); }
public void AddAddConflictTakeOtherTest() { // initial migration MigrationItemStrings file1 = new MigrationItemStrings("1.txt", "1.txt", TestEnvironment, true); SourceAdapter.AddFile(file1.LocalPath); RunAndValidate(); // add a same file on both ends string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, fileName, TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, fileName, TestEnvironment, false); SourceAdapter.AddFile(sourceFile.LocalPath); TargetAdapter.AddFile(targetFile.LocalPath); Run(); VerifyHistory(2, 1); // resolve conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); VCContentConflictType contentConflict = new VCContentConflictType(); Assert.IsTrue(contentConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be vc content conflict"); // resolve the vc content conflict. The chained conflict will be resolved automatically conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictTakeOtherChangesAction(), "$/"); // The user decide to accept other, so he deleted the items on target system TargetAdapter.DeleteItem(targetFile.ServerPath, "Delete source items to accept other side's adds **NOMIGRATION**"); Run(true, true); Assert.IsTrue(VerifyContents()); }
public void SnapshotMergeRenameEditTest() { // scenario // branch from source to target where source is cloaked // take the snapshot of target branch // item1 on source renamed,edited // item1 was merged to target // VC session converts merge,rename,edit to add,edit // cloak branch from path MappingPair mapping = new MappingPair( TestEnvironment.FirstSourceServerPath + SrcPathSeparator + "source", TestEnvironment.FirstTargetServerPath + TarPathSeparator + "source", true); TestEnvironment.AddMapping(mapping); MigrationItemStrings file1 = new MigrationItemStrings( string.Format("source{0}folder1{1}file1.txt", SrcPathSeparator, SrcPathSeparator), string.Format("source{0}folder2{1}file1.txt", SrcPathSeparator, SrcPathSeparator), TestEnvironment, true); MigrationItemStrings file2 = new MigrationItemStrings( string.Format("source{0}folder2{1}file2.txt", SrcPathSeparator, SrcPathSeparator), null, TestEnvironment, true); MigrationItemStrings file3 = new MigrationItemStrings( string.Format("source{0}folder1{1}file3.txt", SrcPathSeparator, SrcPathSeparator), string.Format("source{0}folder2{1}file3.txt", SrcPathSeparator, SrcPathSeparator), TestEnvironment, true); // branch SourceAdapter.AddFile(file1.LocalPath); SourceAdapter.AddFile(file2.LocalPath); SourceAdapter.AddFile(file3.LocalPath); int changesetId = SourceAdapter.BranchItem(source.ServerPath, target.ServerPath); int snapshotChangesetId = SourceAdapter.EditFile(file2.LocalPath); // pend edit on file1 SourceWorkspace.PendEdit(file1.LocalPath); TestUtils.EditRandomFile(file1.LocalPath); // pend rename (file1 is moved to a different location) SourceWorkspace.PendRename(file1.LocalPath, file1.NewLocalPath); // pend edit on file2 SourceWorkspace.PendEdit(file2.LocalPath); TestUtils.EditRandomFile(file2.LocalPath); // pend rename (file3 is moved to a different location) SourceWorkspace.PendEdit(file3.LocalPath); SourceWorkspace.PendRename(file3.LocalPath, file3.NewLocalPath); SourceWorkspace.CheckIn(SourceWorkspace.GetPendingChanges(), "rename, edit"); // merge changes from source to target // - merge,rename,edit on file1 // - merge,edit on file2 // - merge,rename on file3 SourceWorkspace.Merge(source.LocalPath, target.LocalPath, VersionSpec.ParseSingleSpec(changesetId.ToString(), Environment.UserName), VersionSpec.Latest, LockLevel.None, RecursionType.Full, MergeOptions.None); resolveConflictAcceptThiers(); changesetId = SourceWorkspace.CheckIn(SourceWorkspace.GetPendingChanges(), "merge,rename,edit"); // snapshot TestEnvironment.SnapshotStartPoints = new Dictionary <string, string>(); TestEnvironment.SnapshotStartPoints.Add(TestEnvironment.SourceTeamProject, snapshotChangesetId.ToString()); TestEnvironment.SnapshotBatchSize = 100; Run(); // Resolve "Branch source path not found conflict" using "$/" scope. ConflictResolver conflictManager = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictManager.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be only 1 conflict"); conflictManager.TryResolveConflict(conflicts[0], new VCChangeToAddOnBranchSourceNotMappedAction(), "$/"); // Add on branch source not found Run(); Assert.IsTrue(VerifyContents()); }
public void PathSnapshotBranchTest() { MigrationItemStrings branch = new MigrationItemStrings("source/", "target/", TestEnvironment, true); MigrationItemStrings branch2 = new MigrationItemStrings("source/", "target2/", TestEnvironment, true); MigrationItemStrings[] addFiles = new MigrationItemStrings[10]; // Add files // Create a tree structure so that we can test path compression logic. int sessionSnapshotChangesetId = 1; for (int i = 0; i < 10; i++) { addFiles[i] = new MigrationItemStrings( string.Format("source/addFile{0}.txt", i), string.Format("source/addFile{0}-rename.txt", i), TestEnvironment, true); SourceAdapter.AddFile(addFiles[i].LocalPath); } int editBeforeSnapshotChangesetId = SourceAdapter.EditFile(addFiles[2].LocalPath); int editBeforeSnapshotChangesetId2 = SourceAdapter.EditFile(addFiles[2].LocalPath); SourceAdapter.RenameItem(addFiles[3].ServerPath, addFiles[3].NewServerPath, "Rename before snapshot"); int deleteChangesetID = SourceAdapter.DeleteItem(addFiles[4].ServerPath); SourceAdapter.DeleteItem(addFiles[5].ServerPath); SourceAdapter.UndeleteFile(addFiles[4].ServerPath, deleteChangesetID); int path2SnapshotChangesetId = SourceAdapter.RenameItem(addFiles[6].ServerPath, addFiles[6].NewServerPath, "Rename before snapshot"); int editAfterSnapshotChangesetId = SourceAdapter.EditFile(addFiles[6].NewLocalPath); int editAfterSnapshotChangesetId2 = SourceAdapter.EditFile(addFiles[6].NewLocalPath); SourceAdapter.DeleteItem(addFiles[4].ServerPath); SourceAdapter.RenameItem(addFiles[3].NewServerPath, addFiles[3].ServerPath, "Rename after snapshot"); // Branch from a version before the snapshot SourceWorkspace.Get(VersionSpec.Latest, GetOptions.Overwrite); SourceWorkspace.PendBranch(branch.ServerPath, branch.NewServerPath, new ChangesetVersionSpec(editBeforeSnapshotChangesetId)); SourceWorkspace.CheckIn(SourceWorkspace.GetPendingChanges(), "Branch from a version before snapshot"); SourceAdapter.BranchItem(branch2.ServerPath, branch2.NewServerPath); TestEnvironment.SnapshotStartPoints = new Dictionary <string, string>(); TestEnvironment.SnapshotStartPoints.Add(TestEnvironment.SourceTeamProject, sessionSnapshotChangesetId.ToString()); TestEnvironment.SnapshotBatchSize = 3; // We need to map to the sub item level MappingPair rootMapping = TestEnvironment.Mappings[0]; TestEnvironment.Mappings.Clear(); TestEnvironment.Mappings.Add(new MappingPair(rootMapping.SourcePath + "/target", rootMapping.TargetPath + "/target", false)); TestEnvironment.Mappings.Add(new MappingPair(rootMapping.SourcePath + "/target2", rootMapping.TargetPath + "/target2", false)); TestEnvironment.Mappings.Add(new MappingPair(rootMapping.SourcePath + "/source", rootMapping.TargetPath + "/source", false, path2SnapshotChangesetId.ToString(), null)); Run(); ConflictResolver conflictManager = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictManager.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be only 1 conflict"); conflictManager.TryResolveConflict(conflicts[0], ConflictConstant.TFSHistoryNotFoundSkipAction, "1-" + path2SnapshotChangesetId); Run(true, true); // ToDo, ideally, we should compare content at snapshot changeset and compare history after snapshot changeset. Assert.IsTrue(VerifyContents()); }
public void BranchMergeRenameEditTest() { #region repro steps //1. add $/test/main/a/1.txt //2. branch main to main-branch //3. add $/test/main/b/1.txt //4. tf merge $/test/main $/test/main-branch /r //5. rename $/test/main/b/1.txt to $/test/main/b/2.txt //6. tf merge $/test/main $/test/main-branch /r // resolve a conflict by taking the source branch change // edit $/test/main-branch/2.txt // check in // (2.txt == merge,rename,edit) //7. add $/test/main/b/1.txt //8. tf merge $/test/main $/test/main-branch /r //9. create a configuration file and map server paths like below: //<FilterPair> //<FilterItem MigrationSourceUniqueId="1ebfa76e-6f49-4ec8-b25d-03aac1b05085" FilterString="$/test/main-branch" /> //<FilterItem MigrationSourceUniqueId="67502947-0a21-4a6a-b169-7857d7e9e641" FilterString="$/test/main-branch2" /> //</FilterPair> //10. start migration console app using the config file generated in the step 9 //11. conflict detection - branch root not found //12. resolve the conflict and allow $/ for scope //13. re-start the migration consonle app //14. the exception gets thrown #endregion // 1. add $/test/main/a/1.txt MigrationItemStrings path1 = new MigrationItemStrings("main", "main-branch", TestEnvironment, true); MigrationItemStrings file1 = new MigrationItemStrings("main/a/1.txt", null, TestEnvironment, true); SourceAdapter.AddFolder(path1.LocalPath); SourceAdapter.AddFile(file1.LocalPath); // 2. branch main to main-branch SourceAdapter.BranchItem(path1.ServerPath, path1.NewServerPath); // 3. add $/test/main/b/1.txt MigrationItemStrings file2 = new MigrationItemStrings("main/b/1.txt", "main/b/2.txt", TestEnvironment, true); MigrationItemStrings file3 = new MigrationItemStrings("main-branch/b/1.txt", "main-branch/b/2.txt", TestEnvironment, true); int mergeFromVersion = SourceAdapter.AddFile(file2.LocalPath); // 4. tf merge $/test/main $/test/main-branch /r SourceWorkspace.Merge(path1.ServerPath, path1.NewServerPath, VersionSpec.ParseSingleSpec(mergeFromVersion.ToString(), Environment.UserName), VersionSpec.Latest, LockLevel.None, RecursionType.Full, MergeOptions.None); SourceWorkspace.CheckIn(SourceWorkspace.GetPendingChanges(), MergeComment); // 5. rename $/test/main/b/1.txt to $/test/main/b/2.txt SourceAdapter.RenameItem(file2.ServerPath, file2.NewServerPath); // 6. tf merge $/test/main $/test/main-branch /r SourceWorkspace.Merge(path1.ServerPath, path1.NewServerPath, VersionSpec.ParseSingleSpec(mergeFromVersion.ToString(), Environment.UserName), VersionSpec.Latest, LockLevel.None, RecursionType.Full, MergeOptions.None); ResolveConflicts(Resolution.AcceptTheirs); SourceAdapter.EditFile(file3.NewLocalPath); // merge,rename,edit (edit the pending item 2.txt) // 7. add $/test/main/b/1.txt mergeFromVersion = SourceAdapter.AddFile(file2.LocalPath); // reuse the same file name // 8. tf merge $/test/main $/test/main-branch /r SourceWorkspace.Merge(path1.ServerPath, path1.NewServerPath, VersionSpec.ParseSingleSpec(mergeFromVersion.ToString(), Environment.UserName), VersionSpec.Latest, LockLevel.None, RecursionType.Full, MergeOptions.None); SourceWorkspace.CheckIn(SourceWorkspace.GetPendingChanges(), MergeComment); // 9. migrate main-branch only string source = TestEnvironment.FirstSourceServerPath + SrcPathSeparator + "main-branch"; string target = TestEnvironment.FirstTargetServerPath + TarPathSeparator + "main-branch"; TestEnvironment.Mappings.Clear(); TestEnvironment.AddMapping(new MappingPair(source, target)); // 10. start migration Run(); VerifyHistory(4, 0); // Resolve "Branch source path not found conflict" using "$/" scope. ConflictResolver conflictManager = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictManager.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be only 1 conflict"); conflictManager.TryResolveConflict(conflicts[0], new VCChangeToAddOnBranchSourceNotMappedAction(), "$/"); // Add on branch source not found if (TestEnvironment.SourceTFSVersion == TFSVersionEnum.TFS2010) { Run(true, true); // verify expected differences VerifyHistory(1, 1); //Changeset targetChangeset = diff.TargetChanges[0]; //Changeset sourceChangeset = diff.SourceChanges[0]; //diff.ChangesetDiff(ref targetChangeset, ref sourceChangeset); //Assert.AreEqual(1, sourceChangeset.Changes.Length); //Assert.AreEqual(ChangeType.Merge | ChangeType.Undelete | ChangeType.Edit, // sourceChangeset.Changes[0].ChangeType & ~ChangeType.Encoding); //Assert.AreEqual(1, targetChangeset.Changes.Length); //Assert.AreEqual(ChangeType.Add | ChangeType.Edit, // targetChangeset.Changes[0].ChangeType & ~ChangeType.Encoding); // verify content matches Assert.IsTrue(VerifyContents(), "Content mismatch"); } else { RunAndValidate(true, true); } }
public void RenameEditConflictUserMergeTest() { // 1. migrate a.txt -> a.txt string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, "b.txt", TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, "b.txt", TestEnvironment, false); SourceAdapter.AddFile(sourceFile.LocalPath); RunAndValidate(); // 2. source system: a.txt -> b.txt int deltaChangeId = SourceAdapter.RenameItem(sourceFile.ServerPath, sourceFile.NewServerPath); // 3. target system: a.txt -> edit a.txt int editChangesetId = TargetAdapter.EditFile(targetFile.LocalPath); // 4. migrate Run(); // 5. resolve conflicts // 5.1 check if we have correct conflicts in db ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be only 1 conflict"); VCNameSpaceContentConflictType namespaceConflict = new VCNameSpaceContentConflictType(); Assert.IsTrue(namespaceConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be vc namespace content conflict"); // 5.2 user merge actions // 1) revert edit on a.txt // revert edit on a.txt PendEditToRevertFile(TargetWorkspace, targetFile, editChangesetId, editChangesetId - 1); TargetWorkspace.CheckIn(TargetWorkspace.GetPendingChanges(), "user: revert edit change on a.txt **NOMIGRATION**"); // 2) rename a.txt to b.txt on target system int miChangeId = TargetAdapter.RenameItem(targetFile.ServerPath, targetFile.NewServerPath, "user: rename a.txt to b.txt **NOMIGRATION**"); Dictionary <string, string> dataFields = new Dictionary <string, string>(); dataFields.Add(VCContentConflictUserMergeChangeAction.MigrationInstructionChangeId, miChangeId.ToString()); dataFields.Add(VCContentConflictUserMergeChangeAction.DeltaTableChangeId, deltaChangeId.ToString()); foreach (RTConflict conflict in conflicts) { conflictResolver.TryResolveConflict(conflict, new VCContentConflictUserMergeChangeAction(), string.Format("$/;{0}", deltaChangeId), dataFields); } // 6. migrate Run(true, true); // 7. validation // no remaining conflicts conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be NO conflict"); // content match Assert.IsTrue(VerifyContents()); }
public void EditRenameConflictTakeMergeTest() { // 1. migrate a.txt -> a.txt string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, null, TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, "b.txt", TestEnvironment, false); int changeset; changeset = SourceAdapter.AddFile(sourceFile.LocalPath); TraceManager.TraceInformation("Add Changeset: {0}, {1}", changeset, SourceAdapter.AdapterType); RunAndValidate(); // 2. source system: a.txt -> b.txt int editChangesetId = SourceAdapter.EditFile(sourceFile.LocalPath); TraceManager.TraceInformation("Edit Changeset: {0}, {1}", editChangesetId, SourceAdapter.AdapterType); // 3. target system: a.txt -> edit changeset = TargetAdapter.RenameItem(targetFile.ServerPath, targetFile.NewServerPath); TraceManager.TraceInformation("Rename Changeset: {0}, {1}", changeset, TargetAdapter.AdapterType); // 4. Migration will detect a conflict Run(); // 5. resolve conflicts // 5.1 check if we have correct conflicts in db ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be only 1 conflict"); VCNameSpaceContentConflictType namespaceConflict = new VCNameSpaceContentConflictType(); Assert.AreEqual(namespaceConflict.ReferenceName, conflicts[0].ConflictTypeReference.Value.ReferenceName, "It should be vc namespace content conflict"); // 5.2 user actions // // revert edit on a.txt PendEditToRevertFile(SourceWorkspace, sourceFile, editChangesetId, editChangesetId - 1); int sourceChangeId = SourceWorkspace.CheckIn(SourceWorkspace.GetPendingChanges(), "user: revert edit change on a.txt **NOMIGRATION**"); TraceManager.TraceInformation("Undo Edit Changeset: {0}, {1}", sourceChangeId, SourceAdapter.AdapterType); // revert rename on target int targetChangeId = TargetAdapter.RenameItem(targetFile.NewServerPath, targetFile.ServerPath, "Revert rename change on target side **NOMIGRATION**"); TraceManager.TraceInformation("Undo Rename Changeset: {0}, {1}", targetChangeId, TargetAdapter.AdapterType); int deltaChangeId = sourceChangeId; int miChangeId = targetChangeId; if (TestEnvironment.MigrationTestType == MigrationTestType.TwoWayRight) { deltaChangeId = targetChangeId; miChangeId = sourceChangeId; } // resolve conflicts Dictionary <string, string> dataFields = new Dictionary <string, string>(); dataFields.Add(VCContentConflictUserMergeChangeAction.MigrationInstructionChangeId, miChangeId.ToString()); dataFields.Add(VCContentConflictUserMergeChangeAction.DeltaTableChangeId, deltaChangeId.ToString()); foreach (RTConflict conflict in conflicts) { conflictResolver.TryResolveConflict(conflict, new VCContentConflictUserMergeChangeAction(), "$/", dataFields); } // 6. migrate Run(); // 7. validation // no remaining conflicts and content match conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(0, conflicts.Count, "There should be NO conflict"); // content match Assert.IsTrue(VerifyContents()); }
public void AddAddConflictTakeOtherNoDeleteTest() { // initial migration MigrationItemStrings file1 = new MigrationItemStrings("1.txt", "1.txt", TestEnvironment, true); SourceAdapter.AddFile(file1.LocalPath); RunAndValidate(); // add a same file on both ends string fileName = "a.txt"; MigrationItemStrings sourceFile = new MigrationItemStrings(fileName, fileName, TestEnvironment, true); MigrationItemStrings targetFile = new MigrationItemStrings(fileName, fileName, TestEnvironment, false); int sourceAdd = SourceAdapter.AddFile(sourceFile.LocalPath); TargetAdapter.AddFile(targetFile.LocalPath); Run(); VerifyHistory(2, 1); // resolve conflicts ConflictResolver conflictResolver = new ConflictResolver(Configuration); List <RTConflict> conflicts = conflictResolver.GetConflicts(); Assert.AreEqual(1, conflicts.Count, "There should be 1 conflict"); VCContentConflictType contentConflict = new VCContentConflictType(); Assert.IsTrue(contentConflict.ReferenceName.Equals(conflicts[0].ConflictTypeReference.Value.ReferenceName), "It should be vc content conflict"); // resolve the vc content conflict. The chained conflict will be resolved automatically conflictResolver.TryResolveConflict(conflicts[0], new VCContentConflictTakeOtherChangesAction(), "$/"); // The user decided to accept other but forgot deleting the items on target system // start a conflict resolution thread to detect 'future' TfsCheckinConflict and resolve it asynchronously ConflictResolutionWorker resolutionWorker = new ConflictResolutionWorker() { ConflictResolver = conflictResolver, }; resolutionWorker.ConflictResolutionList.Add(new ConflictResolutionEntry() { Conflict = ConflictConstant.TfsCheckinConflict, Resolution = ConflictConstant.TfsCheckinSkipAction, }); resolutionWorker.ConflictResolutionList.Add(new ConflictResolutionEntry() { Conflict = ConflictConstant.TFSZeroCheckinConflict, Resolution = new TFSZeroCheckinSkipAction().ReferenceName, }); resolutionWorker.Start(); // restart the migraiton tool // migration tool will be in a loop until the TfsCheckinConflict gets resolved Run(true, true); Assert.IsTrue(VerifyContents(), "Content should be the same."); SourceAdapter.EditFile(sourceFile.LocalPath); Run(true, true); Trace.WriteLine("Stopping ConflictResolutionWorker"); resolutionWorker.Stop(); Assert.IsTrue(VerifyContents(), "Content should match!"); }