513fa1aa16
Comment/XML-doc changes only: - add summaries to ~10k test methods, fixtures, fakes and helpers (+ <param> on theories, <returns> on async Task methods, <inheritdoc/> on interface implementations the checker can resolve) - strip ~2.6k project-tracking references (WP*, P*-*, row-NN, Task N, #NN, Component-0NN) from comments, keeping the explanatory text; reword false positives in comments only - real docs on fakes implementing BCL/library interfaces (IDisposable, ILogger, IOptionsMonitor, IAsyncLifetime) - reword the last 5 src/ false positives (CWE-1236, failures-1, year-0001, M365) Only non-comment edits: four one-line nested classes split across lines so members can carry docs. Build 0 errors / 0 warnings.
87 lines
3.8 KiB
C#
87 lines
3.8 KiB
C#
using Microsoft.Data.Sqlite;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.SiteEventLogging.Tests;
|
|
|
|
/// <summary>
|
|
/// Pins the two SQLite provider capabilities the storage cap's size model depends on
|
|
/// (register row 81, <c>docs/plans/2026-08-17-site-event-log-cap-semantics-decision.md</c>).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The intended fix for row 81 was to measure <c>site_events</c>' own pages exactly through the
|
|
/// <c>dbstat</c> virtual table. These tests are the evidence that this is not possible with the
|
|
/// native SQLite this solution ships, and the tripwire that will tell us if that ever changes —
|
|
/// if <c>dbstat</c> appears, the modelled estimate in
|
|
/// <see cref="EventLogPurgeService.EstimateSiteEventsSize"/> should be replaced by a real
|
|
/// measurement.
|
|
/// </remarks>
|
|
public class SqliteCapabilityTests
|
|
{
|
|
private static SqliteConnection OpenMemory()
|
|
{
|
|
var connection = new SqliteConnection("Data Source=:memory:");
|
|
connection.Open();
|
|
return connection;
|
|
}
|
|
|
|
/// <summary>Verifies that the bundled SQLite build has no dbstat table, so the per-table page count has to be modelled.</summary>
|
|
[Fact]
|
|
public void DbStat_IsNotAvailable_SoThePerTablePageCountMustBeModelled()
|
|
{
|
|
// If this test starts FAILING, that is good news, not a regression: the bundled
|
|
// e_sqlite3 has gained SQLITE_ENABLE_DBSTAT_VTAB and the cap can measure
|
|
// `SELECT sum(pgsize) FROM dbstat WHERE name='site_events'` exactly instead of
|
|
// modelling it. Delete the model, not this expectation, if that day comes.
|
|
using var connection = OpenMemory();
|
|
|
|
using var compileOptions = connection.CreateCommand();
|
|
compileOptions.CommandText = "PRAGMA compile_options";
|
|
var options = new List<string>();
|
|
using (var reader = compileOptions.ExecuteReader())
|
|
{
|
|
while (reader.Read())
|
|
options.Add(reader.GetString(0));
|
|
}
|
|
|
|
Assert.DoesNotContain("ENABLE_DBSTAT_VTAB", options);
|
|
|
|
using var modules = connection.CreateCommand();
|
|
modules.CommandText = "SELECT name FROM pragma_module_list";
|
|
var names = new List<string>();
|
|
using (var reader = modules.ExecuteReader())
|
|
{
|
|
while (reader.Read())
|
|
names.Add(reader.GetString(0));
|
|
}
|
|
|
|
// The list is non-empty (fts3/4/5, rtree, geopoly …) so an empty result is not being
|
|
// mistaken for "no dbstat".
|
|
Assert.NotEmpty(names);
|
|
Assert.DoesNotContain("dbstat", names);
|
|
Assert.DoesNotContain("sqlite_dbpage", names);
|
|
|
|
using var query = connection.CreateCommand();
|
|
query.CommandText = "SELECT sum(pgsize) FROM dbstat";
|
|
var ex = Assert.Throws<SqliteException>(() => query.ExecuteScalar());
|
|
Assert.Contains("dbstat", ex.Message, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
/// <summary>Verifies that octet_length is available, so row width is sampled in bytes rather than characters.</summary>
|
|
[Fact]
|
|
public void OctetLength_IsAvailable_SoRowWidthIsSampledInBytesNotCharacters()
|
|
{
|
|
// The size model samples row width with octet_length() (SQLite 3.43+). length() counts
|
|
// CHARACTERS, so a multi-byte UTF-8 message would be under-sized and the cap enforced
|
|
// late. A provider downgrade that drops octet_length must fail here rather than
|
|
// silently shrinking every estimate at runtime.
|
|
using var connection = OpenMemory();
|
|
|
|
using var cmd = connection.CreateCommand();
|
|
cmd.CommandText = "SELECT octet_length('skål'), length('skål')";
|
|
using var reader = cmd.ExecuteReader();
|
|
|
|
Assert.True(reader.Read());
|
|
Assert.Equal(5, reader.GetInt32(0)); // 'å' is two bytes in UTF-8
|
|
Assert.Equal(4, reader.GetInt32(1));
|
|
}
|
|
}
|