feat(localdb): lib-owned schema (meta/oplog/peer_state/row_version/applying/dead_letter)
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using ZB.MOM.WW.LocalDb.Internal;
|
||||
|
||||
namespace ZB.MOM.WW.LocalDb.Tests;
|
||||
|
||||
public sealed class LocalDbSchemaTests : IDisposable
|
||||
{
|
||||
private readonly string _path = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".db");
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
SqliteConnection.ClearAllPools();
|
||||
if (File.Exists(_path))
|
||||
File.Delete(_path);
|
||||
}
|
||||
|
||||
private SqliteConnection Open()
|
||||
{
|
||||
var conn = new SqliteConnection($"Data Source={_path}");
|
||||
conn.Open();
|
||||
return conn;
|
||||
}
|
||||
|
||||
private static long ScalarLong(SqliteConnection conn, string sql)
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = sql;
|
||||
return Convert.ToInt64(cmd.ExecuteScalar());
|
||||
}
|
||||
|
||||
private static string ScalarString(SqliteConnection conn, string sql)
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = sql;
|
||||
return (string)cmd.ExecuteScalar()!;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureCreated_CreatesAllObjects()
|
||||
{
|
||||
using var conn = Open();
|
||||
LocalDbSchema.EnsureCreated(conn);
|
||||
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "SELECT name FROM sqlite_master WHERE type='table'";
|
||||
var tables = new List<string>();
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
while (reader.Read())
|
||||
tables.Add(reader.GetString(0));
|
||||
|
||||
foreach (var expected in new[]
|
||||
{
|
||||
"__localdb_meta", "__localdb_oplog", "__localdb_peer_state",
|
||||
"__localdb_row_version", "__localdb_applying", "__localdb_dead_letter"
|
||||
})
|
||||
Assert.Contains(expected, tables);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureCreated_IsIdempotent()
|
||||
{
|
||||
using var conn = Open();
|
||||
LocalDbSchema.EnsureCreated(conn);
|
||||
LocalDbSchema.EnsureCreated(conn);
|
||||
|
||||
Assert.Equal(1, ScalarLong(conn, "SELECT COUNT(*) FROM __localdb_meta"));
|
||||
Assert.Equal(1, ScalarLong(conn, "SELECT COUNT(*) FROM __localdb_applying"));
|
||||
Assert.Equal(1, ScalarLong(conn, "SELECT COUNT(*) FROM __localdb_peer_state"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Meta_NodeId_MintedOnceAndStable()
|
||||
{
|
||||
string first;
|
||||
using (var conn = Open())
|
||||
{
|
||||
LocalDbSchema.EnsureCreated(conn);
|
||||
first = ScalarString(conn, "SELECT node_id FROM __localdb_meta WHERE id=1");
|
||||
}
|
||||
|
||||
using (var conn = Open())
|
||||
{
|
||||
LocalDbSchema.EnsureCreated(conn);
|
||||
var second = ScalarString(conn, "SELECT node_id FROM __localdb_meta WHERE id=1");
|
||||
Assert.Equal(first, second);
|
||||
}
|
||||
|
||||
Assert.True(Guid.TryParse(first, out _));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Applying_SeededWithZeroRow()
|
||||
{
|
||||
using var conn = Open();
|
||||
LocalDbSchema.EnsureCreated(conn);
|
||||
|
||||
Assert.Equal(0, ScalarLong(conn, "SELECT applying FROM __localdb_applying WHERE id=1"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadMeta_ReturnsNodeIdAndHighWater()
|
||||
{
|
||||
using var conn = Open();
|
||||
LocalDbSchema.EnsureCreated(conn);
|
||||
|
||||
var (nodeId, highWater) = LocalDbSchema.ReadMeta(conn);
|
||||
|
||||
Assert.True(Guid.TryParse(nodeId, out _));
|
||||
Assert.Equal(0, highWater);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FlushHlcHighWater_RoundTrips()
|
||||
{
|
||||
using var conn = Open();
|
||||
LocalDbSchema.EnsureCreated(conn);
|
||||
|
||||
LocalDbSchema.FlushHlcHighWater(conn, 123_456_789L);
|
||||
|
||||
var (_, highWater) = LocalDbSchema.ReadMeta(conn);
|
||||
Assert.Equal(123_456_789L, highWater);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user