// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // #nullable disable using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.SqlTools.ResourceProvider.Core; using Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Fakes; using NUnit.Framework; namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure { /// /// Tests for AzureDatabaseDiscoveryProvider to verify getting azure databases using azure resource manager /// public class AzureDatabaseDiscoveryProviderTest { [Test] public async Task GetShouldReturnDatabasesSuccessfully() { string databaseName1 = "server/db1"; string databaseName2 = "db2"; string databaseName3 = "server/"; string databaseName4 = "/db4"; List databasesForSubscription = new List() { databaseName1, databaseName2 }; Dictionary> subscriptionToDatabaseMap = new Dictionary>(); subscriptionToDatabaseMap.Add(Guid.NewGuid().ToString(), databasesForSubscription); subscriptionToDatabaseMap.Add(Guid.NewGuid().ToString(), new List() { databaseName3, databaseName4, }); AzureDatabaseDiscoveryProvider databaseDiscoveryProvider = FakeDataFactory.CreateAzureDatabaseDiscoveryProvider(subscriptionToDatabaseMap); ServiceResponse response = await databaseDiscoveryProvider.GetDatabaseInstancesAsync(serverName: null, cancellationToken: new CancellationToken()); List list = response.Data.ToList(); Assert.NotNull(list); Assert.True(list.Any(x => x.Name == "db1" && x.ServerInstanceInfo.Name == "server")); Assert.False(list.Any(x => x.Name == "db2" && x.ServerInstanceInfo.Name == "")); Assert.True(list.Any(x => x.Name == "" && x.ServerInstanceInfo.Name == "server")); Assert.False(list.Any(x => x.Name == "db4" && x.ServerInstanceInfo.Name == "")); Assert.True(list.Count() == 2); } [Test] public async Task GetShouldReturnDatabasesEvenIfFailsForOneServer() { string databaseName1 = "server1/db1"; string databaseName2 = "server1/db2"; string databaseName3 = "error/db3"; string databaseName4 = "server2/db4"; List databasesForSubscription = new List() { databaseName1, databaseName2 }; Dictionary> subscriptionToDatabaseMap = new Dictionary>(); subscriptionToDatabaseMap.Add(Guid.NewGuid().ToString(), databasesForSubscription); subscriptionToDatabaseMap.Add(Guid.NewGuid().ToString(), new List() { databaseName3, databaseName4, }); AzureDatabaseDiscoveryProvider databaseDiscoveryProvider = FakeDataFactory.CreateAzureDatabaseDiscoveryProvider(subscriptionToDatabaseMap); ServiceResponse response = await databaseDiscoveryProvider.GetDatabaseInstancesAsync(serverName: null, cancellationToken: new CancellationToken()); List list = response.Data.ToList(); Assert.NotNull(list); Assert.True(list.Any(x => x.Name == "db1" && x.ServerInstanceInfo.Name == "server1")); Assert.True(list.Any(x => x.Name == "db2" && x.ServerInstanceInfo.Name == "server1")); Assert.True(list.Any(x => x.Name == "db4" && x.ServerInstanceInfo.Name == "server2")); Assert.False(list.Any(x => x.Name == "db3" && x.ServerInstanceInfo.Name == "error")); Assert.True(list.Count() == 3); Assert.NotNull(response.Errors); Assert.True(response.Errors.Count() == 1); } [Test] public async Task GetShouldReturnDatabasesFromCacheIfGetCalledTwice() { Dictionary> subscriptionToDatabaseMap = CreateSubscriptonMap(2); AddDatabases(subscriptionToDatabaseMap, 3); AzureDatabaseDiscoveryProvider databaseDiscoveryProvider = FakeDataFactory.CreateAzureDatabaseDiscoveryProvider(subscriptionToDatabaseMap); ServiceResponse response = await databaseDiscoveryProvider.GetDatabaseInstancesAsync(serverName: null, cancellationToken: new CancellationToken()); List list = response.Data.ToList(); ValidateResult(subscriptionToDatabaseMap, list); Dictionary> subscriptionToDatabaseMap2 = CopySubscriptonMap(subscriptionToDatabaseMap); AddDatabases(subscriptionToDatabaseMap2, 5); AzureTestContext testContext = new AzureTestContext(subscriptionToDatabaseMap2); databaseDiscoveryProvider.AccountManager = testContext.AzureAccountManager; databaseDiscoveryProvider.AzureResourceManager = testContext.AzureResourceManager; response = await databaseDiscoveryProvider.GetDatabaseInstancesAsync(serverName: null, cancellationToken: new CancellationToken()); list = response.Data.ToList(); //the provider should get the databases from cache for the list should match the first created data ValidateResult(subscriptionToDatabaseMap, list); } [Test] public async Task GetShouldReturnDatabasesFromServiceIfGetCalledTwiceButRefreshed() { Dictionary> subscriptionToDatabaseMap = CreateSubscriptonMap(2); AddDatabases(subscriptionToDatabaseMap, 3); AzureDatabaseDiscoveryProvider databaseDiscoveryProvider = FakeDataFactory.CreateAzureDatabaseDiscoveryProvider(subscriptionToDatabaseMap); ServiceResponse response = await databaseDiscoveryProvider.GetDatabaseInstancesAsync(serverName: null, cancellationToken: new CancellationToken()); List list = response.Data.ToList(); ValidateResult(subscriptionToDatabaseMap, list); Dictionary> subscriptionToDatabaseMap2 = CopySubscriptonMap(subscriptionToDatabaseMap); AddDatabases(subscriptionToDatabaseMap2, 5); AzureTestContext testContext = new AzureTestContext(subscriptionToDatabaseMap2); databaseDiscoveryProvider.AccountManager = testContext.AzureAccountManager; databaseDiscoveryProvider.AzureResourceManager = testContext.AzureResourceManager; await databaseDiscoveryProvider.ClearCacheAsync(); response = await databaseDiscoveryProvider.GetDatabaseInstancesAsync(serverName: null, cancellationToken: new CancellationToken()); list = response.Data.ToList(); //the provider should get the databases from cache for the list should match the first created data ValidateResult(subscriptionToDatabaseMap2, list); } private void ValidateResult(Dictionary> subscriptionToDatabaseMap, List result) { Assert.NotNull(result); int numberOfDatabases = 0; foreach (KeyValuePair> item in subscriptionToDatabaseMap) { numberOfDatabases += item.Value.Count; foreach (string databaseFullName in item.Value) { string serverName = AzureTestContext.GetServerName(databaseFullName); string databaseName = databaseFullName.Replace(serverName + @"/", ""); Assert.True(result.Any(x => x.Name == databaseName && x.ServerInstanceInfo.Name == serverName)); } } Assert.True(result.Count() == numberOfDatabases); } private void AddDatabases(Dictionary> subscriptionToDatabaseMap, int numberOfDatabases) { foreach (string key in subscriptionToDatabaseMap.Keys.ToList()) { List databases = CreateDatabases(numberOfDatabases); subscriptionToDatabaseMap[key] = databases; } } private List CreateDatabases(int numberOfDatabases) { List databases = new List(); for (int j = 0; j < numberOfDatabases; j++) { databases.Add(string.Format(CultureInfo.InvariantCulture, @"{0}/{1}", Guid.NewGuid().ToString(), Guid.NewGuid().ToString())); } return databases; } private Dictionary> CreateSubscriptonMap(int numberOfSubscriptions) { Dictionary> subscriptionToDatabaseMap = new Dictionary>(); for (int i = 0; i < numberOfSubscriptions; i++) { string id = Guid.NewGuid().ToString(); subscriptionToDatabaseMap.Add(id, null); } return subscriptionToDatabaseMap; } private Dictionary> CopySubscriptonMap(Dictionary> subscriptionToDatabaseMap) { Dictionary> subscriptionToDatabaseMapCopy = new Dictionary>(); foreach (KeyValuePair> pair in subscriptionToDatabaseMap) { subscriptionToDatabaseMapCopy.Add(pair.Key, null); } return subscriptionToDatabaseMapCopy; } [Test] public async Task GetShouldReturnEmptyGivenNotSubscriptionFound() { Dictionary> subscriptionToDatabaseMap = new Dictionary>(); AzureDatabaseDiscoveryProvider databaseDiscoveryProvider = FakeDataFactory.CreateAzureDatabaseDiscoveryProvider(subscriptionToDatabaseMap); ServiceResponse response = await databaseDiscoveryProvider.GetDatabaseInstancesAsync(serverName: null, cancellationToken: new CancellationToken()); Assert.NotNull(response); Assert.NotNull(response.Data); Assert.False(response.Data.Any()); } } }