Merge authors:
  Dmitrijs Ledkovs (xnox)
Related merge proposals:
  https://code.launchpad.net/~xnox/upstart/overrides/+merge/141914
  proposed by: Dmitrijs Ledkovs (xnox)
  review: Approve - James Hunt (jamesodhunt)
------------------------------------------------------------
revno: 1423 [merge]
committer: James Hunt <[email protected]>
branch nick: upstart
timestamp: Tue 2013-01-08 16:28:57 +0000
message:
  Merge of lp:~xnox/upstart/overrides.
modified:
  ChangeLog
  init/conf.c
  init/tests/test_conf.c
  init/tests/test_conf_static.c


--
lp:upstart
https://code.launchpad.net/~upstart-devel/upstart/trunk

Your team Upstart Reviewers is subscribed to branch lp:upstart.
To unsubscribe from this branch go to 
https://code.launchpad.net/~upstart-devel/upstart/trunk/+edit-subscription
=== modified file 'ChangeLog'
--- ChangeLog	2012-12-18 09:02:24 +0000
+++ ChangeLog	2013-01-08 10:27:17 +0000
@@ -1,3 +1,11 @@
+2013-01-04  Dmitrijs Ledkovs  <[email protected]>
+
+	* init/conf.c: add ability to apply override files from higher
+	  priority configuration sources.
+	* init/tests/test_conf.c: test that multiple override files are
+	  correctly applied and removed.
+	* init/tests/test_conf_static.c: test override file detection.
+
 2012-12-17  James Hunt  <[email protected]>
 
 	* init/man/init.5: Document that User Jobs are not supported

=== modified file 'init/conf.c'
--- init/conf.c	2012-12-19 12:46:46 +0000
+++ init/conf.c	2013-01-08 16:15:46 +0000
@@ -2,7 +2,7 @@
  *
  * conf.c - configuration management
  *
- * Copyright © 2009,2010,2011 Canonical Ltd.
+ * Copyright © 2009,2010,2011,2012,2013 Canonical Ltd.
  * Author: Scott James Remnant <[email protected]>.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -86,6 +86,14 @@
 static inline char *toggle_conf_name   (const void *parent, const char *path)
 	__attribute__ ((warn_unused_result, malloc));
 
