James Hunt has proposed merging lp:~jamesodhunt/upstart/bug-1315060 into 
lp:upstart.

Requested reviews:
  Upstart Reviewers (upstart-reviewers)
Related bugs:
  Bug #1315060 in upstart (Ubuntu): "Allow --confdir to look for system jobs in 
more than one directory"
  https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/1315060

For more details, see:
https://code.launchpad.net/~jamesodhunt/upstart/bug-1315060/+merge/218953
-- 
https://code.launchpad.net/~jamesodhunt/upstart/bug-1315060/+merge/218953
Your team Upstart Reviewers is requested to review the proposed merge of 
lp:~jamesodhunt/upstart/bug-1315060 into lp:upstart.
=== modified file 'ChangeLog'
--- ChangeLog	2014-05-07 16:34:44 +0000
+++ ChangeLog	2014-05-09 09:57:49 +0000
@@ -1,8 +1,26 @@
+2014-05-09  James Hunt  <[email protected]>
+
+	* init/main.c: add '--append-confdir' command-line option (LP: #1315060).
+	* init/man/init.8:
+	  - Document '--append-confdir'.
+	  - Add init(5) reference for '--confdir'.
+	* init/tests/test_main.c: New Session and System init tests for
+	  '--append-confdir'.
+
 2014-05-07  James Hunt  <[email protected]>
 
 	* Convert calls to deprecated json_object_object_get() to
 	  json_object_object_get_ex().
 
+2014-05-02  James Hunt  <[email protected]>
+
+	* init/main.c: main(): Allow System Init read from multiple
+	  configuration to directories like a Session Init (LP: #1315060).
+	* init/man/init.5: Clarify default directory.
+	* init/man/init.8: Explain new behaviour.
+	* init/tests/test_main.c: test_confdir(): Update tests for new
+	  '--confdir' behaviour of System init.
+
 2014-04-24  James Hunt  <[email protected]>
 
 	* init/man/init.5:

=== modified file 'init/main.c'
--- init/main.c	2014-04-11 21:15:39 +0000
+++ init/main.c	2014-05-09 09:57:49 +0000
@@ -1,6 +1,6 @@
 /* upstart
  *
- * Copyright © 2009-2011 Canonical Ltd.
+ * Copyright  2009-2011 Canonical Ltd.
  * Author: Scott James Remnant <[email protected]>.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -85,10 +85,11 @@
 static void usr1_handler    (void *data, NihSignal *signal);
 #endif /* DEBUG */
 
-static void handle_confdir      (void);
-static void handle_logdir       (void);
-static int  console_type_setter (NihOption *option, const char *arg);
-static int  conf_dir_setter     (NihOption *option, const char *arg);
+static void handle_confdir         (void);
+static void handle_logdir          (void);
+static int  console_type_setter    (NihOption *option, const char *arg);
+static int  conf_dir_setter        (NihOption *option, const char *arg);
+static int  append_conf_dir_setter (NihOption *option, const char *arg);
 
 
 /**
@@ -107,6 +108,14 @@
 static char **conf_dirs = NULL;
 
 /**
+ * append_conf_dirs:
+ *
+ * Array of full paths to job configuration file directories that will
+ * be added to conf_dirs.
+ **/
+static char **append_conf_dirs = NULL;
+
+/**
  * initial_event:
  *
  * Alternate event to emit at startup (rather than STARTUP_EVENT).
@@ -146,6 +155,9 @@
  * Command-line options we accept.
  **/
 static NihOption options[] = {
+	{ 0, "append-confdir", N_("specify additional directory to load configuration files from"),
+		NULL, "DIR", NULL, append_conf_dir_setter },
+
 	{ 0, "confdir", N_("specify alternative directory to load configuration files from"),
 		NULL, "DIR", NULL, conf_dir_setter },
 
@@ -205,6 +217,7 @@
 	int    ret;
 
 	conf_dirs = NIH_MUST (nih_str_array_new (NULL));
+	append_conf_dirs = NIH_MUST (nih_str_array_new (NULL));
 
 	args_copy = NIH_MUST (nih_str_array_copy (NULL, NULL, argv));
 
@@ -568,24 +581,14 @@
 
 	/* Read configuration */
 	if (! user_mode) {
-		char   *conf_dir;
-		int     len = 0;
-
 		nih_assert (conf_dirs[0]);
 
-		/* Count entries */
-		for (char **d = conf_dirs; d && *d; d++, len++)
-			;
-
-		nih_assert (len);
-
-		/* Use last value specified */
-		conf_dir = conf_dirs[len-1];
-
 		NIH_MUST (conf_source_new (NULL, CONFFILE, CONF_FILE));
 
-		nih_debug ("Using configuration directory %s", conf_dir);
-		NIH_MUST (conf_source_new (NULL, conf_dir, CONF_JOB_DIR));
+		for (char **d = conf_dirs; d && *d; d++) {
+			nih_debug ("Using configuration directory %s", *d);
+			NIH_MUST (conf_source_new (NULL, *d, CONF_JOB_DIR));
+		}
 	} else {
 		nih_local char **dirs = NULL;
 
@@ -597,7 +600,15 @@
 		}
 	}
 
+	if (append_conf_dirs[0]) {
+		for (char **d = append_conf_dirs; d && *d; d++) {
+			nih_debug ("Adding configuration directory %s", *d);
+			NIH_MUST (conf_source_new (NULL, *d, CONF_JOB_DIR));
+		}
+	}
+
 	nih_free (conf_dirs);
+	nih_free (append_conf_dirs);
 
 	job_class_environment_init ();
 
@@ -1105,3 +1116,20 @@
 
 	return 0;
 }
+
+/**  
+ * NihOption setter function to handle selection of configuration file
+ * directories.
+ *
+ * Returns: 0 on success, -1 on invalid console type.
+ **/
+static int
+append_conf_dir_setter (NihOption *option, const char *arg)
+{
+	nih_assert (append_conf_dirs);
+	nih_assert (option);
+
+	NIH_MUST (nih_str_array_add (&append_conf_dirs, NULL, NULL, arg));
+
+	return 0;
+}

=== modified file 'init/man/init.5'
--- init/man/init.5	2014-04-24 12:39:18 +0000
+++ init/man/init.5	2014-05-09 09:57:49 +0000
@@ -22,7 +22,7 @@
 .BR init (8)
 daemon reads its job configuration from files in the
 .I /etc/init/
-directory, and watches for future changes to these files using
+directory by default, and watches for future changes to these files using
 .BR inotify (7).
 
 If Upstart was invoked as a user process with \-\-user option, it will

=== modified file 'init/man/init.8'
--- init/man/init.8	2013-12-23 17:31:22 +0000
+++ init/man/init.8	2014-05-09 09:57:49 +0000
@@ -253,14 +253,39 @@
 by placing them on the kernel command-line.
 .\"
 .TP
+.B \-\-append-confdir \fIdirectory\fP
+Add the specified directory to the default directory or directories
+that job configuration files will be read from. This option may be
+specified multiple times  which will result in job configuration files
+being loaded from each directory specified (which must exist).
+Directories will be searched for jobs in the specified order after the
+default directories have been searched.
+
+Note that if this option is used in combination with
+.BR \-\-confdir ","
+regardless of the order of the options on the command-line, the append
+directories will be added
+.I after
+the other directories.
+.\"
+.TP
 .B \-\-confdir \fIdirectory\fP
 Read job configuration files from a directory other than the default
-(\fI/etc/init\fP for process ID 1).
-
-When running as process ID 1, the last directory specified will be used.
-
-In user session mode, multiple directories will be honoured and job
-configuration files loaded from the directories in the order specified.
+(\fI/etc/init\fP for process ID 1). This option may be specified
+multiple times which will result in job configuration files being
+loaded from each directory specified (which must exist). Directories
+will be searched for jobs in the specified order.
+
+In the case that multiple directories specify a job of the same name,
+the first job encountered will be honoured.
+
+See section
+.B User Session Mode
+in
+.BR init (5)
+for the ordered list of default configuration directories a
+Session Init will consider.
+
 .\"
 .TP
 .B \-\-default-console \fIvalue\fP

=== modified file 'init/tests/test_main.c'
--- init/tests/test_main.c	2013-11-12 12:17:30 +0000
+++ init/tests/test_main.c	2014-05-09 09:57:49 +0000
@@ -46,6 +46,8 @@
 {
 	char             confdir_a[PATH_MAX];
 	char             confdir_b[PATH_MAX];
+	char             confdir_c[PATH_MAX];
+	char             confdir_d[PATH_MAX];
 	char            *xdg_config_home;
 	char            *xdg_runtime_dir;
 	char             logdir[PATH_MAX];
@@ -58,8 +60,10 @@
 	nih_local char  *session_file = NULL;
 	nih_local char  *path = NULL;
 
-	/* space for 2 sets of confdir options and a terminator */
-	char            *extra[5];
+	/* space for 2 sets of confdir options, 2 sets of
+	 * append-confdirs and a terminator.
+	 */
+	char            *extra[9];
 
 	xdg_config_home = getenv ("XDG_CONFIG_HOME");
 	TEST_NE_P (xdg_config_home, NULL);
@@ -75,6 +79,12 @@
 	TEST_FILENAME (confdir_b);
 	assert0 (mkdir (confdir_b, 0755));
 
+	TEST_FILENAME (confdir_c);
+	assert0 (mkdir (confdir_c, 0755));
+
+	TEST_FILENAME (confdir_d);
+	assert0 (mkdir (confdir_d, 0755));
+
 	xdg_conf_dir = nih_sprintf (NULL, "%s/%s", xdg_config_home, "upstart");
 	TEST_NE_P (xdg_conf_dir, NULL);
 	assert0 (mkdir (xdg_conf_dir, 0755));
@@ -151,6 +161,41 @@
 	assert0 (unlink (session_file));
 
 	/************************************************************/
+	TEST_FEATURE ("Session Init with --append-confdir");
+
+	CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true");
+	CREATE_FILE (confdir_a, "conf_dir_job.conf", "exec true");
+
+	extra[0] = "--append-confdir";
+	extra[1] = confdir_a;
+	extra[2] = NULL;
+
+	start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
+
+	/* Should be running */
+	assert0 (kill (upstart_pid, 0));
+
+	session_file = get_session_file (xdg_runtime_dir, upstart_pid);
+
+	cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	qsort (output, lines, sizeof (output[0]), strcmp_compar);
+
+	/* jobs in xdg_conf_dir should be considered */
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "conf_dir_job stop/waiting");
+	TEST_STR_MATCH (output[1], "xdg_dir_job stop/waiting");
+	nih_free (output);
+
+	DELETE_FILE (xdg_conf_dir, "xdg_dir_job.conf");
+	DELETE_FILE (confdir_a, "conf_dir_job.conf");
+
+	STOP_UPSTART (upstart_pid);
+	assert0 (unlink (session_file));
+
+	/************************************************************/
 	TEST_FEATURE ("Session Init with multiple --confdir");
 
 	CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true");
@@ -191,6 +236,47 @@
 	assert0 (unlink (session_file));
 
 	/************************************************************/
+	TEST_FEATURE ("Session Init with multiple --append-confdir");
+
+	CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true");
+	CREATE_FILE (confdir_a, "conf_dir_a_job.conf", "exec true");
+	CREATE_FILE (confdir_b, "conf_dir_b_job.conf", "exec true");
+
+	extra[0] = "--append-confdir";
+	extra[1] = confdir_a;
+	extra[2] = "--append-confdir";
+	extra[3] = confdir_b;
+	extra[4] = NULL;
+
+	/* pass 2 confdir directories */
+	start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
+
+	/* Should be running */
+	assert0 (kill (upstart_pid, 0));
+
+	session_file = get_session_file (xdg_runtime_dir, upstart_pid);
+
+	cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	qsort (output, lines, sizeof (output[0]), strcmp_compar);
+
+	/* jobs in xdg_conf_dir should be considered */
+	TEST_EQ (lines, 3);
+	TEST_STR_MATCH (output[0], "conf_dir_a_job stop/waiting");
+	TEST_STR_MATCH (output[1], "conf_dir_b_job stop/waiting");
+	TEST_STR_MATCH (output[2], "xdg_dir_job stop/waiting");
+	nih_free (output);
+
+	DELETE_FILE (xdg_conf_dir, "xdg_dir_job.conf");
+	DELETE_FILE (confdir_a, "conf_dir_a_job.conf");
+	DELETE_FILE (confdir_b, "conf_dir_b_job.conf");
+
+	STOP_UPSTART (upstart_pid);
+	assert0 (unlink (session_file));
+
+	/************************************************************/
 	TEST_FEATURE ("Session Init with multiple --confdir and conflicting names");
 
 	CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir");
@@ -241,6 +327,162 @@
 	assert0 (unlink (session_file));
 
 	/************************************************************/
+	TEST_FEATURE ("Session Init with multiple --append-confdir and conflicting names");
+
+	CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir");
+	CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a");
+	CREATE_FILE (confdir_b, "foo.conf", "exec true");
+
+	extra[0] = "--append-confdir";
+	extra[1] = confdir_a;
+	extra[2] = "--append-confdir";
+	extra[3] = confdir_b;
+	extra[4] = NULL;
+
+	/* pass 2 confdir directories */
+	start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
+
+	/* Should be running */
+	assert0 (kill (upstart_pid, 0));
+
+	session_file = get_session_file (xdg_runtime_dir, upstart_pid);
+
+	cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	qsort (output, lines, sizeof (output[0]), strcmp_compar);
+
+	/* We expect jobs in xdg_conf_dir to be ignored */
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "conflict stop/waiting");
+	TEST_STR_MATCH (output[1], "foo stop/waiting");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	/* Ensure the correct version of the conflict job is found */
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "conflict");
+	TEST_STR_MATCH (output[1], "  emits xdg_conf_dir");
+	nih_free (output);
+
+	DELETE_FILE (xdg_conf_dir, "conflict.conf");
+	DELETE_FILE (confdir_a, "conflict.conf");
+	DELETE_FILE (confdir_b, "foo.conf");
+
+	STOP_UPSTART (upstart_pid);
+	assert0 (unlink (session_file));
+
+	/************************************************************/
+	TEST_FEATURE ("Session Init with multiple --confdir and multiple --append-confdir and conflicting names");
+
+	CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir");
+	CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a");
+	CREATE_FILE (confdir_b, "foo.conf", "exec true");
+	CREATE_FILE (confdir_c, "conflict.conf", "emits confdir_c");
+
+	extra[0] = "--confdir";
+	extra[1] = confdir_a;
+	extra[2] = "--confdir";
+	extra[3] = confdir_b;
+	extra[4] = "--append-confdir";
+	extra[5] = confdir_c;
+	extra[6] = NULL;
+
+	start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
+
+	/* Should be running */
+	assert0 (kill (upstart_pid, 0));
+
+	session_file = get_session_file (xdg_runtime_dir, upstart_pid);
+
+	cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	qsort (output, lines, sizeof (output[0]), strcmp_compar);
+
+	/* We expect jobs in xdg_conf_dir to be ignored */
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "conflict stop/waiting");
+	TEST_STR_MATCH (output[1], "foo stop/waiting");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	/* Ensure the correct version of the conflict job is found */
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "conflict");
+	TEST_STR_MATCH (output[1], "  emits confdir_a");
+	nih_free (output);
+
+	DELETE_FILE (xdg_conf_dir, "conflict.conf");
+	DELETE_FILE (confdir_a, "conflict.conf");
+	DELETE_FILE (confdir_b, "foo.conf");
+	DELETE_FILE (confdir_c, "conflict.conf");
+
+	STOP_UPSTART (upstart_pid);
+	assert0 (unlink (session_file));
+
+	/************************************************************/
+	TEST_FEATURE ("Session Init with multiple out of order --confdir and --append-confdir");
+
+	CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir");
+	CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a");
+	CREATE_FILE (confdir_b, "foo.conf", "exec true");
+	CREATE_FILE (confdir_c, "conflict.conf", "emits confdir_c");
+
+	extra[0] = "--append-confdir";
+	extra[1] = confdir_a;
+	extra[2] = "--confdir";
+	extra[3] = confdir_b;
+	extra[4] = "--confdir";
+	extra[5] = confdir_c;
+	extra[6] = NULL;
+
+	start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra);
+
+	/* Should be running */
+	assert0 (kill (upstart_pid, 0));
+
+	session_file = get_session_file (xdg_runtime_dir, upstart_pid);
+
+	cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	qsort (output, lines, sizeof (output[0]), strcmp_compar);
+
+	/* We expect jobs in xdg_conf_dir to be ignored */
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "conflict stop/waiting");
+	TEST_STR_MATCH (output[1], "foo stop/waiting");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	/* Ensure the correct version of the conflict job is found */
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "conflict");
+	TEST_STR_MATCH (output[1], "  emits confdir_c");
+	nih_free (output);
+
+	DELETE_FILE (xdg_conf_dir, "conflict.conf");
+	DELETE_FILE (confdir_a, "conflict.conf");
+	DELETE_FILE (confdir_b, "foo.conf");
+	DELETE_FILE (confdir_c, "conflict.conf");
+
+	STOP_UPSTART (upstart_pid);
+	assert0 (unlink (session_file));
+
+	/************************************************************/
 	TEST_FEATURE ("System Init without --confdir");
 
 	/* Use the "secret" interface */
