Files
ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.SiteEventLogging.Tests/SqliteCapabilityTests.cs
T
Joseph Doherty 513fa1aa16 docs(tests): fix CommentChecker findings across tests/ — 13,392 → 0 (repo-wide scan clean)
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.
2026-10-07 15:05:49 -04:00

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));
}
}