+static inline char * conf_to_job_name  (const char *source_path,
+                                        const char *conf_path)
+	__attribute__ ((malloc, warn_unused_result));
+
+static char * conf_get_best_override   (const char *name,
+                                        const ConfSource *last_source)
+	__attribute__ ((malloc, warn_unused_result));
+
 /**
  * conf_sources:
  *
@@ -110,6 +118,8 @@
 static inline int
 is_conf_file_std (const char *path)
 {
+	nih_assert (path != NULL);
+
 	char *ptr = strrchr (path, '.');
 
 	if (ptr && IS_CONF_EXT_STD (ptr))
@@ -132,6 +142,8 @@
 static inline int
 is_conf_file_override (const char *path)
 {
+	nih_assert (path != NULL);
+
 	char *ptr = strrchr (path, '.');
 
 	if (ptr && IS_CONF_EXT_OVERRIDE (ptr))
@@ -154,6 +166,8 @@
 static inline int
 is_conf_file (const char *path)
 {
+	nih_assert (path != NULL);
+
 	char *ptr = strrchr (path, '.');
 
 	if (ptr && (ptr > path) && (ptr[-1] != '/') && IS_CONF_EXT (ptr))
@@ -163,6 +177,99 @@
 }
 
 /**
+ * conf_to_job_name:
+ * @source_path: path to ConfSource
+ * @conf_path: path to configuration file
+ *
+ * Constructs the job name for a given @conf_path. Removes
+ * @source_path directory name from the front of @conf_path and
+ * extension from the end.
+ *
+ * Returns: newly-allocated name.
+ *
+ **/
+static inline char *
+conf_to_job_name (const char * source_path, const char * conf_path)
+{
+	const char *start, *end;
+	char       *name = NULL;
+	int        source_len;
+
+	nih_assert (source_path != NULL);
+	nih_assert (conf_path != NULL);
+
+	start = conf_path;
+	source_len = strlen (source_path);
+
+	if (! strncmp (start, source_path, source_len))
+		start += source_len;
+
+	while (*start == '/')
+		start++;
+
+	end = strrchr (start, '.');
+	if (end && IS_CONF_EXT (end))
+		name = NIH_MUST (nih_strndup (NULL, start, end - start));
+	else
+		name = NIH_MUST (nih_strdup (NULL, start));
+
+	return name;
+}
+
+
+/**
+ * conf_get_best_override:
+ * @conf_file: conf_file object
+ *
+ * Given a @conf_file iterate over all config sources & find the
+ * first applicable override file. It will not look for override files
+ * beyond the @conf_file's ConfSource.
+ *
+ * Returns: newly allocated path to override file or NULL.
+ **/
+static char *
+conf_get_best_override (const char *name, const ConfSource *last_source)
+{
+	char         *try_path=NULL;
+	struct stat   statbuf;
+
+	nih_assert (name != NULL);
+	nih_assert (last_source != NULL);
+
+	NIH_LIST_FOREACH (conf_sources, iter) {
+
+		ConfSource *source = (ConfSource *)iter;
+
+		/* Look at directories only */
+		if (source->type == CONF_FILE)
+			continue;
+
+		/* Reclaim memory */
+		if (try_path)
+			nih_free (try_path);
+
+		/* construct path */
+		try_path = NIH_MUST (nih_sprintf (NULL, "%s/%s%s", source->path, name, CONF_EXT_OVERRIDE));
+
+		/* Found it! */
+		if (lstat (try_path, &statbuf) == 0 && S_ISREG (statbuf.st_mode))
+			return try_path;
+
+		/* Warning, you have reached the end of the conveyor!
+		 * Ignore overrides beyond .conf itself.
+		 */
+		if (source == last_source)
+			break;
+	}
+
+	if (try_path)
+		nih_free (try_path);
+
+	return NULL;
+}
+
+
+/**
  * Convert a configuration file name to an override file name and vice
  * versa.
  *
@@ -511,7 +618,7 @@
 
 	override_path = toggle_conf_name (NULL, source->path);
 
-	if (stat (override_path, &statbuf) != 0)
+	if (lstat (override_path, &statbuf) != 0)
 		return 0;
 
 	nih_debug ("Updating configuration for %s from %s",
@@ -670,6 +777,66 @@
 }
 
 /**
+ * conf_load_path_with_override:
+ * @source: configuration source
+ * @conf_path: path to config file
+ *
+ * Loads given @conf_path as a config file in a given @source. Then it
+ * finds an override file. If an override file is found it applies it
+ * as well.
+ **/
+static void
+conf_load_path_with_override (ConfSource *source,
+			      const char *conf_path)
+{
+	int                     ret = 0;
+	const char   *error_path = NULL;
+	char      *override_path = NULL;
+	nih_local char *job_name = NULL;
+
+	nih_assert (source != NULL);
+	nih_assert (conf_path != NULL);
+
+	/* reload conf file */
+	nih_debug ("Loading configuration file %s", conf_path);
+	ret = conf_reload_path (source, conf_path, NULL);
+	if (ret < 0) {
+		error_path = conf_path;
+		goto error;
+	}
+
+	job_name = conf_to_job_name (source->path, conf_path);
+	override_path = conf_get_best_override (job_name, source);
+	if (! override_path)
+		return;
+
+	/* overlay override settings */
+	nih_debug ("Loading override file %s for %s", conf_path, override_path);
+	ret = conf_reload_path (source, conf_path, override_path);
+	if (ret < 0) {
+		error_path = override_path;
+		goto error;
+	}
+	nih_free (override_path);
+	return;
+
+error:
+	{
+		NihError *err;
+
+		err = nih_error_get ();
+		nih_error ("%s: %s: %s", error_path,
+			   _("Error while loading configuration file"),
+			   err->message);
+		nih_free (err);
+		if (override_path)
+			nih_free (override_path);
+		return;
+	}
+}
+
+
+/**
  * conf_create_modify_handler:
  * @source: configuration source,
  * @watch: NihWatch for source,
@@ -693,85 +860,45 @@
 			    struct stat *statbuf)
 {
 	ConfFile *file = NULL;
-	const char *error_path = path;
-	nih_local char *new_path = NULL;
-	int ret;
+	char *config_path = NULL;
+	nih_local char *job_name = NULL;
 
 	nih_assert (source != NULL);
 	nih_assert (watch != NULL);
 	nih_assert (path != NULL);
-	nih_assert (statbuf != NULL);
 
 	/* note that symbolic links are ignored */
