public void WarnIfDeprecated_ShouldWarn(string sqVersion) { this.ws = new SonarWebService(this.downloader, "http://myhost:222", this.logger); this.downloader.Pages["http://myhost:222/api/server/version"] = sqVersion; this.ws.WarnIfSonarQubeVersionIsDeprecated().Wait(); this.logger.AssertSingleWarningExists("The version of SonarQube you are using is deprecated. Analyses will fail starting 6.0 release of the Scanner for .NET"); }
public void GetProperties_NullProjectKey_Throws() { // Arrange var testSubject = new SonarWebService(new TestDownloader(), "http://myserver", new TestLogger()); Action act = () => testSubject.GetProperties(null, null); // Act & Assert act.Should().Throw <ArgumentNullException>().And.ParamName.Should().Be("projectKey"); }
public void WarnIfDeprecated_ShouldNotWarn(string sqVersion) { this.ws = new SonarWebService(this.downloader, "http://myhost:222", this.logger); this.downloader.Pages["http://myhost:222/api/server/version"] = sqVersion; this.ws.WarnIfSonarQubeVersionIsDeprecated().Wait(); this.logger.Warnings.Should().BeEmpty(); }
public async Task TryDownloadEmbeddedFile_NullEmbeddedFileName_Throws() { // Arrange var testSubject = new SonarWebService(new TestDownloader(), "http://myserver", new TestLogger()); Func <Task> act = async() => await testSubject.TryDownloadEmbeddedFile("key", null, "targetDir"); // Act & Assert (await act.Should().ThrowAsync <ArgumentNullException>()).And.ParamName.Should().Be("embeddedFileName"); }
public void IsLicenseValid_IsSonarCloud_ShouldReturnTrue() { this.ws = new SonarWebService(this.downloader, "http://myhost:222", this.logger); this.downloader.Pages["http://myhost:222/api/server/version"] = "8.0.0.68001"; var result = this.ws.IsServerLicenseValid().Result; Assert.AreEqual(true, result); }
public void TryDownloadEmbeddedFile_NullTargetDirectory_Throws() { // Arrange var testSubject = new SonarWebService(new TestDownloader(), "http://myserver", new TestLogger()); Action act = () => testSubject.TryDownloadEmbeddedFile("pluginKey", "filename", null); // Act & Assert act.Should().Throw <ArgumentNullException>().And.ParamName.Should().Be("targetDirectory"); }
public void TryDownloadEmbeddedFile_NullPluginKey_Throws() { // Arrange var testSubject = new SonarWebService(new TestDownloader(), "http://myserver", new TestLogger()); Func <Task> act = async() => await testSubject.TryDownloadEmbeddedFile(null, "filename", "targetDir"); // Act & Assert act.Should().Throw <ArgumentNullException>().And.ParamName.Should().Be("pluginKey"); }
public void IsLicenseValid_SonarQube_ServerNotLicensed() { this.ws = new SonarWebService(this.downloader, "http://*****:*****@"{ ""errors"":[{""msg"":""License not found""}] }", false); this.ws.IsServerLicenseValid().Result.Should().BeFalse(); }
public void IsLicenseValid_SonarQube_Commercial_AuthForced_WithoutCredentials_ShouldThrow() { this.ws = new SonarWebService(this.downloader, "http://myhost:222", this.logger); this.downloader.Pages["http://myhost:222/api/server/version"] = "8.5.1.34001"; this.downloader.ConfigureGetLicenseInformationMock(HttpStatusCode.Unauthorized, "", false); _ = this.ws.IsServerLicenseValid().Result; this.logger.AssertErrorLogged("The token you provided doesn't have sufficient rights to check license."); }
void IRulesetGenerator.Generate(SonarWebService ws, string requiredPluginKey, string language, string fxcopRepositoryKey, string sonarProjectKey, string outputFilePath) { Assert.IsNotNull(ws); Assert.IsFalse(string.IsNullOrWhiteSpace(requiredPluginKey), "Supplied requiredPluginKey should not be null or empty"); Assert.IsFalse(string.IsNullOrWhiteSpace(language), "Supplied language should not be null or empty"); Assert.IsFalse(string.IsNullOrWhiteSpace(fxcopRepositoryKey), "Supplied FxCop repository key should not be null or empty"); Assert.IsFalse(string.IsNullOrWhiteSpace(sonarProjectKey), "Supplied project key should not be null or empty"); Assert.IsFalse(string.IsNullOrWhiteSpace(outputFilePath), "Supplied output file path should not be null or empty"); actuals.Add(Tuple.Create(ws, requiredPluginKey, language, fxcopRepositoryKey, sonarProjectKey, outputFilePath)); }
void IRulesetGenerator.Generate(SonarWebService ws, string sonarProjectKey, string outputFilePath) { Assert.IsFalse(string.IsNullOrWhiteSpace(sonarProjectKey), "Supplied project key should not be null"); Assert.IsFalse(string.IsNullOrWhiteSpace(outputFilePath), "Supplied output file path should not be null"); this.generateCalled = true; this.actualKey = sonarProjectKey; this.actualFilePath = outputFilePath; this.actualWs = ws; }
public void IsLicenseValid_SonarQube_Commercial_AuthNotForced_LicenseIsValid() { this.ws = new SonarWebService(this.downloader, "http://*****:*****@"{ ""isValidLicense"": true }"; this.ws.IsServerLicenseValid().Result.Should().BeTrue(); }
IDictionary <string, string> IPropertiesFetcher.FetchProperties(SonarWebService ws, string sonarProjectKey) { Assert.IsFalse(string.IsNullOrWhiteSpace(sonarProjectKey), "Supplied project key should not be null"); this.fetchPropertiesCalled = true; this.actualKey = sonarProjectKey; this.actualWs = ws; return(new Dictionary <string, string>()); }
public void IsLicenseValid_SonarQube_CE_SkipLicenseCheck() { this.ws = new SonarWebService(this.downloader, "http://*****:*****@"{""errors"":[{""msg"":""Unknown url: /api/editions/is_valid_license""}]}", true); var result = this.ws.IsServerLicenseValid().Result; Assert.AreEqual(true, result); }
public void IsLicenseValid_SonarQube_Commercial_AuthNotForced_LicenseIsInvalid() { this.ws = new SonarWebService(this.downloader, "http://*****:*****@"{ ""isValidLicense"": false }"; var result = this.ws.IsServerLicenseValid().Result; Assert.AreEqual(false, result); }
IDictionary <string, string> IPropertiesFetcher.FetchProperties(SonarWebService ws, string sonarProjectKey, ILogger logger) { Assert.IsFalse(string.IsNullOrWhiteSpace(sonarProjectKey), "Supplied project key should not be null"); this.fetchPropertiesCalled = true; if (FetchException != null) { throw FetchException; } this.actualKey = sonarProjectKey; this.actualWs = ws; return(this.PropertiesToReturn ?? new Dictionary <string, string>()); }
IDictionary<string, string> IPropertiesFetcher.FetchProperties(SonarWebService ws, string sonarProjectKey, ILogger logger) { Assert.IsFalse(string.IsNullOrWhiteSpace(sonarProjectKey), "Supplied project key should not be null"); this.fetchPropertiesCalled = true; if (FetchException != null) { throw FetchException; } this.actualKey = sonarProjectKey; this.actualWs = ws; return this.PropertiesToReturn ?? new Dictionary<string, string>(); }
public void ServerUrlWithTrailingSlash() { ws = new SonarWebService(downloader, "http://myhost:222/"); downloader.Pages["http://myhost:222/api/profiles/list?language=cs&project=foo+bar"] = "[{\"name\":\"profile1\",\"language\":\"cs\",\"default\":true}]"; string qualityProfile; bool result = ws.TryGetQualityProfile("foo bar", "cs", out qualityProfile); Assert.IsTrue(result); Assert.AreEqual("profile1", qualityProfile); downloader.Pages["http://myhost:222/api/profiles/index?language=cs&name=Sonar+way"] = "[{\"name\":\"Sonar way\",\"language\":\"cs\",\"default\":true}]"; var expected1 = new List <string>(); var actual1 = new List <string>(ws.GetActiveRuleKeys("Sonar way", "cs", "foo")); Assert.AreEqual(true, expected1.SequenceEqual(actual1)); downloader.Pages["http://myhost:222/api/rules/search?f=internalKey&ps=" + int.MaxValue + "&repositories=fxcop"] = "{\"total\":2,\"p\":1,\"ps\":10,\"rules\":[{\"key\":\"fxcop:My_Own_FxCop_Rule\"},{\"key\":\"fxcop:UriParametersShouldNotBeStrings\",\"internalKey\":\"CA1054\"}]}"; var expected2 = new Dictionary <string, string>(); expected2["fxcop:My_Own_FxCop_Rule"] = null; expected2["fxcop:UriParametersShouldNotBeStrings"] = "CA1054"; var actual2 = ws.GetInternalKeys("fxcop"); Assert.AreEqual(true, expected2.Count == actual2.Count && !expected2.Except(actual2).Any()); downloader.Pages["http://myhost:222/api/properties?resource=foo+bar"] = "[{\"key\": \"sonar.property1\",\"value\": \"value1\"},{\"key\": \"sonar.property2\",\"value\": \"value2\"}]"; var expected3 = new Dictionary <string, string>(); expected3["sonar.property1"] = "value1"; expected3["sonar.property2"] = "value2"; expected3["sonar.cs.msbuild.testProjectPattern"] = SonarProperties.DefaultTestProjectPattern; var actual3 = ws.GetProperties("foo bar", new TestLogger()); Assert.AreEqual(true, expected3.Count == actual3.Count && !expected3.Except(actual3).Any()); downloader.Pages["http://myhost:222/api/updatecenter/installed_plugins"] = "[{\"key\":\"visualstudio\",\"name\":\"...\",\"version\":\"1.2\"},{\"key\":\"csharp\",\"name\":\"C#\",\"version\":\"4.0\"}]"; var expected4 = new List <string>(); expected4.Add("visualstudio"); expected4.Add("csharp"); var actual4 = new List <string>(ws.GetInstalledPlugins()); Assert.AreEqual(true, expected4.SequenceEqual(actual4)); }
public void TryGetQualityProfile_SonarCloud_InvalidOrganizationKey() { const string serverUrl = "http://localhost:42424"; const string projectKey = "projectKey"; var mockDownloader = new Mock <IDownloader>(MockBehavior.Strict); mockDownloader.Setup(x => x.Download($"{serverUrl}/api/server/version", false)).Returns(Task.FromResult("8.0.0.22548")); mockDownloader.Setup(x => x.TryDownloadIfExists($"{serverUrl}/api/qualityprofiles/search?project={projectKey}&organization=ThisIsInvalidValue", false)).Returns(Task.FromResult(Tuple.Create(false, (string)null))); mockDownloader.Setup(x => x.Download($"{serverUrl}/api/qualityprofiles/search?defaults=true&organization=ThisIsInvalidValue", false)).Returns(Task.FromResult <string>(null)); // SC returns 404, WebClientDownloader returns null mockDownloader.Setup(x => x.Dispose()); using (var service = new SonarWebService(mockDownloader.Object, serverUrl, this.logger)) { Action a = () => _ = service.TryGetQualityProfile("projectKey", null, "ThisIsInvalidValue", "cs").Result; a.Should().Throw <AggregateException>().WithMessage("One or more errors occurred. (Cannot download quality profile. Check scanner arguments and the reported URL for more information.)"); logger.AssertErrorLogged("Failed to request and parse 'http://localhost:42424/api/qualityprofiles/search?defaults=true&organization=ThisIsInvalidValue': Cannot download quality profile. Check scanner arguments and the reported URL for more information."); logger.AssertErrorLogged("Failed to request and parse 'http://localhost:42424/api/qualityprofiles/search?project=projectKey&organization=ThisIsInvalidValue': Cannot download quality profile. Check scanner arguments and the reported URL for more information."); } }
public void GetProperties_63plus_Forbidden() { const string serverUrl = "http://localhost"; const string projectKey = "my-project"; var downloaderMock = new Mock <IDownloader>(); downloaderMock .Setup(x => x.Download($"{serverUrl}/api/server/version", false)) .Returns(Task.FromResult("6.3.0.0")); downloaderMock .Setup(x => x.TryDownloadIfExists($"{serverUrl}/api/settings/values?component={projectKey}", true)) .Throws(new HttpRequestException("Forbidden")); var service = new SonarWebService(downloaderMock.Object, serverUrl, this.logger); Action action = () => _ = service.GetProperties(projectKey, null).Result; action.Should().Throw <HttpRequestException>(); this.logger.Errors.Should().HaveCount(1); }
public void Init() { downloader = new TestDownloader(); ws = new SonarWebService(downloader, "http://myhost:222"); }
public void ServerUrlWithTrailingSlash() { ws = new SonarWebService(downloader, "http://myhost:222/", new TestLogger()); // Check that profiles are correctly defaulted as well as branch-specific // This test includes a regression scenario for SONARMSBRU-187: // Requesting properties for project:branch should return branch-specific data downloader.Pages["http://myhost:222/api/profiles/list?language=cs&project=foo+bar"] = "[{\"name\":\"profile1\",\"language\":\"cs\",\"default\":true}]"; downloader.Pages["http://myhost:222/api/profiles/list?language=cs&project=foo+bar%3AaBranch"] = "[{\"name\":\"profile2\",\"language\":\"cs\",\"default\":false}]"; downloader.Pages["http://myhost:222/api/profiles/list?language=cs&project=foo+bar%3AanotherBranch"] = "[{\"name\":\"profile3\",\"language\":\"cs\",\"default\":false}]"; string qualityProfile1; string qualityProfile2; string qualityProfile3; bool result1 = ws.TryGetQualityProfile("foo bar", null, "cs", out qualityProfile1); bool result2 = ws.TryGetQualityProfile("foo bar", "aBranch", "cs", out qualityProfile2); bool result3 = ws.TryGetQualityProfile("foo bar", "anotherBranch", "cs", out qualityProfile3); Assert.IsTrue(result1); Assert.IsTrue(result2); Assert.IsTrue(result3); Assert.AreEqual("profile1", qualityProfile1); Assert.AreEqual("profile2", qualityProfile2); Assert.AreEqual("profile3", qualityProfile3); Assert.IsTrue(result1); Assert.IsTrue(result2); Assert.IsTrue(result3); Assert.AreEqual("profile1", qualityProfile1); Assert.AreEqual("profile2", qualityProfile2); Assert.AreEqual("profile3", qualityProfile3); downloader.Pages["http://myhost:222/api/profiles/index?language=cs&name=Sonar+way"] = "[{\"name\":\"Sonar way\",\"language\":\"cs\",\"default\":true}]"; var expected1 = new List <string>(); var actual1 = new List <string>(ws.GetActiveRuleKeys("Sonar way", "cs", "foo")); Assert.AreEqual(true, expected1.SequenceEqual(actual1)); downloader.Pages["http://myhost:222/api/rules/search?f=internalKey&ps=" + int.MaxValue + "&repositories=fxcop"] = "{\"total\":2,\"p\":1,\"ps\":10,\"rules\":[{\"key\":\"fxcop:My_Own_FxCop_Rule\"},{\"key\":\"fxcop:UriParametersShouldNotBeStrings\",\"internalKey\":\"CA1054\"}]}"; var expected2 = new Dictionary <string, string>(); expected2["fxcop:UriParametersShouldNotBeStrings"] = "CA1054"; var actual2 = ws.GetInternalKeys("fxcop"); Assert.AreEqual(true, expected2.Count == actual2.Count && !expected2.Except(actual2).Any()); downloader.Pages["http://myhost:222/api/properties?resource=foo+bar"] = "[{\"key\": \"sonar.property1\",\"value\": \"value1\"},{\"key\": \"sonar.property2\",\"value\": \"value2\"}]"; downloader.Pages["http://myhost:222/api/properties?resource=foo+bar%3AaBranch"] = "[{\"key\": \"sonar.property1\",\"value\": \"anotherValue1\"},{\"key\": \"sonar.property2\",\"value\": \"anotherValue2\"}]"; var expected3_1 = new Dictionary <string, string>(); expected3_1["sonar.property1"] = "value1"; expected3_1["sonar.property2"] = "value2"; expected3_1["sonar.cs.msbuild.testProjectPattern"] = SonarProperties.DefaultTestProjectPattern; var actual3_1 = ws.GetProperties("foo bar"); var expected3_2 = new Dictionary <string, string>(); expected3_2["sonar.property1"] = "anotherValue1"; expected3_2["sonar.property2"] = "anotherValue2"; expected3_2["sonar.cs.msbuild.testProjectPattern"] = SonarProperties.DefaultTestProjectPattern; var actual3_2 = ws.GetProperties("foo bar", "aBranch"); Assert.AreEqual(true, expected3_1.Count == actual3_1.Count && !expected3_1.Except(actual3_1).Any()); Assert.AreEqual(true, expected3_2.Count == actual3_2.Count && !expected3_2.Except(actual3_2).Any()); downloader.Pages["http://myhost:222/api/updatecenter/installed_plugins"] = "[{\"key\":\"visualstudio\",\"name\":\"...\",\"version\":\"1.2\"},{\"key\":\"csharp\",\"name\":\"C#\",\"version\":\"4.0\"}]"; var expected4 = new List <string>(); expected4.Add("visualstudio"); expected4.Add("csharp"); var actual4 = new List <string>(ws.GetInstalledPlugins()); Assert.AreEqual(true, expected4.SequenceEqual(actual4)); }
public void ServerUrlWithTrailingSlash() { ws = new SonarWebService(downloader, "http://myhost:222/"); downloader.Pages["http://myhost:222/api/profiles/list?language=cs&project=foo+bar"] = "[{\"name\":\"profile1\",\"language\":\"cs\",\"default\":true}]"; string qualityProfile; bool result = ws.TryGetQualityProfile("foo bar", "cs", out qualityProfile); Assert.IsTrue(result); Assert.AreEqual("profile1", qualityProfile); downloader.Pages["http://myhost:222/api/profiles/index?language=cs&name=Sonar+way"] = "[{\"name\":\"Sonar way\",\"language\":\"cs\",\"default\":true}]"; var expected1 = new List<string>(); var actual1 = new List<string>(ws.GetActiveRuleKeys("Sonar way", "cs", "foo")); Assert.AreEqual(true, expected1.SequenceEqual(actual1)); downloader.Pages["http://myhost:222/api/rules/search?f=internalKey&ps=" + int.MaxValue + "&repositories=fxcop"] = "{\"total\":2,\"p\":1,\"ps\":10,\"rules\":[{\"key\":\"fxcop:My_Own_FxCop_Rule\"},{\"key\":\"fxcop:UriParametersShouldNotBeStrings\",\"internalKey\":\"CA1054\"}]}"; var expected2 = new Dictionary<string, string>(); expected2["fxcop:My_Own_FxCop_Rule"] = null; expected2["fxcop:UriParametersShouldNotBeStrings"] = "CA1054"; var actual2 = ws.GetInternalKeys("fxcop"); Assert.AreEqual(true, expected2.Count == actual2.Count && !expected2.Except(actual2).Any()); downloader.Pages["http://myhost:222/api/properties?resource=foo+bar"] = "[{\"key\": \"sonar.property1\",\"value\": \"value1\"},{\"key\": \"sonar.property2\",\"value\": \"value2\"}]"; var expected3 = new Dictionary<string, string>(); expected3["sonar.property1"] = "value1"; expected3["sonar.property2"] = "value2"; expected3["sonar.cs.msbuild.testProjectPattern"] = SonarProperties.DefaultTestProjectPattern; var actual3 = ws.GetProperties("foo bar", new TestLogger()); Assert.AreEqual(true, expected3.Count == actual3.Count && !expected3.Except(actual3).Any()); downloader.Pages["http://myhost:222/api/updatecenter/installed_plugins"] = "[{\"key\":\"visualstudio\",\"name\":\"...\",\"version\":\"1.2\"},{\"key\":\"csharp\",\"name\":\"C#\",\"version\":\"4.0\"}]"; var expected4 = new List<string>(); expected4.Add("visualstudio"); expected4.Add("csharp"); var actual4 = new List<string>(ws.GetInstalledPlugins()); Assert.AreEqual(true, expected4.SequenceEqual(actual4)); }
public void Init() { downloader = new TestDownloader(); ws = new SonarWebService(downloader, "http://localhost:9000", "cs", "fxcop"); }
public void ServerUrlWithTrailingSlash() { ws = new SonarWebService(downloader, "http://myhost:222/", new TestLogger()); // Check that profiles are correctly defaulted as well as branch-specific // This test includes a regression scenario for SONARMSBRU-187: // Requesting properties for project:branch should return branch-specific data downloader.Pages["http://myhost:222/api/profiles/list?language=cs&project=foo+bar"] = "[{\"name\":\"profile1\",\"language\":\"cs\",\"default\":true}]"; downloader.Pages["http://myhost:222/api/profiles/list?language=cs&project=foo+bar%3AaBranch"] = "[{\"name\":\"profile2\",\"language\":\"cs\",\"default\":false}]"; downloader.Pages["http://myhost:222/api/profiles/list?language=cs&project=foo+bar%3AanotherBranch"] = "[{\"name\":\"profile3\",\"language\":\"cs\",\"default\":false}]"; string qualityProfile1; string qualityProfile2; string qualityProfile3; bool result1 = ws.TryGetQualityProfile("foo bar", null, "cs", out qualityProfile1); bool result2 = ws.TryGetQualityProfile("foo bar", "aBranch", "cs", out qualityProfile2); bool result3 = ws.TryGetQualityProfile("foo bar", "anotherBranch", "cs", out qualityProfile3); Assert.IsTrue(result1); Assert.IsTrue(result2); Assert.IsTrue(result3); Assert.AreEqual("profile1", qualityProfile1); Assert.AreEqual("profile2", qualityProfile2); Assert.AreEqual("profile3", qualityProfile3); Assert.IsTrue(result1); Assert.IsTrue(result2); Assert.IsTrue(result3); Assert.AreEqual("profile1", qualityProfile1); Assert.AreEqual("profile2", qualityProfile2); Assert.AreEqual("profile3", qualityProfile3); downloader.Pages["http://myhost:222/api/profiles/index?language=cs&name=Sonar+way"] = "[{\"name\":\"Sonar way\",\"language\":\"cs\",\"default\":true}]"; var expected1 = new List<string>(); var actual1 = new List<string>(ws.GetActiveRuleKeys("Sonar way", "cs", "foo")); Assert.AreEqual(true, expected1.SequenceEqual(actual1)); downloader.Pages["http://myhost:222/api/rules/search?f=internalKey&ps=" + int.MaxValue + "&repositories=fxcop"] = "{\"total\":2,\"p\":1,\"ps\":10,\"rules\":[{\"key\":\"fxcop:My_Own_FxCop_Rule\"},{\"key\":\"fxcop:UriParametersShouldNotBeStrings\",\"internalKey\":\"CA1054\"}]}"; var expected2 = new Dictionary<string, string>(); expected2["fxcop:UriParametersShouldNotBeStrings"] = "CA1054"; var actual2 = ws.GetInternalKeys("fxcop"); Assert.AreEqual(true, expected2.Count == actual2.Count && !expected2.Except(actual2).Any()); downloader.Pages["http://myhost:222/api/properties?resource=foo+bar"] = "[{\"key\": \"sonar.property1\",\"value\": \"value1\"},{\"key\": \"sonar.property2\",\"value\": \"value2\"}]"; downloader.Pages["http://myhost:222/api/properties?resource=foo+bar%3AaBranch"] = "[{\"key\": \"sonar.property1\",\"value\": \"anotherValue1\"},{\"key\": \"sonar.property2\",\"value\": \"anotherValue2\"}]"; var expected3_1 = new Dictionary<string, string>(); expected3_1["sonar.property1"] = "value1"; expected3_1["sonar.property2"] = "value2"; expected3_1["sonar.cs.msbuild.testProjectPattern"] = SonarProperties.DefaultTestProjectPattern; var actual3_1 = ws.GetProperties("foo bar"); var expected3_2 = new Dictionary<string, string>(); expected3_2["sonar.property1"] = "anotherValue1"; expected3_2["sonar.property2"] = "anotherValue2"; expected3_2["sonar.cs.msbuild.testProjectPattern"] = SonarProperties.DefaultTestProjectPattern; var actual3_2 = ws.GetProperties("foo bar", "aBranch"); Assert.AreEqual(true, expected3_1.Count == actual3_1.Count && !expected3_1.Except(actual3_1).Any()); Assert.AreEqual(true, expected3_2.Count == actual3_2.Count && !expected3_2.Except(actual3_2).Any()); downloader.Pages["http://myhost:222/api/updatecenter/installed_plugins"] = "[{\"key\":\"visualstudio\",\"name\":\"...\",\"version\":\"1.2\"},{\"key\":\"csharp\",\"name\":\"C#\",\"version\":\"4.0\"}]"; var expected4 = new List<string>(); expected4.Add("visualstudio"); expected4.Add("csharp"); var actual4 = new List<string>(ws.GetInstalledPlugins()); Assert.AreEqual(true, expected4.SequenceEqual(actual4)); }