fix(scheduler): close core_clock.c isolation-test coverage gap (bug-1827)
core_clock.c joined the mechanically-enforced isolation archive (sched_core_isolation_lib) and its own doc comment claimed coverage by the forbidden-headers/forbidden-symbols text scans, but was actually absent from both -- only the nm(1) undefined-symbol layer covered it, which cannot catch a forbidden #include resolving to no undefined symbol (a macro-only header). Added XCE_CORE_CLOCK_C_PATH (meson.build, mirroring the existing per-file path macros) and extended both test_core_never_includes_forbidden_headers() and test_core_never_calls_forbidden_symbols() to scan core_clock.c. It remains excluded only from the wall-clock scan, for its one sanctioned clock_gettime() call. TDD: confirmed RED by temporarily inserting a forbidden #include into core_clock.c (84/85, correctly attributed failure), reverted (byte-identical to HEAD), reconfirmed GREEN (85/85). No live violation existed -- this closes a coverage gap in the mechanism itself. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
parent
a6657d05a7
commit
4db992b5e4
3 changed files with 43 additions and 12 deletions
|
|
@ -231,6 +231,9 @@ sched_core_isolation_test = executable(
|
|||
'-DXCE_CORE_SESSION_C_PATH="'
|
||||
+ (meson.current_source_dir() / '..' / 'src' / 'core_session.c')
|
||||
+ '"',
|
||||
'-DXCE_CORE_CLOCK_C_PATH="'
|
||||
+ (meson.current_source_dir() / '..' / 'src' / 'core_clock.c')
|
||||
+ '"',
|
||||
'-DXCE_CORE_LIB_PATH="'
|
||||
+ sched_core_isolation_lib.full_path()
|
||||
+ '"'],
|
||||
|
|
|
|||
|
|
@ -22,18 +22,32 @@
|
|||
* incorrectly fail. It has no legitimate reason to reference any
|
||||
* networking/API symbol, so it fully participates in layer 2.
|
||||
*
|
||||
* CORRECTED 2026-09-19 (bug-1827, /xce-audit-invariants scheduler): the
|
||||
* paragraph above was accurate about layer 2 but the claim was narrower
|
||||
* than what layer 1 actually enforced -- core_clock.c was excluded from
|
||||
* ALL of layer 1's text scans (forbidden-headers, forbidden-symbols, AND
|
||||
* wall-clock), not only the wall-clock one. The forbidden-headers/
|
||||
* forbidden-symbols scans have no legitimate reason to exempt
|
||||
* core_clock.c (it has no legitimate reason to include a networking/API
|
||||
* header or reference a networking/API symbol, same as its siblings), and
|
||||
* the nm(1) layer alone cannot catch a forbidden #include that resolves to
|
||||
* no undefined symbol (a macro-only or inline-only header). core_clock.c
|
||||
* now fully participates in the forbidden-headers and forbidden-symbols
|
||||
* scans too -- it remains excluded ONLY from the wall-clock scan, for the
|
||||
* reason stated above.
|
||||
*
|
||||
* Two layers, same genre as test_picker_core_loop_boundary.c /
|
||||
* test_picker_pendreason_factory_audit.c (source-text scans of the real,
|
||||
* current on-disk files, not a frozen snapshot):
|
||||
*
|
||||
* 1. Source-text scan of core.h/core.c/core_events.c/core_session.c: no
|
||||
* #include of client.h, netio.h, xceapi.h, delay.h, idgen.h, or
|
||||
* xce/cluster.h (the "Allowed Dependencies" list in design.md names
|
||||
* exactly these as forbidden); no call-site substring matching a
|
||||
* symbol exported only by those libraries; no wall-clock call
|
||||
* (time()/clock_gettime()/gettimeofday()) anywhere in core.c,
|
||||
* core_events.c, or core_session.c (core_clock.c excepted -- see
|
||||
* above).
|
||||
* 1. Source-text scan of core.h/core.c/core_events.c/core_session.c/
|
||||
* core_clock.c: no #include of client.h, netio.h, xceapi.h, delay.h,
|
||||
* idgen.h, or xce/cluster.h (the "Allowed Dependencies" list in
|
||||
* design.md names exactly these as forbidden); no call-site substring
|
||||
* matching a symbol exported only by those libraries; no wall-clock
|
||||
* call (time()/clock_gettime()/gettimeofday()) anywhere in core.c,
|
||||
* core_events.c, or core_session.c (core_clock.c excepted from this
|
||||
* one sub-check only -- see above).
|
||||
*
|
||||
* 2. The literal build-time/link-time proof the Observable asks for,
|
||||
* not achievable by a text scan alone: core.c/core_events.c/
|
||||
|
|
@ -80,6 +94,10 @@
|
|||
#error \
|
||||
"XCE_CORE_SESSION_C_PATH must be defined by meson.build to core_session.c's absolute path"
|
||||
#endif
|
||||
#ifndef XCE_CORE_CLOCK_C_PATH
|
||||
#error \
|
||||
"XCE_CORE_CLOCK_C_PATH must be defined by meson.build to core_clock.c's absolute path"
|
||||
#endif
|
||||
#ifndef XCE_CORE_LIB_PATH
|
||||
#error \
|
||||
"XCE_CORE_LIB_PATH must be defined by meson.build to the absolute path of core.c's isolated static_library() archive"
|
||||
|
|
@ -177,16 +195,19 @@ static void test_core_source_paths_are_readable(void)
|
|||
char* c = read_whole_file(XCE_CORE_C_PATH);
|
||||
char* ce = read_whole_file(XCE_CORE_EVENTS_C_PATH);
|
||||
char* cs = read_whole_file(XCE_CORE_SESSION_C_PATH);
|
||||
char* cc = read_whole_file(XCE_CORE_CLOCK_C_PATH);
|
||||
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(h, XCE_CORE_H_PATH);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(c, XCE_CORE_C_PATH);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(ce, XCE_CORE_EVENTS_C_PATH);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(cs, XCE_CORE_SESSION_C_PATH);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(cc, XCE_CORE_CLOCK_C_PATH);
|
||||
|
||||
free(h);
|
||||
free(c);
|
||||
free(ce);
|
||||
free(cs);
|
||||
free(cc);
|
||||
}
|
||||
|
||||
/* Scans one file's text for every FORBIDDEN_INCLUDES entry, tagging each
|
||||
|
|
@ -212,21 +233,25 @@ static void test_core_never_includes_forbidden_headers(void)
|
|||
char* c = read_whole_file(XCE_CORE_C_PATH);
|
||||
char* ce = read_whole_file(XCE_CORE_EVENTS_C_PATH);
|
||||
char* cs = read_whole_file(XCE_CORE_SESSION_C_PATH);
|
||||
char* cc = read_whole_file(XCE_CORE_CLOCK_C_PATH);
|
||||
|
||||
TEST_ASSERT_NOT_NULL(h);
|
||||
TEST_ASSERT_NOT_NULL(c);
|
||||
TEST_ASSERT_NOT_NULL(ce);
|
||||
TEST_ASSERT_NOT_NULL(cs);
|
||||
TEST_ASSERT_NOT_NULL(cc);
|
||||
|
||||
assert_no_forbidden_includes(h, "core.h");
|
||||
assert_no_forbidden_includes(c, "core.c");
|
||||
assert_no_forbidden_includes(ce, "core_events.c");
|
||||
assert_no_forbidden_includes(cs, "core_session.c");
|
||||
assert_no_forbidden_includes(cc, "core_clock.c");
|
||||
|
||||
free(h);
|
||||
free(c);
|
||||
free(ce);
|
||||
free(cs);
|
||||
free(cc);
|
||||
}
|
||||
|
||||
/* Shared by test_core_never_calls_forbidden_symbols() -- see
|
||||
|
|
@ -252,21 +277,25 @@ static void test_core_never_calls_forbidden_symbols(void)
|
|||
char* c = read_whole_file(XCE_CORE_C_PATH);
|
||||
char* ce = read_whole_file(XCE_CORE_EVENTS_C_PATH);
|
||||
char* cs = read_whole_file(XCE_CORE_SESSION_C_PATH);
|
||||
char* cc = read_whole_file(XCE_CORE_CLOCK_C_PATH);
|
||||
|
||||
TEST_ASSERT_NOT_NULL(h);
|
||||
TEST_ASSERT_NOT_NULL(c);
|
||||
TEST_ASSERT_NOT_NULL(ce);
|
||||
TEST_ASSERT_NOT_NULL(cs);
|
||||
TEST_ASSERT_NOT_NULL(cc);
|
||||
|
||||
assert_no_forbidden_symbols(h, "core.h");
|
||||
assert_no_forbidden_symbols(c, "core.c");
|
||||
assert_no_forbidden_symbols(ce, "core_events.c");
|
||||
assert_no_forbidden_symbols(cs, "core_session.c");
|
||||
assert_no_forbidden_symbols(cc, "core_clock.c");
|
||||
|
||||
free(h);
|
||||
free(c);
|
||||
free(ce);
|
||||
free(cs);
|
||||
free(cc);
|
||||
}
|
||||
|
||||
/* core_clock.c is deliberately NOT scanned here -- it is the one
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue