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:
parent
54ea3bc5b5
commit
98b8c34bec
5 changed files with 357 additions and 1 deletions
|
|
@ -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'])
|
||||
|
||||
|
|
|
|||
53
src/controller/testsuite/resval_typeresolve.c
Normal file
53
src/controller/testsuite/resval_typeresolve.c
Normal 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;
|
||||
}
|
||||
52
src/controller/testsuite/resval_typeresolve.h
Normal file
52
src/controller/testsuite/resval_typeresolve.h
Normal 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 */
|
||||
105
src/controller/testsuite/test_resval_typeresolve.c
Normal file
105
src/controller/testsuite/test_resval_typeresolve.c
Normal 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();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue