2022-01-26 00:08:27 +00:00
|
|
|
using System;
|
2013-02-23 19:38:25 +00:00
|
|
|
using System.Collections.Generic;
|
2019-08-22 20:15:25 +00:00
|
|
|
using System.Data.SQLite;
|
2020-02-25 21:53:40 +00:00
|
|
|
using System.IO;
|
2013-02-04 00:10:15 +00:00
|
|
|
using System.Linq;
|
2019-10-28 21:12:26 +00:00
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
2022-01-26 00:08:27 +00:00
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
using Npgsql;
|
2013-02-04 00:10:15 +00:00
|
|
|
using NUnit.Framework;
|
2020-02-25 21:53:40 +00:00
|
|
|
using NzbDrone.Common.Extensions;
|
2022-01-26 00:08:27 +00:00
|
|
|
using NzbDrone.Core.Configuration;
|
2013-02-04 00:10:15 +00:00
|
|
|
using NzbDrone.Core.Datastore;
|
2013-03-25 06:13:53 +00:00
|
|
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
2022-01-26 00:08:27 +00:00
|
|
|
using NzbDrone.Test.Common.Datastore;
|
2013-09-11 06:33:47 +00:00
|
|
|
|
2013-02-04 00:10:15 +00:00
|
|
|
namespace NzbDrone.Core.Test.Framework
|
|
|
|
{
|
2013-03-24 04:16:00 +00:00
|
|
|
public abstract class DbTest<TSubject, TModel> : DbTest
|
2013-02-23 19:38:25 +00:00
|
|
|
where TSubject : class
|
2013-02-18 07:59:43 +00:00
|
|
|
where TModel : ModelBase, new()
|
|
|
|
{
|
2013-02-23 19:38:25 +00:00
|
|
|
private TSubject _subject;
|
2013-02-18 07:59:43 +00:00
|
|
|
|
|
|
|
protected BasicRepository<TModel> Storage { get; private set; }
|
|
|
|
|
2016-12-09 06:54:15 +00:00
|
|
|
protected IList<TModel> AllStoredModels => Storage.All().ToList();
|
2013-02-18 07:59:43 +00:00
|
|
|
|
2016-12-09 06:54:15 +00:00
|
|
|
protected TModel StoredModel => Storage.All().Single();
|
2013-02-16 03:50:22 +00:00
|
|
|
|
|
|
|
[SetUp]
|
|
|
|
public void CoreTestSetup()
|
|
|
|
{
|
|
|
|
_subject = null;
|
2013-02-23 19:38:25 +00:00
|
|
|
Storage = Mocker.Resolve<BasicRepository<TModel>>();
|
2013-02-16 03:50:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected TSubject Subject
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (_subject == null)
|
|
|
|
{
|
|
|
|
_subject = Mocker.Resolve<TSubject>();
|
|
|
|
}
|
|
|
|
|
|
|
|
return _subject;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-12 20:00:49 +00:00
|
|
|
[Category("DbTest")]
|
2013-03-24 04:16:00 +00:00
|
|
|
public abstract class DbTest : CoreTest
|
2013-02-04 00:10:15 +00:00
|
|
|
{
|
2013-03-25 03:51:32 +00:00
|
|
|
private ITestDatabase _db;
|
2022-01-26 00:08:27 +00:00
|
|
|
private DatabaseType _databaseType;
|
2013-03-27 04:03:02 +00:00
|
|
|
|
2016-12-09 06:54:15 +00:00
|
|
|
protected virtual MigrationType MigrationType => MigrationType.Main;
|
2013-03-27 04:03:02 +00:00
|
|
|
|
2013-03-25 03:51:32 +00:00
|
|
|
protected ITestDatabase Db
|
2013-02-04 00:10:15 +00:00
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (_db == null)
|
2020-01-03 12:49:24 +00:00
|
|
|
{
|
2013-02-04 00:10:15 +00:00
|
|
|
throw new InvalidOperationException("Test object database doesn't exists. Make sure you call WithRealDb() if you intend to use an actual database.");
|
2020-01-03 12:49:24 +00:00
|
|
|
}
|
2013-02-04 00:10:15 +00:00
|
|
|
|
|
|
|
return _db;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-13 21:23:37 +00:00
|
|
|
protected virtual ITestDatabase WithTestDb(MigrationContext migrationContext)
|
2014-12-02 20:08:37 +00:00
|
|
|
{
|
2020-02-25 21:53:40 +00:00
|
|
|
var database = CreateDatabase(migrationContext);
|
2014-12-02 20:08:37 +00:00
|
|
|
Mocker.SetConstant(database);
|
|
|
|
|
2015-05-03 23:30:16 +00:00
|
|
|
switch (MigrationType)
|
|
|
|
{
|
|
|
|
case MigrationType.Main:
|
|
|
|
{
|
|
|
|
var mainDb = new MainDatabase(database);
|
|
|
|
|
|
|
|
Mocker.SetConstant<IMainDatabase>(mainDb);
|
|
|
|
break;
|
|
|
|
}
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2015-05-03 23:30:16 +00:00
|
|
|
case MigrationType.Log:
|
|
|
|
{
|
|
|
|
var logDb = new LogDatabase(database);
|
|
|
|
|
|
|
|
Mocker.SetConstant<ILogDatabase>(logDb);
|
|
|
|
break;
|
|
|
|
}
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2015-05-03 23:30:16 +00:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
throw new ArgumentException("Invalid MigrationType");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-02 20:08:37 +00:00
|
|
|
var testDb = new TestDatabase(database);
|
|
|
|
|
|
|
|
return testDb;
|
|
|
|
}
|
|
|
|
|
2020-02-25 21:53:40 +00:00
|
|
|
private IDatabase CreateDatabase(MigrationContext migrationContext)
|
|
|
|
{
|
2022-01-26 00:08:27 +00:00
|
|
|
if (_databaseType == DatabaseType.PostgreSQL)
|
|
|
|
{
|
|
|
|
CreatePostgresDb();
|
|
|
|
}
|
|
|
|
|
2020-02-25 21:53:40 +00:00
|
|
|
var factory = Mocker.Resolve<DbFactory>();
|
|
|
|
|
|
|
|
// If a special migration test or log migration then create new
|
2022-01-26 00:08:27 +00:00
|
|
|
if (migrationContext.BeforeMigration != null || _databaseType == DatabaseType.PostgreSQL)
|
2020-02-25 21:53:40 +00:00
|
|
|
{
|
|
|
|
return factory.Create(migrationContext);
|
|
|
|
}
|
|
|
|
|
2022-01-26 00:08:27 +00:00
|
|
|
return CreateSqliteDatabase(factory, migrationContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void CreatePostgresDb()
|
|
|
|
{
|
|
|
|
var options = Mocker.Resolve<IOptions<PostgresOptions>>().Value;
|
|
|
|
PostgresDatabase.Create(options, MigrationType);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void DropPostgresDb()
|
|
|
|
{
|
|
|
|
var options = Mocker.Resolve<IOptions<PostgresOptions>>().Value;
|
|
|
|
PostgresDatabase.Drop(options, MigrationType);
|
|
|
|
}
|
|
|
|
|
|
|
|
private IDatabase CreateSqliteDatabase(IDbFactory factory, MigrationContext migrationContext)
|
|
|
|
{
|
2020-02-25 21:53:40 +00:00
|
|
|
// Otherwise try to use a cached migrated db
|
2022-01-26 00:08:27 +00:00
|
|
|
var cachedDb = SqliteDatabase.GetCachedDb(migrationContext.MigrationType);
|
|
|
|
var testDb = GetTestSqliteDb(migrationContext.MigrationType);
|
2020-02-25 21:53:40 +00:00
|
|
|
if (File.Exists(cachedDb))
|
|
|
|
{
|
|
|
|
TestLogger.Info($"Using cached initial database {cachedDb}");
|
|
|
|
File.Copy(cachedDb, testDb);
|
|
|
|
return factory.Create(migrationContext);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var db = factory.Create(migrationContext);
|
|
|
|
GC.Collect();
|
|
|
|
GC.WaitForPendingFinalizers();
|
|
|
|
SQLiteConnection.ClearAllPools();
|
|
|
|
|
|
|
|
TestLogger.Info("Caching database");
|
|
|
|
File.Copy(testDb, cachedDb);
|
|
|
|
return db;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-26 00:08:27 +00:00
|
|
|
private string GetTestSqliteDb(MigrationType type)
|
2020-02-25 21:53:40 +00:00
|
|
|
{
|
|
|
|
return type == MigrationType.Main ? TestFolderInfo.GetDatabase() : TestFolderInfo.GetLogDatabase();
|
|
|
|
}
|
|
|
|
|
2019-10-28 21:12:26 +00:00
|
|
|
protected virtual void SetupLogging()
|
|
|
|
{
|
|
|
|
Mocker.SetConstant<ILoggerProvider>(NullLoggerProvider.Instance);
|
|
|
|
}
|
|
|
|
|
2014-12-02 20:08:37 +00:00
|
|
|
protected void SetupContainer()
|
2013-02-04 00:10:15 +00:00
|
|
|
{
|
2013-06-28 01:03:04 +00:00
|
|
|
WithTempAsAppPath();
|
2019-10-28 21:12:26 +00:00
|
|
|
SetupLogging();
|
2013-03-25 03:51:32 +00:00
|
|
|
|
2022-01-26 00:08:27 +00:00
|
|
|
// populate the possible postgres options
|
|
|
|
var postgresOptions = PostgresDatabase.GetTestOptions();
|
|
|
|
_databaseType = postgresOptions.Host.IsNotNullOrWhiteSpace() ? DatabaseType.PostgreSQL : DatabaseType.SQLite;
|
|
|
|
|
|
|
|
// Set up remaining container services
|
|
|
|
Mocker.SetConstant(Options.Create(postgresOptions));
|
|
|
|
Mocker.SetConstant<IConfigFileProvider>(Mocker.Resolve<ConfigFileProvider>());
|
2013-07-05 03:56:27 +00:00
|
|
|
Mocker.SetConstant<IConnectionStringFactory>(Mocker.Resolve<ConnectionStringFactory>());
|
|
|
|
Mocker.SetConstant<IMigrationController>(Mocker.Resolve<MigrationController>());
|
|
|
|
|
2020-08-18 20:11:44 +00:00
|
|
|
SqlBuilderExtensions.LogSql = true;
|
2013-02-04 00:10:15 +00:00
|
|
|
}
|
|
|
|
|
2013-02-23 19:38:25 +00:00
|
|
|
[SetUp]
|
2014-12-02 20:08:37 +00:00
|
|
|
public virtual void SetupDb()
|
2013-02-23 19:38:25 +00:00
|
|
|
{
|
2014-12-02 20:08:37 +00:00
|
|
|
SetupContainer();
|
2016-02-13 21:23:37 +00:00
|
|
|
_db = WithTestDb(new MigrationContext(MigrationType));
|
2013-02-23 19:38:25 +00:00
|
|
|
}
|
|
|
|
|
2013-03-25 03:51:32 +00:00
|
|
|
[TearDown]
|
|
|
|
public void TearDown()
|
|
|
|
{
|
2019-08-22 20:15:25 +00:00
|
|
|
// Make sure there are no lingering connections. (When this happens it means we haven't disposed something properly)
|
|
|
|
GC.Collect();
|
|
|
|
GC.WaitForPendingFinalizers();
|
2022-01-26 00:08:27 +00:00
|
|
|
|
2019-08-22 20:15:25 +00:00
|
|
|
SQLiteConnection.ClearAllPools();
|
2022-01-26 00:08:27 +00:00
|
|
|
NpgsqlConnection.ClearAllPools();
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-08-22 20:15:25 +00:00
|
|
|
if (TestFolderInfo != null)
|
2013-03-25 03:51:32 +00:00
|
|
|
{
|
2019-08-22 20:15:25 +00:00
|
|
|
DeleteTempFolder(TestFolderInfo.AppDataFolder);
|
2013-03-25 03:51:32 +00:00
|
|
|
}
|
2022-01-26 00:08:27 +00:00
|
|
|
|
|
|
|
if (_databaseType == DatabaseType.PostgreSQL)
|
|
|
|
{
|
|
|
|
DropPostgresDb();
|
|
|
|
}
|
2013-03-25 03:51:32 +00:00
|
|
|
}
|
2013-03-24 04:16:00 +00:00
|
|
|
}
|
2019-10-28 21:12:26 +00:00
|
|
|
}
|