xref: /freebsd/contrib/pkgconf/tests/api/test-personality.c (revision 592efe252472a3385acf36b1f49ecf710a7f3d9c)
1*592efe25SPierre Pronchery /*
2*592efe25SPierre Pronchery  * test-personality.c
3*592efe25SPierre Pronchery  * Tests for libpkgconf personality functions.
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 static void
test_personality_deinit_null(void)21*592efe25SPierre Pronchery test_personality_deinit_null(void)
22*592efe25SPierre Pronchery {
23*592efe25SPierre Pronchery 	// Should not crash
24*592efe25SPierre Pronchery 	pkgconf_cross_personality_deinit(NULL);
25*592efe25SPierre Pronchery }
26*592efe25SPierre Pronchery 
27*592efe25SPierre Pronchery static void
test_personality_default_refcount(void)28*592efe25SPierre Pronchery test_personality_default_refcount(void)
29*592efe25SPierre Pronchery {
30*592efe25SPierre Pronchery 	pkgconf_cross_personality_t *p1 = pkgconf_cross_personality_default();
31*592efe25SPierre Pronchery 	pkgconf_cross_personality_t *p2 = pkgconf_cross_personality_default();
32*592efe25SPierre Pronchery 
33*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(p1);
34*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(p2);
35*592efe25SPierre Pronchery 	// Both calls must return the same singleton pointer
36*592efe25SPierre Pronchery 	TEST_ASSERT_EQ((long long)(uintptr_t)p1, (long long)(uintptr_t)p2);
37*592efe25SPierre Pronchery 
38*592efe25SPierre Pronchery 	// Refcount is 2 -> first deinit drops it to 1, must not free
39*592efe25SPierre Pronchery 	pkgconf_cross_personality_deinit(p1);
40*592efe25SPierre Pronchery 	// Refcount is 1 -> second deinit drops to 0, frees internal state
41*592efe25SPierre Pronchery 	pkgconf_cross_personality_deinit(p2);
42*592efe25SPierre Pronchery 
43*592efe25SPierre Pronchery 	// Re-initialise from scratch
44*592efe25SPierre Pronchery 	pkgconf_cross_personality_t *p3 = pkgconf_cross_personality_default();
45*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(p3);
46*592efe25SPierre Pronchery 	pkgconf_cross_personality_deinit(p3);
47*592efe25SPierre Pronchery }
48*592efe25SPierre Pronchery 
49*592efe25SPierre Pronchery #ifndef PKGCONF_LITE
50*592efe25SPierre Pronchery 
51*592efe25SPierre Pronchery static void
test_personality_find_invalid_triplet(void)52*592efe25SPierre Pronchery test_personality_find_invalid_triplet(void)
53*592efe25SPierre Pronchery {
54*592efe25SPierre Pronchery 	/* "bad triplet!" has a space and '!' — both rejected by valid_triplet,
55*592efe25SPierre Pronchery 	 * and the direct-file open will also fail, so result must be NULL. */
56*592efe25SPierre Pronchery 	pkgconf_cross_personality_t *p = pkgconf_cross_personality_find("bad triplet!");
57*592efe25SPierre Pronchery 	TEST_ASSERT_NULL(p);
58*592efe25SPierre Pronchery }
59*592efe25SPierre Pronchery 
60*592efe25SPierre Pronchery static void
test_personality_find_direct_path(void)61*592efe25SPierre Pronchery test_personality_find_direct_path(void)
62*592efe25SPierre Pronchery {
63*592efe25SPierre Pronchery 	char path[] = "test-personality-XXXXXX";
64*592efe25SPierre Pronchery 	int fd = mkstemp(path);
65*592efe25SPierre Pronchery 	TEST_ASSERT_TRUE(fd >= 0);
66*592efe25SPierre Pronchery 
67*592efe25SPierre Pronchery 	FILE *f = fdopen(fd, "w");
68*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(f);
69*592efe25SPierre Pronchery 
70*592efe25SPierre Pronchery 	fprintf(f,
71*592efe25SPierre Pronchery 		"Triplet: x86_64-linux-musl\n"
72*592efe25SPierre Pronchery 		"DefaultSearchPaths: /usr/lib/pkgconfig:/usr/share/pkgconfig\n"
73*592efe25SPierre Pronchery 		"SysrootDir: /opt/sysroot\n"
74*592efe25SPierre Pronchery 		"SystemIncludePaths: /opt/sysroot/usr/include\n"
75*592efe25SPierre Pronchery 		"SystemLibraryPaths: /opt/sysroot/usr/lib\n"
76*592efe25SPierre Pronchery 		"WantDefaultStatic: true\n"
77*592efe25SPierre Pronchery 		"WantDefaultPure: yes\n");
78*592efe25SPierre Pronchery 	fclose(f);
79*592efe25SPierre Pronchery 
80*592efe25SPierre Pronchery 	pkgconf_cross_personality_t *p = pkgconf_cross_personality_find(path);
81*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(p);
82*592efe25SPierre Pronchery 	TEST_ASSERT_STRCMP_EQ(p->name, "x86_64-linux-musl");
83*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(p->sysroot_dir);
84*592efe25SPierre Pronchery 	TEST_ASSERT_STRCMP_EQ(p->sysroot_dir, "/opt/sysroot");
85*592efe25SPierre Pronchery 	TEST_ASSERT_TRUE(p->want_default_static);
86*592efe25SPierre Pronchery 	TEST_ASSERT_TRUE(p->want_default_pure);
87*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(p->dir_list.head);
88*592efe25SPierre Pronchery 
89*592efe25SPierre Pronchery 	// Exercises the non-default free path
90*592efe25SPierre Pronchery 	pkgconf_cross_personality_deinit(p);
91*592efe25SPierre Pronchery 	unlink(path);
92*592efe25SPierre Pronchery }
93*592efe25SPierre Pronchery 
94*592efe25SPierre Pronchery #if !defined(_WIN32) && !defined(__HAIKU__)
95*592efe25SPierre Pronchery 
96*592efe25SPierre Pronchery static void
test_personality_find_via_xdg(void)97*592efe25SPierre Pronchery test_personality_find_via_xdg(void)
98*592efe25SPierre Pronchery {
99*592efe25SPierre Pronchery 	char tmpdir[] = "test-personality-xdg-XXXXXX";
100*592efe25SPierre Pronchery 	char *d = mkdtemp(tmpdir);
101*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(d);
102*592efe25SPierre Pronchery 
103*592efe25SPierre Pronchery 	// build: <tmpdir>/pkgconfig/personality.d/
104*592efe25SPierre Pronchery 	char pkgconfig_dir[4096];
105*592efe25SPierre Pronchery 	char personality_d[4096];
106*592efe25SPierre Pronchery 	char file_path[4096];
107*592efe25SPierre Pronchery 
108*592efe25SPierre Pronchery 	snprintf(pkgconfig_dir, sizeof pkgconfig_dir, "%s/pkgconfig", tmpdir);
109*592efe25SPierre Pronchery 	snprintf(personality_d, sizeof personality_d, "%s/pkgconfig/personality.d", tmpdir);
110*592efe25SPierre Pronchery 	snprintf(file_path, sizeof file_path, "%s/pkgconfig/personality.d/xdg-test-triplet.personality", tmpdir);
111*592efe25SPierre Pronchery 
112*592efe25SPierre Pronchery 	TEST_ASSERT_EQ(mkdir(pkgconfig_dir, 0755), 0);
113*592efe25SPierre Pronchery 	TEST_ASSERT_EQ(mkdir(personality_d, 0755), 0);
114*592efe25SPierre Pronchery 
115*592efe25SPierre Pronchery 	FILE *f = fopen(file_path, "w");
116*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(f);
117*592efe25SPierre Pronchery 	fprintf(f, "SysrootDir: /xdg/sysroot\n");
118*592efe25SPierre Pronchery 	fclose(f);
119*592efe25SPierre Pronchery 
120*592efe25SPierre Pronchery 	setenv("XDG_DATA_HOME", tmpdir, 1);
121*592efe25SPierre Pronchery 
122*592efe25SPierre Pronchery 	pkgconf_cross_personality_t *p = pkgconf_cross_personality_find("xdg-test-triplet");
123*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(p);
124*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(p->sysroot_dir);
125*592efe25SPierre Pronchery 	TEST_ASSERT_STRCMP_EQ(p->sysroot_dir, "/xdg/sysroot");
126*592efe25SPierre Pronchery 
127*592efe25SPierre Pronchery 	// Verify it is NOT the default singleton
128*592efe25SPierre Pronchery 	pkgconf_cross_personality_t *def = pkgconf_cross_personality_default();
129*592efe25SPierre Pronchery 	TEST_ASSERT_NE((long long)(uintptr_t)p, (long long)(uintptr_t)def);
130*592efe25SPierre Pronchery 	// Balance the _default() call above
131*592efe25SPierre Pronchery 	pkgconf_cross_personality_deinit(def);
132*592efe25SPierre Pronchery 
133*592efe25SPierre Pronchery 	// Clean up
134*592efe25SPierre Pronchery 	pkgconf_cross_personality_deinit(p);
135*592efe25SPierre Pronchery 	unsetenv("XDG_DATA_HOME");
136*592efe25SPierre Pronchery 
137*592efe25SPierre Pronchery 	unlink(file_path);
138*592efe25SPierre Pronchery 	rmdir(personality_d);
139*592efe25SPierre Pronchery 	rmdir(pkgconfig_dir);
140*592efe25SPierre Pronchery 	rmdir(tmpdir);
141*592efe25SPierre Pronchery }
142*592efe25SPierre Pronchery 
143*592efe25SPierre Pronchery #endif // !_WIN32 && !__HAIKU__
144*592efe25SPierre Pronchery 
145*592efe25SPierre Pronchery static void
test_personality_find_missing_returns_default(void)146*592efe25SPierre Pronchery test_personality_find_missing_returns_default(void)
147*592efe25SPierre Pronchery {
148*592efe25SPierre Pronchery 	// clear XDG / HOME so search goes to known-empty places
149*592efe25SPierre Pronchery 	unsetenv("XDG_DATA_HOME");
150*592efe25SPierre Pronchery 	unsetenv("XDG_DATA_DIRS");
151*592efe25SPierre Pronchery 	unsetenv("HOME");
152*592efe25SPierre Pronchery 
153*592efe25SPierre Pronchery 	pkgconf_cross_personality_t *found = pkgconf_cross_personality_find("nonexistent-triplet-xyzzy");
154*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(found);
155*592efe25SPierre Pronchery 
156*592efe25SPierre Pronchery 	// The find internally called _default(); call it ourselves to compare
157*592efe25SPierre Pronchery 	pkgconf_cross_personality_t *def = pkgconf_cross_personality_default();
158*592efe25SPierre Pronchery 	TEST_ASSERT_EQ((long long)(uintptr_t)found, (long long)(uintptr_t)def);
159*592efe25SPierre Pronchery 
160*592efe25SPierre Pronchery 	// Two deinits: one for find's internal _default(), one for ours above
161*592efe25SPierre Pronchery 	pkgconf_cross_personality_deinit(found);
162*592efe25SPierre Pronchery 	pkgconf_cross_personality_deinit(def);
163*592efe25SPierre Pronchery }
164*592efe25SPierre Pronchery 
165*592efe25SPierre Pronchery #endif /* !PKGCONF_LITE */
166*592efe25SPierre Pronchery 
167*592efe25SPierre Pronchery int
main(int argc,char * argv[])168*592efe25SPierre Pronchery main(int argc, char *argv[])
169*592efe25SPierre Pronchery {
170*592efe25SPierre Pronchery 	(void) argc;
171*592efe25SPierre Pronchery 	const char *basename = pkgconf_path_find_basename(argv[0]);
172*592efe25SPierre Pronchery 
173*592efe25SPierre Pronchery 	// refcount test must run first so the singleton starts at 0
174*592efe25SPierre Pronchery 	TEST_RUN(basename, test_personality_deinit_null);
175*592efe25SPierre Pronchery 	TEST_RUN(basename, test_personality_default_refcount);
176*592efe25SPierre Pronchery 
177*592efe25SPierre Pronchery #ifndef PKGCONF_LITE
178*592efe25SPierre Pronchery 	TEST_RUN(basename, test_personality_find_invalid_triplet);
179*592efe25SPierre Pronchery 	TEST_RUN(basename, test_personality_find_direct_path);
180*592efe25SPierre Pronchery #if !defined(_WIN32) && !defined(__HAIKU__)
181*592efe25SPierre Pronchery 	TEST_RUN(basename, test_personality_find_via_xdg);
182*592efe25SPierre Pronchery #endif
183*592efe25SPierre Pronchery 	TEST_RUN(basename, test_personality_find_missing_returns_default);
184*592efe25SPierre Pronchery #endif
185*592efe25SPierre Pronchery 
186*592efe25SPierre Pronchery 	return EXIT_SUCCESS;
187*592efe25SPierre Pronchery }
188