-	if (! S_ISREG (statbuf->st_mode))
-		return;
-
-	new_path = toggle_conf_name (NULL, path);
-	file = (ConfFile *)nih_hash_lookup (source->files, new_path);
-
-	if (is_conf_file_override (path)) {
-		if (! file) {
-			/* override file has no corresponding conf file */
-			nih_debug ("Ignoring orphan override file %s", path);
-			return;
-		}
-
-		/* reload conf file */
-		nih_debug ("Loading configuration file %s", new_path);
-		ret = conf_reload_path (source, new_path, NULL);
-		if (ret < 0) {
-			error_path = new_path;
-			goto error;
-		}
-
-		/* overlay override settings */
-		nih_debug ("Loading override file %s for %s", path, new_path);
-		ret = conf_reload_path (source, new_path, path);
-		if (ret < 0) {
-			error_path = path;
-			goto error;
-		}
-	} else {
-		nih_debug ("Loading configuration and override files for %s", path);
-
-		/* load conf file */
-		nih_debug ("Loading configuration file %s", path);
-		ret = conf_reload_path (source, path, NULL);
-		if (ret < 0) {
-			error_path = path;
-			goto error;
-		}
-
-		/* ensure we ignore directory changes (which won't have overrides. */
-		if (is_conf_file_std (path)) {
-			struct stat st;
-			if (stat (new_path, &st) == 0) {
-				/* overlay override settings */
-				nih_debug ("Loading override file %s for %s", new_path, path);
-				ret = conf_reload_path (source, path, new_path);
-				if (ret < 0) {
-					error_path = new_path;
-					goto error;
-				}
-			}
-
-		}
+	if (statbuf && ! S_ISREG (statbuf->st_mode))
+		return;
+
+	/* ignore non-config file changes */
+	if (! is_conf_file (path))
+		return;
+
+        /* For config file, load it and it's override file */
+	if (is_conf_file_std (path)) {
+		conf_load_path_with_override (source, path);
+		return;
+	}
+
+	/* For override files, reload all matching conf+override combos */
+	job_name = conf_to_job_name (source->path, path);
+	NIH_LIST_FOREACH (conf_sources, iter) {
+		ConfSource *source = (ConfSource *)iter;
+
+		if (source->type == CONF_FILE)
+			continue;
+
+		config_path = NIH_MUST (nih_sprintf (NULL, "%s/%s%s", source->path, job_name, CONF_EXT_STD));
+		file = (ConfFile *)nih_hash_lookup (source->files, config_path);
+		if (file) {
+			/* Find its override file and reload both */
+			conf_load_path_with_override (source, config_path);
+		}
+		nih_free (config_path);
 	}
 
 	return;
-
-error:
-	{
-		NihError *err;
-
-		err = nih_error_get ();
-		nih_error ("%s: %s: %s", error_path,
-				_("Error while loading configuration file"),
-				err->message);
-		nih_free (err);
-		if (file)
-			nih_unref (file, source);
-	}
 }
 
 /**
@@ -823,28 +950,19 @@
 
 	/* non-override files (and directories) are the simple case, so handle
 	 * them and leave.
-	 */ 
+	 */
 	if (! is_conf_file_override (path)) {
 		nih_unref (file, source);
 		return;
 	}
 
