~vorlon/ubuntu/raring/upstart/lp.1199778

« back to all changes in this revision

Viewing changes to test/test_util_common.h

  • Committer: Steve Langasek
  • Date: 2013-11-07 03:06:51 UTC
  • Revision ID: steve.langasek@canonical.com-20131107030651-f1jzeyi7ifvvw1h8
Attempt to cherry-pick fixes for bug #1199778 to raring; something is still
missing though, the test suite segfaults on one of the json loads.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef TEST_UTIL_COMMON_H
 
2
#define TEST_UTIL_COMMON_H
 
3
 
 
4
#include <string.h>
 
5
#include <sys/types.h>
 
6
#include <sys/wait.h>
 
7
 
 
8
#include <nih-dbus/test_dbus.h>
 
9
 
 
10
#define BUFFER_SIZE 1024
 
11
 
 
12
/**
 
13
 * TEST_QUIESCE_WAIT_PHASE:
 
14
 *
 
15
 * Maximum time we expect upstart to wait in the QUIESCE_PHASE_WAIT
 
16
 * phase.
 
17
 **/
 
18
#define TEST_EXIT_TIME 5
 
19
 
 
20
/**
 
21
 * TEST_QUIESCE_KILL_PHASE:
 
22
 *
 
23
 * Maximum time we expect upstart to wait in the QUIESCE_PHASE_KILL
 
24
 * phase.
 
25
 **/
 
26
#define TEST_QUIESCE_KILL_PHASE 5
 
27
 
 
28
#define TEST_QUIESCE_TOTAL_WAIT_TIME (TEST_EXIT_TIME + TEST_QUIESCE_KILL_PHASE)
 
29
 
 
30
/* A 'reasonable' path, but which also contains a marker at the end so
 
31
 * we know when we're looking at a PATH these tests have set.
 
32
 */
 
33
#define TEST_INITCTL_DEFAULT_PATH "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/wibble"
 
34
 
 
35
/* Default value for TERM if not already set */
 
36
#define TEST_INITCTL_DEFAULT_TERM "linux"
 
37
 
 
38
 
 
39
/* TEST_ENSURE_CLEAN_ENV:
 
40
 *
 
41
 * Ensure the environment is as pristine as possible (to avoid follow-on
 
42
 * errors caused by not freeing objects in a previous test, say)
 
43
 */
 
44
#define TEST_ENSURE_CLEAN_ENV()                                      \
 
45
{                                                                    \
 
46
        setvbuf(stdout, NULL, _IONBF, 0);                            \
 
47
                                                                     \
 
48
        if (job_classes) {                                           \
 
49
                TEST_HASH_EMPTY (job_classes);                       \
 
50
        }                                                            \
 
51
                                                                     \
 
52
        if (conf_sources) {                                          \
 
53
                TEST_LIST_EMPTY (conf_sources);                      \
 
54
        }                                                            \
 
55
                                                                     \
 
56
        if (nih_io_watches) {                                        \
 
57
                TEST_LIST_EMPTY (nih_io_watches);                    \
 
58
        }                                                            \
 
59
                                                                     \
 
60
        if (nih_timers) {                                            \
 
61
                TEST_LIST_EMPTY (nih_timers);                        \
 
62
        }                                                            \
 
63
                                                                     \
 
64
        if (events) {                                                \
 
65
                TEST_LIST_EMPTY (events);                            \
 
66
        }                                                            \
 
67
}
 
68
 
 
69
/**
 
70
 * _TEST_WATCH_UPDATE:
 
71
 * @force: if TRUE, force an update,
 
72
 * @timeout: struct timeval pointer, or NULL if no timeout required.
 
73
 *
 
74
 * Request NIH look for a file event relating to any NihIo objects,
 
75
 * with an optional timeout. Behaviour can be forced via @force.
 
76
 **/
 
77
#define _TEST_WATCH_UPDATE(force, timeout)                           \
 
