# Description Remove stock phrasing and correct misleading or inconsistent technical documentation. The initial two passes covered 367 Markdown files, followed by an interactive review of 169 editorial flags. The U5 interpretation originally deferred in that review has since received the upstream Mantis answer recorded by #4843; remaining server/spec follow-ups stay explicit in the CTT log. - Correct package responsibilities, migration steps, API names, ownership, protocol descriptions and links. Keep bundled migration guides synchronized. Preserve historical conclusions as historical records with separate re-check notes. - Provide at least two rendered TOC levels throughout `docs/`. Convert appropriate architecture figures to Mermaid without changing code examples, transcripts or historical quotations. - Address the October 19 feedback with concrete setup/migration instructions, corrected certificate paths and PubSub names, shorter repeated caveats, consistent XML comments, and a full review of the Concepts guide. Retain #4839's API corrections. - Integrate #4841's runtime/performance guidance and review incoming/recent prose. Preserve dated measurements rather than claiming new benchmark runs; clarify allocation ratios, startup-only processor settings, JIT warm-up and the benchmark commit's scope. Missing raw measurement artifacts and repeat ranges remain tracked by #4842. - Merge master through `e8c5d800a` in `32c6394b7`. Resolve the CTT log conflict using the updated Mantis states and OPC answers, retaining historical framing and re-checks for C28/C32/C43. - Address the latest naming/index feedback in `adb5bf693`: rename the guides to `docs/WotCon.md` and `docs/WotNodeSetConversion.md`; move the provider and DataType-declaration contracts into the conversion guide and remove `docs/WoT.md`. Rename `samples/DI` to `samples/Di` and `samples/Isa95` to `samples/ISA95`. Add content-index READMEs to Di, FluentApi, ISA95, Lds and PubSub; update solution entries, project references, Docker/CI paths, test fixture paths and documentation links with exact casing. **WoT guide scope.** This branch retains the detailed conversion guide that #4758 had replaced with an anchor stub. Conversion limits, verified document sets, preservation rules and provider ownership now live together in `WotNodeSetConversion.md`; binding/runtime guidance remains in `WotBindings.md` and `WotCon.md`. The design-rationale/test-ledger prose was shortened, the oversized argument-table cell moved into its section, and existing anchors preserved. **SDK policy is a separate, explicit user-directed change.** `global.json` sets a stable minimum of `10.0.400`, `rollForward: latestMajor`, and `allowPrerelease: false`. Newer major SDKs are permitted; CI's explicit SDK pins are unchanged. README, GettingStarted, DeveloperGuide and Recycling instructions reflect the possible analyzer differences. The image-contract regression fix accepts compatible stable SDK images instead of requiring exact equality with the floor. The latest four rename/index threads are resolved after publication. Three older threads remain open: universal obsolete-removal timing, unconditional nonce-strength wording, and a blanket Vision NativeAOT claim. Existing implementation/evidence constraints are explained in their inline replies. The two-level TOCs remain as requested. ## Validation - `git diff --check` and staged diff checks: passed. The untouched upstream AutoID NodeSet retains its provenance bytes, including two existing license-header trailing spaces. - `.\.azurepipelines\validate-migration-plugin.ps1`: passed; 15 bundled migration documents and manifests synchronized. - Documentation/path validation: **101** documents retain two rendered TOC levels (**2,228** entries), with idempotent formatting. **52** new relative links and their anchors passed exact-case checks. No tracked references to the old guide/sample paths remain. Both relocated provider-contract sections are preserved in the destination. - `dotnet sln UA.slnx list`: passed; shows the renamed Di/ISA95 projects and the existing FluentApi/Lds/PubSub projects. Updated solution and pump ProjectReference paths also passed exact-case existence checks. - Latest focused commands, run from the repository root: ```powershell # Passed: 61 channel send-order and reconnect tests. dotnet test tests\Opc.Ua.Core.Tests\Opc.Ua.Core.Tests.csproj -p:CustomTestTarget=net10.0 --filter 'FullyQualifiedName~UaSCBinaryChannelSendOrderTests|FullyQualifiedName~TcpReconnectKeyAgreementTests' --verbosity minimal # Passed: 5 pump datasheet tests; builds the renamed pump sample. dotnet test tests\Opc.Ua.Di.Tests\Opc.Ua.Di.Tests.csproj -p:CustomTestTarget=net10.0 --filter 'FullyQualifiedName~PumpDatasheetConformanceTests' --verbosity minimal # Passed: 4 repository NodeSet path/round-trip tests, including the moved pump models. dotnet test tests\Opc.Ua.Types.Tests\Opc.Ua.Types.Tests.csproj -p:CustomTestTarget=net10.0 --filter 'FullyQualifiedName~RepositorySourceSurvivesSerializedLinkedPartitionsAsync' --verbosity minimal # Passed: build, zero warnings/errors. dotnet build samples\ISA95\MinimalIsa95Server\MinimalIsa95Server.csproj -p:CustomTestTarget=net10.0 -f net10.0 --verbosity minimal # Passed: dependent sample-test project build, zero warnings/errors. dotnet build tests\Opc.Ua.WotCon.Samples.Tests\Opc.Ua.WotCon.Samples.Tests.csproj -p:CustomTestTarget=net10.0 -f net10.0 --verbosity minimal ``` Earlier focused integration checks passed 2,620 tests across AutoID, event queues/scheduling, source generation, MCP/package profiles and WoT. Both reviewed Mermaid diagrams rendered locally without network access. These checks are not a full solution run. The full solution has **not** been rerun for this review. Earlier `dotnet test UA.slnx -p:CustomTestTarget=net10.0 --verbosity quiet` did not pass: three AOT projects rejected VSTest and 20 Vision tests failed during graphics initialization with `OutOfMemoryException`. Remaining long-running tests were stopped at the user's request. A focused Vision rerun passed 558 tests and reproduced those 20 failures. The earlier `dotnet test UA.slnx -p:CustomTestTarget=net48 --verbosity quiet` was blocked by the former SDK pin and was not retried after the policy change. The user approved proceeding with those limitations documented; current remote CI is not claimed green. ## Related Issues - Follow-up #4842 tracks the requested 2.0.2+ benchmark/tuning and diagnostic-tool documentation refresh. #4841 supplies documentation and earlier results, not all newly requested measurements. - #4758 explains the conversion guide's earlier consolidation; the current provider contracts are now consolidated into `WotNodeSetConversion.md`. - #4839 supplies the reviewed API corrections; #4843 supplies the updated CTT issue record. - The original prose cleanup and SDK policy were user-requested without a source issue. No new runtime architecture is introduced by these documentation edits. ## Checklist _Put an `x` in the boxes that apply. You can complete these step by step after opening the PR._ - [ ] 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. - [ ] I have added tests that prove my fix is effective or that my feature works and increased code coverage. - [x] I have added all necessary documentation. - [ ] I have verified that my changes do not introduce (new) build or analyzer warnings. - [ ] I ran **all** tests locally using the **UA.slnx** solution against at least .net **framework** and .net **10**, and all passed. - [ ] I fixed **all** failing and flaky tests in the CI pipelines and **all** CodeQL warnings. - [ ] I have addressed **all** PR feedback received. --------- Co-authored-by: Roman Ettlinger <romanett98@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
36 KiB
CTT (Compliance Test Tool) failing test cases
This file lists the test cases of CTT 1.05.06 (scripts 1.05.513) that fail, warn or skip against the OPC
Foundation .NET reference server (ConsoleReferenceServer --ctt) because of a CTT defect. Each entry has a
short abstract and the Mantis issue that tracks it; Mantis has the details. Defects that are not filed,
spec questions, follow-ups for the server and CTT project configuration notes come after the tables. The
procedure for running the CTT is in ctt-testing.md.
- (fixed) means the Mantis issue is resolved and the fix is in the CTT script repository. The fix ships in a script build after 1.05.513, so an installed 1.05.513 still shows the failure.
- The ids (1–19, C1–C66, U1–U6) are stable references for notes and commit messages. Missing ids were withdrawn or no longer fail.
- Mantis states were last checked on 2026-10-19.
Filed in Mantis
Aggregates
| Id | Failing test | Abstract | Mantis |
|---|---|---|---|
| 3 | Aggregate – Base 002-01.js…002-04.js (every Aggregate CU) |
The multi-node path of HAAggregateHelper.js dereferences possibleNodeId without a guard. |
11251 |
| 4 | Aggregate – Base Err-004.js |
Sends an equal-time request when the ProcessingInterval setting is blank. | 11252 |
| C1 | Aggregate – Base 003-0x.js, 004-0x.js, Err-004.js; NumberOfTransitions 003-02.js, 004-02.js |
The harness always sends UseServerCapabilitiesDefaults = TRUE, so the server uses its defaults while the CTT applies the test configuration. |
11420 (duplicate: 11466) |
| C2 | Aggregate – AnnotationCount | Counts raw values instead of Annotations. | 11421 |
| C3 | Aggregate – WorstQuality2 | Also includes the end bound. | 11422 |
| C4 | Aggregate – DurationInStateZero / DurationInStateNonZero | Reports Bad below PercentDataBad. | 11423 |
| C5 | Aggregate – DurationGood/Bad, PercentGood/Bad 002-0x.js |
Truncates durations to whole milliseconds. | 11424 |
| C6 | Aggregate – DurationGood, PercentGood | Ignores the raw value before the interval for the status of the first region (answered, see U4). | 11425 |
| C48 | Aggregate – Minimum, Maximum, MinimumActualTime, MaximumActualTime, Range | Ignores Uncertain values beyond the Good extremum and expects Good instead of UncertainDataSubNormal (answered, see U4). |
11426 |
| C49 | Aggregate – Minimum, MinimumActualTime, MaximumActualTime | Does not set the Calculated bit when non-Good values make the status Uncertain (answered; see U4 for a conflict with 11426). | 11427 |
| U2 | Aggregate – Minimum2 (reverse reads) | Clears the Calculated bit when the minimum is the End bound at the early end of a reverse interval (Part 11 §6.5.4.2). | 11461 |
| U4 | Aggregate – DeltaBounds, StartBound, EndBound, WorstQuality2, TimeAverage2, Total2, Interpolative (TreatUncertainAsBad = True) | Applies TreatUncertainAsBad to bounding values, against the answer to 11462. | 11487 |
| C64 | Every Aggregate CU on the Int32 node (Interpolative, Start/EndBound, DeltaBounds, Minimum2/Maximum2/Range2, *ActualTime2, TimeAverage(2), Total(2); about 1400 readings) | Truncates interpolated bounds of integer Variables (23.8 → 23). Bounds are real (Part 13 §3.1.8); source-type results round by adding 0.5 and truncating (Part 4 §7.7.3), giving 24; Double results use the real bound (ramp 0…23.8 averages 11.9, the CTT expects 11.8866). In *ActualTime2 a truncated End bound ties an earlier raw value. | 11494; spec: 11499 |
Historical Access
| Id | Failing test | Abstract | Mantis |
|---|---|---|---|
| 2 | Read Raw initialize.js |
Accesses CUVariables.ArrayItems without its isDefined guard. |
11249 |
| 6 | Read Raw 004.js |
Rejects correct reverse ordering. | 11263 (fixed) |
| 7 | Read Raw 014.js |
Indexes a nonexistent second node result. | 11264 |
| 8 | Read Raw 019.js |
Bypasses the CTT test harness. | 11265 |
| 10 | Read Raw 012.js |
Expects BadIndexRangeNoData at the wrong level and sizes arrays from the first array item. |
11267, 11273 |
| 16 | Read Raw 013.js |
Reuses continuation points after changing the IndexRange. | 11257 (fixed) |
| C7 | Read Raw Err-013.js |
The message calls the operation-level BadContinuationPointInvalid a ServiceResult. |
11428 |
| C8 | Read Raw Err-019.js |
The messages at lines 25 and 43 use an undefined loop variable. | 11429 |
| C45 | Read Raw Err-025.js |
Expects BadNotSupported for a non-historizing node; the test case will be removed. |
11347 (fixed), 11353 |
Address Space, Base Information, Attribute and View Services
| Id | Failing test | Abstract | Mantis |
|---|---|---|---|
| 1 | Base Info State Machine Instance 001.js |
The GeneratesEvent target validation uses the wrong helper. |
11248 = 11125 (fixed) |
| 5 | AliasName Hierarchy 002.js |
References an undefined variable. | 11262 (fixed) |
| 11 | Attribute Read 026.js, 032.js, 034.js, 036.js; Attribute Write Index 007.js |
The array helpers support neither NodeId[] nor StatusCode[]. |
11261, 11250 |
| 12 | Base Info Core Structure 2 001.js |
The error message cites the UA 1.04 reference model. | 11268 (fixed) |
| 13 | Base Info Core Structure 2 001.js |
ConformanceUnits is tested as a scalar. |
11269 = 11144 (fixed) |
| 14 | Base Info Core Structure 2 001.js |
Reads TransactionDiagnostics before any transaction and does not accept BadOutOfService. |
11256 (also 11509) |
| C15 | Base Info Core Structure 2 001.js |
The Organizes check in InfoFactory.js dereferences an undefined sourceTypeNodeId for View sources. |
11435 |
| C15b | Base Info Core Structure 2 001.js (every View validated by InformationModelValidation) |
The View validator's HierarchicalReferences knows only i=33 and Contains() returns undefined, so every inverse reference to a View from a hierarchical subtype fails. |
11476 |
| 15 | Base Info SemanticChange 001.js |
Decodes the Changes array as one ExtensionObject, and the Range post-increment writes the old value. |
11093 |
| C13 | Base Info Currency 004.js |
The SByte Exponent of the toCurrencyUnitType() result does not convert to a number. |
11434 |
| C46 | Address Space Atomicity 001.js (skips) |
Examines only the first 10000 variables sorted by NodeId string (a literal in the script; MaxNodesToReturn is an Int16, so 32767 is the most that works), and its bit test detects only NonatomicRead. |
11446 |
Monitored Item, Subscription and Session Services
| Id | Failing test | Abstract | Mantis |
|---|---|---|---|
| C9 | Monitor Value Change V2 042.js |
Computes indexValue from itself; the message cannot identify the missing item. |
11430 |
| C17 | Monitor Basic 039.js |
Calls getMatrixValues without including its library. |
11097 (fixed) |
| 18 | Subscription Durable 008.js |
Misspells MoreNotifications and does not drain the queue; the DataChange count check rarely runs and the write spacing uses only items[0]'s sampling interval. |
11259 (fixed), 11475 |
| C38 | Subscription Durable 012.js |
Ignores a denied diagnostics Browse (BadUserAccessDenied) and then reads an empty node list. The server side matches 11445 ~0025750 since #4664: every Session may browse its own subscriptions in SubscriptionDiagnosticsArray, and reading the whole array stays administrator-only. |
11445 |
| 19 | Subscription Minimum 02 020.js |
Accepts unrelated audit events and other server events (for example simulated alarms). | 11260 |
| C50 | Security None 007.js, Security Basic 256 Sha256 005.js, Subscription Publish Basic cleanup.js (warnings) |
CloseSession is stamped before the CTT stops the SessionThread (about 550 ms), so the delay warning blames the server. | 11454 |
Node Management, Discovery and Security
| Id | Failing test | Abstract | Mantis |
|---|---|---|---|
| 9 | Node Management Add Node Err-008.js |
Tests duplicate NodeIds while client-specified NodeIds are disabled. | 11266 |
| C34 | Node Management Add Node 001.js–003.js, Err-003.js, Err-005.js, Err-008.js (with RequestedNodeId enabled) |
RequestedNewNodeId() ignores RequestedNodeId_Namespace and always requests namespace 1. |
11443 |
| C16 | Discovery Get Endpoints 003.js |
AcceptedProfileUris omits the WebSocket transport profiles; the CTT will report them as unsupported endpoint types. |
11436 |
| C35 | Security User Anonymous 002.js |
initialize.js selects the opc.wss endpoint, which the CTT cannot open. |
11102 |
| C37 | Session Base Err-002.js, Err-005.js, Err-022.js |
Send CreateSession with the opc.wss EndpointUrl, whose host name the CTT reads as empty. |
11102 |
| C36 | Security User Name Password 2 015.js |
FindTokenType in UaE.js rewrites the cached endpoints, so identical UserTokenPolicies look different. |
11444 (follows 11258) |
GDS
| Id | Failing test | Abstract | Mantis |
|---|---|---|---|
| C19 | Application Directory 060.js, 067.js, 069.js |
Register an ApplicationUri that is not a valid URI. | 11438 |
| C20 | Application Directory 060.js, 065.js; Query Applications 011.js, 016.js |
Evaluate the Like patterns [_] and [%] as "contains". |
11410 |
| C21 | Application Directory 074.js; Query Applications 025.js |
Evaluate %[^f-h]% and %[^w-y]% as "contains none of". The OPC Foundation decided to test negated lists only at the start or end of a string until Part 4 clarifies the pattern; until then both test cases should be skipped. |
11411 |
| C22 | Application Directory 078.js, 079.js |
callQueryServers() dereferences the output arguments of a failed Call. |
11407 |
| C23 | Application Directory 018.js (sometimes 011.js, 028.js) |
Selects ActionTimestamp instead of ActionTimeStamp and creates the audit item with queue size 1; 018.js also passes Variants to the typed event classes and sends an empty AuditEntryId. |
11439 |
| C24 | Application Directory 019.js |
The batched RegisterApplication Call of step 3 never reaches the server: the native client stack fails a Call locally (BadNotFound) when a generic-structure ExtensionObject is in any request but the first. |
11409 |
| C25 | Application Directory 010.js |
Dereferences the ApplicationId of a rejected registration. | 11106 (fixed, still in 1.05.513), 11408 |
| C26 | Application Directory 012.js, 032.js |
Require ServerCapabilities for a Server record. | 11441 |
| C27 | Application Directory 027.js |
Changes a Server that has a DiscoveryUrl into a Client. | 11442 |
| C29 | Application Directory 005.js |
The random ApplicationUri is cut at its first NUL, so both calls are identical; the oversized URI is then rejected at decode with Bad_EncodingLimitsExceeded, which the script does not accept. |
11406 |
| C30 | Query Applications 036.js |
Expects rcp+ DiscoveryUrls the test never registered. |
11412 |
| C31 | Query Applications 038.js |
Treats applicationType 3 as invalid. | 11413 |
| C51 | Application Directory 066.js, 079.js; Query Applications 039.js (pass only because the server returns NA records) |
Register the reference Servers with ServerCapabilities NA and expect them in query results, which OPC 10000-12 §6.5.10/§6.5.11 exclude; with the exclusion 40 test cases fail. |
11458 |
| C57 | Application Directory 011.js, 018.js, 028.js |
Expect ApplicationRegistrationChangedAuditEvents on the DiscoveryAdmin Session, but the GDS NodeSet grants ReceiveEvents on that EventType only to SecurityAdmin (OPC 10000-3 §8.55). | 11482 |
Alarms and Conditions
| Id | Failing test | Abstract | Mantis |
|---|---|---|---|
| C10 | A & C Alarm Test_002.js; A & C Confirm Test_001.js (depends on the alarm phase) |
ValidateRetain ignores LatchedState: a latched alarm keeps Retain TRUE until it is reset (Part 9 §5.8.2). |
11431 |
| C11 | A & C Alarm Test_004.js |
Reads the InputNode on the CU session, which has timed out (BadSessionIdInvalid) while the collector used only the alarm-thread session. |
11432 |
| C12 | A & C Enable Test_002.js |
Passes four arguments to the three-argument AddMessage, so the reason text is lost. |
11433 |
| C18 | A & C Acknowledge, A & C Confirm (warnings) | The recommended TwoStateVariable texts are not found for locale en-US. |
11437 |
| C39 | A & C Comment Test_001.js–Test_004.js (skip); A & C Enable Test_002.js |
GetCallTime() returns an unset call time; the wrapped 32-bit difference lets the Comment cases pass by accident for about 25 of every 50 days. |
11447 |
| C40 | A & C Exclusive/Non-Exclusive Limit/Level Test_003.js–Test_006.js |
initialize.js creates the filter subscriptions on a CU session that timed out during the initial event capture. |
11448 |
| C41 | A & C Alarm Test_002.js (runs to the maximum test time) |
AcknowledgeableConditionType never gets a result. | 11449 |
| C42 | A & C Enable Test_003.js (runs to the maximum test time) |
Depends on all alarm types going active within one tenth of the Alarm Cycle Time. | 11450 |
| C44 | A & C CertificateExpiration (a --close --hidden run never exits) |
initialize.js opens a modal dialog. |
11453 |
| C52 | A & C Refresh, Refresh2, Shelving (BadSubscriptionIdInvalid under CPU load) |
Refresh Err_004.js and Refresh2 Err_003.js leave 10 subscriptions each on the shared alarm session, and ShutdownItem() leaves one per Refresh test case. |
11459 |
| C53 | A & C (alarm thread) | StartThreadPublish.js lines 28–29 default misspelled properties, so MaximumPublishCalls/MaximumOutstandingCalls are sent undefined (code cleanup only). |
11460 |
Not filed
Historical findings: C28, C32 and C43 below retain the original conclusions and held-back status. Their re-checks are follow-up work, not new verification of the current server or CTT.
- C28. GDS Application Directory
029.js,038.js,039.jsexpectBadInvalidArgumentfor a null or unknown ApplicationId. The server returnsBadNotFound, the only code OPC 10000-12 §6.5.7/§6.5.9 define for an unknown ApplicationId. Held back until the GDS server behavior is reviewed. Re-check: distinguish null from unknown ApplicationIds against the Method requirements and current server. - C32. Monitor Basic
038.jswarns when a requested SamplingInterval of 0 is revised to 0, unless Fastest Sampling Interval Supported is 0. The nodes declare MinimumSamplingInterval 0, so 0 is correct (Part 4 §7.21). The setting cannot be lowered becausemonitoredItem.jsuses it as the default sampling interval. Held back: relevance unclear. Re-check: verify Part 4 §7.21 and the effect of changing the shared default in the current CTT project. - C43. A & C Enable
Err_004.jscalls Disable, Disable and Enable for every event of a condition without per-condition state, which feeds itself (up to about 850 events in 15 s). In 8 of 28 runs the alarm thread then returned no further events. Held back: needs more investigation. Re-check: correlate the server trace, CTT acknowledgements and alarm-thread state before assigning a cause. - C54. GDS AliasName Discovery
002.js,004.js,006.js,007.js,009.js,011.js,012.js,014.js,015.js.AssertAliasNamesReplicated(library/GDS/AliasNameDiscoveryHelpers.jsline 92) compares the AliasFor targets withUaExpandedNodeId.equals(). On the source the target is local (ServerIndex 0); the GDS must reference it with the source's ServerIndex and namespace URI (OPC 10000-17 Annex C.1, OPC 10000-4 §7.16), so a conformant GDS never matches. Fix: compare identifier and namespace URI and check that the GDS ServerArray entry at the target's ServerIndex is the source's ApplicationUri. Draft ready, not filed. - C55. GDS AliasName Discovery
001.js,005.js,010.js,013.jscheck that no aliases of remote servers exist before registration, but fail on every AliasNameType instance, including the GDS's own aliases (ServerIndex 0). Fix: count only aliases with an AliasFor target whose ServerIndex is not 0. With the C54 and C55 fixes all 15 test cases pass. Draft ready, not filed. - C56. Monitored Items Deadband Filter
Err-006.jssets a PercentDeadband on a BaseDataVariable without EURange and accepts onlyGoodorBad_MonitoredItemFilterUnsupported. OPC 10000-8 §7.3.2 Table 61 definesBad_DeadbandFilterInvalidfor that case, which the server returns since #4629. Draft ready, not filed. - C58. UAFX FxRoot
001.jsfails instead of skipping when the server has no UA FX Data namespace, unlike the other UAFX/DI CUs. - C59. A & C Refresh
Err_004.js/Test_006.js, Refresh2Err_003.jswait 30/20/30 s without checking anything during the wait; 2–5 s are enough (about 87 s per A&C run). - C60. A & C Limit/Level
Test_003.js–Test_006.js(and any A&C CU that shares the alarm thread) fail with "Filtered Event counts are not equal" when the CTT's native publish thread stops sending Publish requests. A traced server answered all 413 Publish requests; afterwards the session sent only Reads, so its Subscriptions expired. Five Subscriptions on one publish thread with one outstanding Publish make it likely: with Default Subscription Publish Interval 150 ms the stall hit 6 of 9 runs on a GitHub-hosted runner, with 250 ms 0 of 3. Native CTT code, no script fix. - C61. A & C Enable
Test_002.jstakes a second notification of the previous EnabledState as the answer to the next call. - C62. A & C Confirm
Err_004.jsfails withBad_EventIdUnknownwhen the Event reaches the second session late; the Confirm then uses an EventId the Condition has already replaced (Part 9 B.1.2 keeps no previous states), so the server is right. - C63. A & C units reuse an alarm thread whose publish thread stalled (C60) at the end of the previous
unit, so the whole next unit fails. Seen in the weekly run of 2026-10-18: Refresh2
Test_002.js,Test_003.jsandcleanup.jsfailed withBadSubscriptionIdInvalid, and the unit stopped afterTest_004.js. At 250 ms the stall still hits about 1 in 5 A&C runs on a GitHub-hosted runner, sometimes within a unit (Refresh2Err_003.js). Workaround in the CTT CI: each unit checks at its start that the publish thread still receives keep-alives and otherwise starts on a new alarm thread. A part whose first attempt has regressions together with the C60 watchdog warning runs once more, and the second attempt is the result. - C65. Aggregate Bad data search reads forward.
HAAggregateHelper.GetBadDatareads 120 raw values "backward" from the configuredStartOfBadData*time with EndTimenew UaDateTime(), the null DateTime. The server therefore reads forward (Part 11 §6.5.3), and the helper takes the last value as the earliest. The search then covers the 120 values after the configured time, and the final read spans from the end of that search to the 120th value after the first non-Good value it found. The Bad block must lie in that final read, not in the search window (see Bad data entries for aggregates). Proposed fix (EndTime1601-01-01T00:00:00.001Z) not tested yet. Related, different defect: 11505 (no contiguous Bad block → TypeError). - C66. Aggregates on Boolean/String nodes. The CTT's expected values for StartBound/EndBound and DurationInState* on non-numeric nodes differ from the stepped Simple Bounding Values (Part 13 §3.1.9, §5.4.3.22–23, §5.4.3.28–29). The status-only aggregates are covered by C3, C4 and C6. Not filed: the CTT's own values were not recorded. Related: 11274. The server interpolates non-numeric values stepped whatever the Stepped property says (a String bound between "23" and "24" is "23").
Spec questions
U4. TreatUncertainAsBad and the aggregate definitions (answered)
The OPC Foundation (Paul Hunkar) answered in Mantis that the aggregate definition wins over TreatUncertainAsBad; the general rules of §4.2.1.2 apply only where a definition says nothing else:
- 11462 ~0025840: TreatUncertainAsBad does not apply to
bounding values; they follow §3.1.7–§3.1.9 only. An Uncertain neighbour makes a bound
UncertainDataSubNormal, and only a Bad value after a Simple bound reverts to stepped. The CTT side is 11487. A follow-up question (~0025849) on §3.1.7's "in all cases the TreatUncertainAsBad flag is used" is unanswered. - 11425 ~0025847 and 11495 ~0025874: DurationGood/DurationBad (and PercentGood/PercentBad) use the stepped Simple bound and its status for the first region; DurationGood divides into Good and non-Good regions, DurationBad into Bad and non-Bad regions, so Uncertain counts for neither.
- 11426 ~0025852: Minimum, Maximum, MinimumActualTime,
MaximumActualTime and Range follow OPC Classic. Uncertain values are candidates as if Good; an Uncertain
extremum is returned with
UncertainDataSubNormal; otherwise the status is Good,UncertainDataSubNormalif Bad values exist,BadNoDataif all are Bad. 11427 ~0025875 instead returns the Good minimum withUncertainDataSubNormaland the Calculated bit when a lower Uncertain value exists. The two answers conflict for that case; not raised yet. Minimum2/Maximum2 keep TreatUncertainAsBad, which §5.4.3.15 names explicitly.
The server follows 11462, 11425 and 11426 since #4702. With the patched scripts, Aggregates (p06) has 0 errors against it.
U5. TreatUncertainAsBad = False for Average, Count, Delta, StandardDeviation*, Variance* (answered)
Since C1 is fixed, the CTT sends TreatUncertainAsBad = False in 003-02.js, 003-03.js, 004-02.js and
004-03.js, and 34 test cases differ. The server includes Uncertain values like Good ones (§4.2.1.2,
§5.4.3.2.1). The CTT excludes them because the definitions say "Good", and reports UncertainDataSubNormal.
11495 ~0025874 (and earlier
7975) confirms the CTT for Count: non-Good values are never
counted, but they do affect the status. By the same rule the CTT is right for the other aggregates whose
definition says Good. The server follows this with #4846.
U6. NumberOfTransitions with TreatUncertainAsBad = True (open)
§5.4.3.24 compares "the earliest non-Bad value in the interval to the previous non-Bad value" (Table 72: "Bound Uncertain: Use as value"). Under the U4 rule Uncertain values count, and the server counts them. The CTT skips them when TreatUncertainAsBad = True (16 p06 errors). Not asked in Mantis yet.
Server follow-ups from the answers
- C48/C49: if 11427 ~0025875 is confirmed over 11426 ~0025852, return the Good extremum (not the Uncertain
one) with
UncertainDataSubNormal. - C64: if 11499 defines another conversion than Part 4 §7.7.3 rounding, follow it for the source-type aggregates.
CTT project configuration notes
Tests skipped because of reference server sample-data gaps or missing CTT project settings are tracked in #4479.
-
Aggregate ProcessingInterval.
samples/UAReferenceServer.ctt.xmlsets/Server Test/NodeIds/Static/HA Profile/Aggregates/ProcessingIntervalto 1; keep it positive (issue 4). -
Bad data entries for aggregates.
005-05.js/005-06.jsneed an explicit Bad data entry; without itHAAggregateHelper.GetRequestEntryfalls back to the start entry or throws.GetStartBadDataTimereads.../Aggregates/StartOfBadData<Name>as an absolute time. The helper looks for a block of at least two consecutive non-Good values.- The reference server seeds every history node with 1001 values relative to its start time, 10 s apart:
index mod 10 = 7 is
BadDataUnavailable, index mod 10 = 9 isUncertainSubstituteValue, the rest are Good. - Every scalar history node also gets 400 values from
2026-01-01T00:00:00Z(value = index, source timestamp- 1.234 s):
- index 0–149 repeat the pattern (the first 120 are the start data of the other test cases);
- 150–267 are Good, 268 is Bad and 269–274 are Good;
- 275–279 are the Bad block;
- 280–399 repeat the pattern.
- All ten
StartOfBadData*settings are2026-01-01T00:25:01.234Z(index 150). The layout follows the forward-reading search (C65): 120 values after index 150 must contain a non-Good value followed by a Good one (268), and the block must lie between index 269 and 387. - The
003-xx/004-xxtest cases that request "bad or start" data use this block too. StartOfArchive is the fixed date.
-
Reference server settings for #4479.
samples/UAReferenceServer.ctt.xmlsets the following; copy them into projects created from an older template:/Server Test/NodeIds/Static/All Profiles/Scalar/Bool=ns=2;s=Scalar_Static_NonHistorizing_Boolean, the non-historizing node of Historical Access Read RawErr-025.jsand Delete Valuedat-Err-001.js/Err-004.js. The HA Profile and Aggregate Boolean settings stay onScalar_Static_Boolean./Server Test/NodeIds/References/Has References of a ReferenceType and SubType=i=2253(the Server object hasHasComponentandHasAddIn;References_HasReferenceTypeAndSubTypeloses its hierarchical references in the source generator, #4484)./Server Test/NodeIds/NodeClasses/Object=i=2253, so View Basic 2018.jsalso sees Method references.
-
Base Info Diagnostics
018-1.js–018-3.jswriteServer.ServerDiagnostics.EnabledFlag. The reference server allows that only for SecurityAdmin or ConfigureAdmin over SignAndEncrypt (the project'ssysadminuser). The "Session diagnostics not available" warning of018-1.jsis expected. -
Node Management Add Node
002.jsadds a Variable with every enabled/Server Test/NodeIds/NodeManagement/SupportedReferencesentry. Enable only hierarchical references valid for a Variable target (Organizes,HasProperty,HasComponent); the others correctly returnBadReferenceNotAllowed(Part 4 §5.8.2). -
Node Management client NodeIds. The template enables
RequestedNodeIdwithRequestedNodeId_Namespace= 2. That needs the C34 fix; with unfixed scripts disable the setting (Err-008.jsthen keeps failing, issue 9). -
DI Base Model and UAFX. The 14 DI Base Model CUs and the UAFX groups (59 CUs) need the DI and UA FX models, which the reference server does not load. They skip, except that UAFX
initialize.jsreports the missing namespaces and FxRoot001.jsfails (C58). -
PubSub Publisher UADP CUs (chunking, Defined Ordering, Periodic Fixed Settings) abort in
initialize.jsbecause the server implements no PubSub publisher. Deselect the PubSub General group. -
UserDefinedCU logs "Hello error"/"Hello warning" by design. Deselect it.
-
Discovery.
- Find Servers Filter
002.jsneeds an LDS with at least two servers. - Find Servers Self
010.jsand Get Endpoints009.jsneed a multi-homed host.
- Find Servers Filter
-
Auditing. Auditing Connections
002.js,003.js,008.js,010.jsand014.jsskip unless another test case in the same run produces their audit event. Run Auditing together with the audited service groups. -
GDS target server.
- The reference server in
--cttmode and a dedicated GDS run the same code, so both give the same results. - The reference server keeps its GDS database in memory (empty
DatabaseStorePath). - A GDS with a JSON database keeps the records of aborted runs; delete that file before each run.
- Run the four GDS CUs in one run: their test cases depend on the records registered by
initialize.jsand by earlier test cases.
- The reference server in
-
GDS AliasName Discovery tests the GDS AliasName Server Facet (OPC 10000-17 Annex C).
Ctt.ReferenceServer.Config.xmlenablesEnableAliasNameAggregation.initialize.jsuses the CTT's embedded server as the first source.005.js–009.jsneed a second and010.js–015.jsa third AliasName Server (.../AliasName Source 1 URL,... Source 2 URL). The template leaves them empty because the repository has no suitable server.- Each source must offer Anonymous on an endpoint the CTT selects and trust the CTT and the GDS.
- Its alias and category names must differ from those of the GDS and of the other sources.
- It must expose no optional children (
FindAliasVerbose,AddAliasesToCategory,LastChange) on its own categories. RegisterApplicationwarns about the delay because it waits for the source to be read.- C54/C55 fail the remaining test cases.
-
GDS LDS-ME Connectivity skips unless an LDS/LDS-ME is registered with the GDS; the reference server has none.
-
Monitored Item Services manual test cases. These are Not Implemented in scripts 1.05.513:
- Monitor Basic
036.js, Monitor Complex Value001.js–003.js, Monitor Events002.js/003.jsand Monitor Queueing013.js/014.js; - the Monitor Complex Event Filter and Monitor QueueSize_ServerMax CUs;
- Node Management Add Ref and Delete Ref.
- Monitor Basic
-
Security groups need the CTT PKI, not
-a(ctt-testing.md); with-aevery negative certificate test fails spuriously. -
SecureChannels without a Session. Security None
007.jsand Security Basic 256 Sha256005.jskeep channels without a Session idle for about 51 s. The server closes such channels afterChannelLifetime(default 30 s);Ctt.ReferenceServer.Config.xmlsets 120000, and both pass (005.jskeeps the C50 warning). -
Security coverage.
- 50 of the 53 Security General CUs contain only Not Implemented test cases.
- Certificate Validation
004.jsskips because the CTT cannot send an empty client certificate. 049.js/050.jsneed the deprecated Basic128Rsa15 policy.- Security User Anonymous
003.jsneeds a secure endpoint without Anonymous. - User Name Password 2
002.jsneeds an unencrypted password policy on an encrypted endpoint (not applicable). 012.jspasses only because the configured denied login is an unknown user.- Kerberos, JWT, Authority Profile, Token Unencrypted, Invalid user token and X509
003.js/012.jsare Not Implemented.
-
Alarms and Conditions coverage.
- The single-case CUs (ConditionClasses, Suppression by Operator, Silencing, OutOfService, On-Off Delay, Re-Alarming, First in Group, Audible Sound, Discrepancy, Trip, A&E Wrapper Mapping, Dialog) are manual.
/Server Test/Alarms and Conditions/Chattering Alarmsis empty, so most Shelving test cases finish without testing anything. Testing them needs an alarm source that oscillates inside the alarm band.
-
A & C Alarm Cycle Time and session timeout. The Alarm Cycle Time sets the initial event capture (1×), the maximum time of every collector test case (3×) and the Enable
Test_003.jsrefresh delay (1/10). Keep it below/Server Test/Session/RequestedSessionTimeoutwhen a Limit/Level CU can run first (C40). The template sets 30 s against a 60 s session timeout. -
Session and Subscription coverage. These are manual (Not Implemented):
- Subscription Basic
072.js/073.js; - Subscription Multiple
001.js–003.js; - Subscription Publish Basic
005.js–007.jsandErr-001.js; - Subscription PublishRequest Queue Overflow
001.js/002.js; - Subscription Durable
013.js.
Durable StorageLevel High/Medium/Small and Retransmission Queue contain only
NoTestCaseDefined.js. These are skipped by the scripts:- Subscription Basic
067.js; - Subscription Durable
006.jsand009.js; - Subscription Transfer
Err-010.js; - Session Base
Err-009.js(Kerberos) andErr-023.js(the server offers SecurityPolicy None).
- Subscription Basic
-
Historical Access coverage. Every Historical Access CU except Read Raw contains only
NoTestCaseDefined.jsin scripts 1.05.513.