using System;
using System.Threading.Tasks;
using Kyoo.Postgresql;
using Kyoo.SqLite;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using Xunit;
namespace Kyoo.Tests
{
public sealed class SqLiteTestContext : TestContext
{
///
/// The internal sqlite connection used by all context returned by this class.
///
private readonly SqliteConnection _connection;
///
/// The context's options that specify to use an in memory Sqlite database.
///
private readonly DbContextOptions _context;
public SqLiteTestContext()
{
_connection = new SqliteConnection("DataSource=:memory:");
_connection.Open();
_context = new DbContextOptionsBuilder()
.UseSqlite(_connection)
.Options;
using DatabaseContext context = New();
context.Database.Migrate();
TestSample.FillDatabase(context);
}
public override void Dispose()
{
_connection.Close();
}
public override async ValueTask DisposeAsync()
{
await _connection.CloseAsync();
}
public override DatabaseContext New()
{
return new SqLiteContext(_context);
}
}
[CollectionDefinition(nameof(Postgresql))]
public class PostgresCollection : ICollectionFixture
{}
public sealed class PostgresFixture : IDisposable
{
private readonly DbContextOptions _options;
public string Template { get; }
public string Connection => PostgresTestContext.GetConnectionString(Template);
public PostgresFixture()
{
string id = Guid.NewGuid().ToString().Replace('-', '_');
Template = $"kyoo_template_{id}";
_options = new DbContextOptionsBuilder()
.UseNpgsql(Connection)
.Options;
using PostgresContext context = new(_options);
context.Database.Migrate();
using NpgsqlConnection conn = (NpgsqlConnection)context.Database.GetDbConnection();
conn.Open();
conn.ReloadTypes();
TestSample.FillDatabase(context);
}
public void Dispose()
{
using PostgresContext context = new(_options);
context.Database.EnsureDeleted();
}
}
public sealed class PostgresTestContext : TestContext
{
private readonly NpgsqlConnection _connection;
private readonly DbContextOptions _context;
public PostgresTestContext(PostgresFixture template)
{
string id = Guid.NewGuid().ToString().Replace('-', '_');
string database = $"kyoo_test_{id}";
using (NpgsqlConnection connection = new(template.Connection))
{
connection.Open();
using NpgsqlCommand cmd = new($"CREATE DATABASE {database} WITH TEMPLATE {template.Template}", connection);
cmd.ExecuteNonQuery();
}
_connection = new NpgsqlConnection(GetConnectionString(database));
_connection.Open();
_context = new DbContextOptionsBuilder()
.UseNpgsql(_connection)
.Options;
}
public static string GetConnectionString(string database)
{
return $"Server=127.0.0.1;Port=5432;Database={database};User ID=kyoo;Password=kyooPassword";
}
public override void Dispose()
{
using DatabaseContext db = New();
db.Database.EnsureDeleted();
_connection.Close();
}
public override async ValueTask DisposeAsync()
{
await using DatabaseContext db = New();
await db.Database.EnsureDeletedAsync();
await _connection.CloseAsync();
}
public override DatabaseContext New()
{
return new PostgresContext(_context);
}
}
///
/// Class responsible to fill and create in memory databases for unit tests.
///
public abstract class TestContext : IDisposable, IAsyncDisposable
{
///
/// Add an arbitrary data to the test context.
///
public void Add(T obj)
where T : class
{
using DatabaseContext context = New();
context.Set().Add(obj);
context.SaveChanges();
}
///
/// Add an arbitrary data to the test context.
///
public async Task AddAsync(T obj)
where T : class
{
await using DatabaseContext context = New();
await context.Set().AddAsync(obj);
await context.SaveChangesAsync();
}
///
/// Get a new database context connected to a in memory Sqlite database.
///
/// A valid DatabaseContext
public abstract DatabaseContext New();
public abstract void Dispose();
public abstract ValueTask DisposeAsync();
}
}