Skip to content

Commit

Permalink
SLVS-1738 Refactor ConnectionInformation (#5919)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriela-trutan-sonarsource authored Dec 24, 2024
1 parent 9b87ffa commit ab00890
Show file tree
Hide file tree
Showing 39 changed files with 430 additions and 297 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.Binding;
public class UnintrusiveBindingControllerTests
{
private static readonly CancellationToken ACancellationToken = CancellationToken.None;
private static readonly BasicAuthCredentials ValidToken = new("TOKEN", new SecureString());
private static readonly UsernameAndPasswordCredentials ValidToken = new("TOKEN", new SecureString());
private static readonly BoundServerProject AnyBoundProject = new("any", "any", new ServerConnection.SonarCloud("any", credentials: ValidToken));
private IActiveSolutionChangedHandler activeSolutionChangedHandler;
private IBindingProcess bindingProcess;
Expand Down Expand Up @@ -86,8 +86,8 @@ await sonarQubeService
.Received()
.ConnectAsync(
Arg.Is<ConnectionInformation>(x => x.ServerUri.Equals("https://sonarcloud.io/")
&& x.UserName.Equals(ValidToken.UserName)
&& string.IsNullOrEmpty(x.Password.ToUnsecureString())),
&& ((UsernameAndPasswordCredentials)x.Credentials).UserName.Equals(ValidToken.UserName)
&& string.IsNullOrEmpty(((UsernameAndPasswordCredentials)x.Credentials).Password.ToUnsecureString())),
ACancellationToken);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ private void MockValidBinding(string bindingPath, BoundSonarQubeProject sonarQub

private static BoundSonarQubeProject CreateBoundProject(string url, string projectKey)
{
return new BoundSonarQubeProject(new Uri(url), projectKey, "projectName", credentials: new BasicAuthCredentials("admin", "admin".ToSecureString()));
return new BoundSonarQubeProject(new Uri(url), projectKey, "projectName", credentials: new UsernameAndPasswordCredentials("admin", "admin".ToSecureString()));
}

private static bool IsExpectedServerConnection(ServerConnection serverConnection, BoundSonarQubeProject boundProject)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void ConvertToModel_SonarQubeConnection_ConvertsCorrectly()
[TestMethod]
public void ConvertFromModelToLegacy_ConvertsCorrectly()
{
var credentials = Substitute.For<ICredentials>();
var credentials = Substitute.For<IConnectionCredentials>();
var bindingModel = new BindingJsonModel
{
Organization = new SonarQubeOrganization("org", "my org"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using Microsoft.VisualStudio.LanguageServices.Progression;
using SonarLint.VisualStudio.ConnectedMode.Persistence;
using SonarLint.VisualStudio.Core.Binding;
using SonarLint.VisualStudio.TestInfrastructure;
Expand Down Expand Up @@ -47,8 +48,7 @@ public void BoundSonarQubeProject_CreateConnectionInformation_NoCredentials()

// Assert
conn.ServerUri.Should().Be(input.ServerUri);
conn.UserName.Should().BeNull();
conn.Password.Should().BeNull();
conn.Credentials.Should().BeAssignableTo<INoCredentials>();
conn.Organization.Key.Should().Be("org_key");
conn.Organization.Name.Should().Be("org_name");
}
Expand All @@ -57,7 +57,7 @@ public void BoundSonarQubeProject_CreateConnectionInformation_NoCredentials()
public void BoundSonarQubeProject_CreateConnectionInformation_BasicAuthCredentials()
{
// Arrange
var creds = new BasicAuthCredentials("UserName", "password".ToSecureString());
var creds = new UsernameAndPasswordCredentials("UserName", "password".ToSecureString());
var input = new BoundSonarQubeProject(new Uri("http://server"), "ProjectKey", "projectName", creds,
new SonarQubeOrganization("org_key", "org_name"));

Expand All @@ -66,8 +66,10 @@ public void BoundSonarQubeProject_CreateConnectionInformation_BasicAuthCredentia

// Assert
conn.ServerUri.Should().Be(input.ServerUri);
conn.UserName.Should().Be(creds.UserName);
conn.Password.ToUnsecureString().Should().Be(creds.Password.ToUnsecureString());
var basicAuth = conn.Credentials as UsernameAndPasswordCredentials;
basicAuth.Should().NotBeNull();
basicAuth.UserName.Should().Be(creds.UserName);
basicAuth.Password.ToUnsecureString().Should().Be(creds.Password.ToUnsecureString());
conn.Organization.Key.Should().Be("org_key");
conn.Organization.Name.Should().Be("org_name");
}
Expand All @@ -83,11 +85,10 @@ public void BoundSonarQubeProject_CreateConnectionInformation_NoOrganizationNoAu

// Assert
conn.ServerUri.Should().Be(input.ServerUri);
conn.UserName.Should().BeNull();
conn.Password.Should().BeNull();
conn.Credentials.Should().BeAssignableTo<INoCredentials>();
conn.Organization.Should().BeNull();
}

[TestMethod]
public void BoundServerProject_CreateConnectionInformation_ArgCheck()
{
Expand All @@ -105,26 +106,26 @@ public void BoundServerProject_CreateConnectionInformation_NoCredentials()

// Assert
conn.ServerUri.Should().Be(input.ServerConnection.ServerUri);
conn.UserName.Should().BeNull();
conn.Password.Should().BeNull();
conn.Credentials.Should().BeAssignableTo<INoCredentials>();
conn.Organization.Key.Should().Be("org_key");
}


[TestMethod]
public void BoundServerProject_CreateConnectionInformation_BasicAuthCredentials()
{
// Arrange
var creds = new BasicAuthCredentials("UserName", "password".ToSecureString());
var creds = new UsernameAndPasswordCredentials("UserName", "password".ToSecureString());
var input = new BoundServerProject("solution", "ProjectKey", new ServerConnection.SonarCloud("org_key", credentials: creds));

// Act
ConnectionInformation conn = input.CreateConnectionInformation();

// Assert
conn.ServerUri.Should().Be(input.ServerConnection.ServerUri);
conn.UserName.Should().Be(creds.UserName);
conn.Password.ToUnsecureString().Should().Be(creds.Password.ToUnsecureString());
var basicAuth = conn.Credentials as UsernameAndPasswordCredentials;
basicAuth.Should().NotBeNull();
basicAuth.UserName.Should().Be(creds.UserName);
basicAuth.Password.ToUnsecureString().Should().Be(creds.Password.ToUnsecureString());
conn.Organization.Key.Should().Be("org_key");
}

Expand All @@ -139,8 +140,7 @@ public void BoundServerProject_CreateConnectionInformation_NoOrganizationNoAuth(

// Assert
conn.ServerUri.Should().Be(input.ServerConnection.ServerUri);
conn.UserName.Should().BeNull();
conn.Password.Should().BeNull();
conn.Credentials.Should().BeAssignableTo<INoCredentials>();
conn.Organization.Should().BeNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void BoundProject_Serialization()
// Arrange
var serverUri = new Uri("https://finding-nemo.org");
var projectKey = "MyProject Key";
var testSubject = new BoundSonarQubeProject(serverUri, projectKey, "projectName", new BasicAuthCredentials("used", "pwd".ToSecureString()));
var testSubject = new BoundSonarQubeProject(serverUri, projectKey, "projectName", new UsernameAndPasswordCredentials("used", "pwd".ToSecureString()));

// Act (serialize + de-serialize)
string data = JsonHelper.Serialize(testSubject);
Expand All @@ -55,7 +55,7 @@ public void BoundProject_BindingJsonModel_Serialization()
// Arrange
var serverUri = new Uri("https://finding-nemo.org");
var projectKey = "MyProject Key";
var testSubject = new BoundSonarQubeProject(serverUri, projectKey, "projectName", new BasicAuthCredentials("used", "pwd".ToSecureString()));
var testSubject = new BoundSonarQubeProject(serverUri, projectKey, "projectName", new UsernameAndPasswordCredentials("used", "pwd".ToSecureString()));

// Act (serialize + de-serialize)
string data = JsonHelper.Serialize(testSubject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
using SonarLint.VisualStudio.Core.Binding;
using SonarLint.VisualStudio.Core.Persistence;
using SonarLint.VisualStudio.TestInfrastructure;
using SonarQube.Client.Models;
using static SonarLint.VisualStudio.Core.Binding.ServerConnection;

namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.Persistence;
Expand All @@ -40,8 +41,8 @@ public class ServerConnectionsRepositoryTests
private IEnvironmentVariableProvider environmentVariableProvider;
private IServerConnectionModelMapper serverConnectionModelMapper;
private ISolutionBindingCredentialsLoader credentialsLoader;
private readonly SonarCloud sonarCloudServerConnection = new("myOrganization", new ServerConnectionSettings(true), Substitute.For<ICredentials>());
private readonly ServerConnection.SonarQube sonarQubeServerConnection = new(new Uri("http://localhost"), new ServerConnectionSettings(true), Substitute.For<ICredentials>());
private readonly SonarCloud sonarCloudServerConnection = new("myOrganization", new ServerConnectionSettings(true), Substitute.For<IConnectionCredentials>());
private readonly ServerConnection.SonarQube sonarQubeServerConnection = new(new Uri("http://localhost"), new ServerConnectionSettings(true), Substitute.For<IConnectionCredentials>());
private IFileSystem fileSystem;

[TestInitialize]
Expand Down Expand Up @@ -128,7 +129,7 @@ public void TryGet_FileExistsAndConnectionIsSonarCloud_ReturnsSonarCloudConnecti
public void TryGet_FileExistsAndConnectionIsSonarCloud_FillsCredentials()
{
var expectedConnection = MockFileWithOneSonarCloudConnection();
var credentials = Substitute.For<ICredentials>();
var credentials = Substitute.For<IConnectionCredentials>();
credentialsLoader.Load(expectedConnection.CredentialsUri).Returns(credentials);

var succeeded = testSubject.TryGet(expectedConnection.Id, out ServerConnection serverConnection);
Expand Down Expand Up @@ -157,7 +158,7 @@ public void TryGet_FileExistsAndConnectionIsSonarQube_ReturnsSonarQubeConnection
public void TryGet_FileExistsAndConnectionIsSonarQube_FillsCredentials()
{
var expectedConnection = MockFileWithOneSonarQubeConnection();
var credentials = Substitute.For<ICredentials>();
var credentials = Substitute.For<IConnectionCredentials>();
credentialsLoader.Load(expectedConnection.CredentialsUri).Returns(credentials);

var succeeded = testSubject.TryGet(expectedConnection.Id, out ServerConnection serverConnection);
Expand Down Expand Up @@ -289,7 +290,7 @@ public void TryAdd_ConnectionIsAddedAndCredentialsAreNull_ReturnsFalse()
var succeeded = testSubject.TryAdd(sonarCloudServerConnection);

succeeded.Should().BeFalse();
credentialsLoader.DidNotReceive().Save(Arg.Any<ICredentials>(), Arg.Any<Uri>());
credentialsLoader.DidNotReceive().Save(Arg.Any<IConnectionCredentials>(), Arg.Any<Uri>());
}

[TestMethod]
Expand All @@ -300,7 +301,7 @@ public void TryAdd_ConnectionIsNotAdded_DoesNotSaveCredentials()
var succeeded = testSubject.TryAdd(sonarCloud);

succeeded.Should().BeFalse();
credentialsLoader.DidNotReceive().Save(Arg.Any<ICredentials>(), Arg.Any<Uri>());
credentialsLoader.DidNotReceive().Save(Arg.Any<IConnectionCredentials>(), Arg.Any<Uri>());
}

[TestMethod]
Expand Down Expand Up @@ -589,17 +590,17 @@ public void TryUpdateCredentialsById_ConnectionDoesNotExist_DoesNotUpdateCredent
{
MockReadingFile(new ServerConnectionsListJsonModel());

var succeeded = testSubject.TryUpdateCredentialsById("myConn", Substitute.For<ICredentials>());
var succeeded = testSubject.TryUpdateCredentialsById("myConn", Substitute.For<IConnectionCredentials>());

succeeded.Should().BeFalse();
credentialsLoader.DidNotReceive().Save(Arg.Any<ICredentials>(), Arg.Any<Uri>());
credentialsLoader.DidNotReceive().Save(Arg.Any<IConnectionCredentials>(), Arg.Any<Uri>());
}

[TestMethod]
public void TryUpdateCredentialsById_SonarCloudConnectionExists_UpdatesCredentials()
{
var sonarCloud = MockFileWithOneSonarCloudConnection();
var newCredentials = Substitute.For<ICredentials>();
var newCredentials = Substitute.For<IConnectionCredentials>();

var succeeded = testSubject.TryUpdateCredentialsById(sonarCloud.Id, newCredentials);

Expand All @@ -611,7 +612,7 @@ public void TryUpdateCredentialsById_SonarCloudConnectionExists_UpdatesCredentia
public void TryUpdateCredentialsById_SonarQubeConnectionExists_UpdatesCredentials()
{
var sonarQube = MockFileWithOneSonarQubeConnection();
var newCredentials = Substitute.For<ICredentials>();
var newCredentials = Substitute.For<IConnectionCredentials>();

var succeeded = testSubject.TryUpdateCredentialsById(sonarQube.Id, newCredentials);

Expand All @@ -626,7 +627,7 @@ public void TryUpdateCredentialsById_DoesNotUpdateCredentials_DoesNotInvokeConne
var eventHandler = Substitute.For<EventHandler<ServerConnectionUpdatedEventArgs>>();
testSubject.CredentialsChanged += eventHandler;

testSubject.TryUpdateCredentialsById("non-existingConn", Substitute.For<ICredentials>());
testSubject.TryUpdateCredentialsById("non-existingConn", Substitute.For<IConnectionCredentials>());

eventHandler.DidNotReceive().Invoke(testSubject, Arg.Any<ServerConnectionUpdatedEventArgs>());
}
Expand All @@ -638,7 +639,7 @@ public void TryUpdateCredentialsById_UpdatesCredentials_InvokesConnectionChanged
var eventHandler = Substitute.For<EventHandler<ServerConnectionUpdatedEventArgs>>();
testSubject.CredentialsChanged += eventHandler;

testSubject.TryUpdateCredentialsById(sonarQube.Id, Substitute.For<ICredentials>());
testSubject.TryUpdateCredentialsById(sonarQube.Id, Substitute.For<IConnectionCredentials>());

eventHandler.Received(1).Invoke(testSubject, Arg.Is<ServerConnectionUpdatedEventArgs>(args => args.ServerConnection == sonarQube));
}
Expand All @@ -660,9 +661,9 @@ public void TryUpdateCredentialsById_SavingCredentialsThrows_ReturnsFalseAndLogs
{
var exceptionMsg = "failed";
var connection = MockFileWithOneSonarCloudConnection();
credentialsLoader.When(x => x.Save(Arg.Any<ICredentials>(), Arg.Any<Uri>())).Do(x => throw new Exception(exceptionMsg));
credentialsLoader.When(x => x.Save(Arg.Any<IConnectionCredentials>(), Arg.Any<Uri>())).Do(x => throw new Exception(exceptionMsg));

var succeeded = testSubject.TryUpdateCredentialsById(connection.Id, Substitute.For<ICredentials>());
var succeeded = testSubject.TryUpdateCredentialsById(connection.Id, Substitute.For<IConnectionCredentials>());

succeeded.Should().BeFalse();
logger.Received(1).WriteLine($"Failed updating credentials: {exceptionMsg}");
Expand All @@ -671,7 +672,7 @@ public void TryUpdateCredentialsById_SavingCredentialsThrows_ReturnsFalseAndLogs
private SonarCloud MockFileWithOneSonarCloudConnection(bool isSmartNotificationsEnabled = true)
{
var sonarCloudModel = GetSonarCloudJsonModel(isSmartNotificationsEnabled);
var sonarCloud = new SonarCloud(sonarCloudModel.OrganizationKey, sonarCloudModel.Settings, Substitute.For<ICredentials>());
var sonarCloud = new SonarCloud(sonarCloudModel.OrganizationKey, sonarCloudModel.Settings, Substitute.For<IConnectionCredentials>());
MockReadingFile(new ServerConnectionsListJsonModel { ServerConnections = [sonarCloudModel] });
serverConnectionModelMapper.GetServerConnection(sonarCloudModel).Returns(sonarCloud);

Expand All @@ -681,7 +682,7 @@ private SonarCloud MockFileWithOneSonarCloudConnection(bool isSmartNotifications
private ServerConnection.SonarQube MockFileWithOneSonarQubeConnection(bool isSmartNotificationsEnabled = true)
{
var sonarQubeModel = GetSonarQubeJsonModel(new Uri("http://localhost"), isSmartNotificationsEnabled);
var sonarQube = new ServerConnection.SonarQube(new Uri(sonarQubeModel.ServerUri), sonarQubeModel.Settings, Substitute.For<ICredentials>());
var sonarQube = new ServerConnection.SonarQube(new Uri(sonarQubeModel.ServerUri), sonarQubeModel.Settings, Substitute.For<IConnectionCredentials>());
MockReadingFile(new ServerConnectionsListJsonModel { ServerConnections = [sonarQubeModel] });
serverConnectionModelMapper.GetServerConnection(sonarQubeModel).Returns(sonarQube);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using SonarLint.VisualStudio.ConnectedMode.Persistence;
using SonarLint.VisualStudio.Core.Binding;
using SonarQube.Client.Helpers;
using SonarQube.Client.Models;

namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.Persistence
{
Expand Down Expand Up @@ -74,13 +75,13 @@ public void Load_CredentialsExist_CredentialsWithSecuredString()
.Returns(credentials);

var actual = testSubject.Load(mockUri);
actual.Should().BeEquivalentTo(new BasicAuthCredentials("user", "password".ToSecureString()));
actual.Should().BeEquivalentTo(new UsernameAndPasswordCredentials("user", "password".ToSecureString()));
}

[TestMethod]
public void Save_ServerUriIsNull_CredentialsNotSaved()
{
var credentials = new BasicAuthCredentials("user", "password".ToSecureString());
var credentials = new UsernameAndPasswordCredentials("user", "password".ToSecureString());

testSubject.Save(credentials, null);

Expand All @@ -98,7 +99,7 @@ public void Save_CredentialsAreNull_CredentialsNotSaved()
[TestMethod]
public void Save_CredentialsAreNotBasicAuth_CredentialsNotSaved()
{
var mockCredentials = new Mock<ICredentials>();
var mockCredentials = new Mock<IConnectionCredentials>();
testSubject.Save(mockCredentials.Object, mockUri);

store.DidNotReceive().WriteCredentials(Arg.Any<TargetUri>(), Arg.Any<Credential>());
Expand All @@ -107,7 +108,7 @@ public void Save_CredentialsAreNotBasicAuth_CredentialsNotSaved()
[TestMethod]
public void Save_CredentialsAreBasicAuth_CredentialsSavedWithUnsecuredString()
{
var credentials = new BasicAuthCredentials("user", "password".ToSecureString());
var credentials = new UsernameAndPasswordCredentials("user", "password".ToSecureString());
testSubject.Save(credentials, mockUri);

store.Received(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class SolutionBindingRepositoryTests
private ISolutionBindingCredentialsLoader credentialsLoader;
private TestLogger logger;

private BasicAuthCredentials mockCredentials;
private UsernameAndPasswordCredentials mockCredentials;
private ServerConnection serverConnection;
private IServerConnectionsRepository serverConnectionsRepository;
private ISolutionBindingFileLoader solutionBindingFileLoader;
Expand All @@ -59,7 +59,7 @@ public void TestInitialize()

testSubject = new SolutionBindingRepository(unintrusiveBindingPathProvider, bindingJsonModelConverter, serverConnectionsRepository, solutionBindingFileLoader, credentialsLoader, logger);

mockCredentials = new BasicAuthCredentials("user", "pwd".ToSecureString());
mockCredentials = new UsernameAndPasswordCredentials("user", "pwd".ToSecureString());

serverConnection = new ServerConnection.SonarCloud("org");
boundServerProject = new BoundServerProject("solution.123", "project_123", serverConnection);
Expand Down
Loading

0 comments on commit ab00890

Please sign in to comment.