78
{                                                                    \
 
79
        int         nfds = 0;                                        \
 
80
        int         ret = 0;                                         \
 
81
        fd_set      readfds, writefds, exceptfds;                    \
 
82
                                                                     \
 
83
        FD_ZERO (&readfds);                                          \
 
84
        FD_ZERO (&writefds);                                         \
 
85
        FD_ZERO (&exceptfds);                                        \
 
86
                                                                     \
 
87
        nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);  \
 
88
        if (! force) {                                               \
 
89
          ret = select (nfds, &readfds, &writefds,                   \
 
90
                        &exceptfds, timeout);                        \
 
91
        }                                                            \
 
92
        if (force || ret > 0)                                        \
 
93
                nih_io_handle_fds (&readfds, &writefds, &exceptfds); \
 
94
}
 
95
 
 
96
/**
 
97
 * TEST_WATCH_UPDATE:
 
98
 *
 
99
 * Request NIH look for a file event relating to any NihIo objects,
 
100
 * */
 
101
#define TEST_WATCH_UPDATE()                                          \
 
102
        _TEST_WATCH_UPDATE (0, NULL)
 
103
 
 
104
/**
 
105
 * TEST_WATCH_UPDATE_TIMEOUT:
 
106
 * @timeout: struct timeval pointer.
 
107
 *
 
108
 * Request NIH look for a file event relating to any NihIo objects
 
109
 * within time period @timeout.
 
110
 **/
 
111
#define TEST_WATCH_UPDATE_TIMEOUT(timeout)                           \
 
112
        _TEST_WATCH_UPDATE (0, timeout)
 
113
 
 
114
/**
 
115
 * TEST_WATCH_UPDATE_TIMEOUT_SECS:
 
116
 * @secs: seconds to wait before timeout.
 
117
 *
 
118
 * Request NIH look for a file event relating to any NihIo objects
 
119
 * within @secs timeout.
 
120
 **/
 
121
#define TEST_WATCH_UPDATE_TIMEOUT_SECS(secs)                         \
 
122
{                                                                    \
 
123
        struct timeval _t;                                           \
 
124
        _t.tv_sec  = secs;                                           \
 
125
        _t.tv_usec = 0;                                              \
 
126
        _TEST_WATCH_UPDATE (0, &_t);                                 \
 
127
}
 
128
 
 
129
/**
 
130
 * TEST_FORCE_WATCH_UPDATE:
 
131
 *
 
132
 * Force NIH to look for a file event relating to any NihIo objects.
 
133
 **/
 
134
#define TEST_FORCE_WATCH_UPDATE()                                    \
 
135
        _TEST_WATCH_UPDATE (1, NULL)
 
136
 
 
137
/**
 
138
 * TEST_FORCE_WATCH_UPDATE_TIMEOUT:
 
139
 * @timeout: struct timeval pointer.
 
140
 *
 
141
 * Force NIH to look for a file event relating to any NihIo objects
 
142
 * within time period @timeout.
 
143
 **/
 
144
#define TEST_FORCE_WATCH_UPDATE_TIMEOUT(timeout)                     \
 
145
        _TEST_WATCH_UPDATE (1, timeout)
 
146
 
 
147
/**
 
148
 * TEST_FORCE_WATCH_UPDATE_TIMEOUT_SECS:
 
149
 * @timeout: struct timeval pointer.
 
150
 *
 
151
 * Force NIH to look for a file event relating to any NihIo objects
 
152
 * within time period @timeout.
 
153
 **/
 
154
#define TEST_FORCE_WATCH_UPDATE_TIMEOUT_SECS(secs)                   \
 
155
{                                                                    \
 
156
        struct timeval _t;                                           \
 
157
        _t.tv_sec  = secs;                                           \
 
158
        _t.tv_usec = 0;                                              \
 
159
        _TEST_WATCH_UPDATE (1, &_t);                                 \
 
160
}
 
161
 
 
162
/**
 
163
 * ENSURE_DIRECTORY_EMPTY:
 
164
 * @path: Full path to a directory.
 
165
 *
 
166
 * Ensure specified directory is empty.
 
167
 **/
 
168
#define ENSURE_DIRECTORY_EMPTY(path)                                 \
 
169
{                                                                    \
 
170
        DIR            *dp = NULL;                                   \
 
171
        struct dirent  *file = NULL;                                 \
 
172
        int             count = 0;                                   \
 
173
                                                                     \
 
174
        dp = opendir (path);                                         \
 
175
        TEST_NE_P (dp, NULL);                                        \
 
176
                                                                     \
 
177
        while((file = readdir (dp))) {                               \
 
178
                if (!strcmp (".", file->d_name) ||                   \
 
179
                                !strcmp ("..", file->d_name))        \
 
180
                        continue;                                    \
 
181
                count++;                                             \
 
182
        }                                                            \
 
183
                                                                     \
 
184
        closedir (dp);                                               \
 
185
                                                                     \
 
186
        TEST_EQ (count, 0);                                          \
 
187
}
 
188
 
 
189
/**
 
190
 * obj_string_check:
 
191
 *
 
192
 * @a: first object,
 
193
 * @b: second object,
 
194
 * @name: name of string element.
 
195
 *
 
196
 * Compare string element @name in objects @a and @b.
 
197
 *
 
198
 * Returns: 0 if strings are identical
 
199
 * (or both NULL), else 1.
 
200
 **/
 
201
#define obj_string_check(a, b, name) \
 
202
        string_check ((a)->name, (b)->name)
 
203
 
 
204
/**
 
205
 * obj_num_check:
 
206
 *
 
207
 * @a: first object,
 
208
 * @b: second object.
 
209
 * @name: name of numeric element.
 
210
 *
 
211
 * Compare numeric element @name in objects @a and @b.
 
212
 *
 
213
 * Returns: 0 if @a and @b are identical, else 1.
 
214
 **/
 
215
#define obj_num_check(a, b, name) \
 
216
        (a->name != b->name)
 
217
 
 
218
/**
 
219
 * TEST_CMP_INT_ARRAYS:
 
220
 * @a: first array,
 
221
 * @b: second array,
 
222
 * @sizea: size of @a,
 
223
 * @sizeb: size of @b.
 
224
 *
 
225
 * Compare integer arrays @a and @b for equivalence.
 
226
 *
 
227
 * Returns: 0 if arrays are identical, else -1.
 
228
 **/
 
229
#define TEST_CMP_INT_ARRAYS(a, b, sizea, sizeb) \
 
230
({int ret = 0; \
 
231
 size_t __i; \
 
232
 if (sizea == sizeb) { \
 
233
         for (__i = 0; \
 
234
                 __i < sizea; \
 
235
                 __i++) { \
 
236
                if ((a)[__i] != (b)[__i]) { \
 
237
                        ret = -1; \
 
238
                        break; \
 
239
                } \
 
240
        } \
 
241
 } else \
 
242
        ret = -1; \
 
243
 ret;})
 
244
 
 
245
/**
 
246
 * TEST_CMP_STR_ARRAYS:
 
247
 * @a: first string array,
 
248
 * @b: second string array,
 
249
 * @sizea: length of @a, 
 
250
 * @sizeb: length of @b.
 
251
 *
 
252
 * Compare string arrays @a and @b for equivalence.
 
253
 *
 
254
 * Returns: 0 if arrays are identical, else -1.
 
255
 **/
 
256
#define TEST_CMP_STR_ARRAYS(a, b, sizea, sizeb) \
 
257
({ int ret = 0; \
 
258
 if (sizea == sizeb) { \
 
259
         for (size_t __i = 0; \
 
260
                 __i < sizea; \
 
261
                 __i++) { \
 
262
                if (strcmp (a[__i], b[__i])) { \
 
263
                        ret = -1; \
 
264
                        break; \
 
265
                } \
 
266
        } \
 
267
 } else \
 
268
        ret = -1; \
 
269
 ret;})
 
270
 
 
271
/**
 
272
 * TEST_TWO_LISTS_FOREACH:
 
273
 * @list1: entry in the first list to iterate,
 
274
 * @list2: entry in the second list to iterate,
 
275
 * @iter1: name of iterator variable for @list1,
 
276
 * @iter2: name of iterator variable for @list2.
 
277
 *
 
278
 * Dual version of NIH_LIST_FOREACH() which iterates 
 
279
 * two lists in tandem.
 
280
 **/
 
