mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-29 09:35:38 -05:00
Unit tests for Azure scenarios (#495)
* Test firewall rule handling is able to process through the service layer * Additional tests for authentication and the resource wrapper code * Positive test case for CreateFirewallRule * Fixed copyright and usings
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Contracts;
|
||||
using Microsoft.SqlTools.ResourceProvider.DefaultImpl;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
|
||||
{
|
||||
public class AzureAuthenticationManagerTest
|
||||
{
|
||||
private Mock<IAzureResourceManager> resourceManagerMock;
|
||||
private RegisteredServiceProvider serviceProvider;
|
||||
|
||||
public AzureAuthenticationManagerTest()
|
||||
{
|
||||
resourceManagerMock = new Mock<IAzureResourceManager>();
|
||||
serviceProvider = new RegisteredServiceProvider();
|
||||
serviceProvider.RegisterSingleService<IAzureResourceManager>(resourceManagerMock.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CurrentUserShouldBeNullWhenUserIsNotSignedIn()
|
||||
{
|
||||
IAzureAuthenticationManager accountManager = await CreateAccountManager(null, null);
|
||||
Assert.Null(await accountManager.GetCurrentAccountAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetSubscriptionShouldReturnEmptyWhenUserIsNotSignedIn()
|
||||
{
|
||||
IAzureAuthenticationManager accountManager = await CreateAccountManager(null, null);
|
||||
IEnumerable<IAzureUserAccountSubscriptionContext> result =
|
||||
await accountManager.GetSelectedSubscriptionsAsync();
|
||||
Assert.False(result.Any());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetSubscriptionShouldThrowWhenUserNeedsAuthentication()
|
||||
{
|
||||
var currentUserAccount = CreateAccount();
|
||||
currentUserAccount.Account.IsStale = true;
|
||||
IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, null);
|
||||
await Assert.ThrowsAsync<UserNeedsAuthenticationException>(() => accountManager.GetSelectedSubscriptionsAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetSubscriptionShouldThrowIfFailed()
|
||||
{
|
||||
var currentUserAccount = CreateAccount();
|
||||
IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, null, true);
|
||||
await Assert.ThrowsAsync<ServiceFailedException>(() => accountManager.GetSelectedSubscriptionsAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetSubscriptionShouldReturnTheListSuccessfully()
|
||||
{
|
||||
List<IAzureUserAccountSubscriptionContext> subscriptions = new List<IAzureUserAccountSubscriptionContext> {
|
||||
new Mock<IAzureUserAccountSubscriptionContext>().Object
|
||||
};
|
||||
var currentUserAccount = CreateAccount();
|
||||
IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, subscriptions, false);
|
||||
IEnumerable<IAzureUserAccountSubscriptionContext> result =
|
||||
await accountManager.GetSelectedSubscriptionsAsync();
|
||||
Assert.True(result.Any());
|
||||
}
|
||||
|
||||
private AccountTokenWrapper CreateAccount(bool needsReauthentication = false)
|
||||
{
|
||||
return new AccountTokenWrapper(new Account()
|
||||
{
|
||||
Key = new AccountKey()
|
||||
{
|
||||
AccountId = "MyAccount",
|
||||
ProviderId = "MSSQL"
|
||||
},
|
||||
IsStale = needsReauthentication
|
||||
},
|
||||
new Dictionary<string, AccountSecurityToken>());
|
||||
}
|
||||
private async Task<AzureAuthenticationManager> CreateAccountManager(AccountTokenWrapper currentAccount,
|
||||
IEnumerable<IAzureUserAccountSubscriptionContext> subscriptions, bool shouldFail = false)
|
||||
{
|
||||
AzureAuthenticationManager azureAuthenticationManager = new AzureAuthenticationManager();
|
||||
azureAuthenticationManager.SetServiceProvider(serviceProvider);
|
||||
if (currentAccount != null)
|
||||
{
|
||||
await azureAuthenticationManager.SetCurrentAccountAsync(currentAccount);
|
||||
}
|
||||
|
||||
if (!shouldFail)
|
||||
{
|
||||
resourceManagerMock.Setup(x => x.GetSubscriptionContextsAsync(It.IsAny<IAzureUserAccount>())).Returns(Task.FromResult(subscriptions));
|
||||
}
|
||||
else
|
||||
{
|
||||
resourceManagerMock.Setup(x => x.GetSubscriptionContextsAsync(It.IsAny<IAzureUserAccount>())).Throws(new Exception());
|
||||
}
|
||||
|
||||
return azureAuthenticationManager;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.Azure.Management.Sql.Models;
|
||||
using Microsoft.SqlTools.ResourceProvider.DefaultImpl;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
|
||||
{
|
||||
public class AzureResourceWrapperTest
|
||||
{
|
||||
[Fact]
|
||||
public void ShouldParseResourceGroupFromId()
|
||||
{
|
||||
// Given a resource with a known resource group
|
||||
TrackedResource trackedResource = CreateMockResource(
|
||||
"/subscriptions/aaaaaaaa-1234-cccc-dddd-a1234v12c23/resourceGroups/myresourcegroup/providers/Microsoft.Sql/servers/my-server",
|
||||
"my-server",
|
||||
"Microsoft.Sql");
|
||||
|
||||
// When I get the resource group name
|
||||
AzureResourceWrapper resource = new AzureResourceWrapper(trackedResource);
|
||||
string rgName = resource.ResourceGroupName;
|
||||
|
||||
// then I get it as expected
|
||||
Assert.Equal("myresourcegroup", rgName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldHandleMissingResourceGroup()
|
||||
{
|
||||
// Given a resource without resource group in the ID
|
||||
TrackedResource trackedResource = CreateMockResource(
|
||||
"/subscriptions/aaaaaaaa-1234-cccc-dddd-a1234v12c23",
|
||||
"my-server",
|
||||
"Microsoft.Sql");
|
||||
|
||||
// When I get the resource group name
|
||||
AzureResourceWrapper resource = new AzureResourceWrapper(trackedResource);
|
||||
string rgName = resource.ResourceGroupName;
|
||||
|
||||
// then I get string.Empty
|
||||
Assert.Equal(string.Empty, rgName);
|
||||
}
|
||||
|
||||
private TrackedResource CreateMockResource(string id = null, string name = null, string type = null)
|
||||
{
|
||||
return new TrackedResource("Somewhere", id, name, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetShouldReturnEmptyGivenNotSubscriptionFound()
|
||||
public async Task GetShouldReturnEmptyGivenNoSubscriptionFound()
|
||||
{
|
||||
Dictionary<string, List<string>> subscriptionToDatabaseMap = new Dictionary<string, List<string>>();
|
||||
|
||||
|
||||
@@ -3,17 +3,30 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core;
|
||||
using Moq;
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ResourceProvider;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Contracts;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Firewall;
|
||||
using Microsoft.SqlTools.ResourceProvider.DefaultImpl;
|
||||
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter
|
||||
{
|
||||
public class ResourceProviderServiceTests
|
||||
{
|
||||
private const int SqlAzureFirewallBlockedErrorNumber = 40615;
|
||||
private const int SqlAzureLoginFailedErrorNumber = 18456;
|
||||
private string errorMessageWithIp = "error Message with 1.2.3.4 as IP address";
|
||||
|
||||
public ResourceProviderServiceTests()
|
||||
{
|
||||
HostMock = new Mock<IProtocolEndpoint>();
|
||||
@@ -34,7 +47,194 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter
|
||||
|
||||
protected ResourceProviderService ResourceProviderService { get; private set; }
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task TestHandleFirewallRuleIgnoresNonMssqlProvider()
|
||||
{
|
||||
// Given a non-MSSQL provider
|
||||
var handleFirewallParams = new HandleFirewallRuleParams()
|
||||
{
|
||||
ErrorCode = SqlAzureFirewallBlockedErrorNumber,
|
||||
ErrorMessage = errorMessageWithIp,
|
||||
ConnectionTypeId = "Other"
|
||||
};
|
||||
// When I ask whether the service can process an error as a firewall rule request
|
||||
await TestUtils.RunAndVerify<HandleFirewallRuleResponse>((context) => ResourceProviderService.ProcessHandleFirewallRuleRequest(handleFirewallParams, context), (response) =>
|
||||
{
|
||||
// Then I expect the response to be false and no IP information to be sent
|
||||
Assert.NotNull(response);
|
||||
Assert.False(response.Result);
|
||||
Assert.Null(response.IpAddress);
|
||||
Assert.Equal(Microsoft.SqlTools.ResourceProvider.Core.SR.FirewallRuleUnsupportedConnectionType, response.ErrorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestHandleFirewallRuleSupportsMssqlProvider()
|
||||
{
|
||||
// Given a firewall error for the MSSQL provider
|
||||
var handleFirewallParams = new HandleFirewallRuleParams()
|
||||
{
|
||||
ErrorCode = SqlAzureFirewallBlockedErrorNumber,
|
||||
ErrorMessage = errorMessageWithIp,
|
||||
ConnectionTypeId = "MSSQL"
|
||||
};
|
||||
// When I ask whether the service can process an error as a firewall rule request
|
||||
await TestUtils.RunAndVerify<HandleFirewallRuleResponse>((context) => ResourceProviderService.ProcessHandleFirewallRuleRequest(handleFirewallParams, context), (response) =>
|
||||
{
|
||||
// Then I expect the response to be true and the IP address to be extracted
|
||||
Assert.NotNull(response);
|
||||
Assert.True(response.Result);
|
||||
Assert.Equal("1.2.3.4", response.IpAddress);
|
||||
Assert.Null(response.ErrorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestHandleFirewallRuleIgnoresNonFirewallErrors()
|
||||
{
|
||||
// Given a login error for the MSSQL provider
|
||||
var handleFirewallParams = new HandleFirewallRuleParams()
|
||||
{
|
||||
ErrorCode = SqlAzureLoginFailedErrorNumber,
|
||||
ErrorMessage = errorMessageWithIp,
|
||||
ConnectionTypeId = "MSSQL"
|
||||
};
|
||||
// When I ask whether the service can process an error as a firewall rule request
|
||||
await TestUtils.RunAndVerify<HandleFirewallRuleResponse>((context) => ResourceProviderService.ProcessHandleFirewallRuleRequest(handleFirewallParams, context), (response) =>
|
||||
{
|
||||
// Then I expect the response to be false and no IP address to be defined
|
||||
Assert.NotNull(response);
|
||||
Assert.False(response.Result);
|
||||
Assert.Equal(string.Empty, response.IpAddress);
|
||||
Assert.Null(response.ErrorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestHandleFirewallRuleDoesntBreakWithoutIp()
|
||||
{
|
||||
// Given a firewall error with no IP address in the error message
|
||||
var handleFirewallParams = new HandleFirewallRuleParams()
|
||||
{
|
||||
ErrorCode = SqlAzureFirewallBlockedErrorNumber,
|
||||
ErrorMessage = "No IP here",
|
||||
ConnectionTypeId = "MSSQL"
|
||||
};
|
||||
// When I ask whether the service can process an error as a firewall rule request
|
||||
await TestUtils.RunAndVerify<HandleFirewallRuleResponse>((context) => ResourceProviderService.ProcessHandleFirewallRuleRequest(handleFirewallParams, context), (response) =>
|
||||
{
|
||||
// Then I expect the response to be fakse as we require the known IP address to function
|
||||
Assert.NotNull(response);
|
||||
Assert.False(response.Result);
|
||||
Assert.Equal(string.Empty, response.IpAddress);
|
||||
Assert.Null(response.ErrorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestCreateFirewallRuleBasicRequest()
|
||||
{
|
||||
// Given a firewall request for a valid subscription
|
||||
string serverName = "myserver.database.windows.net";
|
||||
var sub1Mock = new Mock<IAzureUserAccountSubscriptionContext>();
|
||||
var sub2Mock = new Mock<IAzureUserAccountSubscriptionContext>();
|
||||
var server = new SqlAzureResource(new Azure.Management.Sql.Models.Server("Somewhere",
|
||||
"1234", "myserver", "SQLServer",
|
||||
null, null, null, null, null, null, null,
|
||||
fullyQualifiedDomainName: serverName));
|
||||
var subsToServers = new List<Tuple<IAzureUserAccountSubscriptionContext, IEnumerable<IAzureSqlServerResource>>>()
|
||||
{
|
||||
Tuple.Create(sub1Mock.Object, Enumerable.Empty<IAzureSqlServerResource>()),
|
||||
Tuple.Create(sub2Mock.Object, new IAzureSqlServerResource[] { server }.AsEnumerable())
|
||||
};
|
||||
var azureRmResponse = new FirewallRuleResponse()
|
||||
{
|
||||
Created = true,
|
||||
StartIpAddress = null,
|
||||
EndIpAddress = null
|
||||
};
|
||||
SetupDependencies(subsToServers, azureRmResponse);
|
||||
|
||||
// When I request the firewall be created
|
||||
var createFirewallParams = new CreateFirewallRuleParams()
|
||||
{
|
||||
ServerName = serverName,
|
||||
StartIpAddress = "1.1.1.1",
|
||||
EndIpAddress = "1.1.1.255",
|
||||
Account = CreateAccount(),
|
||||
SecurityTokenMappings = new Dictionary<string, AccountSecurityToken>()
|
||||
};
|
||||
await TestUtils.RunAndVerify<CreateFirewallRuleResponse>(
|
||||
(context) => ResourceProviderService.HandleCreateFirewallRuleRequest(createFirewallParams, context),
|
||||
(response) =>
|
||||
{
|
||||
// Then I expect the response to be fakse as we require the known IP address to function
|
||||
Assert.NotNull(response);
|
||||
Assert.Null(response.ErrorMessage);
|
||||
Assert.True(response.Result);
|
||||
});
|
||||
}
|
||||
|
||||
private void SetupDependencies(
|
||||
IList<Tuple<IAzureUserAccountSubscriptionContext, IEnumerable<IAzureSqlServerResource>>> subsToServers,
|
||||
FirewallRuleResponse response)
|
||||
{
|
||||
SetupCreateSession();
|
||||
SetupReturnsSubscriptions(subsToServers.Select(s => s.Item1));
|
||||
foreach(var s in subsToServers)
|
||||
{
|
||||
SetupAzureServers(s.Item1, s.Item2);
|
||||
}
|
||||
SetupFirewallResponse(response);
|
||||
}
|
||||
|
||||
private void SetupReturnsSubscriptions(IEnumerable<IAzureUserAccountSubscriptionContext> subs)
|
||||
{
|
||||
AuthenticationManagerMock.Setup(a => a.GetSubscriptionsAsync()).Returns(() => Task.FromResult(subs));
|
||||
}
|
||||
|
||||
private void SetupCreateSession()
|
||||
{
|
||||
ResourceManagerMock.Setup(r => r.CreateSessionAsync(It.IsAny<IAzureUserAccountSubscriptionContext>()))
|
||||
.Returns((IAzureUserAccountSubscriptionContext sub) =>
|
||||
{
|
||||
var sessionMock = new Mock<IAzureResourceManagementSession>();
|
||||
sessionMock.SetupProperty(s => s.SubscriptionContext, sub);
|
||||
return Task.FromResult(sessionMock.Object);
|
||||
});
|
||||
}
|
||||
|
||||
private void SetupAzureServers(IAzureSubscriptionContext sub, IEnumerable<IAzureSqlServerResource> servers)
|
||||
{
|
||||
Func<IAzureResourceManagementSession, bool> isExpectedSub = (session) =>
|
||||
{
|
||||
return session.SubscriptionContext == sub;
|
||||
};
|
||||
ResourceManagerMock.Setup(r => r.GetSqlServerAzureResourcesAsync(
|
||||
It.Is<IAzureResourceManagementSession>((session) => isExpectedSub(session))
|
||||
)).Returns(() => Task.FromResult(servers));
|
||||
}
|
||||
|
||||
private void SetupFirewallResponse(FirewallRuleResponse response)
|
||||
{
|
||||
ResourceManagerMock.Setup(r => r.CreateFirewallRuleAsync(
|
||||
It.IsAny<IAzureResourceManagementSession>(),
|
||||
It.IsAny<IAzureSqlServerResource>(),
|
||||
It.IsAny<FirewallRuleRequest>())
|
||||
).Returns(() => Task.FromResult(response));
|
||||
}
|
||||
|
||||
private Account CreateAccount(bool needsReauthentication = false)
|
||||
{
|
||||
return new Account()
|
||||
{
|
||||
Key = new AccountKey()
|
||||
{
|
||||
AccountId = "MyAccount",
|
||||
ProviderId = "MSSQL"
|
||||
},
|
||||
IsStale = needsReauthentication
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user