1*0a9a25a2SRichard Hansen /*
2*0a9a25a2SRichard Hansen  * This file and its contents are supplied under the terms of the
3*0a9a25a2SRichard Hansen  * Common Development and Distribution License ("CDDL"), version 1.0.
4*0a9a25a2SRichard Hansen  * You may only use this file in accordance with the terms of version
5*0a9a25a2SRichard Hansen  * 1.0 of the CDDL.
6*0a9a25a2SRichard Hansen  *
7*0a9a25a2SRichard Hansen  * A full copy of the text of the CDDL should have accompanied this
8*0a9a25a2SRichard Hansen  * source.  A copy of the CDDL is also available via the Internet at
9*0a9a25a2SRichard Hansen  * http://www.illumos.org/license/CDDL.
10*0a9a25a2SRichard Hansen  */
11*0a9a25a2SRichard Hansen 
12*0a9a25a2SRichard Hansen /*
13*0a9a25a2SRichard Hansen  * Copyright 2020 Richard Hansen <rhansen@rhansen.org>
14*0a9a25a2SRichard Hansen  */
15*0a9a25a2SRichard Hansen 
16*0a9a25a2SRichard Hansen #include <errno.h>
17*0a9a25a2SRichard Hansen #include <libintl.h>
18*0a9a25a2SRichard Hansen #include <stdbool.h>
19*0a9a25a2SRichard Hansen #include <stdio.h>
20*0a9a25a2SRichard Hansen #include <string.h>
21*0a9a25a2SRichard Hansen #include <sys/sysmacros.h>
22*0a9a25a2SRichard Hansen #include <umem.h>
23*0a9a25a2SRichard Hansen #include <unistd.h>
24*0a9a25a2SRichard Hansen #include "test_common.h"
25*0a9a25a2SRichard Hansen 
26*0a9a25a2SRichard Hansen const char *
_umem_debug_init(void)27*0a9a25a2SRichard Hansen _umem_debug_init(void)
28*0a9a25a2SRichard Hansen {
29*0a9a25a2SRichard Hansen 	return ("default");
30*0a9a25a2SRichard Hansen }
31*0a9a25a2SRichard Hansen 
32*0a9a25a2SRichard Hansen int
main(int argc,char * argv[])33*0a9a25a2SRichard Hansen main(int argc, char *argv[])
34*0a9a25a2SRichard Hansen {
35*0a9a25a2SRichard Hansen 	int ret = 0;
36*0a9a25a2SRichard Hansen 	int optc;
37*0a9a25a2SRichard Hansen 	while ((optc = getopt(argc, argv, "df")) != -1) {
38*0a9a25a2SRichard Hansen 		switch (optc) {
39*0a9a25a2SRichard Hansen 		case 'd':
40*0a9a25a2SRichard Hansen 			test_set_debug();
41*0a9a25a2SRichard Hansen 			break;
42*0a9a25a2SRichard Hansen 		case 'f':
43*0a9a25a2SRichard Hansen 			test_set_force();
44*0a9a25a2SRichard Hansen 			break;
45*0a9a25a2SRichard Hansen 		default:
46*0a9a25a2SRichard Hansen 			(void) fprintf(stderr, "Usage: %s [-df]\n", argv[0]);
47*0a9a25a2SRichard Hansen 			exit(1);
48*0a9a25a2SRichard Hansen 		}
49*0a9a25a2SRichard Hansen 	}
50*0a9a25a2SRichard Hansen 
51*0a9a25a2SRichard Hansen 	struct {
52*0a9a25a2SRichard Hansen 		const char *name;
53*0a9a25a2SRichard Hansen 		const char *dir;
54*0a9a25a2SRichard Hansen 		bool malloc_fail;
55*0a9a25a2SRichard Hansen 		const char *want;
56*0a9a25a2SRichard Hansen 		int want_errno;
57*0a9a25a2SRichard Hansen 	} test_cases[] = {
58*0a9a25a2SRichard Hansen 		{
59*0a9a25a2SRichard Hansen 			.name = "unbound query",
60*0a9a25a2SRichard Hansen 			.dir = NULL,
61*0a9a25a2SRichard Hansen 			.want = "/usr/lib/locale/",
62*0a9a25a2SRichard Hansen 		},
63*0a9a25a2SRichard Hansen 		{
64*0a9a25a2SRichard Hansen 			.name = "bind malloc fail",
65*0a9a25a2SRichard Hansen 			.dir = "/bounddir1",
66*0a9a25a2SRichard Hansen 			.malloc_fail = true,
67*0a9a25a2SRichard Hansen 			.want = NULL,
68*0a9a25a2SRichard Hansen 			.want_errno = EAGAIN,
69*0a9a25a2SRichard Hansen 		},
70*0a9a25a2SRichard Hansen 		{
71*0a9a25a2SRichard Hansen 			.name = "query after bind malloc fail",
72*0a9a25a2SRichard Hansen 			.dir = NULL,
73*0a9a25a2SRichard Hansen 			.want = "/usr/lib/locale/",
74*0a9a25a2SRichard Hansen 		},
75*0a9a25a2SRichard Hansen 		{
76*0a9a25a2SRichard Hansen 			.name = "normal bind",
77*0a9a25a2SRichard Hansen 			.dir = "/bounddir2",
78*0a9a25a2SRichard Hansen 			.want = "/bounddir2",
79*0a9a25a2SRichard Hansen 		},
80*0a9a25a2SRichard Hansen 		{
81*0a9a25a2SRichard Hansen 			.name = "query after normal bind",
82*0a9a25a2SRichard Hansen 			.dir = NULL,
83*0a9a25a2SRichard Hansen 			.want = "/bounddir2",
84*0a9a25a2SRichard Hansen 		},
85*0a9a25a2SRichard Hansen 		{
86*0a9a25a2SRichard Hansen 			.name = "rebind to same",
87*0a9a25a2SRichard Hansen 			.dir = "/bounddir2",
88*0a9a25a2SRichard Hansen 			.want = "/bounddir2",
89*0a9a25a2SRichard Hansen 		},
90*0a9a25a2SRichard Hansen 		{
91*0a9a25a2SRichard Hansen 			.name = "query after rebind to same",
92*0a9a25a2SRichard Hansen 			.dir = NULL,
93*0a9a25a2SRichard Hansen 			.want = "/bounddir2",
94*0a9a25a2SRichard Hansen 		},
95*0a9a25a2SRichard Hansen 		{
96*0a9a25a2SRichard Hansen 			.name = "rebind to new",
97*0a9a25a2SRichard Hansen 			.dir = "/bounddir3",
98*0a9a25a2SRichard Hansen 			.want = "/bounddir3",
99*0a9a25a2SRichard Hansen 		},
100*0a9a25a2SRichard Hansen 		{
101*0a9a25a2SRichard Hansen 			.name = "query after rebind to new",
102*0a9a25a2SRichard Hansen 			.dir = NULL,
103*0a9a25a2SRichard Hansen 			.want = "/bounddir3",
104*0a9a25a2SRichard Hansen 		},
105*0a9a25a2SRichard Hansen 		{
106*0a9a25a2SRichard Hansen 			.name = "rebind malloc fail",
107*0a9a25a2SRichard Hansen 			.dir = "/bounddir4",
108*0a9a25a2SRichard Hansen 			.malloc_fail = true,
109*0a9a25a2SRichard Hansen 			.want = NULL,
110*0a9a25a2SRichard Hansen 			.want_errno = EAGAIN,
111*0a9a25a2SRichard Hansen 		},
112*0a9a25a2SRichard Hansen 		{
113*0a9a25a2SRichard Hansen 			.name = "query after rebind malloc fail",
114*0a9a25a2SRichard Hansen 			.dir = NULL,
115*0a9a25a2SRichard Hansen 			.want = "/bounddir3",
116*0a9a25a2SRichard Hansen 		},
117*0a9a25a2SRichard Hansen 	}, *tc;
118*0a9a25a2SRichard Hansen 
119*0a9a25a2SRichard Hansen 	for (size_t i = 0; i < ARRAY_SIZE(test_cases); ++i) {
120*0a9a25a2SRichard Hansen 		tc = &test_cases[i];
121*0a9a25a2SRichard Hansen 		test_t t = test_start(tc->name);
122*0a9a25a2SRichard Hansen 		umem_setmtbf((uint_t)tc->malloc_fail);
123*0a9a25a2SRichard Hansen 		errno = 0;
124*0a9a25a2SRichard Hansen 		const char *got = bindtextdomain("domain", tc->dir);
125*0a9a25a2SRichard Hansen 		int got_errno = errno;
126*0a9a25a2SRichard Hansen 		umem_setmtbf(0);
127*0a9a25a2SRichard Hansen 		if (((got == NULL) != (tc->want == NULL)) ||
128*0a9a25a2SRichard Hansen 		    ((got != NULL) && strcmp(got, tc->want))) {
129*0a9a25a2SRichard Hansen 			test_failed(t, "returned %s, want %s",
130*0a9a25a2SRichard Hansen 			    got != NULL ? got : "<NULL>",
131*0a9a25a2SRichard Hansen 			    tc->want != NULL ? tc->want : "<NULL>");
132*0a9a25a2SRichard Hansen 			ret = 1;
133*0a9a25a2SRichard Hansen 		}
134*0a9a25a2SRichard Hansen 		if (got_errno != tc->want_errno) {
135*0a9a25a2SRichard Hansen 			test_failed(t, "got errno %d, want %d",
136*0a9a25a2SRichard Hansen 			    got_errno, tc->want_errno);
137*0a9a25a2SRichard Hansen 			ret = 1;
138*0a9a25a2SRichard Hansen 		}
139*0a9a25a2SRichard Hansen 		test_passed(t);
140*0a9a25a2SRichard Hansen 	}
141*0a9a25a2SRichard Hansen 	test_summary();
142*0a9a25a2SRichard Hansen 	return (ret);
143*0a9a25a2SRichard Hansen }