feat(resource-value-verification): extract resupdate type-resolution logic (task 1.1)

Move set_resval()'s resource-name lookup table into a new, dependency-light
resval_typeresolve.c/.h module so it's independently unit-testable (test.c
can't be white-box included into Unity). Adds RED tests for the not-yet-
implemented numeric-fallback/type-override behavior (task 2.1).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-08-17 23:03:57 +00:00
parent 54ea3bc5b5
commit 98b8c34bec
Signed by: rshen
SSH key fingerprint: SHA256:8Vf2pZ3h6rJa7EhGK+WaAQ9Mta/apZvteW6g9U/WKKk
5 changed files with 357 additions and 1 deletions

View file

@ -54,7 +54,7 @@ controller = executable('xce_controller',
link_args: wrap_link_args,
install: true)
xce_test_src = [ 'testsuite/test.c', 'testsuite/waldump.c', 'testsuite/walcompare.c', 'testsuite/snapverify.c', 'testsuite/snapdiff.c', 'testsuite/configcompare.c']
xce_test_src = [ 'testsuite/test.c', 'testsuite/waldump.c', 'testsuite/walcompare.c', 'testsuite/snapverify.c', 'testsuite/snapdiff.c', 'testsuite/configcompare.c', 'testsuite/resval_typeresolve.c']
# BSD-licensed readline replacement (scheduler-core spec, task 12.1 review
# finding): GNU readline is GPL; xce_test's REPL only needs readline()/
@ -283,3 +283,29 @@ test('apiserver push test', apiserver_push_unit_test,
timeout: 60,
env: ['ASAN_OPTIONS=detect_leaks=0'])
# resource-value-verification task 1.1: resval_typeresolve.c is a small,
# dependency-light module (no networking/REPL/global state) extracted from
# test.c's set_resval() specifically so its name -> Value_u_which resolution
# logic can be unit-tested in isolation -- test.c itself (4298 lines, its own
# main(), heavy libedit/network dependencies) cannot be white-box included
# into a Unity test. Standalone binary (not folded into controller_unit_test_
# src) since it has zero dependency on controller.c/cluster.c internals,
# mirroring sched_push_unit_test's/apiserver_push_unit_test's own standalone-
# binary rationale above.
resval_typeresolve_unit_test_src = [
'testsuite/test_resval_typeresolve.c',
'testsuite/resval_typeresolve.c',
]
resval_typeresolve_unit_test = executable('resval_typeresolve_unit_test',
resval_typeresolve_unit_test_src,
include_directories: [incdir],
dependencies: controller_unit_test_deps,
c_args: ['-DXCE_TESTING'],
install: false)
test('resval typeresolve test', resval_typeresolve_unit_test,
suite: 'controller',
timeout: 60,
env: ['ASAN_OPTIONS=detect_leaks=0'])

View file

@ -0,0 +1,53 @@
/* resval_typeresolve.c -- resource-value-verification task 1.1
*
* See resval_typeresolve.h for the full rationale and TASK 1.1 STATUS note.
*/
#include <string.h>
#include "resval_typeresolve.h"
int resval_resolve_type(const char* name, int type_override)
{
/* Verbatim extraction of set_resval()'s resinfo[] table (test.c),
* unchanged: type/model are Value_u_svalue; everything else here is
* Value_u_fvalue. */
static const struct {
const char* name;
int valtype;
} resinfo[] = {
{ "r15s", Value_u_fvalue },
{ "r1m", Value_u_fvalue },
{ "slots", Value_u_fvalue },
{ "ut", Value_u_fvalue },
{ "mem", Value_u_fvalue },
{ "maxcpus", Value_u_fvalue },
{ "ndisks", Value_u_fvalue },
{ "cpuf", Value_u_fvalue },
{ "maxswap", Value_u_fvalue },
{ "maxtmp", Value_u_fvalue },
{ "type", Value_u_svalue },
{ "model", Value_u_svalue },
{ "verilog", Value_u_fvalue },
{ "dyna", Value_u_fvalue },
{ NULL, 0 }
};
int i;
/* task 2.1 wires this in for the unrecognized-name numeric-default
* fallback / explicit-override path (Requirement 1.1/1.4); until then
* it has no effect -- an unrecognized name always returns
* RESVAL_TYPE_UNKNOWN below, regardless of what was passed here. */
(void)type_override;
if (name == NULL) {
return RESVAL_TYPE_UNKNOWN;
}
for (i = 0; resinfo[i].name != NULL; i++) {
if (strcmp(resinfo[i].name, name) == 0) {
return resinfo[i].valtype;
}
}
return RESVAL_TYPE_UNKNOWN;
}

