LCOV - code coverage report
Current view: top level - test - test-conf-parser.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 209 209 100.0 %
Date: 2019-08-23 13:36:53 Functions: 25 25 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 48 89 53.9 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include "conf-parser.h"
       4                 :            : #include "fd-util.h"
       5                 :            : #include "fs-util.h"
       6                 :            : #include "log.h"
       7                 :            : #include "macro.h"
       8                 :            : #include "string-util.h"
       9                 :            : #include "strv.h"
      10                 :            : #include "tmpfile-util.h"
      11                 :            : #include "util.h"
      12                 :            : 
      13                 :         28 : static void test_config_parse_path_one(const char *rvalue, const char *expected) {
      14                 :         28 :         _cleanup_free_ char *path = NULL;
      15                 :            : 
      16         [ -  + ]:         28 :         assert_se(config_parse_path("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &path, NULL) >= 0);
      17         [ -  + ]:         28 :         assert_se(streq_ptr(expected, path));
      18                 :         28 : }
      19                 :            : 
      20                 :         12 : static void test_config_parse_log_level_one(const char *rvalue, int expected) {
      21                 :         12 :         int log_level = 0;
      22                 :            : 
      23         [ -  + ]:         12 :         assert_se(config_parse_log_level("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_level, NULL) >= 0);
      24         [ -  + ]:         12 :         assert_se(expected == log_level);
      25                 :         12 : }
      26                 :            : 
      27                 :         12 : static void test_config_parse_log_facility_one(const char *rvalue, int expected) {
      28                 :         12 :         int log_facility = 0;
      29                 :            : 
      30         [ -  + ]:         12 :         assert_se(config_parse_log_facility("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_facility, NULL) >= 0);
      31         [ -  + ]:         12 :         assert_se(expected == log_facility);
      32                 :         12 : }
      33                 :            : 
      34                 :         36 : static void test_config_parse_iec_size_one(const char *rvalue, size_t expected) {
      35                 :         36 :         size_t iec_size = 0;
      36                 :            : 
      37         [ -  + ]:         36 :         assert_se(config_parse_iec_size("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &iec_size, NULL) >= 0);
      38         [ -  + ]:         36 :         assert_se(expected == iec_size);
      39                 :         36 : }
      40                 :            : 
      41                 :         36 : static void test_config_parse_si_size_one(const char *rvalue, size_t expected) {
      42                 :         36 :         size_t si_size = 0;
      43                 :            : 
      44         [ -  + ]:         36 :         assert_se(config_parse_si_size("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &si_size, NULL) >= 0);
      45         [ -  + ]:         36 :         assert_se(expected == si_size);
      46                 :         36 : }
      47                 :            : 
      48                 :         28 : static void test_config_parse_int_one(const char *rvalue, int expected) {
      49                 :         28 :         int v = -1;
      50                 :            : 
      51         [ -  + ]:         28 :         assert_se(config_parse_int("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
      52         [ -  + ]:         28 :         assert_se(expected == v);
      53                 :         28 : }
      54                 :            : 
      55                 :         28 : static void test_config_parse_unsigned_one(const char *rvalue, unsigned expected) {
      56                 :         28 :         unsigned v = 0;
      57                 :            : 
      58         [ -  + ]:         28 :         assert_se(config_parse_unsigned("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
      59         [ -  + ]:         28 :         assert_se(expected == v);
      60                 :         28 : }
      61                 :            : 
      62                 :         24 : static void test_config_parse_strv_one(const char *rvalue, char **expected) {
      63                 :         24 :         _cleanup_strv_free_ char **strv = NULL;
      64                 :            : 
      65         [ -  + ]:         24 :         assert_se(config_parse_strv("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &strv, NULL) >= 0);
      66         [ -  + ]:         24 :         assert_se(strv_equal(expected, strv));
      67                 :         24 : }
      68                 :            : 
      69                 :         28 : static void test_config_parse_mode_one(const char *rvalue, mode_t expected) {
      70                 :         28 :         mode_t v = 0;
      71                 :            : 
      72         [ -  + ]:         28 :         assert_se(config_parse_mode("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
      73         [ -  + ]:         28 :         assert_se(expected == v);
      74                 :         28 : }
      75                 :            : 
      76                 :         28 : static void test_config_parse_sec_one(const char *rvalue, usec_t expected) {
      77                 :         28 :         usec_t v = 0;
      78                 :            : 
      79         [ -  + ]:         28 :         assert_se(config_parse_sec("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
      80         [ -  + ]:         28 :         assert_se(expected == v);
      81                 :         28 : }
      82                 :            : 
      83                 :         28 : static void test_config_parse_nsec_one(const char *rvalue, nsec_t expected) {
      84                 :         28 :         nsec_t v = 0;
      85                 :            : 
      86         [ -  + ]:         28 :         assert_se(config_parse_nsec("unit", "filename", 1, "nsection", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
      87         [ -  + ]:         28 :         assert_se(expected == v);
      88                 :         28 : }
      89                 :            : 
      90                 :          4 : static void test_config_parse_path(void) {
      91                 :          4 :         test_config_parse_path_one("/path", "/path");
      92                 :          4 :         test_config_parse_path_one("/path//////////", "/path");
      93                 :          4 :         test_config_parse_path_one("///path/foo///bar////bar//", "/path/foo/bar/bar");
      94                 :          4 :         test_config_parse_path_one("/path//./////hogehoge///.", "/path/hogehoge");
      95                 :          4 :         test_config_parse_path_one("/path/\xc3\x80", "/path/\xc3\x80");
      96                 :            : 
      97                 :          4 :         test_config_parse_path_one("not_absolute/path", NULL);
      98                 :          4 :         test_config_parse_path_one("/path/\xc3\x7f", NULL);
      99                 :          4 : }
     100                 :            : 
     101                 :          4 : static void test_config_parse_log_level(void) {
     102                 :          4 :         test_config_parse_log_level_one("debug", LOG_DEBUG);
     103                 :          4 :         test_config_parse_log_level_one("info", LOG_INFO);
     104                 :            : 
     105                 :          4 :         test_config_parse_log_level_one("garbage", 0);
     106                 :          4 : }
     107                 :            : 
     108                 :          4 : static void test_config_parse_log_facility(void) {
     109                 :          4 :         test_config_parse_log_facility_one("mail", LOG_MAIL);
     110                 :          4 :         test_config_parse_log_facility_one("user", LOG_USER);
     111                 :            : 
     112                 :          4 :         test_config_parse_log_facility_one("garbage", 0);
     113                 :          4 : }
     114                 :            : 
     115                 :          4 : static void test_config_parse_iec_size(void) {
     116                 :          4 :         test_config_parse_iec_size_one("1024", 1024);
     117                 :          4 :         test_config_parse_iec_size_one("2K", 2048);
     118                 :          4 :         test_config_parse_iec_size_one("10M", 10 * 1024 * 1024);
     119                 :          4 :         test_config_parse_iec_size_one("1G", 1 * 1024 * 1024 * 1024);
     120                 :          4 :         test_config_parse_iec_size_one("0G", 0);
     121                 :          4 :         test_config_parse_iec_size_one("0", 0);
     122                 :            : 
     123                 :          4 :         test_config_parse_iec_size_one("-982", 0);
     124                 :          4 :         test_config_parse_iec_size_one("49874444198739873000000G", 0);
     125                 :          4 :         test_config_parse_iec_size_one("garbage", 0);
     126                 :          4 : }
     127                 :            : 
     128                 :          4 : static void test_config_parse_si_size(void) {
     129                 :          4 :         test_config_parse_si_size_one("1024", 1024);
     130                 :          4 :         test_config_parse_si_size_one("2K", 2000);
     131                 :          4 :         test_config_parse_si_size_one("10M", 10 * 1000 * 1000);
     132                 :          4 :         test_config_parse_si_size_one("1G", 1 * 1000 * 1000 * 1000);
     133                 :          4 :         test_config_parse_si_size_one("0G", 0);
     134                 :          4 :         test_config_parse_si_size_one("0", 0);
     135                 :            : 
     136                 :          4 :         test_config_parse_si_size_one("-982", 0);
     137                 :          4 :         test_config_parse_si_size_one("49874444198739873000000G", 0);
     138                 :          4 :         test_config_parse_si_size_one("garbage", 0);
     139                 :          4 : }
     140                 :            : 
     141                 :          4 : static void test_config_parse_int(void) {
     142                 :          4 :         test_config_parse_int_one("1024", 1024);
     143                 :          4 :         test_config_parse_int_one("-1024", -1024);
     144                 :          4 :         test_config_parse_int_one("0", 0);
     145                 :            : 
     146                 :          4 :         test_config_parse_int_one("99999999999999999999999999999999999999999999999999999999", -1);
     147                 :          4 :         test_config_parse_int_one("-99999999999999999999999999999999999999999999999999999999", -1);
     148                 :          4 :         test_config_parse_int_one("1G", -1);
     149                 :          4 :         test_config_parse_int_one("garbage", -1);
     150                 :          4 : }
     151                 :            : 
     152                 :          4 : static void test_config_parse_unsigned(void) {
     153                 :          4 :         test_config_parse_unsigned_one("10241024", 10241024);
     154                 :          4 :         test_config_parse_unsigned_one("1024", 1024);
     155                 :          4 :         test_config_parse_unsigned_one("0", 0);
     156                 :            : 
     157                 :          4 :         test_config_parse_unsigned_one("99999999999999999999999999999999999999999999999999999999", 0);
     158                 :          4 :         test_config_parse_unsigned_one("1G", 0);
     159                 :          4 :         test_config_parse_unsigned_one("garbage", 0);
     160                 :          4 :         test_config_parse_unsigned_one("1000garbage", 0);
     161                 :          4 : }
     162                 :            : 
     163                 :          4 : static void test_config_parse_strv(void) {
     164                 :          4 :         test_config_parse_strv_one("", STRV_MAKE_EMPTY);
     165                 :          4 :         test_config_parse_strv_one("foo", STRV_MAKE("foo"));
     166                 :          4 :         test_config_parse_strv_one("foo bar foo", STRV_MAKE("foo", "bar", "foo"));
     167                 :          4 :         test_config_parse_strv_one("\"foo bar\" foo", STRV_MAKE("foo bar", "foo"));
     168                 :          4 :         test_config_parse_strv_one("\xc3\x80", STRV_MAKE("\xc3\x80"));
     169                 :          4 :         test_config_parse_strv_one("\xc3\x7f", STRV_MAKE("\xc3\x7f"));
     170                 :          4 : }
     171                 :            : 
     172                 :          4 : static void test_config_parse_mode(void) {
     173                 :          4 :         test_config_parse_mode_one("777", 0777);
     174                 :          4 :         test_config_parse_mode_one("644", 0644);
     175                 :            : 
     176                 :          4 :         test_config_parse_mode_one("-777", 0);
     177                 :          4 :         test_config_parse_mode_one("999", 0);
     178                 :          4 :         test_config_parse_mode_one("garbage", 0);
     179                 :          4 :         test_config_parse_mode_one("777garbage", 0);
     180                 :          4 :         test_config_parse_mode_one("777 garbage", 0);
     181                 :          4 : }
     182                 :            : 
     183                 :          4 : static void test_config_parse_sec(void) {
     184                 :          4 :         test_config_parse_sec_one("1", 1 * USEC_PER_SEC);
     185                 :          4 :         test_config_parse_sec_one("1s", 1 * USEC_PER_SEC);
     186                 :          4 :         test_config_parse_sec_one("100ms", 100 * USEC_PER_MSEC);
     187                 :          4 :         test_config_parse_sec_one("5min 20s", 5 * 60 * USEC_PER_SEC + 20 * USEC_PER_SEC);
     188                 :            : 
     189                 :          4 :         test_config_parse_sec_one("-1", 0);
     190                 :          4 :         test_config_parse_sec_one("10foo", 0);
     191                 :          4 :         test_config_parse_sec_one("garbage", 0);
     192                 :          4 : }
     193                 :            : 
     194                 :          4 : static void test_config_parse_nsec(void) {
     195                 :          4 :         test_config_parse_nsec_one("1", 1);
     196                 :          4 :         test_config_parse_nsec_one("1s", 1 * NSEC_PER_SEC);
     197                 :          4 :         test_config_parse_nsec_one("100ms", 100 * NSEC_PER_MSEC);
     198                 :          4 :         test_config_parse_nsec_one("5min 20s", 5 * 60 * NSEC_PER_SEC + 20 * NSEC_PER_SEC);
     199                 :            : 
     200                 :          4 :         test_config_parse_nsec_one("-1", 0);
     201                 :          4 :         test_config_parse_nsec_one("10foo", 0);
     202                 :          4 :         test_config_parse_nsec_one("garbage", 0);
     203                 :          4 : }
     204                 :            : 
     205                 :          4 : static void test_config_parse_iec_uint64(void) {
     206                 :          4 :         uint64_t offset = 0;
     207         [ -  + ]:          4 :         assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
     208         [ -  + ]:          4 :         assert_se(offset == 4 * 1024 * 1024);
     209                 :            : 
     210         [ -  + ]:          4 :         assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
     211                 :          4 : }
     212                 :            : 
     213                 :            : #define x10(x) x x x x x x x x x x
     214                 :            : #define x100(x) x10(x10(x))
     215                 :            : #define x1000(x) x10(x100(x))
     216                 :            : 
     217                 :            : static const char* const config_file[] = {
     218                 :            :         "[Section]\n"
     219                 :            :         "setting1=1\n",
     220                 :            : 
     221                 :            :         "[Section]\n"
     222                 :            :         "setting1=1",        /* no terminating newline */
     223                 :            : 
     224                 :            :         "\n\n\n\n[Section]\n\n\n"
     225                 :            :         "setting1=1",        /* some whitespace, no terminating newline */
     226                 :            : 
     227                 :            :         "[Section]\n"
     228                 :            :         "[Section]\n"
     229                 :            :         "setting1=1\n"
     230                 :            :         "setting1=2\n"
     231                 :            :         "setting1=1\n",      /* repeated settings */
     232                 :            : 
     233                 :            :         "[Section]\n"
     234                 :            :         "[Section]\n"
     235                 :            :         "setting1=1\n"
     236                 :            :         "setting1=2\\\n"
     237                 :            :         "   \n"              /* empty line breaks continuation */
     238                 :            :         "setting1=1\n",      /* repeated settings */
     239                 :            : 
     240                 :            :         "[Section]\n"
     241                 :            :         "setting1=1\\\n"     /* normal continuation */
     242                 :            :         "2\\\n"
     243                 :            :         "3\n",
     244                 :            : 
     245                 :            :         "[Section]\n"
     246                 :            :         "#hogehoge\\\n"      /* continuation is ignored in comment */
     247                 :            :         "setting1=1\\\n"     /* normal continuation */
     248                 :            :         "2\\\n"
     249                 :            :         "3\n",
     250                 :            : 
     251                 :            :         "[Section]\n"
     252                 :            :         "setting1=1\\\n"     /* normal continuation */
     253                 :            :         "#hogehoge\\\n"      /* commented out line in continuation is ignored */
     254                 :            :         "2\\\n"
     255                 :            :         "3\n",
     256                 :            : 
     257                 :            :         "[Section]\n"
     258                 :            :         "   #hogehoge\\\n"   /* whitespaces before comments */
     259                 :            :         "   setting1=1\\\n"  /* whitespaces before key */
     260                 :            :         "2\\\n"
     261                 :            :         "3\n",
     262                 :            : 
     263                 :            :         "[Section]\n"
     264                 :            :         "   setting1=1\\\n"  /* whitespaces before key */
     265                 :            :         "   #hogehoge\\\n"   /* commented out line prefixed with whitespaces in continuation */
     266                 :            :         "2\\\n"
     267                 :            :         "3\n",
     268                 :            : 
     269                 :            :         "[Section]\n"
     270                 :            :         "setting1=1\\\n"     /* continuation with extra trailing backslash at the end */
     271                 :            :         "2\\\n"
     272                 :            :         "3\\\n",
     273                 :            : 
     274                 :            :         "[Section]\n"
     275                 :            :         "setting1=1\\\\\\\n" /* continuation with trailing escape symbols */
     276                 :            :         "\\\\2\n",           /* note that C requires one level of escaping, so the
     277                 :            :                               * parser gets "…1 BS BS BS NL BS BS 2 NL", which
     278                 :            :                               * it translates into "…1 BS BS SP BS BS 2" */
     279                 :            : 
     280                 :            :         "\n[Section]\n\n"
     281                 :            :         "setting1="          /* a line above LINE_MAX length */
     282                 :            :         x1000("ABCD")
     283                 :            :         "\n",
     284                 :            : 
     285                 :            :         "[Section]\n"
     286                 :            :         "setting1="          /* a line above LINE_MAX length, with continuation */
     287                 :            :         x1000("ABCD") "\\\n"
     288                 :            :         "foobar",
     289                 :            : 
     290                 :            :         "[Section]\n"
     291                 :            :         "setting1="          /* a line above LINE_MAX length, with continuation */
     292                 :            :         x1000("ABCD") "\\\n" /* and an extra trailing backslash */
     293                 :            :         "foobar\\\n",
     294                 :            : 
     295                 :            :         "[Section]\n"
     296                 :            :         "setting1="          /* a line above the allowed limit: 9 + 1050000 + 1 */
     297                 :            :         x1000(x1000("x") x10("abcde")) "\n",
     298                 :            : 
     299                 :            :         "[Section]\n"
     300                 :            :         "setting1="          /* many continuation lines, together above the limit */
     301                 :            :         x1000(x1000("x") x10("abcde") "\\\n") "xxx",
     302                 :            : };
     303                 :            : 
     304                 :         68 : static void test_config_parse(unsigned i, const char *s) {
     305                 :         68 :         _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-conf-parser.XXXXXX";
     306                 :         68 :         _cleanup_fclose_ FILE *f = NULL;
     307                 :        136 :         _cleanup_free_ char *setting1 = NULL;
     308                 :            :         int r;
     309                 :            : 
     310                 :         68 :         const ConfigTableItem items[] = {
     311                 :            :                 { "Section", "setting1",  config_parse_string,   0, &setting1},
     312                 :            :                 {}
     313                 :            :         };
     314                 :            : 
     315         [ +  - ]:         68 :         log_info("== %s[%i] ==", __func__, i);
     316                 :            : 
     317         [ -  + ]:         68 :         assert_se(fmkostemp_safe(name, "r+", &f) == 0);
     318         [ -  + ]:         68 :         assert_se(fwrite(s, strlen(s), 1, f) == 1);
     319                 :         68 :         rewind(f);
     320                 :            : 
     321                 :            :         /*
     322                 :            :         int config_parse(const char *unit,
     323                 :            :                          const char *filename,
     324                 :            :                          FILE *f,
     325                 :            :                          const char *sections,
     326                 :            :                          ConfigItemLookup lookup,
     327                 :            :                          const void *table,
     328                 :            :                          bool relaxed,
     329                 :            :                          bool allow_include,
     330                 :            :                          bool warn,
     331                 :            :                          void *userdata)
     332                 :            :         */
     333                 :            : 
     334                 :         68 :         r = config_parse(NULL, name, f,
     335                 :            :                          "Section\0",
     336                 :            :                          config_item_table_lookup, items,
     337                 :            :                          CONFIG_PARSE_WARN, NULL);
     338                 :            : 
     339   [ +  +  +  +  :         68 :         switch (i) {
                +  +  - ]
     340                 :         20 :         case 0 ... 4:
     341         [ -  + ]:         20 :                 assert_se(r == 0);
     342         [ -  + ]:         20 :                 assert_se(streq(setting1, "1"));
     343                 :         20 :                 break;
     344                 :            : 
     345                 :         24 :         case 5 ... 10:
     346         [ -  + ]:         24 :                 assert_se(r == 0);
     347         [ -  + ]:         24 :                 assert_se(streq(setting1, "1 2 3"));
     348                 :         24 :                 break;
     349                 :            : 
     350                 :          4 :         case 11:
     351         [ -  + ]:          4 :                 assert_se(r == 0);
     352         [ -  + ]:          4 :                 assert_se(streq(setting1, "1\\\\ \\\\2"));
     353                 :          4 :                 break;
     354                 :            : 
     355                 :          4 :         case 12:
     356         [ -  + ]:          4 :                 assert_se(r == 0);
     357         [ -  + ]:          4 :                 assert_se(streq(setting1, x1000("ABCD")));
     358                 :          4 :                 break;
     359                 :            : 
     360                 :          8 :         case 13 ... 14:
     361         [ -  + ]:          8 :                 assert_se(r == 0);
     362         [ -  + ]:          8 :                 assert_se(streq(setting1, x1000("ABCD") " foobar"));
     363                 :          8 :                 break;
     364                 :            : 
     365                 :          8 :         case 15 ... 16:
     366         [ -  + ]:          8 :                 assert_se(r == -ENOBUFS);
     367         [ -  + ]:          8 :                 assert_se(setting1 == NULL);
     368                 :          8 :                 break;
     369                 :            :         }
     370                 :         68 : }
     371                 :            : 
     372                 :          4 : int main(int argc, char **argv) {
     373                 :            :         unsigned i;
     374                 :            : 
     375                 :          4 :         log_parse_environment();
     376                 :          4 :         log_open();
     377                 :            : 
     378                 :          4 :         test_config_parse_path();
     379                 :          4 :         test_config_parse_log_level();
     380                 :          4 :         test_config_parse_log_facility();
     381                 :          4 :         test_config_parse_iec_size();
     382                 :          4 :         test_config_parse_si_size();
     383                 :          4 :         test_config_parse_int();
     384                 :          4 :         test_config_parse_unsigned();
     385                 :          4 :         test_config_parse_strv();
     386                 :          4 :         test_config_parse_mode();
     387                 :          4 :         test_config_parse_sec();
     388                 :          4 :         test_config_parse_nsec();
     389                 :          4 :         test_config_parse_iec_uint64();
     390                 :            : 
     391         [ +  + ]:         72 :         for (i = 0; i < ELEMENTSOF(config_file); i++)
     392                 :         68 :                 test_config_parse(i, config_file[i]);
     393                 :            : 
     394                 :          4 :         return 0;
     395                 :            : }

Generated by: LCOV version 1.14