Files
lmxopcua/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.IntegrationTests/ZB.MOM.WW.OtOpcUa.Driver.Sql.IntegrationTests.csproj
T
Joseph Doherty 9675823cd6 test(sql): env-gated Postgres + Oracle integration suites
Two disposable docker fixtures (postgres:17-alpine on 15432, gvenzl/oracle-free:
23-slim on 11521) shaped like the existing mssql one — project label, distinct
container name, healthcheck, one-shot seed service — plus a live suite per
provider, gated on SQL_PG_* / SQL_ORACLE_* and skipping clean offline.

Each suite covers what a DIALECT can get wrong, rather than re-running the
provider-agnostic read semantics already pinned against SQL Server and SQLite:
liveness + catalog load, a KeyValue read, the provider's own row-limit syntax via
topByTimestamp (LIMIT 1 / FETCH FIRST 1 ROWS ONLY, where T-SQL emits TOP 1),
identifier case-folding through the design §8.1 catalog gate, and the AdminUI
browse walk driven through SqlDriverBrowser.

Two seed decisions are load-bearing rather than scaffolding:

- The Postgres schema is owned by a role the suite is NOT; the connecting login
  holds USAGE + SELECT only. That is the exact provisioning PostgresDialect's
  ListSchemasSql exists for (information_schema.schemata lists only schemas the
  role OWNS, so a granted-not-owning poller would see none and every tag would be
  rejected). A fixture that owned its own schema would pass either way.
- Every identifier in both seeds is created UNQUOTED, so the catalogs hold
  lower-case (Postgres) and UPPER-case (Oracle) spellings. The case-folding legs
  author the opposite case and pin SqlCatalog.TryMatch's REAL contract — exact
  ordinal first, then a UNIQUE case-insensitive match whose catalog spelling is
  substituted — which on both providers is what makes mixed-case authoring work
  at all, since both dialects emit case-sensitive double-quoted identifiers.

Connection strings are composed through dialect.Factory.CreateConnectionString-
Builder() and the abstract DbConnectionStringBuilder indexer, so the csproj keeps
its no-direct-provider-reference discipline; every key used was verified accepted
through that indexer. The csproj gains only Driver.Sql.Browser, for the browse leg.

Live-run evidence (local OrbStack, both images arm64): Postgres 5/5 green;
Oracle 6/6 green after the ORA-01745 dialect fix this suite found. Offline the
whole project is 33 skipped / 0 failed.
2026-08-05 07:15:43 -04:00

48 lines
2.5 KiB
XML

<Project Sdk="Microsoft.NET.Sdk">
<!-- OTOPCUA0001 (arch-review 07/C-1): this suite invokes driver capability methods DIRECTLY to
exercise the real Microsoft.Data.SqlClient path — the analyzer's documented intentional case
("move the suppression into a NoWarn for the test project"). Not a resilience-dispatch gap. -->
<PropertyGroup>
<NoWarn>$(NoWarn);OTOPCUA0001</NoWarn>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<RootNamespace>ZB.MOM.WW.OtOpcUa.Driver.Sql.IntegrationTests</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="xunit.v3"/>
<PackageReference Include="Shouldly"/>
<PackageReference Include="Microsoft.NET.Test.Sdk"/>
<PackageReference Include="xunit.runner.visualstudio">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<!--
No Microsoft.Data.SqlClient / Npgsql / Oracle.ManagedDataAccess.Core PackageReference here on purpose:
this suite must exercise EXACTLY the providers the driver ships, and they arrive transitively through
Driver.Sql. Adding one here would let the two versions drift and the suite would then prove something
about a provider nobody deploys. The Postgres and Oracle suites therefore never name a provider type:
they compose their connection strings through `dialect.Factory.CreateConnectionStringBuilder()` and the
abstract DbConnectionStringBuilder indexer.
Driver.Sql.Browser is referenced for the browse-session walk (schema → table → column) the Postgres and
Oracle suites drive through the AdminUI's real seam, SqlDriverBrowser — the only place the dialects'
catalog SQL is exercised as the picker actually calls it.
-->
<ItemGroup>
<ProjectReference Include="..\..\..\src\Drivers\ZB.MOM.WW.OtOpcUa.Driver.Sql\ZB.MOM.WW.OtOpcUa.Driver.Sql.csproj"/>
<ProjectReference Include="..\..\..\src\Drivers\ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser\ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser.csproj"/>
<ProjectReference Include="..\..\..\src\Drivers\ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts\ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts.csproj"/>
</ItemGroup>
</Project>