View file

@ -0,0 +1,52 @@
#ifndef RESVAL_TYPERESOLVE_H
#define RESVAL_TYPERESOLVE_H
/* resval_typeresolve.h -- resource-value-verification task 1.1
*
* Extracted from test.c's set_resval(): pure resource-name -> wire-type
* resolution logic, with NO networking, REPL, or global-state dependency
* (unlike set_resval() itself, which also allocates xce_val_t and tags
* .host via get_setting("myname") -- that stays in test.c since it needs
* REPL state). This isolation is what makes the logic unit-testable outside
* of test.c, which cannot be white-box #include'd into a Unity test (4298
* lines, its own main(), heavy libedit/network dependencies).
*
* The resolved type is a Value_u_which tag (controller.capnp.h) -- e.g.
* Value_u_fvalue for a numeric resource, Value_u_svalue for a string one.
*/
#include "controller.capnp.h" /* enum Value_u_which */
/* Sentinel: not a valid Value_u_which value. Used both as:
* - the RETURN value when `name` is not present in the known-resource
* table and no override applies;
* - the `type_override` INPUT value meaning "no override requested".
*/
#define RESVAL_TYPE_UNKNOWN (-1)
/* Resolve `name` to its Value_u_which wire type.
*
* `type_override`: pass a valid Value_u_which value (Value_u_fvalue,
* Value_u_svalue, ...) to request that type for a name not in the known-
* resource table, or RESVAL_TYPE_UNKNOWN for no override.
*
* Returns:
* - the table's type, for any of the 14 currently-known resource names
* (r15s, r1m, slots, ut, mem, maxcpus, ndisks, cpuf, maxswap, maxtmp,
* type, model, verilog, dyna) -- `type_override` is ignored for a known
* name, exactly as set_resval() behaves today.
* - RESVAL_TYPE_UNKNOWN, for `name` == NULL or a name not in the table.
*
* *** TASK 1.1 STATUS (non-behavioral extraction) ***
* This is a byte-for-byte extraction of set_resval()'s existing resinfo[]
* table lookup -- current behavior for every one of the 14 known names is
* UNCHANGED. The numeric-by-default fallback for an unrecognized name, and
* honoring `type_override` for one, are Requirement 1.1/1.4 behavior that
* task 2.1 implements on top of this same signature -- until then,
* `type_override` is accepted but ignored, and an unrecognized name always
* returns RESVAL_TYPE_UNKNOWN regardless of `type_override`. See
* test_resval_typeresolve.c for the RED tests documenting this gap.
*/
int resval_resolve_type(const char* name, int type_override);
#endif /* RESVAL_TYPERESOLVE_H */

View file

