mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-29 15:11:53 +08:00
Merge origin/master and preserve data-channel lifecycle guards
Keep data-channel close notifications while adopting terminal-error transport draining. Retain recipient-scoped event visibility alongside source-emission admission and shared filter evaluation. Reconcile overlapping NUnit 5 assertion fixes.
This commit is contained in:
@@ -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).
|
||||
@@ -483,6 +488,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.
|
||||
|
||||
Reference in New Issue
Block a user