-	/* if an override file is deleted for which there is a corresponding
-	 * conf file, reload the conf file to remove any modifications
-	 * introduced by the override file.
+	/* Deleting override file is about the same as changing one.
+	 * We need to iterate across all matching jobs and reload them
+	 * with new "best" override file, if any.
 	 */
-	new_path = toggle_conf_name (NULL, path);
-	file = (ConfFile *)nih_hash_lookup (source->files, new_path);
-
-	if (file) {
-		nih_debug ("Reloading configuration for %s on deletion of overide (%s)",
-				new_path, path);
-
-		if ( conf_reload_path (source, new_path, NULL) < 0 ) {
-			nih_warn ("%s: %s", new_path,
-					_("Unable to reload configuration after override deletion"));
-		}
-	}
+	nih_debug ("Reloading configuration for matching configs on deletion of override (%s)",
+		   path);
+	conf_create_modify_handler (source, watch, path, NULL);
 }
 
 /**
@@ -867,64 +985,18 @@
 		   const char  *path,
 		   struct stat *statbuf)
 {
-	ConfFile *file = NULL;
-	nih_local char *new_path = NULL;
-
 	nih_assert (source != NULL);
 	nih_assert (dirname != NULL);
 	nih_assert (path != NULL);
 	nih_assert (statbuf != NULL);
 
-	/* We assume that CONF_EXT_STD files are visited before
-	 * CONF_EXT_OVERRIDE files. Happily, this assumption is currently
-	 * valid since CONF_EXT_STD comes before CONF_EXT_OVERRIDE if ordered
-	 * alphabetically.
-	 *
-	 * If this were ever to change (for example if we decided to
-	 * rename the CONF_EXT_OVERRIDE files to end in ".abc", say), the logic
-	 * in this function would be erroneous since it would never be possible when
-	 * visiting an override file (before a conf file) to lookup a conf file
-	 * in the hash, since the conf file would not yet have been seen and thus would
-	 * not exist in the hash (yet).
-	 */
-	nih_assert (CONF_EXT_STD[1] < CONF_EXT_OVERRIDE[1]);
-
 	if (! S_ISREG (statbuf->st_mode))
 		return 0;
 
-	if (is_conf_file_std (path)) {
-		if (conf_reload_path (source, path, NULL) < 0) {
-			NihError *err;
-
-			err = nih_error_get ();
-			nih_error ("%s: %s: %s", path,
-					_("Error while loading configuration file"),
-					err->message);
-			nih_free (err);
-		}
-		return 0;
-	}
-
-	new_path = toggle_conf_name (NULL, path);
-	file = (ConfFile *)nih_hash_lookup (source->files, new_path);
-
-	if (file) {
-		/* we're visiting an override file with an associated conf file that
-		 * has already been loaded, so just overlay the override file. If
-		 * there is no corresponding conf file, we ignore the override file.
-		 */
-		if (conf_reload_path (source, new_path, path) < 0) {
-			NihError *err;
-
-			err = nih_error_get ();
-			nih_error ("%s: %s: %s", new_path,
-					_("Error while reloading configuration file"),
-					err->message);
-			nih_free (err);
-		}
-	}
-
-	return 0;
+	if (is_conf_file_std (path))
+		conf_load_path_with_override (source, path);
+	
+	return 0;      
 }
 
 
