docs(plan): drop the launchd integration test
Task 6 is documentation-only. A real launchd cycle test would either hard-code the live label and risk clobbering a working installation, or need a test-only --label flag; the manual acceptance section covers the mechanism instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGntTHCW3sEPy1VBRopNNp
This commit is contained in:
@@ -38,9 +38,14 @@
|
|||||||
| `crates/xy/src/cli/mod.rs` | *Modify:* declare `mod service;` and re-export |
|
| `crates/xy/src/cli/mod.rs` | *Modify:* declare `mod service;` and re-export |
|
||||||
| `crates/xy/src/main.rs` | *Modify:* `Service` subcommand arm; reorder path resolution before logger init |
|
| `crates/xy/src/main.rs` | *Modify:* `Service` subcommand arm; reorder path resolution before logger init |
|
||||||
| `crates/xy/src/daemon/mod.rs` | *Modify:* drop the now-duplicated `ensure_dirs()` call |
|
| `crates/xy/src/daemon/mod.rs` | *Modify:* drop the now-duplicated `ensure_dirs()` call |
|
||||||
| `crates/xy/tests/service.rs` | *New:* `#[ignore]` end-to-end launchd cycle |
|
|
||||||
| `README.md` | *Modify:* document the five verbs |
|
| `README.md` | *Modify:* document the five verbs |
|
||||||
|
|
||||||
|
No integration test is planned. Driving a real launchd cycle would either
|
||||||
|
hard-code the live `se.aceofba.xy` label and risk clobbering a working
|
||||||
|
installation, or require a test-only `--label` flag on the CLI. The load/unload
|
||||||
|
mechanism is covered instead by the *Manual acceptance* section at the end of
|
||||||
|
this plan, which is the only check that can actually prove `RunAtLoad` works.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Task 1: `io::Write` for `RotatingLogWriter`
|
### Task 1: `io::Write` for `RotatingLogWriter`
|
||||||
@@ -1161,82 +1166,21 @@ git commit -m "feat(cli): xy service install/uninstall/start/stop/status"
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Task 6: End-to-end test and documentation
|
### Task 6: Documentation
|
||||||
|
|
||||||
An ignored integration test that exercises a real launchd cycle under a distinct label, plus README coverage.
|
Document the five verbs in the README. No integration test: driving a real
|
||||||
|
launchd cycle would either hard-code the live `se.aceofba.xy` label and risk
|
||||||
|
clobbering a working installation, or require a test-only `--label` flag on the
|
||||||
|
CLI. The *Manual acceptance* section below covers the mechanism instead.
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Create: `crates/xy/tests/service.rs`
|
|
||||||
- Modify: `README.md`
|
- Modify: `README.md`
|
||||||
|
|
||||||
**Interfaces:**
|
**Interfaces:**
|
||||||
- Consumes: the `xy` binary built by cargo. The test shells out rather than linking, because `service.rs` is `pub(crate)`.
|
- Consumes: nothing from earlier tasks.
|
||||||
- Produces: nothing consumed by later tasks.
|
- Produces: nothing consumed by later tasks.
|
||||||
|
|
||||||
- [ ] **Step 1: Write the ignored end-to-end test**
|
- [ ] **Step 1: Document the feature**
|
||||||
|
|
||||||
Create `crates/xy/tests/service.rs`:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
fn launchctl(verb: &str, arg: &str) -> bool {
|
|
||||||
Command::new("launchctl")
|
|
||||||
.arg(verb)
|
|
||||||
.arg(arg)
|
|
||||||
.output()
|
|
||||||
.map(|out| out.status.success())
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore = "installs a real launchd agent; run manually with --ignored"]
|
|
||||||
fn install_start_stop_uninstall_cycle() {
|
|
||||||
let home = std::env::var("HOME").unwrap();
|
|
||||||
let plist = format!("{home}/Library/LaunchAgents/se.aceofba.xy-test.plist");
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
!std::path::Path::new(&plist).exists(),
|
|
||||||
"test agent already installed; remove {plist} first"
|
|
||||||
);
|
|
||||||
|
|
||||||
let contents = format!(
|
|
||||||
r#"<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0"><dict>
|
|
||||||
<key>Label</key><string>se.aceofba.xy-test</string>
|
|
||||||
<key>ProgramArguments</key><array><string>/bin/sleep</string><string>3600</string></array>
|
|
||||||
<key>RunAtLoad</key><true/>
|
|
||||||
</dict></plist>
|
|
||||||
"#
|
|
||||||
);
|
|
||||||
|
|
||||||
std::fs::write(&plist, contents).unwrap();
|
|
||||||
|
|
||||||
assert!(launchctl("load", &plist), "load failed");
|
|
||||||
assert!(launchctl("unload", &plist), "unload failed");
|
|
||||||
|
|
||||||
std::fs::remove_file(&plist).unwrap();
|
|
||||||
|
|
||||||
assert!(!std::path::Path::new(&plist).exists());
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This deliberately drives `launchctl` against a harmless `/bin/sleep` agent under the `se.aceofba.xy-test` label rather than invoking `xy service install`, which would hard-code the real `se.aceofba.xy` label and could disturb a working installation. It verifies the load/unload mechanism Task 4 relies on.
|
|
||||||
|
|
||||||
- [ ] **Step 2: Confirm it is skipped by default**
|
|
||||||
|
|
||||||
Run: `cargo nextest run -p xy`
|
|
||||||
|
|
||||||
Expected: the test is listed as skipped, not run.
|
|
||||||
|
|
||||||
- [ ] **Step 3: Run it explicitly and confirm it passes**
|
|
||||||
|
|
||||||
Run: `cargo nextest run -p xy --run-ignored all -E 'test(/install_start_stop_uninstall_cycle/)'`
|
|
||||||
|
|
||||||
Expected: PASS. Then confirm no residue: `ls ~/Library/LaunchAgents/ | grep xy-test` returns nothing.
|
|
||||||
|
|
||||||
- [ ] **Step 4: Document the feature**
|
|
||||||
|
|
||||||
Add to `README.md`, after the existing command list:
|
Add to `README.md`, after the existing command list:
|
||||||
|
|
||||||
@@ -1264,7 +1208,7 @@ visible only to launchd:
|
|||||||
launchctl print gui/$UID/se.aceofba.xy
|
launchctl print gui/$UID/se.aceofba.xy
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 5: Full suite, format, lint**
|
- [ ] **Step 2: Full suite, format, lint**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo nextest run
|
cargo nextest run
|
||||||
@@ -1272,11 +1216,11 @@ cargo +nightly fmt
|
|||||||
cargo clippy --workspace
|
cargo clippy --workspace
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 6: Commit**
|
- [ ] **Step 3: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add crates/xy/tests/service.rs README.md
|
git add README.md
|
||||||
git commit -m "test(service): ignored launchd cycle test; document xy service"
|
git commit -m "docs(readme): document xy service verbs"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Reference in New Issue
Block a user