test(config): add receive-side golden oracle and sharpen fixture
Address low-severity review findings on the X-macro config refactor: 1. The golden test only hashed config_send_wire_block(), so a receive-side KIND that reads a different width/order could still round-trip symmetrically. Add test_config_wire_golden_receive(): capture the same hash-pinned 633-byte frame and feed it through config_receive(), asserting every field (config_wire_equal) plus the derived use_delta/use_xattrs bits and representative bounded kinds. Add test_config_wire_receive_bounds() for bounds the symmetric round-trip cannot reach: an out-of-range BOOL (hand-built frame), RAW_MAXALLOC zero, a malformed STR_MODULE, an over-cap INT_IDMAPCOUNT, and an out-of-range INT_IDENTITY chown_uid. 2. golden_config_populate() set long runs of booleans to all-1, so an adjacent swap within a run produced identical bytes. Alternate the boolean values and make the fixture receiver-valid (chmod grammar "u=rwx,go=rx" is the same 11 bytes; delta_max_file_size inside the bound). Re-pin the golden: len stays 633, hash is now 9160991280011164139 (computed, not guessed). 3. Document in config.h and client_cli.c that the CLI option tables remain hand-maintained and are deliberately not generated from the wire-field X-macro (client-only fields, flag/alias/negation semantics). No CLI-table rewrite. PROTOCOL_VERSION stays "2.20.0"; src/shared/config.c is untouched and the wire bytes are unchanged apart from the fixture's own new values.
This commit is contained in:
@@ -608,7 +608,15 @@ typedef struct {
|
||||
size_t offset; /* offsetof of the boolean target field in Config */
|
||||
} NegatableOption;
|
||||
|
||||
/* Options that map directly onto a Config field with no side effects. */
|
||||
/* Options that map directly onto a Config field with no side effects.
|
||||
*
|
||||
* NOTE: these CLI tables are intentionally NOT generated from the wire-field
|
||||
* X-macro table in config.h. The two sets only overlap partially: the CLI
|
||||
* surface also carries client-only fields that never cross the wire (rsh,
|
||||
* outbuf, remote-option, batch paths, trust-sender, ...) and needs flag/alias/
|
||||
* negation semantics that the wire table does not model. Keeping them
|
||||
* hand-maintained is deliberate; the shared contract is enforced at the wire
|
||||
* boundary by config.[ch] and the golden test. */
|
||||
static const OptionEntry OPTION_TABLE[] = {
|
||||
{"--dry-run", "-n", OPT_FLAG, offsetof(Config, dry_run)},
|
||||
{"--remove-source-files", NULL, OPT_FLAG, offsetof(Config, remove_source_files)},
|
||||
|
||||
@@ -100,6 +100,12 @@ typedef enum SuperMode { SUPER_MODE_AUTO = 0, SUPER_MODE_ON = 1, SUPER_MODE_OFF
|
||||
* (STR_MODULE), repeated count+array blocks (BLOCK_*), --copy-as presence
|
||||
* (COPY_AS_*), and the derived --delta / use_xattrs bits (DERIVED_DELTA,
|
||||
* BOOL_XATTR_DERIVE).
|
||||
*
|
||||
* SCOPE: this table covers ONLY the serialized wire frame. The client CLI
|
||||
* option tables in client_cli.c (OPTION_TABLE / NEGATABLE_OPTIONS) are still
|
||||
* hand-maintained and are deliberately NOT generated from this table: the CLI
|
||||
* surface carries client-only fields and flag/alias/negation semantics that
|
||||
* have no wire representation. Do not assume the two are folded together.
|
||||
* =========================================================================== */
|
||||
#define CONFIG_WIRE_HEADER_FIELDS(X) X(version, char*, str_dup(PROTOCOL_VERSION), STR)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user