using System.Data.Common; using Microsoft.EntityFrameworkCore; namespace MeterVault.Integration.Tests; [Collection("Timescale")] public sealed class SchemaTests(TimescaleFixture fx) { [Fact] public async Task Migrations_are_applied() { await using var ctx = fx.CreateContext(); var applied = (await ctx.Database.GetAppliedMigrationsAsync()).ToList(); Assert.Contains(applied, m => m.EndsWith("InitialSchema", StringComparison.Ordinal)); Assert.Contains(applied, m => m.EndsWith("TimescaleHypertables", StringComparison.Ordinal)); } [Fact] public async Task Reading_and_consumption_are_hypertables() { await using var ctx = fx.CreateContext(); var conn = ctx.Database.GetDbConnection(); await conn.OpenAsync(); var names = await QueryStringsAsync(conn, "SELECT hypertable_name FROM timescaledb_information.hypertables ORDER BY hypertable_name;"); Assert.Equal(["consumption", "reading"], names); } [Fact] public async Task Reading_has_a_compression_policy() { await using var ctx = fx.CreateContext(); var conn = ctx.Database.GetDbConnection(); await conn.OpenAsync(); // A compression/columnstore policy shows up as a scheduled job against the hypertable. var jobs = await QueryStringsAsync(conn, "SELECT hypertable_name FROM timescaledb_information.jobs " + "WHERE proc_name IN ('policy_compression', 'policy_columnstore') AND hypertable_name = 'reading';"); Assert.Contains("reading", jobs); } private static async Task> QueryStringsAsync(DbConnection conn, string sql) { await using var cmd = conn.CreateCommand(); cmd.CommandText = sql; var results = new List(); await using var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { results.Add(reader.GetString(0)); } return results; } }