]> git.ozlabs.org Git - petitboot/blob - test/lib/test-fold.c
Fix pb-discover segfaults caused by list corruption.
[petitboot] / test / lib / test-fold.c
1
2 #define _GNU_SOURCE
3
4 #include <stdlib.h>
5 #include <string.h>
6 #include <assert.h>
7 #include <locale.h>
8 #include <wchar.h>
9 #include <langinfo.h>
10
11 #include <fold/fold.h>
12 #include <list/list.h>
13 #include <talloc/talloc.h>
14
15 struct line {
16         const char              *buf;
17         unsigned int            len;
18         struct list_item        list;
19 };
20
21 struct ctx {
22         struct list             lines;
23 };
24
25 struct test {
26         const char      *in;
27         unsigned int    linelen;
28         const char      *out[];
29 };
30
31 /* split on newline boundaries, no actual folding */
32 struct test test_split = {
33         .in     = "Lorem ipsum dolor\nsit amet,\nconsectetuer\n",
34         .linelen = 20,
35         .out = {
36                 "Lorem ipsum dolor",
37                 "sit amet,",
38                 "consectetuer",
39                 "",
40                 NULL,
41         },
42 };
43
44 /* fold a long line */
45 struct test test_fold_line = {
46         .in = "Lorem ipsum dolor sit amet, consectetuer adipiscing "
47                 "elit, sed diam nonummy nibh euismod tincidunt ut "
48                 "laoreet dolore magna aliquam erat volutpat.",
49         .linelen = 20,
50         .out = {
51                 "Lorem ipsum dolor",
52                 "sit amet,",
53                 "consectetuer",
54                 "adipiscing elit,",
55                 "sed diam nonummy",
56                 "nibh euismod",
57                 "tincidunt ut",
58                 "laoreet dolore",
59                 "magna aliquam erat",
60                 "volutpat.",
61                 NULL
62         },
63 };
64
65 /* break a word */
66 struct test test_break = {
67         .in = "Lorem ipsum dolor sit amet, consectetuer",
68         .linelen = 10,
69         .out = {
70                 "Lorem",
71                 "ipsum",
72                 "dolor sit",
73                 "amet,",
74                 "consectetu",
75                 "er",
76                 NULL
77         },
78 };
79
80 struct test test_mbs = {
81         .in = "從主功能表畫面中,選取啟動選項。",
82         .linelen = 15,
83         .out = {
84                 "從主功能表畫面",
85                 "中,選取啟動選",
86                 "項。",
87                 NULL,
88         },
89 };
90
91 struct test test_mbs_sep = {
92         .in = "從主功 能表 畫面中,選 取啟 動選項。",
93         .linelen = 15,
94         .out = {
95                 "從主功 能表",
96                 "畫面中,選",
97                 "取啟 動選項。",
98                 NULL,
99         },
100 };
101
102 static struct test *tests[] = {
103         &test_split, &test_fold_line, &test_break, &test_mbs, &test_mbs_sep,
104 };
105
106 static void __attribute__((noreturn)) fail(struct ctx *ctx,
107                 struct test *test, const char *msg)
108 {
109         struct line *line;
110         int i;
111
112         fprintf(stderr, "%s\n", msg);
113         fprintf(stderr, "input, split at %d:\n%s\n", test->linelen, test->in);
114
115         fprintf(stderr, "expected:\n");
116         for (i = 0; test->out[i]; i++)
117                 fprintf(stderr, "  '%s'\n", test->out[i]);
118
119         fprintf(stderr, "actual:\n");
120         list_for_each_entry(&ctx->lines, line, list) {
121                 char *buf = talloc_strndup(ctx, line->buf, line->len);
122                 fprintf(stderr, "  '%s'\n", buf);
123                 talloc_free(buf);
124         }
125
126         exit(EXIT_FAILURE);
127 }
128
129 static int fold_line_cb(void *arg, const char *start, int len)
130 {
131         struct ctx *ctx = arg;
132         struct line *line;
133
134         line = talloc(ctx, struct line);
135         line->buf = start;
136         line->len = len;
137         list_add_tail(&ctx->lines, &line->list);
138
139         return 0;
140 }
141
142 static void run_test(struct test *test)
143 {
144         struct line *line;
145         struct ctx *ctx;
146         wchar_t *wcs;
147         int i, n;
148
149         ctx = talloc(NULL, struct ctx);
150         n = strlen(test->in) + 1;
151         list_init(&ctx->lines);
152         fold_text(test->in, test->linelen, fold_line_cb, ctx);
153
154
155         i = 0;
156         list_for_each_entry(&ctx->lines, line, list) {
157                 size_t wcslen;
158                 char *buf;
159                 int width;
160
161                 if (!test->out[i])
162                         fail(ctx, test,
163                                 "fold_text returned more lines than expected");
164
165                 buf = talloc_strndup(ctx, line->buf, line->len);
166                 wcslen = mbstowcs(NULL, buf, 0);
167
168                 if (wcslen == (size_t)-1)
169                         fail(ctx, test, "invalid mutlibyte sequence");
170
171                 wcs = talloc_array(ctx, wchar_t, wcslen + 1);
172                 wcslen = mbstowcs(wcs, buf, n);
173
174                 width = wcswidth(wcs, wcslen);
175                 if (width == -1)
176                         fail(ctx, test, "nonprintable characters present");
177
178                 if (width > (signed int)test->linelen)
179                         fail(ctx, test, "line too long");
180
181                 if (line->len != strlen(test->out[i]))
182                         fail(ctx, test, "line lengths differ");
183
184                 if (strncmp(line->buf, test->out[i], line->len))
185                         fail(ctx, test, "line data differs");
186
187                 i++;
188         }
189
190         if (test->out[i])
191                 fail(ctx, test, "fold_text returned fewer lines than expected");
192
193         talloc_free(ctx);
194 }
195
196 int main(void)
197 {
198         unsigned int i;
199         char *charset;
200
201         setlocale(LC_CTYPE, "");
202
203         charset = nl_langinfo(CODESET);
204         if (strcmp(charset, "UTF-8")) {
205                 fprintf(stderr, "Current charset is %s, tests require UTF-8\n",
206                                 charset);
207                 return EXIT_FAILURE;
208         }
209
210         for (i = 0; i < ARRAY_SIZE(tests); i++)
211                 run_test(tests[i]);
212
213         return EXIT_SUCCESS;
214 }