281
#define TEST_TWO_LISTS_FOREACH(list1, list2, iter1, iter2) \
 
282
        for (NihList *iter1 = (list1)->next, \
 
283
                     *iter2 = (list2)->next; \
 
284
                iter1 != (list1) && iter2 != (list2); \
 
285
                iter1 = iter1->next, \
 
286
                iter2 = iter2->next)
 
287
 
 
288
/**
 
289
 * TEST_TWO_HASHES_FOREACH:
 
290
 * @hash1: entry in the first hash to iterate,
 
291
 * @hash2: entry in the second hash to iterate,
 
292
 * @iter1: name of iterator variable for @hash1,
 
293
 * @iter2: name of iterator variable for @hash2.
 
294
 *
 
295
 * Dual version of NIH_HASH_FOREACH() which iterates
 
296
 * two hashes in tandem.
 
297
 **/
 
298
#define TEST_TWO_HASHES_FOREACH(hash1, hash2, iter1, iter2) \
 
299
        for (size_t _##iter##_i = 0; _##iter##_i < (hash1)->size; \
 
300
             _##iter##_i++) \
 
301
                TEST_TWO_LISTS_FOREACH (&(hash1)->bins[_##iter##_i], \
 
302
                                        &(hash2)->bins[_##iter##_i], \
 
303
                                iter1, iter2)
 
304
 
 
305
/**
 
306
 * TEST_TWO_TREES_FOREACH:
 
307
 * @tree1: root of the first tree to iterate,
 
308
 * @tree2: root of the second tree to iterate,
 
309
 * @iter1: name of iterator variable for @tree1,
 
310
 * @iter2: name of iterator variable for @tree2.
 
311
 *
 
312
 * Dual version of NIH_TREE_FOREACH() which walks
 
313
 * two trees in tandem.
 
314
 **/
 
315
#define TEST_TWO_TREES_FOREACH(tree1, tree2, iter1, iter2) \
 
316
        for (NihTree *iter1 = nih_tree_next (tree1, NULL), \
 
317
                        *iter2 = nih_tree_next (tree2, NULL); \
 
318
                        iter1 != NULL && iter2 != NULL; \
 
319
                        iter1 = nih_tree_next (tree1, iter1), \
 
320
                        iter2 = nih_tree_next (tree2, iter2))
 
321
 
 
322
 
 
323
/**
 
324
 * TEST_ARRAY_SIZE:
 
325
 * @array: array.
 
326
 * 
 
327
 * Determine size of specified array.
 
328
 *
 
329
 * Returns: array size.
 
330
 **/
 
331
#define TEST_ARRAY_SIZE(array) \
 
332
        (sizeof (array) / sizeof (array[0]))
 
333
 
 
334
/**
 
335
 * START_UPSTART:
 
336
 *
 
337
 * @pid: pid_t that will contain pid of running instance on success,
 
338
 * @user_mode: TRUE for Session Init (or FALSE to use D-Bus
 
339
 * session bus).
 
340
 *
 
341
 * Start an instance of Upstart and return PID in @pid.
 
342
 **/
 
343
#define START_UPSTART(pid, user_mode)                                \
 
344
        start_upstart_common (&(pid), user_mode, NULL, NULL, NULL)
 
345
 
 
346
/**
 
347
 * KILL_UPSTART:
 
348
 *
 
349
 * @pid: pid of upstart to kill,
 
350
 * @signo: signal number to send to @pid,
 
351
 * @wait: TRUE to wait for @pid to die.
 
352
 *
 
353
 * Send specified signal to upstart process @pid.
 
354
 **/
 
355
#define KILL_UPSTART(pid, signo, wait)                               \
 
356
{                                                                    \
 
357
        int status;                                                  \
 
358
        assert (pid);                                                \
 
359
        assert (signo);                                              \
 
360
                                                                     \
 
361
        assert0 (kill (pid, signo));                                 \
 
362
        if (wait) {                                                  \
 
363
                TEST_EQ (waitpid (pid, &status, 0), pid);            \
 
364
                TEST_TRUE (WIFSIGNALED (status));                    \
 
365
                TEST_TRUE (WTERMSIG (status) == signo);              \
 
366
        }                                                            \
 
367
        /* reset since a subsequent start could specify a different  \
 
368
         * user_mode value.                                          \
 
369
         */                                                          \
 
370
        test_user_mode = FALSE;                                      \
 
371
}
 
372
 
 
373
/**
 
374
 * STOP_UPSTART:
 
375
 *
 
376
 * @pid: pid of upstart to kill.
 
377
 *
 
378
 * Stop upstart process @pid.
 
379
 **/
 
380
#define STOP_UPSTART(pid)                                            \
 
381
        KILL_UPSTART (pid, SIGKILL, TRUE)
 
382
 
 
383
/**
 
384
 * REEXEC_UPSTART:
 
385
 *
 
386
 * @pid: pid of upstart,
 
387
 * @user: TRUE if @pid refers to a Session Init, else FALSE.
 
388
 *
 
389
 * Force upstart to perform a re-exec.
 
390
 **/
 
391
#define REEXEC_UPSTART(pid, user)                                    \
 
392
        KILL_UPSTART (pid, SIGTERM, FALSE);                          \
 
393
        wait_for_upstart (user ? pid : FALSE)
 
394
 
 
395
/**
 
396
 * RUN_COMMAND:
 
397
 *
 
398
 * @parent: pointer to parent object,
 
399
 * @cmd: string representing command to run,
 
400
 * @result: "char ***" pointer which will contain an array of string
 
401
 * values corresponding to lines of standard output generated by @cmd,
 
402
 * @len: size_t pointer which will be set to length of @result.
 
403
 *
 
404
 * Run a command and return its standard output. It is the callers
 
405
 * responsibility to free @result. Errors from running @cmd are fatal.
 
406
 *
 
407
 * Note: trailing '\n' characters are removed in returned command
 
408
 * output.
 
409
 **/
 
410
#define RUN_COMMAND(parent, cmd, result, len)                        \
 
411
{                                                                    \
 
412
        FILE    *f;                                                  \
 
413
        char     buffer[BUFFER_SIZE];                                \
 
414
        char   **ret;                                                \
 
415
                                                                     \
 
416
        assert (cmd[0]);                                             \
 
417
                                                                     \
 
418
        *(result) = nih_str_array_new (parent);                      \
 
419
        TEST_NE_P (*result, NULL);                                   \
 
420
        *(len) = 0;                                                  \
 
421
                                                                     \
 
422
        f = popen (cmd, "r");                                        \
 
423
        TEST_NE_P (f, NULL);                                         \
 
424
                                                                     \
 
425
        while (fgets (buffer, BUFFER_SIZE, f)) {                     \
 
426
                size_t l = strlen (buffer)-1;                        \
 
427
                                                                     \
 
428
                if ( buffer[l] == '\n')                              \
 
429
                        buffer[l] = '\0';                            \
 
430
                ret = nih_str_array_add (result, parent, len,        \
 
431
                        buffer);                                     \
 
432
                TEST_NE_P (ret, NULL);                               \
 
433
        }                                                            \
 
434
                                                                     \
 
435
        TEST_NE (pclose (f), -1);                                    \
 
436
}
 
437
 
 
438
/**
 
439
 * CREATE_FILE:
 
440
 *
 
441
 * @dirname: directory name (assumed to already exist),
 
442
 * @name: name of file to create (no leading slash),
 
443
 * @contents: string contents of @name.
 
444
 *
 
445
 * Create a file in the specified directory with the specified
 
446
 * contents.
 
447
 *
 
448
 * Notes: A newline character is added in the case where @contents does
 
449
 * not end with one.
 
450
 **/
 
451
#define CREATE_FILE(dirname, name, contents)                         \
 
452
{                                                                    \
 
453
        FILE    *f;                                                  \
 
454
        char     filename[PATH_MAX];                                 \
 
455
                                                                     \
 
456
        assert (dirname[0]);                                         \
 
457
        assert (name[0]);                                            \
 
458
                                                                     \
 
459
        strcpy (filename, dirname);                                  \
 
460
        if ( name[0] != '/' )                                        \
 
461
          strcat (filename, "/");                                    \
 
462
        strcat (filename, name);                                     \
 
463
        f = fopen (filename, "w");                                   \
 
464
        TEST_NE_P (f, NULL);                                         \
 
465
        fprintf (f, "%s", contents);                                 \
 
466
        if ( contents[strlen(contents)-1] != '\n')                   \
 
467
          fprintf (f, "\n");                                         \
 
468
        fclose (f);                                                  \
 
469
}
 
470
 
 
471
/**
 
472
 * DELETE_FILE:
 
473
 *
 
474
 * @dirname: directory in which file to delete exists,
 
475
 * @name: name of file in @dirname to delete.
 
476
 *
 
477
 * Delete specified file.
 
478
 *
 
479
 **/
 
480
#define DELETE_FILE(dirname, name)                                   \
 
481
{                                                                    \
 
482
        char     filename[PATH_MAX];                                 \
 
483
                                                                     \
 
484
        assert (dirname[0]);                                         \
 
485
        assert (name[0]);                                            \
 
486
                                                                     \
 
487
        strcpy (filename, dirname);                                  \
 
488
        if ( name[0] != '/' )                                        \
 
489
          strcat (filename, "/");                                    \
 
490
        strcat (filename, name);                                     \
 
491
                                                                     \
 
492
        TEST_EQ (unlink (filename), 0);                              \
 
493
}
 
494
 
 
495
/**
 
496
 * _WAIT_FOR_FILE():
 
497
 *
 
498
 * @path: full path to file to look for,
 
499
 * @sleep_secs: number of seconds to sleep per loop,
 
500
 * @loops: number of times to check for file.
 
501
 *
 
502
 * Wait for a reasonable period of time for @path to be created.
 
503
 *
 
504
 * Abort if file does not appear within (sleep_secs * loops) seconds.
 
505
 *
 
506
 * XXX:WARNING: this is intrinsically racy since although the file has
 
507
 * been _created_, it has not necessarily been fully written at the
 
508
 * point this macro signifies success. For that we need inotify or
 
509
 * similar.
 
510
 **/
 
511
#define _WAIT_FOR_FILE(path, sleep_secs, loops)                      \
 
512
{                                                                    \
 
513
        int              ok;                                         \
 
514
        struct stat      statbuf;                                    \
 
515
                                                                     \
 
516
        assert (path[0]);                                            \
 
517
                                                                     \
 
518
        /* Wait for log to be created */                             \
 
519
        ok = FALSE;                                                  \
 
520
        for (int i = 0; i < loops; i++) {                            \
 
521
                sleep (sleep_secs);                                  \
 
522
                if (! stat (logfile, &statbuf)) {                    \
 
523
                        ok = TRUE;                                   \
 
524
                        break;                                       \
 
525
                }                                                    \
 
526
        }                                                            \
 
527
        TEST_EQ (ok, TRUE);                                          \
 
528
}
 
529
 
 
530
/**
 
531
 * WAIT_FOR_FILE():
 
532
 *
 
533
 * @path: full path to file to look for.
 
534
 *
 
535
 * Wait for a "reasonable period of time" for @path to be created.
 
536
 *
 
537
 * Abort if file does not appear within.
 
538
 **/
 
539
#define WAIT_FOR_FILE(path)                                         \
 
540
        _WAIT_FOR_FILE (path, 1, 5)
 
541
 
 
542
/**
 
543
 * TEST_STR_MATCH:
 
544
 * @_string: string to check,
 
545
 * @_pattern: pattern to expect.
 
546
 *
 
547
 * Check that @_string matches the glob pattern @_pattern, which
 
548
 * should include the terminating newline if one is expected.
 
549
 *
 
550
 * Notes: Analagous to TEST_FILE_MATCH().
 
551
 **/
 
552
#define TEST_STR_MATCH(_string, _pattern)                            \
 
553
        do {                                                         \
 
554
                if (fnmatch ((_pattern), _string, 0))                \
 
555
                        TEST_FAILED ("wrong string value, "          \
 
556
                                        "expected '%s' got '%s'",    \
 
557
                             (_pattern), _string);                   \
 
558
        } while (0)
 
559
 
 
560
/**
 
561
 * _TEST_STR_ARRAY_CONTAINS:
 
562
 *
 
563
 * @_array: string array,
 
564
 * @_pattern: pattern to expect,
 
565
 * @_invert: invert meaning.
 
566
 *
 
567
 * Check that atleast 1 element in @_array matches @_pattern.
 
568
 *
 
569
 * If @_invert is TRUE, ensure @_pattern is _NOT_ found in @_array.
 
570
 **/
 
571
#define _TEST_STR_ARRAY_CONTAINS(_array, _pattern, _invert)          \
 
572
        do {                                                         \
 
573
                char  **p;                                           \
 
574
                int     got = FALSE;                                 \
 
575
                                                                     \
 
576
                for (p = _array; p && *p; p++) {                     \
 
577
                                                                     \
 
578
                        if (! fnmatch ((_pattern), *p, 0)) {         \
 
579
                                got = TRUE;                          \
 
580
                                break;                               \
 
581
                        }                                            \
 
582
                }                                                    \
 
583
                                                                     \
 
584
                if (_invert) {                                       \
 
585
                  if (got) {                                         \
 
586
                        TEST_FAILED ("wrong content in array "       \
 
587
                                "%p (%s), '%s' found unexpectedly",  \
 
588
                             (_array), #_array, (_pattern));         \
 
589
                  }                                                  \
 
590
                } else {                                             \
 
591
                  if (! got) {                                       \
 
592
                        TEST_FAILED ("wrong content in array "       \
 
593
                                "%p (%s), '%s' not found",           \
 
594
                             (_array), #_array, (_pattern));         \
 
595
                  }                                                  \
 
596
                }                                                    \
 
597
        } while (0)
 
598
 
 
599
/**
 
600
 * _TEST_FILE_CONTAINS:
 
601
 * @_file: FILE to read from,
 
602
 * @_pattern: pattern to expect,
 
603
 * @_invert: invert meaning.
 
604
 *
 
605
 * Check that any subsequent line in file @_file matches the glob pattern
 
606
 * @_pattern, which should include the terminating newline if one is expected.
 
607
 *
 
608
 * If @_invert is TRUE, ensure @_pattern is _NOT_ found in @_file.
 
609
 **/
 
610
#define _TEST_FILE_CONTAINS(_file, _pattern, _invert)                \
 
611
        do {                                                         \
 
612
                char   buffer[1024];                                 \
 
613
                int    got = FALSE;                                  \
 
614
                int    ret;                                          \
 
615
                while (fgets (buffer, sizeof (buffer), _file)) {     \
 
616
                                                                     \
 
617
                        ret = fnmatch ((_pattern), buffer, 0);       \
 
618
                                                                     \
 
619
                        if (! ret) {                                 \
 
620
                                got = TRUE;                          \
 
621
                                break;                               \
 
622
                        }                                            \
 
623
                }                                                    \
 
624
                                                                     \
 
625
                if (_invert) {                                       \
 
626
                    if (got) {                                       \
 
627
                        TEST_FAILED ("wrong content in file "        \
 
628
                                "%p (%s), '%s' found unexpectedly",  \
 
629
                             (_file), #_file, (_pattern));           \
 
630
                    }                                                \
 
631
                } else {                                             \
 
632
                    if (! got) {                                     \
 
633
                        TEST_FAILED ("wrong content in file "        \
 
634
                                "%p (%s), '%s' not found",           \
 
635
                             (_file), #_file, (_pattern));           \
 
636
                    }                                                \
 
637
                }                                                    \
 
638
        } while (0)
 
639
 
 
640
 
 
641
/**
 
642
 * TEST_FILE_CONTAINS:
 
643
 * @_file: FILE to read from,
 
644
 * @_pattern: pattern to expect.
 
645
 *
 
646
 * Check that any subsequent line in file @_file matches the glob pattern
 
647
 * @_pattern, which should include the terminating newline if one is expected.
 
648
 *
 
649
 **/
 
650
#define TEST_FILE_CONTAINS(_file, _pattern)                          \
 
651
        _TEST_FILE_CONTAINS(_file, _pattern, FALSE)
 
652
 
 
653
/**
 
654
 * TEST_FILE_NOT_CONTAINS:
 
655
 * @_file: FILE to read from,
 
656
 * @_pattern: pattern NOT to expect.
 
657
 *
 
658
 * Check that no subsequent line in file @_file does NOT match the glob pattern
 
659
 * @_pattern, which should include the terminating newline if one is expected.
 
660
 *
 
661
 **/
 
662
#define TEST_FILE_NOT_CONTAINS(_file, _pattern)                      \
 
663
        _TEST_FILE_CONTAINS(_file, _pattern, TRUE)
 
664
 
 
665
/**
 
666
 * TEST_STR_ARRAY_CONTAINS:
 
667
 *
 
668
 * @_array: string array,
 
669
 * @_pattern: pattern to expect.
 
670
 *
 
671
 * Check that atleast 1 element in @_array matches @_pattern.
 
672
 **/
 
673
#define TEST_STR_ARRAY_CONTAINS(_array, _pattern)                    \
 
674
        _TEST_STR_ARRAY_CONTAINS (_array, _pattern, FALSE)
 
675
 
 
676
/**
 
677
 * TEST_STR_ARRAY_NOT_CONTAINS:
 
678
 *
 
679
 * @_array: string array,
 
680
 * @_pattern: pattern to expect.
 
681
 *
 
682
 * Check that no element in @_array matches @_pattern.
 
683
 **/
 
684
#define TEST_STR_ARRAY_NOT_CONTAINS(_array, _pattern)                \
 
685
        _TEST_STR_ARRAY_CONTAINS (_array, _pattern, TRUE)
 
686
 
 
687
extern int test_user_mode;
 
688
 
 
689
/* Prototypes */
 
690
int set_upstart_session (pid_t session_init_pid)
 
691
        __attribute__ ((warn_unused_result));
 
692
 
 
693
void wait_for_upstart (int session_init_pid);
 
694
 
 
695
pid_t timed_waitpid (pid_t pid, time_t timeout)
 
696
        __attribute__ ((warn_unused_result));
 
697
 
 
698
char * get_initctl (void)
 
699
        __attribute__ ((warn_unused_result));
 
700
 
 
701
void _start_upstart (pid_t *pid, int user, char * const *args);
 
702
 
 
703
void start_upstart_common (pid_t *pid, int user, const char *confdir,
 
704
                      const char *logdir, char * const *extra);
 
705
 
 
706
void start_upstart (pid_t *pid);
 
707
 
 
708
pid_t job_to_pid (const char *job)
 
709
        __attribute__ ((warn_unused_result));
 
710
 
 
711
int string_check (const char *a, const char *b)
 
712
        __attribute__ ((warn_unused_result));
 
713
 
 
714
const char * get_upstart_binary (void)
 
715
        __attribute__ ((warn_unused_result));
 
716
 
 
717
const char * get_initctl_binary (void)
 
718
        __attribute__ ((warn_unused_result));
 
719
 
 
720
int strcmp_compar (const void *a, const void *b)
 
721
        __attribute__ ((warn_unused_result));
 
722
 
 
723
char *get_session_file (const char *xdg_runtime_dir, pid_t pid)
 
724
        __attribute__ ((warn_unused_result));
 
725
 
 
726
int in_chroot (void)
 
727
        __attribute__ ((warn_unused_result));
 
728
 
 
729
int dbus_configured (void)
 
730
        __attribute__ ((warn_unused_result));
 
731
 
 
732
char *search_and_replace (void *parent, const char *str,
 
733
                          const char *from, const char *to)
 
734
        __attribute__ ((warn_unused_result));
 
735
 
 
736
#endif /* TEST_UTIL_COMMON_H */