using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ZB.MOM.WW.LocalDb;
namespace ZB.MOM.WW.ScadaBridge.TestSupport;
///
/// A real over a temp file, for tests that construct a
/// LocalDb-backed store directly.
///
///
///
/// The stores take rather than a connection string, and there is
/// no in-memory mode — LocalDbOptions.Path is a filesystem path. A real one is
/// used rather than a stub on purpose: connections handed out by ILocalDb carry
/// the zb_hlc_next() UDF that the capture triggers call, so a stub returning a
/// bare SqliteConnection would pass these tests while failing closed the moment
/// the table is registered for replication.
///
///
/// No onReady callback and no RegisterReplicated: each store's own schema
/// initialization creates its table, which is what keeps a directly-constructed store
/// self-sufficient. Registration is the host's job (SiteLocalDbSetup.OnReady).
///
///
/// This lives in a shared support project rather than being copied per test project:
/// seven test projects construct stores that now take , and
/// duplicating the fixture would mean seven places to keep the WAL-sidecar cleanup and
/// the "real, not stubbed" rationale correct.
///
///
public sealed class TestLocalDb : IDisposable
{
private readonly ServiceProvider _provider;
private TestLocalDb(ServiceProvider provider, ILocalDb db)
{
_provider = provider;
Db = db;
}
/// The live local database.
public ILocalDb Db { get; }
/// Opens a local database at .
public static TestLocalDb Create(string databasePath)
{
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary
{
["LocalDb:Path"] = databasePath,
})
.Build();
var provider = new ServiceCollection()
.AddZbLocalDb(configuration)
.BuildServiceProvider();
return new TestLocalDb(provider, provider.GetRequiredService());
}
///
/// Creates a local database at a fresh temp path. Dispose the instance, then call
/// with to clean up.
///
public static TestLocalDb CreateTemp(string prefix = "localdb")
{
var path = System.IO.Path.Combine(
System.IO.Path.GetTempPath(), $"{prefix}-{Guid.NewGuid():N}.db");
var db = Create(path);
db.Path = path;
return db;
}
/// The filesystem path, when created via .
public string Path { get; private set; } = string.Empty;
///
/// Deletes and its WAL sidecars. Call only after the
/// owning is disposed — the master connection anchors the WAL.
///
public static void DeleteFiles(string databasePath)
{
foreach (var suffix in new[] { "", "-wal", "-shm" })
{
try { File.Delete(databasePath + suffix); } catch { /* best effort */ }
}
}
public void Dispose() => _provider.Dispose();
}