1*592efe25SPierre Pronchery /*
2*592efe25SPierre Pronchery * test-audit.c
3*592efe25SPierre Pronchery * Tests for the public libpkgconf audit 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 /*
21*592efe25SPierre Pronchery * Read the entire contents of f (from the start) into buf.
22*592efe25SPierre Pronchery * buf must be large enough; we keep test inputs small.
23*592efe25SPierre Pronchery */
24*592efe25SPierre Pronchery static void
slurp(FILE * f,char * buf,size_t bufsz)25*592efe25SPierre Pronchery slurp(FILE *f, char *buf, size_t bufsz)
26*592efe25SPierre Pronchery {
27*592efe25SPierre Pronchery rewind(f);
28*592efe25SPierre Pronchery size_t n = fread(buf, 1, bufsz - 1, f);
29*592efe25SPierre Pronchery buf[n] = '\0';
30*592efe25SPierre Pronchery }
31*592efe25SPierre Pronchery
32*592efe25SPierre Pronchery static void
test_audit_log_no_logfile_is_noop(void)33*592efe25SPierre Pronchery test_audit_log_no_logfile_is_noop(void)
34*592efe25SPierre Pronchery {
35*592efe25SPierre Pronchery pkgconf_client_t *client = test_client_new();
36*592efe25SPierre Pronchery
37*592efe25SPierre Pronchery // With no audit log set, logging must be a silent no-op and must not crash.
38*592efe25SPierre Pronchery pkgconf_audit_log(client, "should go nowhere\n");
39*592efe25SPierre Pronchery
40*592efe25SPierre Pronchery pkgconf_client_free(client);
41*592efe25SPierre Pronchery }
42*592efe25SPierre Pronchery
43*592efe25SPierre Pronchery static void
test_audit_set_log_and_write(void)44*592efe25SPierre Pronchery test_audit_set_log_and_write(void)
45*592efe25SPierre Pronchery {
46*592efe25SPierre Pronchery pkgconf_client_t *client = test_client_new();
47*592efe25SPierre Pronchery FILE *logf = tmpfile();
48*592efe25SPierre Pronchery TEST_ASSERT_NONNULL(logf);
49*592efe25SPierre Pronchery
50*592efe25SPierre Pronchery pkgconf_audit_set_log(client, logf);
51*592efe25SPierre Pronchery pkgconf_audit_log(client, "hello %s\n", "world");
52*592efe25SPierre Pronchery
53*592efe25SPierre Pronchery char buf[256];
54*592efe25SPierre Pronchery slurp(logf, buf, sizeof(buf));
55*592efe25SPierre Pronchery TEST_ASSERT_STRCMP_EQ(buf, "hello world\n");
56*592efe25SPierre Pronchery
57*592efe25SPierre Pronchery fclose(logf);
58*592efe25SPierre Pronchery pkgconf_client_free(client);
59*592efe25SPierre Pronchery }
60*592efe25SPierre Pronchery
61*592efe25SPierre Pronchery static void
test_audit_log_multiple_writes(void)62*592efe25SPierre Pronchery test_audit_log_multiple_writes(void)
63*592efe25SPierre Pronchery {
64*592efe25SPierre Pronchery pkgconf_client_t *client = test_client_new();
65*592efe25SPierre Pronchery FILE *logf = tmpfile();
66*592efe25SPierre Pronchery TEST_ASSERT_NONNULL(logf);
67*592efe25SPierre Pronchery
68*592efe25SPierre Pronchery pkgconf_audit_set_log(client, logf);
69*592efe25SPierre Pronchery pkgconf_audit_log(client, "first\n");
70*592efe25SPierre Pronchery pkgconf_audit_log(client, "second %d\n", 2);
71*592efe25SPierre Pronchery
72*592efe25SPierre Pronchery char buf[256];
73*592efe25SPierre Pronchery slurp(logf, buf, sizeof(buf));
74*592efe25SPierre Pronchery TEST_ASSERT_STRCMP_EQ(buf, "first\nsecond 2\n");
75*592efe25SPierre Pronchery
76*592efe25SPierre Pronchery fclose(logf);
77*592efe25SPierre Pronchery pkgconf_client_free(client);
78*592efe25SPierre Pronchery }
79*592efe25SPierre Pronchery
80*592efe25SPierre Pronchery static void
test_audit_log_dependency_versionless(void)81*592efe25SPierre Pronchery test_audit_log_dependency_versionless(void)
82*592efe25SPierre Pronchery {
83*592efe25SPierre Pronchery pkgconf_client_t *client = test_client_new();
84*592efe25SPierre Pronchery FILE *logf = tmpfile();
85*592efe25SPierre Pronchery TEST_ASSERT_NONNULL(logf);
86*592efe25SPierre Pronchery
87*592efe25SPierre Pronchery pkgconf_audit_set_log(client, logf);
88*592efe25SPierre Pronchery
89*592efe25SPierre Pronchery // A minimal package: only the fields the logger reads
90*592efe25SPierre Pronchery pkgconf_pkg_t pkg = { 0 };
91*592efe25SPierre Pronchery pkg.id = (char *) "foo";
92*592efe25SPierre Pronchery pkg.version = (char *) "1.2.3";
93*592efe25SPierre Pronchery
94*592efe25SPierre Pronchery /* A dependency with PKGCONF_CMP_ANY and no version: the logger
95*592efe25SPierre Pronchery * should emit only "id [version]", skipping the comparator */
96*592efe25SPierre Pronchery pkgconf_dependency_t dep = { 0 };
97*592efe25SPierre Pronchery dep.compare = PKGCONF_CMP_ANY;
98*592efe25SPierre Pronchery dep.version = NULL;
99*592efe25SPierre Pronchery
100*592efe25SPierre Pronchery pkgconf_audit_log_dependency(client, &pkg, &dep);
101*592efe25SPierre Pronchery
102*592efe25SPierre Pronchery char buf[256];
103*592efe25SPierre Pronchery slurp(logf, buf, sizeof(buf));
104*592efe25SPierre Pronchery TEST_ASSERT_STRCMP_EQ(buf, "foo [1.2.3]\n");
105*592efe25SPierre Pronchery
106*592efe25SPierre Pronchery fclose(logf);
107*592efe25SPierre Pronchery pkgconf_client_free(client);
108*592efe25SPierre Pronchery }
109*592efe25SPierre Pronchery
110*592efe25SPierre Pronchery static void
test_audit_log_dependency_versioned(void)111*592efe25SPierre Pronchery test_audit_log_dependency_versioned(void)
112*592efe25SPierre Pronchery {
113*592efe25SPierre Pronchery pkgconf_client_t *client = test_client_new();
114*592efe25SPierre Pronchery FILE *logf = tmpfile();
115*592efe25SPierre Pronchery TEST_ASSERT_NONNULL(logf);
116*592efe25SPierre Pronchery
117*592efe25SPierre Pronchery pkgconf_audit_set_log(client, logf);
118*592efe25SPierre Pronchery
119*592efe25SPierre Pronchery pkgconf_pkg_t pkg = { 0 };
120*592efe25SPierre Pronchery pkg.id = (char *) "bar";
121*592efe25SPierre Pronchery pkg.version = (char *) "2.0";
122*592efe25SPierre Pronchery
123*592efe25SPierre Pronchery /* version set AND compare != ANY: the logger emits the
124*592efe25SPierre Pronchery * comparator and required version between id and [version] */
125*592efe25SPierre Pronchery pkgconf_dependency_t dep = { 0 };
126*592efe25SPierre Pronchery dep.compare = PKGCONF_CMP_GREATER_THAN_EQUAL;
127*592efe25SPierre Pronchery dep.version = (char *) "1.5";
128*592efe25SPierre Pronchery
129*592efe25SPierre Pronchery pkgconf_audit_log_dependency(client, &pkg, &dep);
130*592efe25SPierre Pronchery
131*592efe25SPierre Pronchery char buf[256];
132*592efe25SPierre Pronchery slurp(logf, buf, sizeof(buf));
133*592efe25SPierre Pronchery TEST_ASSERT_STRCMP_EQ(buf, "bar >= 1.5 [2.0]\n");
134*592efe25SPierre Pronchery
135*592efe25SPierre Pronchery fclose(logf);
136*592efe25SPierre Pronchery pkgconf_client_free(client);
137*592efe25SPierre Pronchery }
138*592efe25SPierre Pronchery
139*592efe25SPierre Pronchery static void
test_audit_log_dependency_no_logfile_is_noop(void)140*592efe25SPierre Pronchery test_audit_log_dependency_no_logfile_is_noop(void)
141*592efe25SPierre Pronchery {
142*592efe25SPierre Pronchery pkgconf_client_t *client = test_client_new();
143*592efe25SPierre Pronchery
144*592efe25SPierre Pronchery pkgconf_pkg_t pkg = { 0 };
145*592efe25SPierre Pronchery pkg.id = (char *) "foo";
146*592efe25SPierre Pronchery pkg.version = (char *) "1.0";
147*592efe25SPierre Pronchery
148*592efe25SPierre Pronchery pkgconf_dependency_t dep = { 0 };
149*592efe25SPierre Pronchery dep.compare = PKGCONF_CMP_ANY;
150*592efe25SPierre Pronchery
151*592efe25SPierre Pronchery // No log set: must be a silent no-op
152*592efe25SPierre Pronchery pkgconf_audit_log_dependency(client, &pkg, &dep);
153*592efe25SPierre Pronchery
154*592efe25SPierre Pronchery pkgconf_client_free(client);
155*592efe25SPierre Pronchery }
156*592efe25SPierre Pronchery
157*592efe25SPierre Pronchery int
main(int argc,char * argv[])158*592efe25SPierre Pronchery main(int argc, char *argv[])
159*592efe25SPierre Pronchery {
160*592efe25SPierre Pronchery (void) argc;
161*592efe25SPierre Pronchery const char *basename = pkgconf_path_find_basename(argv[0]);
162*592efe25SPierre Pronchery
163*592efe25SPierre Pronchery TEST_RUN(basename, test_audit_log_no_logfile_is_noop);
164*592efe25SPierre Pronchery TEST_RUN(basename, test_audit_set_log_and_write);
165*592efe25SPierre Pronchery TEST_RUN(basename, test_audit_log_multiple_writes);
166*592efe25SPierre Pronchery TEST_RUN(basename, test_audit_log_dependency_versionless);
167*592efe25SPierre Pronchery TEST_RUN(basename, test_audit_log_dependency_versioned);
168*592efe25SPierre Pronchery TEST_RUN(basename, test_audit_log_dependency_no_logfile_is_noop);
169*592efe25SPierre Pronchery
170*592efe25SPierre Pronchery return EXIT_SUCCESS;
171*592efe25SPierre Pronchery }
172