aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/cli.rs346
1 files changed, 346 insertions, 0 deletions
diff --git a/tests/cli.rs b/tests/cli.rs
new file mode 100644
index 0000000..7cb68b7
--- /dev/null
+++ b/tests/cli.rs
@@ -0,0 +1,346 @@
1use assert_cmd::Command;
2use predicates::prelude::*;
3use std::fs;
4use std::time::Duration;
5use tempfile::TempDir;
6
7#[test]
8fn test_help_output() {
9 let mut cmd = Command::cargo_bin("demon").unwrap();
10 cmd.args(&["--help"])
11 .assert()
12 .success()
13 .stdout(predicate::str::contains("daemon process management"))
14 .stdout(predicate::str::contains("run"))
15 .stdout(predicate::str::contains("stop"))
16 .stdout(predicate::str::contains("tail"))
17 .stdout(predicate::str::contains("cat"))
18 .stdout(predicate::str::contains("list"))
19 .stdout(predicate::str::contains("status"))
20 .stdout(predicate::str::contains("clean"));
21}
22
23#[test]
24fn test_version_output() {
25 let mut cmd = Command::cargo_bin("demon").unwrap();
26 cmd.args(&["--version"])
27 .assert()
28 .success()
29 .stdout(predicate::str::contains("demon 0.1.0"));
30}
31
32#[test]
33fn test_run_missing_command() {
34 let temp_dir = TempDir::new().unwrap();
35
36 let mut cmd = Command::cargo_bin("demon").unwrap();
37 cmd.current_dir(temp_dir.path())
38 .args(&["run", "--id", "test"])
39 .assert()
40 .failure()
41 .stderr(predicate::str::contains("Command cannot be empty"));
42}
43
44#[test]
45fn test_run_creates_files() {
46 let temp_dir = TempDir::new().unwrap();
47
48 let mut cmd = Command::cargo_bin("demon").unwrap();
49 cmd.current_dir(temp_dir.path())
50 .args(&["run", "--id", "test", "echo", "hello"])
51 .assert()
52 .success()
53 .stdout(predicate::str::contains("Started daemon 'test'"));
54
55 // Verify files were created
56 assert!(temp_dir.path().join("test.pid").exists());
57 assert!(temp_dir.path().join("test.stdout").exists());
58 assert!(temp_dir.path().join("test.stderr").exists());
59
60 // Check that stdout contains our output
61 let stdout_content = fs::read_to_string(temp_dir.path().join("test.stdout")).unwrap();
62 assert_eq!(stdout_content.trim(), "hello");
63}
64
65#[test]
66fn test_run_duplicate_process() {
67 let temp_dir = TempDir::new().unwrap();
68
69 // Start a long-running process
70 let mut cmd = Command::cargo_bin("demon").unwrap();
71 cmd.current_dir(temp_dir.path())
72 .args(&["run", "--id", "long", "sleep", "30"])
73 .assert()
74 .success();
75
76 // Try to start another with the same ID
77 let mut cmd = Command::cargo_bin("demon").unwrap();
78 cmd.current_dir(temp_dir.path())
79 .args(&["run", "--id", "long", "sleep", "5"])
80 .assert()
81 .failure()
82 .stderr(predicate::str::contains("already running"));
83
84 // Clean up the running process
85 let mut cmd = Command::cargo_bin("demon").unwrap();
86 cmd.current_dir(temp_dir.path())
87 .args(&["stop", "--id", "long"])
88 .assert()
89 .success();
90}
91
92#[test]
93fn test_list_empty() {
94 let temp_dir = TempDir::new().unwrap();
95
96 let mut cmd = Command::cargo_bin("demon").unwrap();
97 cmd.current_dir(temp_dir.path())
98 .args(&["list"])
99 .assert()
100 .success()
101 .stdout(predicate::str::contains("ID"))
102 .stdout(predicate::str::contains("PID"))
103 .stdout(predicate::str::contains("STATUS"))
104 .stdout(predicate::str::contains("No daemon processes found"));
105}
106
107#[test]
108fn test_list_with_processes() {
109 let temp_dir = TempDir::new().unwrap();
110
111 // Start a process
112 let mut cmd = Command::cargo_bin("demon").unwrap();
113 cmd.current_dir(temp_dir.path())
114 .args(&["run", "--id", "test", "echo", "done"])
115 .assert()
116 .success();
117
118 // List processes
119 let mut cmd = Command::cargo_bin("demon").unwrap();
120 cmd.current_dir(temp_dir.path())
121 .args(&["list"])
122 .assert()
123 .success()
124 .stdout(predicate::str::contains("test"))
125 .stdout(predicate::str::contains("DEAD")); // Process should be finished by now
126}
127
128#[test]
129fn test_cat_output() {
130 let temp_dir = TempDir::new().unwrap();
131
132 // Create a process with output
133 let mut cmd = Command::cargo_bin("demon").unwrap();
134 cmd.current_dir(temp_dir.path())
135 .args(&[
136 "run", "--id", "test", "--",
137 "sh", "-c", "echo 'stdout line'; echo 'stderr line' >&2"
138 ])
139 .assert()
140 .success();
141
142 // Cat the output
143 let mut cmd = Command::cargo_bin("demon").unwrap();
144 cmd.current_dir(temp_dir.path())
145 .args(&["cat", "--id", "test"])
146 .assert()
147 .success()
148 .stdout(predicate::str::contains("stdout line"))
149 .stdout(predicate::str::contains("stderr line"));
150}
151
152#[test]
153fn test_cat_stdout_only() {
154 let temp_dir = TempDir::new().unwrap();
155
156 // Create a process with output
157 let mut cmd = Command::cargo_bin("demon").unwrap();
158 cmd.current_dir(temp_dir.path())
159 .args(&[
160 "run", "--id", "test", "--",
161 "sh", "-c", "echo 'stdout line'; echo 'stderr line' >&2"
162 ])
163 .assert()
164 .success();
165
166 // Cat only stdout
167 let mut cmd = Command::cargo_bin("demon").unwrap();
168 cmd.current_dir(temp_dir.path())
169 .args(&["cat", "--id", "test", "--stdout"])
170 .assert()
171 .success()
172 .stdout(predicate::str::contains("stdout line"))
173 .stdout(predicate::str::contains("stderr line").not());
174}
175
176#[test]
177fn test_status_nonexistent() {
178 let temp_dir = TempDir::new().unwrap();
179
180 let mut cmd = Command::cargo_bin("demon").unwrap();
181 cmd.current_dir(temp_dir.path())
182 .args(&["status", "--id", "nonexistent"])
183 .assert()
184 .success()
185 .stdout(predicate::str::contains("NOT FOUND"));
186}
187
188#[test]
189fn test_status_dead_process() {
190 let temp_dir = TempDir::new().unwrap();
191
192 // Create a short-lived process
193 let mut cmd = Command::cargo_bin("demon").unwrap();
194 cmd.current_dir(temp_dir.path())
195 .args(&["run", "--id", "dead", "echo", "hello"])
196 .assert()
197 .success();
198
199 // Check its status (should be dead)
200 let mut cmd = Command::cargo_bin("demon").unwrap();
201 cmd.current_dir(temp_dir.path())
202 .args(&["status", "--id", "dead"])
203 .assert()
204 .success()
205 .stdout(predicate::str::contains("DEAD"));
206}
207
208#[test]
209fn test_stop_nonexistent() {
210 let temp_dir = TempDir::new().unwrap();
211
212 let mut cmd = Command::cargo_bin("demon").unwrap();
213 cmd.current_dir(temp_dir.path())
214 .args(&["stop", "--id", "nonexistent"])
215 .assert()
216 .success()
217 .stdout(predicate::str::contains("not running"));
218}
219
220#[test]
221fn test_stop_process() {
222 let temp_dir = TempDir::new().unwrap();
223
224 // Start a long-running process
225 let mut cmd = Command::cargo_bin("demon").unwrap();
226 cmd.current_dir(temp_dir.path())
227 .args(&["run", "--id", "long", "sleep", "10"])
228 .assert()
229 .success();
230
231 // Stop it
232 let mut cmd = Command::cargo_bin("demon").unwrap();
233 cmd.current_dir(temp_dir.path())
234 .args(&["stop", "--id", "long"])
235 .assert()
236 .success()
237 .stdout(predicate::str::contains("terminated gracefully"));
238
239 // Verify PID file is gone
240 assert!(!temp_dir.path().join("long.pid").exists());
241}
242
243#[test]
244fn test_clean_no_orphans() {
245 let temp_dir = TempDir::new().unwrap();
246
247 let mut cmd = Command::cargo_bin("demon").unwrap();
248 cmd.current_dir(temp_dir.path())
249 .args(&["clean"])
250 .assert()
251 .success()
252 .stdout(predicate::str::contains("No orphaned files found"));
253}
254
255#[test]
256fn test_clean_with_orphans() {
257 let temp_dir = TempDir::new().unwrap();
258
259 // Create a dead process
260 let mut cmd = Command::cargo_bin("demon").unwrap();
261 cmd.current_dir(temp_dir.path())
262 .args(&["run", "--id", "dead", "echo", "hello"])
263 .assert()
264 .success();
265
266 // Clean up orphaned files
267 let mut cmd = Command::cargo_bin("demon").unwrap();
268 cmd.current_dir(temp_dir.path())
269 .args(&["clean"])
270 .assert()
271 .success()
272 .stdout(predicate::str::contains("Cleaned up"))
273 .stdout(predicate::str::contains("orphaned"));
274
275 // Verify files are gone
276 assert!(!temp_dir.path().join("dead.pid").exists());
277 assert!(!temp_dir.path().join("dead.stdout").exists());
278 assert!(!temp_dir.path().join("dead.stderr").exists());
279}
280
281#[test]
282fn test_run_with_complex_command() {
283 let temp_dir = TempDir::new().unwrap();
284
285 let mut cmd = Command::cargo_bin("demon").unwrap();
286 cmd.current_dir(temp_dir.path())
287 .args(&[
288 "run", "--id", "complex", "--",
289 "sh", "-c", "for i in 1 2 3; do echo \"line $i\"; done"
290 ])
291 .assert()
292 .success();
293
294 // Give the process a moment to complete
295 std::thread::sleep(Duration::from_millis(100));
296
297 // Check the output contains all lines
298 let stdout_content = fs::read_to_string(temp_dir.path().join("complex.stdout")).unwrap();
299 assert!(stdout_content.contains("line 1"));
300 assert!(stdout_content.contains("line 2"));
301 assert!(stdout_content.contains("line 3"));
302}
303
304#[test]
305fn test_timeout_configuration() {
306 let temp_dir = TempDir::new().unwrap();
307
308 // Start a process
309 let mut cmd = Command::cargo_bin("demon").unwrap();
310 cmd.current_dir(temp_dir.path())
311 .args(&["run", "--id", "timeout-test", "sleep", "5"])
312 .assert()
313 .success();
314
315 // Stop with custom timeout (should work normally since sleep responds to SIGTERM)
316 let mut cmd = Command::cargo_bin("demon").unwrap();
317 cmd.current_dir(temp_dir.path())
318 .args(&["stop", "--id", "timeout-test", "--timeout", "2"])
319 .assert()
320 .success()
321 .stdout(predicate::str::contains("terminated gracefully"));
322}
323
324#[test]
325fn test_invalid_process_id() {
326 let temp_dir = TempDir::new().unwrap();
327
328 // Create an invalid PID file
329 fs::write(temp_dir.path().join("invalid.pid"), "not-a-number").unwrap();
330
331 // Status should handle it gracefully
332 let mut cmd = Command::cargo_bin("demon").unwrap();
333 cmd.current_dir(temp_dir.path())
334 .args(&["status", "--id", "invalid"])
335 .assert()
336 .success()
337 .stdout(predicate::str::contains("ERROR"));
338
339 // Clean should remove it
340 let mut cmd = Command::cargo_bin("demon").unwrap();
341 cmd.current_dir(temp_dir.path())
342 .args(&["clean"])
343 .assert()
344 .success()
345 .stdout(predicate::str::contains("invalid PID file"));
346} \ No newline at end of file