WoT runtime materialization, binding execution and native source emission (#4757)

# Description

- WoT registry, prepared file store, immutable content, version leases,
dependency-graph sharing (advanced graph rewrite), coordinator,
materialization, views and atomic refresh.
- Explicit caller-context propagation (`IWotRegistryService` / versioned
registry / prepared host / publication capture) and the additive
`IXRegistryProjectionContextualDelete` capability.
- UA/HTTP/MQTT binding execution and compilation, plus the 1.02 FileType
bridge and discovery.
- WoT-specific native event, source-emission and readiness integration
(`MasterNodeManager.SourceEmissions`, `EventManager` identity admission,
external-value monitored sources, Fluent attach/detach) and event lease
conservation.
- All corresponding `WotCon.*` runtime tests, WotCon sample app code,
WoT docs, CI feature budgets and Samples.Tests, plus the WotCon Design
NodeSet/csv/csproj and ModelSourceParity tests.
- Joint model metadata: XRegistry model 0.7.0 / 2026-09-12
(NamespaceVersion 63563, NamespacePublicationDate 63564), RequiredModel
date 2025-01-08.
- XML-doc work from the frozen WIP, applied to G12-owned declarations
only.

## Related Issues

- Fixes #4751.
- Part of the WoT split tracked in #4511.

## Checklist

- [x] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [x] I have added tests that prove my fix is effective or that my
feature works and increased code coverage. (Tests included, not yet run
against current master.)
- [ ] I have added all necessary documentation.
- [ ] I have verified that my changes do not introduce (new) build or
analyzer warnings. (Not run.)
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed. (Not run.)
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.
This commit is contained in:
Marc Schier
2026-10-20 10:43:02 +00:00
committed by GitHub
parent 0edc3b55a6
commit 65a67dd2f4
419 changed files with 112946 additions and 4832 deletions
+19
View File
@@ -93,6 +93,11 @@ dotnet test UA.slnx
Conventions and requirements:
- **Frameworks.** Test projects use either **NUnit** (with `Assert.That` assertions and **Moq** for mocking) or **TUnit** (with its own assertions and mock helpers). Do not mix the two in one project, and do not use the classic NUnit asserts (`Assert.AreEqual`, …).
- **Out-of-tree sample-test output.** When `--artifacts-path` places the WoT
aggregation tests outside the checkout, set `OPCUA_TEST_REPOSITORY_ROOT` to
the checkout containing `UA.slnx`. The sample fixtures read their original
repository assets there; no asset or assembly copying is needed. An invalid
configured root fails explicitly instead of falling back to another checkout.
- **NUnit 5 async assertions.** Always await `Assert.ThrowsAsync`, `Assert.CatchAsync`, and `Assert.DoesNotThrowAsync`; these methods return tasks and no longer block until the assertion completes. The enclosing test or helper must return `Task`.
- **Ordered NUnit fixtures.** Use `DependsOnTest` rather than the obsolete `Order` attribute. Existing sequencing-only dependencies use `AllowFailure = true` so one failed test does not suppress later tests. Filtering a dependent test also runs its prerequisites; dependency chains must not use fixture-level `Parallelizable`.
- **Coverage.** Coverage is measured with **Coverlet** and must not regress; every non-application, non-test project should stay at or above **80 %**. Two gates enforce this in CI — see [Continuous integration](#continuous-integration).
@@ -442,6 +447,20 @@ GitHub refuses to start a run whose matrices expand past 256 jobs, and the limit
The executor fails a project when its build fails, when the TRX counters report any failure, when a test fixture's setup or teardown fails, when it produces **no** TRX at all, when nothing in it actually ran, or when it outlives its per-project ceiling. A "no tests ran" outcome is a failure, not a pass — and that includes a suite whose tests were *all* skipped, which records a non-zero total while verifying nothing.
The WoT aggregation sample tests keep their complete companion-model corpus in a
dedicated CI batch. That batch has a finite 240-minute combined build/test budget
and a 65-minute inactivity limit; ordinary projects retain their 45-minute combined
budget. The sample's full generation-replacement case includes two complete
publications and must not be truncated to fit the ordinary project budget.
The Server, WoT and Types integration projects also run separately, with a 90-minute
combined budget. Server and WoT keep the 10-minute inactivity guard; Types uses
30 minutes for complete instrumented companion-model conversions. Hosted cold builds
have consumed 20-28 minutes before their healthy integration suites start;
the larger finite budget prevents truncation without hiding an inactive test.
The .NET Framework WoT profile reserves 150 combined minutes because its complete
regeneration and server-integration run exceeded an hour after a 27-minute cold
build. Its per-test inactivity guard remains unchanged.
That per-project ceiling is a **single combined budget** covering the project's build *and* its test run, measured by one stopwatch. The matrix derives each job's `timeout-minutes` from it as `20 + projectCount × perProjectTimeout`, so spending it twice per project would let a batch outlive its job: GitHub would cancel the run, and a cancelled job produces neither the executor's per-project annotation nor its results. A batch whose budgets add up past the job ceiling is an error in `get-ci-matrix.ps1` rather than a clamped `timeout-minutes`, for the same reason. `CiMatrixScriptTests` pins both halves of that arithmetic.
The verdict comes from the emitted TRX rather than from the `dotnet test` exit code, and lives in [`.github/scripts/get-test-verdict.ps1`](../.github/scripts/get-test-verdict.ps1) so it can be tested on its own — see [`CiTestVerdictTests`](../tests/Opc.Ua.Tools.Tests/CiTestVerdictTests.cs). A failed fixture setup or teardown, such as the assembly-level certificate leak check in a `[OneTimeTearDown]`, is not a test result, so no counter records it: the NUnit adapter writes it to the TRX as a run message (`TearDown failed for test fixture …`), and the verdict rejects it whatever the exit code says. A non-zero exit is tolerated when, and only when, the results record at least one **passing** test, no failure, error, timeout, abort or `passedButRunAborted`, and no failed fixture setup or teardown. That combination means the host died during process **exit**, after the last test and every teardown had already run; failing it would report a false red. It is not a macOS quirk — Windows hosts do it too (run 35714133848, `test-windows-net48 (5/30)`: `Opc.Ua.Client.Tests` reported 256 passed, 0 failed, host exit 1). A host that dies mid-run leaves a non-zero counter and is still rejected, and a run in which every test was skipped is rejected whatever the exit code says. Every tolerated run raises a warning annotation and is labelled in the job summary, so a host that keeps dying stays visible.