@@ -957,7 +1029,6 @@
 {
 	ConfFile       *file = NULL;
 	nih_local char *buf = NULL;
-	const char     *start, *end;
 	nih_local char *name = NULL;
 	size_t          len, pos, lineno;
 	NihError       *err = NULL;
@@ -1014,23 +1085,8 @@
 
 		break;
 	case CONF_JOB_DIR:
-		/* Construct the job name by taking the path and removing
-		 * the directory name from the front and the extension
-		 * from the end.
-		 */
-		start = path;
-		if (! strncmp (start, source->path, strlen (source->path)))
-			start += strlen (source->path);
-
-		while (*start == '/')
-			start++;
-
-		end = strrchr (start, '.');
-		if (end && IS_CONF_EXT (end)) {
-			name = NIH_MUST (nih_strndup (NULL, start, end - start));
-		} else {
-			name = NIH_MUST (nih_strdup (NULL, start));
-		}
+
+		name = conf_to_job_name (source->path, path);
 
 		/* Create a new job item and parse the buffer to produce
 		 * the job definition.
@@ -1388,4 +1444,3 @@
 }
 
 #endif /* DEBUG */
-

=== modified file 'init/tests/test_conf.c'
--- init/tests/test_conf.c	2012-12-19 12:46:46 +0000
+++ init/tests/test_conf.c	2013-01-04 13:03:47 +0000
@@ -2424,7 +2424,8 @@
 	FILE       *f;
 	int         ret, fd[4096], i = 0;
 	char        dirname[PATH_MAX];
-	char        filename[PATH_MAX], override[PATH_MAX];
+	char        filename[PATH_MAX], override[PATH_MAX], override2[PATH_MAX];
+	char       *dir;
 	JobClass   *job;
 	NihError   *err;
 
@@ -3424,6 +3425,123 @@
 	unlink (filename);
 	TEST_EQ (rmdir (dirname), 0);
 
+	TEST_FEATURE ("create two watches, two overrides, conf, then delete override files one by one");
+	TEST_ENSURE_CLEAN_ENV ();
+	TEST_FILENAME (dirname);
+	TEST_EQ (mkdir (dirname, 0755), 0);
+
+	strcpy (override, dirname);
+	strcat (override, "/peter/foo.override");
+	strcpy (override2, dirname);
+	strcat (override2, "/paul/foo.override");
+	strcpy (filename, dirname);
+	strcat (filename, "/paul/foo.conf");
+
+	const char *sources[] = {"peter", "paul", NULL};
+
+	for (const char **src = sources; *src; src++) {
+		dir = nih_sprintf (NULL, "%s/%s", dirname, *src);
+		TEST_EQ (mkdir (dir, 0755), 0);
+		source = conf_source_new (NULL, dir, CONF_JOB_DIR);
+		TEST_NE_P (source, NULL);
+		ret = conf_source_reload (source);
+		TEST_EQ (ret, 0);
+		nih_free (dir);
+	}
+
+	TEST_FORCE_WATCH_UPDATE();
+
+	/* create override */
+	f = fopen (override, "w");
+	TEST_NE_P (f, NULL);
+	fprintf (f, "manual\n");
+	fprintf (f, "author \"peter\"\n");
+	fclose (f);
+
+	TEST_FORCE_WATCH_UPDATE();
+
+	/* create override */
+	f = fopen (override2, "w");
+	TEST_NE_P (f, NULL);
+	fprintf (f, "manual\n");
+	fprintf (f, "author \"paul\"\n");
+	fprintf (f, "env wibble=wobble\n");
+	fclose (f);
+
+	TEST_FORCE_WATCH_UPDATE();
+
+	/* create conf */
+	f = fopen (filename, "w");
+	TEST_NE_P (f, NULL);
+	fprintf (f, "start on started\n");
+	fprintf (f, "emits hello\n");
+	fprintf (f, "author \"mary\"\n");
+	fclose (f);
+
+	TEST_FORCE_WATCH_UPDATE();
+
+	/* ensure conf loaded */
+	file = (ConfFile *)nih_hash_lookup (source->files, filename);
+	TEST_NE_P (file, NULL);
+	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
+	TEST_NE_P (job, NULL);
+	TEST_EQ_P (file->job, job);
+	TEST_EQ_STR ((job->emits)[0], "hello");
+
+	/* should pick up the top-priority override, *NOT* conf */
+	TEST_EQ_P (job->start_on, NULL);
+	TEST_EQ_STR (job->author, "peter");
+
+	/* delete override */
+	unlink (override);
+
+	TEST_FORCE_WATCH_UPDATE();
+
+	/* ensure conf reloaded and updated with the second override */
+	file = (ConfFile *)nih_hash_lookup (source->files, filename);
+	TEST_NE_P (file, NULL);
+	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
+	TEST_NE_P (job, NULL);
+	TEST_EQ_P (file->job, job);
+	TEST_EQ_STR ((job->emits)[0], "hello");
+
+	/* should pick up the second override, *NOT* conf */
+	TEST_EQ_P (job->start_on, NULL);
+	TEST_EQ_STR (job->author, "paul");
+	TEST_EQ_STR ((job->env)[0], "wibble=wobble");
+
+	TEST_FORCE_WATCH_UPDATE();
+
+	/* delete override */
+	unlink (override2);
+
+	TEST_FORCE_WATCH_UPDATE();
+
+	/* ensure conf loaded */
+	file = (ConfFile *)nih_hash_lookup (source->files, filename);
+	TEST_NE_P (file, NULL);
+	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
+	TEST_NE_P (job, NULL);
+	TEST_EQ_P (file->job, job);
+	TEST_EQ_STR (job->author, "mary");
+	TEST_EQ_STR ((job->emits)[0], "hello");
+	TEST_NE_P (job->start_on, NULL);
+	TEST_EQ_P (job->env, NULL);
+
+	unlink (filename);
+
+	for (const char **src = sources; *src; src++) {
+		dir = nih_sprintf (NULL, "%s/%s", dirname, *src);
+		TEST_EQ (rmdir (dir), 0);
+		nih_free (dir);
+	}
+
+	TEST_EQ (rmdir (dirname), 0);
+
+	NIH_LIST_FOREACH_SAFE (conf_sources, iter) {
+		ConfSource *source = (ConfSource *)iter;
+		nih_free (source);
+	}
 
 	TEST_FEATURE ("create conf, watch, then create invalid override, delete override");
 	TEST_ENSURE_CLEAN_ENV ();

=== modified file 'init/tests/test_conf_static.c'
--- init/tests/test_conf_static.c	2012-12-19 12:46:46 +0000
+++ init/tests/test_conf_static.c	2013-01-04 13:03:47 +0000
@@ -34,8 +34,8 @@
 	char *f;
 	char *p;
 
-	TEST_FUNCTION_FEATURE ("toggle_conf_name",
-			"changing conf to override");
+	TEST_FUNCTION ("toggle_conf_name");
+	TEST_FEATURE ("changing conf to override");
 
 	TEST_FILENAME (dirname);
 	strcpy (filename, dirname);
@@ -71,11 +71,154 @@
 	nih_free (job);
 }
 