@@ -305,6 +547,36 @@
 	STOP_UPSTART (upstart_pid);
 
 	/************************************************************/
+	TEST_FEATURE ("System Init with --append-confdir");
+
+	TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf"));
+
+	CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "exec true");
+
+	extra[0] = "--append-confdir";
+	extra[1] = confdir_a;
+	extra[2] = NULL;
+
+	start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
+
+	/* Should be running */
+	assert0 (kill (upstart_pid, 0));
+
+	cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	qsort (output, lines, sizeof (output[0]), strcmp_compar);
+
+	TEST_EQ (lines, 1);
+	TEST_STR_MATCH (output[0], "must-not-exist-by-default stop/waiting");
+	nih_free (output);
+
+	DELETE_FILE (confdir_a, "must-not-exist-by-default.conf");
+
+	STOP_UPSTART (upstart_pid);
+
+	/************************************************************/
 	TEST_FEATURE ("System Init with multiple --confdir");
 
 	assert0 (setenv ("UPSTART_CONFDIR", xdg_conf_dir, 1));
@@ -331,14 +603,14 @@
 
 	qsort (output, lines, sizeof (output[0]), strcmp_compar);
 
-	TEST_EQ (lines, 2);
-	/* XXX: Only the last instance of --confdir should be honoured.
-	 *
-	 * This behaviour deviates from running as a Session Init where *all*
-	 * --confdir's specified are used.
+	/* Like a Session Init, the System Init behaviour is (now) to
+	 * honour all --confdirs.
 	 */
