Skip to content

test(common): add integration tests for layered config precedence#1202

Merged
geoffjay merged 19 commits into
issue-1194from
issue-1199
May 13, 2026
Merged

test(common): add integration tests for layered config precedence#1202
geoffjay merged 19 commits into
issue-1194from
issue-1199

Conversation

@geoffjay
Copy link
Copy Markdown
Owner

Adds 10 new integration tests to agentd_common::config covering empty files, unknown TOML keys, full three-layer precedence, concurrent loading, and per-service edge cases. All 33 tests pass.

Closes #1199

@geoffjay geoffjay added the review-agent Used to invoke a review by an agent tracking this label label May 12, 2026
Copy link
Copy Markdown
Owner Author

@geoffjay geoffjay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: test(common): add integration tests for layered config precedence

Stack position: This PR (issue-1199) is stacked on PR #1201 (issue-1194), which currently has needs-rework. It cannot merge until #1201 is fixed and landed. Once #1201 is reworked — particularly the schema additions for MonitorConfig, HookConfig, and IndexConfig — this branch will need a restack and the new fields should get coverage here too (see below).

The test work itself is solid. Reviewing it now so feedback is ready to act on immediately after the parent lands.


Bugfix in existing tests — correct

Adding ENV_LOCK to test_load_with_config_file and test_precedence_file_beats_default is correct and important. Both call load_from_path(Some(path)) which runs apply_env_overrides internally, so they were silently racing with the env-var-setting tests. Good catch.


New tests — assessment

Test Verdict Notes
test_load_empty_file_uses_defaults Correct — empty TOML is valid and all fields fall back to Default
test_load_unknown_keys_are_ignored Correctly validates serde's ignore-unknown-fields behaviour for [unknown_section]
test_full_precedence_chain ✅ with note See comment below
test_env_absent_preserves_file_value Clean test for the no-env-var path
test_partial_toml_leaves_other_services_at_defaults Good exhaustive sweep of all 11 service ports
test_all_default_ports_match_spec Useful regression guard; port table is clear
test_concurrent_load_returns_consistent_results ✅ with note See comment below
test_hook_notify_url_from_file Correctly exercises the Option<String> field via load_from_path
test_mcp_urls_from_file Good spot-check for partial MCP URL override
test_index_languages_from_file_overrides_default Not a duplicate — exercises load_from_pathmerge() path, unlike the existing test_toml_services_index_languages_override which calls toml::from_str directly

Minor observations (non-blocking)

1. test_full_precedence_chain — comment is slightly misleading

// Remove env var BEFORE asserting so a panic can't leave it set
env::remove_var("AGENTD_ASK_PORT");

The comment implies a panic in load_from_path would still clean up — it wouldn't, since remove_var is called after .expect(...). Reordering remove_var before the assertions (the current position) is correct for protecting against assertion panics, but not load_from_path panics. Not a real risk here, but the comment overpromises. The existing env-override tests follow the same set→use→remove pattern, so this is style-consistent; just worth a more accurate comment like: // Remove before assertions so a test-assert panic cannot leave the var set.

2. test_concurrent_load_returns_consistent_results — no ENV_LOCK

The test spawns 8 threads all calling load_from_path(None) without holding ENV_LOCK. Each thread reads env vars via apply_env_overrides. If an env-var-setting test runs concurrently (e.g., test_env_override_log_level), some threads could see log_level = "trace" while others see "info", and the cross-thread equality check would fail intermittently. In practice the ENV_LOCK serialisation makes this unlikely, but the concurrent test is the one place where not holding the lock creates a real race window rather than just a theoretical one. Consider acquiring ENV_LOCK for the duration of the spawned-threads test.

3. Redundant use std::io::Write; in new test functions

use std::io::Write; is already imported at the top of mod tests. The five new tests that re-import it locally are correct but noisy — Clippy may flag them on some lint configurations. They can be removed safely.


Coverage gap to address after restack

