Skip to content

test(auth): add positive and negative unit tests for auth commands - #423

Merged
platinummonkey merged 1 commit into
mainfrom
test/auth-coverage
Apr 24, 2026
Merged

test(auth): add positive and negative unit tests for auth commands#423
platinummonkey merged 1 commit into
mainfrom
test/auth-coverage

Conversation

@platinummonkey

Copy link
Copy Markdown
Collaborator

Summary

Add a #[cfg(test)] module to src/commands/auth.rs covering the public command functions that can be exercised hermetically. The file previously had zero tests despite being security-critical OAuth2 code with ~10 public functions.

Coverage Added

Eight new tests, all passing:

Function Covered scenarios
token() Positive: cfg.access_token = Some(...) bypasses storage. Pin test: empty-string Some("") still bypasses (guards the if let Some(_) contract).
status() Unauthenticated: returns Ok with and without an org label.
list() Empty session registry (hermetic — STORAGE never touched) and populated registry (sessions saved, no tokens → "no token" enrichment).
logout() Idempotent on a never-logged-in site; multi-org case removes only the targeted session entry from sessions.json and leaves the default-org session intact.

Functions Skipped (with reasons)

  • login() — Requires live Dynamic Client Registration HTTP calls, open::that() to launch a browser, and a callback server waiting up to 300 seconds on an ephemeral loopback port. Cannot be tested hermetically without either a mock OAuth2 server (new dependency, rejected per REVIEW.md §4) or misrepresenting real behaviour (explicitly rejected by task constraints).
  • refresh() — Requires a real OAuth2 token-refresh HTTP call to the Datadog IdP. Same constraints as login().
  • with_storage() — Private helper, not part of the public surface the task asked to cover.
  • Authenticated branch of status() — The STORAGE singleton in src/auth/storage.rs captures its base_dir at first init (line 63-68) and cannot be reset per-test. Writing real tokens into STORAGE's frozen dir from outside the auth/storage module would require either widening internal visibility or duplicating FileStorage file-format logic. Left as-is; auth/storage.rs already has extensive round-trip coverage for FileStorage token I/O.
  • WASM variants of login/logout/refresh/list — Gated by #[cfg(target_arch = "wasm32")]; trivially just bail!(...). Not compiled in our test build.

Implementation Notes

  • Tests use PUP_CONFIG_DIR (for session-registry isolation) and DD_TOKEN_STORAGE=file (to force the file backend on first singleton init). All env-mutating tests acquire crate::test_support::lock_env() so sync and async tests in this module serialize against a single tokio mutex, avoiding the ENV_LOCK vs lock_env() split that would otherwise let them race each other for PUP_CONFIG_DIR.
  • TempDir helper is duplicated from src/auth/storage.rs (two occurrences total; REVIEW.md §1 extracts on the third).
  • No production code was modified. No visibility widened. No new crate dependencies.

Test plan

  • cargo test --bin pup 'commands::auth::tests' — 8/8 pass, verified stable across 5 consecutive runs.
  • cargo clippy --bin pup --all-targets -- -D warnings — clean.
  • cargo fmt --check — clean.
  • Full cargo test --bin pup — 882/882 pass. (Note: cargo test with all targets exhibits pre-existing intermittent failures in extensions::discovery::* and client::test_make_dd_config_with_mock_server due to an ENV_LOCK poisoning issue that also reproduces on main without these changes; see git stash && cargo test. Not introduced by this PR.)

🤖 Generated with Claude Code

Add a test module to src/commands/auth.rs covering the public command
functions that can be exercised hermetically (without network, live
keychain, or DCR flows). The existing module had zero tests despite
being security-critical OAuth2 code.

- token(): positive path where cfg.access_token bypasses the STORAGE
  singleton; additional pin-test for the empty-string Some(_) branch.
- status(): unauthenticated return path, with and without an org label.
- list(): empty session registry (STORAGE never touched) and populated
  registry (storage returns None → "no token" enrichment).
- logout(): idempotent-on-empty-state and the multi-org case that
  removes just the targeted session entry from sessions.json.

Tests use PUP_CONFIG_DIR + DD_TOKEN_STORAGE=file for isolation and
serialize through crate::test_support::lock_env so sync/async tests
in the module share a single mutex. No production code was modified.

Co-Authored-By: Claude <noreply@anthropic.com>
@platinummonkey
platinummonkey merged commit 5d0080f into main Apr 24, 2026
9 checks passed
@platinummonkey
platinummonkey deleted the test/auth-coverage branch April 24, 2026 19:52
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.

1 participant