msvcp120: Add _Do_call implementation.
[wine.git] / dlls / msvcp120 / tests / msvcp120.c
blobb5b4301c048484411cb5c67f159d8c555328ad1d
1 /*
2 * Copyright 2014 Yifu Wang for ESRI
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.
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.
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
19 #include <locale.h>
21 #include "wine/test.h"
22 #include "winbase.h"
24 typedef int MSVCRT_long;
26 /* xtime */
27 typedef struct {
28 __time64_t sec;
29 MSVCRT_long nsec;
30 } xtime;
32 typedef struct {
33 unsigned page;
34 int mb_max;
35 int unk;
36 BYTE isleadbyte[32];
37 } _Cvtvec;
39 static char* (__cdecl *p_setlocale)(int, const char*);
40 static int (__cdecl *p__setmbcp)(int);
41 static int (__cdecl *p_isleadbyte)(int);
43 static MSVCRT_long (__cdecl *p__Xtime_diff_to_millis2)(const xtime*, const xtime*);
44 static int (__cdecl *p_xtime_get)(xtime*, int);
45 static _Cvtvec* (__cdecl *p__Getcvt)(_Cvtvec*);
46 static void (CDECL *p__Call_once)(int *once, void (CDECL *func)(void));
47 static void (CDECL *p__Call_onceEx)(int *once, void (CDECL *func)(void*), void *argv);
48 static void (CDECL *p__Do_call)(void *this);
50 static HMODULE msvcp;
52 static BOOL init(void)
54 HANDLE msvcr;
56 msvcp = LoadLibraryA("msvcp120.dll");
57 if(!msvcp)
59 win_skip("msvcp120.dll not installed\n");
60 return FALSE;
63 p__Xtime_diff_to_millis2 = (void*)GetProcAddress(msvcp, "_Xtime_diff_to_millis2");
64 p_xtime_get = (void*)GetProcAddress(msvcp, "xtime_get");
65 p__Getcvt = (void*)GetProcAddress(msvcp, "_Getcvt");
66 p__Call_once = (void*)GetProcAddress(msvcp, "_Call_once");
67 p__Call_onceEx = (void*)GetProcAddress(msvcp, "_Call_onceEx");
68 p__Do_call = (void*)GetProcAddress(msvcp, "_Do_call");
70 msvcr = GetModuleHandleA("msvcr120.dll");
71 p_setlocale = (void*)GetProcAddress(msvcr, "setlocale");
72 p__setmbcp = (void*)GetProcAddress(msvcr, "_setmbcp");
73 p_isleadbyte = (void*)GetProcAddress(msvcr, "isleadbyte");
74 return TRUE;
77 static void test__Xtime_diff_to_millis2(void)
79 struct {
80 __time64_t sec_before;
81 MSVCRT_long nsec_before;
82 __time64_t sec_after;
83 MSVCRT_long nsec_after;
84 MSVCRT_long expect;
85 } tests[] = {
86 {1, 0, 2, 0, 1000},
87 {0, 1000000000, 0, 2000000000, 1000},
88 {1, 100000000, 2, 100000000, 1000},
89 {1, 100000000, 1, 200000000, 100},
90 {0, 0, 0, 1000000000, 1000},
91 {0, 0, 0, 1200000000, 1200},
92 {0, 0, 0, 1230000000, 1230},
93 {0, 0, 0, 1234000000, 1234},
94 {0, 0, 0, 1234100000, 1235},
95 {0, 0, 0, 1234900000, 1235},
96 {0, 0, 0, 1234010000, 1235},
97 {0, 0, 0, 1234090000, 1235},
98 {0, 0, 0, 1234000001, 1235},
99 {0, 0, 0, 1234000009, 1235},
100 {0, 0, -1, 0, 0},
101 {0, 0, 0, -10000000, 0},
102 {0, 0, -1, -100000000, 0},
103 {-1, 0, 0, 0, 1000},
104 {0, -100000000, 0, 0, 100},
105 {-1, -100000000, 0, 0, 1100},
106 {0, 0, -1, 2000000000, 1000},
107 {0, 0, -2, 2000000000, 0},
108 {0, 0, -2, 2100000000, 100}
110 int i;
111 MSVCRT_long ret;
112 xtime t1, t2;
114 for(i = 0; i < sizeof(tests) / sizeof(tests[0]); ++ i)
116 t1.sec = tests[i].sec_before;
117 t1.nsec = tests[i].nsec_before;
118 t2.sec = tests[i].sec_after;
119 t2.nsec = tests[i].nsec_after;
120 ret = p__Xtime_diff_to_millis2(&t2, &t1);
121 ok(ret == tests[i].expect,
122 "_Xtime_diff_to_millis2(): test: %d expect: %d, got: %d\n",
123 i, tests[i].expect, ret);
127 static void test_xtime_get(void)
129 static const MSVCRT_long tests[] = {1, 50, 100, 200, 500};
130 MSVCRT_long diff;
131 xtime before, after;
132 int i;
134 for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i ++)
136 p_xtime_get(&before, 1);
137 Sleep(tests[i]);
138 p_xtime_get(&after, 1);
140 diff = p__Xtime_diff_to_millis2(&after, &before);
142 ok(diff >= tests[i],
143 "xtime_get() not functioning correctly, test: %d, expect: ge %d, got: %d\n",
144 i, tests[i], diff);
147 /* Test parameter and return value */
148 before.sec = 0xdeadbeef, before.nsec = 0xdeadbeef;
149 i = p_xtime_get(&before, 0);
150 ok(i == 0, "expect xtime_get() to return 0, got: %d\n", i);
151 ok(before.sec == 0xdeadbeef && before.nsec == 0xdeadbeef,
152 "xtime_get() shouldn't have modified the xtime struct with the given option\n");
154 before.sec = 0xdeadbeef, before.nsec = 0xdeadbeef;
155 i = p_xtime_get(&before, 1);
156 ok(i == 1, "expect xtime_get() to return 1, got: %d\n", i);
157 ok(before.sec != 0xdeadbeef && before.nsec != 0xdeadbeef,
158 "xtime_get() should have modified the xtime struct with the given option\n");
161 static void test__Getcvt(void)
163 _Cvtvec cvtvec;
164 int i;
166 p__Getcvt(&cvtvec);
167 ok(cvtvec.page == 0, "cvtvec.page = %d\n", cvtvec.page);
168 ok(cvtvec.mb_max == 1, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
169 todo_wine ok(cvtvec.unk == 1, "cvtvec.unk = %d\n", cvtvec.unk);
170 for(i=0; i<32; i++)
171 ok(cvtvec.isleadbyte[i] == 0, "cvtvec.isleadbyte[%d] = %x\n", i, cvtvec.isleadbyte[i]);
173 if(!p_setlocale(LC_ALL, ".936")) {
174 win_skip("_Getcvt tests\n");
175 return;
177 p__Getcvt(&cvtvec);
178 ok(cvtvec.page == 936, "cvtvec.page = %d\n", cvtvec.page);
179 ok(cvtvec.mb_max == 2, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
180 ok(cvtvec.unk == 0, "cvtvec.unk = %d\n", cvtvec.unk);
181 for(i=0; i<32; i++)
182 ok(cvtvec.isleadbyte[i] == 0, "cvtvec.isleadbyte[%d] = %x\n", i, cvtvec.isleadbyte[i]);
184 p__setmbcp(936);
185 p__Getcvt(&cvtvec);
186 ok(cvtvec.page == 936, "cvtvec.page = %d\n", cvtvec.page);
187 ok(cvtvec.mb_max == 2, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
188 ok(cvtvec.unk == 0, "cvtvec.unk = %d\n", cvtvec.unk);
189 for(i=0; i<32; i++) {
190 BYTE b = 0;
191 int j;
193 for(j=0; j<8; j++)
194 b |= (p_isleadbyte(i*8+j) ? 1 : 0) << j;
195 ok(cvtvec.isleadbyte[i] ==b, "cvtvec.isleadbyte[%d] = %x (%x)\n", i, cvtvec.isleadbyte[i], b);
199 static int cnt;
200 static int once;
202 static void __cdecl call_once_func(void)
204 ok(!once, "once != 0\n");
205 cnt += 0x10000;
208 static void __cdecl call_once_ex_func(void *arg)
210 int *i = arg;
212 ok(!once, "once != 0\n");
213 (*i)++;
216 DWORD WINAPI call_once_thread(void *arg)
218 p__Call_once(&once, call_once_func);
219 return 0;
222 DWORD WINAPI call_once_ex_thread(void *arg)
224 p__Call_onceEx(&once, call_once_ex_func, &cnt);
225 return 0;
228 static void test__Call_once(void)
230 HANDLE h[4];
231 int i;
233 for(i=0; i<4; i++)
234 h[i] = CreateThread(NULL, 0, call_once_thread, &once, 0, NULL);
235 ok(WaitForMultipleObjects(4, h, TRUE, INFINITE) == WAIT_OBJECT_0,
236 "error waiting for all threads to finish\n");
237 ok(cnt == 0x10000, "cnt = %x\n", cnt);
238 ok(once == 1, "once = %x\n", once);
240 once = cnt = 0;
241 for(i=0; i<4; i++)
242 h[i] = CreateThread(NULL, 0, call_once_ex_thread, &once, 0, NULL);
243 ok(WaitForMultipleObjects(4, h, TRUE, INFINITE) == WAIT_OBJECT_0,
244 "error waiting for all threads to finish\n");
245 ok(cnt == 1, "cnt = %x\n", cnt);
246 ok(once == 1, "once = %x\n", once);
249 static void **vtbl_func0;
250 #ifdef __i386__
251 /* TODO: this should be a __thiscall function */
252 static void __stdcall thiscall_func(void)
254 cnt = 1;
256 #else
257 static void __cdecl thiscall_func(void *this)
259 ok(this == &vtbl_func0, "incorrect this value\n");
260 cnt = 1;
262 #endif
264 static void test__Do_call(void)
266 void *pfunc = thiscall_func;
268 cnt = 0;
269 vtbl_func0 = &pfunc;
270 p__Do_call(&vtbl_func0);
271 ok(cnt == 1, "func was not called\n");
274 START_TEST(msvcp120)
276 if(!init()) return;
277 test__Xtime_diff_to_millis2();
278 test_xtime_get();
279 test__Getcvt();
280 test__Call_once();
281 test__Do_call();
283 FreeLibrary(msvcp);