@ -0,0 +1,105 @@
/* test_resval_typeresolve.c -- resource-value-verification task 1.1
*
* Unity unit tests for resval_typeresolve.c's resource-name -> Value_u_which
* resolution, extracted from test.c's set_resval() (design.md "Testing
* Strategy"). Four cases, matching tasks.md task 1.1 exactly:
*
* 1. A currently-known numeric name (mem) resolves Value_u_fvalue, exactly
* as today (Requirement 1.4) -- GREEN.
* 2. A currently-known string name (type) resolves Value_u_svalue, exactly
* as today (Requirement 1.4) -- GREEN.
* 3. An unrecognized name (r15m) defaults to numeric (Requirement 1.1) --
* RED: task 2.1 has not yet implemented the fallback.
* 4. An unrecognized name with an explicit type-override resolves to the
* requested type (Requirement 1.1) -- RED: task 2.1 has not yet wired
* `type_override` in.
*
* Cases 3 and 4 are INTENTIONALLY FAILING (RED) evidence for this task --
* see resval_typeresolve.h's "TASK 1.1 STATUS" note and tasks.md task 2.1,
* which implements the behavior these two cases assert.
*/
#include <stdio.h>
#include <unity/unity.h>
#include "resval_typeresolve.h"
/* ------------------------------------------------------------------ */
/* Tests */
/* ------------------------------------------------------------------ */
/* 1. Currently-known numeric name -- unchanged behavior (GREEN). */
static void test_known_numeric_name_resolves_fvalue(void)
{
int rc = resval_resolve_type("mem", RESVAL_TYPE_UNKNOWN);
TEST_ASSERT_EQUAL_INT_MESSAGE(
Value_u_fvalue, rc,
"a currently-known numeric resource name (mem) must still resolve "
"Value_u_fvalue exactly as set_resval() does today");
printf("test_known_numeric_name_resolves_fvalue: PASS\n");
}
/* 2. Currently-known string name -- unchanged behavior (GREEN). */
static void test_known_string_name_resolves_svalue(void)
{
int rc = resval_resolve_type("type", RESVAL_TYPE_UNKNOWN);
TEST_ASSERT_EQUAL_INT_MESSAGE(
Value_u_svalue, rc,
"a currently-known string resource name (type) must still resolve "
"Value_u_svalue exactly as set_resval() does today");
printf("test_known_string_name_resolves_svalue: PASS\n");
}
/* 3. Unrecognized name defaults to numeric -- RED (task 2.1 implements). */
static void test_unrecognized_name_defaults_to_numeric(void)
{
int rc = resval_resolve_type("r15m", RESVAL_TYPE_UNKNOWN);
TEST_ASSERT_EQUAL_INT_MESSAGE(
Value_u_fvalue, rc,
"an unrecognized resource name (r15m) with no type override must "
"default to Value_u_fvalue (Requirement 1.1) -- NOT YET "
"IMPLEMENTED, expected RED until task 2.1");
printf("test_unrecognized_name_defaults_to_numeric: PASS\n");
}
/* 4. Unrecognized name + explicit override -- RED (task 2.1 implements). */
static void test_unrecognized_name_with_override_resolves_requested_type(
void)
{
int rc = resval_resolve_type("r15m", Value_u_svalue);
TEST_ASSERT_EQUAL_INT_MESSAGE(
Value_u_svalue, rc,
"an unrecognized resource name (r15m) with an explicit type "
"override must resolve to the requested type (Requirement 1.1) -- "
"NOT YET IMPLEMENTED, expected RED until task 2.1");
printf(
"test_unrecognized_name_with_override_resolves_requested_type: "
"PASS\n");
}
/* ------------------------------------------------------------------ */
/* Standalone Unity main (this binary is its own test executable -- see */
/* meson.build's resval_typeresolve_unit_test) */
/* ------------------------------------------------------------------ */
void setUp(void) { return; }
void tearDown(void) { return; }
int main(void)
{
printf("\n>> resource-value-verification task 1.1: resval_typeresolve "
"type resolution\n\n");
UNITY_BEGIN();
RUN_TEST(test_known_numeric_name_resolves_fvalue);
RUN_TEST(test_known_string_name_resolves_svalue);
RUN_TEST(test_unrecognized_name_defaults_to_numeric);
RUN_TEST(test_unrecognized_name_with_override_resolves_requested_type);
return UNITY_END();
}