Skip to content

refactor(server, tests): improve error feedback, logging, and test infrastructure#436

Open
16bit-ykiko wants to merge 1 commit intomainfrom
improve-error-feedback-and-logging
Open

refactor(server, tests): improve error feedback, logging, and test infrastructure#436
16bit-ykiko wants to merge 1 commit intomainfrom
improve-error-feedback-and-logging

Conversation

@16bit-ykiko
Copy link
Copy Markdown
Member

@16bit-ykiko 16bit-ykiko commented Apr 23, 2026

Summary

  • Replace silent null returns with proper LSP errors (kota::fail) for feature requests on closed documents, failed compilations, invalid positions, and unresolvable hierarchy items
  • Add window/logMessage notifications for key failures (PCM/PCH build, no compile_commands.json, config warnings, worker pool errors) so integration tests can observe errors without reading server logs
  • Expand logging coverage: compile args lookup, compilation phases (invocation/target/BeginSourceFile/PCH errors), completion/signature help results, position mapping failures
  • Improve test infrastructure: conditional log dump on failure, yield-based workspace fixture with post-test cleanup, named timing constants, log message capture/assertion helpers
  • Unit test dedup: Tester::to_local_range() helper, remove unused code

Test plan

  • 551 unit tests pass
  • 124 integration tests pass
  • 2/2 smoke tests pass
  • pixi run format clean

🤖 Generated with Claude Code


View in Codesmith
Codesmith can help with this PR — just tag @codesmith or enable autofix.

  • Autofix CI and bot reviews

Summary by CodeRabbit

  • New Features

    • Enhanced server logging for compilation failures, configuration issues, and dependency problems.
    • Added explicit error reporting instead of silent failures for missing documents and closed sessions.
  • Bug Fixes

    • Improved error handling when documents close during compilation or feature queries.
    • Configuration loading now provides detailed warning messages when defaults are used.
  • Tests

    • Introduced shared timing constants for consistent test execution.
    • Enhanced test assertions to verify error conditions and log messages.

…frastructure

Replace silent null returns with proper LSP errors (kota::fail) for
feature requests on closed documents, failed compilations, invalid
positions, and unresolvable hierarchy items. Add client notifications
(window/logMessage) for key failures so integration tests can observe
errors without reading server logs. Expand logging coverage in
compilation pipeline (compile args, compilation phases, worker results).

Improve test infrastructure: conditional log dump on failure, yield-based
workspace fixture with post-test cleanup, named timing constants replacing
hardcoded sleeps, and log message capture/assertion helpers.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Walkthrough

The PR adds comprehensive warning and error logging throughout compilation and server layers, replaces silent failures (returning null) with explicit error propagation via kota::fail(), updates the test infrastructure to capture server log messages, consolidates timing constants across tests, and centralizes test helper functions.

Changes

Cohort / File(s) Summary
Compilation & Diagnostic Logging
src/compile/compilation.cpp, src/server/compiler.cpp
Added warning logs at early-failure paths in run_clang; added client-visible notifications when PCM/PCH builds fail and compilation fails; added debug logging for CDB-based compile args resolution.
Server Configuration & Initialization
src/server/config.h, src/server/config.cpp
Updated Config::load_from_workspace signature to accept optional std::string* warning output parameter; writes human-readable warnings when config fails to parse.
Master Server Request Handlers
src/server/master_server.cpp
Added LSP log notifications for config/init failures; replaced silent null returns with explicit kota::fail() error paths for "document/session not found" cases; updated hierarchy/workspace symbol endpoints to fail rather than return null when lookups fail.
Worker Logging
src/server/stateful_worker.cpp, src/server/stateless_worker.cpp
Added warning logs in with_ast when document/AST unavailable; adjusted completion and signature help logging to report item/signature counts.
Test Framework Configuration
tests/conftest.py
Converted workspace fixture to generator with post-test cleanup; updated client fixture teardown to enable verbose shutdown logging on test failure; stores pytest report objects per test.
Shared Test Timing Constants
tests/integration/utils/wait.py
Added module-level constants: MTIME_GRANULARITY, SETTLE_TIME, IDLE_TIMEOUT for standardized test timing.
Integration Tests Using Timing Constants
tests/integration/compilation/test_persistent_cache.py, test_staleness.py, tests/integration/features/test_server.py, tests/integration/lifecycle/test_file_operation.py, tests/integration/modules/test_modules.py, tests/integration/stress/test_rapid_edit.py
Replaced hardcoded sleep durations with shared timing constants; updated hover/feature expectations to raise "Document not open" exception instead of returning None.
Test Assertion & Client Utilities
tests/integration/utils/assertions.py, tests/integration/utils/client.py
Added has_log_message() and assert_no_log_errors() helpers; extended client to track server-sent window log messages via new log_messages list and notification handler.
Test Helper Consolidation
tests/unit/test/tester.h, tests/unit/feature/document_link_tests.cpp, tests/unit/feature/folding_range_tests.cpp
Added centralized Tester::to_local_range() helper in tester.h; updated unit tests to use centralized helper instead of local to_local_range implementations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PR #337: Refactors CompilationUnitRef::Self::run_clang function, which is directly touched by the new warning logs added in this PR for diagnostic/error paths.
  • PR #403: Extracts and defines Compiler/worker interfaces in src/server/compiler.cpp; this PR's logging and error-propagation changes are made within those forwarding paths and worker methods.
  • PR #435: Hardens PCH/PCM build handling in ensure_pch; this PR augments logging and client notifications around PCM/PCH build failures in the same code area.

Poem

🐰 Logs now bloom where silence once lived,
Errors no longer hide in the void,
Tests march in sync with constants true,
Helpers shake paws—one home, not two,
Progress whispers through warning calls! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: improvements to error feedback, logging, and test infrastructure across server and test code.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch improve-error-feedback-and-logging

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/server/config.cpp (1)

177-184: ⚠️ Potential issue | 🟡 Minor

Delay the warning until defaults are actually used.

Line 182 sets warning immediately after one config file fails. If a later standard location loads successfully, the caller still emits a stale “falling back to defaults” warning even though defaults were not used.

