mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-10-28 02:38:55 -04:00
Add a shared SQLite test database helper (#754)
This commit is contained in:
1 parent
47bd8b0e50
commit
caebcf550d
3 files changed
+72
-32
No files matched your search
@@ -2,6 +2,7 @@ using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
using Cleanuparr.Domain.Enums;
|
||||
using Cleanuparr.Infrastructure.Tests.TestHelpers;
|
||||
using Cleanuparr.Persistence;
|
||||
using Cleanuparr.Persistence.Models.Configuration.Arr;
|
||||
using Cleanuparr.Persistence.Models.Configuration.BlacklistSync;
|
||||
@@ -43,11 +44,11 @@ public class SeedParityTests
|
||||
throw new SkipException($"Docker is unavailable, skipping seed parity test: {exception.Message}");
|
||||
}
|
||||
|
||||
string sqlitePath = Path.Combine(Path.GetTempPath(), $"cleanuparr-seed-parity-{Guid.NewGuid():N}.db");
|
||||
using SqliteTestDatabase sqlite = SqliteTestDatabase.Create("seed-parity");
|
||||
|
||||
try
|
||||
{
|
||||
SeedSnapshot sqliteSnapshot = await LoadSqliteSeedAsync(sqlitePath);
|
||||
SeedSnapshot sqliteSnapshot = await LoadSqliteSeedAsync(sqlite);
|
||||
SeedSnapshot postgresSnapshot = await LoadPostgresSeedAsync(postgresContainer);
|
||||
|
||||
AssertSingletonMatches("general_configs", sqliteSnapshot.GeneralConfig, postgresSnapshot.GeneralConfig);
|
||||
@@ -62,23 +63,12 @@ public class SeedParityTests
|
||||
finally
|
||||
{
|
||||
await postgresContainer.DisposeAsync();
|
||||
|
||||
if (File.Exists(sqlitePath))
|
||||
{
|
||||
File.Delete(sqlitePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<SeedSnapshot> LoadSqliteSeedAsync(string sqlitePath)
|
||||
private static async Task<SeedSnapshot> LoadSqliteSeedAsync(SqliteTestDatabase sqlite)
|
||||
{
|
||||
DbContextOptionsBuilder<DataContext> optionsBuilder = new();
|
||||
optionsBuilder
|
||||
.UseSqlite($"Data Source={sqlitePath}", options => options.MigrationsAssembly("Cleanuparr.Persistence.Sqlite"))
|
||||
.UseLowerCaseNamingConvention()
|
||||
.UseSnakeCaseNamingConvention();
|
||||
|
||||
await using DataContext context = new(optionsBuilder.Options, new SqliteDatabaseProvider());
|
||||
await using DataContext context = sqlite.CreateContext<DataContext>();
|
||||
await context.Database.MigrateAsync();
|
||||
|
||||
return await LoadSnapshotAsync(context);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Cleanuparr.Domain.Enums;
|
||||
using Cleanuparr.Infrastructure.Tests.TestHelpers;
|
||||
using Cleanuparr.Persistence;
|
||||
using Cleanuparr.Persistence.Models.Events;
|
||||
using Cleanuparr.Persistence.Providers;
|
||||
@@ -42,11 +43,11 @@ public class TimelineParityTests
|
||||
throw new SkipException($"Docker is unavailable, skipping timeline parity test: {exception.Message}");
|
||||
}
|
||||
|
||||
string sqlitePath = Path.Combine(Path.GetTempPath(), $"cleanuparr-timeline-parity-{Guid.NewGuid():N}.db");
|
||||
using SqliteTestDatabase sqlite = SqliteTestDatabase.Create("timeline-parity");
|
||||
|
||||
try
|
||||
{
|
||||
List<string> sqliteLabels = await BucketLabelsSqliteAsync(sqlitePath, size);
|
||||
List<string> sqliteLabels = await BucketLabelsSqliteAsync(sqlite, size);
|
||||
List<string> postgresLabels = await BucketLabelsPostgresAsync(postgresContainer, size);
|
||||
|
||||
postgresLabels.ShouldBe(sqliteLabels);
|
||||
@@ -54,28 +55,17 @@ public class TimelineParityTests
|
||||
finally
|
||||
{
|
||||
await postgresContainer.DisposeAsync();
|
||||
|
||||
if (File.Exists(sqlitePath))
|
||||
{
|
||||
File.Delete(sqlitePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<List<string>> BucketLabelsSqliteAsync(string sqlitePath, TimelineBucketSize size)
|
||||
private static async Task<List<string>> BucketLabelsSqliteAsync(
|
||||
SqliteTestDatabase sqlite, TimelineBucketSize size)
|
||||
{
|
||||
SqliteDatabaseProvider provider = new();
|
||||
DbContextOptionsBuilder<EventsContext> builder = new();
|
||||
builder
|
||||
.UseSqlite($"Data Source={sqlitePath}", options => options.MigrationsAssembly("Cleanuparr.Persistence.Sqlite"))
|
||||
.UseLowerCaseNamingConvention()
|
||||
.UseSnakeCaseNamingConvention();
|
||||
|
||||
await using EventsContext context = new(builder.Options, provider);
|
||||
await using EventsContext context = sqlite.CreateContext<EventsContext>();
|
||||
await context.Database.MigrateAsync();
|
||||
await SeedAsync(context);
|
||||
|
||||
return await BucketLabelsAsync(context, provider, size);
|
||||
return await BucketLabelsAsync(context, sqlite.Provider, size);
|
||||
}
|
||||
|
||||
private static async Task<List<string>> BucketLabelsPostgresAsync(PostgreSqlContainer container, TimelineBucketSize size)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
using Cleanuparr.Persistence.Providers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Tests.TestHelpers;
|
||||
|
||||
/// <summary>
|
||||
/// A throwaway file-backed SQLite database, wired the way the app wires one.
|
||||
/// Dispose deletes the file and its journals.
|
||||
/// </summary>
|
||||
public sealed class SqliteTestDatabase : IDisposable
|
||||
{
|
||||
private readonly string _path;
|
||||
|
||||
private SqliteTestDatabase(string path)
|
||||
{
|
||||
_path = path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The provider the contexts were built with.
|
||||
/// </summary>
|
||||
public SqliteDatabaseProvider Provider { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Names the temp file after the caller.
|
||||
/// </summary>
|
||||
public static SqliteTestDatabase Create(string name) =>
|
||||
new(Path.Combine(Path.GetTempPath(), $"cleanuparr-{name}-{Guid.NewGuid():N}.db"));
|
||||
|
||||
/// <summary>
|
||||
/// A context pointing at this database, unmigrated.
|
||||
/// </summary>
|
||||
public TContext CreateContext<TContext>()
|
||||
where TContext : DbContext
|
||||
{
|
||||
DbContextOptionsBuilder<TContext> optionsBuilder = new();
|
||||
optionsBuilder
|
||||
.UseSqlite(
|
||||
$"Data Source={_path}",
|
||||
options => options.MigrationsAssembly("Cleanuparr.Persistence.Sqlite"))
|
||||
.UseLowerCaseNamingConvention()
|
||||
.UseSnakeCaseNamingConvention();
|
||||
|
||||
return (TContext)Activator.CreateInstance(
|
||||
typeof(TContext),
|
||||
optionsBuilder.Options,
|
||||
Provider)!;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (string file in new[] { _path, $"{_path}-wal", $"{_path}-shm" })
|
||||
{
|
||||
if (File.Exists(file))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user