Build and publish packages and Docker images / Test, build and publish (push) Successful in 43m50s
93 lines
4.4 KiB
C#
93 lines
4.4 KiB
C#
using Eis.Infrastructure.Authentication;
|
|
using Eis.Infrastructure.Data;
|
|
using Microsoft.Data.Sqlite;
|
|
|
|
namespace Eis.Infrastructure.Tests.Data;
|
|
|
|
public sealed class DatabaseInitializerTests
|
|
{
|
|
[Fact]
|
|
public async Task EmbeddedSchemas_AreNativeSqlResources()
|
|
{
|
|
var assembly = typeof(DatabaseInitializer).Assembly;
|
|
var resourceNames = assembly.GetManifestResourceNames();
|
|
var sqliteName = Assert.Single(resourceNames, name => name.EndsWith("Schema.sqlite.sql", StringComparison.Ordinal));
|
|
var mysqlName = Assert.Single(resourceNames, name => name.EndsWith("Schema.mysql.sql", StringComparison.Ordinal));
|
|
|
|
var sqlite = await ReadResourceAsync(assembly, sqliteName);
|
|
var mysql = (await ReadResourceAsync(assembly, mysqlName)).ReplaceLineEndings("\n");
|
|
var mysqlStatements = mysql.Split(
|
|
"\n-- EIS-STATEMENT\n",
|
|
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
|
|
|
Assert.Contains("CREATE TABLE IF NOT EXISTS schema_metadata", sqlite, StringComparison.Ordinal);
|
|
Assert.DoesNotContain("export const", sqlite, StringComparison.Ordinal);
|
|
Assert.True(mysqlStatements.Length >= 30);
|
|
Assert.All(mysqlStatements, statement =>
|
|
Assert.StartsWith("CREATE TABLE IF NOT EXISTS", statement, StringComparison.Ordinal));
|
|
Assert.Contains("`separator` VARCHAR(10)", mysql, StringComparison.Ordinal);
|
|
Assert.DoesNotContain("export const", mysql, StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task InitializeAsync_CreatesFreshDatabaseAndIsIdempotent()
|
|
{
|
|
var root = Path.Combine(Path.GetTempPath(), $"eis-fresh-init-{Guid.NewGuid():N}");
|
|
var path = Path.Combine(root, "eis.sqlite");
|
|
Directory.CreateDirectory(root);
|
|
try
|
|
{
|
|
var options = DatabaseOptions.CreateSqliteForTests(path);
|
|
var factory = new RelationalConnectionFactory(options);
|
|
var passwords = new PasswordCompatibilityService();
|
|
var initializer = new DatabaseInitializer(factory, options, passwords);
|
|
|
|
await initializer.InitializeAsync(CancellationToken.None);
|
|
await initializer.InitializeAsync(CancellationToken.None);
|
|
|
|
await using var connection = new SqliteConnection($"Data Source={path}");
|
|
await connection.OpenAsync();
|
|
Assert.True(await ScalarAsync(connection,
|
|
"SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'") >= 32);
|
|
Assert.Equal(20, await ScalarAsync(connection,
|
|
"SELECT schema_version FROM schema_metadata WHERE id = 1"));
|
|
Assert.Equal(1, await ScalarAsync(connection,
|
|
"SELECT COUNT(*) FROM users WHERE id = 'usr_admin' AND role = 'admin' AND admin_level = 'super'"));
|
|
Assert.Equal("-", await ScalarTextAsync(connection,
|
|
"SELECT `separator` FROM number_rules WHERE id = 'rule_default'"));
|
|
Assert.Equal(5, await ScalarAsync(connection,
|
|
"SELECT COUNT(*) FROM workflow_definitions WHERE active = 1"));
|
|
Assert.Equal(4, await ScalarAsync(connection,
|
|
"SELECT COUNT(*) FROM admission_number_rules WHERE active = 1"));
|
|
await connection.DisposeAsync();
|
|
SqliteConnection.ClearAllPools();
|
|
}
|
|
finally
|
|
{
|
|
if (Directory.Exists(root)) Directory.Delete(root, recursive: true);
|
|
}
|
|
}
|
|
|
|
private static async Task<long> ScalarAsync(SqliteConnection connection, string sql)
|
|
{
|
|
await using var command = connection.CreateCommand();
|
|
command.CommandText = sql;
|
|
return Convert.ToInt64(await command.ExecuteScalarAsync());
|
|
}
|
|
|
|
private static async Task<string> ScalarTextAsync(SqliteConnection connection, string sql)
|
|
{
|
|
await using var command = connection.CreateCommand();
|
|
command.CommandText = sql;
|
|
return Convert.ToString(await command.ExecuteScalarAsync()) ?? "";
|
|
}
|
|
|
|
private static async Task<string> ReadResourceAsync(System.Reflection.Assembly assembly, string name)
|
|
{
|
|
await using var stream = assembly.GetManifestResourceStream(name)
|
|
?? throw new InvalidOperationException($"Missing resource: {name}");
|
|
using var reader = new StreamReader(stream);
|
|
return await reader.ReadToEndAsync();
|
|
}
|
|
}
|