f2efeb37b7
Tasks 5 and 6 of the Phase 2 plan, committed together because their test
fallout is entangled — several fixtures construct both stores.
StoreAndForwardStorage and SiteStorageService now take ILocalDb. Connections
come from ILocalDb.CreateConnection(), which hands out an already-open,
pragma-configured connection carrying the zb_hlc_next() UDF the capture triggers
call; a raw connection would lack the UDF and every write to a replicated table
would fail closed. Deleted with the connection strings: S&F's
EnsureDatabaseDirectoryExists and its per-open busy_timeout pragma, and the site
service's BusyTimeoutFloorSeconds normalization — LocalDb owns all of it now.
DI: AddSiteRuntime's string overload is gone (nothing left to supply), so the
Host calls the no-arg form. ScadaBridge:Database:SiteDbPath and
StoreAndForwardOptions.SqliteDbPath survive only as the migrator's source
locations in Tasks 8/9.
Two things the plan did not anticipate, both worth reading:
1. FOUND A REAL LATENT DEFECT, from Phase 1, now fixed. The plan assumed
directory creation simply moved to LocalDb along with file ownership. It did
not: the LocalDb library never creates the parent directory, and
SqliteLocalDb opens the file eagerly in its constructor — so a missing
directory is a hard boot failure ("SQLite Error 14: unable to open database
file"), not a degraded start. The default site config points at the RELATIVE
path ./data/site-localdb.db, so any site node without a pre-existing data/
directory fails to boot. The docker rig escapes only because its volume mount
happens to create /app/data — a coincidence that would have hidden this until
a bare-metal or fresh deployment. This has been latent since Phase 1 made
LocalDb:Path required; deleting S&F's EnsureDatabaseDirectoryExists here
would have widened it. Re-established the guarantee at the layer that now
owns the path (SiteLocalDbDirectory.Ensure, called before AddZbLocalDb) and
pinned it with SiteLocalDbDirectoryTests. Non-vacuity is not assumed: two
tests written against the wrong assumption failed with exactly this
SQLite Error 14 before the fix existed.
2. Test fallout was ~7x the plan's estimate. The plan named "fixtures" in one
project; the constructor change actually reaches 40 files across 7 test
projects, and most used Mode=Memory;Cache=Shared — which LocalDb has no
equivalent for, so every one had to move to a real temp file. Rather than
copy the Phase 1 TestLocalDb fixture into 7 projects, added a shared
tests/ZB.MOM.WW.ScadaBridge.TestSupport library (not a test project) so the
WAL-sidecar cleanup and the "real, not stubbed" rationale live in one place.
Retargeted rather than deleted, in both directions: the S&F WAL test now asserts
against the LocalDb-backed store (WAL genuinely is LocalDb's job), while the
directory-creation test moved to Host.Tests (that guarantee is NOT LocalDb's).
SiteStorageServiceTests.Initialize_EnablesWalJournalMode got the same treatment.
DeploymentManagerMediumFindingsTests induced a persistence failure via an
unopenable path, which no longer reaches the assertion since the fixture now
throws first; it induces the same failure shape via an uninitialized store.
Verified: full solution build 0 warnings; SiteRuntime 532, Host 318,
AuditLog 355, ExternalSystemGateway 142, HealthMonitoring 97,
StoreAndForward 153 — 1597 passed, 0 failed.
Claude-Session: https://claude.ai/code/session_01BL2Vu1ESDQ9SCN4gVKkdts
89 lines
4.3 KiB
XML
89 lines
4.3 KiB
XML
<Project Sdk="Microsoft.NET.Sdk">
|
|
|
|
<PropertyGroup>
|
|
<TargetFramework>net10.0</TargetFramework>
|
|
<ImplicitUsings>enable</ImplicitUsings>
|
|
<Nullable>enable</Nullable>
|
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
|
<IsPackable>false</IsPackable>
|
|
</PropertyGroup>
|
|
|
|
<ItemGroup>
|
|
<PackageReference Include="Akka.TestKit.Xunit2" />
|
|
<PackageReference Include="coverlet.collector" />
|
|
<!--
|
|
Bundle D D2 needs Microsoft.Data.SqlClient for the MsSqlMigrationFixture
|
|
(mirroring ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests). Pinning 6.1.1 here for
|
|
the same reason: EF SqlServer 10.0.7 needs >= 6.1.1 but the central pin
|
|
is 6.0.2 (production ExternalSystemGateway). Override is test-only.
|
|
-->
|
|
<PackageReference Include="Microsoft.Data.SqlClient" VersionOverride="6.1.1" />
|
|
<PackageReference Include="Microsoft.Data.Sqlite" />
|
|
<!-- Security pin: GHSA-2m69-gcr7-jv3q. Microsoft.Data.Sqlite pulls the
|
|
vulnerable native 2.1.11; 2.1.12 patches it. Bumping Sqlite does not help. -->
|
|
<PackageReference Include="SQLitePCLRaw.lib.e_sqlite3" />
|
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
|
|
<!--
|
|
M4 Bundle E (Task E3): Microsoft.Extensions.Configuration.Json,
|
|
DependencyInjection, and Logging.Abstractions are now provided by the
|
|
Microsoft.AspNetCore.App framework reference below (pulled in for the
|
|
TestHost-based middleware E2E) so we drop them as explicit package
|
|
references to satisfy the warn-as-error pruning rule.
|
|
-->
|
|
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
|
<PackageReference Include="NSubstitute" />
|
|
<PackageReference Include="xunit" />
|
|
<PackageReference Include="xunit.runner.visualstudio" />
|
|
<!--
|
|
SkippableFact pattern (xunit 2.9.x has no native Assert.Skip) — used by
|
|
Bundle D D2 MSSQL-backed AuditLogIngestActor tests to report Skipped when
|
|
the dev MSSQL container is not reachable.
|
|
-->
|
|
<PackageReference Include="Xunit.SkippableFact" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<Using Include="Xunit" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<ProjectReference Include="../../src/ZB.MOM.WW.ScadaBridge.AuditLog/ZB.MOM.WW.ScadaBridge.AuditLog.csproj" />
|
|
<!--
|
|
D2: the AuditLogIngestActor tests use the real AuditLogRepository against
|
|
a per-test MSSQL database via MsSqlMigrationFixture. The fixture lives in
|
|
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests; we reference that test project so
|
|
the fixture + EF migrations come along without duplicating them.
|
|
-->
|
|
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.csproj" />
|
|
<!--
|
|
G2/G3/G4: the cached-call combined telemetry integration tests compose the
|
|
production OperationTrackingStore (site SQLite source of truth for
|
|
Tracking.Status) alongside the M2 audit writer chain, so the harness
|
|
needs a project reference to SiteRuntime where the store lives.
|
|
-->
|
|
<ProjectReference Include="../../src/ZB.MOM.WW.ScadaBridge.SiteRuntime/ZB.MOM.WW.ScadaBridge.SiteRuntime.csproj" />
|
|
<!--
|
|
M4 Bundle E (Task E2): the dispatcher audit-trail end-to-end test
|
|
constructs the production NotificationOutboxActor against the real
|
|
CentralAuditWriter so the Attempted/Delivered NotifyDeliver rows land in
|
|
the central MSSQL AuditLog table.
|
|
-->
|
|
<ProjectReference Include="../../src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/ZB.MOM.WW.ScadaBridge.NotificationOutbox.csproj" />
|
|
<!--
|
|
M4 Bundle E (Task E3): the inbound API audit-trail end-to-end test wires
|
|
the production AuditWriteMiddleware into a TestHost pipeline and asserts
|
|
one InboundRequest/InboundAuthFailure row per request lands in the
|
|
central MSSQL AuditLog.
|
|
-->
|
|
<ProjectReference Include="../../src/ZB.MOM.WW.ScadaBridge.InboundAPI/ZB.MOM.WW.ScadaBridge.InboundAPI.csproj" />
|
|
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.TestSupport/ZB.MOM.WW.ScadaBridge.TestSupport.csproj" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<!-- M4 Bundle E (Task E3): need ASP.NET Core for the TestHost-based middleware E2E. -->
|
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
|
<PackageReference Include="Microsoft.AspNetCore.TestHost" />
|
|
</ItemGroup>
|
|
|
|
</Project>
|