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