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