-
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathRegressionTestHelper.cs
More file actions
96 lines (83 loc) · 3.97 KB
/
Copy pathRegressionTestHelper.cs
File metadata and controls
96 lines (83 loc) · 3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System.Runtime.CompilerServices;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace LcmCrdt.Tests.Data;
public class RegressionTestHelper(string projectName) : IAsyncLifetime
{
private IHost _host = null!;
private AsyncServiceScope _asyncScope;
//unique db path per instance, so CurrentProjectService doesn't think a db has already run migrations
private readonly CrdtProject _crdtProject = new(projectName, $"{projectName}-{Guid.NewGuid():N}.sqlite");
public IServiceProvider Services => _asyncScope.ServiceProvider;
private async Task InitDbFromScripts(RegressionVersion version)
{
var initialSqlFile = GetFilePath($"Scripts/{version}.sql");
var projectsService = _asyncScope.ServiceProvider.GetRequiredService<CurrentProjectService>();
projectsService.SetupProjectContextForNewDb(_crdtProject);
await using var lcmCrdtDbContext = await _asyncScope.ServiceProvider.GetRequiredService<IDbContextFactory<LcmCrdtDbContext>>().CreateDbContextAsync();
var sql = await File.ReadAllTextAsync(initialSqlFile);
var dbConnection = lcmCrdtDbContext.Database.GetDbConnection();
await dbConnection.OpenAsync();
var dbCommand = dbConnection.CreateCommand();
// Make virtual tables immediately useable (included here so we don't have to update future sql dumps)
// see: https://sqlite.org/forum/info/b68bc59ddd4aeca38d44823611fa931a671158403e4af522105bf2ba21a96327
var resetSchema = "PRAGMA writable_schema=RESET;";
dbCommand.CommandText = $"{sql}\n{resetSchema}";
await dbCommand.ExecuteNonQueryAsync();
//need to close the connection, otherwise the collations won't get created, they would normally be created on open or save, so we're closing so they get created when EF opens the connection.
await dbConnection.CloseAsync();
await lcmCrdtDbContext.Database.MigrateAsync();
await projectsService.RefreshProjectData();
}
public Task InitializeAsync()
{
return InitializeAsync(RegressionVersion.v2);
}
public async Task InitializeAsync(RegressionVersion version, bool withDataMigrations = false)
{
var builder = Host.CreateEmptyApplicationBuilder(null);
builder.Services.AddTestLcmCrdtClient();
_host = builder.Build();
var services = _host.Services;
_asyncScope = services.CreateAsyncScope();
await InitDbFromScripts(version);
// Data migrations are already on their way out. It doesn't really make sense for all tests to run them,
// which would change a bunch of verified project snapshots.
// When data migrations are removed (#2350), we should run this code unconditionally
// at the end of InitDbFromScripts (instead of the current db-migration and refresh-project-data approach)
// Because that's closer to the prod code.
if (withDataMigrations)
{
await Services.GetRequiredService<CurrentProjectService>().SetupProjectContext(_crdtProject);
}
}
public async Task DisposeAsync()
{
await _asyncScope.DisposeAsync();
if (_host is IAsyncDisposable asyncDisposable) await asyncDisposable.DisposeAsync();
else
{
_host.Dispose();
}
if (File.Exists(_crdtProject.DbPath))
{
using var connection = new SqliteConnection($"Data Source={_crdtProject.DbPath}");
SqliteConnection.ClearPool(connection);
File.Delete(_crdtProject.DbPath);
}
}
private static string GetFilePath(string name, [CallerFilePath] string sourceFile = "")
{
return Path.Combine(
Path.GetDirectoryName(sourceFile) ??
throw new InvalidOperationException("Could not get directory of source file"),
name);
}
public enum RegressionVersion
{
v1,
v2,
}
}