Skip to content

Commit

Permalink
List Existing Connection Info (#5208)
Browse files Browse the repository at this point in the history
Fixes #5203
  • Loading branch information
ugras-ergun-sonarsource committed Apr 3, 2024
1 parent 5ed7db7 commit 9218fc1
Show file tree
Hide file tree
Showing 11 changed files with 489 additions and 15 deletions.
151 changes: 151 additions & 0 deletions src/ConnectedMode.UnitTests/Binding/BindingInfoProviderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* SonarLint for Visual Studio
* Copyright (C) 2016-2024 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using System;
using System.Linq;
using SonarLint.VisualStudio.ConnectedMode.Binding;
using SonarLint.VisualStudio.ConnectedMode.Persistence;
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.Core.Binding;
using SonarLint.VisualStudio.TestInfrastructure;
using SonarQube.Client.Models;

namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.Binding
{
[TestClass]
public class BindingInfoProviderTests
{
[TestMethod]
public void GetExistingBindings_NoBindings_ReturnsEmpty()
{
var testSubject = CreateTestSubject();

var result = testSubject.GetExistingBindings();

result.Should().BeEmpty();
}

[TestMethod]
public void GetExistingBindings_MakeSureCallInBackground()
{
var threadHandling = new Mock<IThreadHandling>();

var testSubject = CreateTestSubject(threadHandling: threadHandling.Object);

_ = testSubject.GetExistingBindings();

threadHandling.Verify(t => t.ThrowIfOnUIThread(), Times.Once());
threadHandling.VerifyNoOtherCalls();
}

[TestMethod]
public void GetExistingBindings_HaveBindings_ReturnsBinding()
{
var unintrusiveBindingPathProvider = CreateUnintrusiveBindingPathProvider("C:\\Bindings\\Binding1\\binding.config", "C:\\Bindings\\Binding2\\binding.config");

var solutionBindingFileLoader = new Mock<ISolutionBindingFileLoader>();

var binding1 = CreateBoundSonarQubeProject("https://sonarqube.somedomain.com", null, "projectKey1");
var binding2 = CreateBoundSonarQubeProject("https://sonarcloud.io", "organisation", "projectKey2");

solutionBindingFileLoader.Setup(sbf => sbf.Load("C:\\Bindings\\Binding1\\binding.config")).Returns(binding1);
solutionBindingFileLoader.Setup(sbf => sbf.Load("C:\\Bindings\\Binding2\\binding.config")).Returns(binding2);

var testSubject = CreateTestSubject(unintrusiveBindingPathProvider: unintrusiveBindingPathProvider, solutionBindingFileLoader: solutionBindingFileLoader.Object);

var result = testSubject.GetExistingBindings().ToList();

result.Should().HaveCount(2);
result[0].ServerUri.ToString().Should().Be("https://sonarqube.somedomain.com/");
result[0].Organization.Should().BeNull();
result[1].ServerUri.ToString().Should().Be("https://sonarcloud.io/");
result[1].Organization.Should().Be("organisation");
}

[TestMethod]
public void GetExistingBindings_BindingConfigMissing_SkipFile()
{
var unintrusiveBindingPathProvider = CreateUnintrusiveBindingPathProvider("C:\\Bindings\\Binding1\\binding.config", "C:\\Bindings\\Binding2\\binding.config");

var solutionBindingFileLoader = new Mock<ISolutionBindingFileLoader>();

var binding1 = CreateBoundSonarQubeProject("https://sonarqube.somedomain.com", null, "projectKey1");
var binding2 = CreateBoundSonarQubeProject("https://sonarcloud.io", "organisation", "projectKey2");

solutionBindingFileLoader.Setup(sbf => sbf.Load("C:\\Bindings\\Binding1\\binding.config")).Returns(binding1);
solutionBindingFileLoader.Setup(sbf => sbf.Load("C:\\Bindings\\Binding2\\binding.config")).Returns((BoundSonarQubeProject)null);

var testSubject = CreateTestSubject(unintrusiveBindingPathProvider: unintrusiveBindingPathProvider, solutionBindingFileLoader: solutionBindingFileLoader.Object);

var result = testSubject.GetExistingBindings();

result.Should().HaveCount(1);
}

[TestMethod]
public void GetExistingBindings_SameBindingMultipleTime_ReturnsDistinct()
{
var unintrusiveBindingPathProvider = CreateUnintrusiveBindingPathProvider("C:\\Bindings\\Binding1\\binding.config", "C:\\Bindings\\Binding2\\binding.config");

var solutionBindingFileLoader = new Mock<ISolutionBindingFileLoader>();

var binding1 = CreateBoundSonarQubeProject("https://sonarqube.somedomain.com", null, "projectKey1");
var binding2 = CreateBoundSonarQubeProject("https://sonarqube.somedomain.com", null, "projectKey2");

solutionBindingFileLoader.Setup(sbf => sbf.Load("C:\\Bindings\\Binding1\\binding.config")).Returns(binding1);
solutionBindingFileLoader.Setup(sbf => sbf.Load("C:\\Bindings\\Binding2\\binding.config")).Returns(binding2);

var testSubject = CreateTestSubject(unintrusiveBindingPathProvider: unintrusiveBindingPathProvider, solutionBindingFileLoader: solutionBindingFileLoader.Object);

var result = testSubject.GetExistingBindings();

result.Should().HaveCount(1);
}

private static IUnintrusiveBindingPathProvider CreateUnintrusiveBindingPathProvider(params string[] bindigFolders)
{
var unintrusiveBindingPathProvider = new Mock<IUnintrusiveBindingPathProvider>();
unintrusiveBindingPathProvider.Setup(u => u.GetBindingPaths()).Returns(bindigFolders);
return unintrusiveBindingPathProvider.Object;
}

private static BoundConnectionInfoProvider CreateTestSubject(IUnintrusiveBindingPathProvider unintrusiveBindingPathProvider = null, ISolutionBindingFileLoader solutionBindingFileLoader = null, IThreadHandling threadHandling = null)
{
unintrusiveBindingPathProvider ??= CreateUnintrusiveBindingPathProvider();

solutionBindingFileLoader ??= Mock.Of<ISolutionBindingFileLoader>();
threadHandling ??= new NoOpThreadHandler();

var testSubject = new BoundConnectionInfoProvider(unintrusiveBindingPathProvider, solutionBindingFileLoader, threadHandling);
return testSubject;
}

private static BoundSonarQubeProject CreateBoundSonarQubeProject(string uri, string organizationKey, string projectKey)
{
var organization = CreateOrganization(organizationKey);

var serverUri = new Uri(uri);

return new BoundSonarQubeProject(serverUri, projectKey, null, organization: organization);
}

private static SonarQubeOrganization CreateOrganization(string organizationKey) => organizationKey == null ? null : new SonarQubeOrganization(organizationKey, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* SonarLint for Visual Studio
* Copyright (C) 2016-2024 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using System;
using SonarLint.VisualStudio.ConnectedMode.Binding;

namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.Binding
{
[TestClass]
public class BoundConnectionInfoUriComparerTests
{
BoundConnectionInfoUriComparer comparer;

[TestInitialize]
public void Init()
{
comparer = new BoundConnectionInfoUriComparer();
}

[TestMethod]
public void Equals_BothNull_ReturnsTrue()
{
BoundConnectionInfo bindingInfo1 = null;
BoundConnectionInfo bindingInfo2 = null;

comparer.Equals(bindingInfo1, bindingInfo2).Should().BeTrue();
}

[TestMethod]
public void Equals_OneNull_ReturnsFalse()
{
BoundConnectionInfo bindingInfo1 = new BoundConnectionInfo();
BoundConnectionInfo bindingInfo2 = null;

comparer.Equals(bindingInfo1, bindingInfo2).Should().BeFalse();
}

[TestMethod]
public void Equals_SameUri_ReturnsTrue()
{
BoundConnectionInfo bindingInfo1 = new BoundConnectionInfo { ServerUri = new Uri("https://www.google.com") };
BoundConnectionInfo bindingInfo2 = new BoundConnectionInfo { ServerUri = new Uri("https://www.google.com") };

comparer.Equals(bindingInfo1, bindingInfo2).Should().BeTrue();
}

[TestMethod]
public void GetHashCode_SameAsUri()
{
BoundConnectionInfo bindingInfo = new BoundConnectionInfo { ServerUri = new Uri("https://www.google.com") };

comparer.GetHashCode(bindingInfo).Should().Be(bindingInfo.ServerUri.GetHashCode());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
*/

using System;
using System.IO.Abstractions;
using System.IO.Abstractions.TestingHelpers;
using SonarLint.VisualStudio.Core;
using SonarLint.VisualStudio.TestInfrastructure;

Expand Down Expand Up @@ -54,7 +56,7 @@ public void Get_NoOpenSolution_ReturnsNull()
var serviceProvider = CreateSolutionInfoProvider(null);
var testSubject = CreateTestSubject(serviceProvider.Object);

var actual = testSubject.Get();
var actual = testSubject.GetCurrentBindingPath();
actual.Should().BeNull();
}

Expand All @@ -69,19 +71,78 @@ public void Get_HasOpenSolution_ReturnsExpectedValue()

var testSubject = CreateTestSubject(solutionInfoProvider.Object, envVars);

var actual = testSubject.Get();
var actual = testSubject.GetCurrentBindingPath();

actual.Should().Be($@"{rootFolderName}SonarLint for Visual Studio\Bindings\{solutionName}\binding.config");
}

private static UnintrusiveBindingPathProvider CreateTestSubject(ISolutionInfoProvider solutionInfoProvider,
IEnvironmentVariableProvider envVars = null)
[TestMethod]
public void GetBindingFolders_NoBindingFolder_ReturnsEmpy()
{
const string solutionName = "mysolutionName";
const string rootFolderName = @"x:\users\foo\";

var solutionInfoProvider = CreateSolutionInfoProvider(solutionName);
var envVars = CreateEnvVars(rootFolderName);

var testSubject = CreateTestSubject(solutionInfoProvider.Object, envVars);

var actual = testSubject.GetBindingPaths();

actual.Should().NotBeNull();
actual.Should().BeEmpty();
}

[TestMethod]
public void GetBindingFolders_NoBindings_ReturnsEmpty()
{
const string rootFolderName = @"x:\users\foo\";

var envVars = CreateEnvVars(rootFolderName);

var fileSystem = new MockFileSystem();
fileSystem.AddDirectory($@"{rootFolderName}SonarLint for Visual Studio\Bindings\");

var testSubject = CreateTestSubject(envVars: envVars, fileSystem: fileSystem);

var actual = testSubject.GetBindingPaths();

actual.Should().NotBeNull();
actual.Should().BeEmpty();
}

[TestMethod]
public void GetBindingFolders_ReturnsBindings()
{
const string rootFolderName = @"x:\users\foo\";

var envVars = CreateEnvVars(rootFolderName);

var fileSystem = new MockFileSystem();
fileSystem.AddDirectory($@"{rootFolderName}SonarLint for Visual Studio\Bindings\");
fileSystem.AddDirectory($@"{rootFolderName}SonarLint for Visual Studio\Bindings\Binding1");
fileSystem.AddDirectory($@"{rootFolderName}SonarLint for Visual Studio\Bindings\Binding2");

var bindingFolders = new string[] { $@"{rootFolderName}SonarLint for Visual Studio\Bindings\Binding1\binding.config", $@"{rootFolderName}SonarLint for Visual Studio\Bindings\Binding2\binding.config" };

var testSubject = CreateTestSubject(envVars: envVars, fileSystem: fileSystem);

var actual = testSubject.GetBindingPaths();

actual.Should().HaveCount(2);
actual.Should().BeEquivalentTo(bindingFolders);
}

private static UnintrusiveBindingPathProvider CreateTestSubject(ISolutionInfoProvider solutionInfoProvider = null,
IEnvironmentVariableProvider envVars = null, IFileSystem fileSystem = null)
{
solutionInfoProvider ??= CreateSolutionInfoProvider(null).Object;
fileSystem ??= new MockFileSystem();
envVars ??= CreateEnvVars("any");
return new UnintrusiveBindingPathProvider(solutionInfoProvider, envVars);
return new UnintrusiveBindingPathProvider(solutionInfoProvider, envVars, fileSystem);
}

private Mock<ISolutionInfoProvider> CreateSolutionInfoProvider(string solutionName = null)
private static Mock<ISolutionInfoProvider> CreateSolutionInfoProvider(string solutionName = null)
{
var solutionInfoProvider = new Mock<ISolutionInfoProvider>();
solutionInfoProvider.Setup(x => x.GetSolutionName()).Returns(solutionName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ private static UnintrusiveConfigurationProvider CreateTestSubject(IUnintrusiveBi
private static IUnintrusiveBindingPathProvider CreatePathProvider(string pathToReturn)
{
var pathProvider = new Mock<IUnintrusiveBindingPathProvider>();
pathProvider.Setup(x => x.Get()).Returns(() => pathToReturn);
pathProvider.Setup(x => x.GetCurrentBindingPath()).Returns(() => pathToReturn);
return pathProvider.Object;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void Persist_NullProject_Throws()
public void Persist_SaveNewConfig()
{
var projectToWrite = new BoundSonarQubeProject();
configFilePathProvider.Setup(x => x.Get()).Returns("c:\\new.txt");
configFilePathProvider.Setup(x => x.GetCurrentBindingPath()).Returns("c:\\new.txt");

solutionBindingDataWriter
.Setup(x => x.Write("c:\\new.txt", projectToWrite))
Expand Down
Loading

0 comments on commit 9218fc1

Please sign in to comment.