Merge lp:~jamesodhunt/upstart/bug-1315060 into lp:upstart

Proposed by James Hunt on 2014-05-09
Status: Merged
Merged at revision: 1630
Proposed branch: lp:~jamesodhunt/upstart/bug-1315060
Merge into: lp:upstart
Diff against target: 1167 lines (+898/-43)
5 files modified
ChangeLog (+24/-0)
init/main.c (+91/-25)
init/man/init.5 (+1/-1)
init/man/init.8 (+51/-6)
init/tests/test_main.c (+731/-11)
To merge this branch: bzr merge lp:~jamesodhunt/upstart/bug-1315060
Reviewer Review Type Date Requested Status
Dimitri John Ledkov 2014-05-09 Approve on 2014-06-05
Review via email: mp+218953@code.launchpad.net
To post a comment you must log in.
Dimitri John Ledkov (xnox) wrote :

As implemented here: if i place foo.conf in both --confdir /etc/init --append-confdir /usr/share/upstart/system, the /etc/init/foo.conf will win.

Which I interpret to be opposite of "append" as in last one wins / "Last In First Out", and opposite of what was requested:
""
As for session jobs, I assume we can just set /custom as an XDG_CONFIG_DIR, and have /custom/upstart with jobs there.
""

In session init if foo.conf exists in both /usr/share/upstart/session and XDG_CONFIG_DIR/upstart, the "override" location XDG_CONFIG_DIR/upstart/foo.conf wins.

James Hunt (jamesodhunt) wrote :

Right, it does sound like we need a '--prepend-confdir' option instead:

# read jobs+overrides from /foo, then /etc/init/ (PID 1)
--prepend-confdir /foo

# read jobs+overrides from /foo, then /bar, then /etc/init/ (PID 1)
--prepend-confdir /foo --prepend-confdir /bar

# read jobs+overrides from /foo, then /bar, then /hello
--confdir /hello --prepend-confdir /foo --prepend-confdir /bar

# read jobs+overrides from /bar, then /qux, then /foo, then /bar (PID 1)
--confdir /foo --prepend-confdir /bar --confdir /baz --prepend-confdir /qux

# read jobs+overrides from /bar, then /qux, then the normal Session Init directories
--user --prepend-confdir /bar --prepend-confdir /qux

# read jobs+overrides from /bar, then /qux, then /foo, then /baz
--user --confdir /foo --prepend-confdir /bar --confdir /baz --prepend-confdir /qux

When booting in --debug mode, Upstart will display the directories it is reading jobs from in the order it reads those directories. However, I do wonder if -- to mimimize confusion -- we should add a further option that simply displays the list of directories that would be searched. If that option is specified anywhere on the command line, it would display the search order, then exit. Something like:

$ init --prepend-confdir /foo --list-confdirs
/foo
/etc/init

$ init --user --confdir /foo --prepend-confdir /bar --confdir /baz --prepend-confdir /qux --list-confdirs
/bar
/qux
/foo
/baz

Dimitri John Ledkov (xnox) wrote :

On 14 May 2014 17:09, James Hunt <email address hidden> wrote:
> Right, it does sound like we need a '--prepend-confdir' option instead:
>
> # read jobs+overrides from /foo, then /etc/init/ (PID 1)
> --prepend-confdir /foo
>
> # read jobs+overrides from /foo, then /bar, then /etc/init/ (PID 1)
> --prepend-confdir /foo --prepend-confdir /bar
>
> # read jobs+overrides from /foo, then /bar, then /hello
> --confdir /hello --prepend-confdir /foo --prepend-confdir /bar
>
> # read jobs+overrides from /bar, then /qux, then /foo, then /bar (PID 1)
> --confdir /foo --prepend-confdir /bar --confdir /baz --prepend-confdir /qux
>
> # read jobs+overrides from /bar, then /qux, then the normal Session Init directories
> --user --prepend-confdir /bar --prepend-confdir /qux
>
> # read jobs+overrides from /bar, then /qux, then /foo, then /baz
> --user --confdir /foo --prepend-confdir /bar --confdir /baz --prepend-confdir /qux
>
> When booting in --debug mode, Upstart will display the directories it is reading jobs from in the order it reads those directories. However, I do wonder if -- to mimimize confusion -- we should add a further option that simply displays the list of directories that would be searched. If that option is specified anywhere on the command line, it would display the search order, then exit. Something like:
>

all looks correct.

> $ init --prepend-confdir /foo --list-confdirs
> /foo
> /etc/init
>
> $ init --user --confdir /foo --prepend-confdir /bar --confdir /baz --prepend-confdir /qux --list-confdirs
> /bar
> /qux
> /foo
> /baz
>

Hm, i wouldn't want to convert init into a client tool. Instead I'd
like to simply e.g. add $ initctl dump-state, which dumps the whole
json state. All conf-sources are serialised in that state, and one can
examine currently monitored conf sources. Or create an $ initctl
list-config-sources which prints serialized conf-sources in a nicer
format. I'd rather inspect conf-sources at runtime, since for e.g.
session init conf-sources depend on the XDG environment variables
which may not be the same if one execs a new/standalone init with the
same args, but different environment.

--
Regards,

Dimitri.

James Hunt (jamesodhunt) wrote :

... and conversely we want to avoid feeping creaturism - KISS FTW. I'm not convinced that dump-state should be added as a front-end to GetState(): the method is there for those that care, but dumping internal state (particularly in JSON) is not something even an admin needs to do. However, as you say, GetState() does provide an existing way to determine the .conf ordering at runtime.

I think you are right that it isn't appropriate to add --list-confdirs though. That is in fact dangerous since due to the way the option parsing works if that option name is mis-typed, it will be ignored and a new init daemon will attempt to start.

What we could do is tweak init-checkconf as I had originally planned:

https://wiki.ubuntu.com/FoundationsTeam/Specs/RaringUpstartUserSessions#init-checkconf

... except that rather than adding the --list-confdirs option, we can have init-checkconf run GetState(), parse out the conf_dirs and dump them in a readable (non-JSON) format. Might be worth rewriting that script in Python to simplify the JSON parsing though. Another advantage to changing inti-checkconf is that it could also be changed to not spawn a new init and connect to an existing one resulting in a tool that can show the theoretical search path or the actual search path for the running init.

James Hunt (jamesodhunt) wrote :

Branch updated to also support '--prepend-confdir'. Let's add init-checkconf sugar once this is merged.

lp:~jamesodhunt/upstart/bug-1315060 updated on 2014-06-04
1622. By James Hunt on 2014-05-21

* init/main.c: Add support for '--prepend-confdir'.
* init/man/init.8: Add '--prepend-confdir'.
* init/tests/test_main.c: Add tests for '--prepend-confdir'.

