xref: /freebsd/contrib/pkgconf/tests/api/test-buffer.c (revision 592efe252472a3385acf36b1f49ecf710a7f3d9c)
1 /*
2  * test-buffer.c
3  * Tests for libpkgconf buffer API.
4  *
5  * SPDX-License-Identifier: pkgconf
6  *
7  * Copyright (c) 2025 pkgconf authors (see AUTHORS).
8  *
9  * Permission to use, copy, modify, and/or distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * This software is provided 'as is' and without any warranty, express or
14  * implied.  In no event shall the authors be liable for any damages arising
15  * from the use of this software.
16  */
17 
18 #include <libpkgconf/stdinc.h>
19 #include <libpkgconf/libpkgconf.h>
20 #include "test-api.h"
21 
22 static void
test_buffer_empty(void)23 test_buffer_empty(void)
24 {
25 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
26 
27 	TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 0);
28 	TEST_ASSERT_NULL(pkgconf_buffer_str(&buf));
29 	TEST_ASSERT_EMPTY_STRING(pkgconf_buffer_str_or_empty(&buf));
30 	TEST_ASSERT_EQ(pkgconf_buffer_lastc(&buf), '\0');
31 
32 	pkgconf_buffer_finalize(&buf);
33 }
34 
35 static void
test_buffer_append(void)36 test_buffer_append(void)
37 {
38 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
39 
40 	TEST_ASSERT_TRUE(pkgconf_buffer_append(&buf, "hello"));
41 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "hello");
42 	TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 5);
43 
44 	TEST_ASSERT_TRUE(pkgconf_buffer_append(&buf, " world"));
45 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "hello world");
46 	TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 11);
47 
48 	TEST_ASSERT_EQ(pkgconf_buffer_lastc(&buf), 'd');
49 
50 	pkgconf_buffer_finalize(&buf);
51 }
52 
53 static void
test_buffer_append_slice(void)54 test_buffer_append_slice(void)
55 {
56 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
57 
58 	TEST_ASSERT_TRUE(pkgconf_buffer_append_slice(&buf, "abcdefgh", 3));
59 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "abc");
60 
61 	TEST_ASSERT_TRUE(pkgconf_buffer_append_slice(&buf, "xyz", 0));
62 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "abc");
63 
64 	pkgconf_buffer_finalize(&buf);
65 }
66 
67 static void
test_buffer_append_fmt(void)68 test_buffer_append_fmt(void)
69 {
70 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
71 
72 	TEST_ASSERT_TRUE(pkgconf_buffer_append_fmt(&buf, "%s=%d", "x", 42));
73 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "x=42");
74 
75 	TEST_ASSERT_TRUE(pkgconf_buffer_append_fmt(&buf, " %s", "ok"));
76 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "x=42 ok");
77 
78 	pkgconf_buffer_finalize(&buf);
79 }
80 
81 static void
test_buffer_prepend(void)82 test_buffer_prepend(void)
83 {
84 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
85 
86 	pkgconf_buffer_append(&buf, "world");
87 	TEST_ASSERT_TRUE(pkgconf_buffer_prepend(&buf, "hello "));
88 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "hello world");
89 
90 	pkgconf_buffer_finalize(&buf);
91 }
92 
93 static void
test_buffer_push_byte(void)94 test_buffer_push_byte(void)
95 {
96 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
97 
98 	TEST_ASSERT_TRUE(pkgconf_buffer_push_byte(&buf, 'a'));
99 	TEST_ASSERT_TRUE(pkgconf_buffer_push_byte(&buf, 'b'));
100 	TEST_ASSERT_TRUE(pkgconf_buffer_push_byte(&buf, 'c'));
101 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "abc");
102 	TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 3);
103 
104 	pkgconf_buffer_finalize(&buf);
105 }
106 
107 static void
test_buffer_trim_byte(void)108 test_buffer_trim_byte(void)
109 {
110 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
111 
112 	pkgconf_buffer_append(&buf, "hello\n");
113 	TEST_ASSERT_TRUE(pkgconf_buffer_trim_byte(&buf));
114 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "hello");
115 
116 	pkgconf_buffer_reset(&buf);
117 	pkgconf_buffer_push_byte(&buf, 'x');
118 	TEST_ASSERT_TRUE(pkgconf_buffer_trim_byte(&buf));
119 	TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 0);
120 	TEST_ASSERT_FALSE(pkgconf_buffer_trim_byte(&buf));
121 
122 	pkgconf_buffer_finalize(&buf);
123 }
124 
125 static void
test_buffer_reset(void)126 test_buffer_reset(void)
127 {
128 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
129 
130 	pkgconf_buffer_append(&buf, "some content");
131 	TEST_ASSERT_NE(pkgconf_buffer_len(&buf), 0);
132 
133 	pkgconf_buffer_reset(&buf);
134 	TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 0);
135 	TEST_ASSERT_NULL(pkgconf_buffer_str(&buf));
136 
137 	TEST_ASSERT_TRUE(pkgconf_buffer_append(&buf, "fresh"));
138 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "fresh");
139 
140 	pkgconf_buffer_finalize(&buf);
141 }
142 
143 static void
test_buffer_freeze(void)144 test_buffer_freeze(void)
145 {
146 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
147 
148 	pkgconf_buffer_append(&buf, "frozen");
149 	char *out = pkgconf_buffer_freeze(&buf);
150 	TEST_ASSERT_NONNULL(out);
151 	TEST_ASSERT_STRCMP_EQ(out, "frozen");
152 	TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 0);
153 
154 	TEST_ASSERT_NULL(pkgconf_buffer_freeze(&buf));
155 
156 	free(out);
157 	pkgconf_buffer_finalize(&buf);
158 }
159 
160 static void
test_buffer_copy(void)161 test_buffer_copy(void)
162 {
163 	pkgconf_buffer_t src = PKGCONF_BUFFER_INITIALIZER;
164 	pkgconf_buffer_t dst = PKGCONF_BUFFER_INITIALIZER;
165 
166 	pkgconf_buffer_append(&src, "original");
167 	pkgconf_buffer_append(&dst, "to be replaced");
168 	TEST_ASSERT_TRUE(pkgconf_buffer_copy(&src, &dst));
169 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst), "original");
170 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&src), "original"); // src is unchanged
171 
172 	pkgconf_buffer_finalize(&src);
173 	pkgconf_buffer_finalize(&dst);
174 }
175 
176 static void
test_buffer_join(void)177 test_buffer_join(void)
178 {
179 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
180 
181 	TEST_ASSERT_TRUE(pkgconf_buffer_join(&buf, '/', "usr", "local", "lib", NULL));
182 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "usr/local/lib");
183 
184 	pkgconf_buffer_finalize(&buf);
185 }
186 
187 static void
test_buffer_contains(void)188 test_buffer_contains(void)
189 {
190 	pkgconf_buffer_t hay = PKGCONF_BUFFER_INITIALIZER;
191 	pkgconf_buffer_t needle = PKGCONF_BUFFER_INITIALIZER;
192 
193 	pkgconf_buffer_append(&hay, "the quick brown fox");
194 
195 	pkgconf_buffer_append(&needle, "quick");
196 	TEST_ASSERT_TRUE(pkgconf_buffer_contains(&hay, &needle));
197 
198 	pkgconf_buffer_reset(&needle);
199 	pkgconf_buffer_append(&needle, "slow");
200 	TEST_ASSERT_FALSE(pkgconf_buffer_contains(&hay, &needle));
201 
202 	TEST_ASSERT_TRUE(pkgconf_buffer_contains_byte(&hay, 'q'));
203 	TEST_ASSERT_FALSE(pkgconf_buffer_contains_byte(&hay, 'z'));
204 
205 	pkgconf_buffer_finalize(&hay);
206 	pkgconf_buffer_finalize(&needle);
207 }
208 
209 static void
test_buffer_match(void)210 test_buffer_match(void)
211 {
212 	pkgconf_buffer_t a = PKGCONF_BUFFER_INITIALIZER;
213 	pkgconf_buffer_t b = PKGCONF_BUFFER_INITIALIZER;
214 
215 	pkgconf_buffer_append(&a, "identical");
216 	pkgconf_buffer_append(&b, "identical");
217 	TEST_ASSERT_TRUE(pkgconf_buffer_match(&a, &b));
218 
219 	// Identical length, but different contents
220 	pkgconf_buffer_reset(&b);
221 	pkgconf_buffer_append(&b, "different");
222 	TEST_ASSERT_FALSE(pkgconf_buffer_match(&a, &b));
223 
224 	// Different length and contents
225 	pkgconf_buffer_reset(&b);
226 	pkgconf_buffer_append(&b, "different!");
227 	TEST_ASSERT_FALSE(pkgconf_buffer_match(&a, &b));
228 
229 	pkgconf_buffer_finalize(&a);
230 	pkgconf_buffer_finalize(&b);
231 }
232 
233 static void
test_buffer_has_prefix(void)234 test_buffer_has_prefix(void)
235 {
236 	pkgconf_buffer_t hay = PKGCONF_BUFFER_INITIALIZER;
237 	pkgconf_buffer_t pre = PKGCONF_BUFFER_INITIALIZER;
238 
239 	pkgconf_buffer_append(&hay, "/usr/local/lib");
240 
241 	pkgconf_buffer_append(&pre, "/usr");
242 	TEST_ASSERT_TRUE(pkgconf_buffer_has_prefix(&hay, &pre));
243 
244 	pkgconf_buffer_reset(&pre);
245 	pkgconf_buffer_append(&pre, "/opt");
246 	TEST_ASSERT_FALSE(pkgconf_buffer_has_prefix(&hay, &pre));
247 
248 	pkgconf_buffer_finalize(&hay);
249 	pkgconf_buffer_finalize(&pre);
250 }
251 
252 static void
test_buffer_subst(void)253 test_buffer_subst(void)
254 {
255 	pkgconf_buffer_t src = PKGCONF_BUFFER_INITIALIZER;
256 	pkgconf_buffer_t dst = PKGCONF_BUFFER_INITIALIZER;
257 
258 	pkgconf_buffer_append(&src, "prefix=${PREFIX}/share");
259 	TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst, &src, "${PREFIX}", "/opt/foo"));
260 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst), "prefix=/opt/foo/share");
261 
262 	pkgconf_buffer_finalize(&src);
263 	pkgconf_buffer_finalize(&dst);
264 }
265 
266 static void
test_buffer_subst_empty_pattern(void)267 test_buffer_subst_empty_pattern(void)
268 {
269 	pkgconf_buffer_t src = PKGCONF_BUFFER_INITIALIZER;
270 	pkgconf_buffer_t dst0 = PKGCONF_BUFFER_INITIALIZER;
271 	pkgconf_buffer_t dst1 = PKGCONF_BUFFER_INITIALIZER;
272 	pkgconf_buffer_t dst2 = PKGCONF_BUFFER_INITIALIZER;
273 	pkgconf_buffer_t dst3 = PKGCONF_BUFFER_INITIALIZER;
274 	pkgconf_buffer_t dst4 = PKGCONF_BUFFER_INITIALIZER;
275 	pkgconf_buffer_t dst5 = PKGCONF_BUFFER_INITIALIZER;
276 
277 	pkgconf_buffer_append(&src, "prefix=${PREFIX}/share");
278 
279 	TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst0, &src, "", "foo"));
280 	TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst1, &src, "", ""));
281 	TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst2, &src, "", NULL));
282 	TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst3, &src, NULL, "foo"));
283 	TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst4, &src, NULL, ""));
284 	TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst5, &src, NULL, NULL));
285 
286 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst0), "prefix=${PREFIX}/share");
287 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst1), "prefix=${PREFIX}/share");
288 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst2), "prefix=${PREFIX}/share");
289 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst3), "prefix=${PREFIX}/share");
290 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst4), "prefix=${PREFIX}/share");
291 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst5), "prefix=${PREFIX}/share");
292 
293 	pkgconf_buffer_finalize(&src);
294 	pkgconf_buffer_finalize(&dst0);
295 	pkgconf_buffer_finalize(&dst1);
296 	pkgconf_buffer_finalize(&dst2);
297 	pkgconf_buffer_finalize(&dst3);
298 	pkgconf_buffer_finalize(&dst4);
299 	pkgconf_buffer_finalize(&dst5);
300 }
301 
302 static void
test_buffer_escape(void)303 test_buffer_escape(void)
304 {
305 	pkgconf_buffer_t src = PKGCONF_BUFFER_INITIALIZER;
306 	pkgconf_buffer_t dst = PKGCONF_BUFFER_INITIALIZER;
307 
308 	pkgconf_span_t spans[] = {
309 		{ ' ', ' ' },
310 		{ '\t', '\t' },
311 	};
312 
313 	pkgconf_buffer_append(&src, "a b\tc");
314 	TEST_ASSERT_TRUE(pkgconf_buffer_escape(&dst, &src, spans, PKGCONF_ARRAY_SIZE(spans)));
315 	TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst), "a\\ b\\\tc");
316 
317 	pkgconf_buffer_finalize(&src);
318 	pkgconf_buffer_finalize(&dst);
319 }
320 
321 static void
test_str_eq_slice(void)322 test_str_eq_slice(void)
323 {
324 	TEST_ASSERT_TRUE(pkgconf_str_eq_slice("hello", "hello", 5));
325 	TEST_ASSERT_FALSE(pkgconf_str_eq_slice("hello!", "hello", 5));
326 	TEST_ASSERT_FALSE(pkgconf_str_eq_slice("hello", "world", 5));
327 	TEST_ASSERT_FALSE(pkgconf_str_eq_slice(NULL, "hello", 5));
328 }
329 
330 static void
test_span_contains(void)331 test_span_contains(void)
332 {
333 	pkgconf_span_t spans[] = {
334 		{ '0', '9' },
335 		{ 'a', 'z' },
336 	};
337 
338 	TEST_ASSERT_TRUE(pkgconf_span_contains('5', spans, PKGCONF_ARRAY_SIZE(spans)));
339 	TEST_ASSERT_TRUE(pkgconf_span_contains('m', spans, PKGCONF_ARRAY_SIZE(spans)));
340 	TEST_ASSERT_FALSE(pkgconf_span_contains('A', spans, PKGCONF_ARRAY_SIZE(spans)));
341 	TEST_ASSERT_FALSE(pkgconf_span_contains('!', spans, PKGCONF_ARRAY_SIZE(spans)));
342 }
343 
344 static void
test_buffer_fputs_nonempty(void)345 test_buffer_fputs_nonempty(void)
346 {
347 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
348 	FILE *f = tmpfile();
349 	TEST_ASSERT_NONNULL(f);
350 
351 	pkgconf_buffer_append(&buf, "hello world");
352 	TEST_ASSERT_TRUE(pkgconf_buffer_fputs(&buf, f));
353 
354 	char out[64];
355 	rewind(f);
356 	size_t n = fread(out, 1, sizeof(out) - 1, f);
357 	out[n] = '\0';
358 
359 	// Buffer contents followed by a newline.
360 	TEST_ASSERT_STRCMP_EQ(out, "hello world\n");
361 
362 	fclose(f);
363 	pkgconf_buffer_finalize(&buf);
364 }
365 
366 static void
test_buffer_fputs_empty(void)367 test_buffer_fputs_empty(void)
368 {
369 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
370 	FILE *f = tmpfile();
371 	TEST_ASSERT_NONNULL(f);
372 
373 	// An empty buffer writes only a newline.
374 	TEST_ASSERT_TRUE(pkgconf_buffer_fputs(&buf, f));
375 
376 	char out[64];
377 	rewind(f);
378 	size_t n = fread(out, 1, sizeof(out) - 1, f);
379 	out[n] = '\0';
380 
381 	TEST_ASSERT_STRCMP_EQ(out, "\n");
382 
383 	fclose(f);
384 	pkgconf_buffer_finalize(&buf);
385 }
386 
387 int
main(int argc,const char ** argv)388 main(int argc, const char **argv)
389 {
390 	(void) argc;
391 
392 	const char *basename = pkgconf_path_find_basename(argv[0]);
393 
394 	TEST_RUN(basename, test_buffer_empty);
395 	TEST_RUN(basename, test_buffer_append);
396 	TEST_RUN(basename, test_buffer_append_slice);
397 	TEST_RUN(basename, test_buffer_append_fmt);
398 	TEST_RUN(basename, test_buffer_prepend);
399 	TEST_RUN(basename, test_buffer_push_byte);
400 	TEST_RUN(basename, test_buffer_trim_byte);
401 	TEST_RUN(basename, test_buffer_reset);
402 	TEST_RUN(basename, test_buffer_freeze);
403 	TEST_RUN(basename, test_buffer_copy);
404 	TEST_RUN(basename, test_buffer_join);
405 	TEST_RUN(basename, test_buffer_contains);
406 	TEST_RUN(basename, test_buffer_match);
407 	TEST_RUN(basename, test_buffer_has_prefix);
408 	TEST_RUN(basename, test_buffer_subst);
409 	TEST_RUN(basename, test_buffer_subst_empty_pattern);
410 	TEST_RUN(basename, test_buffer_escape);
411 	TEST_RUN(basename, test_str_eq_slice);
412 	TEST_RUN(basename, test_span_contains);
413 	TEST_RUN(basename, test_buffer_fputs_nonempty);
414 	TEST_RUN(basename, test_buffer_fputs_empty);
415 
416 	return EXIT_SUCCESS;
417 }
418