Reactos
1/*
2 * Copyright 2016 Daniel Lehman (Esri)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include <errno.h>
20#include <stdarg.h>
21#include <stdlib.h>
22#include <wchar.h>
23#include <stdio.h>
24
25#include <windef.h>
26#include <winbase.h>
27#include <verrsrc.h>
28#include <dbghelp.h>
29#include "wine/test.h"
30
31typedef unsigned char MSVCRT_bool;
32
33typedef struct {
34 const char *what;
35 MSVCRT_bool dofree;
36} __std_exception_data;
37
38typedef struct
39{
40 char *name;
41 char mangled[32];
42} type_info140;
43
44typedef struct _type_info_list
45{
46 SLIST_ENTRY entry;
47 char name[1];
48} type_info_list;
49
50static void* (CDECL *p_malloc)(size_t);
51static void (CDECL *p___std_exception_copy)(const __std_exception_data*, __std_exception_data*);
52static void (CDECL *p___std_exception_destroy)(__std_exception_data*);
53static int (CDECL *p___std_type_info_compare)(const type_info140*, const type_info140*);
54static const char* (CDECL *p___std_type_info_name)(type_info140*, SLIST_HEADER*);
55static void (CDECL *p___std_type_info_destroy_list)(SLIST_HEADER*);
56static size_t (CDECL *p___std_type_info_hash)(type_info140*);
57static char* (__cdecl *p___unDName)(char*,const char*,int,void*,void*,unsigned short int);
58
59static BOOL init(void)
60{
61 HMODULE module;
62
63 module = LoadLibraryA("ucrtbase.dll");
64 if (!module)
65 {
66 win_skip("ucrtbase.dll not installed\n");
67 return FALSE;
68 }
69
70 p_malloc = (void*)GetProcAddress(module, "malloc");
71 p___std_exception_copy = (void*)GetProcAddress(module, "__std_exception_copy");
72 p___std_exception_destroy = (void*)GetProcAddress(module, "__std_exception_destroy");
73 p___std_type_info_compare = (void*)GetProcAddress(module, "__std_type_info_compare");
74 p___std_type_info_name = (void*)GetProcAddress(module, "__std_type_info_name");
75 p___std_type_info_destroy_list = (void*)GetProcAddress(module, "__std_type_info_destroy_list");
76 p___std_type_info_hash = (void*)GetProcAddress(module, "__std_type_info_hash");
77 p___unDName = (void*)GetProcAddress(module, "__unDName");
78 return TRUE;
79}
80
81static void test___std_exception(void)
82{
83 __std_exception_data src;
84 __std_exception_data dst;
85
86 if (0) /* crash on Windows */
87 {
88 p___std_exception_copy(NULL, &src);
89 p___std_exception_copy(&dst, NULL);
90
91 src.what = "invalid free";
92 src.dofree = 1;
93 p___std_exception_destroy(&src);
94 p___std_exception_destroy(NULL);
95 }
96
97 src.what = "what";
98 src.dofree = 0;
99 p___std_exception_copy(&src, &dst);
100 ok(dst.what == src.what, "expected what to be same, got src %p dst %p\n", src.what, dst.what);
101 ok(!dst.dofree, "expected 0, got %d\n", dst.dofree);
102
103 src.dofree = 0x42;
104 p___std_exception_copy(&src, &dst);
105 ok(dst.what != src.what, "expected what to be different, got src %p dst %p\n", src.what, dst.what);
106 ok(dst.dofree == 1, "expected 1, got %d\n", dst.dofree);
107
108 p___std_exception_destroy(&dst);
109 ok(!dst.what, "expected NULL, got %p\n", dst.what);
110 ok(!dst.dofree, "expected 0, got %d\n", dst.dofree);
111
112 src.what = NULL;
113 src.dofree = 0;
114 p___std_exception_copy(&src, &dst);
115 ok(!dst.what, "dst.what != NULL\n");
116 ok(!dst.dofree, "dst.dofree != FALSE\n");
117
118 src.what = NULL;
119 src.dofree = 1;
120 p___std_exception_copy(&src, &dst);
121 ok(!dst.what, "dst.what != NULL\n");
122 ok(!dst.dofree, "dst.dofree != FALSE\n");
123}
124
125static void test___std_type_info(void)
126{
127 type_info140 ti1 = { NULL, ".?AVa@@" };
128 type_info140 ti2 = { NULL, ".?AVb@@" };
129 type_info140 ti3 = ti1;
130 SLIST_HEADER header;
131 type_info_list *elem;
132 const char *ret;
133 size_t hash1, hash2;
134 int eq;
135
136
137 InitializeSListHead(&header);
138 p___std_type_info_destroy_list(&header);
139
140 elem = p_malloc(sizeof(*elem));
141 memset(elem, 0, sizeof(*elem));
142 InterlockedPushEntrySList(&header, &elem->entry);
143 p___std_type_info_destroy_list(&header);
144 ok(!InterlockedPopEntrySList(&header), "list is not empty\n");
145
146 ret = p___std_type_info_name(&ti1, &header);
147 ok(!strcmp(ret, "class a"), "__std_type_info_name(&ti1) = %s\n", ret);
148 ok(ti1.name == ret, "ti1.name = %p, ret = %p\n", ti1.name, ret);
149
150 p___std_type_info_destroy_list(&header);
151 ok(!InterlockedPopEntrySList(&header), "list is not empty\n");
152 ok(ti1.name == ret, "ti1.name = %p, ret = %p\n", ti1.name, ret);
153 ti1.name = NULL;
154
155 eq = p___std_type_info_compare(&ti1, &ti1);
156 ok(eq == 0, "__std_type_info_compare(&ti1, &ti1) = %d\n", eq);
157
158 eq = p___std_type_info_compare(&ti1, &ti2);
159 ok(eq == -1, "__std_type_info_compare(&ti1, &ti2) = %d\n", eq);
160
161 eq = p___std_type_info_compare(&ti1, &ti3);
162 ok(eq == 0, "__std_type_info_compare(&ti1, &ti3) = %d\n", eq);
163
164 ti1.mangled[0] = 0;
165 ti1.mangled[1] = 0;
166 ti1.mangled[2] = 0;
167 hash1 = p___std_type_info_hash(&ti1);
168#ifdef _WIN64
169 ok(hash1 == 0xcbf29ce44fd0bfc1, "hash = %p\n", (void*)hash1);
170#else
171 ok(hash1 == 0x811c9dc5, "hash = %p\n", (void*)hash1);
172#endif
173
174 ti1.mangled[0] = 1;
175 hash2 = p___std_type_info_hash(&ti1);
176 ok(hash1 == hash2, "hash1 != hash2 (first char not ignored)\n");
177
178 ti1.mangled[1] = 1;
179 hash1 = p___std_type_info_hash(&ti1);
180#ifdef _WIN64
181 ok(hash1 == 0xaf63bc4c29620a60, "hash = %p\n", (void*)hash1);
182#else
183 ok(hash1 == 0x40c5b8c, "hash = %p\n", (void*)hash1);
184#endif
185 ok(hash1 != hash2, "hash1 == hash2 for different strings\n");
186
187 ti1.mangled[1] = 2;
188 hash2 = p___std_type_info_hash(&ti1);
189 ok(hash1 != hash2, "hash1 == hash2 for different strings\n");
190
191 hash1 = p___std_type_info_hash(&ti2);
192 ok(hash1 != hash2, "hash1 == hash2 for different strings\n");
193}
194
195static void test___unDName(void)
196{
197 static struct {const char *in; const char *out; const char *broken; unsigned int flags;} und_tests[] =
198 {
199/* 0 */ {"??4QDnsDomainNameRecord@@QAEAAV0@$$QAV0@@Z",
200 "public: class QDnsDomainNameRecord & __thiscall QDnsDomainNameRecord::operator=(class QDnsDomainNameRecord &&)"},
201/* 1 */ {"??4QDnsDomainNameRecord@@QAEAAV0@$$QEAV0@@Z",
202 "public: class QDnsDomainNameRecord & __thiscall QDnsDomainNameRecord::operator=(class QDnsDomainNameRecord && __ptr64)"},
203/* 2 */ {"??__K_l@@YA?AUCC@@I@Z", "struct CC __cdecl operator \"\" _l(unsigned int)",
204 "??__K_l@@YA?AUCC@@I@Z" /* W10 1507 fails on this :-( */},
205/* 3 */ {"?meth@Q@@QEGBA?AV1@XZ",
206 "public: class Q __cdecl Q::meth(void)const __ptr64& ",
207 "public: ?? :: ?? ::XZ::V1" /* W10 1507 fails on this :-( */},
208/* 4 */ {"?meth@Q@@QEHAA?AV1@XZ",
209 "public: class Q __cdecl Q::meth(void) __ptr64&& ",
210 "public: ?? :: ?? ::XZ::V1" /* W10 1507 fails on this :-( */},
211/* 5 */ {"?meth@Q@@QEGBA?AV1@XZ",
212 "public: class Q Q::meth(void)const & ",
213 "public: ?? :: ?? ::XZ::V1" /* W10 1507 fails on this :-( */,
214 UNDNAME_NO_MS_KEYWORDS},
215/* 6 */ {"?meth@Q@@QEHAA?AV1@XZ",
216 "public: class Q Q::meth(void)&& ",
217 "public: ?? :: ?? ::XZ::V1" /* W10 1507 fails on this :-( */,
218 UNDNAME_NO_MS_KEYWORDS},
219/* 7 */ {"?AU?$my_iter@H$0A@$$V@@",
220 "struct my_iter<int,0>",
221 NULL,
222 UNDNAME_NO_ARGUMENTS},
223/* 8 */ {"??$foo@J_W$$T@bar@@YAJQB_W$$THQAUgod@@@Z",
224 "long __cdecl bar::foo<long,wchar_t,std::nullptr_t>(wchar_t const * const,std::nullptr_t,int,struct god * const)"},
225
226 };
227 unsigned i;
228 for (i = 0; i < ARRAY_SIZE(und_tests); i++)
229 {
230 char *name = p___unDName(0, und_tests[i].in, 0, malloc, free, und_tests[i].flags);
231 ok(!strcmp(name, und_tests[i].out) ||
232 broken(und_tests[i].broken && !strcmp(und_tests[i].broken, name)),
233 "unDName returned %s for #%u\n", wine_dbgstr_a(name), i);
234 free(name);
235 }
236}
237
238START_TEST(cpp)
239{
240 if (!init()) return;
241 test___std_exception();
242 test___std_type_info();
243 test___unDName();
244}