Skip to content

Commit 5ca1c7f

Browse files
committed
feat(diagnostics): add conditional trace writes
1 parent 07a7224 commit 5ca1c7f

7 files changed

Lines changed: 88 additions & 16 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
## Non-negotiable rules
1010

1111
1. **Zero errors, zero warnings** before any commit. `cmake --build build --parallel 4` must be clean.
12-
2. **No test-count regression.** `scripts/run_component_tests.sh build` must show no failures. The verified baseline is 12,672 tests across 36 component executables and one integration executable; this floor should be raised as new tests are added and lowered only with an explicit, documented reason.
12+
2. **No test-count regression.** `scripts/run_component_tests.sh build` must show no failures. The verified baseline is 12,675 tests across 36 component executables and one integration executable; this floor should be raised as new tests are added and lowered only with an explicit, documented reason.
1313
3. **Push only to `feature/work`.** Never push to `develop` or `master`, and never create tags, without explicit per-action user approval.
1414
4. **SPDX header on every project source/header**`// SPDX-License-Identifier: MIT` + copyright + .NET attribution. Vendored sources retain their upstream headers; Markdown uses an HTML SPDX comment where one is present.
1515
5. **Property naming:** always `getXxxProperty()` / `setXxxProperty()`. Exception: indexers

NEXT.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
# NEXT.md
55

66
*Last verified: 2026-07-25. Branch: `feature/work`. The P0 component-boundary
7-
repair, three P1 parity repairs, P1 portability revalidation, and nineteen bounded
7+
repair, three P1 parity repairs, P1 portability revalidation, and twenty bounded
88
P2 API slices are complete: 41 physical modules, 90 production dependency
9-
edges, and 12,672 tests across 37 executables.*
9+
edges, and 12,675 tests across 37 executables.*
1010

1111
This is the cold-start handoff for the next working session. Keep it focused
1212
on verified facts, remaining bounded work, and commands needed to resume.
@@ -28,7 +28,7 @@ Historical session detail belongs in git history and `plan.sqlite3`.
2828
- The ten-job selective consumer matrix, including a direct
2929
`Collections.Blocking` consumer, is green. Text.Json retains its target
3030
absence and negative include-leakage assertions.
31-
- The full native baseline is a warning-free build with 12,672 passing tests
31+
- The full native baseline is a warning-free build with 12,675 passing tests
3232
across 36 component executables and one integration executable.
3333
- `TaskT<TResult>::ContinueWith` now supports both action and result-producing
3434
callbacks. It runs inline on completion; `NotOn*` and `OnlyOn*` filter the
@@ -77,6 +77,9 @@ Historical session detail belongs in git history and `plan.sqlite3`.
7777
- `UTF7Encoding` implements RFC 2152 modified-Base64 conversion for BMP and
7878
astral Unicode, including optional direct characters and U+FFFD recovery for
7979
malformed shifts. UTF-7 remains obsolete and unsuitable for new protocols.
80+
- `Trace::WriteIf` and `Trace::WriteLineIf` now conditionally preserve the
81+
existing stderr write/newline behavior; category and listener surfaces stay
82+
intentionally deferred.
8083
- MinGW-w64 GCC 14-win32/CMake 3.31.6 and Emscripten 5.0.7/CMake 3.31.6 both
8184
compile the post-modular `All` graph and selective `Text.Json` libraries.
8285
This is compile-only evidence: cross tests were deliberately disabled.
@@ -85,7 +88,7 @@ Historical session detail belongs in git history and `plan.sqlite3`.
8588
ASan/LSan ownership scenarios, including 100 continuation teardowns, pass.
8689

8790
The local `plan.sqlite3` snapshot contains 16,201 classified `task` rows and
88-
1,761 completed tickets. Ticket #1737 records the completed P0 split, tickets
91+
1,762 completed tickets. Ticket #1737 records the completed P0 split, tickets
8992
#1738/#1739 the MemoryStream and generic-continuation repairs, ticket #1740 the
9093
XML whitespace repair, #1741 the completed cross-build revalidation and
9194
`WebProxy` portability fix, #1742 focused sanitizer evidence, and #1743 the
@@ -99,8 +102,8 @@ for its equality-based item mutations, #1754 for its equality-based range
99102
queries, #1755 for its comparer-aware binary search, #1756 for its default
100103
range sort, #1757 for `BigInteger` bitwise operators, #1758 for signed
101104
`BigInteger` shifts, #1759 for byte-vector conversion, and #1760 for the
102-
`ImmutableList<T>` Builder core, and #1761 for RFC 2152 UTF-7; it is
103-
git-ignored and is not part of a fresh clone.
105+
`ImmutableList<T>` Builder core, #1761 for RFC 2152 UTF-7, and #1762 for
106+
conditional Trace writes; it is git-ignored and is not part of a fresh clone.
104107

105108
## P0 completion: restore Collections isolation
106109

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ collector, or the complete .NET platform.
77

88
The repository currently builds as 41 independently selectable CMake
99
components. The verified Linux baseline on 2026-07-25 is a warning-free build
10-
with **12,672 passing tests across 37 test executables**.
10+
with **12,675 passing tests across 37 test executables**.
1111

1212
## What is included
1313

@@ -181,7 +181,7 @@ Other platform evidence is narrower:
181181

182182
| Platform/toolchain | Verified scope |
183183
|---|---|
184-
| Linux/GCC | Current full component build and all 12,672 tests. |
184+
| Linux/GCC | Current full component build and all 12,675 tests. |
185185
| Windows/MinGW | MinGW-w64 GCC 14-win32/CMake 3.31.6 compiled the post-component `All` and selective `Text.Json` library graphs under ticket #1741. GoogleTest was not cross-built and repository CI remains Ubuntu-only. |
186186
| Emscripten | Emscripten 5.0.7/CMake 3.31.6 compiled the post-component `All` and selective `Text.Json` library graphs under ticket #1741. Tests were not cross-built or run, and some runtime APIs deliberately throw `PlatformNotSupportedException`. |
187187
| macOS/Apple Clang | Real downstream Xcode 15.4 builds drove portability fixes on 2026-07-20; this repository has no macOS job or recorded full standalone test baseline. |

docs/CMakeComponents.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ are named `SharpRuntimeTests_<Component>`; genuinely cross-module scenarios
131131
are in `SharpRuntimeIntegrationTests`. CTest also discovers every individual
132132
GoogleTest case.
133133

134-
The verified 2026-07-25 `All` baseline contains 12,672 tests across 36
134+
The verified 2026-07-25 `All` baseline contains 12,675 tests across 36
135135
component executables and one integration executable.
136136

137137
## Boundary validation and CI

