1 /* 2 * test-path-utils.c 3 * Tests for libpkgconf internal path utility functions. 4 * 5 * SPDX-License-Identifier: pkgconf 6 * 7 * Copyright (c) 2025-2026 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 <libpkgconf/path.h> 21 #include "test-api.h" 22 23 static void 24 test_path_find_basename(void) 25 { 26 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename("/usr/lib/pkgconfig/foo.pc"), "foo.pc"); 27 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename("/usr/lib/pkgconfig"), "pkgconfig"); 28 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename("foo.pc"), "foo.pc"); 29 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename("/foo.pc"), "foo.pc"); 30 TEST_ASSERT_EMPTY_STRING(pkgconf_path_find_basename("/")); 31 TEST_ASSERT_EMPTY_STRING(pkgconf_path_find_basename("")); 32 TEST_ASSERT_EMPTY_STRING(pkgconf_path_find_basename("/usr/")); 33 TEST_ASSERT_EMPTY_STRING(pkgconf_path_find_basename("usr/")); 34 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename("///usr/lib///pkgconfig///foo.pc"), "foo.pc"); 35 #ifdef _WIN32 36 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename("C:\\lib\\pkgconfig\\foo.pc"), "foo.pc"); 37 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename("C:/lib/pkgconfig/foo.pc"), "foo.pc"); 38 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename("C:/lib\\pkgconfig/foo.pc"), "foo.pc"); 39 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename("C:\\lib/pkgconfig\\foo.pc"), "foo.pc"); 40 #endif 41 } 42 43 static void 44 test_path_trim_basename(void) 45 { 46 pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; 47 48 pkgconf_buffer_append(&buf, "/usr/lib/pkgconfig/foo.pc"); 49 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 50 TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "/usr/lib/pkgconfig"); 51 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 52 TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "/usr/lib"); 53 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 54 TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "/usr"); 55 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 56 TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), ""); 57 TEST_ASSERT_FALSE(pkgconf_path_trim_basename(&buf)); 58 TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), ""); 59 60 pkgconf_buffer_reset(&buf); 61 pkgconf_buffer_append(&buf, "foo.pc"); 62 TEST_ASSERT_FALSE(pkgconf_path_trim_basename(&buf)); 63 TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "foo.pc"); 64 65 pkgconf_buffer_finalize(&buf); 66 } 67 68 static void 69 test_determine_prefix_logic(void) 70 { 71 pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; 72 73 // Normal case 74 pkgconf_buffer_append(&buf, "/opt/foo/lib/pkgconfig/bar.pc"); 75 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 76 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename(pkgconf_buffer_str(&buf)), "pkgconfig"); 77 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 78 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 79 TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "/opt/foo"); 80 81 // Short path: /pkgconfig/foo.pc 82 pkgconf_buffer_reset(&buf); 83 pkgconf_buffer_append(&buf, "/pkgconfig/foo.pc"); 84 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 85 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename(pkgconf_buffer_str(&buf)), "pkgconfig"); 86 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); // trims pkgconfig, returns true because of / 87 TEST_ASSERT_FALSE(pkgconf_path_trim_basename(&buf)); // fails to trim further 88 89 // Another short path: lib/pkgconfig/foo.pc 90 pkgconf_buffer_reset(&buf); 91 pkgconf_buffer_append(&buf, "lib/pkgconfig/foo.pc"); 92 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 93 TEST_ASSERT_STRCMP_EQ(pkgconf_path_find_basename(pkgconf_buffer_str(&buf)), "pkgconfig"); 94 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 95 TEST_ASSERT_FALSE(pkgconf_path_trim_basename(&buf)); 96 97 // Trailing slash 98 pkgconf_buffer_reset(&buf); 99 pkgconf_buffer_append(&buf, "/usr/lib/pkgconfig/"); 100 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 101 TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "/usr/lib/pkgconfig"); 102 TEST_ASSERT_TRUE(pkgconf_path_trim_basename(&buf)); 103 TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "/usr/lib"); 104 105 pkgconf_buffer_finalize(&buf); 106 } 107 108 static const char * 109 nth_path(const pkgconf_list_t *list, size_t idx) 110 { 111 pkgconf_node_t *n; 112 size_t i = 0; 113 114 PKGCONF_FOREACH_LIST_ENTRY(list->head, n) 115 { 116 const pkgconf_path_t *p = n->data; 117 118 if (i++ == idx) 119 return p->path; 120 } 121 122 return NULL; 123 } 124 125 static void 126 test_path_prepend(void) 127 { 128 pkgconf_list_t list = PKGCONF_LIST_INITIALIZER; 129 130 pkgconf_path_prepend("/a", &list, false); 131 pkgconf_path_prepend("/b", &list, false); 132 pkgconf_path_prepend("/c", &list, false); 133 134 TEST_ASSERT_EQ(list.length, 3); 135 TEST_ASSERT_STRCMP_EQ(nth_path(&list, 0), "/c"); 136 TEST_ASSERT_STRCMP_EQ(nth_path(&list, 1), "/b"); 137 TEST_ASSERT_STRCMP_EQ(nth_path(&list, 2), "/a"); 138 139 pkgconf_path_add("/d", &list, false); 140 TEST_ASSERT_EQ(list.length, 4); 141 TEST_ASSERT_STRCMP_EQ(nth_path(&list, 0), "/c"); 142 TEST_ASSERT_STRCMP_EQ(nth_path(&list, 3), "/d"); 143 144 pkgconf_path_prepend("/e//f", &list, false); 145 TEST_ASSERT_STRCMP_EQ(nth_path(&list, 0), "/e/f"); 146 147 pkgconf_path_free(&list); 148 TEST_ASSERT_EQ(list.length, 0); 149 TEST_ASSERT_NULL(list.head); 150 TEST_ASSERT_NULL(list.tail); 151 } 152 153 static void 154 test_path_prepend_filter(void) 155 { 156 pkgconf_list_t list = PKGCONF_LIST_INITIALIZER; 157 158 pkgconf_path_prepend(".", &list, true); 159 TEST_ASSERT_EQ(list.length, 1); 160 161 pkgconf_path_prepend(".", &list, true); 162 TEST_ASSERT_EQ(list.length, 1); 163 164 pkgconf_path_prepend("..", &list, true); 165 TEST_ASSERT_EQ(list.length, 2); 166 167 pkgconf_path_prepend(".", &list, false); 168 TEST_ASSERT_EQ(list.length, 3); 169 170 pkgconf_path_free(&list); 171 } 172 173 static void 174 test_path_prepend_list(void) 175 { 176 pkgconf_list_t src = PKGCONF_LIST_INITIALIZER; 177 pkgconf_list_t dst = PKGCONF_LIST_INITIALIZER; 178 179 pkgconf_path_add("/s1", &src, false); 180 pkgconf_path_add("/s2", &src, false); 181 pkgconf_path_add("/s3", &src, false); 182 183 pkgconf_path_add("/d1", &dst, false); 184 pkgconf_path_add("/d2", &dst, false); 185 186 pkgconf_path_prepend_list(&dst, &src); 187 188 TEST_ASSERT_EQ(dst.length, 5); 189 TEST_ASSERT_STRCMP_EQ(nth_path(&dst, 0), "/s3"); 190 TEST_ASSERT_STRCMP_EQ(nth_path(&dst, 1), "/s2"); 191 TEST_ASSERT_STRCMP_EQ(nth_path(&dst, 2), "/s1"); 192 TEST_ASSERT_STRCMP_EQ(nth_path(&dst, 3), "/d1"); 193 TEST_ASSERT_STRCMP_EQ(nth_path(&dst, 4), "/d2"); 194 195 TEST_ASSERT_EQ(src.length, 3); 196 TEST_ASSERT_STRCMP_EQ(nth_path(&src, 0), "/s1"); 197 TEST_ASSERT_TRUE(nth_path(&dst, 2) != nth_path(&src, 0)); 198 199 pkgconf_path_free(&dst); 200 TEST_ASSERT_EQ(dst.length, 0); 201 202 TEST_ASSERT_EQ(src.length, 3); 203 TEST_ASSERT_STRCMP_EQ(nth_path(&src, 2), "/s3"); 204 205 pkgconf_path_prepend_list(&dst, &src); 206 TEST_ASSERT_EQ(dst.length, 3); 207 TEST_ASSERT_STRCMP_EQ(nth_path(&dst, 0), "/s3"); 208 TEST_ASSERT_STRCMP_EQ(nth_path(&dst, 2), "/s1"); 209 210 pkgconf_path_free(&src); 211 pkgconf_path_free(&dst); 212 } 213 214 static bool 215 plausible(const char *text) 216 { 217 pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; 218 bool result; 219 220 pkgconf_buffer_append(&buf, text); 221 result = pkgconf_path_is_plausible(&buf); 222 pkgconf_buffer_finalize(&buf); 223 224 return result; 225 } 226 227 static void 228 test_path_is_plausible(void) 229 { 230 pkgconf_buffer_t empty = PKGCONF_BUFFER_INITIALIZER; 231 232 TEST_ASSERT_FALSE(pkgconf_path_is_plausible(NULL)); 233 TEST_ASSERT_FALSE(pkgconf_path_is_plausible(&empty)); 234 pkgconf_buffer_finalize(&empty); 235 236 TEST_ASSERT_FALSE(plausible("")); 237 TEST_ASSERT_FALSE(plausible(" ")); 238 TEST_ASSERT_FALSE(plausible("libfoo")); 239 TEST_ASSERT_FALSE(plausible("foo bar")); 240 TEST_ASSERT_FALSE(plausible(".")); 241 TEST_ASSERT_FALSE(plausible("..")); 242 243 TEST_ASSERT_TRUE(plausible("/usr/lib/pkgconfig")); 244 TEST_ASSERT_TRUE(plausible(" /usr/lib")); 245 TEST_ASSERT_TRUE(plausible("./foo")); 246 TEST_ASSERT_TRUE(plausible("../foo")); 247 TEST_ASSERT_TRUE(plausible(".\\foo")); 248 TEST_ASSERT_TRUE(plausible("..\\foo")); 249 TEST_ASSERT_TRUE(plausible("C:/foo")); 250 TEST_ASSERT_TRUE(plausible("C:\\foo")); 251 TEST_ASSERT_TRUE(plausible("relative/path")); 252 TEST_ASSERT_TRUE(plausible("relative\\path")); 253 TEST_ASSERT_TRUE(plausible("Program Files/MySDK")); 254 } 255 256 int 257 main(int argc, char *argv[]) 258 { 259 (void) argc; 260 const char *basename = pkgconf_path_find_basename(argv[0]); 261 262 TEST_RUN(basename, test_path_find_basename); 263 TEST_RUN(basename, test_path_trim_basename); 264 TEST_RUN(basename, test_determine_prefix_logic); 265 TEST_RUN(basename, test_path_prepend); 266 TEST_RUN(basename, test_path_prepend_filter); 267 TEST_RUN(basename, test_path_prepend_list); 268 TEST_RUN(basename, test_path_is_plausible); 269 270 return EXIT_SUCCESS; 271 } 272