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 }