//
// 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());
}
}
}