xref: /illumos-gate/usr/src/test/util-tests/tests/demangle/rust.c (revision f96a0cef040313f6281fbc014a0b63d5c5cc760f)
1 /*
2  * Copyright (c) 2014 Alex Crichton
3  *
4  * Permission is hereby granted, free of charge, to any
5  * person obtaining a copy of this software and associated
6  * documentation files (the "Software"), to deal in the
7  * Software without restriction, including without
8  * limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of
10  * the Software, and to permit persons to whom the Software
11  * is furnished to do so, subject to the following
12  * conditions:
13  *
14  * The above copyright notice and this permission notice
15  * shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
19  * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
20  * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
21  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
22  * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
25  * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  */
28 /*
29  * Copyright 2019, Joyent, Inc.
30  * Copyright 2021 Jason King
31  */
32 
33 /*
34  * Test cases taken from rustc-demangle 0.1.9
35  */
36 #include <errno.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/sysmacros.h>
41 #include <demangle-sys.h>
42 
43 typedef struct rust_test_case {
44 	const char *mangled;
45 	const char *demangled;
46 } rust_test_case_t;
47 #define	T(_m, _d) { .mangled = _m, .demangled = _d }
48 #define	T_ERR(_m) { .mangled = _m }
49 
50 typedef struct rust_test_grp {
51 	const char		*name;
52 	rust_test_case_t	tests[];
53 } rust_test_grp_t;
54 #define	GROUP(_n, ...)			\
55 	static rust_test_grp_t _n = {	\
56 		.name = #_n,		\
57 		.tests = {		\
58 			__VA_ARGS__,	\
59 			{ NULL, NULL }	\
60 		}			\
61 	}
62 
63 GROUP(demangle,
64     T_ERR("test"),
65     T("_ZN4testE", "test"),
66     T_ERR("_ZN4test"),
67     T("_ZN4test1a2bcE", "test::a::bc"));
68 
69 GROUP(demangle_dollars,
70     T("_ZN4$RP$E", ")"),
71     T("_ZN8$RF$testE", "&test"),
72     T("_ZN8$BP$test4foobE", "*test::foob"),
73     T("_ZN9$u20$test4foobE", " test::foob"),
74     T("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>"));
75 
76 GROUP(demangle_many_dollars,
77     T("_ZN13test$u20$test4foobE", "test test::foob"),
78     T("_ZN12test$BP$test4foobE", "test*test::foob"));
79 
80 /* BEGIN CSTYLED */
81 GROUP(demangle_osx,
82     T("__ZN5alloc9allocator6Layout9for_value17h02a996811f781011E",
83     "alloc::allocator::Layout::for_value::h02a996811f781011"),
84     T("__ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap18_MSG_FILE_LINE_COL17haf7cb8d5824ee659E",
85     "<core::option::Option<T>>::unwrap::_MSG_FILE_LINE_COL::haf7cb8d5824ee659"),
86     T("__ZN4core5slice89_$LT$impl$u20$core..iter..traits..IntoIterator$u20$for$u20$$RF$$u27$a$u20$$u5b$T$u5d$$GT$9into_iter17h450e234d27262170E",
87     "core::slice::<impl core::iter::traits::IntoIterator for &'a [T]>::into_iter::h450e234d27262170"));
88 
89 GROUP(demangle_elements_beginning_with_underscore,
90     T("_ZN13_$LT$test$GT$E", "<test>"),
91     T("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}"),
92     T("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR"));
93 
94 GROUP(demangle_trait_impls,
95     T("_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE",
96     "<Test + 'static as foo::Bar<Test>>::bar"));
97 
98 GROUP(invalid_no_chop, T_ERR("_ZNfooE"));
99 
100 GROUP(handle_assoc_types,
101     T("_ZN151_$LT$alloc..boxed..Box$LT$alloc..boxed..FnBox$LT$A$C$$u20$Output$u3d$R$GT$$u20$$u2b$$u20$$u27$a$GT$$u20$as$u20$core..ops..function..FnOnce$LT$A$GT$$GT$9call_once17h69e8f44b3723e1caE",
102     "<alloc::boxed::Box<alloc::boxed::FnBox<A, Output=R> + 'a> as core::ops::function::FnOnce<A>>::call_once::h69e8f44b3723e1ca"));
103 
104 /* C++ mangled names that aren't valid rust names */
105 GROUP(cplusplus_as_rust, T_ERR("_ZN7mozilla3dom13BrowserParent22RecvUpdateContentCacheERKNS_12ContentCacheE"));
106 
107 /* END CSTYLED */
108 
109 static rust_test_grp_t *rust_tests[] = {
110 	&demangle,
111 	&demangle_dollars,
112 	&demangle_many_dollars,
113 	&demangle_osx,
114 	&demangle_elements_beginning_with_underscore,
115 	&demangle_trait_impls,
116 	&invalid_no_chop,
117 	&handle_assoc_types,
118 	&cplusplus_as_rust,
119 };
120 
121 static const size_t n_rust_tests = ARRAY_SIZE(rust_tests);
122 
123 static boolean_t
124 check_failure(size_t i, rust_test_case_t *tc, const char *dem, boolean_t res)
125 {
126 	int savederr = errno;
127 
128 	if (dem == NULL && savederr == EINVAL)
129 		return (B_TRUE);
130 
131 	if (res)
132 		(void) printf("FAILURE\n");
133 
134 	if (dem != NULL) {
135 		(void) printf("  [%zu] Successfully demanged an invalid "
136 		    "name\n", i);
137 		(void) printf("         Name: '%s'\n", tc->mangled);
138 		(void) printf("    Demangled: '%s'\n", dem);
139 		return (B_FALSE);
140 	}
141 
142 	(void) printf("  [%zu] demangle() returned an unexpected error\n", i);
143 	(void) printf("    Errno: %d\n", savederr);
144 	return (B_FALSE);
145 }
146 
147 static boolean_t
148 check_success(size_t i, rust_test_case_t *tc, const char *dem, boolean_t res)
149 {
150 	if (dem != NULL && strcmp(tc->demangled, dem) == 0)
151 		return (B_TRUE);
152 
153 	if (res)
154 		(void) printf("FAILURE\n");
155 
156 	if (dem == NULL) {
157 		(void) printf("  [%zu] Failed to demangle '%s'\n", i,
158 		    tc->mangled);
159 		return (B_FALSE);
160 	}
161 
162 	(void) printf("  [%zu] Demangled results do not match.\n", i);
163 	(void) printf("       Mangled: %s\n", tc->mangled);
164 	(void) printf("      Expected: %s\n", tc->demangled);
165 	(void) printf("        Actual: %s\n", dem);
166 	return (B_FALSE);
167 }
168 
169 static boolean_t
170 run_test(rust_test_grp_t *test)
171 {
172 	boolean_t res = B_TRUE;
173 
174 	(void) printf("Test %s: ", test->name);
175 
176 	for (size_t i = 0; test->tests[i].mangled != NULL; i++) {
177 		char *dem;
178 
179 		dem = sysdemangle(test->tests[i].mangled, SYSDEM_LANG_RUST,
180 		    NULL);
181 		if (test->tests[i].demangled == NULL)
182 			res &= check_failure(i, &test->tests[i], dem, res);
183 		else
184 			res &= check_success(i, &test->tests[i], dem, res);
185 
186 		free(dem);
187 	}
188 
189 	if (res)
190 		(void) printf("SUCCESS\n");
191 
192 	return (res);
193 }
194 
195 int
196 main(int argc, char **argv)
197 {
198 	boolean_t ok = B_TRUE;
199 
200 	for (size_t i = 0; i < n_rust_tests; i++)
201 		ok &= run_test(rust_tests[i]);
202 
203 	return (ok ? 0 : 1);
204 }
205 
206 const char *
207 _umem_debug_init(void)
208 {
209 	return ("default,verbose");
210 }
211 
212 const char *
213 _umem_logging_init(void)
214 {
215 	return ("fail,contents");
216 }
217