modules/diagnostics/include/System/Diagnostics/Trace.hpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ namespace System::Diagnostics {
1414
* Partial C++ counterpart of .NET System.Diagnostics.Trace.
1515
*
1616
* @note Status: Partial — writes to std::cerr; no TraceListeners/TraceListenerCollection,
17-
* no CorrelationManager, no Refreshing event, no WriteIf/WriteLineIf family, no
18-
* category-suffixed Write/WriteLine overloads, and no object-typed Write/WriteLine
17+
* no CorrelationManager, no Refreshing event, no category-suffixed Write/WriteLine
18+
* overloads, and no object-typed Write/WriteLine
1919
* overloads. Real .NET's Trace and Debug share the same underlying static IndentLevel
2020
* state (both delegate to an internal TraceInternal class); this port keeps them as
2121
* separate, independently-tracked indent levels since Debug's provider-hook design isn't
@@ -79,6 +79,20 @@ namespace System::Diagnostics {
7979
/** @brief Writes a blank line to stderr. */
8080
static void WriteLine() { std::cerr << '\n'; }
8181

82+
/** @brief Writes @p message to stderr only when @p condition is true. */
83+
static void WriteIf(bool condition, const std::string& message) {
84+
if (condition) {
85+
Write(message);
86+
}
87+
}
88+
89+
/** @brief Writes @p message and a newline to stderr only when @p condition is true. */
90+
static void WriteLineIf(bool condition, const std::string& message) {
91+
if (condition) {
92+
WriteLine(message);
93+
}
94+
}
95+
8296
/** @brief Writes an informational @p message prefixed with [Info]. */
8397
static void TraceInformation(const std::string& message) {
8498
std::cerr << "[Info] " << message << '\n';
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright (c) Robert Vokac and contributors
3+
// Portions based on .NET runtime API (MIT License, Copyright .NET Foundation and Contributors)
4+
#include <gtest/gtest.h>
5+
6+
#include <iostream>
7+
#include <sstream>
8+
9+
#include "System/Diagnostics/Trace.hpp"
10+
11+
using System::Diagnostics::Trace;
12+
13+
namespace {
14+
class CerrCapture final {
15+
std::streambuf* previous_;
16+
std::ostringstream captured_;
17+
18+
public:
19+
CerrCapture() : previous_(std::cerr.rdbuf(captured_.rdbuf())) {}
20+
~CerrCapture() { std::cerr.rdbuf(previous_); }
21+
22+
[[nodiscard]] std::string getCaptured() const { return captured_.str(); }
23+
};
24+
} // namespace
25+
26+
TEST(TraceConditionalWriteTest, FalseConditionsDoNotWrite) {
27+
CerrCapture capture;
28+
29+
Trace::WriteIf(false, "hidden");
30+
Trace::WriteLineIf(false, "also hidden");
31+
Trace::Flush();
32+
33+
EXPECT_TRUE(capture.getCaptured().empty());
34+
}
35+
36+
TEST(TraceConditionalWriteTest, WriteIfWritesWithoutTrailingNewline) {
37+
CerrCapture capture;
38+
39+
Trace::WriteIf(true, "visible");
40+
Trace::Flush();
41+
42+
EXPECT_EQ(capture.getCaptured(), "visible");
43+
}
44+
45+
TEST(TraceConditionalWriteTest, WriteLineIfWritesWithTrailingNewline) {
46+
CerrCapture capture;
47+
48+
Trace::WriteLineIf(true, "visible");
49+
Trace::Flush();
50+
51+
EXPECT_EQ(capture.getCaptured(), "visible\n");
52+
}

plan.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Sharp Runtime plan
22

33
*Last verified: 2026-07-25 — 41 physical components, 90 direct production
4-
dependency edges, a clean native build, 12,672 passing tests across 37
4+
dependency edges, a clean native build, 12,675 passing tests across 37
55
executables, and a green ten-job selective matrix.*
66

77
Sharp Runtime is in a consumer-driven expansion phase. The original type
@@ -32,7 +32,7 @@ was never created. Neither file should be linked as current documentation.
3232
### Code and validation
3333

3434
- Native Linux/GCC build: zero errors and zero warnings.
35-
- Tests: 12,672 passing across 36 component binaries plus one integration
35+
- Tests: 12,675 passing across 36 component binaries plus one integration
3636
binary.
3737
- Component graph: 41 physical modules and 90 direct production edges.
3838
- Boundary validator: no cycles, duplicate public include paths, orphan
@@ -52,7 +52,7 @@ The 2026-07-25 local snapshot contains:
5252
| Table | State |
5353
|---|---|
5454
| `task` | 16,201 rows: 1,082 `ported`, 140 `ignore`, 14,979 legacy `ignored`; no unclassified or `tobedecided` rows |
55-
| `ticket` | 1,761 rows, all `done`; no `todo`, `doing`, `blocked`, or `needs_user` rows |
55+
| `ticket` | 1,762 rows, all `done`; no `todo`, `doing`, `blocked`, or `needs_user` rows |
5656

5757
Because `plan.sqlite3` is git-ignored, these counts describe the maintainer
5858
snapshot, not data shipped in a fresh clone.
@@ -148,6 +148,9 @@ assertion without an explicit architecture decision.
148148
shifts over UTF-16BE units, optional-direct-character control, astral
149149
Unicode support, and U+FFFD recovery for malformed input. It remains
150150
obsolete and unsuitable for new protocols.
151+
- Added conditional `Trace::WriteIf` and `Trace::WriteLineIf` under ticket
152+
#1762. They suppress output when false and retain the existing stderr
153+
write/newline behavior when true.
151154
- Added consumer-driven coverage across core, collections, IO, networking,
152155
threading/tasks, text/JSON, XML, numerics, globalization, and cryptographic
153156
hashing/random APIs.
@@ -208,7 +211,7 @@ The first consumer-driven ports after modularization added:
208211
- XML schema exception types.
209212

210213
The verified test baseline grew from 12,494 at the modularization checkpoint
211-
to 12,672.
214+
to 12,675.
212215

213216
## Candidate roadmap
214217

0 commit comments

Comments
 (0)