cnfparse.c

Small library to make config parsing easier
git clone git://git.finwo.net/lib/cnfparse.c
Log | Files | Refs | README | LICENSE

0000-basics.c (8412B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 
      5 #include "assert.h"
      6 #include "cnfparse.h"
      7 
      8 static FILE *open_string(const char *text) {
      9   return fmemopen((void *)text, strlen(text), "r");
     10 }
     11 
     12 void test_empty_file() {
     13   FILE *fd = open_string("");
     14   ASSERT("fmemopen succeeds", fd != NULL);
     15   struct cnf_directive *dir = cnf_directive_read(fd);
     16   ASSERT("empty file returns NULL", dir == NULL);
     17   fclose(fd);
     18 }
     19 
     20 void test_blank_lines_only() {
     21   FILE *fd = open_string("\n\n   \t\r\n");
     22   ASSERT("fmemopen succeeds", fd != NULL);
     23   struct cnf_directive *dir = cnf_directive_read(fd);
     24   ASSERT("blank lines return NULL", dir == NULL);
     25   fclose(fd);
     26 }
     27 
     28 void test_comment_only_line() {
     29   FILE *fd = open_string("# this is a comment line\n");
     30   ASSERT("fmemopen succeeds", fd != NULL);
     31   struct cnf_directive *dir = cnf_directive_read(fd);
     32   ASSERT("comment-only line returns NULL", dir == NULL);
     33   fclose(fd);
     34 }
     35 
     36 void test_single_word_no_args() {
     37   FILE *fd = open_string("directive\n");
     38   ASSERT("fmemopen succeeds", fd != NULL);
     39   struct cnf_directive *dir = cnf_directive_read(fd);
     40   ASSERT("non-empty directive returned", dir != NULL);
     41   ASSERT_STRING_EQUALS("directive", dir->name);
     42   ASSERT_EQUALS(0, dir->argc);
     43   cnf_directive_free(dir);
     44   fclose(fd);
     45 }
     46 
     47 void test_leading_whitespace() {
     48   FILE *fd = open_string("   \t leading_spaces\n");
     49   ASSERT("fmemopen succeeds", fd != NULL);
     50   struct cnf_directive *dir = cnf_directive_read(fd);
     51   ASSERT("directive with leading whitespace returned", dir != NULL);
     52   ASSERT_STRING_EQUALS("leading_spaces", dir->name);
     53   ASSERT_EQUALS(0, dir->argc);
     54   cnf_directive_free(dir);
     55   fclose(fd);
     56 }
     57 
     58 void test_trailing_whitespace() {
     59   FILE *fd = open_string("trailing   \t\n");
     60   ASSERT("fmemopen succeeds", fd != NULL);
     61   struct cnf_directive *dir = cnf_directive_read(fd);
     62   ASSERT("directive with trailing whitespace returned", dir != NULL);
     63   ASSERT_STRING_EQUALS("trailing", dir->name);
     64   ASSERT_EQUALS(0, dir->argc);
     65   cnf_directive_free(dir);
     66   fclose(fd);
     67 }
     68 
     69 void test_multiple_space_separated_args() {
     70   FILE *fd = open_string("add 10.0.0.0/8 via 192.168.1.1\n");
     71   ASSERT("fmemopen succeeds", fd != NULL);
     72   struct cnf_directive *dir = cnf_directive_read(fd);
     73   ASSERT("directive with args returned", dir != NULL);
     74   ASSERT_STRING_EQUALS("add", dir->name);
     75   ASSERT_EQUALS(3, dir->argc);
     76   ASSERT_STRING_EQUALS("10.0.0.0/8", dir->argv[0]);
     77   ASSERT_STRING_EQUALS("via", dir->argv[1]);
     78   ASSERT_STRING_EQUALS("192.168.1.1", dir->argv[2]);
     79   cnf_directive_free(dir);
     80   fclose(fd);
     81 }
     82 
     83 void test_multiple_spaces_between_args() {
     84   FILE *fd = open_string("   del    10.1.0.0/16\n");
     85   ASSERT("fmemopen succeeds", fd != NULL);
     86   struct cnf_directive *dir = cnf_directive_read(fd);
     87   ASSERT("directive with extra spaces returned", dir != NULL);
     88   ASSERT_STRING_EQUALS("del", dir->name);
     89   ASSERT_EQUALS(1, dir->argc);
     90   ASSERT_STRING_EQUALS("10.1.0.0/16", dir->argv[0]);
     91   cnf_directive_free(dir);
     92   fclose(fd);
     93 }
     94 
     95 void test_quoted_double_args() {
     96   FILE *fd = open_string("set note \"hello world\" and \"foo bar\"\n");
     97   ASSERT("fmemopen succeeds", fd != NULL);
     98   struct cnf_directive *dir = cnf_directive_read(fd);
     99   ASSERT("directive with quoted args returned", dir != NULL);
    100   ASSERT_STRING_EQUALS("set", dir->name);
    101   ASSERT_EQUALS(4, dir->argc);
    102   ASSERT_STRING_EQUALS("note", dir->argv[0]);
    103   ASSERT_STRING_EQUALS("hello world", dir->argv[1]);
    104   ASSERT_STRING_EQUALS("and", dir->argv[2]);
    105   ASSERT_STRING_EQUALS("foo bar", dir->argv[3]);
    106   fclose(fd);
    107 }
    108 
    109 void test_quoted_single_args() {
    110   FILE *fd = open_string("op 'single quoted'\n");
    111   ASSERT("fmemopen succeeds", fd != NULL);
    112   struct cnf_directive *dir = cnf_directive_read(fd);
    113   ASSERT("directive with single-quoted arg returned", dir != NULL);
    114   ASSERT_STRING_EQUALS("op", dir->name);
    115   ASSERT_EQUALS(1, dir->argc);
    116   ASSERT_STRING_EQUALS("single quoted", dir->argv[0]);
    117   cnf_directive_free(dir);
    118   fclose(fd);
    119 }
    120 
    121 void test_escaped_quote_in_double() {
    122   FILE *fd = open_string("op arg \"a \\\" b\"\n");
    123   ASSERT("fmemopen succeeds", fd != NULL);
    124   struct cnf_directive *dir = cnf_directive_read(fd);
    125   ASSERT("directive with escaped quote returned", dir != NULL);
    126   ASSERT_STRING_EQUALS("op", dir->name);
    127   ASSERT_EQUALS(2, dir->argc);
    128   ASSERT_STRING_EQUALS("arg", dir->argv[0]);
    129   ASSERT_STRING_EQUALS("a \" b", dir->argv[1]);
    130   cnf_directive_free(dir);
    131   fclose(fd);
    132 }
    133 
    134 void test_hash_in_quoted_string() {
    135   FILE *fd = open_string("set note \"a # b\"\n");
    136   ASSERT("fmemopen succeeds", fd != NULL);
    137   struct cnf_directive *dir = cnf_directive_read(fd);
    138   ASSERT("directive with hash in quotes returned", dir != NULL);
    139   ASSERT_STRING_EQUALS("set", dir->name);
    140   ASSERT_EQUALS(2, dir->argc);
    141   ASSERT_STRING_EQUALS("note", dir->argv[0]);
    142   ASSERT_STRING_EQUALS("a # b", dir->argv[1]);
    143   cnf_directive_free(dir);
    144   fclose(fd);
    145 }
    146 
    147 void test_trailing_comment() {
    148   FILE *fd = open_string("op arg # trailing comment\n");
    149   ASSERT("fmemopen succeeds", fd != NULL);
    150   struct cnf_directive *dir = cnf_directive_read(fd);
    151   ASSERT("directive before trailing comment returned", dir != NULL);
    152   ASSERT_STRING_EQUALS("op", dir->name);
    153   ASSERT_EQUALS(1, dir->argc);
    154   ASSERT_STRING_EQUALS("arg", dir->argv[0]);
    155   cnf_directive_free(dir);
    156   fclose(fd);
    157 }
    158 
    159 void test_comment_no_space() {
    160   FILE *fd = open_string("route 172.16.0.0/12 #comment with no space\n");
    161   ASSERT("fmemopen succeeds", fd != NULL);
    162   struct cnf_directive *dir = cnf_directive_read(fd);
    163   ASSERT("directive before tight comment returned", dir != NULL);
    164   ASSERT_STRING_EQUALS("route", dir->name);
    165   ASSERT_EQUALS(1, dir->argc);
    166   ASSERT_STRING_EQUALS("172.16.0.0/12", dir->argv[0]);
    167   cnf_directive_free(dir);
    168   fclose(fd);
    169 }
    170 
    171 void test_multiple_directives_sequence() {
    172   FILE *fd = open_string("first one\nsecond two three\n");
    173   ASSERT("fmemopen succeeds", fd != NULL);
    174 
    175   struct cnf_directive *d1 = cnf_directive_read(fd);
    176   ASSERT("first directive returned", d1 != NULL);
    177   ASSERT_STRING_EQUALS("first", d1->name);
    178   ASSERT_EQUALS(1, d1->argc);
    179   ASSERT_STRING_EQUALS("one", d1->argv[0]);
    180   cnf_directive_free(d1);
    181 
    182   struct cnf_directive *d2 = cnf_directive_read(fd);
    183   ASSERT("second directive returned", d2 != NULL);
    184   ASSERT_STRING_EQUALS("second", d2->name);
    185   ASSERT_EQUALS(2, d2->argc);
    186   ASSERT_STRING_EQUALS("two", d2->argv[0]);
    187   ASSERT_STRING_EQUALS("three", d2->argv[1]);
    188   cnf_directive_free(d2);
    189 
    190   struct cnf_directive *d3 = cnf_directive_read(fd);
    191   ASSERT("exhausted file returns NULL", d3 == NULL);
    192   fclose(fd);
    193 }
    194 
    195 void test_blank_lines_between_directives() {
    196   FILE *fd = open_string("\n\nfirst arg\n\n\nsecond\n");
    197   ASSERT("fmemopen succeeds", fd != NULL);
    198 
    199   struct cnf_directive *d1 = cnf_directive_read(fd);
    200   ASSERT("directive after blank lines returned", d1 != NULL);
    201   ASSERT_STRING_EQUALS("first", d1->name);
    202   ASSERT_EQUALS(1, d1->argc);
    203   cnf_directive_free(d1);
    204 
    205   struct cnf_directive *d2 = cnf_directive_read(fd);
    206   ASSERT("directive after more blank lines returned", d2 != NULL);
    207   ASSERT_STRING_EQUALS("second", d2->name);
    208   ASSERT_EQUALS(0, d2->argc);
    209   cnf_directive_free(d2);
    210 
    211   fclose(fd);
    212 }
    213 
    214 void test_no_trailing_newline() {
    215   FILE *fd = open_string("final one two three");
    216   ASSERT("fmemopen succeeds", fd != NULL);
    217   struct cnf_directive *dir = cnf_directive_read(fd);
    218   ASSERT("directive without trailing newline returned", dir != NULL);
    219   ASSERT_STRING_EQUALS("final", dir->name);
    220   ASSERT_EQUALS(3, dir->argc);
    221   ASSERT_STRING_EQUALS("one", dir->argv[0]);
    222   ASSERT_STRING_EQUALS("two", dir->argv[1]);
    223   ASSERT_STRING_EQUALS("three", dir->argv[2]);
    224   cnf_directive_free(dir);
    225   fclose(fd);
    226 }
    227 
    228 void test_directive_free_null() {
    229   cnf_directive_free(NULL);
    230   ASSERT("free NULL does not crash", 1);
    231 }
    232 
    233 int main(int argc, const char *argv[]) {
    234   RUN(test_empty_file);
    235   RUN(test_blank_lines_only);
    236   RUN(test_comment_only_line);
    237   RUN(test_single_word_no_args);
    238   RUN(test_leading_whitespace);
    239   RUN(test_trailing_whitespace);
    240   RUN(test_multiple_space_separated_args);
    241   RUN(test_multiple_spaces_between_args);
    242   RUN(test_quoted_double_args);
    243   RUN(test_quoted_single_args);
    244   RUN(test_escaped_quote_in_double);
    245   RUN(test_hash_in_quoted_string);
    246   RUN(test_trailing_comment);
    247   RUN(test_comment_no_space);
    248   RUN(test_multiple_directives_sequence);
    249   RUN(test_blank_lines_between_directives);
    250   RUN(test_no_trailing_newline);
    251   RUN(test_directive_free_null);
    252   return TEST_REPORT();
    253 }