Merge lp:~jamesodhunt/ubuntu/precise/upstart/fix-for-bug-912558 into lp:ubuntu/precise/upstart
- Precise (12.04)
- fix-for-bug-912558
- Merge into precise
Proposed by
James Hunt
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 1352 | ||||
Proposed branch: | lp:~jamesodhunt/ubuntu/precise/upstart/fix-for-bug-912558 | ||||
Merge into: | lp:ubuntu/precise/upstart | ||||
Diff against target: |
3355 lines (+685/-766) 10 files modified
ChangeLog (+43/-0) debian/changelog (+8/-2) init/job_process.c (+12/-0) init/log.c (+165/-36) init/log.h (+6/-0) init/main.c (+0/-10) init/man/init.5 (+8/-7) init/tests/test_job_process.c (+293/-18) init/tests/test_log.c (+150/-140) util/tests/test_user_sessions.sh (+0/-553) |
||||
To merge this branch: | bzr merge lp:~jamesodhunt/ubuntu/precise/upstart/fix-for-bug-912558 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson | Approve | ||
Review via email: mp+90278@code.launchpad.net |
Commit message
Description of the change
[ Stéphane Graber ]
* Mark upstart Multi-Arch:foreign
[ James Hunt ]
* Merge of important logger fixes from upstream lp:upstart
(LP: #912558).
* Reverted temporary fix to disable job logging.
To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'ChangeLog' | |||
2 | --- ChangeLog 2011-12-22 16:52:22 +0000 | |||
3 | +++ ChangeLog 2012-01-26 15:59:26 +0000 | |||
4 | @@ -1,3 +1,46 @@ | |||
5 | 1 | 2012-01-25 James Hunt <james.hunt@ubuntu.com> | ||
6 | 2 | |||
7 | 3 | * init/job_process.c: job_process_terminated(): Free log to ensure data | ||
8 | 4 | written as soon as _any_ process ends (consider respawn jobs). | ||
9 | 5 | * init/log.c: | ||
10 | 6 | - log_destroy(): | ||
11 | 7 | - Improved documentation. | ||
12 | 8 | - Now calls new function log_flush(). | ||
13 | 9 | - log_flush(): New function to ensure no lingering buffered job data | ||
14 | 10 | remains. Now considers EBADF (LP: #912558). | ||
15 | 11 | - log_io_reader(): | ||
16 | 12 | - Added missing assert for @len. | ||
17 | 13 | - Simplified ENOSPC handling. | ||
18 | 14 | - Ensure log->io set to NULL to allow other routines to detect it | ||
19 | 15 | really has gone. | ||
20 | 16 | - log_file_write(): Added @len checks. | ||
21 | 17 | - log_read_watch(): New function to drain data from a watch descriptor | ||
22 | 18 | (which also must consider EBADF). | ||
23 | 19 | * init/log.h: Added define for LOG_READ_SIZE. | ||
24 | 20 | * init/tests/test_job_process.c: | ||
25 | 21 | - test_run(): | ||
26 | 22 | - Added some extra pointer checks. | ||
27 | 23 | - Free class *before* checking file to ensure destructor invoked at | ||
28 | 24 | correct point. | ||
29 | 25 | - Added test "with single-line command running an invalid command" | ||
30 | 26 | (for scenario bug 912558 exposed). | ||
31 | 27 | - Added test "with single-line command writing fast and exiting". | ||
32 | 28 | * init/tests/test_log.c: Changed all tests to use openpty(3) rather than | ||
33 | 29 | pipe(2) for semantic parity with actual code. | ||
34 | 30 | * util/tests/test_user_sessions.sh: | ||
35 | 31 | - ensure_no_output(): Now calls check_job_output() and delete_job() to | ||
36 | 32 | simplify logic. | ||
37 | 33 | - delete_job(): Call get_job_file() rather than doing it long-hand. | ||
38 | 34 | - check_job_output(): New function. | ||
39 | 35 | - start_job(): Added allow_failure parameter. | ||
40 | 36 | - test_ensure_no_unexpected_output(): New test | ||
41 | 37 | "ensure command job does not create log file with invalid command". | ||
42 | 38 | |||
43 | 39 | 2012-01-05 James Hunt <james.hunt@ubuntu.com> | ||
44 | 40 | |||
45 | 41 | * init/man/init.5: Explain that all job processes affected | ||
46 | 42 | by 'setuid' and 'setgid' stanzas. | ||
47 | 43 | |||
48 | 1 | 2011-12-22 James Hunt <james.hunt@ubuntu.com> | 44 | 2011-12-22 James Hunt <james.hunt@ubuntu.com> |
49 | 2 | 45 | ||
50 | 3 | * init/job_process.c: job_process_spawn(): | 46 | * init/job_process.c: job_process_spawn(): |
51 | 4 | 47 | ||
52 | === modified file 'debian/changelog' | |||
53 | --- debian/changelog 2012-01-09 10:10:08 +0000 | |||
54 | +++ debian/changelog 2012-01-26 15:59:26 +0000 | |||
55 | @@ -1,8 +1,14 @@ | |||
57 | 1 | upstart (1.4-0ubuntu3) UNRELEASED; urgency=low | 1 | upstart (1.4-0ubuntu3) precise; urgency=low |
58 | 2 | 2 | ||
59 | 3 | [ Stéphane Graber ] | ||
60 | 3 | * Mark upstart Multi-Arch:foreign | 4 | * Mark upstart Multi-Arch:foreign |
61 | 4 | 5 | ||
63 | 5 | -- Stéphane Graber <stgraber@ubuntu.com> Mon, 09 Jan 2012 11:08:27 +0100 | 6 | [ James Hunt ] |
64 | 7 | * Merge of important logger fixes from upstream lp:upstart | ||
65 | 8 | (LP: #912558). | ||
66 | 9 | * Reverted temporary fix to disable job logging. | ||
67 | 10 | |||
68 | 11 | -- James Hunt <james.hunt@ubuntu.com> Thu, 26 Jan 2012 15:13:25 +0000 | ||
69 | 6 | 12 | ||
70 | 7 | upstart (1.4-0ubuntu2) precise; urgency=low | 13 | upstart (1.4-0ubuntu2) precise; urgency=low |
71 | 8 | 14 | ||
72 | 9 | 15 | ||
73 | === modified file 'init/job_process.c' | |||
74 | --- init/job_process.c 2011-12-22 16:52:22 +0000 | |||
75 | +++ init/job_process.c 2012-01-26 15:59:26 +0000 | |||
76 | @@ -1571,6 +1571,18 @@ | |||
77 | 1571 | job->kill_process = -1; | 1571 | job->kill_process = -1; |
78 | 1572 | } | 1572 | } |
79 | 1573 | 1573 | ||
80 | 1574 | if (job->class->console == CONSOLE_LOG) { | ||
81 | 1575 | /* It is imperative that we free the log at this stage to ensure | ||
82 | 1576 | * that jobs which respawn have their log written _now_ | ||
83 | 1577 | * (and not just when the overall Job object is freed at | ||
84 | 1578 | * some distant future point). | ||
85 | 1579 | */ | ||
86 | 1580 | if (job->log) { | ||
87 | 1581 | nih_free (job->log); | ||
88 | 1582 | job->log = NULL; | ||
89 | 1583 | } | ||
90 | 1584 | } | ||
91 | 1585 | |||
92 | 1574 | /* Find existing utmp entry for the process pid */ | 1586 | /* Find existing utmp entry for the process pid */ |
93 | 1575 | setutxent(); | 1587 | setutxent(); |
94 | 1576 | while ((utmptr = getutxent()) != NULL) { | 1588 | while ((utmptr = getutxent()) != NULL) { |
95 | 1577 | 1589 | ||
96 | === modified file 'init/log.c' | |||
97 | --- init/log.c 2011-12-15 17:50:14 +0000 | |||
98 | +++ init/log.c 2012-01-26 15:59:26 +0000 | |||
99 | @@ -35,6 +35,8 @@ | |||
100 | 35 | 35 | ||
101 | 36 | static int log_file_open (Log *log); | 36 | static int log_file_open (Log *log); |
102 | 37 | static int log_file_write (Log *log, const char *buf, size_t len); | 37 | static int log_file_write (Log *log, const char *buf, size_t len); |
103 | 38 | static void log_read_watch (Log *log); | ||
104 | 39 | static void log_flush (Log *log); | ||
105 | 38 | 40 | ||
106 | 39 | /** | 41 | /** |
107 | 40 | * log_new: | 42 | * log_new: |
108 | @@ -140,11 +142,54 @@ | |||
109 | 140 | * @log: Log. | 142 | * @log: Log. |
110 | 141 | * | 143 | * |
111 | 142 | * Called automatically when Log is being destroyed. | 144 | * Called automatically when Log is being destroyed. |
112 | 145 | * | ||
113 | 146 | * XXX: Note that the fd associated with the jobs stdout and stderr (as | ||
114 | 147 | * passed to log_new()) *MUST* be closed by the time this function is | ||
115 | 148 | * called since it will continue to read from the fd until an error is | ||
116 | 149 | * detected. This behaviour is required to ensure all job output is | ||
117 | 150 | * read. | ||
118 | 151 | * | ||
119 | 152 | * Returns: 0 always. | ||
120 | 143 | **/ | 153 | **/ |
121 | 144 | int | 154 | int |
122 | 145 | log_destroy (Log *log) | 155 | log_destroy (Log *log) |
123 | 146 | { | 156 | { |
124 | 157 | nih_assert (log); | ||
125 | 158 | |||
126 | 159 | /* User job logging not currently available */ | ||
127 | 160 | nih_assert (log->uid == 0); | ||
128 | 161 | |||
129 | 162 | log_flush (log); | ||
130 | 163 | |||
131 | 164 | /* Force file to flush */ | ||
132 | 165 | if (log->fd != -1) | ||
133 | 166 | close (log->fd); | ||
134 | 167 | |||
135 | 168 | log->fd = -1; | ||
136 | 169 | |||
137 | 170 | return 0; | ||
138 | 171 | } | ||
139 | 172 | |||
140 | 173 | /** | ||
141 | 174 | * log_flush: | ||
142 | 175 | * | ||
143 | 176 | * @log: Log. | ||
144 | 177 | * | ||
145 | 178 | * Ensure that no job output data is buffered and attempt to flush all | ||
146 | 179 | * unflushed data to disk. | ||
147 | 180 | * | ||
148 | 181 | * It is safe to call this function multiple times and may in fact be | ||
149 | 182 | * necessary if the log file cannot be written for any reason. | ||
150 | 183 | * | ||
151 | 184 | * Note no return value since there isn't much that can be done at | ||
152 | 185 | * the point this function is called should the flushing operations | ||
153 | 186 | * fail. | ||
154 | 187 | **/ | ||
155 | 188 | static void | ||
156 | 189 | log_flush (Log *log) | ||
157 | 190 | { | ||
158 | 147 | int ret; | 191 | int ret; |
159 | 192 | int flags; | ||
160 | 148 | 193 | ||
161 | 149 | nih_assert (log); | 194 | nih_assert (log); |
162 | 150 | 195 | ||
163 | @@ -162,21 +207,49 @@ | |||
164 | 162 | goto out; | 207 | goto out; |
165 | 163 | 208 | ||
166 | 164 | ret = log_file_write (log, NULL, 0); | 209 | ret = log_file_write (log, NULL, 0); |
168 | 165 | if (ret < 0) | 210 | if (ret < 0) { |
169 | 211 | close (log->fd); | ||
170 | 212 | log->fd = -1; | ||
171 | 166 | goto out; | 213 | goto out; |
180 | 167 | } | 214 | } |
181 | 168 | 215 | } | |
182 | 169 | /* Force file to flush | 216 | |
183 | 170 | * | 217 | if (log->io) { |
184 | 171 | * Only attempt this for jobs which the current process is | 218 | nih_assert (log->io->watch); |
185 | 172 | * in control of. | 219 | |
186 | 173 | */ | 220 | /* If the job associated with this log produces output _after_ |
187 | 174 | if (log->fd > 0) | 221 | * nih_io_handle_fds() has been called in any loop of the main |
188 | 222 | * loop and just before the job is destroyed, we will miss it. | ||
189 | 223 | * | ||
190 | 224 | * Therefore, attempt to read from the watch fd until we get an error. | ||
191 | 225 | */ | ||
192 | 226 | log_read_watch (log); | ||
193 | 227 | |||
194 | 228 | flags = fcntl (log->io->watch->fd, F_GETFL); | ||
195 | 229 | |||
196 | 230 | if (flags < 0 && errno == EBADF) { | ||
197 | 231 | /* The watch fd is now known to be invalid, so disable | ||
198 | 232 | * the error handler to avoid an infinite loop where the | ||
199 | 233 | * error handler attempts to free the NihIo, which would | ||
200 | 234 | * error, causing the error handler to be called | ||
201 | 235 | * ad infinitum. | ||
202 | 236 | * | ||
203 | 237 | * Note that the NihIo is freed via | ||
204 | 238 | * nih_io_destroy(). | ||
205 | 239 | */ | ||
206 | 240 | log->io->error_handler = NULL; | ||
207 | 241 | |||
208 | 242 | nih_free (log->io); | ||
209 | 243 | log->io = NULL; | ||
210 | 244 | } | ||
211 | 245 | } | ||
212 | 246 | |||
213 | 247 | /* Force file to flush */ | ||
214 | 248 | if (log->fd != -1) | ||
215 | 175 | close (log->fd); | 249 | close (log->fd); |
216 | 176 | 250 | ||
217 | 177 | out: | 251 | out: |
218 | 178 | log->fd = -1; | 252 | log->fd = -1; |
219 | 179 | return 0; | ||
220 | 180 | } | 253 | } |
221 | 181 | 254 | ||
222 | 182 | /** | 255 | /** |
223 | @@ -191,7 +264,7 @@ | |||
224 | 191 | * encapsulated in @io. | 264 | * encapsulated in @io. |
225 | 192 | * | 265 | * |
226 | 193 | * Notes for user jobs: | 266 | * Notes for user jobs: |
228 | 194 | 267 | * | |
229 | 195 | * User jobs by necessity are handled differently to system jobs. Since | 268 | * User jobs by necessity are handled differently to system jobs. Since |
230 | 196 | * a user job must log their data to files owned by a non-root user, the | 269 | * a user job must log their data to files owned by a non-root user, the |
231 | 197 | * safest technique is for a process running as that user to create the | 270 | * safest technique is for a process running as that user to create the |
232 | @@ -223,45 +296,37 @@ | |||
233 | 223 | nih_assert (io); | 296 | nih_assert (io); |
234 | 224 | nih_assert (log->io == io); | 297 | nih_assert (log->io == io); |
235 | 225 | nih_assert (buf); | 298 | nih_assert (buf); |
236 | 299 | nih_assert (len); | ||
237 | 226 | 300 | ||
238 | 227 | /* User job logging not currently available */ | 301 | /* User job logging not currently available */ |
239 | 228 | nih_assert (log->uid == 0); | 302 | nih_assert (log->uid == 0); |
240 | 229 | 303 | ||
241 | 230 | /* Note we don't assert @len in case we are being called after | ||
242 | 231 | * an error is detected (where there is no new data, but may be | ||
243 | 232 | * unflushed data). | ||
244 | 233 | */ | ||
245 | 234 | |||
246 | 235 | /* Just in case we try to write more than read can inform us | 304 | /* Just in case we try to write more than read can inform us |
247 | 236 | * about (this should really be a build-time assertion). | 305 | * about (this should really be a build-time assertion). |
248 | 237 | */ | 306 | */ |
249 | 238 | nih_assert (sizeof (size_t) == sizeof (ssize_t)); | 307 | nih_assert (sizeof (size_t) == sizeof (ssize_t)); |
250 | 239 | 308 | ||
251 | 240 | if (log_file_open (log) < 0) { | 309 | if (log_file_open (log) < 0) { |
257 | 241 | if (errno == ENOSPC) { | 310 | if (errno != ENOSPC) { |
253 | 242 | /* Always discard when out of space */ | ||
254 | 243 | nih_io_buffer_shrink (io->recv_buf, len); | ||
255 | 244 | return; | ||
256 | 245 | } else { | ||
258 | 246 | /* Add new data to unflushed buffer */ | 311 | /* Add new data to unflushed buffer */ |
259 | 247 | if (nih_io_buffer_push (log->unflushed, buf, len) < 0) | 312 | if (nih_io_buffer_push (log->unflushed, buf, len) < 0) |
260 | 248 | return; | 313 | return; |
261 | 249 | |||
262 | 250 | nih_io_buffer_shrink (io->recv_buf, len); | ||
263 | 251 | /* No point attempting to write if we cannot | ||
264 | 252 | * open the file. | ||
265 | 253 | */ | ||
266 | 254 | return; | ||
267 | 255 | } | 314 | } |
268 | 315 | |||
269 | 316 | /* Note that we always discard when out of space */ | ||
270 | 317 | nih_io_buffer_shrink (io->recv_buf, len); | ||
271 | 318 | |||
272 | 319 | /* No point attempting to write if we cannot | ||
273 | 320 | * open the file. | ||
274 | 321 | */ | ||
275 | 322 | return; | ||
276 | 256 | } | 323 | } |
277 | 257 | 324 | ||
278 | 258 | ret = log_file_write (log, buf, len); | 325 | ret = log_file_write (log, buf, len); |
280 | 259 | if (ret < 0) { | 326 | if (ret < 0) |
281 | 260 | nih_warn ("%s %s", _("Failed to write to log file"), log->path); | 327 | nih_warn ("%s %s", _("Failed to write to log file"), log->path); |
282 | 261 | } | ||
283 | 262 | } | 328 | } |
284 | 263 | 329 | ||
285 | 264 | |||
286 | 265 | /** | 330 | /** |
287 | 266 | * log_io_error_handler: | 331 | * log_io_error_handler: |
288 | 267 | * | 332 | * |
289 | @@ -289,12 +354,12 @@ | |||
290 | 289 | err = nih_error_get (); | 354 | err = nih_error_get (); |
291 | 290 | 355 | ||
292 | 291 | nih_assert (err->number == EIO); | 356 | nih_assert (err->number == EIO); |
293 | 357 | |||
294 | 292 | nih_free (err); | 358 | nih_free (err); |
295 | 293 | 359 | ||
300 | 294 | if (log->io) { | 360 | /* Ensure the NihIo is closed */ |
301 | 295 | /* Close the connection */ | 361 | nih_free (log->io); |
302 | 296 | nih_free (log->io); | 362 | log->io = NULL; |
299 | 297 | } | ||
303 | 298 | } | 363 | } |
304 | 299 | 364 | ||
305 | 300 | /** | 365 | /** |
306 | @@ -448,10 +513,12 @@ | |||
307 | 448 | * Note that data is always discarded when out of | 513 | * Note that data is always discarded when out of |
308 | 449 | * space. | 514 | * space. |
309 | 450 | */ | 515 | */ |
311 | 451 | if (saved != ENOSPC && nih_io_buffer_push (log->unflushed, buf, len) < 0) | 516 | if (saved != ENOSPC && len |
312 | 517 | && nih_io_buffer_push (log->unflushed, buf, len) < 0) | ||
313 | 452 | goto error; | 518 | goto error; |
314 | 453 | 519 | ||
316 | 454 | nih_io_buffer_shrink (io->recv_buf, len); | 520 | if (len) |
317 | 521 | nih_io_buffer_shrink (io->recv_buf, len); | ||
318 | 455 | 522 | ||
319 | 456 | /* Still need to indicate that the write failed */ | 523 | /* Still need to indicate that the write failed */ |
320 | 457 | goto error; | 524 | goto error; |
321 | @@ -466,6 +533,9 @@ | |||
322 | 466 | * next time. | 533 | * next time. |
323 | 467 | */ | 534 | */ |
324 | 468 | if (log->unflushed->len) { | 535 | if (log->unflushed->len) { |
325 | 536 | if (! len) | ||
326 | 537 | goto error; | ||
327 | 538 | |||
328 | 469 | /* Save new data */ | 539 | /* Save new data */ |
329 | 470 | if (nih_io_buffer_push (log->unflushed, buf, len) < 0) | 540 | if (nih_io_buffer_push (log->unflushed, buf, len) < 0) |
330 | 471 | goto error; | 541 | goto error; |
331 | @@ -504,3 +574,62 @@ | |||
332 | 504 | return -1; | 574 | return -1; |
333 | 505 | } | 575 | } |
334 | 506 | 576 | ||
335 | 577 | /** | ||
336 | 578 | * log_read_watch: | ||
337 | 579 | * | ||
338 | 580 | * @log: Log. | ||
339 | 581 | * | ||
340 | 582 | * Attempt a final read from the watch descriptor to ensure we've | ||
341 | 583 | * drained all the data from the job. | ||
342 | 584 | **/ | ||
343 | 585 | void | ||
344 | 586 | log_read_watch (Log *log) | ||
345 | 587 | { | ||
346 | 588 | NihIo *io; | ||
347 | 589 | ssize_t len; | ||
348 | 590 | int saved; | ||
349 | 591 | |||
350 | 592 | nih_assert (log); | ||
351 | 593 | |||
352 | 594 | /* Must not be called if there is unflushed data as the log | ||
353 | 595 | * would then not be written in order . | ||
354 | 596 | */ | ||
355 | 597 | nih_assert (! log->unflushed->len); | ||
356 | 598 | |||
357 | 599 | io = log->io; | ||
358 | 600 | |||
359 | 601 | if (! io) | ||
360 | 602 | return; | ||
361 | 603 | |||
362 | 604 | while (1) { | ||
363 | 605 | /* Ensure we have some space to read data from the job */ | ||
364 | 606 | if (nih_io_buffer_resize (io->recv_buf, LOG_READ_SIZE) < 0) | ||
365 | 607 | break; | ||
366 | 608 | |||
367 | 609 | /* Append to buffer */ | ||
368 | 610 | len = read (io->watch->fd, | ||
369 | 611 | io->recv_buf->buf + io->recv_buf->len, | ||
370 | 612 | io->recv_buf->size - io->recv_buf->len); | ||
371 | 613 | saved = errno; | ||
372 | 614 | |||
373 | 615 | if (len > 0) | ||
374 | 616 | io->recv_buf->len += len; | ||
375 | 617 | |||
376 | 618 | if (io->recv_buf->len) | ||
377 | 619 | log_io_reader (log, io, io->recv_buf->buf, io->recv_buf->len); | ||
378 | 620 | |||
379 | 621 | /* If an error occurs, it is likely to be EIO or EBADF. | ||
380 | 622 | * But erring on the side of caution, any unusual error | ||
381 | 623 | * causes the loop to be exited. | ||
382 | 624 | */ | ||
383 | 625 | if ((len < 0 && saved != EAGAIN && saved != EWOULDBLOCK) || len == 0) { | ||
384 | 626 | /* Either the job process end of the pty has | ||
385 | 627 | * been closed, or there really | ||
386 | 628 | * is no (more) data to be read. | ||
387 | 629 | */ | ||
388 | 630 | close (log->fd); | ||
389 | 631 | log->fd = -1; | ||
390 | 632 | break; | ||
391 | 633 | } | ||
392 | 634 | } | ||
393 | 635 | } | ||
394 | 507 | 636 | ||
395 | === modified file 'init/log.h' | |||
396 | --- init/log.h 2011-12-09 14:07:11 +0000 | |||
397 | +++ init/log.h 2012-01-26 15:59:26 +0000 | |||
398 | @@ -41,6 +41,12 @@ | |||
399 | 41 | **/ | 41 | **/ |
400 | 42 | #define LOG_DEFAULT_MODE (S_IRWXU | S_IRGRP) | 42 | #define LOG_DEFAULT_MODE (S_IRWXU | S_IRGRP) |
401 | 43 | 43 | ||
402 | 44 | /** LOG_READ_SIZE: | ||
403 | 45 | * | ||
404 | 46 | * Minimum buffer size for reading log data. | ||
405 | 47 | **/ | ||
406 | 48 | #define LOG_READ_SIZE 1024 | ||
407 | 49 | |||
408 | 44 | /** | 50 | /** |
409 | 45 | * Log: | 51 | * Log: |
410 | 46 | * | 52 | * |
411 | 47 | 53 | ||
412 | === modified file 'init/main.c' | |||
413 | --- init/main.c 2012-01-06 16:12:52 +0000 | |||
414 | +++ init/main.c 2012-01-26 15:59:26 +0000 | |||
415 | @@ -121,7 +121,6 @@ | |||
416 | 121 | 121 | ||
417 | 122 | extern int disable_sessions; | 122 | extern int disable_sessions; |
418 | 123 | extern int disable_job_logging; | 123 | extern int disable_job_logging; |
419 | 124 | int force_logging; | ||
420 | 125 | extern int use_session_bus; | 124 | extern int use_session_bus; |
421 | 126 | extern int default_console; | 125 | extern int default_console; |
422 | 127 | extern char *log_dir; | 126 | extern char *log_dir; |
423 | @@ -139,9 +138,6 @@ | |||
424 | 139 | { 0, "default-console", N_("default value for console stanza"), | 138 | { 0, "default-console", N_("default value for console stanza"), |
425 | 140 | NULL, "VALUE", NULL, console_type_setter }, | 139 | NULL, "VALUE", NULL, console_type_setter }, |
426 | 141 | 140 | ||
427 | 142 | { 0, "log", N_("enable job logging"), | ||
428 | 143 | NULL, NULL, &force_logging, NULL }, | ||
429 | 144 | |||
430 | 145 | { 0, "logdir", N_("specify alternative directory to store job output logs in"), | 141 | { 0, "logdir", N_("specify alternative directory to store job output logs in"), |
431 | 146 | NULL, "DIR", &log_dir, NULL }, | 142 | NULL, "DIR", &log_dir, NULL }, |
432 | 147 | 143 | ||
433 | @@ -185,9 +181,6 @@ | |||
434 | 185 | "process id 1 to denote its special status. When executed " | 181 | "process id 1 to denote its special status. When executed " |
435 | 186 | "by a user process, it will actually run /sbin/telinit.")); | 182 | "by a user process, it will actually run /sbin/telinit.")); |
436 | 187 | 183 | ||
437 | 188 | /* Temporarily disable job logging (bug 912558) */ | ||
438 | 189 | disable_job_logging = 1; | ||
439 | 190 | |||
440 | 191 | args = nih_option_parser (NULL, argc, argv, options, FALSE); | 184 | args = nih_option_parser (NULL, argc, argv, options, FALSE); |
441 | 192 | if (! args) | 185 | if (! args) |
442 | 193 | exit (1); | 186 | exit (1); |
443 | @@ -195,9 +188,6 @@ | |||
444 | 195 | handle_confdir (); | 188 | handle_confdir (); |
445 | 196 | handle_logdir (); | 189 | handle_logdir (); |
446 | 197 | 190 | ||
447 | 198 | if (force_logging) | ||
448 | 199 | disable_job_logging = 0; | ||
449 | 200 | |||
450 | 201 | if (disable_job_logging) | 191 | if (disable_job_logging) |
451 | 202 | nih_debug ("Job logging disabled"); | 192 | nih_debug ("Job logging disabled"); |
452 | 203 | 193 | ||
453 | 204 | 194 | ||
454 | === modified file 'init/man/init.5' | |||
455 | --- init/man/init.5 2011-12-15 17:50:14 +0000 | |||
456 | +++ init/man/init.5 2012-01-26 15:59:26 +0000 | |||
457 | @@ -761,10 +761,10 @@ | |||
458 | 761 | .B setuid \fIUSERNAME | 761 | .B setuid \fIUSERNAME |
459 | 762 | Changes to the user | 762 | Changes to the user |
460 | 763 | .I USERNAME | 763 | .I USERNAME |
462 | 764 | before running the job's process. | 764 | before running any job process. |
463 | 765 | 765 | ||
466 | 766 | If this stanza is unspecified, the job will run as root in the case of | 766 | If this stanza is unspecified, all job processes will run as root in the |
467 | 767 | system jobs, and as the user in the case of user jobs. | 767 | case of system jobs, and as the user in the case of user jobs. |
468 | 768 | 768 | ||
469 | 769 | Note that system jobs using the | 769 | Note that system jobs using the |
470 | 770 | .B setuid | 770 | .B setuid |
471 | @@ -777,14 +777,15 @@ | |||
472 | 777 | .B setgid \fIGROUPNAME | 777 | .B setgid \fIGROUPNAME |
473 | 778 | Changes to the group | 778 | Changes to the group |
474 | 779 | .I GROUPNAME | 779 | .I GROUPNAME |
476 | 780 | before running the job's process. | 780 | before running any job process. |
477 | 781 | 781 | ||
478 | 782 | If this stanza is unspecified, the primary group of the user specified | 782 | If this stanza is unspecified, the primary group of the user specified |
479 | 783 | in the | 783 | in the |
480 | 784 | .B setuid | 784 | .B setuid |
484 | 785 | block is used. If both stanzas are unspecified, the job will run with | 785 | block is used for all job processes. If both stanzas are unspecified, |
485 | 786 | its group ID set to 0 in the case of system jobs, and as the primary | 786 | all job processes will run with its group ID set to 0 in the case of |
486 | 787 | group of the user in the case of User Jobs. | 787 | system jobs, and as the primary group of the user in the case of User |
487 | 788 | Jobs. | ||
488 | 788 | .\" | 789 | .\" |
489 | 789 | .SS Override File Handling | 790 | .SS Override File Handling |
490 | 790 | Override files allow a jobs environment to be changed without modifying | 791 | Override files allow a jobs environment to be changed without modifying |
491 | 791 | 792 | ||
492 | === modified file 'init/tests/test_job_process.c' | |||
493 | --- init/tests/test_job_process.c 2011-12-22 16:52:22 +0000 | |||
494 | +++ init/tests/test_job_process.c 2012-01-26 15:59:26 +0000 | |||
495 | @@ -296,13 +296,21 @@ | |||
496 | 296 | char *p; | 296 | char *p; |
497 | 297 | int ok; | 297 | int ok; |
498 | 298 | char buffer[1024]; | 298 | char buffer[1024]; |
500 | 299 | 299 | pid_t pid; | |
501 | 300 | 300 | ||
502 | 301 | TEST_FUNCTION ("job_process_run"); | 301 | TEST_FUNCTION ("job_process_run"); |
503 | 302 | 302 | ||
504 | 303 | TEST_FILENAME (filename); | 303 | TEST_FILENAME (filename); |
505 | 304 | program_name = "test"; | 304 | program_name = "test"; |
506 | 305 | 305 | ||
507 | 306 | TEST_FILENAME (dirname); | ||
508 | 307 | TEST_EQ (mkdir (dirname, 0755), 0); | ||
509 | 308 | |||
510 | 309 | /* Override default location to ensure job output goes to a | ||
511 | 310 | * writeable location | ||
512 | 311 | */ | ||
513 | 312 | TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); | ||
514 | 313 | |||
515 | 306 | /* Check that we can run a simple command, and have the process id | 314 | /* Check that we can run a simple command, and have the process id |
516 | 307 | * and state filled in. We should be able to wait for the pid to | 315 | * and state filled in. We should be able to wait for the pid to |
517 | 308 | * finish and see that it has been run as expected. | 316 | * finish and see that it has been run as expected. |
518 | @@ -1277,6 +1285,8 @@ | |||
519 | 1277 | class->process[PROCESS_MAIN]->script = FALSE; | 1285 | class->process[PROCESS_MAIN]->script = FALSE; |
520 | 1278 | 1286 | ||
521 | 1279 | job = job_new (class, ""); | 1287 | job = job_new (class, ""); |
522 | 1288 | TEST_NE_P (job, NULL); | ||
523 | 1289 | |||
524 | 1280 | job->goal = JOB_START; | 1290 | job->goal = JOB_START; |
525 | 1281 | job->state = JOB_SPAWNED; | 1291 | job->state = JOB_SPAWNED; |
526 | 1282 | 1292 | ||
527 | @@ -1293,6 +1303,9 @@ | |||
528 | 1293 | TEST_TRUE (WIFSIGNALED (status)); | 1303 | TEST_TRUE (WIFSIGNALED (status)); |
529 | 1294 | TEST_EQ (WTERMSIG (status), SIGKILL); | 1304 | TEST_EQ (WTERMSIG (status), SIGKILL); |
530 | 1295 | 1305 | ||
531 | 1306 | /* allow destructor to write any lingering unflushed data */ | ||
532 | 1307 | nih_free (class); | ||
533 | 1308 | |||
534 | 1296 | TEST_EQ (stat (filename, &statbuf), 0); | 1309 | TEST_EQ (stat (filename, &statbuf), 0); |
535 | 1297 | 1310 | ||
536 | 1298 | TEST_TRUE (S_ISREG (statbuf.st_mode)); | 1311 | TEST_TRUE (S_ISREG (statbuf.st_mode)); |
537 | @@ -1333,7 +1346,6 @@ | |||
538 | 1333 | fclose (output); | 1346 | fclose (output); |
539 | 1334 | 1347 | ||
540 | 1335 | TEST_EQ (unlink (filename), 0); | 1348 | TEST_EQ (unlink (filename), 0); |
541 | 1336 | nih_free (class); | ||
542 | 1337 | 1349 | ||
543 | 1338 | /************************************************************/ | 1350 | /************************************************************/ |
544 | 1339 | TEST_FEATURE ("with multi-line script that is killed"); | 1351 | TEST_FEATURE ("with multi-line script that is killed"); |
545 | @@ -2523,14 +2535,36 @@ | |||
546 | 2523 | nih_free (class); | 2535 | nih_free (class); |
547 | 2524 | 2536 | ||
548 | 2525 | /************************************************************ | 2537 | /************************************************************ |
556 | 2526 | * No point in running a test for: | 2538 | * Superficially, there seems little point in running a test for |
557 | 2527 | * | 2539 | * this scenario since if Upstart attempts to exec(2) directly a |
558 | 2528 | * TEST_FEATURE ("with single-line command running an invalid command"); | 2540 | * command that does not exist, the exec simply fails (since |
559 | 2529 | * | 2541 | * there is no shell to report the error). |
560 | 2530 | * Since as such commands are exec'ed directly, there is no shell to report | 2542 | * |
561 | 2531 | * an error back - exec just fails. | 2543 | * And yet -- ironically -- bug 912558 would have been prevented |
562 | 2532 | * | 2544 | * had we originally tested this scenario! |
563 | 2533 | ************************************************************/ | 2545 | ************************************************************/ |
564 | 2546 | TEST_FEATURE ("with single-line command running an invalid command"); | ||
565 | 2547 | |||
566 | 2548 | class = job_class_new (NULL, "buzz", NULL); | ||
567 | 2549 | TEST_NE_P (class, NULL); | ||
568 | 2550 | |||
569 | 2551 | TEST_FILENAME (filename); | ||
570 | 2552 | TEST_GT (sprintf (filename, "%s/buzz.log", dirname), 0); | ||
571 | 2553 | |||
572 | 2554 | class->console = CONSOLE_LOG; | ||
573 | 2555 | class->process[PROCESS_MAIN] = process_new (class); | ||
574 | 2556 | class->process[PROCESS_MAIN]->command = nih_strdup ( | ||
575 | 2557 | class->process[PROCESS_MAIN], | ||
576 | 2558 | "/this/command/does/not/exist"); | ||
577 | 2559 | class->process[PROCESS_MAIN]->script = FALSE; | ||
578 | 2560 | |||
579 | 2561 | job = job_new (class, ""); | ||
580 | 2562 | job->goal = JOB_START; | ||
581 | 2563 | job->state = JOB_SPAWNED; | ||
582 | 2564 | |||
583 | 2565 | ret = job_process_run (job, PROCESS_MAIN); | ||
584 | 2566 | TEST_LT (ret, 0); | ||
585 | 2567 | nih_free (class); | ||
586 | 2534 | 2568 | ||
587 | 2535 | /************************************************************/ | 2569 | /************************************************************/ |
588 | 2536 | TEST_FEATURE ("with multi-line script running an invalid command"); | 2570 | TEST_FEATURE ("with multi-line script running an invalid command"); |
589 | @@ -2713,6 +2747,246 @@ | |||
590 | 2713 | TEST_EQ (unlink (filename), 0); | 2747 | TEST_EQ (unlink (filename), 0); |
591 | 2714 | nih_free (class); | 2748 | nih_free (class); |
592 | 2715 | 2749 | ||
593 | 2750 | /************************************************************/ | ||
594 | 2751 | /* XXX: Note that we don't force a watch update here to simulate | ||
595 | 2752 | * a job that writes data _after_ Upstart has run nih_io_handle_fds() | ||
596 | 2753 | * in the main loop and just _before_ it exits _in the same main | ||
597 | 2754 | * loop iteration_. | ||
598 | 2755 | */ | ||
599 | 2756 | TEST_FEATURE ("with single line command writing fast and exiting"); | ||
600 | 2757 | |||
601 | 2758 | class = job_class_new (NULL, "budapest", NULL); | ||
602 | 2759 | TEST_NE_P (class, NULL); | ||
603 | 2760 | |||
604 | 2761 | TEST_FILENAME (filename); | ||
605 | 2762 | TEST_GT (sprintf (filename, "%s/budapest.log", dirname), 0); | ||
606 | 2763 | |||
607 | 2764 | class->console = CONSOLE_LOG; | ||
608 | 2765 | class->process[PROCESS_MAIN] = process_new (class); | ||
609 | 2766 | /* program to run "fast", so directly exec a program with | ||
610 | 2767 | * no shell intervention. | ||
611 | 2768 | */ | ||
612 | 2769 | class->process[PROCESS_MAIN]->command = nih_sprintf ( | ||
613 | 2770 | class->process[PROCESS_MAIN], | ||
614 | 2771 | "%s hello\n", | ||
615 | 2772 | TEST_CMD_ECHO); | ||
616 | 2773 | class->process[PROCESS_MAIN]->script = FALSE; | ||
617 | 2774 | |||
618 | 2775 | job = job_new (class, ""); | ||
619 | 2776 | job->goal = JOB_START; | ||
620 | 2777 | job->state = JOB_SPAWNED; | ||
621 | 2778 | |||
622 | 2779 | ret = job_process_run (job, PROCESS_MAIN); | ||
623 | 2780 | TEST_EQ (ret, 0); | ||
624 | 2781 | |||
625 | 2782 | /* allow destructor to write any lingering unflushed data */ | ||
626 | 2783 | nih_free (class); | ||
627 | 2784 | |||
628 | 2785 | TEST_EQ (stat (filename, &statbuf), 0); | ||
629 | 2786 | |||
630 | 2787 | TEST_TRUE (S_ISREG (statbuf.st_mode)); | ||
631 | 2788 | |||
632 | 2789 | TEST_TRUE (statbuf.st_mode & S_IRUSR); | ||
633 | 2790 | TEST_TRUE (statbuf.st_mode & S_IWUSR); | ||
634 | 2791 | TEST_FALSE (statbuf.st_mode & S_IXUSR); | ||
635 | 2792 | |||
636 | 2793 | TEST_TRUE (statbuf.st_mode & S_IRGRP); | ||
637 | 2794 | TEST_FALSE (statbuf.st_mode & S_IWGRP); | ||
638 | 2795 | TEST_FALSE (statbuf.st_mode & S_IXGRP); | ||
639 | 2796 | |||
640 | 2797 | TEST_FALSE (statbuf.st_mode & S_IROTH); | ||
641 | 2798 | TEST_FALSE (statbuf.st_mode & S_IWOTH); | ||
642 | 2799 | TEST_FALSE (statbuf.st_mode & S_IXOTH); | ||
643 | 2800 | |||
644 | 2801 | output = fopen (filename, "r"); | ||
645 | 2802 | TEST_NE_P (output, NULL); | ||
646 | 2803 | |||
647 | 2804 | TEST_FILE_EQ (output, "hello\r\n"); | ||
648 | 2805 | TEST_FILE_END (output); | ||
649 | 2806 | fclose (output); | ||
650 | 2807 | |||
651 | 2808 | TEST_EQ (unlink (filename), 0); | ||
652 | 2809 | |||
653 | 2810 | /************************************************************/ | ||
654 | 2811 | TEST_FEATURE ("with single line command writing lots of data fast and exiting"); | ||
655 | 2812 | |||
656 | 2813 | class = job_class_new (NULL, "foo", NULL); | ||
657 | 2814 | TEST_NE_P (class, NULL); | ||
658 | 2815 | |||
659 | 2816 | TEST_FILENAME (filename); | ||
660 | 2817 | TEST_GT (sprintf (filename, "%s/foo.log", dirname), 0); | ||
661 | 2818 | |||
662 | 2819 | class->console = CONSOLE_LOG; | ||
663 | 2820 | class->process[PROCESS_MAIN] = process_new (class); | ||
664 | 2821 | /* program must run "fast", so directly exec with | ||
665 | 2822 | * no shell intervention. | ||
666 | 2823 | * | ||
667 | 2824 | * Writes large number of nulls (3MB). | ||
668 | 2825 | */ | ||
669 | 2826 | #define EXPECTED_1K_BLOCKS (1024*3) | ||
670 | 2827 | #define TEST_BLOCKSIZE 1024 | ||
671 | 2828 | |||
672 | 2829 | class->process[PROCESS_MAIN]->command = nih_sprintf ( | ||
673 | 2830 | class->process[PROCESS_MAIN], | ||
674 | 2831 | "%s if=/dev/zero bs=%d count=%d", | ||
675 | 2832 | TEST_CMD_DD, TEST_BLOCKSIZE, EXPECTED_1K_BLOCKS); | ||
676 | 2833 | class->process[PROCESS_MAIN]->script = FALSE; | ||
677 | 2834 | |||
678 | 2835 | NIH_MUST (nih_child_add_watch (NULL, | ||
679 | 2836 | -1, | ||
680 | 2837 | NIH_CHILD_ALL, | ||
681 | 2838 | job_process_handler, | ||
682 | 2839 | NULL)); | ||
683 | 2840 | |||
684 | 2841 | job = job_new (class, ""); | ||
685 | 2842 | job->goal = JOB_START; | ||
686 | 2843 | job->state = JOB_SPAWNED; | ||
687 | 2844 | |||
688 | 2845 | ret = job_process_run (job, PROCESS_MAIN); | ||
689 | 2846 | TEST_EQ (ret, 0); | ||
690 | 2847 | |||
691 | 2848 | pid = job->pid[PROCESS_MAIN]; | ||
692 | 2849 | |||
693 | 2850 | /* job will block until something reads the other end of the pty */ | ||
694 | 2851 | TEST_EQ (kill (pid, 0), 0); | ||
695 | 2852 | |||
696 | 2853 | { | ||
697 | 2854 | size_t bytes; | ||
698 | 2855 | size_t expected_bytes = TEST_BLOCKSIZE * EXPECTED_1K_BLOCKS; | ||
699 | 2856 | off_t filesize = (off_t)-1; | ||
700 | 2857 | |||
701 | 2858 | /* Check repeatedly for job log output jobs until | ||
702 | 2859 | * we've either read the expected number of nulls, or we | ||
703 | 2860 | * timed out. | ||
704 | 2861 | */ | ||
705 | 2862 | while ( 1 ) { | ||
706 | 2863 | size_t length; | ||
707 | 2864 | size_t i; | ||
708 | 2865 | struct timeval t; | ||
709 | 2866 | nih_local char *file = NULL; | ||
710 | 2867 | |||
711 | 2868 | t.tv_sec = 1; | ||
712 | 2869 | t.tv_usec = 0; | ||
713 | 2870 | |||
714 | 2871 | TEST_FORCE_WATCH_UPDATE_TIMEOUT (t); | ||
715 | 2872 | |||
716 | 2873 | TEST_EQ (stat (filename, &statbuf), 0); | ||
717 | 2874 | |||
718 | 2875 | /* We expect the file size to change */ | ||
719 | 2876 | if (statbuf.st_size == filesize) { | ||
720 | 2877 | break; | ||
721 | 2878 | } | ||
722 | 2879 | |||
723 | 2880 | filesize = statbuf.st_size; | ||
724 | 2881 | |||
725 | 2882 | file = nih_file_read (NULL, filename, &length); | ||
726 | 2883 | TEST_NE_P (file, NULL); | ||
727 | 2884 | |||
728 | 2885 | bytes = 0; | ||
729 | 2886 | for (i=0; i < length; ++i) { | ||
730 | 2887 | if (file[i] == '\0') | ||
731 | 2888 | bytes++; | ||
732 | 2889 | } | ||
733 | 2890 | |||
734 | 2891 | if (bytes == expected_bytes) { | ||
735 | 2892 | break; | ||
736 | 2893 | } | ||
737 | 2894 | } | ||
738 | 2895 | |||
739 | 2896 | TEST_EQ (bytes, expected_bytes); | ||
740 | 2897 | } | ||
741 | 2898 | |||
742 | 2899 | TEST_EQ (kill (pid, 0), 0); | ||
743 | 2900 | nih_child_poll (); | ||
744 | 2901 | |||
745 | 2902 | /* The process should now be dead */ | ||
746 | 2903 | TEST_EQ (kill (pid, 0), -1); | ||
747 | 2904 | TEST_EQ (errno, ESRCH); | ||
748 | 2905 | |||
749 | 2906 | nih_free (class); | ||
750 | 2907 | TEST_EQ (stat (filename, &statbuf), 0); | ||
751 | 2908 | |||
752 | 2909 | TEST_TRUE (S_ISREG (statbuf.st_mode)); | ||
753 | 2910 | |||
754 | 2911 | TEST_TRUE (statbuf.st_mode & S_IRUSR); | ||
755 | 2912 | TEST_TRUE (statbuf.st_mode & S_IWUSR); | ||
756 | 2913 | TEST_FALSE (statbuf.st_mode & S_IXUSR); | ||
757 | 2914 | |||
758 | 2915 | TEST_TRUE (statbuf.st_mode & S_IRGRP); | ||
759 | 2916 | TEST_FALSE (statbuf.st_mode & S_IWGRP); | ||
760 | 2917 | TEST_FALSE (statbuf.st_mode & S_IXGRP); | ||
761 | 2918 | |||
762 | 2919 | TEST_FALSE (statbuf.st_mode & S_IROTH); | ||
763 | 2920 | TEST_FALSE (statbuf.st_mode & S_IWOTH); | ||
764 | 2921 | TEST_FALSE (statbuf.st_mode & S_IXOTH); | ||
765 | 2922 | |||
766 | 2923 | TEST_EQ (unlink (filename), 0); | ||
767 | 2924 | |||
768 | 2925 | #undef EXPECTED_1K_BLOCKS | ||
769 | 2926 | #undef TEST_BLOCKSIZE | ||
770 | 2927 | |||
771 | 2928 | /************************************************************/ | ||
772 | 2929 | /* Applies to respawn jobs too */ | ||
773 | 2930 | |||
774 | 2931 | TEST_FEATURE ("with log object freed on process exit"); | ||
775 | 2932 | |||
776 | 2933 | class = job_class_new (NULL, "acorn", NULL); | ||
777 | 2934 | TEST_NE_P (class, NULL); | ||
778 | 2935 | |||
779 | 2936 | TEST_FILENAME (filename); | ||
780 | 2937 | TEST_GT (sprintf (filename, "%s/acorn.log", dirname), 0); | ||
781 | 2938 | |||
782 | 2939 | class->console = CONSOLE_LOG; | ||
783 | 2940 | class->process[PROCESS_MAIN] = process_new (class); | ||
784 | 2941 | class->process[PROCESS_MAIN]->command = nih_sprintf ( | ||
785 | 2942 | class->process[PROCESS_MAIN], | ||
786 | 2943 | "%s hello", | ||
787 | 2944 | TEST_CMD_ECHO); | ||
788 | 2945 | class->process[PROCESS_MAIN]->script = FALSE; | ||
789 | 2946 | |||
790 | 2947 | /* XXX: Manually add the class so job_process_find() works */ | ||
791 | 2948 | nih_hash_add (job_classes, &class->entry); | ||
792 | 2949 | |||
793 | 2950 | NIH_MUST (nih_child_add_watch (NULL, | ||
794 | 2951 | -1, | ||
795 | 2952 | NIH_CHILD_ALL, | ||
796 | 2953 | job_process_handler, | ||
797 | 2954 | NULL)); | ||
798 | 2955 | |||
799 | 2956 | job = job_new (class, ""); | ||
800 | 2957 | job->goal = JOB_START; | ||
801 | 2958 | job->state = JOB_SPAWNED; | ||
802 | 2959 | |||
803 | 2960 | TEST_EQ_P (job->log, NULL); | ||
804 | 2961 | |||
805 | 2962 | ret = job_process_run (job, PROCESS_MAIN); | ||
806 | 2963 | TEST_EQ (ret, 0); | ||
807 | 2964 | |||
808 | 2965 | pid = job->pid[PROCESS_MAIN]; | ||
809 | 2966 | |||
810 | 2967 | job->goal = JOB_STOP; | ||
811 | 2968 | job->state = JOB_KILLED; | ||
812 | 2969 | |||
813 | 2970 | TEST_NE (job->pid[PROCESS_MAIN], 0); | ||
814 | 2971 | |||
815 | 2972 | TEST_NE_P (job->log, NULL); | ||
816 | 2973 | |||
817 | 2974 | TEST_FREE_TAG (job); | ||
818 | 2975 | TEST_FREE_TAG (job->log); | ||
819 | 2976 | |||
820 | 2977 | TEST_FORCE_WATCH_UPDATE (); | ||
821 | 2978 | |||
822 | 2979 | nih_child_poll (); | ||
823 | 2980 | |||
824 | 2981 | /* Should have been destroyed now */ | ||
825 | 2982 | TEST_FREE (job); | ||
826 | 2983 | TEST_FREE (job->log); | ||
827 | 2984 | |||
828 | 2985 | nih_free (class); | ||
829 | 2986 | unlink (filename); | ||
830 | 2987 | |||
831 | 2988 | /************************************************************/ | ||
832 | 2989 | |||
833 | 2716 | /* Check that we can succesfully setuid and setgid to | 2990 | /* Check that we can succesfully setuid and setgid to |
834 | 2717 | * ourselves. This should always work, privileged or | 2991 | * ourselves. This should always work, privileged or |
835 | 2718 | * otherwise. | 2992 | * otherwise. |
836 | @@ -3315,7 +3589,7 @@ | |||
837 | 3315 | 3589 | ||
838 | 3316 | TEST_EQ (fclose (output), 0); | 3590 | TEST_EQ (fclose (output), 0); |
839 | 3317 | 3591 | ||
841 | 3318 | unlink (filename); | 3592 | TEST_EQ (unlink (filename), 0); |
842 | 3319 | 3593 | ||
843 | 3320 | TEST_EQ (rmdir (dirname), 0); | 3594 | TEST_EQ (rmdir (dirname), 0); |
844 | 3321 | TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); | 3595 | TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); |
845 | @@ -3409,6 +3683,9 @@ | |||
846 | 3409 | 3683 | ||
847 | 3410 | TEST_FORCE_WATCH_UPDATE (); | 3684 | TEST_FORCE_WATCH_UPDATE (); |
848 | 3411 | 3685 | ||
849 | 3686 | /* This will eventually call the log destructor */ | ||
850 | 3687 | nih_free (class); | ||
851 | 3688 | |||
852 | 3412 | output = fopen (filename, "r"); | 3689 | output = fopen (filename, "r"); |
853 | 3413 | TEST_NE_P (output, NULL); | 3690 | TEST_NE_P (output, NULL); |
854 | 3414 | 3691 | ||
855 | @@ -3423,8 +3700,6 @@ | |||
856 | 3423 | TEST_EQ (rmdir (dirname), 0); | 3700 | TEST_EQ (rmdir (dirname), 0); |
857 | 3424 | TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); | 3701 | TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); |
858 | 3425 | 3702 | ||
859 | 3426 | nih_free (job); | ||
860 | 3427 | |||
861 | 3428 | /************************************************************/ | 3703 | /************************************************************/ |
862 | 3429 | TEST_FEATURE ("read data from daemon process"); | 3704 | TEST_FEATURE ("read data from daemon process"); |
863 | 3430 | 3705 | ||
864 | @@ -3456,10 +3731,14 @@ | |||
865 | 3456 | pid = job_process_spawn (job, args, NULL, FALSE, -1); | 3731 | pid = job_process_spawn (job, args, NULL, FALSE, -1); |
866 | 3457 | TEST_GT (pid, 0); | 3732 | TEST_GT (pid, 0); |
867 | 3458 | 3733 | ||
868 | 3734 | TEST_FORCE_WATCH_UPDATE (); | ||
869 | 3735 | |||
870 | 3459 | TEST_EQ (waitpid (pid, &status, 0), pid); | 3736 | TEST_EQ (waitpid (pid, &status, 0), pid); |
871 | 3460 | TEST_TRUE (WIFEXITED (status)); | 3737 | TEST_TRUE (WIFEXITED (status)); |
872 | 3738 | TEST_EQ (WEXITSTATUS (status), 0); | ||
873 | 3461 | 3739 | ||
875 | 3462 | TEST_FORCE_WATCH_UPDATE (); | 3740 | /* This will eventually call the log destructor */ |
876 | 3741 | nih_free (class); | ||
877 | 3463 | 3742 | ||
878 | 3464 | output = fopen (filename, "r"); | 3743 | output = fopen (filename, "r"); |
879 | 3465 | TEST_NE_P (output, NULL); | 3744 | TEST_NE_P (output, NULL); |
880 | @@ -3475,9 +3754,6 @@ | |||
881 | 3475 | TEST_EQ (rmdir (dirname), 0); | 3754 | TEST_EQ (rmdir (dirname), 0); |
882 | 3476 | TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); | 3755 | TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); |
883 | 3477 | 3756 | ||
884 | 3478 | nih_free (job); | ||
885 | 3479 | |||
886 | 3480 | |||
887 | 3481 | /* FIXME */ | 3757 | /* FIXME */ |
888 | 3482 | #if 0 | 3758 | #if 0 |
889 | 3483 | /************************************************************/ | 3759 | /************************************************************/ |
890 | @@ -3538,14 +3814,13 @@ | |||
891 | 3538 | TEST_EQ (err->number, ENOMEM); | 3814 | TEST_EQ (err->number, ENOMEM); |
892 | 3539 | nih_free (err); | 3815 | nih_free (err); |
893 | 3540 | } | 3816 | } |
895 | 3541 | nih_free (job); | 3817 | nih_free (class); |
896 | 3542 | } | 3818 | } |
897 | 3543 | #else | 3819 | #else |
898 | 3544 | /* FIXME */ | 3820 | /* FIXME */ |
899 | 3545 | TEST_FEATURE ("WARNING: FIXME: test 'when no free ptys' disabled due to kernel bug"); | 3821 | TEST_FEATURE ("WARNING: FIXME: test 'when no free ptys' disabled due to kernel bug"); |
900 | 3546 | #endif | 3822 | #endif |
901 | 3547 | 3823 | ||
902 | 3548 | nih_free (class); | ||
903 | 3549 | TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); | 3824 | TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); |
904 | 3550 | } | 3825 | } |
905 | 3551 | 3826 | ||
906 | 3552 | 3827 | ||
907 | === modified file 'init/tests/test_log.c' | |||
908 | --- init/tests/test_log.c 2011-12-09 14:07:11 +0000 | |||
909 | +++ init/tests/test_log.c 2012-01-26 15:59:26 +0000 | |||
910 | @@ -91,7 +91,6 @@ | |||
911 | 91 | test_log_new (void) | 91 | test_log_new (void) |
912 | 92 | { | 92 | { |
913 | 93 | Log *log; | 93 | Log *log; |
914 | 94 | int fds[2] = { -1, -1 }; | ||
915 | 95 | char path[] = "/foo"; | 94 | char path[] = "/foo"; |
916 | 96 | char str[] = "hello, world!"; | 95 | char str[] = "hello, world!"; |
917 | 97 | char str2[] = "The end?"; | 96 | char str2[] = "The end?"; |
918 | @@ -104,6 +103,8 @@ | |||
919 | 104 | FILE *output; | 103 | FILE *output; |
920 | 105 | mode_t old_perms; | 104 | mode_t old_perms; |
921 | 106 | off_t old_size; | 105 | off_t old_size; |
922 | 106 | int pty_master; | ||
923 | 107 | int pty_slave; | ||
924 | 107 | 108 | ||
925 | 108 | TEST_FUNCTION ("log_new"); | 109 | TEST_FUNCTION ("log_new"); |
926 | 109 | 110 | ||
927 | @@ -130,8 +131,8 @@ | |||
928 | 130 | TEST_FEATURE ("object checks with uid 0"); | 131 | TEST_FEATURE ("object checks with uid 0"); |
929 | 131 | 132 | ||
930 | 132 | TEST_ALLOC_FAIL { | 133 | TEST_ALLOC_FAIL { |
933 | 133 | TEST_EQ (pipe (fds), 0); | 134 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
934 | 134 | log = log_new (NULL, path, fds[0], 0); | 135 | log = log_new (NULL, path, pty_master, 0); |
935 | 135 | 136 | ||
936 | 136 | /* Handle all alloc failures where the alloc calls were | 137 | /* Handle all alloc failures where the alloc calls were |
937 | 137 | * initiated by log_new(). | 138 | * initiated by log_new(). |
938 | @@ -140,8 +141,8 @@ | |||
939 | 140 | (test_alloc_failed <= LOG_NEW_ALLOC_CALLS)) { | 141 | (test_alloc_failed <= LOG_NEW_ALLOC_CALLS)) { |
940 | 141 | 142 | ||
941 | 142 | TEST_EQ_P (log, NULL); | 143 | TEST_EQ_P (log, NULL); |
944 | 143 | close (fds[0]); | 144 | close (pty_master); |
945 | 144 | close (fds[1]); | 145 | close (pty_slave); |
946 | 145 | continue; | 146 | continue; |
947 | 146 | } | 147 | } |
948 | 147 | 148 | ||
949 | @@ -153,11 +154,11 @@ | |||
950 | 153 | TEST_ALLOC_PARENT (log->path, log); | 154 | TEST_ALLOC_PARENT (log->path, log); |
951 | 154 | 155 | ||
952 | 155 | TEST_EQ_STR (log->path, path); | 156 | TEST_EQ_STR (log->path, path); |
954 | 156 | TEST_EQ (log->io->watch->fd, fds[0]); | 157 | TEST_EQ (log->io->watch->fd, pty_master); |
955 | 157 | TEST_EQ (log->uid, 0); | 158 | TEST_EQ (log->uid, 0); |
956 | 158 | TEST_LT (log->fd, 0); | 159 | TEST_LT (log->fd, 0); |
957 | 159 | 160 | ||
959 | 160 | close (fds[1]); | 161 | close (pty_slave); |
960 | 161 | 162 | ||
961 | 162 | /* frees fds[0] */ | 163 | /* frees fds[0] */ |
962 | 163 | nih_free (log); | 164 | nih_free (log); |
963 | @@ -168,13 +169,13 @@ | |||
964 | 168 | /* XXX: No support for logging of user job output currently */ | 169 | /* XXX: No support for logging of user job output currently */ |
965 | 169 | TEST_FEATURE ("ensure logging disallowed for uid >0"); | 170 | TEST_FEATURE ("ensure logging disallowed for uid >0"); |
966 | 170 | 171 | ||
968 | 171 | TEST_EQ (pipe (fds), 0); | 172 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
969 | 172 | 173 | ||
971 | 173 | log = log_new (NULL, path, fds[0], 1); | 174 | log = log_new (NULL, path, pty_master, 1); |
972 | 174 | TEST_EQ (log, NULL); | 175 | TEST_EQ (log, NULL); |
973 | 175 | 176 | ||
976 | 176 | close (fds[0]); | 177 | close (pty_master); |
977 | 177 | close (fds[1]); | 178 | close (pty_slave); |
978 | 178 | 179 | ||
979 | 179 | /************************************************************/ | 180 | /************************************************************/ |
980 | 180 | TEST_FEATURE ("parent check"); | 181 | TEST_FEATURE ("parent check"); |
981 | @@ -185,14 +186,15 @@ | |||
982 | 185 | string = NIH_MUST (nih_strdup (NULL, str)); | 186 | string = NIH_MUST (nih_strdup (NULL, str)); |
983 | 186 | } | 187 | } |
984 | 187 | 188 | ||
990 | 188 | TEST_EQ (pipe (fds), 0); | 189 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
991 | 189 | 190 | ||
992 | 190 | log = log_new (string, path, fds[0], 0); | 191 | log = log_new (string, path, pty_master, 0); |
993 | 191 | 192 | ||
994 | 192 | if (test_alloc_failed) { | 193 | if (test_alloc_failed && |
995 | 194 | (test_alloc_failed <= LOG_NEW_ALLOC_CALLS)) { | ||
996 | 193 | TEST_EQ_P (log, NULL); | 195 | TEST_EQ_P (log, NULL); |
999 | 194 | close (fds[0]); | 196 | close (pty_master); |
1000 | 195 | close (fds[1]); | 197 | close (pty_slave); |
1001 | 196 | nih_free (string); | 198 | nih_free (string); |
1002 | 197 | continue; | 199 | continue; |
1003 | 198 | } | 200 | } |
1004 | @@ -201,7 +203,7 @@ | |||
1005 | 201 | TEST_ALLOC_PARENT (log, string); | 203 | TEST_ALLOC_PARENT (log, string); |
1006 | 202 | TEST_FREE_TAG (log); | 204 | TEST_FREE_TAG (log); |
1007 | 203 | 205 | ||
1009 | 204 | close (fds[1]); | 206 | close (pty_slave); |
1010 | 205 | 207 | ||
1011 | 206 | /* Freeing the parent should free the child */ | 208 | /* Freeing the parent should free the child */ |
1012 | 207 | nih_free (string); | 209 | nih_free (string); |
1013 | @@ -215,9 +217,9 @@ | |||
1014 | 215 | 217 | ||
1015 | 216 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 218 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1016 | 217 | TEST_LT (stat (filename, &statbuf), 0); | 219 | TEST_LT (stat (filename, &statbuf), 0); |
1018 | 218 | TEST_EQ (pipe (fds), 0); | 220 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1019 | 219 | 221 | ||
1021 | 220 | log = log_new (NULL, filename, fds[0], 0); | 222 | log = log_new (NULL, filename, pty_master, 0); |
1022 | 221 | 223 | ||
1023 | 222 | /* First time through at this point only log_new() has been called. | 224 | /* First time through at this point only log_new() has been called. |
1024 | 223 | * But by the end of the first loop, log_io_reader() will have | 225 | * But by the end of the first loop, log_io_reader() will have |
1025 | @@ -232,16 +234,16 @@ | |||
1026 | 232 | if (test_alloc_failed && | 234 | if (test_alloc_failed && |
1027 | 233 | (test_alloc_failed <= LOG_NEW_ALLOC_CALLS)) { | 235 | (test_alloc_failed <= LOG_NEW_ALLOC_CALLS)) { |
1028 | 234 | TEST_EQ_P (log, NULL); | 236 | TEST_EQ_P (log, NULL); |
1031 | 235 | close (fds[0]); | 237 | close (pty_master); |
1032 | 236 | close (fds[1]); | 238 | close (pty_slave); |
1033 | 237 | continue; | 239 | continue; |
1034 | 238 | } | 240 | } |
1035 | 239 | 241 | ||
1036 | 240 | TEST_NE_P (log, NULL); | 242 | TEST_NE_P (log, NULL); |
1037 | 241 | 243 | ||
1039 | 242 | ret = write (fds[1], str, strlen (str)); | 244 | ret = write (pty_slave, str, strlen (str)); |
1040 | 243 | TEST_GT (ret, 0); | 245 | TEST_GT (ret, 0); |
1042 | 244 | ret = write (fds[1], "\n", 1); | 246 | ret = write (pty_slave, "\n", 1); |
1043 | 245 | TEST_EQ (ret, 1); | 247 | TEST_EQ (ret, 1); |
1044 | 246 | 248 | ||
1045 | 247 | TEST_FORCE_WATCH_UPDATE (); | 249 | TEST_FORCE_WATCH_UPDATE (); |
1046 | @@ -251,12 +253,13 @@ | |||
1047 | 251 | */ | 253 | */ |
1048 | 252 | if (test_alloc_failed == 1+LOG_NEW_ALLOC_CALLS) { | 254 | if (test_alloc_failed == 1+LOG_NEW_ALLOC_CALLS) { |
1049 | 253 | TEST_NE_P (log, NULL); | 255 | TEST_NE_P (log, NULL); |
1051 | 254 | close (fds[1]); | 256 | close (pty_slave); |
1052 | 255 | nih_free (log); | 257 | nih_free (log); |
1053 | 258 | TEST_EQ (unlink (filename), 0); | ||
1054 | 256 | continue; | 259 | continue; |
1055 | 257 | } | 260 | } |
1056 | 258 | 261 | ||
1058 | 259 | close (fds[1]); | 262 | close (pty_slave); |
1059 | 260 | nih_free (log); | 263 | nih_free (log); |
1060 | 261 | 264 | ||
1061 | 262 | TEST_EQ (stat (filename, &statbuf), 0); | 265 | TEST_EQ (stat (filename, &statbuf), 0); |
1062 | @@ -277,7 +280,7 @@ | |||
1063 | 277 | output = fopen (filename, "r"); | 280 | output = fopen (filename, "r"); |
1064 | 278 | TEST_NE_P (output, NULL); | 281 | TEST_NE_P (output, NULL); |
1065 | 279 | 282 | ||
1067 | 280 | TEST_FILE_EQ (output, "hello, world!\n"); | 283 | TEST_FILE_EQ (output, "hello, world!\r\n"); |
1068 | 281 | TEST_FILE_END (output); | 284 | TEST_FILE_END (output); |
1069 | 282 | fclose (output); | 285 | fclose (output); |
1070 | 283 | 286 | ||
1071 | @@ -287,17 +290,17 @@ | |||
1072 | 287 | /************************************************************/ | 290 | /************************************************************/ |
1073 | 288 | TEST_FEATURE ("same logger appending to file with uid 0"); | 291 | TEST_FEATURE ("same logger appending to file with uid 0"); |
1074 | 289 | 292 | ||
1076 | 290 | TEST_EQ (pipe (fds), 0); | 293 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1077 | 291 | 294 | ||
1078 | 292 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 295 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1079 | 293 | TEST_LT (stat (filename, &statbuf), 0); | 296 | TEST_LT (stat (filename, &statbuf), 0); |
1080 | 294 | 297 | ||
1082 | 295 | log = log_new (NULL, filename, fds[0], 0); | 298 | log = log_new (NULL, filename, pty_master, 0); |
1083 | 296 | TEST_NE_P (log, NULL); | 299 | TEST_NE_P (log, NULL); |
1084 | 297 | 300 | ||
1086 | 298 | ret = write (fds[1], str, strlen (str)); | 301 | ret = write (pty_slave, str, strlen (str)); |
1087 | 299 | TEST_GT (ret, 0); | 302 | TEST_GT (ret, 0); |
1089 | 300 | ret = write (fds[1], "\n", 1); | 303 | ret = write (pty_slave, "\n", 1); |
1090 | 301 | TEST_EQ (ret, 1); | 304 | TEST_EQ (ret, 1); |
1091 | 302 | 305 | ||
1092 | 303 | TEST_FORCE_WATCH_UPDATE (); | 306 | TEST_FORCE_WATCH_UPDATE (); |
1093 | @@ -321,11 +324,11 @@ | |||
1094 | 321 | output = fopen (filename, "r"); | 324 | output = fopen (filename, "r"); |
1095 | 322 | TEST_NE_P (output, NULL); | 325 | TEST_NE_P (output, NULL); |
1096 | 323 | 326 | ||
1098 | 324 | TEST_FILE_EQ (output, "hello, world!\n"); | 327 | TEST_FILE_EQ (output, "hello, world!\r\n"); |
1099 | 325 | TEST_FILE_END (output); | 328 | TEST_FILE_END (output); |
1100 | 326 | fclose (output); | 329 | fclose (output); |
1101 | 327 | 330 | ||
1103 | 328 | ret = write (fds[1], str2, strlen (str2)); | 331 | ret = write (pty_slave, str2, strlen (str2)); |
1104 | 329 | TEST_GT (ret, 0); | 332 | TEST_GT (ret, 0); |
1105 | 330 | 333 | ||
1106 | 331 | TEST_FORCE_WATCH_UPDATE (); | 334 | TEST_FORCE_WATCH_UPDATE (); |
1107 | @@ -351,31 +354,32 @@ | |||
1108 | 351 | output = fopen (filename, "r"); | 354 | output = fopen (filename, "r"); |
1109 | 352 | TEST_NE_P (output, NULL); | 355 | TEST_NE_P (output, NULL); |
1110 | 353 | 356 | ||
1112 | 354 | TEST_FILE_EQ (output, "hello, world!\n"); | 357 | TEST_FILE_EQ (output, "hello, world!\r\n"); |
1113 | 355 | TEST_FILE_EQ (output, str2); | 358 | TEST_FILE_EQ (output, str2); |
1114 | 356 | TEST_FILE_END (output); | 359 | TEST_FILE_END (output); |
1115 | 357 | fclose (output); | 360 | fclose (output); |
1116 | 358 | 361 | ||
1117 | 359 | TEST_EQ (unlink (filename), 0); | 362 | TEST_EQ (unlink (filename), 0); |
1119 | 360 | close (fds[1]); | 363 | close (pty_slave); |
1120 | 361 | nih_free (log); | 364 | nih_free (log); |
1121 | 362 | 365 | ||
1122 | 363 | /************************************************************/ | 366 | /************************************************************/ |
1123 | 364 | TEST_FEATURE ("different logger appending to file with uid 0"); | 367 | TEST_FEATURE ("different logger appending to file with uid 0"); |
1124 | 365 | 368 | ||
1126 | 366 | TEST_EQ (pipe (fds), 0); | 369 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1127 | 367 | 370 | ||
1128 | 368 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 371 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1130 | 369 | log = log_new (NULL, filename, fds[0], 0); | 372 | log = log_new (NULL, filename, pty_master, 0); |
1131 | 370 | TEST_NE_P (log, NULL); | 373 | TEST_NE_P (log, NULL); |
1132 | 371 | 374 | ||
1133 | 372 | bytes = 0; | 375 | bytes = 0; |
1135 | 373 | ret = write (fds[1], str, strlen (str)); | 376 | ret = write (pty_slave, str, strlen (str)); |
1136 | 374 | TEST_GT (ret, 0); | 377 | TEST_GT (ret, 0); |
1137 | 375 | bytes += ret; | 378 | bytes += ret; |
1139 | 376 | ret = write (fds[1], "\n", 1); | 379 | ret = write (pty_slave, "\n", 1); |
1140 | 377 | TEST_EQ (ret, 1); | 380 | TEST_EQ (ret, 1); |
1142 | 378 | bytes += ret; | 381 | /* XXX: '+1' for '\r' */ |
1143 | 382 | bytes += (ret+1); | ||
1144 | 379 | 383 | ||
1145 | 380 | TEST_FORCE_WATCH_UPDATE (); | 384 | TEST_FORCE_WATCH_UPDATE (); |
1146 | 381 | 385 | ||
1147 | @@ -400,16 +404,16 @@ | |||
1148 | 400 | output = fopen (filename, "r"); | 404 | output = fopen (filename, "r"); |
1149 | 401 | TEST_NE_P (output, NULL); | 405 | TEST_NE_P (output, NULL); |
1150 | 402 | 406 | ||
1152 | 403 | TEST_FILE_EQ (output, "hello, world!\n"); | 407 | TEST_FILE_EQ (output, "hello, world!\r\n"); |
1153 | 404 | TEST_FILE_END (output); | 408 | TEST_FILE_END (output); |
1154 | 405 | fclose (output); | 409 | fclose (output); |
1155 | 406 | 410 | ||
1157 | 407 | close (fds[1]); | 411 | close (pty_slave); |
1158 | 408 | nih_free (log); | 412 | nih_free (log); |
1159 | 409 | 413 | ||
1161 | 410 | TEST_EQ (pipe (fds), 0); | 414 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1162 | 411 | 415 | ||
1164 | 412 | log = log_new (NULL, filename, fds[0], 0); | 416 | log = log_new (NULL, filename, pty_master, 0); |
1165 | 413 | TEST_NE_P (log, NULL); | 417 | TEST_NE_P (log, NULL); |
1166 | 414 | 418 | ||
1167 | 415 | TEST_EQ (stat (filename, &statbuf), 0); | 419 | TEST_EQ (stat (filename, &statbuf), 0); |
1168 | @@ -430,16 +434,17 @@ | |||
1169 | 430 | TEST_EQ (statbuf.st_size, old_size); | 434 | TEST_EQ (statbuf.st_size, old_size); |
1170 | 431 | 435 | ||
1171 | 432 | bytes = 0; | 436 | bytes = 0; |
1173 | 433 | ret = write (fds[1], str2, strlen (str2)); | 437 | ret = write (pty_slave, str2, strlen (str2)); |
1174 | 434 | TEST_GT (ret, 0); | 438 | TEST_GT (ret, 0); |
1175 | 435 | bytes += ret; | 439 | bytes += ret; |
1177 | 436 | ret = write (fds[1], "\n", 1); | 440 | ret = write (pty_slave, "\n", 1); |
1178 | 437 | TEST_EQ (ret, 1); | 441 | TEST_EQ (ret, 1); |
1180 | 438 | bytes += ret; | 442 | /* '+1' for '\r' */ |
1181 | 443 | bytes += (1+ret); | ||
1182 | 439 | 444 | ||
1183 | 440 | TEST_FORCE_WATCH_UPDATE (); | 445 | TEST_FORCE_WATCH_UPDATE (); |
1184 | 441 | 446 | ||
1186 | 442 | close (fds[1]); | 447 | close (pty_slave); |
1187 | 443 | nih_free (log); | 448 | nih_free (log); |
1188 | 444 | 449 | ||
1189 | 445 | TEST_EQ (stat (filename, &statbuf), 0); | 450 | TEST_EQ (stat (filename, &statbuf), 0); |
1190 | @@ -462,8 +467,8 @@ | |||
1191 | 462 | output = fopen (filename, "r"); | 467 | output = fopen (filename, "r"); |
1192 | 463 | TEST_NE_P (output, NULL); | 468 | TEST_NE_P (output, NULL); |
1193 | 464 | 469 | ||
1196 | 465 | TEST_FILE_EQ (output, "hello, world!\n"); | 470 | TEST_FILE_EQ (output, "hello, world!\r\n"); |
1197 | 466 | TEST_FILE_EQ (output, "The end?\n"); | 471 | TEST_FILE_EQ (output, "The end?\r\n"); |
1198 | 467 | TEST_FILE_END (output); | 472 | TEST_FILE_END (output); |
1199 | 468 | fclose (output); | 473 | fclose (output); |
1200 | 469 | 474 | ||
1201 | @@ -472,15 +477,15 @@ | |||
1202 | 472 | /************************************************************/ | 477 | /************************************************************/ |
1203 | 473 | TEST_FEATURE ("ensure logging resumes when file made accessible with uid 0"); | 478 | TEST_FEATURE ("ensure logging resumes when file made accessible with uid 0"); |
1204 | 474 | 479 | ||
1206 | 475 | TEST_EQ (pipe (fds), 0); | 480 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1207 | 476 | 481 | ||
1208 | 477 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 482 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1210 | 478 | log = log_new (NULL, filename, fds[0], 0); | 483 | log = log_new (NULL, filename, pty_master, 0); |
1211 | 479 | TEST_NE_P (log, NULL); | 484 | TEST_NE_P (log, NULL); |
1212 | 480 | 485 | ||
1214 | 481 | ret = write (fds[1], str, strlen (str)); | 486 | ret = write (pty_slave, str, strlen (str)); |
1215 | 482 | TEST_GT (ret, 0); | 487 | TEST_GT (ret, 0); |
1217 | 483 | ret = write (fds[1], "\n", 1); | 488 | ret = write (pty_slave, "\n", 1); |
1218 | 484 | TEST_EQ (ret, 1); | 489 | TEST_EQ (ret, 1); |
1219 | 485 | 490 | ||
1220 | 486 | TEST_FORCE_WATCH_UPDATE (); | 491 | TEST_FORCE_WATCH_UPDATE (); |
1221 | @@ -508,7 +513,7 @@ | |||
1222 | 508 | output = fopen (filename, "r"); | 513 | output = fopen (filename, "r"); |
1223 | 509 | TEST_NE_P (output, NULL); | 514 | TEST_NE_P (output, NULL); |
1224 | 510 | 515 | ||
1226 | 511 | TEST_FILE_EQ (output, "hello, world!\n"); | 516 | TEST_FILE_EQ (output, "hello, world!\r\n"); |
1227 | 512 | TEST_FILE_END (output); | 517 | TEST_FILE_END (output); |
1228 | 513 | fclose (output); | 518 | fclose (output); |
1229 | 514 | 519 | ||
1230 | @@ -516,9 +521,9 @@ | |||
1231 | 516 | TEST_EQ (chmod (filename, 0x0), 0); | 521 | TEST_EQ (chmod (filename, 0x0), 0); |
1232 | 517 | 522 | ||
1233 | 518 | /* Send more data to logger */ | 523 | /* Send more data to logger */ |
1235 | 519 | ret = write (fds[1], str2, strlen (str2)); | 524 | ret = write (pty_slave, str2, strlen (str2)); |
1236 | 520 | TEST_GT (ret, 0); | 525 | TEST_GT (ret, 0); |
1238 | 521 | ret = write (fds[1], "\n", 1); | 526 | ret = write (pty_slave, "\n", 1); |
1239 | 522 | TEST_EQ (ret, 1); | 527 | TEST_EQ (ret, 1); |
1240 | 523 | 528 | ||
1241 | 524 | /* File shouldn't have changed */ | 529 | /* File shouldn't have changed */ |
1242 | @@ -531,12 +536,12 @@ | |||
1243 | 531 | /* Further data should cause previous data that could not be | 536 | /* Further data should cause previous data that could not be |
1244 | 532 | * written to be flushed to the file. | 537 | * written to be flushed to the file. |
1245 | 533 | */ | 538 | */ |
1247 | 534 | ret = write (fds[1], "foo\n", 4); | 539 | ret = write (pty_slave, "foo\n", 4); |
1248 | 535 | TEST_EQ (ret, 4); | 540 | TEST_EQ (ret, 4); |
1249 | 536 | 541 | ||
1250 | 537 | TEST_FORCE_WATCH_UPDATE (); | 542 | TEST_FORCE_WATCH_UPDATE (); |
1251 | 538 | 543 | ||
1253 | 539 | close (fds[1]); | 544 | close (pty_slave); |
1254 | 540 | nih_free (log); | 545 | nih_free (log); |
1255 | 541 | 546 | ||
1256 | 542 | TEST_EQ (stat (filename, &statbuf), 0); | 547 | TEST_EQ (stat (filename, &statbuf), 0); |
1257 | @@ -559,9 +564,9 @@ | |||
1258 | 559 | TEST_NE_P (output, NULL); | 564 | TEST_NE_P (output, NULL); |
1259 | 560 | 565 | ||
1260 | 561 | /* Re-check entire file contents */ | 566 | /* Re-check entire file contents */ |
1264 | 562 | TEST_FILE_EQ (output, "hello, world!\n"); | 567 | TEST_FILE_EQ (output, "hello, world!\r\n"); |
1265 | 563 | TEST_FILE_EQ (output, "The end?\n"); | 568 | TEST_FILE_EQ (output, "The end?\r\n"); |
1266 | 564 | TEST_FILE_EQ (output, "foo\n"); | 569 | TEST_FILE_EQ (output, "foo\r\n"); |
1267 | 565 | TEST_FILE_END (output); | 570 | TEST_FILE_END (output); |
1268 | 566 | fclose (output); | 571 | fclose (output); |
1269 | 567 | 572 | ||
1270 | @@ -570,18 +575,18 @@ | |||
1271 | 570 | /************************************************************/ | 575 | /************************************************************/ |
1272 | 571 | TEST_FEATURE ("ensure logger flushes when destroyed with uid 0"); | 576 | TEST_FEATURE ("ensure logger flushes when destroyed with uid 0"); |
1273 | 572 | 577 | ||
1275 | 573 | TEST_EQ (pipe (fds), 0); | 578 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1276 | 574 | 579 | ||
1277 | 575 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 580 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1278 | 576 | 581 | ||
1279 | 577 | TEST_EQ (rmdir (dirname), 0); | 582 | TEST_EQ (rmdir (dirname), 0); |
1280 | 578 | 583 | ||
1282 | 579 | log = log_new (NULL, filename, fds[0], 0); | 584 | log = log_new (NULL, filename, pty_master, 0); |
1283 | 580 | TEST_NE_P (log, NULL); | 585 | TEST_NE_P (log, NULL); |
1284 | 581 | 586 | ||
1286 | 582 | ret = write (fds[1], str, strlen (str)); | 587 | ret = write (pty_slave, str, strlen (str)); |
1287 | 583 | TEST_GT (ret, 0); | 588 | TEST_GT (ret, 0); |
1289 | 584 | ret = write (fds[1], "\n", 1); | 589 | ret = write (pty_slave, "\n", 1); |
1290 | 585 | TEST_EQ (ret, 1); | 590 | TEST_EQ (ret, 1); |
1291 | 586 | 591 | ||
1292 | 587 | TEST_FORCE_WATCH_UPDATE (); | 592 | TEST_FORCE_WATCH_UPDATE (); |
1293 | @@ -591,7 +596,7 @@ | |||
1294 | 591 | umask (old_perms); | 596 | umask (old_perms); |
1295 | 592 | 597 | ||
1296 | 593 | /* No more data sent to ensure logger writes it on log destroy */ | 598 | /* No more data sent to ensure logger writes it on log destroy */ |
1298 | 594 | close (fds[1]); | 599 | close (pty_slave); |
1299 | 595 | nih_free (log); | 600 | nih_free (log); |
1300 | 596 | 601 | ||
1301 | 597 | output = fopen (filename, "r"); | 602 | output = fopen (filename, "r"); |
1302 | @@ -611,7 +616,7 @@ | |||
1303 | 611 | TEST_FALSE (statbuf.st_mode & S_IROTH); | 616 | TEST_FALSE (statbuf.st_mode & S_IROTH); |
1304 | 612 | TEST_FALSE (statbuf.st_mode & S_IWOTH); | 617 | TEST_FALSE (statbuf.st_mode & S_IWOTH); |
1305 | 613 | TEST_FALSE (statbuf.st_mode & S_IXOTH); | 618 | TEST_FALSE (statbuf.st_mode & S_IXOTH); |
1307 | 614 | TEST_FILE_EQ (output, "hello, world!\n"); | 619 | TEST_FILE_EQ (output, "hello, world!\r\n"); |
1308 | 615 | TEST_FILE_END (output); | 620 | TEST_FILE_END (output); |
1309 | 616 | fclose (output); | 621 | fclose (output); |
1310 | 617 | 622 | ||
1311 | @@ -620,35 +625,31 @@ | |||
1312 | 620 | /************************************************************/ | 625 | /************************************************************/ |
1313 | 621 | TEST_FEATURE ("ensure log written when directory created accessible with uid 0"); | 626 | TEST_FEATURE ("ensure log written when directory created accessible with uid 0"); |
1314 | 622 | 627 | ||
1316 | 623 | TEST_EQ (pipe (fds), 0); | 628 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1317 | 624 | 629 | ||
1318 | 625 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 630 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1319 | 626 | 631 | ||
1320 | 627 | TEST_EQ (rmdir (dirname), 0); | 632 | TEST_EQ (rmdir (dirname), 0); |
1321 | 628 | 633 | ||
1323 | 629 | log = log_new (NULL, filename, fds[0], 0); | 634 | log = log_new (NULL, filename, pty_master, 0); |
1324 | 630 | TEST_NE_P (log, NULL); | 635 | TEST_NE_P (log, NULL); |
1325 | 631 | 636 | ||
1327 | 632 | ret = write (fds[1], str, strlen (str)); | 637 | ret = write (pty_slave, str, strlen (str)); |
1328 | 633 | TEST_GT (ret, 0); | 638 | TEST_GT (ret, 0); |
1330 | 634 | ret = write (fds[1], "\n", 1); | 639 | ret = write (pty_slave, "\n", 1); |
1331 | 635 | TEST_EQ (ret, 1); | 640 | TEST_EQ (ret, 1); |
1332 | 636 | 641 | ||
1333 | 637 | TEST_FORCE_WATCH_UPDATE (); | ||
1334 | 638 | |||
1335 | 639 | old_perms = umask (0); | 642 | old_perms = umask (0); |
1336 | 640 | TEST_EQ (mkdir (dirname, 0755), 0); | 643 | TEST_EQ (mkdir (dirname, 0755), 0); |
1337 | 641 | umask (old_perms); | 644 | umask (old_perms); |
1338 | 642 | 645 | ||
1339 | 643 | /* Send more data */ | 646 | /* Send more data */ |
1341 | 644 | ret = write (fds[1], str2, strlen (str2)); | 647 | ret = write (pty_slave, str2, strlen (str2)); |
1342 | 645 | TEST_GT (ret, 0); | 648 | TEST_GT (ret, 0); |
1344 | 646 | ret = write (fds[1], "\n", 1); | 649 | ret = write (pty_slave, "\n", 1); |
1345 | 647 | TEST_EQ (ret, 1); | 650 | TEST_EQ (ret, 1); |
1346 | 648 | 651 | ||
1350 | 649 | TEST_FORCE_WATCH_UPDATE (); | 652 | close (pty_slave); |
1348 | 650 | |||
1349 | 651 | close (fds[1]); | ||
1351 | 652 | nih_free (log); | 653 | nih_free (log); |
1352 | 653 | 654 | ||
1353 | 654 | output = fopen (filename, "r"); | 655 | output = fopen (filename, "r"); |
1354 | @@ -668,8 +669,8 @@ | |||
1355 | 668 | TEST_FALSE (statbuf.st_mode & S_IROTH); | 669 | TEST_FALSE (statbuf.st_mode & S_IROTH); |
1356 | 669 | TEST_FALSE (statbuf.st_mode & S_IWOTH); | 670 | TEST_FALSE (statbuf.st_mode & S_IWOTH); |
1357 | 670 | TEST_FALSE (statbuf.st_mode & S_IXOTH); | 671 | TEST_FALSE (statbuf.st_mode & S_IXOTH); |
1360 | 671 | TEST_FILE_EQ (output, "hello, world!\n"); | 672 | TEST_FILE_EQ (output, "hello, world!\r\n"); |
1361 | 672 | TEST_FILE_EQ (output, "The end?\n"); | 673 | TEST_FILE_EQ (output, "The end?\r\n"); |
1362 | 673 | TEST_FILE_END (output); | 674 | TEST_FILE_END (output); |
1363 | 674 | fclose (output); | 675 | fclose (output); |
1364 | 675 | 676 | ||
1365 | @@ -678,16 +679,16 @@ | |||
1366 | 678 | /************************************************************/ | 679 | /************************************************************/ |
1367 | 679 | TEST_FEATURE ("ensure remainder of log written when file deleted with uid 0"); | 680 | TEST_FEATURE ("ensure remainder of log written when file deleted with uid 0"); |
1368 | 680 | 681 | ||
1370 | 681 | TEST_EQ (pipe (fds), 0); | 682 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1371 | 682 | 683 | ||
1372 | 683 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 684 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1373 | 684 | 685 | ||
1375 | 685 | log = log_new (NULL, filename, fds[0], 0); | 686 | log = log_new (NULL, filename, pty_master, 0); |
1376 | 686 | TEST_NE_P (log, NULL); | 687 | TEST_NE_P (log, NULL); |
1377 | 687 | 688 | ||
1379 | 688 | ret = write (fds[1], str, strlen (str)); | 689 | ret = write (pty_slave, str, strlen (str)); |
1380 | 689 | TEST_GT (ret, 0); | 690 | TEST_GT (ret, 0); |
1382 | 690 | ret = write (fds[1], "\n", 1); | 691 | ret = write (pty_slave, "\n", 1); |
1383 | 691 | TEST_EQ (ret, 1); | 692 | TEST_EQ (ret, 1); |
1384 | 692 | 693 | ||
1385 | 693 | TEST_FORCE_WATCH_UPDATE (); | 694 | TEST_FORCE_WATCH_UPDATE (); |
1386 | @@ -711,7 +712,7 @@ | |||
1387 | 711 | TEST_FALSE (statbuf.st_mode & S_IXOTH); | 712 | TEST_FALSE (statbuf.st_mode & S_IXOTH); |
1388 | 712 | TEST_EQ (fstat (log->fd, &statbuf), 0); | 713 | TEST_EQ (fstat (log->fd, &statbuf), 0); |
1389 | 713 | 714 | ||
1391 | 714 | TEST_FILE_EQ (output, "hello, world!\n"); | 715 | TEST_FILE_EQ (output, "hello, world!\r\n"); |
1392 | 715 | TEST_FILE_END (output); | 716 | TEST_FILE_END (output); |
1393 | 716 | fclose (output); | 717 | fclose (output); |
1394 | 717 | 718 | ||
1395 | @@ -720,9 +721,9 @@ | |||
1396 | 720 | TEST_EQ (fstat (log->fd, &statbuf), 0); | 721 | TEST_EQ (fstat (log->fd, &statbuf), 0); |
1397 | 721 | 722 | ||
1398 | 722 | /* Send more data */ | 723 | /* Send more data */ |
1400 | 723 | ret = write (fds[1], str2, strlen (str2)); | 724 | ret = write (pty_slave, str2, strlen (str2)); |
1401 | 724 | TEST_GT (ret, 0); | 725 | TEST_GT (ret, 0); |
1403 | 725 | ret = write (fds[1], "\n", 1); | 726 | ret = write (pty_slave, "\n", 1); |
1404 | 726 | TEST_EQ (ret, 1); | 727 | TEST_EQ (ret, 1); |
1405 | 727 | 728 | ||
1406 | 728 | TEST_FORCE_WATCH_UPDATE (); | 729 | TEST_FORCE_WATCH_UPDATE (); |
1407 | @@ -744,31 +745,31 @@ | |||
1408 | 744 | TEST_FALSE (statbuf.st_mode & S_IROTH); | 745 | TEST_FALSE (statbuf.st_mode & S_IROTH); |
1409 | 745 | TEST_FALSE (statbuf.st_mode & S_IWOTH); | 746 | TEST_FALSE (statbuf.st_mode & S_IWOTH); |
1410 | 746 | TEST_FALSE (statbuf.st_mode & S_IXOTH); | 747 | TEST_FALSE (statbuf.st_mode & S_IXOTH); |
1412 | 747 | TEST_FILE_EQ (output, "The end?\n"); | 748 | TEST_FILE_EQ (output, "The end?\r\n"); |
1413 | 748 | TEST_FILE_END (output); | 749 | TEST_FILE_END (output); |
1414 | 749 | fclose (output); | 750 | fclose (output); |
1415 | 750 | 751 | ||
1417 | 751 | close (fds[1]); | 752 | close (pty_slave); |
1418 | 752 | nih_free (log); | 753 | nih_free (log); |
1419 | 753 | TEST_EQ (unlink (filename), 0); | 754 | TEST_EQ (unlink (filename), 0); |
1420 | 754 | 755 | ||
1421 | 755 | /************************************************************/ | 756 | /************************************************************/ |
1422 | 756 | TEST_FEATURE ("writing 1 null with uid 0"); | 757 | TEST_FEATURE ("writing 1 null with uid 0"); |
1423 | 757 | 758 | ||
1425 | 758 | TEST_EQ (pipe (fds), 0); | 759 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1426 | 759 | 760 | ||
1427 | 760 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 761 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1428 | 761 | TEST_LT (stat (filename, &statbuf), 0); | 762 | TEST_LT (stat (filename, &statbuf), 0); |
1429 | 762 | 763 | ||
1431 | 763 | log = log_new (NULL, filename, fds[0], 0); | 764 | log = log_new (NULL, filename, pty_master, 0); |
1432 | 764 | TEST_NE_P (log, NULL); | 765 | TEST_NE_P (log, NULL); |
1433 | 765 | 766 | ||
1435 | 766 | ret = write (fds[1], "\000", 1); | 767 | ret = write (pty_slave, "\000", 1); |
1436 | 767 | TEST_EQ (ret, 1); | 768 | TEST_EQ (ret, 1); |
1437 | 768 | 769 | ||
1438 | 769 | TEST_FORCE_WATCH_UPDATE (); | 770 | TEST_FORCE_WATCH_UPDATE (); |
1439 | 770 | 771 | ||
1441 | 771 | close (fds[1]); | 772 | close (pty_slave); |
1442 | 772 | nih_free (log); | 773 | nih_free (log); |
1443 | 773 | 774 | ||
1444 | 774 | TEST_EQ (stat (filename, &statbuf), 0); | 775 | TEST_EQ (stat (filename, &statbuf), 0); |
1445 | @@ -799,20 +800,20 @@ | |||
1446 | 799 | /************************************************************/ | 800 | /************************************************************/ |
1447 | 800 | TEST_FEATURE ("writing >1 null with uid 0"); | 801 | TEST_FEATURE ("writing >1 null with uid 0"); |
1448 | 801 | 802 | ||
1450 | 802 | TEST_EQ (pipe (fds), 0); | 803 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1451 | 803 | 804 | ||
1452 | 804 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 805 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1453 | 805 | TEST_LT (stat (filename, &statbuf), 0); | 806 | TEST_LT (stat (filename, &statbuf), 0); |
1454 | 806 | 807 | ||
1456 | 807 | log = log_new (NULL, filename, fds[0], 0); | 808 | log = log_new (NULL, filename, pty_master, 0); |
1457 | 808 | TEST_NE_P (log, NULL); | 809 | TEST_NE_P (log, NULL); |
1458 | 809 | 810 | ||
1460 | 810 | ret = write (fds[1], "\000\000\000", 3); | 811 | ret = write (pty_slave, "\000\000\000", 3); |
1461 | 811 | TEST_EQ (ret, 3); | 812 | TEST_EQ (ret, 3); |
1462 | 812 | 813 | ||
1463 | 813 | TEST_FORCE_WATCH_UPDATE (); | 814 | TEST_FORCE_WATCH_UPDATE (); |
1464 | 814 | 815 | ||
1466 | 815 | close (fds[1]); | 816 | close (pty_slave); |
1467 | 816 | nih_free (log); | 817 | nih_free (log); |
1468 | 817 | 818 | ||
1469 | 818 | TEST_EQ (stat (filename, &statbuf), 0); | 819 | TEST_EQ (stat (filename, &statbuf), 0); |
1470 | @@ -843,20 +844,20 @@ | |||
1471 | 843 | /************************************************************/ | 844 | /************************************************************/ |
1472 | 844 | TEST_FEATURE ("writing 1 non-printable only with uid 0"); | 845 | TEST_FEATURE ("writing 1 non-printable only with uid 0"); |
1473 | 845 | 846 | ||
1475 | 846 | TEST_EQ (pipe (fds), 0); | 847 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1476 | 847 | 848 | ||
1477 | 848 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 849 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1478 | 849 | TEST_LT (stat (filename, &statbuf), 0); | 850 | TEST_LT (stat (filename, &statbuf), 0); |
1479 | 850 | 851 | ||
1481 | 851 | log = log_new (NULL, filename, fds[0], 0); | 852 | log = log_new (NULL, filename, pty_master, 0); |
1482 | 852 | TEST_NE_P (log, NULL); | 853 | TEST_NE_P (log, NULL); |
1483 | 853 | 854 | ||
1485 | 854 | ret = write (fds[1], " ", 1); | 855 | ret = write (pty_slave, " ", 1); |
1486 | 855 | TEST_EQ (ret, 1); | 856 | TEST_EQ (ret, 1); |
1487 | 856 | 857 | ||
1488 | 857 | TEST_FORCE_WATCH_UPDATE (); | 858 | TEST_FORCE_WATCH_UPDATE (); |
1489 | 858 | 859 | ||
1491 | 859 | close (fds[1]); | 860 | close (pty_slave); |
1492 | 860 | nih_free (log); | 861 | nih_free (log); |
1493 | 861 | 862 | ||
1494 | 862 | TEST_EQ (stat (filename, &statbuf), 0); | 863 | TEST_EQ (stat (filename, &statbuf), 0); |
1495 | @@ -887,20 +888,20 @@ | |||
1496 | 887 | /************************************************************/ | 888 | /************************************************************/ |
1497 | 888 | TEST_FEATURE ("writing >1 non-printable only with uid 0"); | 889 | TEST_FEATURE ("writing >1 non-printable only with uid 0"); |
1498 | 889 | 890 | ||
1500 | 890 | TEST_EQ (pipe (fds), 0); | 891 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1501 | 891 | 892 | ||
1502 | 892 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); | 893 | TEST_GT (sprintf (filename, "%s/test.log", dirname), 0); |
1503 | 893 | TEST_LT (stat (filename, &statbuf), 0); | 894 | TEST_LT (stat (filename, &statbuf), 0); |
1504 | 894 | 895 | ||
1506 | 895 | log = log_new (NULL, filename, fds[0], 0); | 896 | log = log_new (NULL, filename, pty_master, 0); |
1507 | 896 | TEST_NE_P (log, NULL); | 897 | TEST_NE_P (log, NULL); |
1508 | 897 | 898 | ||
1510 | 898 | ret = write (fds[1], "\n \t", 3); | 899 | ret = write (pty_slave, "\n \t", 3); |
1511 | 899 | TEST_EQ (ret, 3); | 900 | TEST_EQ (ret, 3); |
1512 | 900 | 901 | ||
1513 | 901 | TEST_FORCE_WATCH_UPDATE (); | 902 | TEST_FORCE_WATCH_UPDATE (); |
1514 | 902 | 903 | ||
1516 | 903 | close (fds[1]); | 904 | close (pty_slave); |
1517 | 904 | nih_free (log); | 905 | nih_free (log); |
1518 | 905 | 906 | ||
1519 | 906 | TEST_EQ (stat (filename, &statbuf), 0); | 907 | TEST_EQ (stat (filename, &statbuf), 0); |
1520 | @@ -917,15 +918,18 @@ | |||
1521 | 917 | TEST_FALSE (statbuf.st_mode & S_IROTH); | 918 | TEST_FALSE (statbuf.st_mode & S_IROTH); |
1522 | 918 | TEST_FALSE (statbuf.st_mode & S_IWOTH); | 919 | TEST_FALSE (statbuf.st_mode & S_IWOTH); |
1523 | 919 | TEST_FALSE (statbuf.st_mode & S_IXOTH); | 920 | TEST_FALSE (statbuf.st_mode & S_IXOTH); |
1525 | 920 | TEST_EQ (statbuf.st_size, 3); | 921 | |
1526 | 922 | /* '\r', '\n', ' ', '\t' */ | ||
1527 | 923 | TEST_EQ (statbuf.st_size, 4); | ||
1528 | 921 | 924 | ||
1529 | 922 | output = fopen (filename, "r"); | 925 | output = fopen (filename, "r"); |
1530 | 923 | TEST_NE_P (output, NULL); | 926 | TEST_NE_P (output, NULL); |
1531 | 924 | 927 | ||
1536 | 925 | TEST_EQ (fread (buffer, 1, 3, output), 3); | 928 | TEST_EQ (fread (buffer, 1, 4, output), 4); |
1537 | 926 | TEST_EQ (buffer[0], '\n'); | 929 | TEST_EQ (buffer[0], '\r'); |
1538 | 927 | TEST_EQ (buffer[1], ' '); | 930 | TEST_EQ (buffer[1], '\n'); |
1539 | 928 | TEST_EQ (buffer[2], '\t'); | 931 | TEST_EQ (buffer[2], ' '); |
1540 | 932 | TEST_EQ (buffer[3], '\t'); | ||
1541 | 929 | 933 | ||
1542 | 930 | TEST_FILE_END (output); | 934 | TEST_FILE_END (output); |
1543 | 931 | fclose (output); | 935 | fclose (output); |
1544 | @@ -949,13 +953,17 @@ | |||
1545 | 949 | 953 | ||
1546 | 950 | memset (long_path+len, 'J', sizeof(long_path)-len-1); | 954 | memset (long_path+len, 'J', sizeof(long_path)-len-1); |
1547 | 951 | 955 | ||
1551 | 952 | TEST_EQ (pipe (fds), 0); | 956 | nih_debug("long_path='%s'", long_path); |
1552 | 953 | 957 | ||
1553 | 954 | log = log_new (NULL, long_path, fds[0], 0); | 958 | pty_master = -1; pty_slave = -1; |
1554 | 959 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); | ||
1555 | 960 | |||
1556 | 961 | log = log_new (NULL, long_path, pty_master, 0); | ||
1557 | 955 | TEST_NE_P (log, NULL); | 962 | TEST_NE_P (log, NULL); |
1558 | 956 | 963 | ||
1559 | 964 | close (pty_slave); | ||
1560 | 965 | pty_slave = -1; | ||
1561 | 957 | nih_free (log); | 966 | nih_free (log); |
1562 | 958 | close (fds[1]); | ||
1563 | 959 | } | 967 | } |
1564 | 960 | 968 | ||
1565 | 961 | /************************************************************/ | 969 | /************************************************************/ |
1566 | @@ -975,12 +983,13 @@ | |||
1567 | 975 | 983 | ||
1568 | 976 | memset (illegal_path+len, 'z', sizeof(illegal_path)-len-1); | 984 | memset (illegal_path+len, 'z', sizeof(illegal_path)-len-1); |
1569 | 977 | 985 | ||
1571 | 978 | TEST_EQ (pipe (fds), 0); | 986 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1572 | 979 | 987 | ||
1574 | 980 | log = log_new (NULL, illegal_path, fds[0], 0); | 988 | log = log_new (NULL, illegal_path, pty_master, 0); |
1575 | 981 | TEST_EQ_P (log, NULL); | 989 | TEST_EQ_P (log, NULL); |
1576 | 982 | 990 | ||
1578 | 983 | close (fds[1]); | 991 | close (pty_master); |
1579 | 992 | close (pty_slave); | ||
1580 | 984 | } | 993 | } |
1581 | 985 | 994 | ||
1582 | 986 | /************************************************************/ | 995 | /************************************************************/ |
1583 | @@ -997,13 +1006,13 @@ | |||
1584 | 997 | 1006 | ||
1585 | 998 | memset (long_path+len, 'J', sizeof(long_path)-len-1); | 1007 | memset (long_path+len, 'J', sizeof(long_path)-len-1); |
1586 | 999 | 1008 | ||
1588 | 1000 | TEST_EQ (pipe (fds), 0); | 1009 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1589 | 1001 | 1010 | ||
1591 | 1002 | log = log_new (NULL, long_path, fds[0], 0); | 1011 | log = log_new (NULL, long_path, pty_master, 0); |
1592 | 1003 | TEST_NE_P (log, NULL); | 1012 | TEST_NE_P (log, NULL); |
1593 | 1004 | 1013 | ||
1594 | 1014 | close (pty_slave); | ||
1595 | 1005 | nih_free (log); | 1015 | nih_free (log); |
1596 | 1006 | close (fds[1]); | ||
1597 | 1007 | } | 1016 | } |
1598 | 1008 | 1017 | ||
1599 | 1009 | /************************************************************/ | 1018 | /************************************************************/ |
1600 | @@ -1020,12 +1029,13 @@ | |||
1601 | 1020 | 1029 | ||
1602 | 1021 | memset (illegal_path+len, 'z', sizeof(illegal_path)-len-1); | 1030 | memset (illegal_path+len, 'z', sizeof(illegal_path)-len-1); |
1603 | 1022 | 1031 | ||
1605 | 1023 | TEST_EQ (pipe (fds), 0); | 1032 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1606 | 1024 | 1033 | ||
1608 | 1025 | log = log_new (NULL, illegal_path, fds[0], 0); | 1034 | log = log_new (NULL, illegal_path, pty_master, 0); |
1609 | 1026 | TEST_EQ_P (log, NULL); | 1035 | TEST_EQ_P (log, NULL); |
1610 | 1027 | 1036 | ||
1612 | 1028 | close (fds[1]); | 1037 | close (pty_master); |
1613 | 1038 | close (pty_slave); | ||
1614 | 1029 | } | 1039 | } |
1615 | 1030 | 1040 | ||
1616 | 1031 | /************************************************************/ | 1041 | /************************************************************/ |
1617 | @@ -1035,48 +1045,48 @@ | |||
1618 | 1035 | TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); | 1045 | TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0); |
1619 | 1036 | } | 1046 | } |
1620 | 1037 | 1047 | ||
1622 | 1038 | void | 1048 | void |
1623 | 1039 | test_log_destroy (void) | 1049 | test_log_destroy (void) |
1624 | 1040 | { | 1050 | { |
1625 | 1041 | Log *log; | 1051 | Log *log; |
1626 | 1042 | int fd; | ||
1627 | 1043 | int ret; | 1052 | int ret; |
1628 | 1044 | int flags; | 1053 | int flags; |
1629 | 1045 | int fds[2]; | ||
1630 | 1046 | char str[] = "hello, world!"; | 1054 | char str[] = "hello, world!"; |
1631 | 1055 | int pty_master; | ||
1632 | 1056 | int pty_slave; | ||
1633 | 1047 | 1057 | ||
1634 | 1048 | TEST_FUNCTION ("log_destroy"); | 1058 | TEST_FUNCTION ("log_destroy"); |
1635 | 1049 | 1059 | ||
1636 | 1050 | /************************************************************/ | 1060 | /************************************************************/ |
1637 | 1051 | TEST_FEATURE ("ensure log fd closed with uid 0"); | 1061 | TEST_FEATURE ("ensure log fd closed with uid 0"); |
1638 | 1052 | 1062 | ||
1641 | 1053 | fd = dup (2); | 1063 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1640 | 1054 | TEST_GT (fd, 0); | ||
1642 | 1055 | 1064 | ||
1644 | 1056 | flags = fcntl (fd, F_GETFL); | 1065 | flags = fcntl (pty_master, F_GETFL); |
1645 | 1057 | TEST_NE (flags, -1); | 1066 | TEST_NE (flags, -1); |
1646 | 1058 | 1067 | ||
1648 | 1059 | log = log_new (NULL, "/foo", fd, 0); | 1068 | log = log_new (NULL, "/foo", pty_master, 0); |
1649 | 1060 | TEST_NE_P (log, NULL); | 1069 | TEST_NE_P (log, NULL); |
1650 | 1061 | 1070 | ||
1651 | 1071 | close (pty_slave); | ||
1652 | 1062 | nih_free (log); | 1072 | nih_free (log); |
1653 | 1063 | 1073 | ||
1655 | 1064 | flags = fcntl (fd, F_GETFL); | 1074 | flags = fcntl (pty_master, F_GETFL); |
1656 | 1065 | TEST_EQ (flags, -1); | 1075 | TEST_EQ (flags, -1); |
1657 | 1066 | TEST_EQ (errno, EBADF); | 1076 | TEST_EQ (errno, EBADF); |
1658 | 1067 | 1077 | ||
1659 | 1068 | /************************************************************/ | 1078 | /************************************************************/ |
1660 | 1069 | TEST_FEATURE ("ensure path and io elements freed with uid 0"); | 1079 | TEST_FEATURE ("ensure path and io elements freed with uid 0"); |
1661 | 1070 | 1080 | ||
1664 | 1071 | fd = dup (2); | 1081 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1663 | 1072 | TEST_GT (fd, 0); | ||
1665 | 1073 | 1082 | ||
1667 | 1074 | log = log_new (NULL, "/bar", fd, 0); | 1083 | log = log_new (NULL, "/bar", pty_master, 0); |
1668 | 1075 | TEST_NE_P (log, NULL); | 1084 | TEST_NE_P (log, NULL); |
1669 | 1076 | 1085 | ||
1670 | 1077 | TEST_FREE_TAG (log->path); | 1086 | TEST_FREE_TAG (log->path); |
1671 | 1078 | TEST_FREE_TAG (log->io); | 1087 | TEST_FREE_TAG (log->io); |
1672 | 1079 | 1088 | ||
1673 | 1089 | close (pty_slave); | ||
1674 | 1080 | nih_free (log); | 1090 | nih_free (log); |
1675 | 1081 | 1091 | ||
1676 | 1082 | TEST_FREE (log->path); | 1092 | TEST_FREE (log->path); |
1677 | @@ -1085,13 +1095,12 @@ | |||
1678 | 1085 | /************************************************************/ | 1095 | /************************************************************/ |
1679 | 1086 | TEST_FEATURE ("ensure unflushed data freed with uid 0"); | 1096 | TEST_FEATURE ("ensure unflushed data freed with uid 0"); |
1680 | 1087 | 1097 | ||
1683 | 1088 | TEST_EQ (pipe (fds), 0); | 1098 | TEST_EQ (openpty (&pty_master, &pty_slave, NULL, NULL, NULL), 0); |
1682 | 1089 | TEST_GT (fd, 0); | ||
1684 | 1090 | 1099 | ||
1686 | 1091 | log = log_new (NULL, "/bar", fds[0], 0); | 1100 | log = log_new (NULL, "/bar", pty_master, 0); |
1687 | 1092 | TEST_NE_P (log, NULL); | 1101 | TEST_NE_P (log, NULL); |
1688 | 1093 | 1102 | ||
1690 | 1094 | ret = write (fds[1], str, strlen (str)); | 1103 | ret = write (pty_slave, str, strlen (str)); |
1691 | 1095 | TEST_GT (ret, 0); | 1104 | TEST_GT (ret, 0); |
1692 | 1096 | 1105 | ||
1693 | 1097 | TEST_FORCE_WATCH_UPDATE (); | 1106 | TEST_FORCE_WATCH_UPDATE (); |
1694 | @@ -1100,6 +1109,7 @@ | |||
1695 | 1100 | TEST_EQ_STR (log->unflushed->buf, str); | 1109 | TEST_EQ_STR (log->unflushed->buf, str); |
1696 | 1101 | TEST_FREE_TAG (log->unflushed); | 1110 | TEST_FREE_TAG (log->unflushed); |
1697 | 1102 | 1111 | ||
1698 | 1112 | close (pty_slave); | ||
1699 | 1103 | nih_free (log); | 1113 | nih_free (log); |
1700 | 1104 | TEST_FREE (log->unflushed); | 1114 | TEST_FREE (log->unflushed); |
1701 | 1105 | } | 1115 | } |
1702 | 1106 | 1116 | ||
1703 | === added file 'util/tests/test_user_sessions.sh' | |||
1704 | --- util/tests/test_user_sessions.sh 1970-01-01 00:00:00 +0000 | |||
1705 | +++ util/tests/test_user_sessions.sh 2012-01-26 15:59:26 +0000 | |||
1706 | @@ -0,0 +1,1091 @@ | |||
1707 | 1 | #!/bin/sh | ||
1708 | 2 | #--------------------------------------------------------------------- | ||
1709 | 3 | # Script to run minimal Upstart user session tests. | ||
1710 | 4 | # | ||
1711 | 5 | # Note that this script _cannot_ be run as part of the "make check" | ||
1712 | 6 | # tests since those tests stimulate functions and features of the | ||
1713 | 7 | # as-yet-uninstalled version of Upstart. However, this script needs to | ||
1714 | 8 | # run on a system where the version of Upstart under test has _already_ | ||
1715 | 9 | # been fully installed. | ||
1716 | 10 | #--------------------------------------------------------------------- | ||
1717 | 11 | # | ||
1718 | 12 | # Copyright (C) 2011 Canonical Ltd. | ||
1719 | 13 | # | ||
1720 | 14 | # Author: James Hunt <james.hunt@canonical.com> | ||
1721 | 15 | # | ||
1722 | 16 | # This program is free software: you can redistribute it and/or modify | ||
1723 | 17 | # it under the terms of the GNU General Public License as published by | ||
1724 | 18 | # the Free Software Foundation, version 3 of the License. | ||
1725 | 19 | # | ||
1726 | 20 | # This program is distributed in the hope that it will be useful, | ||
1727 | 21 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1728 | 22 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1729 | 23 | # GNU General Public License for more details. | ||
1730 | 24 | # | ||
1731 | 25 | # You should have received a copy of the GNU General Public License | ||
1732 | 26 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1733 | 27 | # | ||
1734 | 28 | #--------------------------------------------------------------------- | ||
1735 | 29 | |||
1736 | 30 | script_name=${0##*/} | ||
1737 | 31 | sys_job_dir="/etc/init" | ||
1738 | 32 | user_job_dir="$HOME/.init" | ||
1739 | 33 | user_log_dir="$HOME/.cache/upstart/log" | ||
1740 | 34 | sys_log_dir="/var/log/upstart" | ||
1741 | 35 | bug_url="https://bugs.launchpad.net/upstart/+filebug" | ||
1742 | 36 | test_dir= | ||
1743 | 37 | test_dir_suffix= | ||
1744 | 38 | user_to_create= | ||
1745 | 39 | uid= | ||
1746 | 40 | gid= | ||
1747 | 41 | opt= | ||
1748 | 42 | OPTARG= | ||
1749 | 43 | debug_enabled=0 | ||
1750 | 44 | feature= | ||
1751 | 45 | |||
1752 | 46 | # allow non-priv users to find 'initctl' | ||
1753 | 47 | export PATH=$PATH:/sbin | ||
1754 | 48 | |||
1755 | 49 | # for assertions | ||
1756 | 50 | die() | ||
1757 | 51 | { | ||
1758 | 52 | msg="$*" | ||
1759 | 53 | echo "ERROR: $msg" >&2 | ||
1760 | 54 | exit 1 | ||
1761 | 55 | } | ||
1762 | 56 | |||
1763 | 57 | debug() | ||
1764 | 58 | { | ||
1765 | 59 | str="$1" | ||
1766 | 60 | [ "$debug_enabled" = 1 ] && echo "DEBUG: $str" | ||
1767 | 61 | } | ||
1768 | 62 | |||
1769 | 63 | get_job_pid() | ||
1770 | 64 | { | ||
1771 | 65 | job="$1" | ||
1772 | 66 | [ -z "$job" ] && die "need job" | ||
1773 | 67 | |||
1774 | 68 | pid=$(initctl status "$job"|grep process|awk '{print $NF}') | ||
1775 | 69 | [ -z "$pid" ] && die "job $job has no pid" | ||
1776 | 70 | |||
1777 | 71 | echo "$pid" | ||
1778 | 72 | } | ||
1779 | 73 | |||
1780 | 74 | # take a string and convert it into a valid job name | ||
1781 | 75 | make_job_name() | ||
1782 | 76 | { | ||
1783 | 77 | str="$1" | ||
1784 | 78 | |||
1785 | 79 | echo "$str" |\ | ||
1786 | 80 | sed -e 's/>/ gt /g' -e 's/</ lt /g' -e 's/+/ and /g' |\ | ||
1787 | 81 | sed -e 's/[[:punct:]]//g' -e 's/ */ /g' |\ | ||
1788 | 82 | tr ' ' '-' | ||
1789 | 83 | } | ||
1790 | 84 | |||
1791 | 85 | upstart_encode() | ||
1792 | 86 | { | ||
1793 | 87 | str="$1" | ||
1794 | 88 | |||
1795 | 89 | echo "$str" | sed 's!/!_!g' | ||
1796 | 90 | } | ||
1797 | 91 | |||
1798 | 92 | # take a string and convert it into a valid job log file name | ||
1799 | 93 | make_log_name() | ||
1800 | 94 | { | ||
1801 | 95 | str="$1" | ||
1802 | 96 | upstart_encode "$str" | ||
1803 | 97 | } | ||
1804 | 98 | |||
1805 | 99 | TEST_FAILED() | ||
1806 | 100 | { | ||
1807 | 101 | args="$*" | ||
1808 | 102 | |||
1809 | 103 | [ -z "$args" ] && die "need args" | ||
1810 | 104 | |||
1811 | 105 | echo | ||
1812 | 106 | echo "ERROR: TEST FAILED ('$feature')" | ||
1813 | 107 | echo | ||
1814 | 108 | printf "BAD: ${args}\n" | ||
1815 | 109 | printf "\nPlease report a bug at $bug_url including the following details:\n" | ||
1816 | 110 | printf "\nUpstart:\n" | ||
1817 | 111 | /sbin/init --version|head -n1 | ||
1818 | 112 | /sbin/initctl --version|head -n1 | ||
1819 | 113 | echo | ||
1820 | 114 | printf "cmdline:\n" | ||
1821 | 115 | cat /proc/cmdline | ||
1822 | 116 | echo | ||
1823 | 117 | printf "Upstart Env:\n" | ||
1824 | 118 | set|grep UPSTART_ | ||
1825 | 119 | echo | ||
1826 | 120 | printf "lsb:\n" | ||
1827 | 121 | lsb_release -a | ||
1828 | 122 | printf "\nuname:\n" | ||
1829 | 123 | uname -a | ||
1830 | 124 | echo | ||
1831 | 125 | sync | ||
1832 | 126 | echo "ERROR: TEST FAILED ('$feature')" | ||
1833 | 127 | echo | ||
1834 | 128 | exit 1 | ||
1835 | 129 | } | ||
1836 | 130 | |||
1837 | 131 | TEST_GROUP() | ||
1838 | 132 | { | ||
1839 | 133 | name="$1" | ||
1840 | 134 | |||
1841 | 135 | [ -z "$name" ] && die "need name" | ||
1842 | 136 | |||
1843 | 137 | printf "Testing %s\n" "$name" | ||
1844 | 138 | } | ||
1845 | 139 | |||
1846 | 140 | TEST_FEATURE() | ||
1847 | 141 | { | ||
1848 | 142 | feature="$1" | ||
1849 | 143 | |||
1850 | 144 | [ -z "$feature" ] && die "need feature" | ||
1851 | 145 | |||
1852 | 146 | printf "...%s\n" "$feature" | ||
1853 | 147 | } | ||
1854 | 148 | |||
1855 | 149 | TEST_NE() | ||
1856 | 150 | { | ||
1857 | 151 | cmd="$1" | ||
1858 | 152 | value="$2" | ||
1859 | 153 | expected="$3" | ||
1860 | 154 | |||
1861 | 155 | # XXX: no checks on value or expected since they might be blank | ||
1862 | 156 | [ -z "$cmd" ] && die "need cmd" | ||
1863 | 157 | |||
1864 | 158 | [ "$value" = "$expected" ] && TEST_FAILED \ | ||
1865 | 159 | "wrong value for '$cmd', expected $expected got $value" | ||
1866 | 160 | } | ||
1867 | 161 | |||
1868 | 162 | TEST_EQ() | ||
1869 | 163 | { | ||
1870 | 164 | cmd="$1" | ||
1871 | 165 | value="$2" | ||
1872 | 166 | expected="$3" | ||
1873 | 167 | |||
1874 | 168 | # XXX: no checks on value or expected since they might be blank | ||
1875 | 169 | [ -z "$cmd" ] && die "need cmd" | ||
1876 | 170 | |||
1877 | 171 | [ "$value" != "$expected" ] && TEST_FAILED \ | ||
1878 | 172 | "wrong value for '$cmd', expected '$expected' got '$value'" | ||
1879 | 173 | } | ||
1880 | 174 | |||
1881 | 175 | checks() | ||
1882 | 176 | { | ||
1883 | 177 | cmd=initctl | ||
1884 | 178 | [ -z "$(command -v $cmd)" ] && die "cannot find command $cmd" | ||
1885 | 179 | |||
1886 | 180 | [ "$(id -u)" = 0 ] && die "ERROR: should not run this function as root" | ||
1887 | 181 | |||
1888 | 182 | # This will fail for a non-root user unless D-Bus is correctly | ||
1889 | 183 | # configured | ||
1890 | 184 | $cmd emit foo || die \ | ||
1891 | 185 | "You do not appear to have configured D-Bus for Upstart user sessions. See usage." | ||
1892 | 186 | } | ||
1893 | 187 | |||
1894 | 188 | setup() | ||
1895 | 189 | { | ||
1896 | 190 | uid=$(id -u) | ||
1897 | 191 | gid=$(id -g) | ||
1898 | 192 | |||
1899 | 193 | if [ "$uid" = 0 ] | ||
1900 | 194 | then | ||
1901 | 195 | [ -z "$user_to_create" ] && die "need '-u' option when running as root" | ||
1902 | 196 | |||
1903 | 197 | getent passwd "$user_to_create" && \ | ||
1904 | 198 | die "user '$user_to_create' already exists" | ||
1905 | 199 | |||
1906 | 200 | echo "Creating user '$user_to_create'" | ||
1907 | 201 | cmd="useradd -mU -c 'Upstart Test User' $user_to_create" | ||
1908 | 202 | eval "$cmd" | ||
1909 | 203 | TEST_EQ "$cmd" $? 0 | ||
1910 | 204 | |||
1911 | 205 | echo "Locking account for user '$user_to_create'" | ||
1912 | 206 | cmd="usermod -L $user_to_create" | ||
1913 | 207 | eval "$cmd" | ||
1914 | 208 | TEST_EQ "$cmd" $? 0 | ||
1915 | 209 | |||
1916 | 210 | # Run ourselves again as the new user | ||
1917 | 211 | su -c "$0 -a" "$user_to_create" | ||
1918 | 212 | test_run_rc=$? | ||
1919 | 213 | |||
1920 | 214 | if [ $test_run_rc -eq 0 ] | ||
1921 | 215 | then | ||
1922 | 216 | echo "Deleting user '$user_to_create'" | ||
1923 | 217 | cmd="userdel -r \"$user_to_create\"" | ||
1924 | 218 | eval "$cmd" | ||
1925 | 219 | TEST_EQ "$cmd" $? 0 | ||
1926 | 220 | fi | ||
1927 | 221 | |||
1928 | 222 | exit $test_run_rc | ||
1929 | 223 | fi | ||
1930 | 224 | |||
1931 | 225 | checks | ||
1932 | 226 | |||
1933 | 227 | # setup | ||
1934 | 228 | if [ ! -d "$user_job_dir" ] | ||
1935 | 229 | then | ||
1936 | 230 | cmd="mkdir -p \"$user_job_dir\"" | ||
1937 | 231 | eval $cmd | ||
1938 | 232 | TEST_EQ "$cmd" $? 0 | ||
1939 | 233 | |||
1940 | 234 | cmd="chmod 755 \"$user_job_dir\"" | ||
1941 | 235 | eval "$cmd" | ||
1942 | 236 | TEST_EQ "$cmd" $? 0 | ||
1943 | 237 | fi | ||
1944 | 238 | |||
1945 | 239 | # create somewhere to store user jobs | ||
1946 | 240 | cmd="mktemp -d --tmpdir=\"$user_job_dir\"" | ||
1947 | 241 | test_dir=$(eval "$cmd") | ||
1948 | 242 | TEST_EQ "$cmd" $? 0 | ||
1949 | 243 | TEST_NE "$test_dir" "$test_dir" "" | ||
1950 | 244 | test_dir_suffix=${test_dir#${user_job_dir}/} | ||
1951 | 245 | |||
1952 | 246 | # ensure files in this directory are accessible since | ||
1953 | 247 | # mktemp sets directory perms to 0700 regardless of umask. | ||
1954 | 248 | cmd="chmod 755 \"$test_dir\"" | ||
1955 | 249 | eval "$cmd" | ||
1956 | 250 | TEST_EQ "$cmd" $? 0 | ||
1957 | 251 | |||
1958 | 252 | TEST_NE "HOME" "$HOME" "" | ||
1959 | 253 | } | ||
1960 | 254 | |||
1961 | 255 | cleanup() | ||
1962 | 256 | { | ||
1963 | 257 | if [ -d "$test_dir" ] | ||
1964 | 258 | then | ||
1965 | 259 | echo "Removing test directory '$test_dir'" | ||
1966 | 260 | cmd="rmdir \"$test_dir\"" | ||
1967 | 261 | eval "$cmd" | ||
1968 | 262 | TEST_EQ "$cmd" $? 0 | ||
1969 | 263 | fi | ||
1970 | 264 | } | ||
1971 | 265 | |||
1972 | 266 | ensure_job_known() | ||
1973 | 267 | { | ||
1974 | 268 | job="$1" | ||
1975 | 269 | job_name="$2" | ||
1976 | 270 | |||
1977 | 271 | [ -z "$job" ] && die "no job" | ||
1978 | 272 | [ -z "$job_name" ] && die "no job name" | ||
1979 | 273 | |||
1980 | 274 | TEST_FEATURE "ensure 'initctl' recognises job" | ||
1981 | 275 | initctl list|grep -q "^$job " || \ | ||
1982 | 276 | TEST_FAILED "job $job_name not known to initctl" | ||
1983 | 277 | |||
1984 | 278 | TEST_FEATURE "ensure 'status' recognises job" | ||
1985 | 279 | cmd="status ${job}" | ||
1986 | 280 | eval "$cmd" >/dev/null 2>&1 | ||
1987 | 281 | rc=$? | ||
1988 | 282 | TEST_EQ "$cmd" $rc 0 | ||
1989 | 283 | } | ||
1990 | 284 | |||
1991 | 285 | # Note that if the specified job is *not* as task, it is expected to run | ||
1992 | 286 | # indefinately. This allows us to perform PID checks, etc. | ||
1993 | 287 | run_user_job_tests() | ||
1994 | 288 | { | ||
1995 | 289 | job_name="$1" | ||
1996 | 290 | job_file="$2" | ||
1997 | 291 | task="$3" | ||
1998 | 292 | env="$4" | ||
1999 | 293 | |||
2000 | 294 | # XXX: env can be empty | ||
2001 | 295 | [ -z "$job_name" ] && die "no job name" | ||
2002 | 296 | [ -z "$job_file" ] && die "no job file" | ||
2003 | 297 | [ -z "$task" ] && die "no task value" | ||
2004 | 298 | |||
2005 | 299 | job="${test_dir_suffix}/${job_name}" | ||
2006 | 300 | |||
2007 | 301 | [ -f "$job_file" ] || TEST_FAILED "job file '$job_file' does not exist" | ||
2008 | 302 | |||
2009 | 303 | ensure_job_known "$job" "$job_name" | ||
2010 | 304 | |||
2011 | 305 | TEST_FEATURE "ensure job can be started" | ||
2012 | 306 | cmd="start ${job} ${env}" | ||
2013 | 307 | output=$(eval "$cmd") | ||
2014 | 308 | rc=$? | ||
2015 | 309 | TEST_EQ "$cmd" $rc 0 | ||
2016 | 310 | |||
2017 | 311 | if [ "$task" = no ] | ||
2018 | 312 | then | ||
2019 | 313 | TEST_FEATURE "ensure 'start' shows job pid" | ||
2020 | 314 | pid=$(echo "$output"|awk '{print $4}') | ||
2021 | 315 | TEST_NE "pid" "$pid" "" | ||
2022 | 316 | |||
2023 | 317 | TEST_FEATURE "ensure 'initctl' shows job is running with pid" | ||
2024 | 318 | initctl list|grep -q "^$job start/running, process $pid" || \ | ||
2025 | 319 | TEST_FAILED "job $job_name did not start" | ||
2026 | 320 | |||
2027 | 321 | TEST_FEATURE "ensure 'status' shows job is running with pid" | ||
2028 | 322 | cmd="status ${job}" | ||
2029 | 323 | output=$(eval "$cmd") | ||
2030 | 324 | echo "$output"|while read job_tmp state ignored status_pid | ||
2031 | 325 | do | ||
2032 | 326 | state=$(echo $state|tr -d ',') | ||
2033 | 327 | TEST_EQ "job name" "$job_tmp" "$job" | ||
2034 | 328 | TEST_EQ "job state" "$state" "start/running" | ||
2035 | 329 | TEST_EQ "job pid" "$status_pid" "$pid" | ||
2036 | 330 | done | ||
2037 | 331 | |||
2038 | 332 | TEST_FEATURE "ensure job pid is running with correct uids" | ||
2039 | 333 | pid_uids=$(ps --no-headers -p $pid -o euid,ruid) | ||
2040 | 334 | for pid_uid in $pid_uids | ||
2041 | 335 | do | ||
2042 | 336 | TEST_EQ "pid uid" "$pid_uid" "$uid" | ||
2043 | 337 | done | ||
2044 | 338 | |||
2045 | 339 | TEST_FEATURE "ensure job pid is running with correct gids" | ||
2046 | 340 | pid_gids=$(ps --no-headers -p $pid -o egid,rgid) | ||
2047 | 341 | for pid_gid in $pid_gids | ||
2048 | 342 | do | ||
2049 | 343 | TEST_EQ "pid gid" "$pid_gid" "$gid" | ||
2050 | 344 | done | ||
2051 | 345 | |||
2052 | 346 | TEST_FEATURE "ensure process is running in correct directory" | ||
2053 | 347 | cwd=$(readlink /proc/$pid/cwd) | ||
2054 | 348 | TEST_EQ "cwd" "$cwd" "$HOME" | ||
2055 | 349 | |||
2056 | 350 | TEST_FEATURE "ensure job can be stopped" | ||
2057 | 351 | cmd="stop ${job}" | ||
2058 | 352 | output=$(eval "$cmd") | ||
2059 | 353 | rc=$? | ||
2060 | 354 | TEST_EQ "$cmd" $rc 0 | ||
2061 | 355 | |||
2062 | 356 | TEST_FEATURE "ensure job pid no longer exists" | ||
2063 | 357 | pid_ids=$(ps --no-headers -p $pid -o euid,ruid,egid,rgid) | ||
2064 | 358 | TEST_EQ "pid uids+gids" "$pid_ids" "" | ||
2065 | 359 | fi | ||
2066 | 360 | |||
2067 | 361 | remove_job_file "$job_file" | ||
2068 | 362 | ensure_job_gone "$job" "$job_name" "$env" | ||
2069 | 363 | } | ||
2070 | 364 | |||
2071 | 365 | remove_job_file() | ||
2072 | 366 | { | ||
2073 | 367 | job_file="$1" | ||
2074 | 368 | |||
2075 | 369 | [ -z "$job_file" ] && die "no job file" | ||
2076 | 370 | [ ! -f "$job_file" ] && TEST_FAILED "job file '$job_file' does not exist" | ||
2077 | 371 | |||
2078 | 372 | cmd="rm $job_file" | ||
2079 | 373 | eval "$cmd" | ||
2080 | 374 | TEST_EQ "$cmd" $? 0 | ||
2081 | 375 | } | ||
2082 | 376 | |||
2083 | 377 | ensure_job_gone() | ||
2084 | 378 | { | ||
2085 | 379 | job="$1" | ||
2086 | 380 | job_name="$2" | ||
2087 | 381 | env="$3" | ||
2088 | 382 | |||
2089 | 383 | # XXX: no check on env since it can be empty | ||
2090 | 384 | [ -z "$job" ] && die "no job" | ||
2091 | 385 | [ -z "$job_name" ] && die "no job name" | ||
2092 | 386 | |||
2093 | 387 | TEST_FEATURE "ensure 'initctl' no longer recognises job" | ||
2094 | 388 | initctl list|grep -q "^$job " && \ | ||
2095 | 389 | TEST_FAILED "deleted job $job_name still known to initctl" | ||
2096 | 390 | |||
2097 | 391 | TEST_FEATURE "ensure 'status' no longer recognises job" | ||
2098 | 392 | cmd="status ${job}" | ||
2099 | 393 | eval "$cmd" >/dev/null 2>&1 | ||
2100 | 394 | rc=$? | ||
2101 | 395 | TEST_NE "$cmd" $rc 0 | ||
2102 | 396 | } | ||
2103 | 397 | |||
2104 | 398 | test_user_job() | ||
2105 | 399 | { | ||
2106 | 400 | test_group="$1" | ||
2107 | 401 | job_name="$2" | ||
2108 | 402 | script="$3" | ||
2109 | 403 | task="$4" | ||
2110 | 404 | env="$5" | ||
2111 | 405 | |||
2112 | 406 | # XXX: no test on script or env since they might be empty | ||
2113 | 407 | [ -z "$test_group" ] && die "no test group" | ||
2114 | 408 | [ -z "$job_name" ] && die "no job name" | ||
2115 | 409 | [ -z "$task" ] && die "no task" | ||
2116 | 410 | |||
2117 | 411 | TEST_GROUP "$test_group" | ||
2118 | 412 | |||
2119 | 413 | job_file="${test_dir}/${job_name}.conf" | ||
2120 | 414 | |||
2121 | 415 | echo "$script" > $job_file | ||
2122 | 416 | |||
2123 | 417 | run_user_job_tests "$job_name" "$job_file" "$task" "$env" | ||
2124 | 418 | } | ||
2125 | 419 | |||
2126 | 420 | test_user_job_binary() | ||
2127 | 421 | { | ||
2128 | 422 | group="user job running a binary" | ||
2129 | 423 | job_name="binary_test" | ||
2130 | 424 | script="exec sleep 999" | ||
2131 | 425 | test_user_job "$group" "$job_name" "$script" no "" | ||
2132 | 426 | } | ||
2133 | 427 | |||
2134 | 428 | test_user_job_binary_task() | ||
2135 | 429 | { | ||
2136 | 430 | group="user job running a binary task" | ||
2137 | 431 | job_name="binary_task_test" | ||
2138 | 432 | OUTFILE=$(mktemp) | ||
2139 | 433 | |||
2140 | 434 | script="\ | ||
2141 | 435 | task | ||
2142 | 436 | exec /bin/true > $OUTFILE" | ||
2143 | 437 | |||
2144 | 438 | test_user_job "$group" "$job_name" "$script" yes "OUTFILE=$OUTFILE" | ||
2145 | 439 | rm -f $OUTFILE | ||
2146 | 440 | } | ||
2147 | 441 | |||
2148 | 442 | test_user_job_single_line_script() | ||
2149 | 443 | { | ||
2150 | 444 | group="user job running a single-line script" | ||
2151 | 445 | job_name="single_line_script_test" | ||
2152 | 446 | script="\ | ||
2153 | 447 | script | ||
2154 | 448 | sleep 999 | ||
2155 | 449 | end script" | ||
2156 | 450 | test_user_job "$group" "$job_name" "$script" no "" | ||
2157 | 451 | } | ||
2158 | 452 | |||
2159 | 453 | test_user_job_single_line_script_task() | ||
2160 | 454 | { | ||
2161 | 455 | group="user job running a single-line script task" | ||
2162 | 456 | job_name="single_line_script_task_test" | ||
2163 | 457 | OUTFILE=$(mktemp) | ||
2164 | 458 | |||
2165 | 459 | script="\ | ||
2166 | 460 | task | ||
2167 | 461 | script | ||
2168 | 462 | exec /bin/true > $OUTFILE | ||
2169 | 463 | end script" | ||
2170 | 464 | test_user_job "$group" "$job_name" "$script" yes "OUTFILE=$OUTFILE" | ||
2171 | 465 | rm -f $OUTFILE | ||
2172 | 466 | } | ||
2173 | 467 | |||
2174 | 468 | test_user_job_multi_line_script() | ||
2175 | 469 | { | ||
2176 | 470 | group="user job running a multi-line script" | ||
2177 | 471 | job_name="multi_line_script_test" | ||
2178 | 472 | script="\ | ||
2179 | 473 | script | ||
2180 | 474 | |||
2181 | 475 | /bin/true | ||
2182 | 476 | /bin/true;/bin/true | ||
2183 | 477 | sleep 999 | ||
2184 | 478 | |||
2185 | 479 | end script" | ||
2186 | 480 | test_user_job "$group" "$job_name" "$script" no "" | ||
2187 | 481 | } | ||
2188 | 482 | |||
2189 | 483 | test_user_job_multi_line_script_task() | ||
2190 | 484 | { | ||
2191 | 485 | group="user job running a multi-line script task" | ||
2192 | 486 | job_name="multi_line_script_task_test" | ||
2193 | 487 | OUTFILE=$(mktemp) | ||
2194 | 488 | |||
2195 | 489 | script="\ | ||
2196 | 490 | task | ||
2197 | 491 | script | ||
2198 | 492 | |||
2199 | 493 | /bin/true | ||
2200 | 494 | /bin/true | ||
2201 | 495 | /bin/true | ||
2202 | 496 | |||
2203 | 497 | end script" | ||
2204 | 498 | test_user_job "$group" "$job_name" "$script" yes "OUTFILE=$OUTFILE" | ||
2205 | 499 | rm -f $OUTFILE | ||
2206 | 500 | } | ||
2207 | 501 | |||
2208 | 502 | test_user_emit_events() | ||
2209 | 503 | { | ||
2210 | 504 | job_name="start_on_foo" | ||
2211 | 505 | |||
2212 | 506 | TEST_GROUP "user emitting an event" | ||
2213 | 507 | initctl emit foo || TEST_FAILED "failed to emit event as user" | ||
2214 | 508 | |||
2215 | 509 | TEST_GROUP "user emitting an event to start a job" | ||
2216 | 510 | script="\ | ||
2217 | 511 | start on foo BAR=2 | ||
2218 | 512 | stop on baz cow=moo or hello | ||
2219 | 513 | exec sleep 999" | ||
2220 | 514 | |||
2221 | 515 | job_file="${test_dir}/${job_name}.conf" | ||
2222 | 516 | job="${test_dir_suffix}/${job_name}" | ||
2223 | 517 | |||
2224 | 518 | echo "$script" > $job_file | ||
2225 | 519 | |||
2226 | 520 | ensure_job_known "$job" "$job_name" | ||
2227 | 521 | |||
2228 | 522 | initctl list|grep -q "^$job stop/waiting" || \ | ||
2229 | 523 | TEST_FAILED "job $job_name not stopped" | ||
2230 | 524 | |||
2231 | 525 | TEST_FEATURE "ensure job can be started with event" | ||
2232 | 526 | initctl emit foo BAR=2 || \ | ||
2233 | 527 | TEST_FAILED "failed to emit event for user job" | ||
2234 | 528 | |||
2235 | 529 | initctl status "$job"|grep -q "^$job start/running" || \ | ||
2236 | 530 | TEST_FAILED "job $job_name failed to start" | ||
2237 | 531 | |||
2238 | 532 | TEST_FEATURE "ensure job can be stopped with event" | ||
2239 | 533 | initctl emit baz cow=moo || \ | ||
2240 | 534 | TEST_FAILED "failed to emit event for user job" | ||
2241 | 535 | |||
2242 | 536 | initctl list|grep -q "^$job stop/waiting" || \ | ||
2243 | 537 | TEST_FAILED "job $job_name not stopped" | ||
2244 | 538 | |||
2245 | 539 | rm -f "$job_file" | ||
2246 | 540 | } | ||
2247 | 541 | |||
2248 | 542 | test_user_job_setuid_setgid() | ||
2249 | 543 | { | ||
2250 | 544 | group="user job with setuid and setgid me" | ||
2251 | 545 | job_name="setuid_setgid_me_test" | ||
2252 | 546 | script="\ | ||
2253 | 547 | setuid $(id -un) | ||
2254 | 548 | setgid $(id -gn) | ||
2255 | 549 | exec sleep 999" | ||
2256 | 550 | test_user_job "$group" "$job_name" "$script" no "" | ||
2257 | 551 | |||
2258 | 552 | TEST_GROUP "user job with setuid and setgid root" | ||
2259 | 553 | script="\ | ||
2260 | 554 | setuid root | ||
2261 | 555 | setgid root | ||
2262 | 556 | exec sleep 999" | ||
2263 | 557 | |||
2264 | 558 | job_name="setuid_setgid_root_test" | ||
2265 | 559 | job_file="${test_dir}/${job_name}.conf" | ||
2266 | 560 | job="${test_dir_suffix}/${job_name}" | ||
2267 | 561 | |||
2268 | 562 | echo "$script" > $job_file | ||
2269 | 563 | |||
2270 | 564 | ensure_job_known "$job" "$job_name" | ||
2271 | 565 | |||
2272 | 566 | TEST_FEATURE "ensure job fails to start as root" | ||
2273 | 567 | cmd="start ${job}" | ||
2274 | 568 | output=$(eval "$cmd" 2>&1) | ||
2275 | 569 | rc=$? | ||
2276 | 570 | TEST_EQ "$cmd" $rc 1 | ||
2277 | 571 | |||
2278 | 572 | TEST_FEATURE "ensure 'start' indicates job failure" | ||
2279 | 573 | error=$(echo "$output"|grep failed) | ||
2280 | 574 | TEST_NE "error" "$error" "" | ||
2281 | 575 | |||
2282 | 576 | TEST_FEATURE "ensure 'initctl' does not list job" | ||
2283 | 577 | initctl list|grep -q "^$job stop/waiting" || \ | ||
2284 | 578 | TEST_FAILED "job $job_name not listed as stopped" | ||
2285 | 579 | |||
2286 | 580 | delete_job "$job_name" | ||
2287 | 581 | } | ||
2288 | 582 | |||
2289 | 583 | get_job_file() | ||
2290 | 584 | { | ||
2291 | 585 | job_name="$1" | ||
2292 | 586 | |||
2293 | 587 | [ -z "$job_name" ] && die "no job name" | ||
2294 | 588 | echo "${test_dir}/${job_name}.conf" | ||
2295 | 589 | } | ||
2296 | 590 | |||
2297 | 591 | ensure_no_output() | ||
2298 | 592 | { | ||
2299 | 593 | job_name="$1" | ||
2300 | 594 | script="$2" | ||
2301 | 595 | instance="$3" | ||
2302 | 596 | |||
2303 | 597 | job="${test_dir_suffix}/${job_name}" | ||
2304 | 598 | |||
2305 | 599 | create_job "$job_name" "$script" | ||
2306 | 600 | start_job "$job" "$job_name" "$instance" | ||
2307 | 601 | |||
2308 | 602 | check_job_output "$job_name" | ||
2309 | 603 | delete_job "$job_name" | ||
2310 | 604 | } | ||
2311 | 605 | |||
2312 | 606 | create_job() | ||
2313 | 607 | { | ||
2314 | 608 | job_name="$1" | ||
2315 | 609 | script="$2" | ||
2316 | 610 | |||
2317 | 611 | # XXX: script could be empty | ||
2318 | 612 | [ -z "$job_name" ] && die "no job name" | ||
2319 | 613 | |||
2320 | 614 | debug "create_job: job_name='$job_name'" | ||
2321 | 615 | debug "create_job: script='$script'" | ||
2322 | 616 | |||
2323 | 617 | # Not currently possible to have a user job with the | ||
2324 | 618 | # same name as a system job. | ||
2325 | 619 | # | ||
2326 | 620 | # XXX: Note that this test assumes that user has *not* specified | ||
2327 | 621 | # XXX: an alternate configuration directory using the | ||
2328 | 622 | # XXX: '--confdir' option. | ||
2329 | 623 | [ -e "${sys_job_dir}/${job_name}.conf" ] && \ | ||
2330 | 624 | die "job '$job_name' already exists as a system job" | ||
2331 | 625 | |||
2332 | 626 | job_file="${test_dir}/${job_name}.conf" | ||
2333 | 627 | job="${test_dir_suffix}/${job_name}" | ||
2334 | 628 | |||
2335 | 629 | echo "$script" > "$job_file" | ||
2336 | 630 | sync | ||
2337 | 631 | } | ||
2338 | 632 | |||
2339 | 633 | delete_job() | ||
2340 | 634 | { | ||
2341 | 635 | job_name="$1" | ||
2342 | 636 | |||
2343 | 637 | [ -z "$job_name" ] && die "no job name" | ||
2344 | 638 | |||
2345 | 639 | job_file="$(get_job_file $job_name)" | ||
2346 | 640 | |||
2347 | 641 | rm "$job_file" || TEST_FAILED "unable to remove job file '$job_file'" | ||
2348 | 642 | } | ||
2349 | 643 | |||
2350 | 644 | check_job_output() | ||
2351 | 645 | { | ||
2352 | 646 | job_name="$1" | ||
2353 | 647 | |||
2354 | 648 | [ ! -z "$(ls $user_log_dir 2>/dev/null)" ] && \ | ||
2355 | 649 | TEST_FAILED "job $job_name created logfile unexpectedly in '$user_log_dir'" | ||
2356 | 650 | |||
2357 | 651 | # XXX: note that it might appear that checking in $sys_log_dir | ||
2358 | 652 | # could result in false positives, but this isn't so since | ||
2359 | 653 | # (currently) it is not possible for a user job to have the | ||
2360 | 654 | # same name as a system job. start_job() will detect this | ||
2361 | 655 | # scenario. | ||
2362 | 656 | for dir in "$user_log_dir" "$sys_log_dir" | ||
2363 | 657 | do | ||
2364 | 658 | log_file="${dir}/${job_name}.log" | ||
2365 | 659 | [ -f "$log_file" ] && \ | ||
2366 | 660 | TEST_FAILED "job $job_name created logfile unexpectedly as '$log_file'" | ||
2367 | 661 | done | ||
2368 | 662 | } | ||
2369 | 663 | |||
2370 | 664 | start_job() | ||
2371 | 665 | { | ||
2372 | 666 | job="$1" | ||
2373 | 667 | job_file="$2" | ||
2374 | 668 | instance="$3" | ||
2375 | 669 | allow_failure="$4" | ||
2376 | 670 | |||
2377 | 671 | # XXX: instance may be blank | ||
2378 | 672 | [ -z "$job" ] && die "no job" | ||
2379 | 673 | [ -z "$job_file" ] && die "no job file" | ||
2380 | 674 | |||
2381 | 675 | debug "start_job: job='$job'" | ||
2382 | 676 | debug "start_job: job_file='$job_file'" | ||
2383 | 677 | debug "start_job: instance='$instance'" | ||
2384 | 678 | debug "start_job: allow_failure='$allow_failure'" | ||
2385 | 679 | |||
2386 | 680 | eval output=$(mktemp) | ||
2387 | 681 | |||
2388 | 682 | # XXX: Don't quote instance as we don't want to pass a null instance to | ||
2389 | 683 | # start(8). | ||
2390 | 684 | cmd="start \"$job\" $instance >${output} 2>&1" | ||
2391 | 685 | debug "start_job: running '$cmd'" | ||
2392 | 686 | eval "$cmd" | ||
2393 | 687 | rc=$? | ||
2394 | 688 | |||
2395 | 689 | if [ $rc -ne 0 -a -z "$allow_failure" ] | ||
2396 | 690 | then | ||
2397 | 691 | TEST_FAILED "job $job_file not started: $(cat $output)" | ||
2398 | 692 | fi | ||
2399 | 693 | |||
2400 | 694 | rm -f "$output" | ||
2401 | 695 | } | ||
2402 | 696 | |||
2403 | 697 | get_job_logfile_name() | ||
2404 | 698 | { | ||
2405 | 699 | job_name="$1" | ||
2406 | 700 | instance_value="$2" | ||
2407 | 701 | |||
2408 | 702 | # XXX: instance may be null | ||
2409 | 703 | [ -z "$job_name" ] && die "no job name" | ||
2410 | 704 | |||
2411 | 705 | encoded_test_dir_suffix=$(upstart_encode "${test_dir_suffix}/") | ||
2412 | 706 | file_name="${encoded_test_dir_suffix}$(make_log_name $job_name)" | ||
2413 | 707 | |||
2414 | 708 | if [ ! -z "$instance_value" ] | ||
2415 | 709 | then | ||
2416 | 710 | log_file="${user_log_dir}/${file_name}-${instance_value}.log" | ||
2417 | 711 | else | ||
2418 | 712 | log_file="${user_log_dir}/${file_name}.log" | ||
2419 | 713 | fi | ||
2420 | 714 | |||
2421 | 715 | echo "$log_file" | ||
2422 | 716 | } | ||
2423 | 717 | |||
2424 | 718 | run_job() | ||
2425 | 719 | { | ||
2426 | 720 | job="$1" | ||
2427 | 721 | job_name="$2" | ||
2428 | 722 | script="$3" | ||
2429 | 723 | instance="$4" | ||
2430 | 724 | |||
2431 | 725 | # XXX: script, instance might be blank | ||
2432 | 726 | [ -z "$job" ] && die "no job" | ||
2433 | 727 | [ -z "$job_name" ] && die "no job name" | ||
2434 | 728 | |||
2435 | 729 | debug "run_job: job='$job'" | ||
2436 | 730 | debug "run_job: job_name='$job_name'" | ||
2437 | 731 | debug "run_job: script='$script'" | ||
2438 | 732 | debug "run_job: instance='$instance'" | ||
2439 | 733 | |||
2440 | 734 | create_job "$job_name" "$script" | ||
2441 | 735 | start_job "$job" "$job_name" "$instance" | ||
2442 | 736 | } | ||
2443 | 737 | |||
2444 | 738 | ensure_file_meta() | ||
2445 | 739 | { | ||
2446 | 740 | file="$1" | ||
2447 | 741 | expected_owner="$2" | ||
2448 | 742 | expected_group="$3" | ||
2449 | 743 | expected_perms="$4" | ||
2450 | 744 | |||
2451 | 745 | [ -z "$file" ] && die "no file" | ||
2452 | 746 | [ -z "$expected_owner" ] && die "no expected owner" | ||
2453 | 747 | [ -z "$expected_group" ] && die "no expected group" | ||
2454 | 748 | [ -z "$expected_perms" ] && die "no expected perms" | ||
2455 | 749 | |||
2456 | 750 | [ ! -f "$file" ] && die "file $file does not exist" | ||
2457 | 751 | |||
2458 | 752 | expected_perms="640" | ||
2459 | 753 | umask_value=$(umask) | ||
2460 | 754 | umask_expected=0022 | ||
2461 | 755 | |||
2462 | 756 | if [ "$umask_value" != "$umask_expected" ] | ||
2463 | 757 | then | ||
2464 | 758 | msg="umask value is $umask_value -" | ||
2465 | 759 | msg="${msg} changing it to $umask_expected." | ||
2466 | 760 | echo "WARNING: $msg" | ||
2467 | 761 | umask "$umask_expected" || TEST_FAILED "unable to change umask" | ||
2468 | 762 | fi | ||
2469 | 763 | |||
2470 | 764 | owner=$(ls -l "$file"|awk '{print $3}') | ||
2471 | 765 | group=$(ls -l "$file"|awk '{print $4}') | ||
2472 | 766 | perms=$(stat --printf "%a\n" "$file") | ||
2473 | 767 | |||
2474 | 768 | [ "$owner" = "$expected_owner" ] || TEST_FAILED \ | ||
2475 | 769 | "file $file has wrong owner (expected $expected_owner, got $owner)" | ||
2476 | 770 | |||
2477 | 771 | [ "$group" = "$expected_group" ] || TEST_FAILED \ | ||
2478 | 772 | "file $file has wrong group (expected $expected_group, got $group)" | ||
2479 | 773 | |||
2480 | 774 | [ "$perms" = "$expected_perms" ] || TEST_FAILED \ | ||
2481 | 775 | "file $file has wrong group (expected $expected_perms, got $perms)" | ||
2482 | 776 | } | ||
2483 | 777 | |||
2484 | 778 | |||
2485 | 779 | ensure_output() | ||
2486 | 780 | { | ||
2487 | 781 | job_name="$1" | ||
2488 | 782 | script="$2" | ||
2489 | 783 | expected_output="$3" | ||
2490 | 784 | instance="$4" | ||
2491 | 785 | instance_value="$5" | ||
2492 | 786 | options="$6" | ||
2493 | 787 | |||
2494 | 788 | # XXX: remaining args could be null | ||
2495 | 789 | [ -z "$job_name" ] && die "no job name" | ||
2496 | 790 | |||
2497 | 791 | debug "ensure_output: job_name='$job_name'" | ||
2498 | 792 | debug "ensure_output: script='$script'" | ||
2499 | 793 | debug "ensure_output: expected_ouput='$expected_ouput'" | ||
2500 | 794 | debug "ensure_output: instance='$instance'" | ||
2501 | 795 | debug "ensure_output: instance_value='$instance_value'" | ||
2502 | 796 | debug "ensure_output: options='$options'" | ||
2503 | 797 | |||
2504 | 798 | regex=n | ||
2505 | 799 | retain=n | ||
2506 | 800 | unique="" | ||
2507 | 801 | use_od=n | ||
2508 | 802 | |||
2509 | 803 | for opt in $options | ||
2510 | 804 | do | ||
2511 | 805 | case "$opt" in | ||
2512 | 806 | regex) | ||
2513 | 807 | regex=y | ||
2514 | 808 | ;; | ||
2515 | 809 | retain) | ||
2516 | 810 | retain=y | ||
2517 | 811 | ;; | ||
2518 | 812 | unique) | ||
2519 | 813 | unique='|sort -u' | ||
2520 | 814 | ;; | ||
2521 | 815 | use_od) | ||
2522 | 816 | use_od=y | ||
2523 | 817 | ;; | ||
2524 | 818 | esac | ||
2525 | 819 | done | ||
2526 | 820 | |||
2527 | 821 | debug "ensure_output: regex='$regex'" | ||
2528 | 822 | debug "ensure_output: retain='$retain'" | ||
2529 | 823 | debug "ensure_output: unique='$unique'" | ||
2530 | 824 | debug "ensure_output: use_od='$use_od'" | ||
2531 | 825 | |||
2532 | 826 | expected_owner=$(id -un) | ||
2533 | 827 | expected_group=$(id -gn) | ||
2534 | 828 | expected_perms="640" | ||
2535 | 829 | |||
2536 | 830 | job="${test_dir_suffix}/${job_name}" | ||
2537 | 831 | |||
2538 | 832 | run_job "$job" "$job_name" "$script" "$instance" | ||
2539 | 833 | |||
2540 | 834 | debug "ensure_output: user_log_dir='$user_log_dir'" | ||
2541 | 835 | debug "ensure_output: test_dir='$test_dir'" | ||
2542 | 836 | debug "ensure_output: test_dir_suffix='$test_dir_suffix'" | ||
2543 | 837 | |||
2544 | 838 | log_file=$(get_job_logfile_name "$job_name" "$instance_value") | ||
2545 | 839 | |||
2546 | 840 | debug "ensure_output: log_file='$log_file'" | ||
2547 | 841 | |||
2548 | 842 | # Give Upstart a chance to parse the file | ||
2549 | 843 | count=1 | ||
2550 | 844 | while ! status "$job" >/dev/null 2>&1 | ||
2551 | 845 | do | ||
2552 | 846 | sleep 1 | ||
2553 | 847 | count=$((count+1)) | ||
2554 | 848 | [ "$count" -eq 5 ] && break | ||
2555 | 849 | done | ||
2556 | 850 | |||
2557 | 851 | # give job a chance to start | ||
2558 | 852 | count=1 | ||
2559 | 853 | while [ ! -f "$log_file" ] | ||
2560 | 854 | do | ||
2561 | 855 | sleep 1 | ||
2562 | 856 | count=$((count+1)) | ||
2563 | 857 | [ "$count" -eq 5 ] && break | ||
2564 | 858 | done | ||
2565 | 859 | |||
2566 | 860 | [ ! -f "$log_file" ] && \ | ||
2567 | 861 | TEST_FAILED "job '$job_name' failed to create logfile" | ||
2568 | 862 | |||
2569 | 863 | ensure_file_meta \ | ||
2570 | 864 | "$log_file" \ | ||
2571 | 865 | "$expected_owner" \ | ||
2572 | 866 | "$expected_group" \ | ||
2573 | 867 | "$expected_perms" | ||
2574 | 868 | |||
2575 | 869 | # XXX: note we have to remove carriage returns added by the line | ||
2576 | 870 | # discipline | ||
2577 | 871 | if [ "$regex" = y ] | ||
2578 | 872 | then | ||
2579 | 873 | log=$(eval "cat $log_file|tr -d '\r' $unique") | ||
2580 | 874 | msg="job '$job_name' failed to log correct data\n" | ||
2581 | 875 | msg="${msg}\texpected regex: '$expected_output'\n" | ||
2582 | 876 | msg="${msg}\tgot : '$log'" | ||
2583 | 877 | cat "$log_file" | egrep "$expected_output" || TEST_FAILED "$msg" | ||
2584 | 878 | elif [ "$use_od" = y ] | ||
2585 | 879 | then | ||
2586 | 880 | log=$(eval "cat $log_file|tr -d '\r' $unique|od -x") | ||
2587 | 881 | msg="job '$job_name' failed to log correct data\n" | ||
2588 | 882 | msg="${msg}\texpected hex: '$expected_output'\n" | ||
2589 | 883 | msg="${msg}\tgot : '$log'" | ||
2590 | 884 | [ "$expected_output" != "$log" ] && TEST_FAILED "$msg" | ||
2591 | 885 | else | ||
2592 | 886 | log=$(eval "cat $log_file|tr -d '\r' $unique") | ||
2593 | 887 | msg="job '$job_name' failed to log correct data\n" | ||
2594 | 888 | msg="${msg}\texpected text: '$expected_output'\n" | ||
2595 | 889 | msg="${msg}\tgot : '$log'" | ||
2596 | 890 | [ "$expected_output" != "$log" ] && TEST_FAILED "$msg" | ||
2597 | 891 | fi | ||
2598 | 892 | |||
2599 | 893 | if [ "$retain" = n ] | ||
2600 | 894 | then | ||
2601 | 895 | delete_job "$job_name" | ||
2602 | 896 | rm "$log_file" || TEST_FAILED "unable to remove log file '$log_file'" | ||
2603 | 897 | fi | ||
2604 | 898 | } | ||
2605 | 899 | |||
2606 | 900 | test_ensure_no_unexpected_output() | ||
2607 | 901 | { | ||
2608 | 902 | #--------------------------------------------------------------------- | ||
2609 | 903 | feature="ensure command job does not create log file with no console" | ||
2610 | 904 | TEST_FEATURE "$feature" | ||
2611 | 905 | |||
2612 | 906 | job_name=$(make_job_name "$feature") | ||
2613 | 907 | |||
2614 | 908 | script="\ | ||
2615 | 909 | console none | ||
2616 | 910 | exec echo hello world" | ||
2617 | 911 | |||
2618 | 912 | ensure_no_output "$job_name" "$script" "" | ||
2619 | 913 | |||
2620 | 914 | #--------------------------------------------------------------------- | ||
2621 | 915 | feature="ensure 1-line script job does not create log file with no console" | ||
2622 | 916 | TEST_FEATURE "$feature" | ||
2623 | 917 | |||
2624 | 918 | job_name=$(make_job_name "$feature") | ||
2625 | 919 | |||
2626 | 920 | script="\ | ||
2627 | 921 | console none | ||
2628 | 922 | script | ||
2629 | 923 | echo hello world | ||
2630 | 924 | end script | ||
2631 | 925 | " | ||
2632 | 926 | |||
2633 | 927 | ensure_no_output "$job_name" "$script" "" | ||
2634 | 928 | |||
2635 | 929 | #--------------------------------------------------------------------- | ||
2636 | 930 | feature="ensure multi-line script job does not create log file with no console" | ||
2637 | 931 | TEST_FEATURE "$feature" | ||
2638 | 932 | |||
2639 | 933 | job_name=$(make_job_name "$feature") | ||
2640 | 934 | |||
2641 | 935 | script="\ | ||
2642 | 936 | console none | ||
2643 | 937 | script | ||
2644 | 938 | /bin/true | ||
2645 | 939 | echo hello world | ||
2646 | 940 | end script | ||
2647 | 941 | " | ||
2648 | 942 | |||
2649 | 943 | ensure_no_output "$job_name" "$script" "" | ||
2650 | 944 | |||
2651 | 945 | #--------------------------------------------------------------------- | ||
2652 | 946 | feature="ensure no output if log directory does not exist" | ||
2653 | 947 | TEST_FEATURE "$feature" | ||
2654 | 948 | |||
2655 | 949 | rmdir "${user_log_dir}" || \ | ||
2656 | 950 | TEST_FAILED "unable to delete log directory '$user_log_dir'" | ||
2657 | 951 | |||
2658 | 952 | job_name=$(make_job_name "$feature") | ||
2659 | 953 | string="hello world" | ||
2660 | 954 | script="\ | ||
2661 | 955 | console log | ||
2662 | 956 | script | ||
2663 | 957 | /bin/true | ||
2664 | 958 | /bin/echo hello world | ||
2665 | 959 | end script | ||
2666 | 960 | " | ||
2667 | 961 | |||
2668 | 962 | ensure_no_output "$job_name" "$script" "" | ||
2669 | 963 | |||
2670 | 964 | mkdir "${user_log_dir}" || \ | ||
2671 | 965 | TEST_FAILED "unable to recreate log directory '$user_log_dir'" | ||
2672 | 966 | |||
2673 | 967 | #--------------------------------------------------------------------- | ||
2674 | 968 | feature="ensure command job does not create log file with invalid command" | ||
2675 | 969 | TEST_FEATURE "$feature" | ||
2676 | 970 | |||
2677 | 971 | job_name=$(make_job_name "$feature") | ||
2678 | 972 | |||
2679 | 973 | script="\ | ||
2680 | 974 | console log | ||
2681 | 975 | exec /this/command/does/not/exist" | ||
2682 | 976 | |||
2683 | 977 | job="${test_dir_suffix}/${job_name}" | ||
2684 | 978 | create_job "$job_name" "$script" | ||
2685 | 979 | start_job "$job" "$job_name" "" 1 | ||
2686 | 980 | check_job_output "$job_name" | ||
2687 | 981 | delete_job "$job_name" | ||
2688 | 982 | } | ||
2689 | 983 | |||
2690 | 984 | test_output_logged() | ||
2691 | 985 | { | ||
2692 | 986 | # XXX: upstart won't create this | ||
2693 | 987 | mkdir -p "$user_log_dir" | ||
2694 | 988 | |||
2695 | 989 | test_ensure_no_unexpected_output | ||
2696 | 990 | } | ||
2697 | 991 | |||
2698 | 992 | test_user_jobs() | ||
2699 | 993 | { | ||
2700 | 994 | test_user_job_binary | ||
2701 | 995 | test_user_job_single_line_script | ||
2702 | 996 | test_user_job_multi_line_script | ||
2703 | 997 | |||
2704 | 998 | test_user_job_binary_task | ||
2705 | 999 | test_user_job_single_line_script_task | ||
2706 | 1000 | test_user_job_multi_line_script_task | ||
2707 | 1001 | |||
2708 | 1002 | test_user_job_setuid_setgid | ||
2709 | 1003 | |||
2710 | 1004 | test_user_emit_events | ||
2711 | 1005 | |||
2712 | 1006 | test_output_logged | ||
2713 | 1007 | } | ||
2714 | 1008 | |||
2715 | 1009 | tests() | ||
2716 | 1010 | { | ||
2717 | 1011 | echo | ||
2718 | 1012 | echo -n "Running Upstart user session tests as user '`whoami`'" | ||
2719 | 1013 | echo " (uid $uid, gid $gid) in directory '$test_dir'" | ||
2720 | 1014 | echo | ||
2721 | 1015 | |||
2722 | 1016 | test_user_jobs | ||
2723 | 1017 | |||
2724 | 1018 | echo | ||
2725 | 1019 | echo "All tests completed successfully" | ||
2726 | 1020 | echo | ||
2727 | 1021 | } | ||
2728 | 1022 | |||
2729 | 1023 | usage() | ||
2730 | 1024 | { | ||
2731 | 1025 | cat <<EOT | ||
2732 | 1026 | USAGE: $script_name [options] | ||
2733 | 1027 | |||
2734 | 1028 | OPTIONS: | ||
2735 | 1029 | |||
2736 | 1030 | -a : Actually run this script. | ||
2737 | 1031 | -h : Show this help. | ||
2738 | 1032 | -u <user> : Specify name of test user to create. | ||
2739 | 1033 | |||
2740 | 1034 | DESCRIPTION: | ||
2741 | 1035 | |||
2742 | 1036 | Run simple set of Upstart user session tests. | ||
2743 | 1037 | |||
2744 | 1038 | PREREQUISITE: | ||
2745 | 1039 | |||
2746 | 1040 | For this test to run, non-root users must be allowed to invoke all D-Bus | ||
2747 | 1041 | methods on Upstart via configuration file: | ||
2748 | 1042 | |||
2749 | 1043 | /etc/dbus-1/system.d/Upstart.conf | ||
2750 | 1044 | |||
2751 | 1045 | See dbus-daemon(1) for further details. | ||
2752 | 1046 | |||
2753 | 1047 | WARNING: Note that this script is unavoidably invasive, so read what | ||
2754 | 1048 | WARNING: follows before running! | ||
2755 | 1049 | |||
2756 | 1050 | If run as a non-root user, this script will create a uniquely-named | ||
2757 | 1051 | subdirectory below "\$HOME/.init/" to run its tests in. On successful | ||
2758 | 1052 | completion of these tests, the unique subdirectory and its contents will | ||
2759 | 1053 | be removed. | ||
2760 | 1054 | |||
2761 | 1055 | If however, this script is invoked as the root user, the script will | ||
2762 | 1056 | refuse to run until given the name of a test user to create via the "-u" | ||
2763 | 1057 | option. If the user specified to this option already exists, this script | ||
2764 | 1058 | will exit with an error. If the user does not already exist, it will be | ||
2765 | 1059 | created, the script then run *as that user* and assuming successful | ||
2766 | 1060 | completion of the tests, the test user and their home directory will | ||
2767 | 1061 | then be deleted. | ||
2768 | 1062 | |||
2769 | 1063 | EOT | ||
2770 | 1064 | } | ||
2771 | 1065 | |||
2772 | 1066 | #--------------------------------------------------------------------- | ||
2773 | 1067 | # main | ||
2774 | 1068 | #--------------------------------------------------------------------- | ||
2775 | 1069 | |||
2776 | 1070 | while getopts "dhu:" opt | ||
2777 | 1071 | do | ||
2778 | 1072 | case "$opt" in | ||
2779 | 1073 | d) | ||
2780 | 1074 | debug_enabled=1 | ||
2781 | 1075 | ;; | ||
2782 | 1076 | |||
2783 | 1077 | h) | ||
2784 | 1078 | usage | ||
2785 | 1079 | exit 0 | ||
2786 | 1080 | ;; | ||
2787 | 1081 | |||
2788 | 1082 | u) | ||
2789 | 1083 | user_to_create="$OPTARG" | ||
2790 | 1084 | ;; | ||
2791 | 1085 | esac | ||
2792 | 1086 | done | ||
2793 | 1087 | |||
2794 | 1088 | setup | ||
2795 | 1089 | tests | ||
2796 | 1090 | cleanup | ||
2797 | 1091 | exit 0 | ||
2798 | 0 | 1092 | ||
2799 | === removed file 'util/tests/test_user_sessions.sh' | |||
2800 | --- util/tests/test_user_sessions.sh 2011-07-26 01:09:47 +0000 | |||
2801 | +++ util/tests/test_user_sessions.sh 1970-01-01 00:00:00 +0000 | |||
2802 | @@ -1,553 +0,0 @@ | |||
2803 | 1 | #!/bin/sh -u | ||
2804 | 2 | #--------------------------------------------------------------------- | ||
2805 | 3 | # Script to run minimal Upstart user session tests. | ||
2806 | 4 | # | ||
2807 | 5 | # Note that this script _cannot_ be run as part of the "make check" | ||
2808 | 6 | # tests since those tests stimulate functions and features of the | ||
2809 | 7 | # as-yet-uninstalled version of Upstart. However, this script needs to | ||
2810 | 8 | # run on a system where the version of Upstart under test has _already_ | ||
2811 | 9 | # been fully installed. | ||
2812 | 10 | #--------------------------------------------------------------------- | ||
2813 | 11 | # | ||
2814 | 12 | # Copyright (C) 2011 Canonical Ltd. | ||
2815 | 13 | # | ||
2816 | 14 | # Author: James Hunt <james.hunt@canonical.com> | ||
2817 | 15 | # | ||
2818 | 16 | # This program is free software: you can redistribute it and/or modify | ||
2819 | 17 | # it under the terms of the GNU General Public License as published by | ||
2820 | 18 | # the Free Software Foundation, version 3 of the License. | ||
2821 | 19 | # | ||
2822 | 20 | # This program is distributed in the hope that it will be useful, | ||
2823 | 21 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2824 | 22 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2825 | 23 | # GNU General Public License for more details. | ||
2826 | 24 | # | ||
2827 | 25 | # You should have received a copy of the GNU General Public License | ||
2828 | 26 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2829 | 27 | # | ||
2830 | 28 | #--------------------------------------------------------------------- | ||
2831 | 29 | |||
2832 | 30 | script_name=${0##*/} | ||
2833 | 31 | user_job_dir="$HOME/.init" | ||
2834 | 32 | bug_url="https://bugs.launchpad.net/upstart/+filebug" | ||
2835 | 33 | test_dir= | ||
2836 | 34 | test_dir_suffix= | ||
2837 | 35 | user_to_create= | ||
2838 | 36 | uid= | ||
2839 | 37 | gid= | ||
2840 | 38 | opt= | ||
2841 | 39 | OPTARG= | ||
2842 | 40 | |||
2843 | 41 | # allow non-priv users to find 'initctl' | ||
2844 | 42 | export PATH=$PATH:/sbin | ||
2845 | 43 | |||
2846 | 44 | # for assertions | ||
2847 | 45 | die() | ||
2848 | 46 | { | ||
2849 | 47 | msg="$*" | ||
2850 | 48 | echo "ERROR: $msg" >&2 | ||
2851 | 49 | exit 1 | ||
2852 | 50 | } | ||
2853 | 51 | |||
2854 | 52 | TEST_FAILED() | ||
2855 | 53 | { | ||
2856 | 54 | args="$*" | ||
2857 | 55 | |||
2858 | 56 | [ -z "$args" ] && die "need args" | ||
2859 | 57 | |||
2860 | 58 | printf "BAD: %s\n" "$args" | ||
2861 | 59 | printf "\nPlease report a bug at $bug_url including the following details:\n" | ||
2862 | 60 | printf "\nUpstart:\n" | ||
2863 | 61 | /sbin/init --version|head -n1 | ||
2864 | 62 | /sbin/initctl --version|head -n1 | ||
2865 | 63 | echo | ||
2866 | 64 | printf "cmdline:\n" | ||
2867 | 65 | cat /proc/cmdline | ||
2868 | 66 | echo | ||
2869 | 67 | printf "Upstart Env:\n" | ||
2870 | 68 | set|grep UPSTART_ | ||
2871 | 69 | echo | ||
2872 | 70 | printf "lsb:\n" | ||
2873 | 71 | lsb_release -a | ||
2874 | 72 | printf "\nuname:\n" | ||
2875 | 73 | uname -a | ||
2876 | 74 | echo | ||
2877 | 75 | sync | ||
2878 | 76 | exit 1 | ||
2879 | 77 | } | ||
2880 | 78 | |||
2881 | 79 | TEST_GROUP() | ||
2882 | 80 | { | ||
2883 | 81 | name="$1" | ||
2884 | 82 | |||
2885 | 83 | [ -z "$name" ] && die "need name" | ||
2886 | 84 | |||
2887 | 85 | printf "Testing %s\n", "$name" | ||
2888 | 86 | } | ||
2889 | 87 | |||
2890 | 88 | TEST_FEATURE() | ||
2891 | 89 | { | ||
2892 | 90 | feature="$1" | ||
2893 | 91 | |||
2894 | 92 | [ -z "$feature" ] && die "need feature" | ||
2895 | 93 | |||
2896 | 94 | printf "...%s\n" "$feature" | ||
2897 | 95 | } | ||
2898 | 96 | |||
2899 | 97 | TEST_NE() | ||
2900 | 98 | { | ||
2901 | 99 | cmd="$1" | ||
2902 | 100 | value="$2" | ||
2903 | 101 | expected="$3" | ||
2904 | 102 | |||
2905 | 103 | # XXX: no checks on value or expected since they might be blank | ||
2906 | 104 | [ -z "$cmd" ] && die "need cmd" | ||
2907 | 105 | |||
2908 | 106 | [ "$value" = "$expected" ] && TEST_FAILED \ | ||
2909 | 107 | "wrong value for '$cmd', expected $expected got $value" | ||
2910 | 108 | } | ||
2911 | 109 | |||
2912 | 110 | TEST_EQ() | ||
2913 | 111 | { | ||
2914 | 112 | cmd="$1" | ||
2915 | 113 | value="$2" | ||
2916 | 114 | expected="$3" | ||
2917 | 115 | |||
2918 | 116 | # XXX: no checks on value or expected since they might be blank | ||
2919 | 117 | [ -z "$cmd" ] && die "need cmd" | ||
2920 | 118 | |||
2921 | 119 | [ "$value" != "$expected" ] && TEST_FAILED \ | ||
2922 | 120 | "wrong value for '$cmd', expected '$expected' got '$value'" | ||
2923 | 121 | } | ||
2924 | 122 | |||
2925 | 123 | setup() | ||
2926 | 124 | { | ||
2927 | 125 | uid=$(id -u) | ||
2928 | 126 | gid=$(id -g) | ||
2929 | 127 | |||
2930 | 128 | if [ "$uid" = 0 ] | ||
2931 | 129 | then | ||
2932 | 130 | [ -z "$user_to_create" ] && die "need '-u' option when running as root" | ||
2933 | 131 | |||
2934 | 132 | getent passwd "$user_to_create" && \ | ||
2935 | 133 | die "user '$user_to_create' already exists" | ||
2936 | 134 | |||
2937 | 135 | echo "Creating user '$user_to_create'" | ||
2938 | 136 | cmd="useradd -mU -c 'Upstart Test User' $user_to_create" | ||
2939 | 137 | eval "$cmd" | ||
2940 | 138 | TEST_EQ "$cmd" $? 0 | ||
2941 | 139 | |||
2942 | 140 | echo "Locking account for user '$user_to_create'" | ||
2943 | 141 | cmd="usermod -L $user_to_create" | ||
2944 | 142 | eval "$cmd" | ||
2945 | 143 | TEST_EQ "$cmd" $? 0 | ||
2946 | 144 | |||
2947 | 145 | # Run ourselves again as the new user | ||
2948 | 146 | su -c "$0 -a" "$user_to_create" | ||
2949 | 147 | test_run_rc=$? | ||
2950 | 148 | |||
2951 | 149 | if [ $test_run_rc -eq 0 ] | ||
2952 | 150 | then | ||
2953 | 151 | echo "Deleting user '$user_to_create'" | ||
2954 | 152 | cmd="userdel -r \"$user_to_create\"" | ||
2955 | 153 | eval "$cmd" | ||
2956 | 154 | TEST_EQ "$cmd" $? 0 | ||
2957 | 155 | fi | ||
2958 | 156 | |||
2959 | 157 | exit $test_run_rc | ||
2960 | 158 | fi | ||
2961 | 159 | |||
2962 | 160 | # setup | ||
2963 | 161 | if [ ! -d "$user_job_dir" ] | ||
2964 | 162 | then | ||
2965 | 163 | cmd="mkdir -p \"$user_job_dir\"" | ||
2966 | 164 | eval $cmd | ||
2967 | 165 | TEST_EQ "$cmd" $? 0 | ||
2968 | 166 | |||
2969 | 167 | cmd="chmod 755 \"$user_job_dir\"" | ||
2970 | 168 | eval "$cmd" | ||
2971 | 169 | TEST_EQ "$cmd" $? 0 | ||
2972 | 170 | fi | ||
2973 | 171 | |||
2974 | 172 | # create somewhere to store user jobs | ||
2975 | 173 | cmd="mktemp -d --tmpdir=\"$user_job_dir\"" | ||
2976 | 174 | test_dir=$(eval "$cmd") | ||
2977 | 175 | TEST_EQ "$cmd" $? 0 | ||
2978 | 176 | TEST_NE "$test_dir" "$test_dir" "" | ||
2979 | 177 | test_dir_suffix=${test_dir#${user_job_dir}/} | ||
2980 | 178 | |||
2981 | 179 | # ensure files in this directory are accessible since | ||
2982 | 180 | # mktemp sets directory perms to 0700 regardless of umask. | ||
2983 | 181 | cmd="chmod 755 \"$test_dir\"" | ||
2984 | 182 | eval "$cmd" | ||
2985 | 183 | TEST_EQ "$cmd" $? 0 | ||
2986 | 184 | |||
2987 | 185 | TEST_NE "HOME" "$HOME" "" | ||
2988 | 186 | } | ||
2989 | 187 | |||
2990 | 188 | cleanup() | ||
2991 | 189 | { | ||
2992 | 190 | if [ -d "$test_dir" ] | ||
2993 | 191 | then | ||
2994 | 192 | echo "Removing test directory '$test_dir'" | ||
2995 | 193 | cmd="rmdir \"$test_dir\"" | ||
2996 | 194 | eval "$cmd" | ||
2997 | 195 | TEST_EQ "$cmd" $? 0 | ||
2998 | 196 | fi | ||
2999 | 197 | } | ||
3000 | 198 | |||
3001 | 199 | ensure_job_known() | ||
3002 | 200 | { | ||
3003 | 201 | job="$1" | ||
3004 | 202 | job_name="$2" | ||
3005 | 203 | |||
3006 | 204 | [ -z "$job" ] && die "no job" | ||
3007 | 205 | [ -z "$job_name" ] && die "no job name" | ||
3008 | 206 | |||
3009 | 207 | TEST_FEATURE "ensure 'initctl' recognises job" | ||
3010 | 208 | initctl list|grep -q "^$job " || \ | ||
3011 | 209 | TEST_FAILED "job $job_name not known to initctl" | ||
3012 | 210 | |||
3013 | 211 | TEST_FEATURE "ensure 'status' recognises job" | ||
3014 | 212 | cmd="status ${job}" | ||
3015 | 213 | eval "$cmd" | ||
3016 | 214 | rc=$? | ||
3017 | 215 | TEST_EQ "$cmd" $rc 0 | ||
3018 | 216 | } | ||
3019 | 217 | |||
3020 | 218 | run_user_job_tests() | ||
3021 | 219 | { | ||
3022 | 220 | job_name="$1" | ||
3023 | 221 | job_file="$2" | ||
3024 | 222 | task="$3" | ||
3025 | 223 | env="$4" | ||
3026 | 224 | |||
3027 | 225 | # XXX: env can be empty | ||
3028 | 226 | [ -z "$job_name" ] && die "no job name" | ||
3029 | 227 | [ -z "$job_file" ] && die "no job file" | ||
3030 | 228 | [ -z "$task" ] && die "no task value" | ||
3031 | 229 | |||
3032 | 230 | job="${test_dir_suffix}/${job_name}" | ||
3033 | 231 | |||
3034 | 232 | [ -f "$job_file" ] || TEST_FAILED "job file '$job_file' does not exist" | ||
3035 | 233 | |||
3036 | 234 | ensure_job_known "$job" "$job_name" | ||
3037 | 235 | |||
3038 | 236 | TEST_FEATURE "ensure job can be started" | ||
3039 | 237 | cmd="start ${job} ${env}" | ||
3040 | 238 | output=$(eval "$cmd") | ||
3041 | 239 | rc=$? | ||
3042 | 240 | TEST_EQ "$cmd" $rc 0 | ||
3043 | 241 | |||
3044 | 242 | if [ "$task" = no ] | ||
3045 | 243 | then | ||
3046 | 244 | TEST_FEATURE "ensure 'start' shows job pid" | ||
3047 | 245 | pid=$(echo "$output"|awk '{print $4}') | ||
3048 | 246 | TEST_NE "pid" "$pid" "" | ||
3049 | 247 | |||
3050 | 248 | TEST_FEATURE "ensure 'initctl' shows job is running with pid" | ||
3051 | 249 | initctl list|grep -q "^$job start/running, process $pid" || \ | ||
3052 | 250 | TEST_FAILED "job $job_name did not start" | ||
3053 | 251 | |||
3054 | 252 | TEST_FEATURE "ensure 'status' shows job is running with pid" | ||
3055 | 253 | cmd="status ${job}" | ||
3056 | 254 | output=$(eval "$cmd") | ||
3057 | 255 | echo "$output"|while read job_tmp state ignored status_pid | ||
3058 | 256 | do | ||
3059 | 257 | state=$(echo $state|tr -d ',') | ||
3060 | 258 | TEST_EQ "job name" "$job_tmp" "$job" | ||
3061 | 259 | TEST_EQ "job state" "$state" "start/running" | ||
3062 | 260 | TEST_EQ "job pid" "$status_pid" "$pid" | ||
3063 | 261 | done | ||
3064 | 262 | |||
3065 | 263 | TEST_FEATURE "ensure job pid is running with correct uids" | ||
3066 | 264 | pid_uids=$(ps --no-headers -p $pid -o euid,ruid) | ||
3067 | 265 | for pid_uid in $pid_uids | ||
3068 | 266 | do | ||
3069 | 267 | TEST_EQ "pid uid" "$pid_uid" "$uid" | ||
3070 | 268 | done | ||
3071 | 269 | |||
3072 | 270 | TEST_FEATURE "ensure job pid is running with correct gids" | ||
3073 | 271 | pid_gids=$(ps --no-headers -p $pid -o egid,rgid) | ||
3074 | 272 | for pid_gid in $pid_gids | ||
3075 | 273 | do | ||
3076 | 274 | TEST_EQ "pid gid" "$pid_gid" "$gid" | ||
3077 | 275 | done | ||
3078 | 276 | |||
3079 | 277 | TEST_FEATURE "ensure process is running in correct directory" | ||
3080 | 278 | cwd=$(readlink /proc/$pid/cwd) | ||
3081 | 279 | TEST_EQ "cwd" "$cwd" "$HOME" | ||
3082 | 280 | |||
3083 | 281 | TEST_FEATURE "ensure job can be stopped" | ||
3084 | 282 | cmd="stop ${job}" | ||
3085 | 283 | output=$(eval "$cmd") | ||
3086 | 284 | rc=$? | ||
3087 | 285 | TEST_EQ "$cmd" $rc 0 | ||
3088 | 286 | |||
3089 | 287 | TEST_FEATURE "ensure job pid no longer exists" | ||
3090 | 288 | pid_ids=$(ps --no-headers -p $pid -o euid,ruid,egid,rgid) | ||
3091 | 289 | TEST_EQ "pid uids+gids" "$pid_ids" "" | ||
3092 | 290 | fi | ||
3093 | 291 | |||
3094 | 292 | remove_job_file "$job_file" | ||
3095 | 293 | ensure_job_gone "$job" "$job_name" "$env" | ||
3096 | 294 | } | ||
3097 | 295 | |||
3098 | 296 | remove_job_file() | ||
3099 | 297 | { | ||
3100 | 298 | job_file="$1" | ||
3101 | 299 | |||
3102 | 300 | [ -z "$job_file" ] && die "no job file" | ||
3103 | 301 | [ ! -f "$job_file" ] && TEST_FAILED "job file '$job_file' does not exist" | ||
3104 | 302 | |||
3105 | 303 | cmd="rm $job_file" | ||
3106 | 304 | eval "$cmd" | ||
3107 | 305 | TEST_EQ "$cmd" $? 0 | ||
3108 | 306 | } | ||
3109 | 307 | |||
3110 | 308 | ensure_job_gone() | ||
3111 | 309 | { | ||
3112 | 310 | job="$1" | ||
3113 | 311 | job_name="$2" | ||
3114 | 312 | env="$3" | ||
3115 | 313 | |||
3116 | 314 | # XXX: no check on env since it can be empty | ||
3117 | 315 | [ -z "$job" ] && die "no job" | ||
3118 | 316 | [ -z "$job_name" ] && die "no job name" | ||
3119 | 317 | |||
3120 | 318 | TEST_FEATURE "ensure 'initctl' no longer recognises job" | ||
3121 | 319 | initctl list|grep -q "^$job " && \ | ||
3122 | 320 | TEST_FAILED "deleted job $job_name still known to initctl" | ||
3123 | 321 | |||
3124 | 322 | TEST_FEATURE "ensure 'status' no longer recognises job" | ||
3125 | 323 | cmd="status ${job}" | ||
3126 | 324 | eval "$cmd" | ||
3127 | 325 | rc=$? | ||
3128 | 326 | TEST_NE "$cmd" $rc 0 | ||
3129 | 327 | } | ||
3130 | 328 | |||
3131 | 329 | test_user_job() | ||
3132 | 330 | { | ||
3133 | 331 | test_group="$1" | ||
3134 | 332 | job_name="$2" | ||
3135 | 333 | script="$3" | ||
3136 | 334 | task="$4" | ||
3137 | 335 | env="$5" | ||
3138 | 336 | |||
3139 | 337 | # XXX: no test on script or env since they might be empty | ||
3140 | 338 | [ -z "$test_group" ] && die "no test group" | ||
3141 | 339 | [ -z "$job_name" ] && die "no job name" | ||
3142 | 340 | [ -z "$task" ] && die "no task" | ||
3143 | 341 | |||
3144 | 342 | TEST_GROUP "$test_group" | ||
3145 | 343 | |||
3146 | 344 | job_file="${test_dir}/${job_name}.conf" | ||
3147 | 345 | |||
3148 | 346 | echo "$script" > $job_file | ||
3149 | 347 | |||
3150 | 348 | run_user_job_tests "$job_name" "$job_file" "$task" "$env" | ||
3151 | 349 | } | ||
3152 | 350 | |||
3153 | 351 | test_user_job_binary() | ||
3154 | 352 | { | ||
3155 | 353 | group="user job running a binary" | ||
3156 | 354 | job_name="binary_test" | ||
3157 | 355 | script="exec sleep 999" | ||
3158 | 356 | test_user_job "$group" "$job_name" "$script" no "" | ||
3159 | 357 | } | ||
3160 | 358 | |||
3161 | 359 | test_user_job_binary_task() | ||
3162 | 360 | { | ||
3163 | 361 | group="user job running a binary task" | ||
3164 | 362 | job_name="binary_task_test" | ||
3165 | 363 | OUTFILE=$(mktemp) | ||
3166 | 364 | |||
3167 | 365 | script="\ | ||
3168 | 366 | task | ||
3169 | 367 | exec true > $OUTFILE" | ||
3170 | 368 | |||
3171 | 369 | test_user_job "$group" "$job_name" "$script" yes "OUTFILE=$OUTFILE" | ||
3172 | 370 | rm -f $OUTFILE | ||
3173 | 371 | } | ||
3174 | 372 | |||
3175 | 373 | test_user_job_single_line_script() | ||
3176 | 374 | { | ||
3177 | 375 | group="user job running a single-line script" | ||
3178 | 376 | job_name="single_line_script_test" | ||
3179 | 377 | script="\ | ||
3180 | 378 | script | ||
3181 | 379 | sleep 999 | ||
3182 | 380 | end script" | ||
3183 | 381 | test_user_job "$group" "$job_name" "$script" no "" | ||
3184 | 382 | } | ||
3185 | 383 | |||
3186 | 384 | test_user_job_single_line_script_task() | ||
3187 | 385 | { | ||
3188 | 386 | group="user job running a single-line script task" | ||
3189 | 387 | job_name="single_line_script_task_test" | ||
3190 | 388 | OUTFILE=$(mktemp) | ||
3191 | 389 | |||
3192 | 390 | script="\ | ||
3193 | 391 | task | ||
3194 | 392 | script | ||
3195 | 393 | exec true > $OUTFILE | ||
3196 | 394 | end script" | ||
3197 | 395 | test_user_job "$group" "$job_name" "$script" yes "OUTFILE=$OUTFILE" | ||
3198 | 396 | rm -f $OUTFILE | ||
3199 | 397 | } | ||
3200 | 398 | |||
3201 | 399 | test_user_job_multi_line_script() | ||
3202 | 400 | { | ||
3203 | 401 | group="user job running a multi-line script" | ||
3204 | 402 | job_name="multi_line_script_test" | ||
3205 | 403 | script="\ | ||
3206 | 404 | script | ||
3207 | 405 | |||
3208 | 406 | true | ||
3209 | 407 | true;true | ||
3210 | 408 | sleep 999 | ||
3211 | 409 | |||
3212 | 410 | end script" | ||
3213 | 411 | test_user_job "$group" "$job_name" "$script" no "" | ||
3214 | 412 | } | ||
3215 | 413 | |||
3216 | 414 | test_user_job_multi_line_script_task() | ||
3217 | 415 | { | ||
3218 | 416 | group="user job running a multi-line script task" | ||
3219 | 417 | job_name="multi_line_script_task_test" | ||
3220 | 418 | OUTFILE=$(mktemp) | ||
3221 | 419 | |||
3222 | 420 | script="\ | ||
3223 | 421 | task | ||
3224 | 422 | script | ||
3225 | 423 | |||
3226 | 424 | true | ||
3227 | 425 | true | ||
3228 | 426 | true | ||
3229 | 427 | |||
3230 | 428 | end script" | ||
3231 | 429 | test_user_job "$group" "$job_name" "$script" yes "OUTFILE=$OUTFILE" | ||
3232 | 430 | rm -f $OUTFILE | ||
3233 | 431 | } | ||
3234 | 432 | |||
3235 | 433 | test_user_emit_events() | ||
3236 | 434 | { | ||
3237 | 435 | job_name="start_on_foo" | ||
3238 | 436 | |||
3239 | 437 | TEST_GROUP "user emitting an event" | ||
3240 | 438 | initctl emit foo || TEST_FAILED "failed to emit event as user" | ||
3241 | 439 | |||
3242 | 440 | TEST_GROUP "user emitting an event to start a job" | ||
3243 | 441 | script="\ | ||
3244 | 442 | start on foo BAR=2 | ||
3245 | 443 | stop on baz cow=moo or hello | ||
3246 | 444 | exec sleep 999" | ||
3247 | 445 | |||
3248 | 446 | job_file="${test_dir}/${job_name}.conf" | ||
3249 | 447 | job="${test_dir_suffix}/${job_name}" | ||
3250 | 448 | |||
3251 | 449 | echo "$script" > $job_file | ||
3252 | 450 | |||
3253 | 451 | ensure_job_known "$job" "$job_name" | ||
3254 | 452 | |||
3255 | 453 | initctl list|grep -q "^$job stop/waiting" || \ | ||
3256 | 454 | TEST_FAILED "job $job_name not stopped" | ||
3257 | 455 | |||
3258 | 456 | TEST_FEATURE "ensure job can be started with event" | ||
3259 | 457 | initctl emit foo BAR=2 || \ | ||
3260 | 458 | TEST_FAILED "failed to emit event for user job" | ||
3261 | 459 | |||
3262 | 460 | initctl status "$job"|grep -q "^$job start/running" || \ | ||
3263 | 461 | TEST_FAILED "job $job_name failed to start" | ||
3264 | 462 | |||
3265 | 463 | TEST_FEATURE "ensure job can be stopped with event" | ||
3266 | 464 | initctl emit baz cow=moo || \ | ||
3267 | 465 | TEST_FAILED "failed to emit event for user job" | ||
3268 | 466 | |||
3269 | 467 | initctl list|grep -q "^$job stop/waiting" || \ | ||
3270 | 468 | TEST_FAILED "job $job_name not stopped" | ||
3271 | 469 | |||
3272 | 470 | rm -f "$job_file" | ||
3273 | 471 | } | ||
3274 | 472 | |||
3275 | 473 | test_user_jobs() | ||
3276 | 474 | { | ||
3277 | 475 | test_user_job_binary | ||
3278 | 476 | test_user_job_single_line_script | ||
3279 | 477 | test_user_job_multi_line_script | ||
3280 | 478 | |||
3281 | 479 | test_user_job_binary_task | ||
3282 | 480 | test_user_job_single_line_script_task | ||
3283 | 481 | test_user_job_multi_line_script_task | ||
3284 | 482 | |||
3285 | 483 | test_user_emit_events | ||
3286 | 484 | } | ||
3287 | 485 | |||
3288 | 486 | tests() | ||
3289 | 487 | { | ||
3290 | 488 | echo | ||
3291 | 489 | echo -n "Running user session tests as user '`whoami`'" | ||
3292 | 490 | echo " (uid $uid, gid $gid) in directory '$test_dir'" | ||
3293 | 491 | echo | ||
3294 | 492 | |||
3295 | 493 | test_user_jobs | ||
3296 | 494 | |||
3297 | 495 | echo | ||
3298 | 496 | echo "All tests completed successfully" | ||
3299 | 497 | echo | ||
3300 | 498 | } | ||
3301 | 499 | |||
3302 | 500 | usage() | ||
3303 | 501 | { | ||
3304 | 502 | cat <<EOT | ||
3305 | 503 | USAGE: $script_name [options] | ||
3306 | 504 | |||
3307 | 505 | OPTIONS: | ||
3308 | 506 | |||
3309 | 507 | -a : Actually run this script. | ||
3310 | 508 | -h : Show this help. | ||
3311 | 509 | -u <user> : Specify name of test user to create. | ||
3312 | 510 | |||
3313 | 511 | DESCRIPTION: Run simple set of Upstart user session tests. | ||
3314 | 512 | |||
3315 | 513 | WARNING: Note that this script is unavoidably invasive, so read what | ||
3316 | 514 | WARNING: follows before running! | ||
3317 | 515 | |||
3318 | 516 | If run as a non-root user, this script will create a uniquely-named | ||
3319 | 517 | subdirectory below "\$HOME/.init/" to run its tests in. On successful | ||
3320 | 518 | completion of these tests, the unique subdirectory and its contents will | ||
3321 | 519 | be removed. | ||
3322 | 520 | |||
3323 | 521 | If however, this script is invoked as the root user, the script will | ||
3324 | 522 | refuse to run until given the name of a test user to create via the "-u" | ||
3325 | 523 | option. If the user specified to this option already exists, this script | ||
3326 | 524 | will exit with an error. If the user does not already exist, it will be | ||
3327 | 525 | created, the script then run *as that user* and assuming successful | ||
3328 | 526 | completion of the tests, the test user and their home directory will | ||
3329 | 527 | then be deleted. | ||
3330 | 528 | |||
3331 | 529 | EOT | ||
3332 | 530 | } | ||
3333 | 531 | |||
3334 | 532 | #--------------------------------------------------------------------- | ||
3335 | 533 | # main | ||
3336 | 534 | #--------------------------------------------------------------------- | ||
3337 | 535 | |||
3338 | 536 | while getopts "hu:" opt | ||
3339 | 537 | do | ||
3340 | 538 | case "$opt" in | ||
3341 | 539 | h) | ||
3342 | 540 | usage | ||
3343 | 541 | exit 0 | ||
3344 | 542 | ;; | ||
3345 | 543 | |||
3346 | 544 | u) | ||
3347 | 545 | user_to_create="$OPTARG" | ||
3348 | 546 | ;; | ||
3349 | 547 | esac | ||
3350 | 548 | done | ||
3351 | 549 | |||
3352 | 550 | setup | ||
3353 | 551 | tests | ||
3354 | 552 | cleanup | ||
3355 | 553 | exit 0 |