review(Driver.TwinCAT.Cli): clean parse errors + FlushLogging() in finally
Re-review at 7286d320. -008 (Low): ParseValue maps FormatException/OverflowException to a
clean CommandException (was raw stack trace) + tests. -009: FlushLogging() in all 5 commands'
finally blocks (parity with AbCip.Cli).
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
|---|---|
|
||||
| Module | `src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli` |
|
||||
| Reviewer | Claude Code |
|
||||
| Review date | 2026-05-22 |
|
||||
| Commit reviewed | `76d35d1` |
|
||||
| Review date | 2026-06-19 |
|
||||
| Commit reviewed | `111d6983` |
|
||||
| Status | Reviewed |
|
||||
| Open findings | 0 |
|
||||
|
||||
@@ -251,3 +251,85 @@ accessor required by the abstract base property is intentionally a no-op, and th
|
||||
backing field would cause the two to drift on every refactor. The inner-block comment was
|
||||
tightened to point at the XML summary so the design intent survives whichever doc surface a
|
||||
future maintainer reads first.
|
||||
|
||||
---
|
||||
|
||||
## Re-review 2026-06-19 (commit 111d6983)
|
||||
|
||||
All seven prior findings remain Resolved. The re-review covers the same 8 source files and 4
|
||||
test files at the current HEAD. No new findings were added to categories 2, 3, 5, 6, 7, 8;
|
||||
two new Low findings were identified in categories 4 and 1/4, both fixed in-session.
|
||||
|
||||
#### Checklist coverage (re-review)
|
||||
|
||||
| # | Category | Result |
|
||||
|---|---|---|
|
||||
| 1 | Correctness & logic bugs | No new issues found |
|
||||
| 2 | OtOpcUa conventions | No new issues found |
|
||||
| 3 | Concurrency & thread safety | No new issues found |
|
||||
| 4 | Error handling & resilience | Driver.TwinCAT.Cli-008, Driver.TwinCAT.Cli-009 |
|
||||
| 5 | Security | No new issues found |
|
||||
| 6 | Performance & resource management | No new issues found |
|
||||
| 7 | Design-document adherence | No new issues found |
|
||||
| 8 | Code organization & conventions | No new issues found |
|
||||
| 9 | Testing coverage | No new issues found |
|
||||
| 10 | Documentation & comments | No new issues found |
|
||||
|
||||
### Driver.TwinCAT.Cli-008
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Severity | Low |
|
||||
| Category | Error handling & resilience |
|
||||
| Location | `Commands/WriteCommand.cs:73-93` |
|
||||
| Status | Resolved |
|
||||
|
||||
**Description:** `ParseValue` delegates to the BCL numeric parse methods (`int.Parse`,
|
||||
`sbyte.Parse`, etc.) which throw raw `FormatException` or `OverflowException` on bad
|
||||
input. Those exceptions propagate all the way through `ExecuteAsync` and are caught by
|
||||
CliFx's top-level handler, but CliFx prints a full stack trace for unrecognised exception
|
||||
types. An operator passing `--value xyz --type DInt` sees several lines of .NET internals
|
||||
instead of the single-line "Cannot parse 'xyz' as DInt" message that `CommandException` would
|
||||
produce. The existing test `ParseValue_non_numeric_for_numeric_types_throws` confirmed and
|
||||
preserved the broken behaviour by asserting `FormatException`, so the gap survived review.
|
||||
|
||||
**Recommendation:** Wrap the switch body in a `try/catch` that re-throws `CommandException`
|
||||
(which is already thrown by `ParseBool`) and maps `FormatException`/`OverflowException` to a
|
||||
`CommandException` carrying the raw value and type name.
|
||||
|
||||
**Resolution:** Wrapped the `ParseValue` switch in `try/catch`; `FormatException` and
|
||||
`OverflowException` are caught (via `when` pattern) and re-thrown as `CommandException`
|
||||
with `"Cannot parse '{raw}' as {type}: {message}"`. Pre-existing `CommandException` from
|
||||
`ParseBool` / the unsupported-type arm / the `Structure` guard are re-thrown unchanged.
|
||||
Updated the test: renamed `ParseValue_non_numeric_for_numeric_types_throws` →
|
||||
`ParseValue_non_numeric_for_numeric_types_throws_CommandException` and asserted the message
|
||||
contains both the value and type; added a second test
|
||||
`ParseValue_overflow_for_numeric_types_throws_CommandException` (300 as SInt). 70 tests
|
||||
pass (was 69). Date: 2026-06-19. SHA: blank (not committed).
|
||||
|
||||
### Driver.TwinCAT.Cli-009
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Severity | Low |
|
||||
| Category | Error handling & resilience |
|
||||
| Location | `Commands/BrowseCommand.cs:62-65`, `Commands/ProbeCommand.cs:59-62`, `Commands/ReadCommand.cs:50-53`, `Commands/WriteCommand.cs:63-67`, `Commands/SubscribeCommand.cs:103-111` |
|
||||
| Status | Resolved |
|
||||
|
||||
**Description:** `DriverCommandBase` documents that `FlushLogging()` must be called in a
|
||||
`finally` block to flush any buffered Serilog output before the process exits (see its XML
|
||||
`<summary>` on `FlushLogging`). None of the five TwinCAT CLI commands called it. The sibling
|
||||
`AbCip.Cli` correctly calls `FlushLogging()` in each command's `finally`; TwinCAT, Modbus,
|
||||
S7, AbLegacy, and FOCAS CLIs all omit it. The impact is that any `--verbose` debug lines
|
||||
buffered by Serilog's default asynchronous sink may be lost on process exit — a diagnostic
|
||||
CLI that drops diagnostic output on crash is self-defeating.
|
||||
|
||||
**Recommendation:** Add `FlushLogging()` as the last statement in every command's outer
|
||||
`finally` block, after `ShutdownAsync` (mirroring the AbCip pattern).
|
||||
|
||||
**Resolution:** Added `FlushLogging()` as the last call in the `finally` block of every
|
||||
`ExecuteAsync` in `BrowseCommand`, `ProbeCommand`, `ReadCommand`, `WriteCommand`, and
|
||||
`SubscribeCommand`. No test change needed (the call is not unit-testable without a real ADS
|
||||
router and a real Serilog sink; the fix is verified structurally at build time). The systemic
|
||||
omission in the Modbus/S7/AbLegacy/FOCAS sibling CLIs is out of this module's scope and left
|
||||
for their respective re-reviews. Date: 2026-06-19. SHA: blank (not committed).
|
||||
|
||||
Reference in New Issue
Block a user