LCOV - code coverage report
Current view: top level - test - test-conf-parser.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 209 209 100.0 %
Date: 2019-08-22 15:41:25 Functions: 25 25 100.0 %

          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           7 : static void test_config_parse_path_one(const char *rvalue, const char *expected) {
      14           7 :         _cleanup_free_ char *path = NULL;
      15             : 
      16           7 :         assert_se(config_parse_path("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &path, NULL) >= 0);
      17           7 :         assert_se(streq_ptr(expected, path));
      18           7 : }
      19             : 
      20           3 : static void test_config_parse_log_level_one(const char *rvalue, int expected) {
      21           3 :         int log_level = 0;
      22             : 
      23           3 :         assert_se(config_parse_log_level("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_level, NULL) >= 0);
      24           3 :         assert_se(expected == log_level);
      25           3 : }
      26             : 
      27           3 : static void test_config_parse_log_facility_one(const char *rvalue, int expected) {
      28           3 :         int log_facility = 0;
      29             : 
      30           3 :         assert_se(config_parse_log_facility("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_facility, NULL) >= 0);
      31           3 :         assert_se(expected == log_facility);
      32           3 : }
      33             : 
      34           9 : static void test_config_parse_iec_size_one(const char *rvalue, size_t expected) {
      35           9 :         size_t iec_size = 0;
      36             : 
      37           9 :         assert_se(config_parse_iec_size("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &iec_size, NULL) >= 0);
      38           9 :         assert_se(expected == iec_size);
      39           9 : }
      40             : 
      41           9 : static void test_config_parse_si_size_one(const char *rvalue, size_t expected) {
      42           9 :         size_t si_size = 0;
      43             : 
      44           9 :         assert_se(config_parse_si_size("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &si_size, NULL) >= 0);
      45           9 :         assert_se(expected == si_size);
      46           9 : }
      47             : 
      48           7 : static void test_config_parse_int_one(const char *rvalue, int expected) {
      49           7 :         int v = -1;
      50             : 
      51           7 :         assert_se(config_parse_int("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
      52           7 :         assert_se(expected == v);
      53           7 : }
      54             : 
      55           7 : static void test_config_parse_unsigned_one(const char *rvalue, unsigned expected) {
      56           7 :         unsigned v = 0;
      57             : 
      58           7 :         assert_se(config_parse_unsigned("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
      59           7 :         assert_se(expected == v);
      60           7 : }
      61             : 
      62           6 : static void test_config_parse_strv_one(const char *rvalue, char **expected) {
      63           6 :         _cleanup_strv_free_ char **strv = NULL;
      64             : 
      65           6 :         assert_se(config_parse_strv("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &strv, NULL) >= 0);
      66           6 :         assert_se(strv_equal(expected, strv));
      67           6 : }
      68             : 
      69           7 : static void test_config_parse_mode_one(const char *rvalue, mode_t expected) {
      70           7 :         mode_t v = 0;
      71             : 
      72           7 :         assert_se(config_parse_mode("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
      73           7 :         assert_se(expected == v);
      74           7 : }
      75             : 
      76           7 : static void test_config_parse_sec_one(const char *rvalue, usec_t expected) {
      77           7 :         usec_t v = 0;
      78             : 
      79           7 :         assert_se(config_parse_sec("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
      80           7 :         assert_se(expected == v);
      81           7 : }
      82             : 
      83           7 : static void test_config_parse_nsec_one(const char *rvalue, nsec_t expected) {
      84           7 :         nsec_t v = 0;
      85             : 
      86           7 :         assert_se(config_parse_nsec("unit", "filename", 1, "nsection", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
      87           7 :         assert_se(expected == v);
      88           7 : }
      89             : 
      90           1 : static void test_config_parse_path(void) {
      91           1 :         test_config_parse_path_one("/path", "/path");
      92           1 :         test_config_parse_path_one("/path//////////", "/path");
      93           1 :         test_config_parse_path_one("///path/foo///bar////bar//", "/path/foo/bar/bar");
      94           1 :         test_config_parse_path_one("/path//./////hogehoge///.", "/path/hogehoge");
      95           1 :         test_config_parse_path_one("/path/\xc3\x80", "/path/\xc3\x80");
      96             : 
      97           1 :         test_config_parse_path_one("not_absolute/path", NULL);
      98           1 :         test_config_parse_path_one("/path/\xc3\x7f", NULL);
      99           1 : }
     100             : 
     101           1 : static void test_config_parse_log_level(void) {
     102           1 :         test_config_parse_log_level_one("debug", LOG_DEBUG);
     103           1 :         test_config_parse_log_level_one("info", LOG_INFO);
     104             : 
     105           1 :         test_config_parse_log_level_one("garbage", 0);
     106           1 : }
     107             : 
     108           1 : static void test_config_parse_log_facility(void) {
     109           1 :         test_config_parse_log_facility_one("mail", LOG_MAIL);
     110           1 :         test_config_parse_log_facility_one("user", LOG_USER);
     111             : 
     112           1 :         test_config_parse_log_facility_one("garbage", 0);
     113           1 : }
     114             : 
     115           1 : static void test_config_parse_iec_size(void) {
     116           1 :         test_config_parse_iec_size_one("1024", 1024);
     117           1 :         test_config_parse_iec_size_one("2K", 2048);
     118           1 :         test_config_parse_iec_size_one("10M", 10 * 1024 * 1024);
     119           1 :         test_config_parse_iec_size_one("1G", 1 * 1024 * 1024 * 1024);
     120           1 :         test_config_parse_iec_size_one("0G", 0);
     121           1 :         test_config_parse_iec_size_one("0", 0);
     122             : 
     123           1 :         test_config_parse_iec_size_one("-982", 0);
     124           1 :         test_config_parse_iec_size_one("49874444198739873000000G", 0);
     125           1 :         test_config_parse_iec_size_one("garbage", 0);
     126           1 : }
     127             : 
     128           1 : static void test_config_parse_si_size(void) {
     129           1 :         test_config_parse_si_size_one("1024", 1024);
     130           1 :         test_config_parse_si_size_one("2K", 2000);
     131           1 :         test_config_parse_si_size_one("10M", 10 * 1000 * 1000);
     132           1 :         test_config_parse_si_size_one("1G", 1 * 1000 * 1000 * 1000);
     133           1 :         test_config_parse_si_size_one("0G", 0);
     134           1 :         test_config_parse_si_size_one("0", 0);
     135             : 
     136           1 :         test_config_parse_si_size_one("-982", 0);
     137           1 :         test_config_parse_si_size_one("49874444198739873000000G", 0);
     138           1 :         test_config_parse_si_size_one("garbage", 0);
     139           1 : }
     140             : 
     141           1 : static void test_config_parse_int(void) {
     142           1 :         test_config_parse_int_one("1024", 1024);
     143           1 :         test_config_parse_int_one("-1024", -1024);
     144           1 :         test_config_parse_int_one("0", 0);
     145             : 
     146           1 :         test_config_parse_int_one("99999999999999999999999999999999999999999999999999999999", -1);
     147           1 :         test_config_parse_int_one("-99999999999999999999999999999999999999999999999999999999", -1);
     148           1 :         test_config_parse_int_one("1G", -1);
     149           1 :         test_config_parse_int_one("garbage", -1);
     150           1 : }
     151             : 
     152           1 : static void test_config_parse_unsigned(void) {
     153           1 :         test_config_parse_unsigned_one("10241024", 10241024);
     154           1 :         test_config_parse_unsigned_one("1024", 1024);
     155           1 :         test_config_parse_unsigned_one("0", 0);
     156             : 
     157           1 :         test_config_parse_unsigned_one("99999999999999999999999999999999999999999999999999999999", 0);
     158           1 :         test_config_parse_unsigned_one("1G", 0);
     159           1 :         test_config_parse_unsigned_one("garbage", 0);
     160           1 :         test_config_parse_unsigned_one("1000garbage", 0);
     161           1 : }
     162             : 
     163           1 : static void test_config_parse_strv(void) {
     164           1 :         test_config_parse_strv_one("", STRV_MAKE_EMPTY);
     165           1 :         test_config_parse_strv_one("foo", STRV_MAKE("foo"));
     166           1 :         test_config_parse_strv_one("foo bar foo", STRV_MAKE("foo", "bar", "foo"));
     167           1 :         test_config_parse_strv_one("\"foo bar\" foo", STRV_MAKE("foo bar", "foo"));
     168           1 :         test_config_parse_strv_one("\xc3\x80", STRV_MAKE("\xc3\x80"));
     169           1 :         test_config_parse_strv_one("\xc3\x7f", STRV_MAKE("\xc3\x7f"));
     170           1 : }
     171             : 
     172           1 : static void test_config_parse_mode(void) {
     173           1 :         test_config_parse_mode_one("777", 0777);
     174           1 :         test_config_parse_mode_one("644", 0644);
     175             : 
     176           1 :         test_config_parse_mode_one("-777", 0);
     177           1 :         test_config_parse_mode_one("999", 0);
     178           1 :         test_config_parse_mode_one("garbage", 0);
     179           1 :         test_config_parse_mode_one("777garbage", 0);
     180           1 :         test_config_parse_mode_one("777 garbage", 0);
     181           1 : }
     182             : 
     183           1 : static void test_config_parse_sec(void) {
     184           1 :         test_config_parse_sec_one("1", 1 * USEC_PER_SEC);
     185           1 :         test_config_parse_sec_one("1s", 1 * USEC_PER_SEC);
     186           1 :         test_config_parse_sec_one("100ms", 100 * USEC_PER_MSEC);
     187           1 :         test_config_parse_sec_one("5min 20s", 5 * 60 * USEC_PER_SEC + 20 * USEC_PER_SEC);
     188             : 
     189           1 :         test_config_parse_sec_one("-1", 0);
     190           1 :         test_config_parse_sec_one("10foo", 0);
     191           1 :         test_config_parse_sec_one("garbage", 0);
     192           1 : }
     193             : 
     194           1 : static void test_config_parse_nsec(void) {
     195           1 :         test_config_parse_nsec_one("1", 1);
     196           1 :         test_config_parse_nsec_one("1s", 1 * NSEC_PER_SEC);
     197           1 :         test_config_parse_nsec_one("100ms", 100 * NSEC_PER_MSEC);
     198           1 :         test_config_parse_nsec_one("5min 20s", 5 * 60 * NSEC_PER_SEC + 20 * NSEC_PER_SEC);
     199             : 
     200           1 :         test_config_parse_nsec_one("-1", 0);
     201           1 :         test_config_parse_nsec_one("10foo", 0);
     202           1 :         test_config_parse_nsec_one("garbage", 0);
     203           1 : }
     204             : 
     205           1 : static void test_config_parse_iec_uint64(void) {
     206           1 :         uint64_t offset = 0;
     207           1 :         assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
     208           1 :         assert_se(offset == 4 * 1024 * 1024);
     209             : 
     210           1 :         assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
     211           1 : }
     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          17 : static void test_config_parse(unsigned i, const char *s) {
     305          17 :         _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-conf-parser.XXXXXX";
     306          17 :         _cleanup_fclose_ FILE *f = NULL;
     307          34 :         _cleanup_free_ char *setting1 = NULL;
     308             :         int r;
     309             : 
     310          17 :         const ConfigTableItem items[] = {
     311             :                 { "Section", "setting1",  config_parse_string,   0, &setting1},
     312             :                 {}
     313             :         };
     314             : 
     315          17 :         log_info("== %s[%i] ==", __func__, i);
     316             : 
     317          17 :         assert_se(fmkostemp_safe(name, "r+", &f) == 0);
     318          17 :         assert_se(fwrite(s, strlen(s), 1, f) == 1);
     319          17 :         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          17 :         r = config_parse(NULL, name, f,
     335             :                          "Section\0",
     336             :                          config_item_table_lookup, items,
     337             :                          CONFIG_PARSE_WARN, NULL);
     338             : 
     339          17 :         switch (i) {
     340           5 :         case 0 ... 4:
     341           5 :                 assert_se(r == 0);
     342           5 :                 assert_se(streq(setting1, "1"));
     343           5 :                 break;
     344             : 
     345           6 :         case 5 ... 10:
     346           6 :                 assert_se(r == 0);
     347           6 :                 assert_se(streq(setting1, "1 2 3"));
     348           6 :                 break;
     349             : 
     350           1 :         case 11:
     351           1 :                 assert_se(r == 0);
     352           1 :                 assert_se(streq(setting1, "1\\\\ \\\\2"));
     353           1 :                 break;
     354             : 
     355           1 :         case 12:
     356           1 :                 assert_se(r == 0);
     357           1 :                 assert_se(streq(setting1, x1000("ABCD")));
     358           1 :                 break;
     359             : 
     360           2 :         case 13 ... 14:
     361           2 :                 assert_se(r == 0);
     362           2 :                 assert_se(streq(setting1, x1000("ABCD") " foobar"));
     363           2 :                 break;
     364             : 
     365           2 :         case 15 ... 16:
     366           2 :                 assert_se(r == -ENOBUFS);
     367           2 :                 assert_se(setting1 == NULL);
     368           2 :                 break;
     369             :         }
     370          17 : }
     371             : 
     372           1 : int main(int argc, char **argv) {
     373             :         unsigned i;
     374             : 
     375           1 :         log_parse_environment();
     376           1 :         log_open();
     377             : 
     378           1 :         test_config_parse_path();
     379           1 :         test_config_parse_log_level();
     380           1 :         test_config_parse_log_facility();
     381           1 :         test_config_parse_iec_size();
     382           1 :         test_config_parse_si_size();
     383           1 :         test_config_parse_int();
     384           1 :         test_config_parse_unsigned();
     385           1 :         test_config_parse_strv();
     386           1 :         test_config_parse_mode();
     387           1 :         test_config_parse_sec();
     388           1 :         test_config_parse_nsec();
     389           1 :         test_config_parse_iec_uint64();
     390             : 
     391          18 :         for (i = 0; i < ELEMENTSOF(config_file); i++)
     392          17 :                 test_config_parse(i, config_file[i]);
     393             : 
     394           1 :         return 0;
     395             : }

Generated by: LCOV version 1.14