1623. By James Hunt on 2014-06-04

* Sync with lp:upstart.

Dimitri John Ledkov (xnox) :
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 2014-05-09 15:23:36 +0000
3+++ ChangeLog 2014-06-04 15:39:46 +0000
4@@ -1,3 +1,18 @@
5+2014-05-21 James Hunt <james.hunt@ubuntu.com>
6+
7+ * init/main.c: Add support for '--prepend-confdir'.
8+ * init/man/init.8: Add '--prepend-confdir'.
9+ * init/tests/test_main.c: Add tests for '--prepend-confdir'.
10+
11+2014-05-09 James Hunt <james.hunt@ubuntu.com>
12+
13+ * init/main.c: add '--append-confdir' command-line option (LP: #1315060).
14+ * init/man/init.8:
15+ - Document '--append-confdir'.
16+ - Add init(5) reference for '--confdir'.
17+ * init/tests/test_main.c: New Session and System init tests for
18+ '--append-confdir'.
19+
20 2014-05-09 Dimitri John Ledkov <xnox@ubuntu.com>
21
22 * util/reboot.c: only use rebootcommand code path in runlevels 0,
23@@ -11,6 +26,15 @@
24 * Convert calls to deprecated json_object_object_get() to
25 json_object_object_get_ex().
26
27+2014-05-02 James Hunt <james.hunt@ubuntu.com>
28+
29+ * init/main.c: main(): Allow System Init read from multiple
30+ configuration to directories like a Session Init (LP: #1315060).
31+ * init/man/init.5: Clarify default directory.
32+ * init/man/init.8: Explain new behaviour.
33+ * init/tests/test_main.c: test_confdir(): Update tests for new
34+ '--confdir' behaviour of System init.
35+
36 2014-04-24 James Hunt <james.hunt@ubuntu.com>
37
38 * init/man/init.5:
39
40=== modified file 'init/main.c'
41--- init/main.c 2014-04-11 21:15:39 +0000
42+++ init/main.c 2014-06-04 15:39:46 +0000
43@@ -1,6 +1,6 @@
44 /* upstart
45 *
46- * Copyright © 2009-2011 Canonical Ltd.
47+ * Copyright 2009-2011 Canonical Ltd.
48 * Author: Scott James Remnant <scott@netsplit.com>.
49 *
50 * This program is free software; you can redistribute it and/or modify
51@@ -85,10 +85,12 @@
52 static void usr1_handler (void *data, NihSignal *signal);
53 #endif /* DEBUG */
54
55-static void handle_confdir (void);
56-static void handle_logdir (void);
57-static int console_type_setter (NihOption *option, const char *arg);
58-static int conf_dir_setter (NihOption *option, const char *arg);
59+static void handle_confdir (void);
60+static void handle_logdir (void);
61+static int console_type_setter (NihOption *option, const char *arg);
62+static int conf_dir_setter (NihOption *option, const char *arg);
63+static int prepend_conf_dir_setter (NihOption *option, const char *arg);
64+static int append_conf_dir_setter (NihOption *option, const char *arg);
65
66
67 /**
68@@ -107,6 +109,22 @@
69 static char **conf_dirs = NULL;
70
71 /**
72+ * prepend_conf_dirs:
73+ *
74+ * Array of full paths to job configuration file directories that will
75+ * be added to before the other values in conf_dirs.
76+ **/
77+static char **prepend_conf_dirs = NULL;
78+
79+/**
80+ * append_conf_dirs:
81+ *
82+ * Array of full paths to job configuration file directories that will
83+ * be added to conf_dirs.
84+ **/
85+static char **append_conf_dirs = NULL;
86+
87+/**
88 * initial_event:
89 *
90 * Alternate event to emit at startup (rather than STARTUP_EVENT).
91@@ -146,30 +164,36 @@
92 * Command-line options we accept.
93 **/
94 static NihOption options[] = {
95+ { 0, "append-confdir", N_("specify additional directory to load configuration files from"),
96+ NULL, "DIR", NULL, append_conf_dir_setter },
97+
98+ { 0, "chroot-sessions", N_("enable chroot sessions"),
99+ NULL, NULL, &chroot_sessions, NULL },
100+
101 { 0, "confdir", N_("specify alternative directory to load configuration files from"),
102 NULL, "DIR", NULL, conf_dir_setter },
103
104 { 0, "default-console", N_("default value for console stanza"),
105 NULL, "VALUE", NULL, console_type_setter },
106
107+ { 0, "logdir", N_("specify alternative directory to store job output logs in"),
108+ NULL, "DIR", &log_dir, NULL },
109+
110 { 0, "no-dbus", N_("do not connect to a D-Bus bus"),
111 NULL, NULL, &disable_dbus, NULL },
112
113 { 0, "no-inherit-env", N_("jobs will not inherit environment of init"),
114 NULL, NULL, &no_inherit_env , NULL },
115
116- { 0, "logdir", N_("specify alternative directory to store job output logs in"),
117- NULL, "DIR", &log_dir, NULL },
118-
119 { 0, "no-log", N_("disable job logging"),
120 NULL, NULL, &disable_job_logging, NULL },
121
122- { 0, "chroot-sessions", N_("enable chroot sessions"),
123- NULL, NULL, &chroot_sessions, NULL },
124-
125 { 0, "no-startup-event", N_("do not emit any startup event (for testing)"),
126 NULL, NULL, &disable_startup_event, NULL },
127
128+ { 0, "prepend-confdir", N_("specify additional initial directory to load configuration files from"),
129+ NULL, "DIR", NULL, prepend_conf_dir_setter },
130+
131 /* Must be specified for both stateful and stateless re-exec */
132 { 0, "restart", N_("flag a re-exec has occurred"),
133 NULL, NULL, &restart, NULL },
134@@ -205,6 +229,8 @@
135 int ret;
136
137 conf_dirs = NIH_MUST (nih_str_array_new (NULL));
138+ append_conf_dirs = NIH_MUST (nih_str_array_new (NULL));
139+ prepend_conf_dirs = NIH_MUST (nih_str_array_new (NULL));
140
141 args_copy = NIH_MUST (nih_str_array_copy (NULL, NULL, argv));
142
143@@ -567,25 +593,22 @@
144 }
145
146 /* Read configuration */
147+ if (prepend_conf_dirs[0]) {
148+ for (char **d = prepend_conf_dirs; d && *d; d++) {
149+ nih_debug ("Prepending configuration directory %s", *d);
150+ NIH_MUST (conf_source_new (NULL, *d, CONF_JOB_DIR));
151+ }
152+ }
153+
154 if (! user_mode) {
155- char *conf_dir;
156- int len = 0;
157-
158 nih_assert (conf_dirs[0]);
159
160- /* Count entries */
161- for (char **d = conf_dirs; d && *d; d++, len++)
162- ;
163-
164- nih_assert (len);
165-
166- /* Use last value specified */
167- conf_dir = conf_dirs[len-1];
168-
169 NIH_MUST (conf_source_new (NULL, CONFFILE, CONF_FILE));
170
171- nih_debug ("Using configuration directory %s", conf_dir);
172- NIH_MUST (conf_source_new (NULL, conf_dir, CONF_JOB_DIR));
173+ for (char **d = conf_dirs; d && *d; d++) {
174+ nih_debug ("Using configuration directory %s", *d);
175+ NIH_MUST (conf_source_new (NULL, *d, CONF_JOB_DIR));
176+ }
177 } else {
178 nih_local char **dirs = NULL;
179
180@@ -597,7 +620,16 @@
181 }
182 }
183
184+ if (append_conf_dirs[0]) {
185+ for (char **d = append_conf_dirs; d && *d; d++) {
186+ nih_debug ("Adding configuration directory %s", *d);
187+ NIH_MUST (conf_source_new (NULL, *d, CONF_JOB_DIR));
188+ }
189+ }
190+
191 nih_free (conf_dirs);
192+ nih_free (prepend_conf_dirs);
193+ nih_free (append_conf_dirs);
194
195 job_class_environment_init ();
196
197@@ -1105,3 +1137,37 @@
198
199 return 0;
200 }
201+
202+/**
203+ * NihOption setter function to handle selection of configuration file
204+ * directories.
205+ *
206+ * Returns: 0 on success, -1 on invalid console type.
207+ **/
208+static int
209+prepend_conf_dir_setter (NihOption *option, const char *arg)
210+{
211+ nih_assert (prepend_conf_dirs);
212+ nih_assert (option);
213+
214+ NIH_MUST (nih_str_array_add (&prepend_conf_dirs, NULL, NULL, arg));
215+
216+ return 0;
217+}
218+
219+/**
220+ * NihOption setter function to handle selection of configuration file
221+ * directories.
222+ *
223+ * Returns: 0 on success, -1 on invalid console type.
224+ **/
225+static int
226+append_conf_dir_setter (NihOption *option, const char *arg)
227+{
228+ nih_assert (append_conf_dirs);
229+ nih_assert (option);
230+
231+ NIH_MUST (nih_str_array_add (&append_conf_dirs, NULL, NULL, arg));
232+
233+ return 0;
234+}
235
236=== modified file 'init/man/init.5'
237--- init/man/init.5 2014-04-24 12:39:18 +0000
238+++ init/man/init.5 2014-06-04 15:39:46 +0000
239@@ -22,7 +22,7 @@
240 .BR init (8)
241 daemon reads its job configuration from files in the
242 .I /etc/init/
243-directory, and watches for future changes to these files using
244+directory by default, and watches for future changes to these files using
245 .BR inotify (7).
246
247 If Upstart was invoked as a user process with \-\-user option, it will
248
249=== modified file 'init/man/init.8'
250--- init/man/init.8 2013-12-23 17:31:22 +0000
251+++ init/man/init.8 2014-06-04 15:39:46 +0000
252@@ -253,14 +253,41 @@
253 by placing them on the kernel command-line.
254 .\"
255 .TP
256+.B \-\-append-confdir \fIdirectory\fP
257+Add the specified directory to the default directory or directories
258+that job configuration files will be read from. This option may be
259+specified multiple times which will result in job configuration files
260+being loaded from each directory specified (which must exist).
261+Directories will be searched for jobs in the specified order after the
262+default directories have been searched.
263+
264+Note that if this option is used in combination with
265+.BR \-\-confdir ","
266+or
267+.BR \-\-prepend\-confdir ","
268+regardless of the order of the options on the command-line, the append
269+directories will be added
270+.I after
271+the other directories.
272+.\"
273+.TP
274 .B \-\-confdir \fIdirectory\fP
275 Read job configuration files from a directory other than the default
276-(\fI/etc/init\fP for process ID 1).
277-
278-When running as process ID 1, the last directory specified will be used.
279-
280-In user session mode, multiple directories will be honoured and job
281-configuration files loaded from the directories in the order specified.
282+(\fI/etc/init\fP for process ID 1). This option may be specified
283+multiple times which will result in job configuration files being
284+loaded from each directory specified (which must exist). Directories
285+will be searched for jobs in the specified order.
286+
287+In the case that multiple directories specify a job of the same name,
288+the first job encountered will be honoured.
289+
290+See section
291+.B User Session Mode
292+in
293+.BR init (5)
294+for the ordered list of default configuration directories a
295+Session Init will consider.
296+
297 .\"
298 .TP
299 .B \-\-default-console \fIvalue\fP
300@@ -308,6 +335,24 @@
301 daemon from starting \fBany\fP jobs automatically.
302 .\"
303 .TP
304+.B \-\-prepend-confdir \fIdirectory\fP
305+Add the specified directory to the directory or directories
306+that job configuration files will be read from. This option may be
307+specified multiple times which will result in job configuration files
308+being loaded from each directory specified (which must exist).
309+Directories will be searched for jobs in the specified order before the
310+default directories have been searched.
311+
312+Note that if this option is used in combination with
313+.BR \-\-confdir ","
314+or
315+.BR \-\-append\-confdir ","
316+regardless of the order of the options on the command-line, the prepend
317+directories will be added
318+.I before
319+the other directories.
320+.\"
321+.TP
322 .B \-\-session
323 Connect to the D\-Bus session bus. This should only be used for testing.
324 .\"
325
326=== modified file 'init/tests/test_main.c'
327--- init/tests/test_main.c 2013-11-12 12:17:30 +0000
328+++ init/tests/test_main.c 2014-06-04 15:39:46 +0000
329@@ -46,6 +46,10 @@
330 {
331 char confdir_a[PATH_MAX];
332 char confdir_b[PATH_MAX];
333+ char confdir_c[PATH_MAX];
334+ char confdir_d[PATH_MAX];
335+ char confdir_e[PATH_MAX];
336+ char confdir_f[PATH_MAX];
337 char *xdg_config_home;
338 char *xdg_runtime_dir;
339 char logdir[PATH_MAX];
340@@ -58,8 +62,10 @@
341 nih_local char *session_file = NULL;
342 nih_local char *path = NULL;
343
344- /* space for 2 sets of confdir options and a terminator */
345- char *extra[5];
346+ /* space for 2 sets of confdir options, 2 sets of
347+ * prepend-confdir, 2 sets of append-confdirs and a terminator.
348+ */
349+ char *extra[13];
350
351 xdg_config_home = getenv ("XDG_CONFIG_HOME");
352 TEST_NE_P (xdg_config_home, NULL);
353@@ -75,6 +81,18 @@
354 TEST_FILENAME (confdir_b);
355 assert0 (mkdir (confdir_b, 0755));
356
357+ TEST_FILENAME (confdir_c);
358+ assert0 (mkdir (confdir_c, 0755));
359+
360+ TEST_FILENAME (confdir_d);
361+ assert0 (mkdir (confdir_d, 0755));
362+
363+ TEST_FILENAME (confdir_e);
364+ assert0 (mkdir (confdir_e, 0755));
365+
366+ TEST_FILENAME (confdir_f);
367+ assert0 (mkdir (confdir_f, 0755));
368+
369 xdg_conf_dir = nih_sprintf (NULL, "%s/%s", xdg_config_home, "upstart");
370 TEST_NE_P (xdg_conf_dir, NULL);
371 assert0 (mkdir (xdg_conf_dir, 0755));
372@@ -151,6 +169,89 @@
373 assert0 (unlink (session_file));
374
375 /************************************************************/
376+ TEST_FEATURE ("Session Init with --prepend-confdir");
377+
378+ CREATE_FILE (confdir_a, "foo.conf", "exec foo");
379+ CREATE_FILE (confdir_a, "conflict.conf", "emits prepend");
380+ CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits confdir");
381+ CREATE_FILE (xdg_conf_dir, "baz.conf", "exec baz");
382+
383+ extra[0] = "--prepend-confdir";
384+ extra[1] = confdir_a;
385+ extra[2] = NULL;
386+
387+ start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
388+
389+ /* Should be running */
390+ assert0 (kill (upstart_pid, 0));
391+
392+ session_file = get_session_file (xdg_runtime_dir, upstart_pid);
393+
394+ cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
395+ TEST_NE_P (cmd, NULL);
396+ RUN_COMMAND (NULL, cmd, &output, &lines);
397+
398+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
399+
400+ TEST_EQ (lines, 3);
401+ TEST_STR_MATCH (output[0], "baz stop/waiting");
402+ TEST_STR_MATCH (output[1], "conflict stop/waiting");
403+ TEST_STR_MATCH (output[2], "foo stop/waiting");
404+ nih_free (output);
405+
406+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict");
407+ TEST_NE_P (cmd, NULL);
408+ RUN_COMMAND (NULL, cmd, &output, &lines);
409+
410+ TEST_EQ (lines, 2);
411+ TEST_STR_MATCH (output[0], "conflict");
412+ TEST_STR_MATCH (output[1], " emits prepend");
413+ nih_free (output);
414+
415+ DELETE_FILE (confdir_a, "foo.conf");
416+ DELETE_FILE (confdir_a, "conflict.conf");
417+ DELETE_FILE (xdg_conf_dir, "conflict.conf");
418+ DELETE_FILE (xdg_conf_dir, "baz.conf");
419+
420+ STOP_UPSTART (upstart_pid);
421+ assert0 (unlink (session_file));
422+
423+ /************************************************************/
424+ TEST_FEATURE ("Session Init with --append-confdir");
425+
426+ CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true");
427+ CREATE_FILE (confdir_a, "conf_dir_job.conf", "exec true");
428+
429+ extra[0] = "--append-confdir";
430+ extra[1] = confdir_a;
431+ extra[2] = NULL;
432+
433+ start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
434+
435+ /* Should be running */
436+ assert0 (kill (upstart_pid, 0));
437+
438+ session_file = get_session_file (xdg_runtime_dir, upstart_pid);
439+
440+ cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
441+ TEST_NE_P (cmd, NULL);
442+ RUN_COMMAND (NULL, cmd, &output, &lines);
443+
444+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
445+
446+ /* jobs in xdg_conf_dir should be considered */
447+ TEST_EQ (lines, 2);
448+ TEST_STR_MATCH (output[0], "conf_dir_job stop/waiting");
449+ TEST_STR_MATCH (output[1], "xdg_dir_job stop/waiting");
450+ nih_free (output);
451+
452+ DELETE_FILE (xdg_conf_dir, "xdg_dir_job.conf");
453+ DELETE_FILE (confdir_a, "conf_dir_job.conf");
454+
455+ STOP_UPSTART (upstart_pid);
456+ assert0 (unlink (session_file));
457+
458+ /************************************************************/
459 TEST_FEATURE ("Session Init with multiple --confdir");
460
461 CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true");
462@@ -191,6 +292,88 @@
463 assert0 (unlink (session_file));
464
465 /************************************************************/
466+ TEST_FEATURE ("Session Init with multiple --prepend-confdir");
467+
468+ CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true");
469+ CREATE_FILE (confdir_a, "conf_dir_a_job.conf", "exec true");
470+ CREATE_FILE (confdir_b, "conf_dir_b_job.conf", "exec true");
471+
472+ extra[0] = "--prepend-confdir";
473+ extra[1] = confdir_a;
474+ extra[2] = "--prepend-confdir";
475+ extra[3] = confdir_b;
476+ extra[4] = NULL;
477+
478+ /* pass 2 confdir directories */
479+ start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
480+
481+ /* Should be running */
482+ assert0 (kill (upstart_pid, 0));
483+
484+ session_file = get_session_file (xdg_runtime_dir, upstart_pid);
485+
486+ cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
487+ TEST_NE_P (cmd, NULL);
488+ RUN_COMMAND (NULL, cmd, &output, &lines);
489+
490+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
491+
492+ /* jobs in xdg_conf_dir should be considered */
493+ TEST_EQ (lines, 3);
494+ TEST_STR_MATCH (output[0], "conf_dir_a_job stop/waiting");
495+ TEST_STR_MATCH (output[1], "conf_dir_b_job stop/waiting");
496+ TEST_STR_MATCH (output[2], "xdg_dir_job stop/waiting");
497+ nih_free (output);
498+
499+ DELETE_FILE (xdg_conf_dir, "xdg_dir_job.conf");
500+ DELETE_FILE (confdir_a, "conf_dir_a_job.conf");
501+ DELETE_FILE (confdir_b, "conf_dir_b_job.conf");
502+
503+ STOP_UPSTART (upstart_pid);
504+ assert0 (unlink (session_file));
505+
506+ /************************************************************/
507+ TEST_FEATURE ("Session Init with multiple --append-confdir");
508+
509+ CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true");
510+ CREATE_FILE (confdir_a, "conf_dir_a_job.conf", "exec true");
511+ CREATE_FILE (confdir_b, "conf_dir_b_job.conf", "exec true");
512+
513+ extra[0] = "--append-confdir";
514+ extra[1] = confdir_a;
515+ extra[2] = "--append-confdir";
516+ extra[3] = confdir_b;
517+ extra[4] = NULL;
518+
519+ /* pass 2 confdir directories */
520+ start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
521+
522+ /* Should be running */
523+ assert0 (kill (upstart_pid, 0));
524+
525+ session_file = get_session_file (xdg_runtime_dir, upstart_pid);
526+
527+ cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
528+ TEST_NE_P (cmd, NULL);
529+ RUN_COMMAND (NULL, cmd, &output, &lines);
530+
531+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
532+
533+ /* jobs in xdg_conf_dir should be considered */
534+ TEST_EQ (lines, 3);
535+ TEST_STR_MATCH (output[0], "conf_dir_a_job stop/waiting");
536+ TEST_STR_MATCH (output[1], "conf_dir_b_job stop/waiting");
537+ TEST_STR_MATCH (output[2], "xdg_dir_job stop/waiting");
538+ nih_free (output);
539+
540+ DELETE_FILE (xdg_conf_dir, "xdg_dir_job.conf");
541+ DELETE_FILE (confdir_a, "conf_dir_a_job.conf");
542+ DELETE_FILE (confdir_b, "conf_dir_b_job.conf");
543+
544+ STOP_UPSTART (upstart_pid);
545+ assert0 (unlink (session_file));
546+
547+ /************************************************************/
548 TEST_FEATURE ("Session Init with multiple --confdir and conflicting names");
549
550 CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir");
551@@ -241,6 +424,233 @@
552 assert0 (unlink (session_file));
553
554 /************************************************************/
555+ TEST_FEATURE ("Session Init with multiple --prepend-confdir and conflicting names");
556+
557+ CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir");
558+ CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a");
559+ CREATE_FILE (confdir_b, "foo.conf", "exec true");
560+
561+ extra[0] = "--prepend-confdir";
562+ extra[1] = confdir_a;
563+ extra[2] = "--prepend-confdir";
564+ extra[3] = confdir_b;
565+ extra[4] = NULL;
566+
567+ /* pass 2 confdir directories */
568+ start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
569+
570+ /* Should be running */
571+ assert0 (kill (upstart_pid, 0));
572+
573+ session_file = get_session_file (xdg_runtime_dir, upstart_pid);
574+
575+ cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
576+ TEST_NE_P (cmd, NULL);
577+ RUN_COMMAND (NULL, cmd, &output, &lines);
578+
579+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
580+
581+ /* We expect jobs in xdg_conf_dir to be ignored */
582+ TEST_EQ (lines, 2);
583+ TEST_STR_MATCH (output[0], "conflict stop/waiting");
584+ TEST_STR_MATCH (output[1], "foo stop/waiting");
585+ nih_free (output);
586+
587+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict");
588+ TEST_NE_P (cmd, NULL);
589+ RUN_COMMAND (NULL, cmd, &output, &lines);
590+
591+ /* Ensure the correct version of the conflict job is found */
592+ TEST_EQ (lines, 2);
593+ TEST_STR_MATCH (output[0], "conflict");
594+ TEST_STR_MATCH (output[1], " emits confdir_a");
595+ nih_free (output);
596+
597+ DELETE_FILE (xdg_conf_dir, "conflict.conf");
598+ DELETE_FILE (confdir_a, "conflict.conf");
599+ DELETE_FILE (confdir_b, "foo.conf");
600+
601+ STOP_UPSTART (upstart_pid);
602+ assert0 (unlink (session_file));
603+
604+ /************************************************************/
605+ TEST_FEATURE ("Session Init with multiple --append-confdir and conflicting names");
606+
607+ CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir");
608+ CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a");
609+ CREATE_FILE (confdir_b, "foo.conf", "exec true");
610+
611+ extra[0] = "--append-confdir";
612+ extra[1] = confdir_a;
613+ extra[2] = "--append-confdir";
614+ extra[3] = confdir_b;
615+ extra[4] = NULL;
616+
617+ /* pass 2 confdir directories */
618+ start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
619+
620+ /* Should be running */
621+ assert0 (kill (upstart_pid, 0));
622+
623+ session_file = get_session_file (xdg_runtime_dir, upstart_pid);
624+
625+ cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
626+ TEST_NE_P (cmd, NULL);
627+ RUN_COMMAND (NULL, cmd, &output, &lines);
628+
629+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
630+
631+ /* We expect jobs in xdg_conf_dir to be ignored */
632+ TEST_EQ (lines, 2);
633+ TEST_STR_MATCH (output[0], "conflict stop/waiting");
634+ TEST_STR_MATCH (output[1], "foo stop/waiting");
635+ nih_free (output);
636+
637+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict");
638+ TEST_NE_P (cmd, NULL);
639+ RUN_COMMAND (NULL, cmd, &output, &lines);
640+
641+ /* Ensure the correct version of the conflict job is found */
642+ TEST_EQ (lines, 2);
643+ TEST_STR_MATCH (output[0], "conflict");
644+ TEST_STR_MATCH (output[1], " emits xdg_conf_dir");
645+ nih_free (output);
646+
647+ DELETE_FILE (xdg_conf_dir, "conflict.conf");
648+ DELETE_FILE (confdir_a, "conflict.conf");
649+ DELETE_FILE (confdir_b, "foo.conf");
650+
651+ STOP_UPSTART (upstart_pid);
652+ assert0 (unlink (session_file));
653+
654+ /************************************************************/
655+ TEST_FEATURE ("Session Init with multiple --confdir, --prepend-confdir and --append-confdir with conflicting names");
656+
657+ CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir");
658+ CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a");
659+ CREATE_FILE (confdir_b, "foo.conf", "exec true");
660+ CREATE_FILE (confdir_c, "conflict.conf", "emits confdir_c");
661+ CREATE_FILE (confdir_d, "conflict.conf", "emits confdir_d");
662+ CREATE_FILE (confdir_e, "bar.conf", "exec false");
663+
664+ extra[0] = "--prepend-confdir";
665+ extra[1] = confdir_d;
666+ extra[2] = "--prepend-confdir";
667+ extra[3] = confdir_e;
668+ extra[4] = "--confdir";
669+ extra[5] = confdir_a;
670+ extra[6] = "--confdir";
671+ extra[7] = confdir_b;
672+ extra[8] = "--append-confdir";
673+ extra[9] = confdir_c;
674+ extra[10] = NULL;
675+
676+ start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
677+
678+ /* Should be running */
679+ assert0 (kill (upstart_pid, 0));
680+
681+ session_file = get_session_file (xdg_runtime_dir, upstart_pid);
682+
683+ cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
684+ TEST_NE_P (cmd, NULL);
685+ RUN_COMMAND (NULL, cmd, &output, &lines);
686+
687+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
688+
689+ TEST_EQ (lines, 3);
690+ TEST_STR_MATCH (output[0], "bar stop/waiting");
691+ TEST_STR_MATCH (output[1], "conflict stop/waiting");
692+ TEST_STR_MATCH (output[2], "foo stop/waiting");
693+ nih_free (output);
694+
695+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict");
696+ TEST_NE_P (cmd, NULL);
697+ RUN_COMMAND (NULL, cmd, &output, &lines);
698+
699+ /* Ensure the correct version of the conflict job is found */
700+ TEST_EQ (lines, 2);
701+ TEST_STR_MATCH (output[0], "conflict");
702+ TEST_STR_MATCH (output[1], " emits confdir_d");
703+ nih_free (output);
704+
705+ DELETE_FILE (xdg_conf_dir, "conflict.conf");
706+ DELETE_FILE (confdir_a, "conflict.conf");
707+ DELETE_FILE (confdir_b, "foo.conf");
708+ DELETE_FILE (confdir_c, "conflict.conf");
709+ DELETE_FILE (confdir_d, "conflict.conf");
710+ DELETE_FILE (confdir_e, "bar.conf");
711+
712+ STOP_UPSTART (upstart_pid);
713+ assert0 (unlink (session_file));
714+
715+ /************************************************************/
716+ TEST_FEATURE ("Session Init with multiple out of order --confdir, --prepend-confdir and --append-confdir");
717+
718+ CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir");
719+ CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a");
720+ CREATE_FILE (confdir_b, "foo.conf", "exec true");
721+ CREATE_FILE (confdir_c, "conflict.conf", "emits confdir_c");
722+ CREATE_FILE (confdir_d, "conflict.conf", "emits confdir_d");
723+ CREATE_FILE (confdir_e, "bar.conf", "exec false");
724+ CREATE_FILE (confdir_f, "baz.conf", "exec false");
725+
726+ extra[0] = "--append-confdir";
727+ extra[1] = confdir_a;
728+ extra[2] = "--prepend-confdir";
729+ extra[3] = confdir_e;
730+ extra[4] = "--confdir";
731+ extra[5] = confdir_b;
732+ extra[6] = "--append-confdir";
733+ extra[7] = confdir_c;
734+ extra[8] = "--prepend-confdir";
735+ extra[9] = confdir_f;
736+ extra[10] = "--confdir";
737+ extra[11] = confdir_d;
738+ extra[12] = NULL;
739+
740+ start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
741+
742+ /* Should be running */
743+ assert0 (kill (upstart_pid, 0));
744+
745+ session_file = get_session_file (xdg_runtime_dir, upstart_pid);
746+
747+ cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
748+ TEST_NE_P (cmd, NULL);
749+ RUN_COMMAND (NULL, cmd, &output, &lines);
750+
751+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
752+
753+ TEST_EQ (lines, 4);
754+ TEST_STR_MATCH (output[0], "bar stop/waiting");
755+ TEST_STR_MATCH (output[1], "baz stop/waiting");
756+ TEST_STR_MATCH (output[2], "conflict stop/waiting");
757+ TEST_STR_MATCH (output[3], "foo stop/waiting");
758+ nih_free (output);
759+
760+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict");
761+ TEST_NE_P (cmd, NULL);
762+ RUN_COMMAND (NULL, cmd, &output, &lines);
763+
764+ /* Ensure the correct version of the conflict job is found */
765+ TEST_EQ (lines, 2);
766+ TEST_STR_MATCH (output[0], "conflict");
767+ TEST_STR_MATCH (output[1], " emits confdir_d");
768+ nih_free (output);
769+
770+ DELETE_FILE (xdg_conf_dir, "conflict.conf");
771+ DELETE_FILE (confdir_a, "conflict.conf");
772+ DELETE_FILE (confdir_b, "foo.conf");
773+ DELETE_FILE (confdir_c, "conflict.conf");
774+ DELETE_FILE (confdir_d, "conflict.conf");
775+ DELETE_FILE (confdir_e, "bar.conf");
776+ DELETE_FILE (confdir_f, "baz.conf");
777+
778+ STOP_UPSTART (upstart_pid);
779+ assert0 (unlink (session_file));
780+
781+ /************************************************************/
782 TEST_FEATURE ("System Init without --confdir");
783
784 /* Use the "secret" interface */
785@@ -305,6 +715,66 @@
786 STOP_UPSTART (upstart_pid);
787
788 /************************************************************/
789+ TEST_FEATURE ("System Init with --prepend-confdir");
790+
791+ TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf"));
792+
793+ CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "exec true");
794+
795+ extra[0] = "--prepend-confdir";
796+ extra[1] = confdir_a;
797+ extra[2] = NULL;
798+
799+ start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
800+
801+ /* Should be running */
802+ assert0 (kill (upstart_pid, 0));
803+
804+ cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default");
805+ TEST_NE_P (cmd, NULL);
806+ RUN_COMMAND (NULL, cmd, &output, &lines);
807+
808+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
809+
810+ TEST_EQ (lines, 1);
811+ TEST_STR_MATCH (output[0], "must-not-exist-by-default stop/waiting");
812+ nih_free (output);
813+
814+ DELETE_FILE (confdir_a, "must-not-exist-by-default.conf");
815+
816+ STOP_UPSTART (upstart_pid);
817+
818+ /************************************************************/
819+ TEST_FEATURE ("System Init with --append-confdir");
820+
821+ TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf"));
822+
823+ CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "exec true");
824+
825+ extra[0] = "--append-confdir";
826+ extra[1] = confdir_a;
827+ extra[2] = NULL;
828+
829+ start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
830+
831+ /* Should be running */
832+ assert0 (kill (upstart_pid, 0));
833+
834+ cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default");
835+ TEST_NE_P (cmd, NULL);
836+ RUN_COMMAND (NULL, cmd, &output, &lines);
837+
838+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
839+
840+ TEST_EQ (lines, 1);
841+ TEST_STR_MATCH (output[0], "must-not-exist-by-default stop/waiting");
842+ nih_free (output);
843+
844+ DELETE_FILE (confdir_a, "must-not-exist-by-default.conf");
845+
846+ STOP_UPSTART (upstart_pid);
847+
848+ /************************************************************/
849 TEST_FEATURE ("System Init with multiple --confdir");
850
851 assert0 (setenv ("UPSTART_CONFDIR", xdg_conf_dir, 1));
852@@ -331,14 +801,14 @@
853
854 qsort (output, lines, sizeof (output[0]), strcmp_compar);
855
856- TEST_EQ (lines, 2);
857- /* XXX: Only the last instance of --confdir should be honoured.
858- *
859- * This behaviour deviates from running as a Session Init where *all*
860- * --confdir's specified are used.
861+ /* Like a Session Init, the System Init behaviour is (now) to
862+ * honour all --confdirs.
863 */
864- TEST_STR_MATCH (output[0], "baz stop/waiting");
865- TEST_STR_MATCH (output[1], "qux stop/waiting");
866+ TEST_EQ (lines, 3);
867+
868+ TEST_STR_MATCH (output[0], "bar stop/waiting");
869+ TEST_STR_MATCH (output[1], "baz stop/waiting");
870+ TEST_STR_MATCH (output[2], "qux stop/waiting");
871 nih_free (output);
872
873 DELETE_FILE (xdg_conf_dir, "foo.conf");
874@@ -349,6 +819,96 @@
875 STOP_UPSTART (upstart_pid);
876
877 /************************************************************/
878+ TEST_FEATURE ("System Init with multiple --prepend-confdir");
879+
880+ TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf"));
881+ TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default2.conf"));
882+
883+ CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "exec true");
884+ CREATE_FILE (confdir_b, "must-not-exist-by-default2.conf", "exec true");
885+
886+ extra[0] = "--prepend-confdir";
887+ extra[1] = confdir_a;
888+ extra[2] = "--prepend-confdir";
889+ extra[3] = confdir_b;
890+ extra[4] = NULL;
891+
892+ start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
893+
894+ /* Should be running */
895+ assert0 (kill (upstart_pid, 0));
896+
897+ cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default");
898+ TEST_NE_P (cmd, NULL);
899+ RUN_COMMAND (NULL, cmd, &output, &lines);
900+
901+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
902+
903+ TEST_EQ (lines, 1);
904+ TEST_STR_MATCH (output[0], "must-not-exist-by-default stop/waiting");
905+ nih_free (output);
906+
907+ cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default2");
908+ TEST_NE_P (cmd, NULL);
909+ RUN_COMMAND (NULL, cmd, &output, &lines);
910+
911+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
912+
913+ TEST_EQ (lines, 1);
914+ TEST_STR_MATCH (output[0], "must-not-exist-by-default2 stop/waiting");
915+ nih_free (output);
916+
917+ DELETE_FILE (confdir_a, "must-not-exist-by-default.conf");
918+ DELETE_FILE (confdir_b, "must-not-exist-by-default2.conf");
919+
920+ STOP_UPSTART (upstart_pid);
921+
922+ /************************************************************/
923+ TEST_FEATURE ("System Init with multiple --append-confdir");
924+
925+ TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf"));
926+ TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default2.conf"));
927+
928+ CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "exec true");
929+ CREATE_FILE (confdir_b, "must-not-exist-by-default2.conf", "exec true");
930+
931+ extra[0] = "--append-confdir";
932+ extra[1] = confdir_a;
933+ extra[2] = "--append-confdir";
934+ extra[3] = confdir_b;
935+ extra[4] = NULL;
936+
937+ start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
938+
939+ /* Should be running */
940+ assert0 (kill (upstart_pid, 0));
941+
942+ cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default");
943+ TEST_NE_P (cmd, NULL);
944+ RUN_COMMAND (NULL, cmd, &output, &lines);
945+
946+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
947+
948+ TEST_EQ (lines, 1);
949+ TEST_STR_MATCH (output[0], "must-not-exist-by-default stop/waiting");
950+ nih_free (output);
951+
952+ cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default2");
953+ TEST_NE_P (cmd, NULL);
954+ RUN_COMMAND (NULL, cmd, &output, &lines);
955+
956+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
957+
958+ TEST_EQ (lines, 1);
959+ TEST_STR_MATCH (output[0], "must-not-exist-by-default2 stop/waiting");
960+ nih_free (output);
961+
962+ DELETE_FILE (confdir_a, "must-not-exist-by-default.conf");
963+ DELETE_FILE (confdir_b, "must-not-exist-by-default2.conf");
964+
965+ STOP_UPSTART (upstart_pid);
966+
967+ /************************************************************/
968 TEST_FEATURE ("System Init with multiple --confdir and conflicting names");
969
970 assert0 (setenv ("UPSTART_CONFDIR", xdg_conf_dir, 1));
971@@ -363,6 +923,7 @@
972 extra[3] = confdir_b;
973 extra[4] = NULL;
974
975+ /* pass 2 confdir directories */
976 start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
977
978 /* Should be running */
979@@ -375,7 +936,6 @@
980 qsort (output, lines, sizeof (output[0]), strcmp_compar);
981
982 TEST_EQ (lines, 1);
983- /* only the last instance of --confdir should be honoured */
984 TEST_STR_MATCH (output[0], "conflict stop/waiting");
985 nih_free (output);
986
987@@ -386,7 +946,7 @@
988 /* Ensure the correct version of the conflict job is found */
989 TEST_EQ (lines, 2);
990 TEST_STR_MATCH (output[0], "conflict");
991- TEST_STR_MATCH (output[1], " emits confdir_b");
992+ TEST_STR_MATCH (output[1], " emits confdir_a");
993 nih_free (output);
994
995 DELETE_FILE (xdg_conf_dir, "conflict.conf");
996@@ -396,11 +956,171 @@
997 STOP_UPSTART (upstart_pid);
998
999 /************************************************************/
1000+ TEST_FEATURE ("System Init with multiple --prepend-confdir and conflicting names");
1001+
1002+ TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf"));
1003+
1004+ CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "emits confdir_a");
1005+ CREATE_FILE (confdir_b, "must-not-exist-by-default.conf", "emits confdir_b");
1006+
1007+ extra[0] = "--prepend-confdir";
1008+ extra[1] = confdir_a;
1009+ extra[2] = "--prepend-confdir";
1010+ extra[3] = confdir_b;
1011+ extra[4] = NULL;
1012+
1013+ start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
1014+
1015+ /* Should be running */
1016+ assert0 (kill (upstart_pid, 0));
1017+
1018+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "must-not-exist-by-default");
1019+ TEST_NE_P (cmd, NULL);
1020+ RUN_COMMAND (NULL, cmd, &output, &lines);
1021+
1022+ /* Ensure the correct version of the conflict job is found */
1023+ TEST_EQ (lines, 2);
1024+ TEST_STR_MATCH (output[0], "must-not-exist-by-default");
1025+ TEST_STR_MATCH (output[1], " emits confdir_a");
1026+ nih_free (output);
1027+
1028+ DELETE_FILE (confdir_a, "must-not-exist-by-default.conf");
1029+ DELETE_FILE (confdir_b, "must-not-exist-by-default.conf");
1030+
1031+ STOP_UPSTART (upstart_pid);
1032+
1033+ /************************************************************/
1034+ TEST_FEATURE ("System Init with multiple --append-confdir and conflicting names");
1035+
1036+ TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf"));
1037+
1038+ CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "emits confdir_a");
1039+ CREATE_FILE (confdir_b, "must-not-exist-by-default.conf", "emits confdir_b");
1040+
1041+ extra[0] = "--append-confdir";
1042+ extra[1] = confdir_a;
1043+ extra[2] = "--append-confdir";
1044+ extra[3] = confdir_b;
1045+ extra[4] = NULL;
1046+
1047+ start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
1048+
1049+ /* Should be running */
1050+ assert0 (kill (upstart_pid, 0));
1051+
1052+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "must-not-exist-by-default");
1053+ TEST_NE_P (cmd, NULL);
1054+ RUN_COMMAND (NULL, cmd, &output, &lines);
1055+
1056+ /* Ensure the correct version of the conflict job is found */
1057+ TEST_EQ (lines, 2);
1058+ TEST_STR_MATCH (output[0], "must-not-exist-by-default");
1059+ TEST_STR_MATCH (output[1], " emits confdir_a");
1060+ nih_free (output);
1061+
1062+ DELETE_FILE (confdir_a, "must-not-exist-by-default.conf");
1063+ DELETE_FILE (confdir_b, "must-not-exist-by-default.conf");
1064+
1065+ STOP_UPSTART (upstart_pid);
1066+
1067+ /************************************************************/
1068+ TEST_FEATURE ("System Init with multiple out of order --confdir, --prepend-confdir and --append-confdir");
1069+
1070+ CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a");
1071+ CREATE_FILE (confdir_a, "wibble.conf", "emits wobble");
1072+ CREATE_FILE (confdir_b, "conflict.conf", "emits confdir_b");
1073+ CREATE_FILE (confdir_c, "conflict.conf", "emits confdir_c");
1074+ CREATE_FILE (confdir_d, "foo.conf", "emits hello");
1075+ CREATE_FILE (confdir_e, "bar.conf", "emits world");
1076+ CREATE_FILE (confdir_e, "conflict.conf", "emits confdir_e");
1077+ CREATE_FILE (confdir_f, "conflict.conf", "emits confdir_f");
1078+ CREATE_FILE (confdir_f, "baz.conf", "exec true");
1079+
1080+ extra[0] = "--append-confdir";
1081+ extra[1] = confdir_a;
1082+ extra[2] = "--prepend-confdir";
1083+ extra[3] = confdir_e;
1084+ extra[4] = "--confdir";
1085+ extra[5] = confdir_b;
1086+ extra[6] = "--append-confdir";
1087+ extra[7] = confdir_f;
1088+ extra[8] = "--confdir";
1089+ extra[9] = confdir_c;
1090+ extra[10] = "--prepend-confdir";
1091+ extra[11] = confdir_d;
1092+ extra[12] = NULL;
1093+
1094+ start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
1095+
1096+ /* Should be running */
1097+ assert0 (kill (upstart_pid, 0));
1098+
1099+ cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
1100+ TEST_NE_P (cmd, NULL);
1101+ RUN_COMMAND (NULL, cmd, &output, &lines);
1102+
1103+ qsort (output, lines, sizeof (output[0]), strcmp_compar);
1104+
1105+ TEST_EQ (lines, 5);
1106+ TEST_STR_MATCH (output[0], "bar stop/waiting");
1107+ TEST_STR_MATCH (output[1], "baz stop/waiting");
1108+ TEST_STR_MATCH (output[2], "conflict stop/waiting");
1109+ TEST_STR_MATCH (output[3], "foo stop/waiting");
1110+ TEST_STR_MATCH (output[4], "wibble stop/waiting");
1111+ nih_free (output);
1112+
1113+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict");
1114+ TEST_NE_P (cmd, NULL);
1115+ RUN_COMMAND (NULL, cmd, &output, &lines);
1116+ TEST_EQ (lines, 2);
1117+ TEST_STR_MATCH (output[0], "conflict");
1118+ TEST_STR_MATCH (output[1], " emits confdir_e");
1119+ nih_free (output);
1120+
1121+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "wibble");
1122+ TEST_NE_P (cmd, NULL);
1123+ RUN_COMMAND (NULL, cmd, &output, &lines);
1124+ TEST_EQ (lines, 2);
1125+ TEST_STR_MATCH (output[0], "wibble");
1126+ TEST_STR_MATCH (output[1], " emits wobble");
1127+ nih_free (output);
1128+
1129+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "foo");
1130+ TEST_NE_P (cmd, NULL);
1131+ RUN_COMMAND (NULL, cmd, &output, &lines);
1132+ TEST_EQ (lines, 2);
1133+ TEST_STR_MATCH (output[0], "foo");
1134+ TEST_STR_MATCH (output[1], " emits hello");
1135+ nih_free (output);
1136+
1137+ cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "bar");
1138+ TEST_NE_P (cmd, NULL);
1139+ RUN_COMMAND (NULL, cmd, &output, &lines);
1140+ TEST_EQ (lines, 2);
1141+ TEST_STR_MATCH (output[0], "bar");
1142+ TEST_STR_MATCH (output[1], " emits world");
1143+ nih_free (output);
1144+
1145+ DELETE_FILE (confdir_a, "conflict.conf");
1146+ DELETE_FILE (confdir_a, "wibble.conf");
1147+ DELETE_FILE (confdir_b, "conflict.conf");
1148+ DELETE_FILE (confdir_c, "conflict.conf");
1149+ DELETE_FILE (confdir_d, "foo.conf");
1150+ DELETE_FILE (confdir_e, "bar.conf");
1151+ DELETE_FILE (confdir_e, "conflict.conf");
1152+ DELETE_FILE (confdir_f, "conflict.conf");
1153+ DELETE_FILE (confdir_f, "baz.conf");
1154+
1155+ STOP_UPSTART (upstart_pid);
1156
1157 TEST_DBUS_END (dbus_pid);
1158
1159 assert0 (rmdir (confdir_a));
1160 assert0 (rmdir (confdir_b));
1161+ assert0 (rmdir (confdir_c));
1162+ assert0 (rmdir (confdir_d));
1163+ assert0 (rmdir (confdir_e));
1164+ assert0 (rmdir (confdir_f));
1165 assert0 (rmdir (xdg_conf_dir));
1166 assert0 (rmdir (logdir));
1167 assert0 (unsetenv ("UPSTART_CONFDIR"));

Subscribers

People subscribed via source and target branches