Once #1201's rework adds the missing schema fields, this PR should add tests for:

  • MonitorConfig: cpu_alert_threshold, memory_alert_threshold, disk_alert_threshold, history_size (metric snapshots)
  • HookConfig: notify_on_failure, notify_on_long_running, long_running_threshold_ms
  • IndexConfig: embedding_endpoint, embedding_api_key, lance_table, watch_interval_secs, ignore_patterns
  • AGENTD_MONITOR_HISTORY_SIZE / AGENTD_HOOK_HISTORY_SIZE (whichever naming resolution #1201 adopts for the collision)

The existing test_partial_toml_leaves_other_services_at_defaults and test_all_default_ports_match_spec are good templates for the new fields.


Summary: Bugfix is correct, new tests are well-structured with good comments. Three minor items above — none blocking. Hold for parent #1201 to land, restack, then add coverage for the new schema fields.

@geoffjay geoffjay removed the review-agent Used to invoke a review by an agent tracking this label label May 12, 2026
@geoffjay geoffjay linked an issue May 12, 2026 that may be closed by this pull request
7 tasks
geoffjay and others added 14 commits May 12, 2026 16:29
…_file_path indirection

- Make cmd_init pub(crate) so tests can call it directly
- Replace boolean-literal overwrite-guard tests with real tests that set
  AGENTD_CONFIG to a tempdir and call cmd_init; verify error message mentions
  --force on refusal and that the template is written on force-overwrite
- Add ENV_LOCK mutex to serialise tests that mutate AGENTD_CONFIG
- Remove the config_file_path() local wrapper; import via use instead
- Fix cmd_show None arm to reuse the already-resolved path rather than
  calling config_file_path() a second time

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…g tests

Add ENV_LOCK to mcp and index config test modules so env-var-mutating
tests are serialised in the parallel test harness. Also clear AGENTD_PORT
(set by agentd at runtime) before asserting default port values.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s; add TODO(#1201) comments

Replace silent unwrap_or_default() with unwrap_or_else(|e| tracing::warn\!(...)) in
all six migrated load() callers (hook, monitor, mcp, memory::EmbeddingConfig,
memory::LanceConfig, index, ui). Operators now see a warning when config.toml is
malformed rather than silently falling back to compiled defaults.

Add TODO(#1201) comments on every hardcoded fallback that is pending a schema
addition: notify_on_failure, notify_on_long_running, long_running_threshold_ms
(hook); cpu/memory/disk_alert_threshold, history_size (monitor);
embedding_endpoint (index.embedding); lance_table (index.lance).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a ValidateConfig trait to agentd_common with implementations for all
12 shared config sections. Add AgentdConfig::validate() that collects
errors from every section. Implement ValidateConfig on all service-level
config structs and wire validate() into each service's startup path so
misconfigurations fail early with descriptive error messages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Create dedicated config.rs modules for core, orchestrator, wrap, ask,
notify, and communicate. Each struct loads from agentd_common::config::load()
first, then overlays legacy AGENTD_* env vars for backward compatibility.
All inline env::var() calls in main.rs replaced with config struct access.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add impl ValidateConfig for EmbeddingConfig and LanceConfig in
  crates/memory/src/config.rs (blocking gap: memory was the only service
  with no validation at startup)
- Wire validation in memory/main.rs: call validate() on embedding and
  lance configs, load shared config for port/host so port=0 is caught
  before any I/O with a clear error message
- Remove validate_inner() indirection in crates/index/src/config.rs;
  move logic directly into impl ValidateConfig for IndexConfig and
  import the trait in index/main.rs and the test module
- Make validate_url() pub in agentd-common so service crates can reuse
  it without duplicating the http/https check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ilures

Replace silent unwrap_or_default() with unwrap_or_else(|e| { tracing::warn\!(...) })
in all six new service config loaders (ask, communicate, core, notify, orchestrator,
wrap). Restore diagnostic warn\!() calls for invalid AGENTD_WRAP_HISTORY_BYTES and
AGENTD_WRAP_CHANNEL_CAPACITY env vars with TODO comments referencing #1201.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Create docs/configuration.md with quick start, file location, precedence
  rules, complete key reference table, per-service sections, migration guide,
  and four example configs (minimal, development, production, Docker)
- Fix the env var table in agentd-common/config.rs to include all overrides
  (AGENTD_INDEX_LANGUAGES, AGENTD_RECONCILE_INTERVAL_SECS, all MCP URLs,
  AGENTD_NOTIFY_SERVICE_URL, AGENTD_COLLECTION_INTERVAL_SECS)
- Add link to configuration reference from README.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
geoffjay added 3 commits May 12, 2026 16:59
docs: add configuration system documentation
feat: add ValidateConfig trait and per-service validation
feat: add config structs for services with inline env var config
geoffjay added 2 commits May 12, 2026 17:00
refactor: migrate services with existing config.rs to shared TOML config
feat(cli): add config init and config show subcommands
@geoffjay geoffjay merged commit 2036182 into issue-1194 May 13, 2026
@geoffjay geoffjay deleted the issue-1199 branch May 13, 2026 00:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add integration tests for layered config precedence

1 participant