Suggested fix
 Config Config::load_from_workspace(llvm::StringRef workspace_root, std::string* warning) {
+    std::string invalid_config_path;
     if(!workspace_root.empty()) {
         for(auto* name: {"clice.toml", ".clice/config.toml"}) {
             auto config_path = path::join(workspace_root, name);
             if(!llvm::sys::fs::exists(config_path))
                 continue;
             if(auto config = load(config_path, workspace_root))
                 return std::move(*config);
             // Present but malformed: fall through to defaults, but surface
             // the situation clearly so users know their config wasn't applied.
             LOG_WARN("Falling back to default configuration because {} is invalid", config_path);
-            if(warning)
-                *warning = std::format("Configuration file {} is invalid, falling back to defaults",
-                                       config_path);
+            if(invalid_config_path.empty())
+                invalid_config_path = std::move(config_path);
         }
     }
 
     Config config;
     config.apply_defaults(workspace_root);
+    if(warning && !invalid_config_path.empty())
+        *warning = std::format("Configuration file {} is invalid, falling back to defaults",
+                               invalid_config_path);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/config.cpp` around lines 177 - 184, The code logs a warning and
sets *warning immediately when a single config_path load fails, which can
produce a stale "falling back to defaults" message even if a later standard
location succeeds; change the logic so the LOG_WARN and assignment to *warning
are NOT done here but instead only performed at the point where the function
actually decides to return the defaults (i.e., after all load attempts fail).
Concretely, remove the LOG_WARN(...) and the *warning = ... lines from the
failing-try block around load(config_path, workspace_root) and set that warning
(or a boolean that triggers it) in the final branch where the default
configuration is returned; reference symbols: load(), config_path,
workspace_root, warning, LOG_WARN.
🧹 Nitpick comments (5)
tests/integration/utils/wait.py (1)

13-13: MTIME_GRANULARITY = 1.1 is fine for ext4/APFS/NTFS but not FAT32/exFAT.

Most Linux/macOS/Windows dev filesystems have ≤1s mtime resolution, so 1.1s covers them with margin. FAT32/exFAT have 2s granularity; if any CI runner or tmp dir ever lands on such a filesystem, staleness-detection tests could flake. If that's plausible in this project's CI matrix, consider bumping to ~2.1s or detecting the FS; otherwise the current value is a reasonable default.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/utils/wait.py` at line 13, MTIME_GRANULARITY is set to 1.1
which can still flake on FAT32/exFAT (2s) filesystems; update the constant
MTIME_GRANULARITY in tests/integration/utils/wait.py to a safer default such as
2.1 to cover 2s-granularity filesystems, or implement a small runtime probe in
the module that detects the filesystem mtime resolution (e.g., create a temp
file, sleep short intervals and check mtime changes) and set MTIME_GRANULARITY
dynamically based on that probe so tests are robust across CI environments.
src/server/stateful_worker.cpp (1)

95-118: Potential log noise on every query to an in-progress/broken document.

with_ast now logs a warning for both "document not found" and "AST not available". Since feature handlers (Hover, SemanticTokens, InlayHints, FoldingRange, DocumentSymbol, DocumentLink) all funnel through here, a client firing multiple feature requests against a path whose compilation hasn't completed (or failed non-fatally) will produce one warn per request per feature. Consider downgrading to LOG_DEBUG/LOG_TRACE, or rate-limiting by caching the last-warned (path, state) — the error has already been surfaced to the client via kota::fail/window/logMessage at the compile layer.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/stateful_worker.cpp` around lines 95 - 118, with_ast currently
emits LOG_WARN in two benign cases ("document not found" and "AST not
available"), causing noisy warnings for every feature request (Hover,
SemanticTokens, InlayHints, FoldingRange, DocumentSymbol, DocumentLink) while a
document is compiling or has non-fatal errors; change those LOG_WARN calls in
with_ast to a lower-severity level (e.g., LOG_DEBUG or LOG_TRACE) or implement
simple rate-limiting by tracking the last warned state per path (keyed by path +
state like "not_found" or "ast_unavailable") and only log again after a
cooldown; update the messages where LOG_WARN("with_ast: document not found: {}",
path.str()) and LOG_WARN("with_ast: AST not available for {}", path.str())
appear, and ensure the doc lifecycle helpers (touch_lru, doc->ast_ready,
doc->unit.completed(), doc->unit.fatal_error()) remain unchanged.
tests/integration/lifecycle/test_file_operation.py (1)

60-63: Tighten the pytest.raises exception type.

Matching on the base Exception class will also swallow unrelated errors (e.g. TimeoutError, connection drops) as long as their message happens to contain "Document not open". If the LSP client raises a specific exception type (e.g. an lsprotocol/JSON-RPC response error), prefer matching that class so a regression that surfaces a different failure still fails the test.

Illustrative refactor
-    with pytest.raises(Exception, match="Document not open"):
+    with pytest.raises(JsonRpcError, match="Document not open"):  # or whichever type client raises
         await client.text_document_hover_async(
             HoverParams(text_document=doc(uri), position=Position(line=0, character=0))
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/lifecycle/test_file_operation.py` around lines 60 - 63, The
test currently uses pytest.raises(Exception, ...) which is too broad; change the
first argument to the specific exception class raised by the LSP client when the
document is not open (the concrete JSON-RPC/LS client error type your client
emits — e.g., JSONRPCError, ResponseError, RpcError, or the lsprotocol-specific
exception) so the assertion is precise; keep the same call to
client.text_document_hover_async (and the match="Document not open") but replace
Exception with that concrete class in the pytest.raises invocation to avoid
swallowing unrelated errors.
tests/conftest.py (2)

96-103: Pre- and post-test .clice cleanup is duplicated.

The fixture removes clice_dir both before yield (lines 97-99) and after (lines 102-103). The post-test rmtree makes the pre-test one redundant in the common case, though the pre-test cleanup does still guard against stale state from a crashed prior run. Not a bug — flagging for awareness; feel free to keep both as belt-and-suspenders.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/conftest.py` around lines 96 - 103, Duplicate cleanup of the .clice
directory occurs around the fixture using clice_dir and yield; either remove the
redundant pre-test or post-test rmtree or extract a small helper (e.g., def
_remove_clice(path): ...) and call it both before yield and after to avoid
duplicated code while preserving the crash-guard behavior; update the fixture to
call the helper or remove one of the rmtree blocks and add a short comment
explaining the remaining cleanup choice.

77-103: Update workspace fixture return type hint.

Now that workspace is a generator fixture, the -> Path | None annotation is inaccurate. Consider Iterator[Path | None] (or Generator[Path | None, None, None]) for clarity.

Proposed change
-from pathlib import Path
+from collections.abc import Iterator
+from pathlib import Path
@@
 `@pytest.fixture`
-def workspace(request: pytest.FixtureRequest, test_data_dir: Path) -> Path | None:
+def workspace(
+    request: pytest.FixtureRequest, test_data_dir: Path
+) -> Iterator[Path | None]:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/conftest.py` around lines 77 - 103, The workspace fixture is a
generator yielding Path|None but is annotated as returning Path|None; update its
type hint to an iterator/generator type (e.g., Iterator[Path | None] or
Generator[Path | None, None, None]) so the signature matches its generator
behavior; modify the annotation on the workspace function (which contains calls
to generate_cdb and uses the clice_dir variable) accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/server/compiler.cpp`:
- Around line 836-849: The current forward_query treats any false from
ensure_compiled(session) as a compilation failure and returns an LSP error,
which misclassifies generation-mismatch/concurrent edits; change the logic so
that when ensure_compiled(session) returns false you re-check the live session
state (find sessions via sessions.find(path_id) and inspect
sit->second.ast_dirty) before emitting an error: if the session was closed, keep
the fail("Document was closed during compilation") path; if the session is still
present but ast_dirty is true (concurrent edit), return the benign
serde_raw{"null"} result instead of a compilation failure; alternatively, have
ensure_compiled return a richer status (e.g., enum {Ok, Dirty, Closed, Error})
and switch on that in forward_query to map Dirty->serde_raw{"null"},
Closed->fail(...), and Error->fail("Compilation failed").

In `@tests/conftest.py`:
- Around line 206-209: The teardown prints client log messages but directly
accesses c.log_messages which can raise AttributeError for clients missing that
attribute (e.g., older fixtures or partially-initialized CliceClient after
start_io failure); change the access to use getattr(c, "log_messages", None) and
only iterate/print when the result is not None to mirror the existing getattr(c,
"_server", None) defensive pattern used by _shutdown_client / shutdown_client.

In `@tests/integration/compilation/test_staleness.py`:
- Line 24: The test references SETTLE_TIME but the top import only brings in
MTIME_GRANULARITY and wait_for_recompile; add SETTLE_TIME to the import from
tests.integration.utils.wait so SETTLE_TIME, MTIME_GRANULARITY, and
wait_for_recompile are all imported, then run the test(s) that use SETTLE_TIME
(around the staleness test that uses SETTLE_TIME at lines ~127-133) to verify
the NameError is resolved.

---

Outside diff comments:
In `@src/server/config.cpp`:
- Around line 177-184: The code logs a warning and sets *warning immediately
when a single config_path load fails, which can produce a stale "falling back to
defaults" message even if a later standard location succeeds; change the logic
so the LOG_WARN and assignment to *warning are NOT done here but instead only
performed at the point where the function actually decides to return the
defaults (i.e., after all load attempts fail). Concretely, remove the
LOG_WARN(...) and the *warning = ... lines from the failing-try block around
load(config_path, workspace_root) and set that warning (or a boolean that
triggers it) in the final branch where the default configuration is returned;
reference symbols: load(), config_path, workspace_root, warning, LOG_WARN.

---

Nitpick comments:
In `@src/server/stateful_worker.cpp`:
- Around line 95-118: with_ast currently emits LOG_WARN in two benign cases
("document not found" and "AST not available"), causing noisy warnings for every
feature request (Hover, SemanticTokens, InlayHints, FoldingRange,
DocumentSymbol, DocumentLink) while a document is compiling or has non-fatal
errors; change those LOG_WARN calls in with_ast to a lower-severity level (e.g.,
LOG_DEBUG or LOG_TRACE) or implement simple rate-limiting by tracking the last
warned state per path (keyed by path + state like "not_found" or
"ast_unavailable") and only log again after a cooldown; update the messages
where LOG_WARN("with_ast: document not found: {}", path.str()) and
LOG_WARN("with_ast: AST not available for {}", path.str()) appear, and ensure
the doc lifecycle helpers (touch_lru, doc->ast_ready, doc->unit.completed(),
doc->unit.fatal_error()) remain unchanged.

In `@tests/conftest.py`:
- Around line 96-103: Duplicate cleanup of the .clice directory occurs around
the fixture using clice_dir and yield; either remove the redundant pre-test or
post-test rmtree or extract a small helper (e.g., def _remove_clice(path): ...)
and call it both before yield and after to avoid duplicated code while
preserving the crash-guard behavior; update the fixture to call the helper or
remove one of the rmtree blocks and add a short comment explaining the remaining
cleanup choice.
- Around line 77-103: The workspace fixture is a generator yielding Path|None
but is annotated as returning Path|None; update its type hint to an
iterator/generator type (e.g., Iterator[Path | None] or Generator[Path | None,
None, None]) so the signature matches its generator behavior; modify the
annotation on the workspace function (which contains calls to generate_cdb and
uses the clice_dir variable) accordingly.

In `@tests/integration/lifecycle/test_file_operation.py`:
- Around line 60-63: The test currently uses pytest.raises(Exception, ...) which
is too broad; change the first argument to the specific exception class raised
by the LSP client when the document is not open (the concrete JSON-RPC/LS client
error type your client emits — e.g., JSONRPCError, ResponseError, RpcError, or
the lsprotocol-specific exception) so the assertion is precise; keep the same
call to client.text_document_hover_async (and the match="Document not open") but
replace Exception with that concrete class in the pytest.raises invocation to
avoid swallowing unrelated errors.

In `@tests/integration/utils/wait.py`:
- Line 13: MTIME_GRANULARITY is set to 1.1 which can still flake on FAT32/exFAT
(2s) filesystems; update the constant MTIME_GRANULARITY in
tests/integration/utils/wait.py to a safer default such as 2.1 to cover
2s-granularity filesystems, or implement a small runtime probe in the module
that detects the filesystem mtime resolution (e.g., create a temp file, sleep
short intervals and check mtime changes) and set MTIME_GRANULARITY dynamically
based on that probe so tests are robust across CI environments.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 804a332c-b653-4f96-8672-5d298748ab15

📥 Commits

Reviewing files that changed from the base of the PR and between 939ab6d and 066e10c.

📒 Files selected for processing (20)
  • src/compile/compilation.cpp
  • src/server/compiler.cpp
  • src/server/config.cpp
  • src/server/config.h
  • src/server/master_server.cpp
  • src/server/stateful_worker.cpp
  • src/server/stateless_worker.cpp
  • tests/conftest.py
  • tests/integration/compilation/test_persistent_cache.py
  • tests/integration/compilation/test_staleness.py
  • tests/integration/features/test_server.py
  • tests/integration/lifecycle/test_file_operation.py
  • tests/integration/modules/test_modules.py
  • tests/integration/stress/test_rapid_edit.py
  • tests/integration/utils/assertions.py
  • tests/integration/utils/client.py
  • tests/integration/utils/wait.py
  • tests/unit/feature/document_link_tests.cpp
  • tests/unit/feature/folding_range_tests.cpp
  • tests/unit/test/tester.h
💤 Files with no reviewable changes (1)
  • tests/unit/feature/document_link_tests.cpp

Comment thread src/server/compiler.cpp
Comment on lines 836 to 849
if(!co_await ensure_compiled(session)) {
co_return serde_raw{"null"};
LOG_WARN("forward_query: compilation failed for {}", path);
co_await kota::fail("Compilation failed");
}

auto sit = sessions.find(path_id);
if(sit == sessions.end() || sit->second.ast_dirty) {
if(sit == sessions.end()) {
LOG_WARN("forward_query: session lost after compile for {}", path);
co_await kota::fail("Document was closed during compilation");
}
if(sit->second.ast_dirty) {
LOG_DEBUG("forward_query: still dirty after compile for {} (concurrent edit)", path);
co_return serde_raw{"null"};
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don’t report concurrent edits as compilation failures.

ensure_compiled() returns false when the session remains dirty, including the generation-mismatch path for edits during compilation. Because Line 838 fails before the Line 846 dirty check, that branch is effectively unreachable for this case and normal rapid edits can surface as "Compilation failed".

Return a richer compile status, or re-check the current session state before converting the result into an LSP error.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/compiler.cpp` around lines 836 - 849, The current forward_query
treats any false from ensure_compiled(session) as a compilation failure and
returns an LSP error, which misclassifies generation-mismatch/concurrent edits;
change the logic so that when ensure_compiled(session) returns false you
re-check the live session state (find sessions via sessions.find(path_id) and
inspect sit->second.ast_dirty) before emitting an error: if the session was
closed, keep the fail("Document was closed during compilation") path; if the
session is still present but ast_dirty is true (concurrent edit), return the
benign serde_raw{"null"} result instead of a compilation failure; alternatively,
have ensure_compiled return a richer status (e.g., enum {Ok, Dirty, Closed,
Error}) and switch on that in forward_query to map Dirty->serde_raw{"null"},
Closed->fail(...), and Error->fail("Compilation failed").

Comment thread tests/conftest.py
Comment on lines +206 to +209
if verbose and c.log_messages:
for msg in c.log_messages:
level = {1: "ERROR", 2: "WARN", 3: "INFO", 4: "LOG"}.get(msg.type, "?")
print(f"[logMessage/{level}] {msg.message}", flush=True)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard against missing log_messages attribute.

_shutdown_client is also exposed as the public shutdown_client alias (line 220) for multi-session tests that may construct CliceClient instances differently. If a client object ever lacks log_messages (e.g., an older fixture, a partially-initialized client after start_io failure), this line will raise AttributeError during teardown and mask the original failure. Consider getattr(c, "log_messages", None) for defensive parity with the existing getattr(c, "_server", None) pattern above.

Proposed change
-    if verbose and c.log_messages:
-        for msg in c.log_messages:
+    log_messages = getattr(c, "log_messages", None)
+    if verbose and log_messages:
+        for msg in log_messages:
             level = {1: "ERROR", 2: "WARN", 3: "INFO", 4: "LOG"}.get(msg.type, "?")
             print(f"[logMessage/{level}] {msg.message}", flush=True)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/conftest.py` around lines 206 - 209, The teardown prints client log
messages but directly accesses c.log_messages which can raise AttributeError for
clients missing that attribute (e.g., older fixtures or partially-initialized
CliceClient after start_io failure); change the access to use getattr(c,
"log_messages", None) and only iterate/print when the result is not None to
mirror the existing getattr(c, "_server", None) defensive pattern used by
_shutdown_client / shutdown_client.


from tests.integration.utils import write_cdb, doc
from tests.integration.utils.wait import wait_for_recompile
from tests.integration.utils.wait import MTIME_GRANULARITY, wait_for_recompile
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Import SETTLE_TIME before using it.

Line 133 references SETTLE_TIME, but Line 24 only imports MTIME_GRANULARITY and wait_for_recompile, so this test currently fails with NameError.

Proposed fix
-from tests.integration.utils.wait import MTIME_GRANULARITY, wait_for_recompile
+from tests.integration.utils.wait import MTIME_GRANULARITY, SETTLE_TIME, wait_for_recompile

Also applies to: 127-133

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/compilation/test_staleness.py` at line 24, The test
references SETTLE_TIME but the top import only brings in MTIME_GRANULARITY and
wait_for_recompile; add SETTLE_TIME to the import from
tests.integration.utils.wait so SETTLE_TIME, MTIME_GRANULARITY, and
wait_for_recompile are all imported, then run the test(s) that use SETTLE_TIME
(around the staleness test that uses SETTLE_TIME at lines ~127-133) to verify
the NameError is resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant