1#include "check_confuse.h"
2#include <string.h>
3#include <stdlib.h>
4#include <sys/types.h>
5#include <sys/socket.h>
6#include <netinet/in.h>
7#include <arpa/inet.h>
8
9static cfg_t *cfg;
10
11int parse_ip_address(cfg_t *cfg, cfg_opt_t *opt, const char *value, void *result)
12{
13    struct in_addr *addr = (struct in_addr *)malloc(sizeof(struct in_addr));
14    if(inet_aton(value, addr) == 0)
15    {
16        /*cfg_error(cfg, "invalid IP address %s in section %s", value, cfg->name);*/
17        free(addr);
18        return 1;
19    }
20    *(void **)result = (void *)addr;
21    return 0;
22}
23
24static unsigned char *my_ether_aton(const char *addr)
25{
26    int i;
27    static unsigned int e[6];
28    static unsigned char ec[6];
29    if(sscanf(addr, "%x:%x:%x:%x:%x:%x", &e[0], &e[1], &e[2], &e[3], &e[4], &e[5]) != 6)
30    {
31        return NULL;
32    }
33    for(i = 0; i < 6; i++)
34    {
35        if(e[i] <= 0xff)
36            ec[i] = e[i];
37        else
38            return NULL;
39    }
40    return ec;
41}
42
43static char *my_ether_ntoa(unsigned char *addr)
44{
45    static char buf[18];
46    sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
47            addr[0], addr[0], addr[0], addr[0], addr[0], addr[0]);
48    return buf;
49}
50
51int parse_ether_address(cfg_t *cfg, cfg_opt_t *opt, const char *value, void *result)
52{
53    unsigned char *tmp;
54
55    tmp = my_ether_aton(value);
56    if(tmp == 0)
57    {
58        /*cfg_error(cfg, "invalid Ethernet address %s in section %s", value, cfg->name);*/
59        return 1;
60    }
61    *(void **)result = malloc(6);
62    memcpy(*(void **)result, tmp, 6);
63    return 0;
64}
65
66void single_setup(void)
67{
68    cfg_opt_t subsec_opts[] =
69    {
70        CFG_STR("subsubstring", "subsubdefault", CFGF_NONE),
71        CFG_INT("subsubinteger", -42, CFGF_NONE),
72        CFG_FLOAT("subsubfloat", 19923.1234, CFGF_NONE),
73        CFG_BOOL("subsubbool", cfg_false, CFGF_NONE),
74        CFG_END()
75    };
76
77    cfg_opt_t sec_opts[] =
78    {
79        CFG_STR("substring", "subdefault", CFGF_NONE),
80        CFG_INT("subinteger", 17, CFGF_NONE),
81        CFG_FLOAT("subfloat", 8.37, CFGF_NONE),
82        CFG_BOOL("subbool", cfg_true, CFGF_NONE),
83        CFG_SEC("subsection", subsec_opts, CFGF_NONE),
84        CFG_END()
85    };
86
87    cfg_opt_t nodef_opts[] =
88    {
89        CFG_STR("string", "defvalue", CFGF_NONE),
90        CFG_INT("int", -17, CFGF_NODEFAULT),
91        CFG_END()
92    };
93
94    cfg_opt_t opts[] =
95    {
96        CFG_STR("string", "default", CFGF_NONE),
97        CFG_INT("integer", 4711, CFGF_NONE),
98        CFG_FLOAT("float", 0.42, CFGF_NONE),
99        CFG_BOOL("bool", cfg_false, CFGF_NONE),
100        CFG_PTR_CB("ip-address", 0, CFGF_NONE, parse_ip_address, free),
101        CFG_PTR_CB("ethernet-address", 0, CFGF_NONE, parse_ether_address, free),
102        CFG_SEC("section", sec_opts, CFGF_NONE),
103        CFG_STR("nodefstring", "not used", CFGF_NODEFAULT),
104        CFG_SEC("nodefsec", nodef_opts, CFGF_NODEFAULT),
105        CFG_END()
106    };
107
108    cfg = cfg_init(opts, 0);
109
110    memset(opts, 0, sizeof(opts));
111    memset(sec_opts, 0, sizeof(sec_opts));
112    memset(subsec_opts, 0, sizeof(subsec_opts));
113}
114
115void single_teardown(void)
116{
117    cfg_free(cfg);
118}
119
120void single_string_test(void)
121{
122    char *buf;
123
124    fail_unless(cfg_size(cfg, "string") == 1);
125    fail_unless(cfg_opt_size(cfg_getopt(cfg, "string")) == 1);
126    fail_unless(strcmp(cfg_getstr(cfg, "string"), "default") == 0);
127    fail_unless(cfg_getnstr(cfg, "string", 0) == cfg_getstr(cfg, "string"));
128    fail_unless(cfg_getnstr(cfg, "string", 1) == 0);
129    buf = "string = 'set'";
130    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
131    fail_unless(strcmp(cfg_getstr(cfg, "string"), "set") == 0);
132    cfg_setstr(cfg, "string", "manually set");
133    fail_unless(strcmp(cfg_getstr(cfg, "string"), "manually set") == 0);
134}
135
136void single_integer_test(void)
137{
138    char *buf;
139
140    fail_unless(cfg_size(cfg, "integer") == 1);
141    fail_unless(cfg_opt_size(cfg_getopt(cfg, "integer")) == 1);
142    fail_unless(cfg_getint(cfg, "integer") == 4711);
143    fail_unless(cfg_getnint(cfg, "integer", 0) == cfg_getint(cfg, "integer"));
144    fail_unless(cfg_getnint(cfg, "integer", 1) == 0);
145    buf = "integer = -46";
146    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
147    fail_unless(cfg_getint(cfg, "integer") == -46);
148    cfg_setint(cfg, "integer", 999999);
149    fail_unless(cfg_getint(cfg, "integer") == 999999);
150}
151
152void single_float_test(void)
153{
154    char *buf;
155
156    fail_unless(cfg_size(cfg, "float") == 1);
157    fail_unless(cfg_opt_size(cfg_getopt(cfg, "float")) == 1);
158    fail_unless(cfg_getfloat(cfg, "float") == 0.42);
159    fail_unless(cfg_getnfloat(cfg, "float", 0) == cfg_getfloat(cfg, "float"));
160    fail_unless(cfg_getnfloat(cfg, "float", 1) == 0);
161    buf = "float = -46.777";
162    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
163    fail_unless(cfg_getfloat(cfg, "float") == -46.777);
164    cfg_setfloat(cfg, "float", 5.1234e2);
165    fail_unless(cfg_getfloat(cfg, "float") == 5.1234e2);
166}
167
168void single_bool_test(void)
169{
170    char *buf;
171
172    fail_unless(cfg_size(cfg, "bool") == 1);
173    fail_unless(cfg_opt_size(cfg_getopt(cfg, "bool")) == 1);
174    fail_unless(cfg_getbool(cfg, "bool") == cfg_false);
175
176    buf = "bool = yes";
177    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
178    fail_unless(cfg_getbool(cfg, "bool") == cfg_true);
179    buf = "bool = no";
180    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
181    fail_unless(cfg_getbool(cfg, "bool") == cfg_false);
182    buf = "bool = true";
183    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
184    fail_unless(cfg_getbool(cfg, "bool") == cfg_true);
185    buf = "bool = false";
186    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
187    fail_unless(cfg_getbool(cfg, "bool") == cfg_false);
188    buf = "bool = on";
189    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
190    fail_unless(cfg_getbool(cfg, "bool") == cfg_true);
191    buf = "bool = off";
192    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
193    fail_unless(cfg_getbool(cfg, "bool") == cfg_false);
194
195    cfg_setbool(cfg, "bool", cfg_true);
196    fail_unless(cfg_getbool(cfg, "bool") == cfg_true);
197    cfg_setbool(cfg, "bool", cfg_false);
198    fail_unless(cfg_getbool(cfg, "bool") == cfg_false);
199}
200
201void single_section_test(void)
202{
203    char *buf;
204    cfg_t *sec, *subsec;
205
206    fail_unless(cfg_size(cfg, "section") == 1);
207    fail_unless(cfg_opt_size(cfg_getopt(cfg, "section")) == 1);
208
209    fail_unless(cfg_size(cfg, "section|subsection") == 1);
210    fail_unless(cfg_opt_size(cfg_getopt(cfg, "section|subsection")) == 1);
211
212    fail_unless(cfg_size(cfg, "section|subsection|subsubstring") == 1);
213    fail_unless(cfg_opt_size(cfg_getopt(cfg, "section|subsection|subsubinteger")) == 1);
214
215    fail_unless(cfg_title(cfg_getsec(cfg, "section")) == 0);
216    fail_unless(cfg_title(cfg_getsec(cfg, "section|subsection")) == 0);
217
218    fail_unless(strcmp(cfg_getstr(cfg, "section|substring"), "subdefault") == 0);
219    sec = cfg_getsec(cfg, "section|subsection");
220    fail_unless(sec != 0);
221    fail_unless(cfg_getint(sec, "subsubinteger") == -42);
222
223    fail_unless(cfg_getnsec(cfg, "section", 0) == cfg_getsec(cfg, "section"));
224    fail_unless(cfg_getnsec(cfg, "section", 1) == 0);
225
226    sec = cfg_getsec(cfg, "section");
227    fail_unless(sec != 0);
228    subsec = cfg_getsec(sec, "subsection");
229    fail_unless(subsec != 0);
230    fail_unless(cfg_getfloat(subsec, "subsubfloat") == 19923.1234);
231
232    buf = "section { substring = \"foo\" subsection { subsubstring = \"bar\"} }";
233    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
234}
235
236void single_ptr_test(void)
237{
238    char *buf;
239    struct in_addr *ipaddr;
240    unsigned char *etheraddr, *cmpether;
241
242    fail_unless(cfg_size(cfg, "ip-address") == 0);
243
244    buf = "ip-address = 192.168.0.1";
245    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
246    ipaddr = cfg_getptr(cfg, "ip-address");
247    fail_unless(ipaddr != 0);
248    fail_unless(strcmp("192.168.0.1", inet_ntoa(*ipaddr)) == 0);
249
250    buf = "ip-address = 192.168.0.325";
251    fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR);
252
253    buf = "ethernet-address = '00:03:93:d4:05:58'";
254    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
255    etheraddr = cfg_getptr(cfg, "ethernet-address");
256    fail_unless(etheraddr != 0);
257    fail_unless(my_ether_ntoa(etheraddr) != 0);
258    cmpether = my_ether_aton("00:03:93:d4:05:58");
259    fail_unless(memcmp(etheraddr, cmpether, 6) == 0);
260
261    buf = "ethernet-address = '00:03:93:d4:05'";
262    fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR);
263}
264
265void parse_buf_test(void)
266{
267    char *buf;
268
269    fail_unless(cfg_parse_buf(cfg, 0) == CFG_SUCCESS);
270    fail_unless(cfg_parse_buf(cfg, "") == CFG_SUCCESS);
271
272    buf = "bool = wrong";
273    fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR);
274
275    buf = "string = ";
276    fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR);
277
278    buf = "option = 'value'";
279    fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR);
280}
281
282void nonexistent_option_test(void)
283{
284    fail_unless(cfg_getopt(cfg, "nonexistent") == 0);
285    fail_unless(cfg_getopt(cfg, "section|subnonexistent") == 0);
286}
287
288void nodefault_test(void)
289{
290    char *buf;
291    cfg_t *nodefsec;
292
293    fail_unless(cfg_size(cfg, "nodefstring") == 0);
294    cfg_setstr(cfg, "nodefstring", "manually set");
295    fail_unless(cfg_size(cfg, "nodefstring") == 1);
296    fail_unless(cfg_size(cfg, "nodefsec") == 0);
297
298    buf = "nodefsec {}";
299    fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS);
300    nodefsec = cfg_getsec(cfg, "nodefsec");
301    fail_unless(nodefsec != 0);
302    fail_unless(cfg_size(nodefsec, "string") == 1);
303    fail_unless(cfg_size(nodefsec, "int") == 0);
304}
305
306int
307main(void)
308{
309    single_setup();
310
311    single_string_test();
312    single_integer_test();
313    single_float_test();
314    single_bool_test();
315    single_section_test();
316    single_ptr_test();
317    parse_buf_test();
318    nonexistent_option_test();
319    nodefault_test();
320
321    single_teardown();
322
323    return 0;
324}
325
326