-	TEST_STR_MATCH (output[0], "baz stop/waiting");
-	TEST_STR_MATCH (output[1], "qux stop/waiting");
+	TEST_EQ (lines, 3);
+
+	TEST_STR_MATCH (output[0], "bar stop/waiting");
+	TEST_STR_MATCH (output[1], "baz stop/waiting");
+	TEST_STR_MATCH (output[2], "qux stop/waiting");
 	nih_free (output);
 
 	DELETE_FILE (xdg_conf_dir, "foo.conf");
@@ -349,6 +621,51 @@
 	STOP_UPSTART (upstart_pid);
 
 	/************************************************************/
+	TEST_FEATURE ("System Init with multiple --append-confdir");
+
+	TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf"));
+	TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default2.conf"));
+
+	CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "exec true");
+	CREATE_FILE (confdir_b, "must-not-exist-by-default2.conf", "exec true");
+
+	extra[0] = "--append-confdir";
+	extra[1] = confdir_a;
+	extra[2] = "--append-confdir";
+	extra[3] = confdir_b;
+	extra[4] = NULL;
+
+	start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
+
+	/* Should be running */
+	assert0 (kill (upstart_pid, 0));
+
+	cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	qsort (output, lines, sizeof (output[0]), strcmp_compar);
+
+	TEST_EQ (lines, 1);
+	TEST_STR_MATCH (output[0], "must-not-exist-by-default stop/waiting");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default2");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	qsort (output, lines, sizeof (output[0]), strcmp_compar);
+
+	TEST_EQ (lines, 1);
+	TEST_STR_MATCH (output[0], "must-not-exist-by-default2 stop/waiting");
+	nih_free (output);
+
+	DELETE_FILE (confdir_a, "must-not-exist-by-default.conf");
+	DELETE_FILE (confdir_b, "must-not-exist-by-default2.conf");
+
+	STOP_UPSTART (upstart_pid);
+
+	/************************************************************/
 	TEST_FEATURE ("System Init with multiple --confdir and conflicting names");
 
 	assert0 (setenv ("UPSTART_CONFDIR", xdg_conf_dir, 1));
