feat(scheduler-sim-diagnostics): promote byte-unit formatting to shared lib (task 7)
Adds Requirement 6 (Human-Readable Units for Byte-Valued Limit Amounts) to the spec: requirements, design, research, and tasks 7-10. Task 7 (Foundation): promotes the REPL's byte-unit scaling algorithm and byte-valued-resource classifier into src/lib/utils.c/utils.h (xce_format_bytes_human, xce_is_bytes_valued_resource), alongside a new display-mode-aware composer (xce_format_units_value, xce_units_mode_t) -- following the fmt_jobid()/fmt_jobid_ex() precedent. repl_fmt.c's scheduler-only functions become one-line delegating wrappers. repl_info.c's repl_format_numeric_resource_value() (shared by info worker/info resource, not just the upcoming info limit) is retyped to delegate to the new shared composer via a small translate_units_mode() bridge, so every consumer benefits from one implementation going forward. No existing symbol's signature changed; only new symbols were added. Confirmed behavior-preserving: full scheduler suite 85/85 unchanged, including info worker/info resource's own regression tests. One narrow, untested, out-of-requirement-scope corner case found and documented (swp's RAW/BOTH mode rendering under the new single-value composer interface) -- logged in tasks.md's Implementation Notes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
parent
8c363de75f
commit
eb23c158ae
10 changed files with 535 additions and 85 deletions
|
|
@ -278,6 +278,154 @@ void test_compose_version_ex_matches_original_when_fingerprint_absent(void)
|
|||
TEST_ASSERT_EQUAL_STRING(buf_orig, buf_ex);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* scheduler-sim-diagnostics spec, task 7 (Requirement 6.1, 6.3, 6.5):
|
||||
* xce_format_bytes_human() / xce_is_bytes_valued_resource() /
|
||||
* xce_format_units_value() -- shared-library promotion of the scheduler
|
||||
* REPL's byte-unit scaling algorithm, its byte-valued-resource
|
||||
* classification, and a display-mode-aware value composer (formerly
|
||||
* repl_fmt.c's repl_format_bytes_human()/repl_is_bytes_valued_resource()
|
||||
* and repl_info.c's repl_format_numeric_resource_value()'s byte-valued
|
||||
* branch). Mirrors test_repl_resource_formatting.c's own assertion style --
|
||||
* that file's tests are the scheduler-side regression proof that
|
||||
* delegating repl_fmt.c's two wrapper functions here left their observable
|
||||
* behavior unchanged; these are the direct unit tests for the promoted
|
||||
* primitives themselves.
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
static void test_xce_is_bytes_valued_resource_true_for_canonical_five(void)
|
||||
{
|
||||
TEST_ASSERT_TRUE_MESSAGE(xce_is_bytes_valued_resource("mem"),
|
||||
"mem's wire unit is bytes");
|
||||
TEST_ASSERT_TRUE_MESSAGE(xce_is_bytes_valued_resource("tmp"),
|
||||
"tmp's wire unit is bytes");
|
||||
TEST_ASSERT_TRUE_MESSAGE(xce_is_bytes_valued_resource("maxmem"),
|
||||
"maxmem's wire unit is bytes");
|
||||
TEST_ASSERT_TRUE_MESSAGE(xce_is_bytes_valued_resource("maxtmp"),
|
||||
"maxtmp's wire unit is bytes");
|
||||
TEST_ASSERT_TRUE_MESSAGE(xce_is_bytes_valued_resource("maxswap"),
|
||||
"maxswap's wire unit is bytes");
|
||||
}
|
||||
|
||||
static void
|
||||
test_xce_is_bytes_valued_resource_false_for_null_empty_and_unknown(void)
|
||||
{
|
||||
TEST_ASSERT_FALSE_MESSAGE(
|
||||
xce_is_bytes_valued_resource(NULL),
|
||||
"a NULL name must not be misclassified as bytes-valued");
|
||||
TEST_ASSERT_FALSE_MESSAGE(
|
||||
xce_is_bytes_valued_resource(""),
|
||||
"an empty name must not be misclassified as bytes-valued");
|
||||
TEST_ASSERT_FALSE_MESSAGE(
|
||||
xce_is_bytes_valued_resource("slots"),
|
||||
"an unknown/custom resource name must not be misclassified as "
|
||||
"bytes-valued -- this is a small, explicit, hardcoded list, not a "
|
||||
"heuristic");
|
||||
}
|
||||
|
||||
static void
|
||||
test_xce_format_bytes_human_scales_across_full_unit_range_at_boundaries(void)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_bytes_human(0.0, buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING("0.00 B", buf);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_bytes_human(1023.0, buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(
|
||||
"1023.00 B", buf, "just below the KB boundary must stay in B");
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_bytes_human(1024.0, buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(
|
||||
"1.00 KB", buf,
|
||||
"exactly 1024 bytes must render as '1.00 KB', not '1024.00 B'");
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_bytes_human(1024.0 * 1024.0, buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING("1.00 MB", buf);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_bytes_human(1024.0 * 1024.0 * 1024.0, buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING("1.00 GB", buf);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_bytes_human(1024.0 * 1024.0 * 1024.0 * 1024.0, buf,
|
||||
sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING("1.00 TB", buf);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_bytes_human(1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0, buf,
|
||||
sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING("1.00 PB", buf);
|
||||
|
||||
/* PB is the largest unit -- a value past it stays capped there instead
|
||||
* of inventing a further unit. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_bytes_human(
|
||||
1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0, buf,
|
||||
sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(
|
||||
"1024.00 PB", buf,
|
||||
"a value past the PB range must stay capped at PB, not invent a "
|
||||
"further unit");
|
||||
}
|
||||
|
||||
static void
|
||||
test_xce_format_bytes_human_fractional_values_render_two_decimals(void)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
/* 5,000,000,000 bytes / 1024^3 = 4.656612873077393... GB, rounds via
|
||||
* "%.2f" to "4.66 GB" -- an arbitrary, non-power-of-2 value, the exact
|
||||
* transcript figure that motivated Requirement 6. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_bytes_human(5000000000.0, buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING("4.66 GB", buf);
|
||||
}
|
||||
|
||||
static void test_xce_format_units_value_raw_mode_renders_bare_value(void)
|
||||
{
|
||||
char buf[64];
|
||||
char expected[64];
|
||||
|
||||
snprintf(expected, sizeof(expected), "%f", 5000000000.0);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_units_value(XCE_UNITS_RAW, 5000000000.0, buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING(expected, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
test_xce_format_units_value_human_mode_renders_scaled_string_alone(void)
|
||||
{
|
||||
char buf[64];
|
||||
char expected[64];
|
||||
|
||||
xce_format_bytes_human(5000000000.0, expected, sizeof(expected));
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_units_value(XCE_UNITS_HUMAN, 5000000000.0, buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING(expected, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
test_xce_format_units_value_both_mode_renders_raw_and_human(void)
|
||||
{
|
||||
char buf[128];
|
||||
char expected[128];
|
||||
char human[64];
|
||||
|
||||
xce_format_bytes_human(5000000000.0, human, sizeof(human));
|
||||
snprintf(expected, sizeof(expected), "%f (%s)", 5000000000.0, human);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
xce_format_units_value(XCE_UNITS_BOTH, 5000000000.0, buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_STRING(expected, buf);
|
||||
}
|
||||
|
||||
void test_utils(void)
|
||||
{
|
||||
printf("\n>> utils test\n\n");
|
||||
|
|
@ -298,4 +446,13 @@ void test_utils(void)
|
|||
RUN_TEST(test_compose_version_ex_empty_fingerprint_dirty_commit_unchanged);
|
||||
RUN_TEST(test_compose_version_ex_null_fingerprint_matches_empty);
|
||||
RUN_TEST(test_compose_version_ex_matches_original_when_fingerprint_absent);
|
||||
RUN_TEST(test_xce_is_bytes_valued_resource_true_for_canonical_five);
|
||||
RUN_TEST(
|
||||
test_xce_is_bytes_valued_resource_false_for_null_empty_and_unknown);
|
||||
RUN_TEST(
|
||||
test_xce_format_bytes_human_scales_across_full_unit_range_at_boundaries);
|
||||
RUN_TEST(test_xce_format_bytes_human_fractional_values_render_two_decimals);
|
||||
RUN_TEST(test_xce_format_units_value_raw_mode_renders_bare_value);
|
||||
RUN_TEST(test_xce_format_units_value_human_mode_renders_scaled_string_alone);
|
||||
RUN_TEST(test_xce_format_units_value_both_mode_renders_raw_and_human);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue