1 /* 2 * test-queue.c 3 * Tests for the public libpkgconf queue API. 4 * 5 * SPDX-License-Identifier: pkgconf 6 * 7 * Copyright (c) 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 "test-api.h" 19 20 #define FIXTURE_DIR "test-queue-pcdir" 21 22 static void 23 write_pc(const char *name, const char *contents) 24 { 25 char path[512]; 26 FILE *f; 27 28 snprintf(path, sizeof path, "%s/%s", FIXTURE_DIR, name); 29 f = fopen(path, "wb"); 30 TEST_ASSERT_NONNULL(f); 31 fwrite(contents, 1, strlen(contents), f); 32 fclose(f); 33 } 34 35 static void 36 setup_fixtures(void) 37 { 38 mkdir(FIXTURE_DIR, 0755); 39 write_pc("qbar.pc", "Name: qbar\nDescription: bar\nVersion: 2.0\n"); 40 write_pc("qfoo.pc", 41 "Name: qfoo\nDescription: foo\nVersion: 1.0\nRequires: qbar >= 1.0\n"); 42 } 43 44 static void 45 teardown_fixtures(void) 46 { 47 remove(FIXTURE_DIR "/qfoo.pc"); 48 remove(FIXTURE_DIR "/qbar.pc"); 49 rmdir(FIXTURE_DIR); 50 } 51 52 static pkgconf_client_t * 53 fixture_client(void) 54 { 55 pkgconf_client_t *client = test_client_new(); 56 57 pkgconf_path_free(&client->dir_list); 58 pkgconf_path_add(FIXTURE_DIR, &client->dir_list, false); 59 60 return client; 61 } 62 63 static size_t 64 required_count(const pkgconf_pkg_t *world) 65 { 66 size_t n = 0; 67 const pkgconf_node_t *iter; 68 69 PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) 70 { 71 n++; 72 } 73 74 return n; 75 } 76 77 static bool 78 contains_dep(const pkgconf_pkg_t *world, const char *name) 79 { 80 const pkgconf_node_t *iter; 81 82 PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter) 83 { 84 const pkgconf_dependency_t *dep = iter->data; 85 86 if (!strcmp(dep->package, name)) 87 return true; 88 } 89 90 return false; 91 } 92 93 static void 94 test_queue_validate_success(void) 95 { 96 pkgconf_client_t *client = fixture_client(); 97 pkgconf_list_t queue = PKGCONF_LIST_INITIALIZER; 98 99 pkgconf_queue_push(&queue, "qfoo"); 100 TEST_ASSERT_TRUE(pkgconf_queue_validate(client, &queue, -1)); 101 102 pkgconf_queue_free(&queue); 103 pkgconf_client_free(client); 104 } 105 106 static void 107 test_queue_validate_version_satisfied(void) 108 { 109 pkgconf_client_t *client = fixture_client(); 110 pkgconf_list_t queue = PKGCONF_LIST_INITIALIZER; 111 112 pkgconf_queue_push(&queue, "qbar >= 1.0"); 113 TEST_ASSERT_TRUE(pkgconf_queue_validate(client, &queue, -1)); 114 115 pkgconf_queue_free(&queue); 116 pkgconf_client_free(client); 117 } 118 119 static void 120 test_queue_validate_missing_package(void) 121 { 122 pkgconf_client_t *client = fixture_client(); 123 pkgconf_list_t queue = PKGCONF_LIST_INITIALIZER; 124 125 pkgconf_queue_push(&queue, "does-not-exist"); 126 TEST_ASSERT_FALSE(pkgconf_queue_validate(client, &queue, -1)); 127 128 pkgconf_queue_free(&queue); 129 pkgconf_client_free(client); 130 } 131 132 static void 133 test_queue_validate_unsatisfiable_version(void) 134 { 135 pkgconf_client_t *client = fixture_client(); 136 pkgconf_list_t queue = PKGCONF_LIST_INITIALIZER; 137 138 pkgconf_queue_push(&queue, "qbar >= 99.0"); 139 TEST_ASSERT_FALSE(pkgconf_queue_validate(client, &queue, -1)); 140 141 pkgconf_queue_free(&queue); 142 pkgconf_client_free(client); 143 } 144 145 static void 146 test_queue_validate_empty(void) 147 { 148 pkgconf_client_t *client = fixture_client(); 149 pkgconf_list_t queue = PKGCONF_LIST_INITIALIZER; 150 151 TEST_ASSERT_FALSE(pkgconf_queue_validate(client, &queue, -1)); 152 153 pkgconf_queue_free(&queue); 154 pkgconf_client_free(client); 155 } 156 157 struct apply_state { 158 int calls; 159 size_t deps; 160 bool saw_qfoo; 161 bool saw_qbar; 162 bool retval; 163 }; 164 165 static bool 166 apply_cb(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) 167 { 168 struct apply_state *st = data; 169 170 (void) client; 171 (void) maxdepth; 172 173 st->calls++; 174 st->deps = required_count(world); 175 st->saw_qfoo = contains_dep(world, "qfoo"); 176 st->saw_qbar = contains_dep(world, "qbar"); 177 178 return st->retval; 179 } 180 181 static void 182 test_queue_apply_success(void) 183 { 184 pkgconf_client_t *client = fixture_client(); 185 pkgconf_list_t queue = PKGCONF_LIST_INITIALIZER; 186 struct apply_state st = { .retval = true }; 187 188 pkgconf_queue_push(&queue, "qfoo"); 189 TEST_ASSERT_TRUE(pkgconf_queue_apply(client, &queue, apply_cb, -1, &st)); 190 191 TEST_ASSERT_EQ(st.calls, 1); 192 TEST_ASSERT_GE(st.deps, 2); 193 TEST_ASSERT_TRUE(st.saw_qfoo); 194 TEST_ASSERT_TRUE(st.saw_qbar); 195 196 pkgconf_queue_free(&queue); 197 pkgconf_client_free(client); 198 } 199 200 static void 201 test_queue_apply_callback_failure(void) 202 { 203 pkgconf_client_t *client = fixture_client(); 204 pkgconf_list_t queue = PKGCONF_LIST_INITIALIZER; 205 struct apply_state st = { .retval = false }; 206 207 pkgconf_queue_push(&queue, "qfoo"); 208 TEST_ASSERT_FALSE(pkgconf_queue_apply(client, &queue, apply_cb, -1, &st)); 209 TEST_ASSERT_EQ(st.calls, 1); 210 211 pkgconf_queue_free(&queue); 212 pkgconf_client_free(client); 213 } 214 215 static void 216 test_queue_apply_missing_package(void) 217 { 218 pkgconf_client_t *client = fixture_client(); 219 pkgconf_list_t queue = PKGCONF_LIST_INITIALIZER; 220 struct apply_state st = { .retval = true }; 221 222 pkgconf_queue_push(&queue, "does-not-exist"); 223 TEST_ASSERT_FALSE(pkgconf_queue_apply(client, &queue, apply_cb, -1, &st)); 224 TEST_ASSERT_EQ(st.calls, 0); 225 226 pkgconf_queue_free(&queue); 227 pkgconf_client_free(client); 228 } 229 230 int 231 main(int argc, char *argv[]) 232 { 233 (void) argc; 234 const char *basename = pkgconf_path_find_basename(argv[0]); 235 236 setup_fixtures(); 237 238 TEST_RUN(basename, test_queue_validate_success); 239 TEST_RUN(basename, test_queue_validate_version_satisfied); 240 TEST_RUN(basename, test_queue_validate_missing_package); 241 TEST_RUN(basename, test_queue_validate_unsatisfiable_version); 242 TEST_RUN(basename, test_queue_validate_empty); 243 TEST_RUN(basename, test_queue_apply_success); 244 TEST_RUN(basename, test_queue_apply_callback_failure); 245 TEST_RUN(basename, test_queue_apply_missing_package); 246 247 teardown_fixtures(); 248 249 return EXIT_SUCCESS; 250 } 251