mirror of
https://github.com/bitwarden/server
synced 2025-12-06 00:03:34 +00:00
* Initial v3 Migration * Migrate tests and debug duplicate ids * Debug duplicate ids * Support seeding * remove seeder * Upgrade to latest XUnit.v3 version * Remove Theory changes for now * Remove Theory change from DeviceRepositoryTests * Remove cancellation token additions
217 lines
7.3 KiB
C#
217 lines
7.3 KiB
C#
using System.Reflection;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Settings;
|
|
using Bit.Infrastructure.Dapper;
|
|
using Bit.Infrastructure.EntityFramework;
|
|
using Bit.Infrastructure.EntityFramework.Repositories;
|
|
using Bit.Infrastructure.IntegrationTest.Services;
|
|
using Microsoft.Extensions.Caching.Distributed;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Time.Testing;
|
|
using Xunit;
|
|
using Xunit.Sdk;
|
|
using Xunit.v3;
|
|
|
|
namespace Bit.Infrastructure.IntegrationTest;
|
|
|
|
public class DatabaseDataAttribute : DataAttribute
|
|
{
|
|
private static IConfiguration? _cachedConfiguration;
|
|
private static IConfiguration GetConfiguration()
|
|
{
|
|
return _cachedConfiguration ??= new ConfigurationBuilder()
|
|
.AddUserSecrets<DatabaseDataAttribute>(optional: true, reloadOnChange: false)
|
|
.AddEnvironmentVariables("BW_TEST_")
|
|
.AddCommandLine(Environment.GetCommandLineArgs())
|
|
.Build();
|
|
}
|
|
|
|
|
|
public bool SelfHosted { get; set; }
|
|
public bool UseFakeTimeProvider { get; set; }
|
|
public string? MigrationName { get; set; }
|
|
|
|
private void AddSqlMigrationTester(IServiceCollection services, string connectionString, string migrationName)
|
|
{
|
|
services.AddSingleton<IMigrationTesterService, SqlMigrationTesterService>(_ => new SqlMigrationTesterService(connectionString, migrationName));
|
|
}
|
|
|
|
private void AddEfMigrationTester(IServiceCollection services, SupportedDatabaseProviders databaseType, string migrationName)
|
|
{
|
|
services.AddSingleton<IMigrationTesterService, EfMigrationTesterService>(sp =>
|
|
{
|
|
var dbContext = sp.GetRequiredService<DatabaseContext>();
|
|
return new EfMigrationTesterService(dbContext, databaseType, migrationName);
|
|
});
|
|
}
|
|
|
|
public override ValueTask<IReadOnlyCollection<ITheoryDataRow>> GetData(MethodInfo testMethod, DisposalTracker disposalTracker)
|
|
{
|
|
var config = GetConfiguration();
|
|
|
|
HashSet<SupportedDatabaseProviders> unconfiguredDatabases =
|
|
[
|
|
SupportedDatabaseProviders.MySql,
|
|
SupportedDatabaseProviders.Postgres,
|
|
SupportedDatabaseProviders.Sqlite,
|
|
SupportedDatabaseProviders.SqlServer
|
|
];
|
|
|
|
var theories = new List<ITheoryDataRow>();
|
|
|
|
foreach (var database in config.GetDatabases())
|
|
{
|
|
unconfiguredDatabases.Remove(database.Type);
|
|
|
|
if (!database.Enabled)
|
|
{
|
|
var theory = new TheoryDataRow()
|
|
.WithSkip("Not-Enabled")
|
|
.WithTrait("Database", database.Type.ToString());
|
|
theory.Label = database.Type.ToString();
|
|
theories.Add(theory);
|
|
continue;
|
|
}
|
|
|
|
var services = new ServiceCollection();
|
|
AddCommonServices(services);
|
|
|
|
if (database.Type == SupportedDatabaseProviders.SqlServer && !database.UseEf)
|
|
{
|
|
// Dapper services
|
|
AddDapperServices(services, database);
|
|
}
|
|
else
|
|
{
|
|
// Ef services
|
|
AddEfServices(services, database);
|
|
}
|
|
|
|
var serviceProvider = services.BuildServiceProvider();
|
|
disposalTracker.Add(serviceProvider);
|
|
|
|
var serviceTheory = new ServiceBasedTheoryDataRow(serviceProvider, testMethod)
|
|
.WithTrait("Database", database.Type.ToString())
|
|
.WithTrait("ConnectionString", database.ConnectionString);
|
|
|
|
serviceTheory.Label = database.Type.ToString();
|
|
theories.Add(serviceTheory);
|
|
}
|
|
|
|
foreach (var unconfiguredDatabase in unconfiguredDatabases)
|
|
{
|
|
var theory = new TheoryDataRow()
|
|
.WithSkip("Unconfigured")
|
|
.WithTrait("Database", unconfiguredDatabase.ToString());
|
|
theory.Label = unconfiguredDatabase.ToString();
|
|
theories.Add(theory);
|
|
}
|
|
|
|
return new(theories);
|
|
}
|
|
|
|
private void AddCommonServices(IServiceCollection services)
|
|
{
|
|
// Common services
|
|
services.AddDataProtection();
|
|
services.AddLogging(logging =>
|
|
{
|
|
logging.AddProvider(new XUnitLoggerProvider());
|
|
});
|
|
if (UseFakeTimeProvider)
|
|
{
|
|
services.AddSingleton<TimeProvider, FakeTimeProvider>();
|
|
}
|
|
}
|
|
|
|
private void AddDapperServices(IServiceCollection services, Database database)
|
|
{
|
|
services.AddDapperRepositories(SelfHosted);
|
|
var globalSettings = new GlobalSettings
|
|
{
|
|
DatabaseProvider = "sqlServer",
|
|
SqlServer = new GlobalSettings.SqlSettings
|
|
{
|
|
ConnectionString = database.ConnectionString,
|
|
},
|
|
PasswordlessAuth = new GlobalSettings.PasswordlessAuthSettings
|
|
{
|
|
UserRequestExpiration = TimeSpan.FromMinutes(15),
|
|
}
|
|
};
|
|
services.AddSingleton(globalSettings);
|
|
services.AddSingleton<IGlobalSettings>(globalSettings);
|
|
services.AddSingleton(database);
|
|
services.AddDistributedSqlServerCache(o =>
|
|
{
|
|
o.ConnectionString = database.ConnectionString;
|
|
o.SchemaName = "dbo";
|
|
o.TableName = "Cache";
|
|
});
|
|
|
|
if (!string.IsNullOrEmpty(MigrationName))
|
|
{
|
|
AddSqlMigrationTester(services, database.ConnectionString, MigrationName);
|
|
}
|
|
}
|
|
|
|
private void AddEfServices(IServiceCollection services, Database database)
|
|
{
|
|
services.SetupEntityFramework(database.ConnectionString, database.Type);
|
|
services.AddPasswordManagerEFRepositories(SelfHosted);
|
|
|
|
var globalSettings = new GlobalSettings
|
|
{
|
|
PasswordlessAuth = new GlobalSettings.PasswordlessAuthSettings
|
|
{
|
|
UserRequestExpiration = TimeSpan.FromMinutes(15),
|
|
},
|
|
};
|
|
services.AddSingleton(globalSettings);
|
|
services.AddSingleton<IGlobalSettings>(globalSettings);
|
|
|
|
services.AddSingleton(database);
|
|
services.AddSingleton<IDistributedCache, EntityFrameworkCache>();
|
|
|
|
if (!string.IsNullOrEmpty(MigrationName))
|
|
{
|
|
AddEfMigrationTester(services, database.Type, MigrationName);
|
|
}
|
|
}
|
|
|
|
public override bool SupportsDiscoveryEnumeration()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
private class ServiceBasedTheoryDataRow : TheoryDataRowBase
|
|
{
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly MethodInfo _testMethod;
|
|
|
|
public ServiceBasedTheoryDataRow(IServiceProvider serviceProvider, MethodInfo testMethod)
|
|
{
|
|
_serviceProvider = serviceProvider;
|
|
_testMethod = testMethod;
|
|
}
|
|
|
|
protected override object?[] GetData()
|
|
{
|
|
var parameters = _testMethod.GetParameters();
|
|
|
|
var services = new object?[parameters.Length];
|
|
|
|
for (var i = 0; i < parameters.Length; i++)
|
|
{
|
|
var parameter = parameters[i];
|
|
// TODO: Could support keyed services/optional/nullable
|
|
services[i] = _serviceProvider.GetRequiredService(parameter.ParameterType);
|
|
}
|
|
|
|
return services;
|
|
}
|
|
}
|
|
}
|