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

@ -0,0 +1,120 @@
# Implementation Plan
- [ ] 1. Foundation: test scaffolding and skill directory setup
- [x] 1.1 Extract resupdate's type-resolution logic and write failing unit tests for its fallback behavior
- Move `set_resval()`'s resource-name → `Value_u_which` table lookup into a new, small, dependency-light `resval_typeresolve.c`/`.h` module with no networking/REPL/global-state dependency — `test.c` (4298 lines, its own `main()`, heavy `libedit`/network dependencies) cannot itself be white-box included into a unit test, so this extraction is a hard prerequisite for testing this logic in isolation at all
- Create `test_resval_typeresolve.c` (Unity) and wire both new files into `src/controller/meson.build`: add `testsuite/resval_typeresolve.c` to `xce_test_src` (line 57) so `xce_test` still links, and add a new `test()` target for `test_resval_typeresolve.c` following the existing `controller_unit_test`/`sched_push_unit_test` pattern (lines 86, 215, 222) — these are hand-maintained explicit lists, not globs, so the module and test will not build without this step
- Write tests covering: a currently-known name (e.g. `mem`) still resolves numeric exactly as today; a currently-known string name (`type`) still resolves string exactly as today; an unrecognized name (e.g. `r15m`) defaults to numeric; an unrecognized name with an explicit type-override flag resolves to the requested type
- Observable completion: the new module and test target both compile and link via `meson`, and the new test target fails (RED) because the fallback-to-numeric and type-override behavior don't exist yet
- _Requirements: 1.1, 1.4_
- [ ] 1.2 (P) Scaffold the xce-test-resources skill directory
- Create the skill directory with a `SKILL.md` stub describing the intended usage (`/xce-test-resources [resource=value ...]`) and the VERDICT line format, following the `xce-test-ha`/`xce-deploy-ha` SKILL.md convention
- Observable completion: the skill is discoverable/invocable (even though its underlying script is not yet functional) and its documented contract matches design.md's Batch/Job Contract for the skill
- _Requirements: 6.1_
- _Boundary: xce-test-resources skill_
- [ ] 2. Core: resupdate resource-name coverage fix
- [ ] 2.1 Wire the extracted resolver into resupdate and add the type-override flag
- Extend `resval_typeresolve.c`'s fallback path so any resource name not in the existing table defaults to numeric (`Value_u_fvalue`), while `type`/`model` and all currently-supported names keep their exact existing behavior
- Make `test.c`'s `set_resval()` a thin wrapper delegating to `resval_typeresolve.c` (for type resolution) plus its own existing `.host` tagging (unchanged, still needs REPL state)
- Add an optional `-t <numeric|string>` flag to `cmd_resupdate()`, applied per `-n`/`-v` pair
- Observable completion: the unit tests from 1.1 pass (GREEN); running `resupdate -n r15m -v 1.5` in the worker context (against a live controller) now succeeds where it previously silently failed
- _Requirements: 1.1, 1.4_
- _Depends: 1.1_
- [ ] 2.2 Implement per-name accept/reject verification in resupdate
- After `cmd_resupdate()` sends the update RPC, issue one follow-up `xcecli_resval()` query per submitted `(resource, worker)` pair (the same client-library call `resval`/`cmd_resval` already uses) and compare the returned value against what was just sent
- Report "accepted" for a matching value, "rejected: unknown resource" for a not-found result, with a short bounded retry before concluding rejection (guards against a genuinely-registered resource whose value hasn't propagated to the query path yet)
- Report every submitted name's individual accept/reject outcome when a single invocation carries multiple `-n`/`-v` pairs
- Observable completion: against a live controller, `resupdate -n mem -v 5 -n not-a-real-resource -v 1` reports `mem` as accepted and `not-a-real-resource` as rejected, in the same invocation
- _Requirements: 1.2, 1.3_
- _Depends: 2.1_
- [ ] 3. Core: apiserver local deployment capability
- [ ] 3.1 (P) Extend `xce-deploy-ha`'s `deploy-ha.sh` with a conditional apiserver step and a combined `start-all.sh`
- In `deploy-ha.sh` Step 3, add a new conditional branch in the same *opt-in-by-presence* spirit as the existing worker/scheduler branch: check for a pre-built apiserver binary at its own Go-build output path (e.g. `/tmp/apiserver`, `make build-server`'s default) — NOT alongside `$BINARY`, since apiserver is a separate build system, not the same meson build dir worker/scheduler share; `deploy-ha.sh` does not invoke `make build-server` itself, building it remains a caller prerequisite (document in SKILL.md's Prerequisites section, same pattern as the existing `/xce-build controller` note). If present, generate `$TOP/scripts/start-apiserver.sh` plus a minimal `logger.yaml` (modeled on `make test-integration`'s `XCE_BIN`/`SRV_URL` convention) — functional auth/RBAC is NOT required (verification is trace-log-based, task 6.4; no REST query is ever issued against this instance), but `logger.yaml` MUST set `logging.level: debug` or task 4.2's trace line is silently never written; absent the binary, generate nothing, so existing callers are unaffected
- Also in Step 3, always generate `$TOP/scripts/start-all.sh`: runs `start.sh` for the controller node(s), waits on Step 5's existing health-check, then runs whichever of `start-worker.sh`/`start-scheduler.sh`/`start-apiserver.sh` were actually generated for this deploy (skipping any that weren't) — start the scheduler with `-vvv` specifically (verbosity 3, matching `tlog_debug3`/`TRACE`), overriding SKILL.md's existing `-v`-only example for this feature's needs, or task 4.1's trace line is silently never written
- Update `.claude/skills/xce-deploy-ha/SKILL.md` with a new "Step 4d" documenting the apiserver step (following the existing Step 4b pattern) and documenting `start-all.sh` as a combined shortcut for Steps 4/4b/4c
- Write apiserver/scheduler logs under the caller's scratch directory, matching the existing `logs/` convention — these are the logs tasks 6.3/6.4 grep
- Observable completion: running `deploy-ha.sh` against a build that includes an apiserver binary, then `start-all.sh`, leaves a running controller, scheduler (at `-vvv`), and apiserver (with debug-level logging) with no further manual steps; running `deploy-ha.sh` against a build without an apiserver binary (e.g. `xce-test-ha`'s existing usage) is unaffected — no `start-apiserver.sh` is generated, and `start-all.sh` skips that step
- _Requirements: 5.3, 6.1_
- _Boundary: xce-deploy-ha (deploy-ha.sh, SKILL.md)_
- [ ] 4. Core: scheduler and apiserver trace-log instrumentation
- [ ] 4.1 (P) Add a trace log line to the scheduler's live resource-update handling
- In `xce_core_push_events()`'s `XCE_CORE_EVENT_RESVALS_DELTA` case (`src/scheduler/src/core_events.c`), add one `TRACE`-level log line (this component's existing `tinylog` convention) immediately after the resolved worker's value is written, logging the resolved host, resource name, and applied value in a fixed, greppable format
- Confirm the existing scheduler testsuite (`test_core_events.c` and friends) still passes unchanged — this is a pure log addition with no control-flow change, so no new unit test is required (consistent with this codebase's existing precedent: other `TRACE`/`WARN` calls in this area, e.g. `apiserver_worker_change`, have no dedicated unit test coverage either); the log line's actual content/format is confirmed live in task 8.1
- Observable completion: a live scheduler daemon's log file contains one line per applied resource update, in the format task 6.3 will grep for; existing scheduler tests are unaffected
- _Requirements: 4.1, 4.2, 4.3_
- [ ] 4.2 (P) Add a trace log line to the apiserver's resource-update storage handling
- In `OnResourceLocationUpdated` (`src/frontend/apiserver/backend/handler.go:92-95`), add one `logger.Debug(...)` call (zap, per this component's existing convention) immediately after `store.ResourceLocations.Put(key, *res)`, logging the resource name, location/host, and stored value
- Confirm existing apiserver backend tests still pass unchanged — same rationale as 4.1, no new unit test required for a pure log addition; content/format confirmed live in task 8.1
- Observable completion: a live apiserver's log file contains one line per stored resource-location update, in the format task 6.4 will grep for; existing backend tests are unaffected
- _Requirements: 5.1, 5.2, 5.4_
- [ ] 5. Integration: full-stack deployment orchestration
- [ ] 5.1 Wire controller, scheduler, and apiserver deployment into the skill via `start-all.sh`
- Invoke `xce-deploy-ha`'s `deploy-ha.sh` (task 3.1) into a fresh scratch directory, then its generated `start-all.sh` — no manual per-component sequencing lives in this skill; `start-all.sh` already gates scheduler/apiserver startup on the controller health-check and handles the `-vvv`/debug-level logging needed for tasks 4.1/4.2's trace lines
- Register a `trap`-based cleanup (or equivalent) before invoking `start-all.sh`, not just at the end of the script — this must cover a mid-deployment abort (e.g. apiserver fails to start after controller+scheduler are already up), not only a completed PASS/FAIL run; deliberately stronger than `xce-deploy-ha`'s own convention (a separate, manually-invoked `cleanup.sh`) because Requirement 6.5 requires cleanup-by-default on every path unless the operator passed the "keep running" flag
- Observable completion: a single invocation of the orchestration script leaves a running controller, live scheduler daemon (built with task 4.1's trace log, started at `-vvv`), and apiserver (built with task 4.2's trace log, debug-level logging enabled), all logging under the same scratch directory, with no manual steps; killing the script mid-deployment (e.g. before the apiserver step completes) still removes every process it had already started, unless "keep running" was passed
- _Requirements: 5.3, 6.1, 6.5_
- _Depends: 1.2, 3.1, 4.1, 4.2_
- [ ] 6. Core: resource injection and per-layer verification checks
- [ ] 6.1 Implement worker join and resource injection
- Join a synthetic worker through the `xce_test` worker context (no real worker daemon process), then run `resupdate` for one or more resource names/values
- Observable completion: after this step runs, `resupdate` has been accepted for every requested resource name with zero real worker daemon processes running
- _Requirements: 2.1, 2.2, 6.1, 6.4_
- _Depends: 2.1, 2.2, 5.1_
- [ ] 6.2 Implement the controller-side verification check
- Query the controller via `resval` for each injected resource/worker pair and compare against the injected value
- Observable completion: the check reports, per resource, whether the controller's observed value matches the injected value, including both values when it does not
- _Requirements: 3.1, 3.2_
- _Depends: 6.1_
- _Boundary: xce-test-resources skill (controller check) — same file as 6.3/6.4 (`run-resource-verify.sh`), sequential, not parallel-safe_
- [ ] 6.3 Implement the scheduler-side verification check via trace-log tail
- Tail/grep the live scheduler daemon's log file (task 4.1's trace line) for each injected resource/worker pair, polling with a short interval up to a generous, explicit bounded wait — no record, no replay, no REPL
- Compare the scheduler's observed value against the injected value, reported distinctly from the controller-side result; a timeout with no matching line is reported as "unreachable," distinct from a value mismatch
- Observable completion: the check reports, per resource, whether the scheduler's observed value matches the injected value within the bounded wait, attributable specifically to the scheduler layer
- _Requirements: 4.1, 4.2, 4.3_
- _Depends: 6.1, 6.2_
- _Boundary: xce-test-resources skill (scheduler check) — same file as 6.2/6.4, sequential_
- [ ] 6.4 Implement the apiserver-side verification check via trace-log tail
- Tail/grep the live apiserver's log file (task 4.2's trace line) for each injected resource/worker pair, polling with a short interval up to a generous, explicit bounded wait — no `xcecli` query, no REST call
- Compare the apiserver's observed value against the injected value, reported distinctly from the controller-side and scheduler-side results; a timeout with no matching line is reported as "unreachable," distinct from a value mismatch
- Observable completion: the check reports, per resource, whether the apiserver's observed value matches the injected value within the bounded wait, attributable specifically to the apiserver layer
- _Requirements: 5.1, 5.2, 5.4_
- _Depends: 6.1, 6.3_
- _Boundary: xce-test-resources skill (apiserver check) — same file as 6.2/6.3, sequential_
- [ ] 7. Integration: verdict aggregation, reporting, and cleanup
- [ ] 7.1 Aggregate layer results, emit the verdict, and clean up
- Combine the controller/scheduler/apiserver check results into a single per-resource, per-layer comparison, implemented as a self-contained comparison step that accepts a set of (resource, injected value, per-layer observed value) records — so it can be invoked directly with synthetic records for testing (task 8.2), not only reachable from a live run
- Emit a machine-parseable VERDICT line (following `xce-test-ha`'s convention) plus the standard terminal PASS/FAIL oracle line, naming every layer that mismatched or was unreachable (timed out)
- Support checking multiple resource names in one run, defaulting to the resource names added in task 2.1 when none are supplied
- Clean up every process and runtime/data-directory artifact this run created, unless the operator passed a flag requesting the deployment be left running — this is the normal-completion firing of the same trap-based cleanup task 5.1 registered for the abort path, not a separate mechanism. **Log files under the scratch directory are always preserved**, regardless of the keep-running flag, so a FAIL verdict's underlying scheduler/apiserver trace-log evidence remains inspectable after the run
- Observable completion: a full run against the default resource set produces exactly one VERDICT line and a matching process exit code, no controller/scheduler/apiserver processes remain afterward (unless the keep-running flag was used), and the run's log files are still present on disk regardless
- _Requirements: 6.2, 6.3, 6.4, 6.5_
- _Depends: 6.2, 6.3, 6.4_
- [ ] 8. Validation: end-to-end live verification runs
- [ ] 8.1 Run the full flow live, including one deliberately-unregistered resource name
- Execute the skill end-to-end against a freshly deployed controller/scheduler/apiserver, using the default resource set (task 2.1's previously-missing names) plus one resource name that does not exist in the cluster's registered set
- Observable completion: every genuinely-registered resource individually reports matching values at all three layers (confirming tasks 4.1/4.2's trace-log lines are correctly formatted and greppable, not just present), AND the unregistered name is reported as a clear, specifically-identified rejection (not a silent omission) with correct per-name accept/reject accounting across the whole batch; per design.md's Error Handling (an unrecognized name is a run-level failure), the run's single overall VERDICT is FAIL, attributable specifically to the unregistered name — not a false overall PASS
- _Requirements: 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 3.1, 3.2, 4.1, 4.2, 4.3, 5.1, 5.2, 5.3, 5.4, 6.1, 6.2, 6.4_
- _Depends: 7.1_
- [ ] 8.2 Verify the verdict logic correctly reports FAIL on a genuine mismatch
- Invoke task 7.1's comparison step directly with a synthetic set of per-layer observed-value records where one layer's value deliberately does not match the corresponding injected value (no live deployment required for this check, since the comparison step is self-contained per task 7.1)
- Observable completion: the comparison step reports an overall FAIL verdict that correctly names the specific layer whose synthetic record was mismatched, and reports PASS for every other, matching layer/resource in the same input set — proving the verdict logic distinguishes pass from fail rather than always reporting PASS
- _Requirements: 6.3_
- _Depends: 7.1_
## Implementation Notes
- Task 1.1: `resval_typeresolve.c`'s new function is `int resval_resolve_type(const char* name, int type_override)`, returning a `Value_u_which` tag or `RESVAL_TYPE_UNKNOWN` (-1, doesn't collide with the real 0-6 enum range). Task 2.1 should build on this exact signature rather than inventing a new one. `test.c`'s `set_resval()`/`cmd_resupdate()` were deliberately left untouched by task 1.1 — task 2.1 is the one that makes `set_resval()` a thin wrapper.
- `controller_unit_test` (the big legacy Unity binary) has a pre-existing, unrelated flaky failure in `test_config_repl.c` (bug-1561, overlayfs `fdatasync errno=5` sandbox artifact) that shows up on every `/xce-build controller` run in this environment. It is NOT caused by this feature's changes — do not chase it in later tasks; cross-check `.wolf/buglog.json`'s bug-1561 entry before treating a `controller_unit_test` failure as real, and confirm via `git status` that `test_config_repl.c`/`config_repl.c` are untouched by the current task's diff.

View file

@ -54,7 +54,7 @@ controller = executable('xce_controller',
link_args: wrap_link_args, link_args: wrap_link_args,
install: true) 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 # BSD-licensed readline replacement (scheduler-core spec, task 12.1 review
# finding): GNU readline is GPL; xce_test's REPL only needs readline()/ # 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, timeout: 60,
env: ['ASAN_OPTIONS=detect_leaks=0']) 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();
}