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