1 #include <unistd.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include "kvvec.c"
6 #include "t-utils.h"
7
8 static int walking_steps, walks;
9
walker(struct key_value * kv,void * discard)10 static int walker(struct key_value *kv, void *discard)
11 {
12 static struct kvvec *vec = (void *)1;
13 static int step;
14
15 walking_steps++;
16
17 if (vec != discard) {
18 walks++;
19 vec = (struct kvvec *)discard;
20 step = 0;
21 }
22
23 if (discard && vec) {
24 t_ok(!kv_compare(&vec->kv[step], kv), "step %d on walk %d",
25 step, walks);
26 }
27
28 step++;
29
30 return 0;
31 }
32
33 #define KVSEP '='
34 #define PAIRSEP '\0'
35 #define OVERALLOC 2
36
37 static const char *test_data[] = {
38 "lala=trudeldudel",
39 "foo=bar",
40 "LOTS AND LOTS OF CAPS WITH SPACES=weird",
41 "key=value",
42 "something-random=pre-determined luls",
43 "string=with\nnewlines\n\n\nand\nlots\nof\nthem\ntoo\n",
44 "tabs= this and that and three in a row",
45 NULL,
46 };
47
48 static const char *pair_term_missing[] = {
49 "foo=bar;lul=bar;haha=lulu",
50 "foo=bar;lul=bar;haha=lulu;",
51 "hobbit=palace;gandalf=wizard1",
52 "hobbit=palace;gandalf=wizard1;",
53 "0=0;1=1;2=2;3=3;4=4",
54 "0=0;1=1;2=2;3=3;4=4;",
55 NULL,
56 };
57
add_vars(struct kvvec * kvv,const char ** ary,int len)58 static void add_vars(struct kvvec *kvv, const char **ary, int len)
59 {
60 int i;
61
62 for (i = 0; i < len && ary[i]; i++) {
63 char *arg = strdup(test_data[i]);
64 char *eq = strchr(arg, '=');
65 if (eq) {
66 *eq++ = 0;
67 }
68 kvvec_addkv(kvv, strdup(arg), eq ? strdup(eq) : NULL);
69 free(arg);
70 }
71 }
72
main(int argc,char ** argv)73 int main(int argc, char **argv)
74 {
75 int i, j;
76 struct kvvec *kvv, *kvv2, *kvv3;
77 struct kvvec_buf *kvvb, *kvvb2;
78 struct kvvec k = KVVEC_INITIALIZER;
79
80 t_set_colors(0);
81
82 t_start("key/value vector tests");
83 kvv = kvvec_create(1);
84 ok_int(kvvec_capacity(kvv), 1, "capacity of one should be guaranteed");
85 kvv2 = kvvec_create(1);
86 kvv3 = kvvec_create(1);
87 add_vars(kvv, test_data, 1239819);
88 add_vars(kvv, (const char **)argv + 1, argc - 1);
89
90 kvvec_sort(kvv);
91 kvvec_foreach(kvv, NULL, walker);
92
93 /* kvvec2buf -> buf2kvvec -> kvvec2buf -> buf2kvvec conversion */
94 kvvb = kvvec2buf(kvv, KVSEP, PAIRSEP, OVERALLOC);
95 kvv3 = buf2kvvec(kvvb->buf, kvvb->buflen, KVSEP, PAIRSEP, KVVEC_COPY);
96 kvvb2 = kvvec2buf(kvv3, KVSEP, PAIRSEP, OVERALLOC);
97
98 buf2kvvec_prealloc(kvv2, kvvb->buf, kvvb->buflen, KVSEP, PAIRSEP, KVVEC_ASSIGN);
99 kvvec_foreach(kvv2, kvv, walker);
100
101 kvvb = kvvec2buf(kvv, KVSEP, PAIRSEP, OVERALLOC);
102
103 test(kvv->kv_pairs == kvv2->kv_pairs, "pairs should be identical");
104
105 for (i = 0; i < kvv->kv_pairs; i++) {
106 struct key_value *kv1, *kv2;
107 kv1 = &kvv->kv[i];
108 if (i >= kvv2->kv_pairs) {
109 t_fail("missing var %d in kvv2", i);
110 printf("[%s=%s] (%d+%d)\n", kv1->key, kv1->value, kv1->key_len, kv1->value_len);
111 continue;
112 }
113 kv2 = &kvv2->kv[i];
114 if (!test(!kv_compare(kv1, kv2), "kv pair %d must match", i)) {
115 printf("%d failed: [%s=%s] (%d+%d) != [%s=%s (%d+%d)]\n",
116 i,
117 kv1->key, kv1->value, kv1->key_len, kv1->value_len,
118 kv2->key, kv2->value, kv2->key_len, kv2->value_len);
119 }
120 }
121
122 test(kvvb2->buflen == kvvb->buflen, "buflens must match");
123 test(kvvb2->bufsize == kvvb->bufsize, "bufsizes must match");
124
125 if (kvvb2->buflen == kvvb->buflen && kvvb2->bufsize == kvvb->bufsize &&
126 !memcmp(kvvb2->buf, kvvb->buf, kvvb->bufsize))
127 {
128 t_pass("kvvec -> buf -> kvvec conversion works flawlessly");
129 } else {
130 t_fail("kvvec -> buf -> kvvec conversion failed :'(");
131 }
132
133 free(kvvb->buf);
134 free(kvvb);
135 free(kvvb2->buf);
136 free(kvvb2);
137 kvvec_destroy(kvv, 1);
138 kvvec_destroy(kvv3, KVVEC_FREE_ALL);
139
140 for (j = 0; pair_term_missing[j]; j++) {
141 buf2kvvec_prealloc(&k, strdup(pair_term_missing[j]), strlen(pair_term_missing[j]), '=', ';', KVVEC_COPY);
142 for (i = 0; i < k.kv_pairs; i++) {
143 struct key_value *kv = &k.kv[i];
144 test(kv->key_len == kv->value_len, "%d.%d; key_len=%d; value_len=%d (%s = %s)",
145 j, i, kv->key_len, kv->value_len, kv->key, kv->value);
146 test(kv->value_len == (int)strlen(kv->value),
147 "%d.%d; kv->value_len(%d) == strlen(%s)(%d)",
148 j, i, kv->value_len, kv->value, (int)strlen(kv->value));
149 }
150 }
151
152 t_end();
153 return 0;
154 }
155