Merge lp:~xnox/upstart/overrides into lp:upstart

Proposed by Dimitri John Ledkov
Status: Merged
Merged at revision: 1423
Proposed branch: lp:~xnox/upstart/overrides
Merge into: lp:upstart
Diff against target: 814 lines (+484/-160)
4 files modified
ChangeLog (+8/-0)
init/conf.c (+212/-157)
init/tests/test_conf.c (+119/-1)
init/tests/test_conf_static.c (+145/-2)
To merge this branch: bzr merge lp:~xnox/upstart/overrides
Reviewer Review Type Date Requested Status
James Hunt Approve
Review via email: mp+141914@code.launchpad.net

Description of the change

This branch implements override files from any directory as specified here [1].

Instead of checking for a known path to .override file, a helper function `conf_get_best_override' is used that iterates across conf_sources and looks for the first .override file.

Next, I refactored another helper function conf_load_path_with_override that: loads a conf file, finds best override file for it & if found, applies it.

For the handlers we now have the following logic:
- if a .conf file is created/modified: simply call conf_load_path_with_override.
- if a .override file is created/modified/deleted: iterate across all conf_sources, check for "matching" .conf file and reload it with conf_load_path_with_override.
- if a .conf file is deleted: the behaviour is the same, unref the file from the ConfSource.

For system init, there shouldn't be much performance impact since there is only one directory to do lookups in.

For session init, most jobs will be in the lowest priority config_source. Thus resulting in lstat call in each config_source for each job to check for an .override file. But in practice, those higher priority config_sources may not even exist and lstat calls on non-existing directories is cheap. Potentially this can be micro-optimised by storing hashes of all found .override files while walking the config_sources and then instead of lstat check do a hash lookup...

[1] https://wiki.ubuntu.com/FoundationsTeam/Specs/RaringUpstartUserSessions#Configuration_Files_for_User_Jobs

To post a comment you must log in.
Revision history for this message
James Hunt (jamesodhunt) wrote :

Hi Dmitrijs,

* Changelog: Need extra indent for 'priority' and 'correctly'.
* init/conf.c:
  - Might just as well add ',2013' to copyright now :)
  - conf_to_job_name():
    - Typo: 'ConfigSource' should be 'ConfSource'.
    - Typo: 'from then' should be 'from the'.
    - You could drop the braces for the final if/else test, but they
      were there originally I guess :)
  - conf_get_best_override():
    - Typo: '& finds the' should be '& find the'.
    - Typo: 'for override file' should be 'for override files'.
    - Typo: 'ConfigSource' should be 'ConfSource'.
    - @name and @last_source are not asserted.
    - Using lstat(2) seems correct since we don't support symlinks on
      purpose, but conf_source_reload_file() is still using stat(2) so
      there is a discrepancy.
  - conf_load_path_with_override():
    - Need space around '=' in initial assignments.
    - 'if (override_path)' at line 818 technically redundant since we already know it
      cannot be NULL.
  - conf_create_modify_handler():
    - Missing check on return from nih_sprintf().
  - conf_delete_handler():
    - Typo: 'overide' rather than 'override'.

Regarding your comments on the lstat issue, we need to keep an eye on this. As you say, the impact should not be great, but it would still be worth performing some tests on a slow system to see if the new code makes any appreciable difference to performance.

review: Needs Fixing
lp:~xnox/upstart/overrides updated
1424. By Dimitri John Ledkov

Review comments

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

Addressed all comments.
Checking return status of nih_sprintf with NIH_MUST.
Converted conf_source_reload_file to use lstat as well.

lp:~xnox/upstart/overrides updated
1425. By Dimitri John Ledkov

;

Revision history for this message
James Hunt (jamesodhunt) wrote :

Thanks. LGTM - merged!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'ChangeLog'
--- ChangeLog 2012-12-18 09:02:24 +0000
+++ ChangeLog 2013-01-08 16:18:21 +0000
@@ -1,3 +1,11 @@
12013-01-04 Dmitrijs Ledkovs <xnox@ubuntu.com>
2
3 * init/conf.c: add ability to apply override files from higher
4 priority configuration sources.
5 * init/tests/test_conf.c: test that multiple override files are
6 correctly applied and removed.
7 * init/tests/test_conf_static.c: test override file detection.
8
12012-12-17 James Hunt <james.hunt@ubuntu.com>92012-12-17 James Hunt <james.hunt@ubuntu.com>
210
3 * init/man/init.5: Document that User Jobs are not supported11 * init/man/init.5: Document that User Jobs are not supported
412
=== modified file 'init/conf.c'
--- init/conf.c 2012-12-19 12:46:46 +0000
+++ init/conf.c 2013-01-08 16:18:21 +0000
@@ -2,7 +2,7 @@
2 *2 *
3 * conf.c - configuration management3 * conf.c - configuration management
4 *4 *
5 * Copyright © 2009,2010,2011 Canonical Ltd.5 * Copyright © 2009,2010,2011,2012,2013 Canonical Ltd.
6 * Author: Scott James Remnant <scott@netsplit.com>.6 * Author: Scott James Remnant <scott@netsplit.com>.
7 *7 *
8 * This program is free software; you can redistribute it and/or modify8 * This program is free software; you can redistribute it and/or modify
@@ -86,6 +86,14 @@
86static inline char *toggle_conf_name (const void *parent, const char *path)86static inline char *toggle_conf_name (const void *parent, const char *path)
87 __attribute__ ((warn_unused_result, malloc));87 __attribute__ ((warn_unused_result, malloc));
8888
89static inline char * conf_to_job_name (const char *source_path,
90 const char *conf_path)
91 __attribute__ ((malloc, warn_unused_result));
92
93static char * conf_get_best_override (const char *name,
94 const ConfSource *last_source)
95 __attribute__ ((malloc, warn_unused_result));
96
89/**97/**
90 * conf_sources:98 * conf_sources:
91 *99 *
@@ -110,6 +118,8 @@
110static inline int118static inline int
111is_conf_file_std (const char *path)119is_conf_file_std (const char *path)
112{120{
121 nih_assert (path != NULL);
122
113 char *ptr = strrchr (path, '.');123 char *ptr = strrchr (path, '.');
114124
115 if (ptr && IS_CONF_EXT_STD (ptr))125 if (ptr && IS_CONF_EXT_STD (ptr))
@@ -132,6 +142,8 @@
132static inline int142static inline int
133is_conf_file_override (const char *path)143is_conf_file_override (const char *path)
134{144{
145 nih_assert (path != NULL);
146
135 char *ptr = strrchr (path, '.');147 char *ptr = strrchr (path, '.');
136148
137 if (ptr && IS_CONF_EXT_OVERRIDE (ptr))149 if (ptr && IS_CONF_EXT_OVERRIDE (ptr))
@@ -154,6 +166,8 @@
154static inline int166static inline int
155is_conf_file (const char *path)167is_conf_file (const char *path)
156{168{
169 nih_assert (path != NULL);
170
157 char *ptr = strrchr (path, '.');171 char *ptr = strrchr (path, '.');
158172
159 if (ptr && (ptr > path) && (ptr[-1] != '/') && IS_CONF_EXT (ptr))173 if (ptr && (ptr > path) && (ptr[-1] != '/') && IS_CONF_EXT (ptr))
@@ -163,6 +177,99 @@
163}177}
164178
165/**179/**
180 * conf_to_job_name:
181 * @source_path: path to ConfSource
182 * @conf_path: path to configuration file
183 *
184 * Constructs the job name for a given @conf_path. Removes
185 * @source_path directory name from the front of @conf_path and
186 * extension from the end.
187 *
188 * Returns: newly-allocated name.
189 *
190 **/
191static inline char *
192conf_to_job_name (const char * source_path, const char * conf_path)
193{
194 const char *start, *end;
195 char *name = NULL;
196 int source_len;
197
198 nih_assert (source_path != NULL);
199 nih_assert (conf_path != NULL);
200
201 start = conf_path;
202 source_len = strlen (source_path);
203
204 if (! strncmp (start, source_path, source_len))
205 start += source_len;
206
207 while (*start == '/')
208 start++;
209
210 end = strrchr (start, '.');
211 if (end && IS_CONF_EXT (end))
212 name = NIH_MUST (nih_strndup (NULL, start, end - start));
213 else
214 name = NIH_MUST (nih_strdup (NULL, start));
215
216 return name;
217}
218
219
220/**
221 * conf_get_best_override:
222 * @conf_file: conf_file object
223 *
224 * Given a @conf_file iterate over all config sources & find the
225 * first applicable override file. It will not look for override files
226 * beyond the @conf_file's ConfSource.
227 *
228 * Returns: newly allocated path to override file or NULL.
229 **/
230static char *
231conf_get_best_override (const char *name, const ConfSource *last_source)
232{
233 char *try_path=NULL;
234 struct stat statbuf;
235
236 nih_assert (name != NULL);
237 nih_assert (last_source != NULL);
238
239 NIH_LIST_FOREACH (conf_sources, iter) {
240
241 ConfSource *source = (ConfSource *)iter;
242
243 /* Look at directories only */
244 if (source->type == CONF_FILE)
245 continue;
246
247 /* Reclaim memory */
248 if (try_path)
249 nih_free (try_path);
250
251 /* construct path */
252 try_path = NIH_MUST (nih_sprintf (NULL, "%s/%s%s", source->path, name, CONF_EXT_OVERRIDE));
253
254 /* Found it! */
255 if (lstat (try_path, &statbuf) == 0 && S_ISREG (statbuf.st_mode))
256 return try_path;
257
258 /* Warning, you have reached the end of the conveyor!
259 * Ignore overrides beyond .conf itself.
260 */
261 if (source == last_source)
262 break;
263 }
264
265 if (try_path)
266 nih_free (try_path);
267
268 return NULL;
269}
270
271
272/**
166 * Convert a configuration file name to an override file name and vice273 * Convert a configuration file name to an override file name and vice
167 * versa.274 * versa.
168 *275 *
@@ -511,7 +618,7 @@
511618
512 override_path = toggle_conf_name (NULL, source->path);619 override_path = toggle_conf_name (NULL, source->path);
513620
514 if (stat (override_path, &statbuf) != 0)621 if (lstat (override_path, &statbuf) != 0)
515 return 0;622 return 0;
516623
517 nih_debug ("Updating configuration for %s from %s",624 nih_debug ("Updating configuration for %s from %s",
@@ -670,6 +777,66 @@
670}777}
671778
672/**779/**
780 * conf_load_path_with_override:
781 * @source: configuration source
782 * @conf_path: path to config file
783 *
784 * Loads given @conf_path as a config file in a given @source. Then it
785 * finds an override file. If an override file is found it applies it
786 * as well.
787 **/
788static void
789conf_load_path_with_override (ConfSource *source,
790 const char *conf_path)
791{
792 int ret = 0;
793 const char *error_path = NULL;
794 char *override_path = NULL;
795 nih_local char *job_name = NULL;
796
797 nih_assert (source != NULL);
798 nih_assert (conf_path != NULL);
799
800 /* reload conf file */
801 nih_debug ("Loading configuration file %s", conf_path);
802 ret = conf_reload_path (source, conf_path, NULL);
803 if (ret < 0) {
804 error_path = conf_path;
805 goto error;
806 }
807
808 job_name = conf_to_job_name (source->path, conf_path);
809 override_path = conf_get_best_override (job_name, source);
810 if (! override_path)
811 return;
812
813 /* overlay override settings */
814 nih_debug ("Loading override file %s for %s", conf_path, override_path);
815 ret = conf_reload_path (source, conf_path, override_path);
816 if (ret < 0) {
817 error_path = override_path;
818 goto error;
819 }
820 nih_free (override_path);
821 return;
822
823error:
824 {
825 NihError *err;
826
827 err = nih_error_get ();
828 nih_error ("%s: %s: %s", error_path,
829 _("Error while loading configuration file"),
830 err->message);
831 nih_free (err);
832 if (override_path)
833 nih_free (override_path);
834 return;
835 }
836}
837
838
839/**
673 * conf_create_modify_handler:840 * conf_create_modify_handler:
674 * @source: configuration source,841 * @source: configuration source,
675 * @watch: NihWatch for source,842 * @watch: NihWatch for source,
@@ -693,85 +860,45 @@
693 struct stat *statbuf)860 struct stat *statbuf)
694{861{
695 ConfFile *file = NULL;862 ConfFile *file = NULL;
696 const char *error_path = path;863 char *config_path = NULL;
697 nih_local char *new_path = NULL;864 nih_local char *job_name = NULL;
698 int ret;
699865
700 nih_assert (source != NULL);866 nih_assert (source != NULL);
701 nih_assert (watch != NULL);867 nih_assert (watch != NULL);
702 nih_assert (path != NULL);868 nih_assert (path != NULL);
703 nih_assert (statbuf != NULL);
704869
705 /* note that symbolic links are ignored */870 /* note that symbolic links are ignored */
706 if (! S_ISREG (statbuf->st_mode))871 if (statbuf && ! S_ISREG (statbuf->st_mode))
707 return;872 return;
708873
709 new_path = toggle_conf_name (NULL, path);874 /* ignore non-config file changes */
710 file = (ConfFile *)nih_hash_lookup (source->files, new_path);875 if (! is_conf_file (path))
711876 return;
712 if (is_conf_file_override (path)) {877
713 if (! file) {878 /* For config file, load it and it's override file */
714 /* override file has no corresponding conf file */879 if (is_conf_file_std (path)) {
715 nih_debug ("Ignoring orphan override file %s", path);880 conf_load_path_with_override (source, path);
716 return;881 return;
717 }882 }
718883
719 /* reload conf file */884 /* For override files, reload all matching conf+override combos */
720 nih_debug ("Loading configuration file %s", new_path);885 job_name = conf_to_job_name (source->path, path);
721 ret = conf_reload_path (source, new_path, NULL);886 NIH_LIST_FOREACH (conf_sources, iter) {
722 if (ret < 0) {887 ConfSource *source = (ConfSource *)iter;
723 error_path = new_path;888
724 goto error;889 if (source->type == CONF_FILE)
725 }890 continue;
726891
727 /* overlay override settings */892 config_path = NIH_MUST (nih_sprintf (NULL, "%s/%s%s", source->path, job_name, CONF_EXT_STD));
728 nih_debug ("Loading override file %s for %s", path, new_path);893 file = (ConfFile *)nih_hash_lookup (source->files, config_path);
729 ret = conf_reload_path (source, new_path, path);894 if (file) {
730 if (ret < 0) {895 /* Find its override file and reload both */
731 error_path = path;896 conf_load_path_with_override (source, config_path);
732 goto error;897 }
733 }898 nih_free (config_path);
734 } else {
735 nih_debug ("Loading configuration and override files for %s", path);
736
737 /* load conf file */
738 nih_debug ("Loading configuration file %s", path);
739 ret = conf_reload_path (source, path, NULL);
740 if (ret < 0) {
741 error_path = path;
742 goto error;
743 }
744
745 /* ensure we ignore directory changes (which won't have overrides. */
746 if (is_conf_file_std (path)) {
747 struct stat st;
748 if (stat (new_path, &st) == 0) {
749 /* overlay override settings */
750 nih_debug ("Loading override file %s for %s", new_path, path);
751 ret = conf_reload_path (source, path, new_path);
752 if (ret < 0) {
753 error_path = new_path;
754 goto error;
755 }
756 }
757
758 }
759 }899 }
760900
761 return;901 return;
762
763error:
764 {
765 NihError *err;
766
767 err = nih_error_get ();
768 nih_error ("%s: %s: %s", error_path,
769 _("Error while loading configuration file"),
770 err->message);
771 nih_free (err);
772 if (file)
773 nih_unref (file, source);
774 }
775}902}
776903
777/**904/**
@@ -823,28 +950,19 @@
823950
824 /* non-override files (and directories) are the simple case, so handle951 /* non-override files (and directories) are the simple case, so handle
825 * them and leave.952 * them and leave.
826 */ 953 */
827 if (! is_conf_file_override (path)) {954 if (! is_conf_file_override (path)) {
828 nih_unref (file, source);955 nih_unref (file, source);
829 return;956 return;
830 }957 }
831958
832 /* if an override file is deleted for which there is a corresponding959 /* Deleting override file is about the same as changing one.
833 * conf file, reload the conf file to remove any modifications960 * We need to iterate across all matching jobs and reload them
834 * introduced by the override file.961 * with new "best" override file, if any.
835 */962 */
836 new_path = toggle_conf_name (NULL, path);963 nih_debug ("Reloading configuration for matching configs on deletion of override (%s)",
837 file = (ConfFile *)nih_hash_lookup (source->files, new_path);964 path);
838965 conf_create_modify_handler (source, watch, path, NULL);
839 if (file) {
840 nih_debug ("Reloading configuration for %s on deletion of overide (%s)",
841 new_path, path);
842
843 if ( conf_reload_path (source, new_path, NULL) < 0 ) {
844 nih_warn ("%s: %s", new_path,
845 _("Unable to reload configuration after override deletion"));
846 }
847 }
848}966}
849967
850/**968/**
@@ -867,64 +985,18 @@
867 const char *path,985 const char *path,
868 struct stat *statbuf)986 struct stat *statbuf)
869{987{
870 ConfFile *file = NULL;
871 nih_local char *new_path = NULL;
872
873 nih_assert (source != NULL);988 nih_assert (source != NULL);
874 nih_assert (dirname != NULL);989 nih_assert (dirname != NULL);
875 nih_assert (path != NULL);990 nih_assert (path != NULL);
876 nih_assert (statbuf != NULL);991 nih_assert (statbuf != NULL);
877992
878 /* We assume that CONF_EXT_STD files are visited before
879 * CONF_EXT_OVERRIDE files. Happily, this assumption is currently
880 * valid since CONF_EXT_STD comes before CONF_EXT_OVERRIDE if ordered
881 * alphabetically.
882 *
883 * If this were ever to change (for example if we decided to
884 * rename the CONF_EXT_OVERRIDE files to end in ".abc", say), the logic
885 * in this function would be erroneous since it would never be possible when
886 * visiting an override file (before a conf file) to lookup a conf file
887 * in the hash, since the conf file would not yet have been seen and thus would
888 * not exist in the hash (yet).
889 */
890 nih_assert (CONF_EXT_STD[1] < CONF_EXT_OVERRIDE[1]);
891
892 if (! S_ISREG (statbuf->st_mode))993 if (! S_ISREG (statbuf->st_mode))
893 return 0;994 return 0;
894995
895 if (is_conf_file_std (path)) {996 if (is_conf_file_std (path))
896 if (conf_reload_path (source, path, NULL) < 0) {997 conf_load_path_with_override (source, path);
897 NihError *err;998
898999 return 0;
899 err = nih_error_get ();
900 nih_error ("%s: %s: %s", path,
901 _("Error while loading configuration file"),
902 err->message);
903 nih_free (err);
904 }
905 return 0;
906 }
907
908 new_path = toggle_conf_name (NULL, path);
909 file = (ConfFile *)nih_hash_lookup (source->files, new_path);
910
911 if (file) {
912 /* we're visiting an override file with an associated conf file that
913 * has already been loaded, so just overlay the override file. If
914 * there is no corresponding conf file, we ignore the override file.
915 */
916 if (conf_reload_path (source, new_path, path) < 0) {
917 NihError *err;
918
919 err = nih_error_get ();
920 nih_error ("%s: %s: %s", new_path,
921 _("Error while reloading configuration file"),
922 err->message);
923 nih_free (err);
924 }
925 }
926
927 return 0;
928}1000}
9291001
9301002
@@ -957,7 +1029,6 @@
957{1029{
958 ConfFile *file = NULL;1030 ConfFile *file = NULL;
959 nih_local char *buf = NULL;1031 nih_local char *buf = NULL;
960 const char *start, *end;
961 nih_local char *name = NULL;1032 nih_local char *name = NULL;
962 size_t len, pos, lineno;1033 size_t len, pos, lineno;
963 NihError *err = NULL;1034 NihError *err = NULL;
@@ -1014,23 +1085,8 @@
10141085
1015 break;1086 break;
1016 case CONF_JOB_DIR:1087 case CONF_JOB_DIR:
1017 /* Construct the job name by taking the path and removing1088
1018 * the directory name from the front and the extension1089 name = conf_to_job_name (source->path, path);
1019 * from the end.
1020 */
1021 start = path;
1022 if (! strncmp (start, source->path, strlen (source->path)))
1023 start += strlen (source->path);
1024
1025 while (*start == '/')
1026 start++;
1027
1028 end = strrchr (start, '.');
1029 if (end && IS_CONF_EXT (end)) {
1030 name = NIH_MUST (nih_strndup (NULL, start, end - start));
1031 } else {
1032 name = NIH_MUST (nih_strdup (NULL, start));
1033 }
10341090
1035 /* Create a new job item and parse the buffer to produce1091 /* Create a new job item and parse the buffer to produce
1036 * the job definition.1092 * the job definition.
@@ -1388,4 +1444,3 @@
1388}1444}
13891445
1390#endif /* DEBUG */1446#endif /* DEBUG */
1391
13921447
=== 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-08 16:18:21 +0000
@@ -2424,7 +2424,8 @@
2424 FILE *f;2424 FILE *f;
2425 int ret, fd[4096], i = 0;2425 int ret, fd[4096], i = 0;
2426 char dirname[PATH_MAX];2426 char dirname[PATH_MAX];
2427 char filename[PATH_MAX], override[PATH_MAX];2427 char filename[PATH_MAX], override[PATH_MAX], override2[PATH_MAX];
2428 char *dir;
2428 JobClass *job;2429 JobClass *job;
2429 NihError *err;2430 NihError *err;
24302431
@@ -3424,6 +3425,123 @@
3424 unlink (filename);3425 unlink (filename);
3425 TEST_EQ (rmdir (dirname), 0);3426 TEST_EQ (rmdir (dirname), 0);
34263427
3428 TEST_FEATURE ("create two watches, two overrides, conf, then delete override files one by one");
3429 TEST_ENSURE_CLEAN_ENV ();
3430 TEST_FILENAME (dirname);
3431 TEST_EQ (mkdir (dirname, 0755), 0);
3432
3433 strcpy (override, dirname);
3434 strcat (override, "/peter/foo.override");
3435 strcpy (override2, dirname);
3436 strcat (override2, "/paul/foo.override");
3437 strcpy (filename, dirname);
3438 strcat (filename, "/paul/foo.conf");
3439
3440 const char *sources[] = {"peter", "paul", NULL};
3441
3442 for (const char **src = sources; *src; src++) {
3443 dir = nih_sprintf (NULL, "%s/%s", dirname, *src);
3444 TEST_EQ (mkdir (dir, 0755), 0);
3445 source = conf_source_new (NULL, dir, CONF_JOB_DIR);
3446 TEST_NE_P (source, NULL);
3447 ret = conf_source_reload (source);
3448 TEST_EQ (ret, 0);
3449 nih_free (dir);
3450 }
3451
3452 TEST_FORCE_WATCH_UPDATE();
3453
3454 /* create override */
3455 f = fopen (override, "w");
3456 TEST_NE_P (f, NULL);
3457 fprintf (f, "manual\n");
3458 fprintf (f, "author \"peter\"\n");
3459 fclose (f);
3460
3461 TEST_FORCE_WATCH_UPDATE();
3462
3463 /* create override */
3464 f = fopen (override2, "w");
3465 TEST_NE_P (f, NULL);
3466 fprintf (f, "manual\n");
3467 fprintf (f, "author \"paul\"\n");
3468 fprintf (f, "env wibble=wobble\n");
3469 fclose (f);
3470
3471 TEST_FORCE_WATCH_UPDATE();
3472
3473 /* create conf */
3474 f = fopen (filename, "w");
3475 TEST_NE_P (f, NULL);
3476 fprintf (f, "start on started\n");
3477 fprintf (f, "emits hello\n");
3478 fprintf (f, "author \"mary\"\n");
3479 fclose (f);
3480
3481 TEST_FORCE_WATCH_UPDATE();
3482
3483 /* ensure conf loaded */
3484 file = (ConfFile *)nih_hash_lookup (source->files, filename);
3485 TEST_NE_P (file, NULL);
3486 job = (JobClass *)nih_hash_lookup (job_classes, "foo");
3487 TEST_NE_P (job, NULL);
3488 TEST_EQ_P (file->job, job);
3489 TEST_EQ_STR ((job->emits)[0], "hello");
3490
3491 /* should pick up the top-priority override, *NOT* conf */
3492 TEST_EQ_P (job->start_on, NULL);
3493 TEST_EQ_STR (job->author, "peter");
3494
3495 /* delete override */
3496 unlink (override);
3497
3498 TEST_FORCE_WATCH_UPDATE();
3499
3500 /* ensure conf reloaded and updated with the second override */
3501 file = (ConfFile *)nih_hash_lookup (source->files, filename);
3502 TEST_NE_P (file, NULL);
3503 job = (JobClass *)nih_hash_lookup (job_classes, "foo");
3504 TEST_NE_P (job, NULL);
3505 TEST_EQ_P (file->job, job);
3506 TEST_EQ_STR ((job->emits)[0], "hello");
3507
3508 /* should pick up the second override, *NOT* conf */
3509 TEST_EQ_P (job->start_on, NULL);
3510 TEST_EQ_STR (job->author, "paul");
3511 TEST_EQ_STR ((job->env)[0], "wibble=wobble");
3512
3513 TEST_FORCE_WATCH_UPDATE();
3514
3515 /* delete override */
3516 unlink (override2);
3517
3518 TEST_FORCE_WATCH_UPDATE();
3519
3520 /* ensure conf loaded */
3521 file = (ConfFile *)nih_hash_lookup (source->files, filename);
3522 TEST_NE_P (file, NULL);
3523 job = (JobClass *)nih_hash_lookup (job_classes, "foo");
3524 TEST_NE_P (job, NULL);
3525 TEST_EQ_P (file->job, job);
3526 TEST_EQ_STR (job->author, "mary");
3527 TEST_EQ_STR ((job->emits)[0], "hello");
3528 TEST_NE_P (job->start_on, NULL);
3529 TEST_EQ_P (job->env, NULL);
3530
3531 unlink (filename);
3532
3533 for (const char **src = sources; *src; src++) {
3534 dir = nih_sprintf (NULL, "%s/%s", dirname, *src);
3535 TEST_EQ (rmdir (dir), 0);
3536 nih_free (dir);
3537 }
3538
3539 TEST_EQ (rmdir (dirname), 0);
3540
3541 NIH_LIST_FOREACH_SAFE (conf_sources, iter) {
3542 ConfSource *source = (ConfSource *)iter;
3543 nih_free (source);
3544 }
34273545
3428 TEST_FEATURE ("create conf, watch, then create invalid override, delete override");3546 TEST_FEATURE ("create conf, watch, then create invalid override, delete override");
3429 TEST_ENSURE_CLEAN_ENV ();3547 TEST_ENSURE_CLEAN_ENV ();
34303548
=== 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-08 16:18:21 +0000
@@ -34,8 +34,8 @@
34 char *f;34 char *f;
35 char *p;35 char *p;
3636
37 TEST_FUNCTION_FEATURE ("toggle_conf_name",37 TEST_FUNCTION ("toggle_conf_name");
38 "changing conf to override");38 TEST_FEATURE ("changing conf to override");
3939
40 TEST_FILENAME (dirname);40 TEST_FILENAME (dirname);
41 strcpy (filename, dirname);41 strcpy (filename, dirname);
@@ -71,11 +71,154 @@
71 nih_free (job);71 nih_free (job);
72}72}
7373
74void
75test_conf_to_job_name (void)
76{
77 char dirname[PATH_MAX];
78 char *filename;
79 char *name;
80
81 TEST_FUNCTION ("conf_to_job_name");
82 TEST_FEATURE ("with .conf file");
83 TEST_FILENAME (dirname);
84 filename = nih_sprintf (NULL, "%s/foo.conf", dirname);
85 name = conf_to_job_name (dirname, filename);
86 TEST_EQ_STR (name, "foo");
87 nih_free (filename);
88 nih_free (name);
89
90 TEST_FEATURE ("with .override file");
91 filename = nih_sprintf (NULL, "%s/foo.override", dirname);
92 name = conf_to_job_name (dirname, filename);
93 TEST_EQ_STR (name, "foo");
94 nih_free (filename);
95 nih_free (name);
96
97 TEST_FEATURE ("with .conf in a sub-directory");
98 filename = nih_sprintf (NULL, "%s/foo/bar.conf", dirname);
99 name = conf_to_job_name (dirname, filename);
100 TEST_EQ_STR (name, "foo/bar");
101 nih_free (filename);
102 nih_free (name);
103
104 TEST_FEATURE ("without extension");
105 filename = nih_sprintf (NULL, "%s/foo", dirname);
106 name = conf_to_job_name (dirname, filename);
107 TEST_EQ_STR (name, "foo");
108 nih_free (filename);
109 nih_free (name);
110
111}
112
113void
114test_conf_get_best_override (void)
115{
116 const char *sources[] = {"peter", "paul", "mary", NULL};
117 FILE *f;
118 char dirname[PATH_MAX];
119 char *dir;
120 char *expected;
121 char *path;
122
123 TEST_FUNCTION ("conf_get_best_override");
124
125 TEST_FILENAME (dirname);
126 mkdir (dirname, 0755);
127
128 for (const char **src = sources; *src; src++) {
129 dir = nih_sprintf (NULL, "%s/%s", dirname, *src);
130 TEST_EQ (mkdir (dir, 0755), 0);
131 NIH_MUST (conf_source_new (NULL, dir, CONF_JOB_DIR));
132 nih_free (dir);
133 }
134
135 TEST_FEATURE ("with no overrides");
136 NIH_LIST_FOREACH (conf_sources, iter) {
137 ConfSource *source = (ConfSource *)iter;
138 path = conf_get_best_override ("foo", source);
139 TEST_EQ_P (path, NULL);
140 }
141
142 TEST_FEATURE ("with single highest priority override");
143 expected = nih_sprintf (NULL, "%s/%s/foo.override", dirname, sources[0]);
144 f = fopen (expected, "w");
145 TEST_NE_P (f, NULL);
146 TEST_EQ (fclose (f), 0);
147
148 NIH_LIST_FOREACH (conf_sources, iter) {
149 ConfSource *source = (ConfSource *)iter;
150 path = conf_get_best_override ("foo", source);
151 TEST_EQ_STR (path, expected);
152 nih_free (path);
153 }
154 TEST_EQ (unlink (expected), 0);
155
156 TEST_FEATURE ("with single middle priority override");
157 expected = nih_sprintf (NULL, "%s/%s/foo.override", dirname, sources[1]);
158 f = fopen (expected, "w");
159 TEST_NE_P (f, NULL);
160 TEST_EQ (fclose (f), 0);
161
162 NIH_LIST_FOREACH (conf_sources, iter) {
163 ConfSource *source = (ConfSource *)iter;
164 path = conf_get_best_override ("foo", source);
165
166 /* Poor-man's basename(1) */
167 dir = conf_to_job_name (dirname, source->path);
168 if (strcmp (dir, sources[0]) == 0) {
169 TEST_EQ_P (path, NULL);
170 } else {
171 TEST_EQ_STR (path, expected);
172 nih_free (path);
173 }
174 nih_free (dir);
175 }
176 TEST_EQ (unlink (expected), 0);
177
178 TEST_FEATURE ("with single lowest priority override");
179 expected = nih_sprintf (NULL, "%s/%s/foo.override", dirname, sources[2]);
180 f = fopen (expected, "w");
181 TEST_NE_P (f, NULL);
182 TEST_EQ (fclose (f), 0);
183
184 NIH_LIST_FOREACH (conf_sources, iter) {
185 ConfSource *source = (ConfSource *)iter;
186 path = conf_get_best_override ("foo", source);
187
188 /* Poor-man's basename(1) */
189 dir = conf_to_job_name (dirname, source->path);
190 if (strcmp (dir, sources[2]) == 0) {
191 TEST_EQ_STR (path, expected);
192 nih_free (path);
193 } else {
194 TEST_EQ_P (path, NULL);
195 }
196 nih_free (dir);
197 }
198 TEST_EQ (unlink (expected), 0);
199
200 /* Clean up */
201 for (const char **src = sources; *src; src++) {
202 dir = nih_sprintf (NULL, "%s/%s", dirname, *src);
203 TEST_EQ (rmdir (dir), 0);
204 nih_free (dir);
205 }
206
207 TEST_EQ (rmdir (dirname), 0);
208
209 NIH_LIST_FOREACH_SAFE (conf_sources, iter) {
210 ConfSource *source = (ConfSource *)iter;
211 nih_free (source);
212 }
213}
214
74int215int
75main (int argc,216main (int argc,
76 char *argv[])217 char *argv[])
77{218{
78 test_toggle_conf_name ();219 test_toggle_conf_name ();
220 test_conf_to_job_name ();
221 test_conf_get_best_override ();
79222
80 return 0;223 return 0;
81}224}

Subscribers

People subscribed via source and target branches