public BindingWorkflow(IHost host, ConnectionInformation connectionInformation, ProjectInformation project) { if (host == null) { throw new ArgumentNullException(nameof(host)); } if (connectionInformation == null) { throw new ArgumentNullException(nameof(connectionInformation)); } if (project == null) { throw new ArgumentNullException(nameof(project)); } this.host = host; this.connectionInformation = connectionInformation; this.project = project; this.projectSystem = this.host.GetService<IProjectSystemHelper>(); this.projectSystem.AssertLocalServiceIsNotNull(); this.solutionBindingOperation = new SolutionBindingOperation( this.host, this.connectionInformation, this.project.Key); }
public SolutionBindingOperation(IServiceProvider serviceProvider, ConnectionInformation connection, string sonarQubeProjectKey) { if (serviceProvider == null) { throw new ArgumentNullException(nameof(serviceProvider)); } if (connection == null) { throw new ArgumentNullException(nameof(connection)); } if (string.IsNullOrWhiteSpace(sonarQubeProjectKey)) { throw new ArgumentNullException(nameof(sonarQubeProjectKey)); } this.serviceProvider = serviceProvider; this.connection = connection; this.sonarQubeProjectKey = sonarQubeProjectKey; this.projectSystem = this.serviceProvider.GetService<IProjectSystemHelper>(); this.projectSystem.AssertLocalServiceIsNotNull(); this.sourceControlledFileSystem = this.serviceProvider.GetService<ISourceControlledFileSystem>(); this.sourceControlledFileSystem.AssertLocalServiceIsNotNull(); }
public void LatestServer_APICompatibility() { // Setup the service used to interact with SQ var s = new SonarQubeServiceWrapper(this.serviceProvider); var connection = new ConnectionInformation(new Uri("http://nemo.sonarqube.org")); // Step 1: Connect anonymously ProjectInformation[] projects = null; RetryAction(() => s.TryGetProjects(connection, CancellationToken.None, out projects), "Get projects from SonarQube server"); Assert.AreNotEqual(0, projects.Length, "No projects were returned"); // Step 2: Get quality profile for the first project var project = projects.FirstOrDefault(); QualityProfile profile = null; RetryAction(() => s.TryGetQualityProfile(connection, project, Language.CSharp, CancellationToken.None, out profile), "Get quality profile from SonarQube server"); Assert.IsNotNull(profile, "No quality profile was returned"); // Step 3: Get quality profile export for the quality profile RoslynExportProfile export = null; RetryAction(() => s.TryGetExportProfile(connection, profile, Language.CSharp, CancellationToken.None, out export), "Get quality profile export from SonarQube server"); Assert.IsNotNull(export, "No quality profile export was returned"); // Errors are logged to output window pane and we don't expect any this.outputWindowPane.AssertOutputStrings(0); }
public void ConnectionWorkflow_ConnectionStep_SuccessfulConnection() { // Setup var connectionInfo = new ConnectionInformation(new Uri("http://server")); var projects = new ProjectInformation[] { new ProjectInformation { Key = "project1" } }; this.sonarQubeService.ReturnProjectInformation = projects; bool projectChangedCallbackCalled = false; this.host.TestStateManager.SetProjectsAction = (c, p) => { projectChangedCallbackCalled = true; Assert.AreSame(connectionInfo, c, "Unexpected connection"); CollectionAssert.AreEqual(projects, p.ToArray(), "Unexpected projects"); }; var controller = new ConfigurableProgressController(); var executionEvents = new ConfigurableProgressStepExecutionEvents(); string connectionMessage = connectionInfo.ServerUri.ToString(); var testSubject= new ConnectionWorkflow(this.host, new RelayCommand(AssertIfCalled)); // Act testSubject.ConnectionStep(controller, CancellationToken.None, connectionInfo, executionEvents); // Verify executionEvents.AssertProgressMessages(connectionMessage, Strings.ConnectionResultSuccess); Assert.IsTrue(projectChangedCallbackCalled, "ConnectedProjectsCallaback was not called"); sonarQubeService.AssertConnectRequests(1); Assert.AreEqual(connectionInfo, testSubject.ConnectedServer); ((ConfigurableUserNotification)this.host.ActiveSection.UserNotifications).AssertNoShowErrorMessages(); ((ConfigurableUserNotification)this.host.ActiveSection.UserNotifications).AssertNoNotification(NotificationIds.FailedToConnectId); }
public void ServerViewModel_SetProjects() { // Setup var connInfo = new ConnectionInformation(new Uri("https://myawesomeserver:1234/")); var viewModel = new ServerViewModel(connInfo); IEnumerable<ProjectInformation> projects = new[] { new ProjectInformation { Name = "Project3", Key="1" }, new ProjectInformation { Name = "Project2", Key="2" }, new ProjectInformation { Name = "project1", Key="3" }, }; string[] expectedOrderedProjectNames = projects.Select(p => p.Name).OrderBy(n => n, StringComparer.CurrentCulture).ToArray(); // Act viewModel.SetProjects(projects); // Verify string[] actualProjectNames = viewModel.Projects.Select(p => p.ProjectInformation.Name).OrderBy(n => n, StringComparer.CurrentCulture).ToArray(); CollectionAssert.AreEqual( expectedOrderedProjectNames, actualProjectNames, message: $"VM projects [{string.Join(", ", actualProjectNames)}] do not match the expected projects [{string.Join(", ", expectedOrderedProjectNames)}]" ); // Act again var newProject = new ProjectInformation(); viewModel.SetProjects(new[] { newProject }); // Verify that the collection was replaced with the new one Assert.AreSame(newProject, viewModel.Projects.SingleOrDefault()?.ProjectInformation, "Expected a single project to be present"); }
internal /* testing purposes */ static ConnectionInformation CreateConnectionInformation(ConnectionInfoDialogViewModel viewModel, SecureString password) { if (viewModel == null) { throw new ArgumentNullException(nameof(viewModel)); } if (password == null) { throw new ArgumentNullException(nameof(password)); } ConnectionInformation info = null; Debug.Assert(viewModel.IsValid, "View model should be valid when creating connection information"); if (viewModel.IsValid) { Uri serverUri = viewModel.ServerUrl; string username = viewModel.Username; info = new ConnectionInformation(serverUri, username, password); } return info; }
public void ConnectionInformation_WithLoginInformation() { // Setup var userName = "******"; var passwordUnsecure = "admin"; var password = passwordUnsecure.ConvertToSecureString(); var serverUri = new Uri("http://localhost/"); var testSubject = new ConnectionInformation(serverUri, userName, password); // Act password.Dispose(); // Connection information should maintain it's own copy of the password // Verify Assert.AreEqual(passwordUnsecure, testSubject.Password.ConvertToUnsecureString(), "Password doesn't match"); Assert.AreEqual(userName, testSubject.UserName, "UserName doesn't match"); Assert.AreEqual(serverUri, testSubject.ServerUri, "ServerUri doesn't match"); // Act clone var testSubject2 = (ConnectionInformation)((ICloneable)testSubject).Clone(); // Now dispose the test subject testSubject.Dispose(); // Verify testSubject Exceptions.Expect<ObjectDisposedException>(() => testSubject.Password.ConvertToUnsecureString()); // Verify testSubject2 Assert.AreEqual(passwordUnsecure, testSubject2.Password.ConvertToUnsecureString(), "Password doesn't match"); Assert.AreEqual(userName, testSubject2.UserName, "UserName doesn't match"); Assert.AreEqual(serverUri, testSubject2.ServerUri, "ServerUri doesn't match"); }
ConnectionInformation IConnectionInformationProvider.GetConnectionInformation(ConnectionInformation currentConnection) { if (this.ExpectExistingConnection) { Assert.IsNotNull(currentConnection, "No existing connection provided"); } return this.ConnectionInformationToReturn; }
public void ConnectionInformation_Ctor_NormalizesServerUri() { // Act var noSlashResult = new ConnectionInformation(new Uri("http://localhost/NoSlash")); // Verify Assert.AreEqual("http://localhost/NoSlash/", noSlashResult.ServerUri.ToString(), "Unexpected normalization of URI without trailing slash"); }
public void ServerViewModel_Ctor_NullArgumentChecks() { var connInfo = new ConnectionInformation(new Uri("http://localhost")); Exceptions.Expect<ArgumentNullException>(() => { new ServerViewModel(null); }); }
public IProgressEvents Run(ConnectionInformation information) { Debug.Assert(this.host.ActiveSection != null, "Expect the section to be attached at least until this method returns"); this.OnProjectsChanged(information, null); IProgressEvents progress = ProgressStepRunner.StartAsync(this.host, this.host.ActiveSection.ProgressHost, (controller) => this.CreateConnectionSteps(controller, information)); this.DebugOnly_MonitorProgress(progress); return progress; }
public ServerViewModel(ConnectionInformation connectionInformation, bool isExpanded = true) { if (connectionInformation == null) { throw new ArgumentNullException(nameof(connectionInformation)); } this.connectionInformation = connectionInformation; this.IsExpanded = isExpanded; }
public void BindingWorkflow_ArgChecks() { var validConnection = new ConnectionInformation(new Uri("http://server")); var validProjectInfo = new ProjectInformation(); var validHost = new ConfigurableHost(); Exceptions.Expect<ArgumentNullException>(() => new BindingWorkflow(null, validConnection, validProjectInfo)); Exceptions.Expect<ArgumentNullException>(() => new BindingWorkflow(validHost, null, validProjectInfo)); Exceptions.Expect<ArgumentNullException>(() => new BindingWorkflow(validHost, validConnection, null)); }
void IConnectionWorkflowExecutor.EstablishConnection(ConnectionInformation information) { this.numberOfCalls++; Assert.IsNotNull(information, "Should not request to establish to a null connection"); // Simulate the expected behavior in product if (!this.sonarQubeService.TryGetProjects(information, CancellationToken.None, out this.lastConnectedProjects)) { Assert.Fail("Failed to establish connection"); } }
public void SolutionBindingOperation_ArgChecks() { var connectionInformation = new ConnectionInformation(new Uri("http://valid")); Exceptions.Expect<ArgumentNullException>(() => new SolutionBindingOperation(null, connectionInformation, "key")); Exceptions.Expect<ArgumentNullException>(() => new SolutionBindingOperation(this.serviceProvider, null, "key")); Exceptions.Expect<ArgumentNullException>(() => new SolutionBindingOperation(this.serviceProvider, connectionInformation, null)); Exceptions.Expect<ArgumentNullException>(() => new SolutionBindingOperation(this.serviceProvider, connectionInformation, string.Empty)); var testSubject = new SolutionBindingOperation(this.serviceProvider, connectionInformation, "key"); Assert.IsNotNull(testSubject, "Avoid 'testSubject' not used analysis warning"); }
internal /*for testing purposes*/ static ConnectionInfoDialogViewModel CreateViewModel(ConnectionInformation currentConnection) { var vm = new ConnectionInfoDialogViewModel(); if (currentConnection != null) { vm.ServerUrlRaw = currentConnection.ServerUri.AbsoluteUri; vm.Username = currentConnection.UserName; } return vm; }
public void RegisterProjectDashboardUrl(ConnectionInformation connectionInfo, ProjectInformation projectInfo, Uri url) { var serverUrl = connectionInfo.ServerUri.ToString(); var projectKey = projectInfo.Key; if (!this.projectDashboardUrls.ContainsKey(serverUrl)) { this.projectDashboardUrls[serverUrl] = new Dictionary<string, Uri>(); } this.projectDashboardUrls[serverUrl][projectKey] = url; }
private ProgressStepDefinition[] CreateConnectionSteps(IProgressController controller, ConnectionInformation connection) { string connectStepDisplayText = string.Format(CultureInfo.CurrentCulture, Resources.Strings.ConnectingToSever, connection.ServerUri); return new[] { new ProgressStepDefinition(connectStepDisplayText, StepAttributes.Indeterminate | StepAttributes.BackgroundThread, (cancellationToken, notifications) => this.ConnectionStep(controller, cancellationToken, connection, notifications)), new ProgressStepDefinition(connectStepDisplayText, StepAttributes.BackgroundThread, (token, notifications) => this.DownloadServiceParameters(controller, token, notifications)), }; }
public static AuthenticationHeaderValue GetAuthenticationHeader(ConnectionInformation connectionInfo) { if (connectionInfo.Authentication == AuthenticationType.Basic) { return string.IsNullOrWhiteSpace(connectionInfo.UserName) ? null : new AuthenticationHeaderValue("Basic", GetBasicAuthToken(connectionInfo.UserName, connectionInfo.Password)); // See more info: https://www.visualstudio.com/en-us/integrate/get-started/auth/overview } else { Debug.Fail("Unsupported Authentication: " + connectionInfo.Authentication); return null; } }
/// <summary> /// Opens a window and returns only when the dialog is closed. /// </summary> /// <param name="currentConnection">Optional, the current connection information to show in the dialog</param> /// <returns>Captured connection information if closed successfully, null otherwise.</returns> public ConnectionInformation ShowDialog(ConnectionInformation currentConnection) { ConnectionInfoDialogViewModel vm = CreateViewModel(currentConnection); ConnectionInfoDialogView dialog = CreateView(); dialog.ViewModel = vm; dialog.Owner = Application.Current.MainWindow; bool? result = dialog.ShowDialog(); if (result.GetValueOrDefault()) { return CreateConnectionInformation(vm, dialog.Password); } return null; }
public void ServerViewModel_Ctor() { // Setup var connInfo = new ConnectionInformation(new Uri("https://myawesomeserver:1234/")); IEnumerable<ProjectInformation> projects = new[] { new ProjectInformation { Name = "Project1", Key="1" }, new ProjectInformation { Name = "Project2", Key="2" }, new ProjectInformation { Name = "Project3", Key="3" }, new ProjectInformation { Name = "Project4", Key="4" } }; string[] projectKeys = projects.Select(x => x.Key).ToArray(); // Case 0: default constructed state // Act var emptyViewModel = new ServerViewModel(connInfo); // Verify Assert.IsTrue(emptyViewModel.IsExpanded); Assert.IsFalse(emptyViewModel.ShowAllProjects); // Case 1, projects with default IsExpanded value // Act var viewModel = new ServerViewModel(connInfo); viewModel.SetProjects(projects); // Verify string[] vmProjectKeys = viewModel.Projects.Select(x => x.Key).ToArray(); Assert.IsTrue(viewModel.ShowAllProjects); Assert.IsTrue(viewModel.IsExpanded); Assert.AreEqual(connInfo.ServerUri, viewModel.Url); CollectionAssert.AreEqual( expected: projectKeys, actual: vmProjectKeys, message: $"VM projects [{string.Join(", ", vmProjectKeys)}] do not match input projects [{string.Join(", ", projectKeys)}]" ); // Case 2, null projects with non default IsExpanded value // Act var viewModel2 = new ServerViewModel(connInfo, isExpanded: false); // Verify Assert.AreEqual(0, viewModel2.Projects.Count, "Not expecting projects"); Assert.IsFalse(viewModel2.IsExpanded); }
public void ConnectionInformation_WithoutLoginInformation() { // Setup var serverUri = new Uri("http://localhost/"); // Act var testSubject = new ConnectionInformation(serverUri); // Verify Assert.IsNull(testSubject.Password, "Password wasn't provided"); Assert.IsNull(testSubject.UserName, "UserName wasn't provided"); Assert.AreEqual(serverUri, testSubject.ServerUri, "ServerUri doesn't match"); // Act clone var testSubject2 = (ConnectionInformation)((ICloneable)testSubject).Clone(); // Verify testSubject2 Assert.IsNull(testSubject2.Password, "Password wasn't provided"); Assert.IsNull(testSubject2.UserName, "UserName wasn't provided"); Assert.AreEqual(serverUri, testSubject2.ServerUri, "ServerUri doesn't match"); }
private void EstablishConnection(ConnectionInformation connectionInfo) { Debug.Assert(connectionInfo != null); this.LastAttemptedConnection = connectionInfo; this.WorkflowExecutor.EstablishConnection(connectionInfo); }
private SolutionBindingOperation CreateTestSubject(string projectKey, ConnectionInformation connection = null) { return new SolutionBindingOperation(this.serviceProvider, connection ?? new ConnectionInformation(new Uri("http://host")), projectKey); }
public void SolutionBindingOperation_CommitSolutionBinding() { // Setup this.serviceProvider.RegisterService(typeof(Persistence.ISolutionBindingSerializer), this.solutionBinding); var csProject = this.solutionMock.AddOrGetProject("CS.csproj"); csProject.SetCSProjectKind(); var projects = new[] { csProject }; var connectionInformation = new ConnectionInformation(new Uri("http://xyz")); SolutionBindingOperation testSubject = this.CreateTestSubject("key", connectionInformation); var ruleSetMap = new Dictionary<Language, RuleSet>(); ruleSetMap[Language.CSharp] = new RuleSet("cs"); testSubject.RegisterKnownRuleSets(ruleSetMap); var profiles = GetQualityProfiles(); profiles[Language.CSharp] = new QualityProfile { Key = "C# Profile", QualityProfileTimestamp = DateTime.Now }; testSubject.Initialize(projects, profiles); testSubject.Binders.Clear(); // Ignore the real binders, not part of this test scope bool commitCalledForBinder = false; testSubject.Binders.Add(new ConfigurableBindingOperation { CommitAction = () => commitCalledForBinder = true }); testSubject.Prepare(CancellationToken.None); this.solutionBinding.WriteSolutionBindingAction = bindingInfo => { Assert.AreEqual(connectionInformation.ServerUri, bindingInfo.ServerUri); Assert.AreEqual(1, bindingInfo.Profiles.Count); QualityProfile csProfile = profiles[Language.CSharp]; Assert.AreEqual(csProfile.Key, bindingInfo.Profiles[Language.CSharp].ProfileKey); Assert.AreEqual(csProfile.QualityProfileTimestamp, bindingInfo.Profiles[Language.CSharp].ProfileTimestamp); return "Doesn't matter"; }; // Sanity this.solutionBinding.AssertWrittenFiles(0); // Act var commitResult = testSubject.CommitSolutionBinding(); // Verify Assert.IsTrue(commitResult); Assert.IsTrue(commitCalledForBinder); Assert.IsTrue(this.solutionItemsProject.Files.ContainsKey(@"c:\solution\SonarQube\keyCSharp.ruleset"), "Ruleset was expected to be added to solution items"); this.solutionBinding.AssertWrittenFiles(1); }
private void OnProjectsChanged(ConnectionInformation connection, ProjectInformation[] projects) { this.host.VisualStateManager.SetProjects(connection, projects); }
private bool VerifyDotNetPlugins(IProgressController controller, CancellationToken cancellationToken, ConnectionInformation connection, IProgressStepExecutionEvents notifications) { notifications.ProgressChanged(Strings.DetectingServerPlugins); ServerPlugin[] plugins; if (!this.host.SonarQubeService.TryGetPlugins(connection, cancellationToken, out plugins)) { notifications.ProgressChanged(cancellationToken.IsCancellationRequested ? Strings.ConnectionResultCancellation : Strings.ConnectionResultFailure); this.host.ActiveSection?.UserNotifications?.ShowNotificationError(Strings.ConnectionFailed, NotificationIds.FailedToConnectId, this.parentCommand); AbortWorkflow(controller, cancellationToken); return false; } IsCSharpPluginSupported = VerifyPluginSupport(plugins, MinimumSupportedServerPlugin.CSharp); IsVBNetPluginSupported = VerifyPluginSupport(plugins, MinimumSupportedServerPlugin.VbNet); var projects = this.projectSystem.GetSolutionProjects().ToList(); var anyCSharpProject = projects.Any(p => MinimumSupportedServerPlugin.CSharp.ISupported(p)); var anyVbNetProject = projects.Any(p => MinimumSupportedServerPlugin.VbNet.ISupported(p)); string errorMessage; if ((IsCSharpPluginSupported && anyCSharpProject) || (IsVBNetPluginSupported && anyVbNetProject)) { return true; } else if (!IsCSharpPluginSupported && !IsVBNetPluginSupported) { errorMessage = Strings.ServerHasNoSupportedPluginVersion; } else if (projects.Count == 0) { errorMessage = Strings.SolutionContainsNoSupportedProject; } else if (IsCSharpPluginSupported && !anyCSharpProject) { errorMessage = string.Format(Strings.OnlySupportedPluginHasNoProjectInSolution, Language.CSharp.Name); } else { errorMessage = string.Format(Strings.OnlySupportedPluginHasNoProjectInSolution, Language.VBNET.Name); } this.host.ActiveSection?.UserNotifications?.ShowNotificationError(errorMessage, NotificationIds.BadServerPluginId, null); VsShellUtils.WriteToSonarLintOutputPane(this.host, Strings.SubTextPaddingFormat, errorMessage); notifications.ProgressChanged(Strings.ConnectionResultFailure); AbortWorkflow(controller, cancellationToken); return false; }
internal /* for testing purposes */ void ConnectionStep(IProgressController controller, CancellationToken cancellationToken, ConnectionInformation connection, IProgressStepExecutionEvents notifications) { this.host.ActiveSection?.UserNotifications?.HideNotification(NotificationIds.FailedToConnectId); this.host.ActiveSection?.UserNotifications?.HideNotification(NotificationIds.BadServerPluginId); notifications.ProgressChanged(connection.ServerUri.ToString()); if (!this.VerifyDotNetPlugins(controller, cancellationToken, connection, notifications)) { return; } this.ConnectedServer = connection; ProjectInformation[] projects; if (!this.host.SonarQubeService.TryGetProjects(connection, cancellationToken, out projects)) { notifications.ProgressChanged(cancellationToken.IsCancellationRequested ? Strings.ConnectionResultCancellation : Strings.ConnectionResultFailure); this.host.ActiveSection?.UserNotifications?.ShowNotificationError(Strings.ConnectionFailed, NotificationIds.FailedToConnectId, this.parentCommand); AbortWorkflow(controller, cancellationToken); return; } this.OnProjectsChanged(connection, projects); notifications.ProgressChanged(Strings.ConnectionResultSuccess); }
void IConnectionWorkflowExecutor.EstablishConnection(ConnectionInformation information) { ConnectionWorkflow workflow = new ConnectionWorkflow(this.host, this.ConnectCommand); IProgressEvents progressEvents = workflow.Run(information); this.SetConnectionInProgress(progressEvents); }
ConnectionInformation IConnectionInformationProvider.GetConnectionInformation(ConnectionInformation currentConnection) { var dialog = new ConnectionInformationDialog(); return dialog.ShowDialog(currentConnection); }