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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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