+void
+test_conf_to_job_name (void)
+{
+	char dirname[PATH_MAX];
+	char         *filename;
+	char             *name;
+
+	TEST_FUNCTION ("conf_to_job_name");
+	TEST_FEATURE ("with .conf file");
+	TEST_FILENAME (dirname);
+	filename = nih_sprintf (NULL, "%s/foo.conf", dirname);
+	name = conf_to_job_name (dirname, filename);
+	TEST_EQ_STR (name, "foo");
+	nih_free (filename);
+	nih_free (name);
+	
+	TEST_FEATURE ("with .override file");
+	filename = nih_sprintf (NULL, "%s/foo.override", dirname);
+	name = conf_to_job_name (dirname, filename);
+	TEST_EQ_STR (name, "foo");
+	nih_free (filename);
+	nih_free (name);
+
+	TEST_FEATURE ("with .conf in a sub-directory");
+	filename = nih_sprintf (NULL, "%s/foo/bar.conf", dirname);
+	name = conf_to_job_name (dirname, filename);
+	TEST_EQ_STR (name, "foo/bar");
+	nih_free (filename);
+	nih_free (name);
+	
+	TEST_FEATURE ("without extension");
+	filename = nih_sprintf (NULL, "%s/foo", dirname);
+	name = conf_to_job_name (dirname, filename);
+	TEST_EQ_STR (name, "foo");
+	nih_free (filename);
+	nih_free (name);
+
+}
+
+void
+test_conf_get_best_override (void)
+{
+	const char *sources[] = {"peter", "paul", "mary", NULL};
+	FILE                *f;
+	char dirname[PATH_MAX];
+	char              *dir;
+	char         *expected;
+	char             *path;
+
+	TEST_FUNCTION ("conf_get_best_override");
+
+	TEST_FILENAME (dirname);
+	mkdir (dirname, 0755);
+	
+	for (const char **src = sources; *src; src++) {
+		dir = nih_sprintf (NULL, "%s/%s", dirname, *src);
+		TEST_EQ (mkdir (dir, 0755), 0);
+		NIH_MUST (conf_source_new (NULL, dir, CONF_JOB_DIR));
+		nih_free (dir);
+	}
+
+	TEST_FEATURE ("with no overrides");
+	NIH_LIST_FOREACH (conf_sources, iter) {
+		ConfSource *source = (ConfSource *)iter;
+		path = conf_get_best_override ("foo", source);
+		TEST_EQ_P (path, NULL);
+	}
+
+	TEST_FEATURE ("with single highest priority override");
+	expected = nih_sprintf (NULL, "%s/%s/foo.override", dirname, sources[0]);
+	f = fopen (expected, "w");
+	TEST_NE_P (f, NULL);
+	TEST_EQ (fclose (f), 0);
+
+	NIH_LIST_FOREACH (conf_sources, iter) {
+		ConfSource *source = (ConfSource *)iter;
+		path = conf_get_best_override ("foo", source);
+		TEST_EQ_STR (path, expected);
+		nih_free (path);
+	}	
+	TEST_EQ (unlink (expected), 0);
+
+	TEST_FEATURE ("with single middle priority override");
+	expected = nih_sprintf (NULL, "%s/%s/foo.override", dirname, sources[1]);
+	f = fopen (expected, "w");
+	TEST_NE_P (f, NULL);
+	TEST_EQ (fclose (f), 0);
+
+	NIH_LIST_FOREACH (conf_sources, iter) {
+		ConfSource *source = (ConfSource *)iter;
+		path = conf_get_best_override ("foo", source);
+
+		/* Poor-man's basename(1) */
+		dir = conf_to_job_name (dirname, source->path);
+		if (strcmp (dir, sources[0]) == 0) {
+			TEST_EQ_P (path, NULL);
+		} else {
+			TEST_EQ_STR (path, expected);
+			nih_free (path);
+		}
+		nih_free (dir);
+	}	
+	TEST_EQ (unlink (expected), 0);
+
+	TEST_FEATURE ("with single lowest priority override");
+	expected = nih_sprintf (NULL, "%s/%s/foo.override", dirname, sources[2]);
+	f = fopen (expected, "w");
+	TEST_NE_P (f, NULL);
+	TEST_EQ (fclose (f), 0);
+
+	NIH_LIST_FOREACH (conf_sources, iter) {
+		ConfSource *source = (ConfSource *)iter;
+		path = conf_get_best_override ("foo", source);
+
+		/* Poor-man's basename(1) */
+		dir = conf_to_job_name (dirname, source->path);
+		if (strcmp (dir, sources[2]) == 0) {
+			TEST_EQ_STR (path, expected);
+			nih_free (path);
+		} else {
+			TEST_EQ_P (path, NULL);
+		}
+		nih_free (dir);
+	}	
+	TEST_EQ (unlink (expected), 0);
+
+	/* Clean up */
+	for (const char **src = sources; *src; src++) {
+		dir = nih_sprintf (NULL, "%s/%s", dirname, *src);
+		TEST_EQ (rmdir (dir), 0);
+		nih_free (dir);
+	}
+
+	TEST_EQ (rmdir (dirname), 0);
+
+	NIH_LIST_FOREACH_SAFE (conf_sources, iter) {
+		ConfSource *source = (ConfSource *)iter;
+		nih_free (source);
+	}
+}
+
 int
 main (int   argc,
       char *argv[])
 {
 	test_toggle_conf_name ();
+	test_conf_to_job_name ();
+	test_conf_get_best_override ();
 
 	return 0;
 }

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

Reply via email to