@@ -363,6 +680,7 @@
 	extra[3] = confdir_b;
 	extra[4] = NULL;
 
+	/* pass 2 confdir directories */
 	start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
 
 	/* Should be running */
@@ -375,7 +693,6 @@
 	qsort (output, lines, sizeof (output[0]), strcmp_compar);
 
 	TEST_EQ (lines, 1);
-	/* only the last instance of --confdir should be honoured */
 	TEST_STR_MATCH (output[0], "conflict stop/waiting");
 	nih_free (output);
 
@@ -386,7 +703,7 @@
 	/* Ensure the correct version of the conflict job is found */
 	TEST_EQ (lines, 2);
 	TEST_STR_MATCH (output[0], "conflict");
-	TEST_STR_MATCH (output[1], "  emits confdir_b");
+	TEST_STR_MATCH (output[1], "  emits confdir_a");
 	nih_free (output);
 
 	DELETE_FILE (xdg_conf_dir, "conflict.conf");
@@ -396,11 +713,113 @@
 	STOP_UPSTART (upstart_pid);
 
 	/************************************************************/
+	TEST_FEATURE ("System Init with multiple --append-confdir and conflicting names");
+
+	TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf"));
+
+	CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "emits confdir_a");
+	CREATE_FILE (confdir_b, "must-not-exist-by-default.conf", "emits confdir_b");
+
+	extra[0] = "--append-confdir";
+	extra[1] = confdir_a;
+	extra[2] = "--append-confdir";
+	extra[3] = confdir_b;
+	extra[4] = NULL;
+
+	start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
+
+	/* Should be running */
+	assert0 (kill (upstart_pid, 0));
+
+	cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "must-not-exist-by-default");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	/* Ensure the correct version of the conflict job is found */
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "must-not-exist-by-default");
+	TEST_STR_MATCH (output[1], "  emits confdir_a");
+	nih_free (output);
+
+	DELETE_FILE (confdir_a, "must-not-exist-by-default.conf");
+	DELETE_FILE (confdir_b, "must-not-exist-by-default.conf");
+
+	STOP_UPSTART (upstart_pid);
+
+	/************************************************************/
+	TEST_FEATURE ("System Init with multiple out of order --confdir and --append-confdir");
+
+	CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a");
+	CREATE_FILE (confdir_a, "wibble.conf", "emits wobble");
+	CREATE_FILE (confdir_b, "conflict.conf", "emits confdir_b");
+	CREATE_FILE (confdir_c, "conflict.conf", "emits confdir_c");
+	CREATE_FILE (confdir_d, "foo.conf", "emits hello");
+
+	extra[0] = "--append-confdir";
+	extra[1] = confdir_a;
+	extra[2] = "--append-confdir";
+	extra[3] = confdir_b;
+	extra[4] = "--confdir";
+	extra[5] = confdir_c;
+	extra[6] = "--confdir";
+	extra[7] = confdir_d;
+	extra[8] = NULL;
+
+	start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra);
+
+	/* Should be running */
+	assert0 (kill (upstart_pid, 0));
+
+	cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+
+	qsort (output, lines, sizeof (output[0]), strcmp_compar);
+
+	TEST_EQ (lines, 3);
+	TEST_STR_MATCH (output[0], "conflict stop/waiting");
+	TEST_STR_MATCH (output[1], "foo stop/waiting");
+	TEST_STR_MATCH (output[2], "wibble stop/waiting");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "conflict");
+	TEST_STR_MATCH (output[1], "  emits confdir_c");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "wibble");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "wibble");
+	TEST_STR_MATCH (output[1], "  emits wobble");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "foo");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &lines);
+	TEST_EQ (lines, 2);
+	TEST_STR_MATCH (output[0], "foo");
+	TEST_STR_MATCH (output[1], "  emits hello");
+	nih_free (output);
+
+	DELETE_FILE (confdir_a, "conflict.conf");
+	DELETE_FILE (confdir_a, "wibble.conf");
+	DELETE_FILE (confdir_b, "conflict.conf");
+	DELETE_FILE (confdir_c, "conflict.conf");
+	DELETE_FILE (confdir_d, "foo.conf");
+
+	STOP_UPSTART (upstart_pid);
 
 	TEST_DBUS_END (dbus_pid);
 
 	assert0 (rmdir (confdir_a));
 	assert0 (rmdir (confdir_b));
+	assert0 (rmdir (confdir_c));
+	assert0 (rmdir (confdir_d));
 	assert0 (rmdir (xdg_conf_dir));
 	assert0 (rmdir (logdir));
 	assert0 (unsetenv ("UPSTART_CONFDIR"));

-- 
upstart-devel mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/upstart-devel

Reply via email to