public int GetUniqueUINameOfProject(IVsHierarchy pHierarchy, out string pbstrUniqueName) { MockIVsProject project = pHierarchy as MockIVsProject; pbstrUniqueName = "Unique name of " + project.ProjectFile; return(VSConstants.S_OK); }
public void AddProject(MockIVsProject project) { if (_solutionFile != null) { _projects.Add(project); foreach (IVsSolutionEvents sink in _eventSinks) { if (sink != null) { sink.OnAfterOpenProject(project, 1); } } } }
public void AddProject(MockIVsProject project) { if (_solutionFile != null) { _projects.Add(project); foreach (IVsSolutionEvents sink in _eventSinks) { if (sink != null) { sink.OnAfterOpenProject(project, 1); } } } }
public void TestSccMenuCommands() { int result = 0; Guid badGuid = new Guid(); Guid guidCmdGroup = GuidList.guidSccProviderCmdSet; OLECMD[] cmdAddToScc = new OLECMD[1]; cmdAddToScc[0].cmdID = CommandId.icmdAddToSourceControl; OLECMD[] cmdCheckin = new OLECMD[1]; cmdCheckin[0].cmdID = CommandId.icmdCheckin; OLECMD[] cmdCheckout = new OLECMD[1]; cmdCheckout[0].cmdID = CommandId.icmdCheckout; OLECMD[] cmdUseSccOffline = new OLECMD[1]; cmdUseSccOffline[0].cmdID = CommandId.icmdUseSccOffline; OLECMD[] cmdViewToolWindow = new OLECMD[1]; cmdViewToolWindow[0].cmdID = CommandId.icmdViewToolWindow; OLECMD[] cmdToolWindowToolbarCommand = new OLECMD[1]; cmdToolWindowToolbarCommand[0].cmdID = CommandId.icmdToolWindowToolbarCommand; OLECMD[] cmdUnsupported = new OLECMD[1]; cmdUnsupported[0].cmdID = 0; // Initialize the provider, etc SccProviderService target = GetSccProviderServiceInstance; // Mock a service implementing IVsMonitorSelection BaseMock monitorSelection = MockIVsMonitorSelectionFactory.GetMonSel(); serviceProvider.AddService(typeof(IVsMonitorSelection), monitorSelection, true); // Commands that don't belong to our package should not be supported result = _sccProvider.QueryStatus(ref badGuid, 1, cmdAddToScc, IntPtr.Zero); Assert.AreEqual((int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED, result); // The command should be invisible when there is no solution VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdAddToScc); // Activate the provider and test the result target.SetActive(); Assert.AreEqual(true, target.Active, "Microsoft.Samples.VisualStudio.SourceControlIntegration.SccProvider.SccProviderService.Active was not reported correctly."); // The commands should be invisible when there is no solution VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdUseSccOffline); // Commands that don't belong to our package should not be supported result = _sccProvider.QueryStatus(ref guidCmdGroup, 1, cmdUnsupported, IntPtr.Zero); Assert.AreEqual((int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED, result); // Deactivate the provider and test the result target.SetInactive(); Assert.AreEqual(false, target.Active, "Microsoft.Samples.VisualStudio.SourceControlIntegration.SccProvider.SccProviderService.Active was not reported correctly."); // Create a solution solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); project.AddItem(Path.GetTempFileName()); solution.AddProject(project); // The commands should be invisible when the provider is not active VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdUseSccOffline); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdViewToolWindow); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdToolWindowToolbarCommand); // Activate the provider and test the result target.SetActive(); Assert.AreEqual(true, target.Active, "Microsoft.Samples.VisualStudio.SourceControlIntegration.SccProvider.SccProviderService.Active was not reported correctly."); // The command should be visible but disabled now, except the toolwindow ones VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdViewToolWindow); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdToolWindowToolbarCommand); // Set selection to solution node VSITEMSELECTION selSolutionRoot; selSolutionRoot.pHier = _solution as IVsHierarchy; selSolutionRoot.itemid = VSConstants.VSITEMID_ROOT; monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot }; // The add command should be available, rest should be disabled VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Still solution hierarchy, but other way selSolutionRoot.pHier = null; selSolutionRoot.itemid = VSConstants.VSITEMID_ROOT; monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot }; // The add command should be available, rest should be disabled VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Set selection to project node VSITEMSELECTION selProjectRoot; selProjectRoot.pHier = project as IVsHierarchy; selProjectRoot.itemid = VSConstants.VSITEMID_ROOT; monitorSelection["Selection"] = new VSITEMSELECTION[] { selProjectRoot }; // The add command should be available, rest should be disabled VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Set selection to project item VSITEMSELECTION selProjectItem; selProjectItem.pHier = project as IVsHierarchy; selProjectItem.itemid = 0; monitorSelection["Selection"] = new VSITEMSELECTION[] { selProjectItem }; // The add command should be available, rest should be disabled VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Set selection to project and item node and add project to scc monitorSelection["Selection"] = new VSITEMSELECTION[] { selProjectRoot, selProjectItem }; VerifyCommandExecution(cmdAddToScc); // The add command and checkin should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdUseSccOffline); // Checkout the project VerifyCommandExecution(cmdCheckout); // The add command and checkout should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdUseSccOffline); // Select the solution monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot }; // The checkout and offline should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Checkin the project VerifyCommandExecution(cmdCheckin); // The add command and checkout should be enabled, rest should be disabled VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Add the solution to scc VerifyCommandExecution(cmdAddToScc); // The add command and checkin should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdUseSccOffline); // Select the solution and project monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot, selProjectRoot }; // Take the project and solution offline VerifyCommandExecution(cmdUseSccOffline); // The offline command should be latched VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_LATCHED, cmdUseSccOffline); // Select the solution only monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot }; // Take the solution online VerifyCommandExecution(cmdUseSccOffline); // The offline command should be normal again VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdUseSccOffline); // Select the solution and project monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot, selProjectRoot }; // The offline command should be disabled for mixed selection VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Add a new item to the project project.AddItem(Path.GetTempFileName()); // Select the new item selProjectItem.pHier = project as IVsHierarchy; selProjectItem.itemid = 1; monitorSelection["Selection"] = new VSITEMSELECTION[] { selProjectItem }; // The add command and checkout should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_LATCHED, cmdUseSccOffline); // Checkin the new file (this should do an add) VerifyCommandExecution(cmdCheckin); // The add command and checkout should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_LATCHED, cmdUseSccOffline); }
public void TestOpenCloseControlled() { const string strProviderName = "Sample Source Control Provider:{B0BAC05D-2000-41D1-A6C3-704E6C1A3DE2}"; const string strSolutionPersistanceKey = "SampleSourceControlProviderSolutionProperties"; const string strSolutionUserOptionsKey = "SampleSourceControlProvider"; int result = 0; // Create a solution SccProviderService target = GetSccProviderServiceInstance; solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); solution.AddProject(project); // Check solution props VSQUERYSAVESLNPROPS[] saveSolnProps = new VSQUERYSAVESLNPROPS[1]; result = sccProvider.QuerySaveSolutionProps(null, saveSolnProps); Assert.AreEqual(VSConstants.S_OK, result); Assert.AreEqual <VSQUERYSAVESLNPROPS>(VSQUERYSAVESLNPROPS.QSP_HasNoProps, saveSolnProps[0]); // Add the solution to source control. Hashtable uncontrolled = new Hashtable(); uncontrolled[project as IVsSccProject2] = true; target.AddProjectsToSourceControl(ref uncontrolled, true); // Solution should be dirty now result = sccProvider.QuerySaveSolutionProps(null, saveSolnProps); Assert.AreEqual(VSConstants.S_OK, result); Assert.AreEqual <VSQUERYSAVESLNPROPS>(VSQUERYSAVESLNPROPS.QSP_HasDirtyProps, saveSolnProps[0]); // Set the project offline so we'll have something to save in the "suo" stream target.ToggleOfflineStatus(project); // Force the provider to write the solution info into a stream IStream pOptionsStream = new ComStreamFromDataStream(new MemoryStream()) as IStream; sccProvider.WriteUserOptions(pOptionsStream, strSolutionUserOptionsKey); // Move the stream position to the beginning LARGE_INTEGER liOffset; liOffset.QuadPart = 0; ULARGE_INTEGER[] ulPosition = new ULARGE_INTEGER[1]; pOptionsStream.Seek(liOffset, 0, ulPosition); // Write solution props BaseMock propertyBag = MockPropertyBagProvider.GetWritePropertyBag(); sccProvider.WriteSolutionProps(null, strSolutionPersistanceKey, propertyBag as IPropertyBag); // Close the solution to clean up the scc status int pfCancel = 0; target.OnQueryCloseProject(project, 0, ref pfCancel); target.OnQueryCloseSolution(null, ref pfCancel); Assert.AreEqual(pfCancel, 0, "Solution close was canceled"); target.OnBeforeCloseProject(project, 0); // Theoretically the project should have called this, but especially after an add to scc, some projects forget to call it // target.UnregisterSccProject(project); target.OnBeforeCloseSolution(null); target.OnAfterCloseSolution(null); // Now attempt the "reopen" // The solution reads the solution properties propertyBag = MockPropertyBagProvider.GetReadPropertyBag(); sccProvider.ReadSolutionProps(null, null, null, strSolutionPersistanceKey, 1, propertyBag as IPropertyBag); // The solution reads the user options from the stream where they were written before sccProvider.ReadUserOptions(pOptionsStream, strSolutionUserOptionsKey); // Then the projects are opened and register with the provider target.RegisterSccProject(project, "Project's location", "AuxPath", Path.GetDirectoryName(project.ProjectFile), strProviderName); // solution event fired for this project target.OnAfterOpenProject(project, 0); // Then solution completes opening target.OnAfterOpenSolution(null, 0); Assert.IsTrue(target.IsProjectControlled(null), "The solution's controlled status was not correctly persisted or read from property bag"); Assert.IsTrue(target.IsProjectControlled(project), "The project's controlled status was not correctly set"); Assert.IsTrue(target.IsProjectOffline(project), "The project's offline status was incorrectly persisted or read from suo stream"); }
public void TestTPDEvents() { int result = 0; SccProviderService target = GetSccProviderServiceInstance; solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); solution.AddProject(project); Hashtable uncontrolled = new Hashtable(); uncontrolled[project as IVsSccProject2] = true; target.AddProjectsToSourceControl(ref uncontrolled, true); // In real live, a QueryEdit call on the project file would be necessary to add/rename/delete items // Add a new item and fire the appropriate events string pendingAddFile = Path.GetTempFileName(); VSQUERYADDFILERESULTS[] pSummaryResultAdd = new VSQUERYADDFILERESULTS[1]; VSQUERYADDFILERESULTS[] rgResultsAdd = new VSQUERYADDFILERESULTS[1]; result = target.OnQueryAddFiles(project as IVsProject, 1, new string[] { pendingAddFile }, null, pSummaryResultAdd, rgResultsAdd); Assert.AreEqual <int>(VSConstants.E_NOTIMPL, result); project.AddItem(pendingAddFile); result = target.OnAfterAddFilesEx(1, 1, new IVsProject[] { project as IVsProject }, new int[] { 0 }, new string[] { pendingAddFile }, null); Assert.AreEqual <int>(VSConstants.E_NOTIMPL, result); Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); // Checkin the pending add file target.AddFileToSourceControl(pendingAddFile); // Rename the item and verify the file remains is controlled string newName = pendingAddFile + ".renamed"; VSQUERYRENAMEFILERESULTS[] pSummaryResultRen = new VSQUERYRENAMEFILERESULTS[1]; VSQUERYRENAMEFILERESULTS[] rgResultsRen = new VSQUERYRENAMEFILERESULTS[1]; result = target.OnQueryRenameFiles(project as IVsProject, 1, new string[] { pendingAddFile }, new string[] { newName }, null, pSummaryResultRen, rgResultsRen); Assert.AreEqual <int>(VSConstants.E_NOTIMPL, result); project.RenameItem(pendingAddFile, newName); result = target.OnAfterRenameFiles(1, 1, new IVsProject[] { project as IVsProject }, new int[] { 0 }, new string[] { pendingAddFile }, new string[] { newName }, new VSRENAMEFILEFLAGS[] { VSRENAMEFILEFLAGS.VSRENAMEFILEFLAGS_NoFlags }); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(newName), "Incorrect status returned"); // Mock the UIShell service to answer Cancel to the dialog invocation BaseMock mockUIShell = MockUiShellProvider.GetShowMessageBoxCancel(); serviceProvider.AddService(typeof(IVsUIShell), mockUIShell, true); // Try to delete the file from project; the delete should not be allowed VSQUERYREMOVEFILERESULTS[] pSummaryResultDel = new VSQUERYREMOVEFILERESULTS[1]; VSQUERYREMOVEFILERESULTS[] rgResultsDel = new VSQUERYREMOVEFILERESULTS[1]; result = target.OnQueryRemoveFiles(project as IVsProject, 1, new string[] { newName }, null, pSummaryResultDel, rgResultsDel); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VSQUERYREMOVEFILERESULTS>(VSQUERYREMOVEFILERESULTS.VSQUERYREMOVEFILERESULTS_RemoveNotOK, pSummaryResultDel[0]); // Mock the UIShell service to answer Yes to the dialog invocation serviceProvider.RemoveService(typeof(IVsUIShell)); mockUIShell = MockUiShellProvider.GetShowMessageBoxYes(); serviceProvider.AddService(typeof(IVsUIShell), mockUIShell, true); // Try to delete the file from project; the delete should be allowed this time result = target.OnQueryRemoveFiles(project as IVsProject, 1, new string[] { newName }, null, pSummaryResultDel, rgResultsDel); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VSQUERYREMOVEFILERESULTS>(VSQUERYREMOVEFILERESULTS.VSQUERYREMOVEFILERESULTS_RemoveOK, pSummaryResultDel[0]); // Remove the file from project project.RemoveItem(newName); result = target.OnAfterRemoveFiles(1, 1, new IVsProject[] { project as IVsProject }, new int[] { 0 }, new string[] { newName }, null); Assert.AreEqual <int>(VSConstants.E_NOTIMPL, result); }
public void TestFileStatus() { SccProviderService target = GetSccProviderServiceInstance; solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); project.AddItem(Path.GetTempFileName()); solution.AddProject(project); VsStateIcon [] rgsiGlyphs = new VsStateIcon[1]; VsStateIcon [] rgsiGlyphsFromStatus = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; int result = 0; string strTooltip; // Check glyphs and statuses for uncontrolled items IList <string> files = new string[] { solution.SolutionFile, project.ProjectFile, project.ProjectItems[0] }; foreach (string file in files) { Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_BLANK, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_NOTCONTROLLED, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Uncontrolled items should not have tooltips target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length == 0); Hashtable uncontrolled = new Hashtable(); uncontrolled[project as IVsSccProject2] = true; target.AddProjectsToSourceControl(ref uncontrolled, true); foreach (string file in files) { Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Checked in items should have tooltips target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); foreach (string file in files) { target.CheckoutFile(file); Assert.AreEqual(SourceControlStatus.scsCheckedOut, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_CHECKEDOUT, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_CHECKEDOUT, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Checked out items should have tooltips, too target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); foreach (string file in files) { target.CheckinFile(file); Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); } // Add a new file to the project (don't worry about TPD events for now) string pendingAddFile = Path.GetTempFileName(); project.AddItem(pendingAddFile); Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { pendingAddFile }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_CHECKEDOUT, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_CHECKEDOUT, rgdwSccStatus[0]); // Pending add items should have tooltips, too target.GetGlyphTipText(project as IVsHierarchy, 1, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); // Checkin the pending add file target.AddFileToSourceControl(pendingAddFile); Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { pendingAddFile }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); }
public void QueryEditQuerySaveTest() { uint pfEditVerdict; uint prgfMoreInfo; uint pdwQSResult; int result; SccProviderService target = GetSccProviderServiceInstance; // check the functions that are not implemented Assert.AreEqual((int)VSConstants.S_OK, (int)target.BeginQuerySaveBatch()); Assert.AreEqual((int)VSConstants.S_OK, (int)target.EndQuerySaveBatch()); Assert.AreEqual((int)VSConstants.S_OK, (int)target.DeclareReloadableFile("", 0, null)); Assert.AreEqual((int)VSConstants.S_OK, (int)target.DeclareUnreloadableFile("", 0, null)); Assert.AreEqual((int)VSConstants.S_OK, (int)target.OnAfterSaveUnreloadableFile("", 0, null)); Assert.AreEqual((int)VSConstants.S_OK, (int)target.IsReloadable("", out result)); Assert.AreEqual(1, result, "Not the right return value from IsReloadable"); // Create a basic service provider IVsShell shell = MockShellProvider.GetShellForCommandLine() as IVsShell; serviceProvider.AddService(typeof(IVsShell), shell, true); // Command line tests result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_ReportOnly, 1, new string[] { "Dummy.txt" }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)0, prgfMoreInfo, "QueryEdit failed."); result = target.QuerySaveFile("Dummy.txt", 0, null, out pdwQSResult); Assert.AreEqual(VSConstants.S_OK, result, "QuerySave failed."); Assert.AreEqual((uint)tagVSQuerySaveResult.QSR_SaveOK, pdwQSResult, "QueryEdit failed."); serviceProvider.RemoveService(typeof(SVsShell)); // UI mode tests shell = MockShellProvider.GetShellForUI() as IVsShell; serviceProvider.AddService(typeof(SVsShell), shell, true); // Edit of an uncontrolled file that doesn't exist on disk result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_ReportOnly, 1, new string[] { "Dummy.txt" }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)0, prgfMoreInfo, "QueryEdit failed."); // Mock a solution with a project and a file solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); solution.AddProject(project); // Add only the project to source control. Hashtable uncontrolled = new Hashtable(); uncontrolled[project as IVsSccProject2] = true; target.AddProjectsToSourceControl(ref uncontrolled, false); // Check that solution file is not controlled Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(solution.SolutionFile), "Incorrect status returned"); // Make the solution read-only on disk File.SetAttributes(solution.SolutionFile, FileAttributes.ReadOnly); // QueryEdit in report mode for uncontrolled readonly file result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_ReportOnly, 1, new string[] { solution.SolutionFile }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditNotOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)(tagVSQueryEditResultFlags.QER_EditNotPossible | tagVSQueryEditResultFlags.QER_ReadOnlyNotUnderScc), prgfMoreInfo, "QueryEdit failed."); // QueryEdit in silent mode for uncontrolled readonly file result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_SilentMode, 1, new string[] { solution.SolutionFile }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditNotOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)(tagVSQueryEditResultFlags.QER_NoisyPromptRequired), (uint)(tagVSQueryEditResultFlags.QER_NoisyPromptRequired) & prgfMoreInfo, "QueryEdit failed."); // Mock the UIShell service to answer Yes to the dialog invocation BaseMock mockUIShell = MockUiShellProvider.GetShowMessageBoxYes(); serviceProvider.AddService(typeof(IVsUIShell), mockUIShell, true); // QueryEdit for uncontrolled readonly file: allow the edit and make the file read-write result = target.QueryEditFiles(0, 1, new string[] { solution.SolutionFile }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)0, prgfMoreInfo, "QueryEdit failed."); Assert.AreEqual <FileAttributes>(FileAttributes.Normal, File.GetAttributes(solution.SolutionFile), "File was not made writable"); serviceProvider.RemoveService(typeof(IVsUIShell)); // QueryEdit in report mode for controlled readonly file result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_ReportOnly, 1, new string[] { project.ProjectFile }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditNotOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)(tagVSQueryEditResultFlags.QER_EditNotPossible | tagVSQueryEditResultFlags.QER_ReadOnlyUnderScc), prgfMoreInfo, "QueryEdit failed."); // QueryEdit in silent mode for controlled readonly file: should allow the edit and make the file read-write result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_SilentMode, 1, new string[] { project.ProjectFile }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResultFlags.QER_MaybeCheckedout, prgfMoreInfo, "QueryEdit failed."); Assert.AreEqual <FileAttributes>(FileAttributes.Normal, File.GetAttributes(solution.SolutionFile), "File was not made writable"); serviceProvider.RemoveService(typeof(IVsUIShell)); }
public void TestTPDEvents() { int result = 0; SccProviderService target = GetSccProviderServiceInstance; solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); solution.AddProject(project); Hashtable uncontrolled = new Hashtable(); uncontrolled[project as IVsSccProject2] = true; target.AddProjectsToSourceControl(ref uncontrolled, true); // In real live, a QueryEdit call on the project file would be necessary to add/rename/delete items // Add a new item and fire the appropriate events string pendingAddFile = Path.GetTempFileName(); VSQUERYADDFILERESULTS[] pSummaryResultAdd = new VSQUERYADDFILERESULTS[1]; VSQUERYADDFILERESULTS[] rgResultsAdd = new VSQUERYADDFILERESULTS[1]; result = target.OnQueryAddFiles(project as IVsProject, 1, new string[] {pendingAddFile}, null, pSummaryResultAdd, rgResultsAdd); Assert.AreEqual<int>(VSConstants.E_NOTIMPL, result); project.AddItem(pendingAddFile); result = target.OnAfterAddFilesEx(1, 1, new IVsProject[] { project as IVsProject }, new int[] { 0 }, new string[] { pendingAddFile }, null); Assert.AreEqual<int>(VSConstants.E_NOTIMPL, result); Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); // Checkin the pending add file target.AddFileToSourceControl(pendingAddFile); // Rename the item and verify the file remains is controlled string newName = pendingAddFile + ".renamed"; VSQUERYRENAMEFILERESULTS[] pSummaryResultRen = new VSQUERYRENAMEFILERESULTS[1]; VSQUERYRENAMEFILERESULTS[] rgResultsRen = new VSQUERYRENAMEFILERESULTS[1]; result = target.OnQueryRenameFiles(project as IVsProject, 1, new string[] { pendingAddFile }, new string[] { newName }, null, pSummaryResultRen, rgResultsRen); Assert.AreEqual<int>(VSConstants.E_NOTIMPL, result); project.RenameItem(pendingAddFile, newName); result = target.OnAfterRenameFiles(1, 1, new IVsProject[] {project as IVsProject}, new int[] {0}, new string[] { pendingAddFile }, new string[] { newName }, new VSRENAMEFILEFLAGS[] {VSRENAMEFILEFLAGS.VSRENAMEFILEFLAGS_NoFlags}); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(newName), "Incorrect status returned"); // Mock the UIShell service to answer Cancel to the dialog invocation BaseMock mockUIShell = MockUiShellProvider.GetShowMessageBoxCancel(); serviceProvider.AddService(typeof(IVsUIShell), mockUIShell, true); // Try to delete the file from project; the delete should not be allowed VSQUERYREMOVEFILERESULTS[] pSummaryResultDel = new VSQUERYREMOVEFILERESULTS[1]; VSQUERYREMOVEFILERESULTS[] rgResultsDel = new VSQUERYREMOVEFILERESULTS[1]; result = target.OnQueryRemoveFiles(project as IVsProject, 1, new string[] { newName }, null, pSummaryResultDel, rgResultsDel); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VSQUERYREMOVEFILERESULTS>(VSQUERYREMOVEFILERESULTS.VSQUERYREMOVEFILERESULTS_RemoveNotOK, pSummaryResultDel[0]); // Mock the UIShell service to answer Yes to the dialog invocation serviceProvider.RemoveService(typeof(IVsUIShell)); mockUIShell = MockUiShellProvider.GetShowMessageBoxYes(); serviceProvider.AddService(typeof(IVsUIShell), mockUIShell, true); // Try to delete the file from project; the delete should be allowed this time result = target.OnQueryRemoveFiles(project as IVsProject, 1, new string[] { newName }, null, pSummaryResultDel, rgResultsDel); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VSQUERYREMOVEFILERESULTS>(VSQUERYREMOVEFILERESULTS.VSQUERYREMOVEFILERESULTS_RemoveOK, pSummaryResultDel[0]); // Remove the file from project project.RemoveItem(newName); result = target.OnAfterRemoveFiles(1, 1, new IVsProject[] { project as IVsProject }, new int[] { 0 }, new string[] { newName }, null); Assert.AreEqual<int>(VSConstants.E_NOTIMPL, result); }
public void TestSccMenuCommands() { int result = 0; Guid badGuid = new Guid(); Guid guidCmdGroup = GuidList.guidSccProviderCmdSet; OLECMD[] cmdAddToScc = new OLECMD[1]; cmdAddToScc[0].cmdID = CommandId.icmdAddToSourceControl; OLECMD[] cmdCheckin = new OLECMD[1]; cmdCheckin[0].cmdID = CommandId.icmdCheckin; OLECMD[] cmdCheckout = new OLECMD[1]; cmdCheckout[0].cmdID = CommandId.icmdCheckout; OLECMD[] cmdUseSccOffline = new OLECMD[1]; cmdUseSccOffline[0].cmdID = CommandId.icmdUseSccOffline; OLECMD[] cmdViewToolWindow = new OLECMD[1]; cmdViewToolWindow[0].cmdID = CommandId.icmdViewToolWindow; OLECMD[] cmdToolWindowToolbarCommand = new OLECMD[1]; cmdToolWindowToolbarCommand[0].cmdID = CommandId.icmdToolWindowToolbarCommand; OLECMD[] cmdUnsupported = new OLECMD[1]; cmdUnsupported[0].cmdID = 0; // Initialize the provider, etc SccProviderService target = GetSccProviderServiceInstance; // Mock a service implementing IVsMonitorSelection BaseMock monitorSelection = MockIVsMonitorSelectionFactory.GetMonSel(); serviceProvider.AddService(typeof(IVsMonitorSelection), monitorSelection, true); // Commands that don't belong to our package should not be supported result = _sccProvider.QueryStatus(ref badGuid, 1, cmdAddToScc, IntPtr.Zero); Assert.AreEqual((int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED, result); // The command should be invisible when there is no solution VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdAddToScc); // Activate the provider and test the result target.SetActive(); Assert.AreEqual(true, target.Active, "Microsoft.Samples.VisualStudio.SourceControlIntegration.SccProvider.SccProviderService.Active was not reported correctly."); // The commands should be invisible when there is no solution VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdUseSccOffline); // Commands that don't belong to our package should not be supported result = _sccProvider.QueryStatus(ref guidCmdGroup, 1, cmdUnsupported, IntPtr.Zero); Assert.AreEqual((int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED, result); // Deactivate the provider and test the result target.SetInactive(); Assert.AreEqual(false, target.Active, "Microsoft.Samples.VisualStudio.SourceControlIntegration.SccProvider.SccProviderService.Active was not reported correctly."); // Create a solution solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); project.AddItem(Path.GetTempFileName()); solution.AddProject(project); // The commands should be invisible when the provider is not active VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdUseSccOffline); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdViewToolWindow); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE, cmdToolWindowToolbarCommand); // Activate the provider and test the result target.SetActive(); Assert.AreEqual(true, target.Active, "Microsoft.Samples.VisualStudio.SourceControlIntegration.SccProvider.SccProviderService.Active was not reported correctly."); // The command should be visible but disabled now, except the toolwindow ones VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdViewToolWindow); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdToolWindowToolbarCommand); // Set selection to solution node VSITEMSELECTION selSolutionRoot; selSolutionRoot.pHier = _solution as IVsHierarchy; selSolutionRoot.itemid = VSConstants.VSITEMID_ROOT; monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot }; // The add command should be available, rest should be disabled VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Still solution hierarchy, but other way selSolutionRoot.pHier = null; selSolutionRoot.itemid = VSConstants.VSITEMID_ROOT; monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot }; // The add command should be available, rest should be disabled VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Set selection to project node VSITEMSELECTION selProjectRoot; selProjectRoot.pHier = project as IVsHierarchy; selProjectRoot.itemid = VSConstants.VSITEMID_ROOT; monitorSelection["Selection"] = new VSITEMSELECTION[] { selProjectRoot }; // The add command should be available, rest should be disabled VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Set selection to project item VSITEMSELECTION selProjectItem; selProjectItem.pHier = project as IVsHierarchy; selProjectItem.itemid = 0; monitorSelection["Selection"] = new VSITEMSELECTION[] { selProjectItem }; // The add command should be available, rest should be disabled VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Set selection to project and item node and add project to scc monitorSelection["Selection"] = new VSITEMSELECTION[] { selProjectRoot, selProjectItem }; VerifyCommandExecution(cmdAddToScc); // The add command and checkin should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdUseSccOffline); // Checkout the project VerifyCommandExecution(cmdCheckout); // The add command and checkout should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdUseSccOffline); // Select the solution monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot }; // The checkout and offline should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Checkin the project VerifyCommandExecution(cmdCheckin); // The add command and checkout should be enabled, rest should be disabled VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Add the solution to scc VerifyCommandExecution(cmdAddToScc); // The add command and checkin should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdUseSccOffline); // Select the solution and project monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot, selProjectRoot }; // Take the project and solution offline VerifyCommandExecution(cmdUseSccOffline); // The offline command should be latched VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_LATCHED, cmdUseSccOffline); // Select the solution only monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot}; // Take the solution online VerifyCommandExecution(cmdUseSccOffline); // The offline command should be normal again VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdUseSccOffline); // Select the solution and project monitorSelection["Selection"] = new VSITEMSELECTION[] { selSolutionRoot, selProjectRoot }; // The offline command should be disabled for mixed selection VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdUseSccOffline); // Add a new item to the project project.AddItem(Path.GetTempFileName()); // Select the new item selProjectItem.pHier = project as IVsHierarchy; selProjectItem.itemid = 1; monitorSelection["Selection"] = new VSITEMSELECTION[] { selProjectItem }; // The add command and checkout should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_LATCHED, cmdUseSccOffline); // Checkin the new file (this should do an add) VerifyCommandExecution(cmdCheckin); // The add command and checkout should be disabled, rest should be available now VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdAddToScc); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED, cmdCheckin); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED, cmdCheckout); VerifyCommandStatus(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_LATCHED, cmdUseSccOffline); }
public void TestOpenCloseControlled() { const string strProviderName = "Sample Source Control Provider:{B0BAC05D-2000-41D1-A6C3-704E6C1A3DE2}"; const string strSolutionPersistanceKey = "SampleSourceControlProviderSolutionProperties"; const string strSolutionUserOptionsKey = "SampleSourceControlProvider"; int result = 0; // Create a solution SccProviderService target = GetSccProviderServiceInstance; solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); solution.AddProject(project); // Check solution props VSQUERYSAVESLNPROPS[] saveSolnProps = new VSQUERYSAVESLNPROPS[1]; result = sccProvider.QuerySaveSolutionProps(null, saveSolnProps); Assert.AreEqual(VSConstants.S_OK, result); Assert.AreEqual<VSQUERYSAVESLNPROPS>(VSQUERYSAVESLNPROPS.QSP_HasNoProps, saveSolnProps[0]); // Add the solution to source control. Hashtable uncontrolled = new Hashtable(); uncontrolled[project as IVsSccProject2] = true; target.AddProjectsToSourceControl(ref uncontrolled, true); // Solution should be dirty now result = sccProvider.QuerySaveSolutionProps(null, saveSolnProps); Assert.AreEqual(VSConstants.S_OK, result); Assert.AreEqual<VSQUERYSAVESLNPROPS>(VSQUERYSAVESLNPROPS.QSP_HasDirtyProps, saveSolnProps[0]); // Set the project offline so we'll have something to save in the "suo" stream target.ToggleOfflineStatus(project); // Force the provider to write the solution info into a stream IStream pOptionsStream = new ComStreamFromDataStream(new MemoryStream()) as IStream; sccProvider.WriteUserOptions(pOptionsStream, strSolutionUserOptionsKey); // Move the stream position to the beginning LARGE_INTEGER liOffset; liOffset.QuadPart = 0; ULARGE_INTEGER[] ulPosition = new ULARGE_INTEGER[1]; pOptionsStream.Seek(liOffset, 0, ulPosition); // Write solution props BaseMock propertyBag = MockPropertyBagProvider.GetWritePropertyBag(); sccProvider.WriteSolutionProps(null, strSolutionPersistanceKey, propertyBag as IPropertyBag); // Close the solution to clean up the scc status int pfCancel = 0; target.OnQueryCloseProject(project, 0, ref pfCancel); target.OnQueryCloseSolution(null, ref pfCancel); Assert.AreEqual(pfCancel, 0, "Solution close was canceled"); target.OnBeforeCloseProject(project, 0); // Theoretically the project should have called this, but especially after an add to scc, some projects forget to call it // target.UnregisterSccProject(project); target.OnBeforeCloseSolution(null); target.OnAfterCloseSolution(null); // Now attempt the "reopen" // The solution reads the solution properties propertyBag = MockPropertyBagProvider.GetReadPropertyBag(); sccProvider.ReadSolutionProps(null, null, null, strSolutionPersistanceKey, 1, propertyBag as IPropertyBag); // The solution reads the user options from the stream where they were written before sccProvider.ReadUserOptions(pOptionsStream, strSolutionUserOptionsKey); // Then the projects are opened and register with the provider target.RegisterSccProject(project, "Project's location", "AuxPath", Path.GetDirectoryName(project.ProjectFile), strProviderName); // solution event fired for this project target.OnAfterOpenProject(project, 0); // Then solution completes opening target.OnAfterOpenSolution(null, 0); Assert.IsTrue(target.IsProjectControlled(null), "The solution's controlled status was not correctly persisted or read from property bag"); Assert.IsTrue(target.IsProjectControlled(project), "The project's controlled status was not correctly set"); Assert.IsTrue(target.IsProjectOffline(project), "The project's offline status was incorrectly persisted or read from suo stream"); }
public void TestFileStatus() { SccProviderService target = GetSccProviderServiceInstance; solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); project.AddItem(Path.GetTempFileName()); solution.AddProject(project); VsStateIcon [] rgsiGlyphs = new VsStateIcon[1]; VsStateIcon [] rgsiGlyphsFromStatus = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; int result = 0; string strTooltip; // Check glyphs and statuses for uncontrolled items IList<string> files = new string[] { solution.SolutionFile, project.ProjectFile, project.ProjectItems[0] }; foreach (string file in files) { Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_BLANK, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_NOTCONTROLLED, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Uncontrolled items should not have tooltips target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length == 0); Hashtable uncontrolled = new Hashtable(); uncontrolled[project as IVsSccProject2] = true; target.AddProjectsToSourceControl(ref uncontrolled, true); foreach (string file in files) { Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Checked in items should have tooltips target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); foreach (string file in files) { target.CheckoutFile(file); Assert.AreEqual(SourceControlStatus.scsCheckedOut, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_CHECKEDOUT, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_CHECKEDOUT, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Checked out items should have tooltips, too target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); foreach (string file in files) { target.CheckinFile(file); Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); } // Add a new file to the project (don't worry about TPD events for now) string pendingAddFile = Path.GetTempFileName(); project.AddItem(pendingAddFile); Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { pendingAddFile }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_CHECKEDOUT, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_CHECKEDOUT, rgdwSccStatus[0]); // Pending add items should have tooltips, too target.GetGlyphTipText(project as IVsHierarchy, 1, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); // Checkin the pending add file target.AddFileToSourceControl(pendingAddFile); Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { pendingAddFile }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); }
public void QueryEditQuerySaveTest() { uint pfEditVerdict; uint prgfMoreInfo; uint pdwQSResult; int result; SccProviderService target = GetSccProviderServiceInstance; // check the functions that are not implemented Assert.AreEqual((int)VSConstants.S_OK, (int)target.BeginQuerySaveBatch()); Assert.AreEqual((int)VSConstants.S_OK, (int)target.EndQuerySaveBatch()); Assert.AreEqual((int)VSConstants.S_OK, (int)target.DeclareReloadableFile("", 0, null)); Assert.AreEqual((int)VSConstants.S_OK, (int)target.DeclareUnreloadableFile("", 0, null)); Assert.AreEqual((int)VSConstants.S_OK, (int)target.OnAfterSaveUnreloadableFile("", 0, null)); Assert.AreEqual((int)VSConstants.S_OK, (int)target.IsReloadable("", out result)); Assert.AreEqual(1, result, "Not the right return value from IsReloadable"); // Create a basic service provider IVsShell shell = MockShellProvider.GetShellForCommandLine() as IVsShell; serviceProvider.AddService(typeof(IVsShell), shell, true); // Command line tests result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_ReportOnly, 1, new string[] { "Dummy.txt" }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)0, prgfMoreInfo, "QueryEdit failed."); result = target.QuerySaveFile("Dummy.txt", 0, null, out pdwQSResult); Assert.AreEqual(VSConstants.S_OK, result, "QuerySave failed."); Assert.AreEqual((uint)tagVSQuerySaveResult.QSR_SaveOK, pdwQSResult, "QueryEdit failed."); serviceProvider.RemoveService(typeof(SVsShell)); // UI mode tests shell = MockShellProvider.GetShellForUI() as IVsShell; serviceProvider.AddService(typeof(SVsShell), shell, true); // Edit of an uncontrolled file that doesn't exist on disk result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_ReportOnly, 1, new string[] { "Dummy.txt" }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)0, prgfMoreInfo, "QueryEdit failed."); // Mock a solution with a project and a file solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); solution.AddProject(project); // Add only the project to source control. Hashtable uncontrolled = new Hashtable(); uncontrolled[project as IVsSccProject2] = true; target.AddProjectsToSourceControl(ref uncontrolled, false); // Check that solution file is not controlled Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(solution.SolutionFile), "Incorrect status returned"); // Make the solution read-only on disk File.SetAttributes(solution.SolutionFile, FileAttributes.ReadOnly); // QueryEdit in report mode for uncontrolled readonly file result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_ReportOnly, 1, new string[] { solution.SolutionFile }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditNotOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)(tagVSQueryEditResultFlags.QER_EditNotPossible | tagVSQueryEditResultFlags.QER_ReadOnlyNotUnderScc), prgfMoreInfo, "QueryEdit failed."); // QueryEdit in silent mode for uncontrolled readonly file result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_SilentMode, 1, new string[] { solution.SolutionFile }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditNotOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)(tagVSQueryEditResultFlags.QER_NoisyPromptRequired), (uint)(tagVSQueryEditResultFlags.QER_NoisyPromptRequired) & prgfMoreInfo, "QueryEdit failed."); // Mock the UIShell service to answer Yes to the dialog invocation BaseMock mockUIShell = MockUiShellProvider.GetShowMessageBoxYes(); serviceProvider.AddService(typeof(IVsUIShell), mockUIShell, true); // QueryEdit for uncontrolled readonly file: allow the edit and make the file read-write result = target.QueryEditFiles(0, 1, new string[] { solution.SolutionFile }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)0, prgfMoreInfo, "QueryEdit failed."); Assert.AreEqual<FileAttributes>(FileAttributes.Normal, File.GetAttributes(solution.SolutionFile), "File was not made writable"); serviceProvider.RemoveService(typeof(IVsUIShell)); // QueryEdit in report mode for controlled readonly file result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_ReportOnly, 1, new string[] { project.ProjectFile }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditNotOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)(tagVSQueryEditResultFlags.QER_EditNotPossible | tagVSQueryEditResultFlags.QER_ReadOnlyUnderScc), prgfMoreInfo, "QueryEdit failed."); // QueryEdit in silent mode for controlled readonly file: should allow the edit and make the file read-write result = target.QueryEditFiles((uint)tagVSQueryEditFlags.QEF_SilentMode, 1, new string[] { project.ProjectFile }, null, null, out pfEditVerdict, out prgfMoreInfo); Assert.AreEqual(VSConstants.S_OK, result, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResult.QER_EditOK, pfEditVerdict, "QueryEdit failed."); Assert.AreEqual((uint)tagVSQueryEditResultFlags.QER_MaybeCheckedout, prgfMoreInfo, "QueryEdit failed."); Assert.AreEqual<FileAttributes>(FileAttributes.Normal, File.GetAttributes(solution.SolutionFile), "File was not made writable"); serviceProvider.RemoveService(typeof(IVsUIShell)); }