LCOV - code coverage report
Current view: top level - test - test-load-fragment.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 427 434 98.4 %
Date: 2019-08-22 15:41:25 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <fcntl.h>
       4             : #include <stddef.h>
       5             : #include <stdio.h>
       6             : #include <string.h>
       7             : #include <sys/capability.h>
       8             : #include <unistd.h>
       9             : 
      10             : #include "all-units.h"
      11             : #include "alloc-util.h"
      12             : #include "capability-util.h"
      13             : #include "conf-parser.h"
      14             : #include "fd-util.h"
      15             : #include "format-util.h"
      16             : #include "fs-util.h"
      17             : #include "hashmap.h"
      18             : #include "hostname-util.h"
      19             : #include "install-printf.h"
      20             : #include "install.h"
      21             : #include "load-fragment.h"
      22             : #include "macro.h"
      23             : #include "memory-util.h"
      24             : #include "rm-rf.h"
      25             : #include "specifier.h"
      26             : #include "string-util.h"
      27             : #include "strv.h"
      28             : #include "test-helper.h"
      29             : #include "tests.h"
      30             : #include "tmpfile-util.h"
      31             : #include "user-util.h"
      32             : 
      33           1 : static int test_unit_file_get_set(void) {
      34             :         int r;
      35             :         Hashmap *h;
      36             :         Iterator i;
      37             :         UnitFileList *p;
      38             : 
      39           1 :         h = hashmap_new(&string_hash_ops);
      40           1 :         assert_se(h);
      41             : 
      42           1 :         r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
      43           1 :         if (IN_SET(r, -EPERM, -EACCES))
      44           0 :                 return log_tests_skipped_errno(r, "unit_file_get_list");
      45             : 
      46           1 :         log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r,
      47             :                        "unit_file_get_list: %m");
      48           1 :         if (r < 0)
      49           0 :                 return EXIT_FAILURE;
      50             : 
      51         508 :         HASHMAP_FOREACH(p, h, i)
      52         507 :                 printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
      53             : 
      54           1 :         unit_file_list_free(h);
      55             : 
      56           1 :         return 0;
      57             : }
      58             : 
      59          24 : static void check_execcommand(ExecCommand *c,
      60             :                               const char* path,
      61             :                               const char* argv0,
      62             :                               const char* argv1,
      63             :                               const char* argv2,
      64             :                               bool ignore) {
      65             :         size_t n;
      66             : 
      67          24 :         assert_se(c);
      68          24 :         log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
      69             :                  path, argv0 ?: path, argv1, argv2);
      70          24 :         n = strv_length(c->argv);
      71          24 :         log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
      72             :                  c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL);
      73          24 :         assert_se(streq(c->path, path));
      74          24 :         assert_se(streq(c->argv[0], argv0 ?: path));
      75          24 :         if (n > 0)
      76          24 :                 assert_se(streq_ptr(c->argv[1], argv1));
      77          24 :         if (n > 1)
      78          22 :                 assert_se(streq_ptr(c->argv[2], argv2));
      79          24 :         assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore);
      80          24 : }
      81             : 
      82           1 : static void test_config_parse_exec(void) {
      83             :         /* int config_parse_exec(
      84             :                  const char *unit,
      85             :                  const char *filename,
      86             :                  unsigned line,
      87             :                  const char *section,
      88             :                  unsigned section_line,
      89             :                  const char *lvalue,
      90             :                  int ltype,
      91             :                  const char *rvalue,
      92             :                  void *data,
      93             :                  void *userdata) */
      94             :         int r;
      95             : 
      96           1 :         ExecCommand *c = NULL, *c1;
      97             :         const char *ccc;
      98           1 :         _cleanup_(manager_freep) Manager *m = NULL;
      99           1 :         _cleanup_(unit_freep) Unit *u = NULL;
     100             : 
     101           1 :         r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
     102           1 :         if (MANAGER_SKIP_TEST(r)) {
     103           0 :                 log_notice_errno(r, "Skipping test: manager_new: %m");
     104           0 :                 return;
     105             :         }
     106             : 
     107           1 :         assert_se(r >= 0);
     108           1 :         assert_se(manager_startup(m, NULL, NULL) >= 0);
     109             : 
     110           1 :         assert_se(u = unit_new(m, sizeof(Service)));
     111             : 
     112           1 :         log_info("/* basic test */");
     113           1 :         r = config_parse_exec(NULL, "fake", 1, "section", 1,
     114             :                               "LValue", 0, "/RValue r1",
     115             :                               &c, u);
     116           1 :         assert_se(r >= 0);
     117           1 :         check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
     118             : 
     119           1 :         r = config_parse_exec(NULL, "fake", 2, "section", 1,
     120             :                               "LValue", 0, "/RValue///slashes r1///",
     121             :                               &c, u);
     122             : 
     123           1 :         log_info("/* test slashes */");
     124           1 :         assert_se(r >= 0);
     125           1 :         c1 = c->command_next;
     126           1 :         check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
     127             : 
     128           1 :         log_info("/* trailing slash */");
     129           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     130             :                               "LValue", 0, "/RValue/ argv0 r1",
     131             :                               &c, u);
     132           1 :         assert_se(r == -ENOEXEC);
     133           1 :         assert_se(c1->command_next == NULL);
     134             : 
     135           1 :         log_info("/* honour_argv0 */");
     136           1 :         r = config_parse_exec(NULL, "fake", 3, "section", 1,
     137             :                               "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
     138             :                               &c, u);
     139           1 :         assert_se(r >= 0);
     140           1 :         c1 = c1->command_next;
     141           1 :         check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
     142             : 
     143           1 :         log_info("/* honour_argv0, no args */");
     144           1 :         r = config_parse_exec(NULL, "fake", 3, "section", 1,
     145             :                               "LValue", 0, "@/RValue",
     146             :                               &c, u);
     147           1 :         assert_se(r == -ENOEXEC);
     148           1 :         assert_se(c1->command_next == NULL);
     149             : 
     150           1 :         log_info("/* no command, whitespace only, reset */");
     151           1 :         r = config_parse_exec(NULL, "fake", 3, "section", 1,
     152             :                               "LValue", 0, "    ",
     153             :                               &c, u);
     154           1 :         assert_se(r == 0);
     155           1 :         assert_se(c == NULL);
     156             : 
     157           1 :         log_info("/* ignore && honour_argv0 */");
     158           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     159             :                               "LValue", 0, "-@/RValue///slashes3 argv0a r1",
     160             :                               &c, u);
     161           1 :         assert_se(r >= 0);
     162           1 :         c1 = c;
     163           1 :         check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
     164             : 
     165           1 :         log_info("/* ignore && honour_argv0 */");
     166           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     167             :                               "LValue", 0, "@-/RValue///slashes4 argv0b r1",
     168             :                               &c, u);
     169           1 :         assert_se(r >= 0);
     170           1 :         c1 = c1->command_next;
     171           1 :         check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
     172             : 
     173           1 :         log_info("/* ignore && ignore */");
     174           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     175             :                               "LValue", 0, "--/RValue argv0 r1",
     176             :                               &c, u);
     177           1 :         assert_se(r == 0);
     178           1 :         assert_se(c1->command_next == NULL);
     179             : 
     180           1 :         log_info("/* ignore && ignore (2) */");
     181           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     182             :                               "LValue", 0, "-@-/RValue argv0 r1",
     183             :                               &c, u);
     184           1 :         assert_se(r == 0);
     185           1 :         assert_se(c1->command_next == NULL);
     186             : 
     187           1 :         log_info("/* semicolon */");
     188           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     189             :                               "LValue", 0,
     190             :                               "-@/RValue argv0 r1 ; "
     191             :                               "/goo/goo boo",
     192             :                               &c, u);
     193           1 :         assert_se(r >= 0);
     194           1 :         c1 = c1->command_next;
     195           1 :         check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
     196             : 
     197           1 :         c1 = c1->command_next;
     198           1 :         check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
     199             : 
     200           1 :         log_info("/* two semicolons in a row */");
     201           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     202             :                               "LValue", 0,
     203             :                               "-@/RValue argv0 r1 ; ; "
     204             :                               "/goo/goo boo",
     205             :                               &c, u);
     206           1 :         assert_se(r == -ENOEXEC);
     207           1 :         c1 = c1->command_next;
     208           1 :         check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
     209             : 
     210             :         /* second command fails because the executable name is ";" */
     211           1 :         assert_se(c1->command_next == NULL);
     212             : 
     213           1 :         log_info("/* trailing semicolon */");
     214           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     215             :                               "LValue", 0,
     216             :                               "-@/RValue argv0 r1 ; ",
     217             :                               &c, u);
     218           1 :         assert_se(r >= 0);
     219           1 :         c1 = c1->command_next;
     220           1 :         check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
     221             : 
     222           1 :         assert_se(c1->command_next == NULL);
     223             : 
     224           1 :         log_info("/* trailing semicolon, no whitespace */");
     225           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     226             :                               "LValue", 0,
     227             :                               "-@/RValue argv0 r1 ;",
     228             :                               &c, u);
     229           1 :         assert_se(r >= 0);
     230           1 :         c1 = c1->command_next;
     231           1 :         check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
     232             : 
     233           1 :         assert_se(c1->command_next == NULL);
     234             : 
     235           1 :         log_info("/* trailing semicolon in single quotes */");
     236           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     237             :                               "LValue", 0,
     238             :                               "-@/RValue argv0 r1 ';'",
     239             :                               &c, u);
     240           1 :         assert_se(r >= 0);
     241           1 :         c1 = c1->command_next;
     242           1 :         check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
     243             : 
     244           1 :         log_info("/* escaped semicolon */");
     245           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     246             :                               "LValue", 0,
     247             :                               "/bin/find \\;",
     248             :                               &c, u);
     249           1 :         assert_se(r >= 0);
     250           1 :         c1 = c1->command_next;
     251           1 :         check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
     252             : 
     253           1 :         log_info("/* escaped semicolon with following arg */");
     254           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     255             :                               "LValue", 0,
     256             :                               "/sbin/find \\; /x",
     257             :                               &c, u);
     258           1 :         assert_se(r >= 0);
     259           1 :         c1 = c1->command_next;
     260           1 :         check_execcommand(c1,
     261             :                           "/sbin/find", NULL, ";", "/x", false);
     262             : 
     263           1 :         log_info("/* escaped semicolon as part of an expression */");
     264           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     265             :                               "LValue", 0,
     266             :                               "/sbin/find \\;x",
     267             :                               &c, u);
     268           1 :         assert_se(r >= 0);
     269           1 :         c1 = c1->command_next;
     270           1 :         check_execcommand(c1,
     271             :                           "/sbin/find", NULL, "\\;x", NULL, false);
     272             : 
     273           1 :         log_info("/* encoded semicolon */");
     274           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     275             :                               "LValue", 0,
     276             :                               "/bin/find \\073",
     277             :                               &c, u);
     278           1 :         assert_se(r >= 0);
     279           1 :         c1 = c1->command_next;
     280           1 :         check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
     281             : 
     282           1 :         log_info("/* quoted semicolon */");
     283           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     284             :                               "LValue", 0,
     285             :                               "/bin/find \";\"",
     286             :                               &c, u);
     287           1 :         assert_se(r >= 0);
     288           1 :         c1 = c1->command_next;
     289           1 :         check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
     290             : 
     291           1 :         log_info("/* quoted semicolon with following arg */");
     292           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     293             :                               "LValue", 0,
     294             :                               "/sbin/find \";\" /x",
     295             :                               &c, u);
     296           1 :         assert_se(r >= 0);
     297           1 :         c1 = c1->command_next;
     298           1 :         check_execcommand(c1,
     299             :                           "/sbin/find", NULL, ";", "/x", false);
     300             : 
     301           1 :         log_info("/* spaces in the filename */");
     302           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     303             :                               "LValue", 0,
     304             :                               "\"/PATH WITH SPACES/daemon\" -1 -2",
     305             :                               &c, u);
     306           1 :         assert_se(r >= 0);
     307           1 :         c1 = c1->command_next;
     308           1 :         check_execcommand(c1,
     309             :                           "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
     310             : 
     311           1 :         log_info("/* spaces in the filename, no args */");
     312           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     313             :                               "LValue", 0,
     314             :                               "\"/PATH WITH SPACES/daemon -1 -2\"",
     315             :                               &c, u);
     316           1 :         assert_se(r >= 0);
     317           1 :         c1 = c1->command_next;
     318           1 :         check_execcommand(c1,
     319             :                           "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false);
     320             : 
     321           1 :         log_info("/* spaces in the filename, everything quoted */");
     322           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     323             :                               "LValue", 0,
     324             :                               "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
     325             :                               &c, u);
     326           1 :         assert_se(r >= 0);
     327           1 :         c1 = c1->command_next;
     328           1 :         check_execcommand(c1,
     329             :                           "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
     330             : 
     331           1 :         log_info("/* escaped spaces in the filename */");
     332           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     333             :                               "LValue", 0,
     334             :                               "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
     335             :                               &c, u);
     336           1 :         assert_se(r >= 0);
     337           1 :         c1 = c1->command_next;
     338           1 :         check_execcommand(c1,
     339             :                           "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
     340             : 
     341           1 :         log_info("/* escaped spaces in the filename (2) */");
     342           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     343             :                               "LValue", 0,
     344             :                               "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
     345             :                               &c, u);
     346           1 :         assert_se(r >= 0);
     347           1 :         c1 = c1->command_next;
     348           1 :         check_execcommand(c1,
     349             :                           "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
     350             : 
     351          12 :         for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) {
     352             :                 /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
     353          11 :                 char path[] = "/path\\X";
     354          11 :                 path[sizeof(path) - 2] = *ccc;
     355             : 
     356          11 :                 log_info("/* invalid character: \\%c */", *ccc);
     357          11 :                 r = config_parse_exec(NULL, "fake", 4, "section", 1,
     358             :                                       "LValue", 0, path,
     359             :                                       &c, u);
     360          11 :                 assert_se(r == -ENOEXEC);
     361          11 :                 assert_se(c1->command_next == NULL);
     362             :         }
     363             : 
     364           1 :         log_info("/* valid character: \\s */");
     365           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     366             :                               "LValue", 0, "/path\\s",
     367             :                               &c, u);
     368           1 :         assert_se(r >= 0);
     369           1 :         c1 = c1->command_next;
     370           1 :         check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
     371             : 
     372           1 :         log_info("/* quoted backslashes */");
     373           1 :         r = config_parse_exec(NULL, "fake", 5, "section", 1,
     374             :                               "LValue", 0,
     375             :                               "/bin/grep '\\w+\\K'",
     376             :                               &c, u);
     377           1 :         assert_se(r >= 0);
     378           1 :         c1 = c1->command_next;
     379           1 :         check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
     380             : 
     381           1 :         log_info("/* trailing backslash: \\ */");
     382             :         /* backslash is invalid */
     383           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     384             :                               "LValue", 0, "/path\\",
     385             :                               &c, u);
     386           1 :         assert_se(r == -ENOEXEC);
     387           1 :         assert_se(c1->command_next == NULL);
     388             : 
     389           1 :         log_info("/* missing ending ' */");
     390           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     391             :                               "LValue", 0, "/path 'foo",
     392             :                               &c, u);
     393           1 :         assert_se(r == -ENOEXEC);
     394           1 :         assert_se(c1->command_next == NULL);
     395             : 
     396           1 :         log_info("/* missing ending ' with trailing backslash */");
     397           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     398             :                               "LValue", 0, "/path 'foo\\",
     399             :                               &c, u);
     400           1 :         assert_se(r == -ENOEXEC);
     401           1 :         assert_se(c1->command_next == NULL);
     402             : 
     403           1 :         log_info("/* invalid space between modifiers */");
     404           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     405             :                               "LValue", 0, "- /path",
     406             :                               &c, u);
     407           1 :         assert_se(r == 0);
     408           1 :         assert_se(c1->command_next == NULL);
     409             : 
     410           1 :         log_info("/* only modifiers, no path */");
     411           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     412             :                               "LValue", 0, "-",
     413             :                               &c, u);
     414           1 :         assert_se(r == 0);
     415           1 :         assert_se(c1->command_next == NULL);
     416             : 
     417           1 :         log_info("/* empty argument, reset */");
     418           1 :         r = config_parse_exec(NULL, "fake", 4, "section", 1,
     419             :                               "LValue", 0, "",
     420             :                               &c, u);
     421           1 :         assert_se(r == 0);
     422           1 :         assert_se(c == NULL);
     423             : 
     424           1 :         exec_command_free_list(c);
     425             : }
     426             : 
     427           1 : static void test_config_parse_log_extra_fields(void) {
     428             :         /* int config_parse_log_extra_fields(
     429             :                 const char *unit,
     430             :                 const char *filename,
     431             :                 unsigned line,
     432             :                 const char *section,
     433             :                 unsigned section_line,
     434             :                 const char *lvalue,
     435             :                 int ltype,
     436             :                 const char *rvalue,
     437             :                 void *data,
     438             :                 void *userdata) */
     439             : 
     440             :         int r;
     441             : 
     442           1 :         _cleanup_(manager_freep) Manager *m = NULL;
     443           1 :         _cleanup_(unit_freep) Unit *u = NULL;
     444           1 :         ExecContext c = {};
     445             : 
     446           1 :         r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
     447           1 :         if (MANAGER_SKIP_TEST(r)) {
     448           0 :                 log_notice_errno(r, "Skipping test: manager_new: %m");
     449           0 :                 return;
     450             :         }
     451             : 
     452           1 :         assert_se(r >= 0);
     453           1 :         assert_se(manager_startup(m, NULL, NULL) >= 0);
     454             : 
     455           1 :         assert_se(u = unit_new(m, sizeof(Service)));
     456             : 
     457           1 :         log_info("/* %s – basic test */", __func__);
     458           1 :         r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
     459             :                                           "LValue", 0, "FOO=BAR \"QOOF=quux '  ' \"",
     460             :                                           &c, u);
     461           1 :         assert_se(r >= 0);
     462           1 :         assert_se(c.n_log_extra_fields == 2);
     463           1 :         assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
     464           1 :         assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux '  ' ", c.log_extra_fields[1].iov_len));
     465             : 
     466           1 :         log_info("/* %s – add some */", __func__);
     467           1 :         r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
     468             :                                           "LValue", 0, "FOO2=BAR2 QOOF2=quux '  '",
     469             :                                           &c, u);
     470           1 :         assert_se(r >= 0);
     471           1 :         assert_se(c.n_log_extra_fields == 4);
     472           1 :         assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
     473           1 :         assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux '  ' ", c.log_extra_fields[1].iov_len));
     474           1 :         assert_se(strneq(c.log_extra_fields[2].iov_base, "FOO2=BAR2", c.log_extra_fields[2].iov_len));
     475           1 :         assert_se(strneq(c.log_extra_fields[3].iov_base, "QOOF2=quux", c.log_extra_fields[3].iov_len));
     476             : 
     477           1 :         exec_context_dump(&c, stdout, "    --> ");
     478             : 
     479           1 :         log_info("/* %s – reset */", __func__);
     480           1 :         r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
     481             :                                           "LValue", 0, "",
     482             :                                           &c, u);
     483           1 :         assert_se(r >= 0);
     484           1 :         assert_se(c.n_log_extra_fields == 0);
     485             : 
     486           1 :         exec_context_free_log_extra_fields(&c);
     487             : 
     488           1 :         log_info("/* %s – bye */", __func__);
     489             : }
     490             : 
     491           1 : static void test_install_printf(void) {
     492           1 :         char    name[] = "name.service",
     493           1 :                 path[] = "/run/systemd/system/name.service";
     494           1 :         UnitFileInstallInfo i = { .name = name, .path = path, };
     495           1 :         UnitFileInstallInfo i2 = { .name= name, .path = path, };
     496           1 :         char    name3[] = "name@inst.service",
     497           1 :                 path3[] = "/run/systemd/system/name.service";
     498           1 :         UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
     499           1 :         UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
     500             : 
     501           1 :         _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL;
     502             : 
     503           1 :         assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
     504           1 :         assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
     505           1 :         assert_se(host = gethostname_malloc());
     506           1 :         assert_se(group = gid_to_name(getgid()));
     507           1 :         assert_se(asprintf(&gid, UID_FMT, getgid()) >= 0);
     508           1 :         assert_se(user = uid_to_name(getuid()));
     509           1 :         assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
     510             : 
     511             : #define expect(src, pattern, result)                                    \
     512             :         do {                                                            \
     513             :                 _cleanup_free_ char *t = NULL;                          \
     514             :                 _cleanup_free_ char                                     \
     515             :                         *d1 = strdup(i.name),                           \
     516             :                         *d2 = strdup(i.path);                           \
     517             :                 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
     518             :                 memzero(i.name, strlen(i.name));                        \
     519             :                 memzero(i.path, strlen(i.path));                        \
     520             :                 assert_se(d1 && d2);                                    \
     521             :                 if (result) {                                           \
     522             :                         printf("%s\n", t);                              \
     523             :                         assert_se(streq(t, result));                    \
     524             :                 } else assert_se(t == NULL);                            \
     525             :                 strcpy(i.name, d1);                                     \
     526             :                 strcpy(i.path, d2);                                     \
     527             :         } while (false)
     528             : 
     529           1 :         expect(i, "%n", "name.service");
     530           1 :         expect(i, "%N", "name");
     531           1 :         expect(i, "%p", "name");
     532           1 :         expect(i, "%i", "");
     533           1 :         expect(i, "%j", "name");
     534           1 :         expect(i, "%g", group);
     535           1 :         expect(i, "%G", gid);
     536           1 :         expect(i, "%u", user);
     537           1 :         expect(i, "%U", uid);
     538             : 
     539           1 :         expect(i, "%m", mid);
     540           1 :         expect(i, "%b", bid);
     541           1 :         expect(i, "%H", host);
     542             : 
     543           1 :         expect(i2, "%g", group);
     544           1 :         expect(i2, "%G", gid);
     545           1 :         expect(i2, "%u", user);
     546           1 :         expect(i2, "%U", uid);
     547             : 
     548           1 :         expect(i3, "%n", "name@inst.service");
     549           1 :         expect(i3, "%N", "name@inst");
     550           1 :         expect(i3, "%p", "name");
     551           1 :         expect(i3, "%g", group);
     552           1 :         expect(i3, "%G", gid);
     553           1 :         expect(i3, "%u", user);
     554           1 :         expect(i3, "%U", uid);
     555             : 
     556           1 :         expect(i3, "%m", mid);
     557           1 :         expect(i3, "%b", bid);
     558           1 :         expect(i3, "%H", host);
     559             : 
     560           1 :         expect(i4, "%g", group);
     561           1 :         expect(i4, "%G", gid);
     562           1 :         expect(i4, "%u", user);
     563           1 :         expect(i4, "%U", uid);
     564           1 : }
     565             : 
     566           6 : static uint64_t make_cap(int cap) {
     567           6 :         return ((uint64_t) 1ULL << (uint64_t) cap);
     568             : }
     569             : 
     570           1 : static void test_config_parse_capability_set(void) {
     571             :         /* int config_parse_capability_set(
     572             :                  const char *unit,
     573             :                  const char *filename,
     574             :                  unsigned line,
     575             :                  const char *section,
     576             :                  unsigned section_line,
     577             :                  const char *lvalue,
     578             :                  int ltype,
     579             :                  const char *rvalue,
     580             :                  void *data,
     581             :                  void *userdata) */
     582             :         int r;
     583           1 :         uint64_t capability_bounding_set = 0;
     584             : 
     585           1 :         r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
     586             :                               "CapabilityBoundingSet", 0, "CAP_NET_RAW",
     587             :                               &capability_bounding_set, NULL);
     588           1 :         assert_se(r >= 0);
     589           1 :         assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
     590             : 
     591           1 :         r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
     592             :                               "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
     593             :                               &capability_bounding_set, NULL);
     594           1 :         assert_se(r >= 0);
     595           1 :         assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
     596             : 
     597           1 :         r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
     598             :                               "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
     599             :                               &capability_bounding_set, NULL);
     600           1 :         assert_se(r >= 0);
     601           1 :         assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
     602             : 
     603           1 :         r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
     604             :                               "CapabilityBoundingSet", 0, "",
     605             :                               &capability_bounding_set, NULL);
     606           1 :         assert_se(r >= 0);
     607           1 :         assert_se(capability_bounding_set == UINT64_C(0));
     608             : 
     609           1 :         r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
     610             :                               "CapabilityBoundingSet", 0, "~",
     611             :                               &capability_bounding_set, NULL);
     612           1 :         assert_se(r >= 0);
     613           1 :         assert_se(cap_test_all(capability_bounding_set));
     614             : 
     615           1 :         capability_bounding_set = 0;
     616           1 :         r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
     617             :                               "CapabilityBoundingSet", 0, "  'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
     618             :                               &capability_bounding_set, NULL);
     619           1 :         assert_se(r >= 0);
     620           1 :         assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
     621           1 : }
     622             : 
     623           1 : static void test_config_parse_rlimit(void) {
     624           1 :         struct rlimit * rl[_RLIMIT_MAX] = {};
     625             : 
     626           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
     627           1 :         assert_se(rl[RLIMIT_NOFILE]);
     628           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
     629           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
     630             : 
     631           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
     632           1 :         assert_se(rl[RLIMIT_NOFILE]);
     633           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
     634           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
     635             : 
     636           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
     637           1 :         assert_se(rl[RLIMIT_NOFILE]);
     638           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
     639           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
     640             : 
     641           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
     642           1 :         assert_se(rl[RLIMIT_NOFILE]);
     643           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
     644           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
     645             : 
     646           1 :         rl[RLIMIT_NOFILE]->rlim_cur = 10;
     647           1 :         rl[RLIMIT_NOFILE]->rlim_max = 20;
     648             : 
     649             :         /* Invalid values don't change rl */
     650           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
     651           1 :         assert_se(rl[RLIMIT_NOFILE]);
     652           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
     653           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
     654             : 
     655           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
     656           1 :         assert_se(rl[RLIMIT_NOFILE]);
     657           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
     658           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
     659             : 
     660           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
     661           1 :         assert_se(rl[RLIMIT_NOFILE]);
     662           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
     663           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
     664             : 
     665           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
     666           1 :         assert_se(rl[RLIMIT_NOFILE]);
     667           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
     668           1 :         assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
     669             : 
     670           1 :         rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
     671             : 
     672           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
     673           1 :         assert_se(rl[RLIMIT_CPU]);
     674           1 :         assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
     675           1 :         assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
     676             : 
     677           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
     678           1 :         assert_se(rl[RLIMIT_CPU]);
     679           1 :         assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
     680           1 :         assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
     681             : 
     682           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
     683           1 :         assert_se(rl[RLIMIT_CPU]);
     684           1 :         assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
     685           1 :         assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
     686             : 
     687           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
     688           1 :         assert_se(rl[RLIMIT_CPU]);
     689           1 :         assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
     690           1 :         assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
     691             : 
     692           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
     693           1 :         assert_se(rl[RLIMIT_CPU]);
     694           1 :         assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
     695           1 :         assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
     696             : 
     697           1 :         rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
     698             : 
     699           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
     700           1 :         assert_se(rl[RLIMIT_RTTIME]);
     701           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
     702           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
     703             : 
     704           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
     705           1 :         assert_se(rl[RLIMIT_RTTIME]);
     706           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
     707           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
     708             : 
     709           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
     710           1 :         assert_se(rl[RLIMIT_RTTIME]);
     711           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
     712           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
     713             : 
     714           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
     715           1 :         assert_se(rl[RLIMIT_RTTIME]);
     716           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
     717           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
     718             : 
     719           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
     720           1 :         assert_se(rl[RLIMIT_RTTIME]);
     721           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
     722           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
     723             : 
     724           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
     725           1 :         assert_se(rl[RLIMIT_RTTIME]);
     726           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
     727           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
     728             : 
     729           1 :         assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
     730           1 :         assert_se(rl[RLIMIT_RTTIME]);
     731           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
     732           1 :         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
     733             : 
     734           1 :         rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
     735           1 : }
     736             : 
     737           1 : static void test_config_parse_pass_environ(void) {
     738             :         /* int config_parse_pass_environ(
     739             :                  const char *unit,
     740             :                  const char *filename,
     741             :                  unsigned line,
     742             :                  const char *section,
     743             :                  unsigned section_line,
     744             :                  const char *lvalue,
     745             :                  int ltype,
     746             :                  const char *rvalue,
     747             :                  void *data,
     748             :                  void *userdata) */
     749             :         int r;
     750           1 :         _cleanup_strv_free_ char **passenv = NULL;
     751             : 
     752           1 :         r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
     753             :                               "PassEnvironment", 0, "A B",
     754             :                               &passenv, NULL);
     755           1 :         assert_se(r >= 0);
     756           1 :         assert_se(strv_length(passenv) == 2);
     757           1 :         assert_se(streq(passenv[0], "A"));
     758           1 :         assert_se(streq(passenv[1], "B"));
     759             : 
     760           1 :         r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
     761             :                               "PassEnvironment", 0, "",
     762             :                               &passenv, NULL);
     763           1 :         assert_se(r >= 0);
     764           1 :         assert_se(strv_isempty(passenv));
     765             : 
     766           1 :         r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
     767             :                               "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
     768             :                               &passenv, NULL);
     769           1 :         assert_se(r >= 0);
     770           1 :         assert_se(strv_length(passenv) == 1);
     771           1 :         assert_se(streq(passenv[0], "normal_name"));
     772             : 
     773           1 : }
     774             : 
     775           1 : static void test_unit_dump_config_items(void) {
     776           1 :         unit_dump_config_items(stdout);
     777           1 : }
     778             : 
     779           1 : int main(int argc, char *argv[]) {
     780           1 :         _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
     781             :         int r;
     782             : 
     783           1 :         test_setup_logging(LOG_INFO);
     784             : 
     785           1 :         r = enter_cgroup_subroot();
     786           1 :         if (r == -ENOMEDIUM)
     787           0 :                 return log_tests_skipped("cgroupfs not available");
     788             : 
     789           1 :         assert_se(runtime_dir = setup_fake_runtime_dir());
     790             : 
     791           1 :         r = test_unit_file_get_set();
     792           1 :         test_config_parse_exec();
     793           1 :         test_config_parse_log_extra_fields();
     794           1 :         test_config_parse_capability_set();
     795           1 :         test_config_parse_rlimit();
     796           1 :         test_config_parse_pass_environ();
     797           1 :         TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
     798           1 :         test_unit_dump_config_items();
     799             : 
     800           1 :         return r;
     801             : }

Generated by: LCOV version 1.14