msvcp110: Add tr2_sys__Equivalent implementation and test.
[wine/multimedia.git] / dlls / msvcp120 / tests / msvcp120.c
blobdefa9342bfb583cd7fd2932048835d0e105d598d
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>
20 #include <stdio.h>
22 #include "wine/test.h"
23 #include "winbase.h"
25 typedef int MSVCRT_long;
27 /* xtime */
28 typedef struct {
29 __time64_t sec;
30 MSVCRT_long nsec;
31 } xtime;
33 typedef struct {
34 unsigned page;
35 int mb_max;
36 int unk;
37 BYTE isleadbyte[32];
38 } _Cvtvec;
40 static inline const char* debugstr_longlong(ULONGLONG ll)
42 static char string[17];
43 if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
44 sprintf(string, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
45 else
46 sprintf(string, "%lx", (unsigned long)ll);
47 return string;
50 static char* (__cdecl *p_setlocale)(int, const char*);
51 static int (__cdecl *p__setmbcp)(int);
52 static int (__cdecl *p_isleadbyte)(int);
54 static MSVCRT_long (__cdecl *p__Xtime_diff_to_millis2)(const xtime*, const xtime*);
55 static int (__cdecl *p_xtime_get)(xtime*, int);
56 static _Cvtvec* (__cdecl *p__Getcvt)(_Cvtvec*);
57 static void (CDECL *p__Call_once)(int *once, void (CDECL *func)(void));
58 static void (CDECL *p__Call_onceEx)(int *once, void (CDECL *func)(void*), void *argv);
59 static void (CDECL *p__Do_call)(void *this);
61 /* filesystem */
62 static ULONGLONG(__cdecl *p_tr2_sys__File_size)(char const*);
63 static int (__cdecl *p_tr2_sys__Equivalent)(char const*, char const*);
65 static HMODULE msvcp;
66 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
67 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
68 static BOOL init(void)
70 HANDLE msvcr;
72 msvcp = LoadLibraryA("msvcp120.dll");
73 if(!msvcp)
75 win_skip("msvcp120.dll not installed\n");
76 return FALSE;
79 SET(p__Xtime_diff_to_millis2,
80 "_Xtime_diff_to_millis2");
81 SET(p_xtime_get,
82 "xtime_get");
83 SET(p__Getcvt,
84 "_Getcvt");
85 SET(p__Call_once,
86 "_Call_once");
87 SET(p__Call_onceEx,
88 "_Call_onceEx");
89 SET(p__Do_call,
90 "_Do_call");
91 if(sizeof(void*) == 8) { /* 64-bit initialization */
92 SET(p_tr2_sys__File_size,
93 "?_File_size@sys@tr2@std@@YA_KPEBD@Z");
94 SET(p_tr2_sys__Equivalent,
95 "?_Equivalent@sys@tr2@std@@YAHPEBD0@Z");
96 } else {
97 SET(p_tr2_sys__File_size,
98 "?_File_size@sys@tr2@std@@YA_KPBD@Z");
99 SET(p_tr2_sys__Equivalent,
100 "?_Equivalent@sys@tr2@std@@YAHPBD0@Z");
103 msvcr = GetModuleHandleA("msvcr120.dll");
104 p_setlocale = (void*)GetProcAddress(msvcr, "setlocale");
105 p__setmbcp = (void*)GetProcAddress(msvcr, "_setmbcp");
106 p_isleadbyte = (void*)GetProcAddress(msvcr, "isleadbyte");
107 return TRUE;
110 static void test__Xtime_diff_to_millis2(void)
112 struct {
113 __time64_t sec_before;
114 MSVCRT_long nsec_before;
115 __time64_t sec_after;
116 MSVCRT_long nsec_after;
117 MSVCRT_long expect;
118 } tests[] = {
119 {1, 0, 2, 0, 1000},
120 {0, 1000000000, 0, 2000000000, 1000},
121 {1, 100000000, 2, 100000000, 1000},
122 {1, 100000000, 1, 200000000, 100},
123 {0, 0, 0, 1000000000, 1000},
124 {0, 0, 0, 1200000000, 1200},
125 {0, 0, 0, 1230000000, 1230},
126 {0, 0, 0, 1234000000, 1234},
127 {0, 0, 0, 1234100000, 1235},
128 {0, 0, 0, 1234900000, 1235},
129 {0, 0, 0, 1234010000, 1235},
130 {0, 0, 0, 1234090000, 1235},
131 {0, 0, 0, 1234000001, 1235},
132 {0, 0, 0, 1234000009, 1235},
133 {0, 0, -1, 0, 0},
134 {0, 0, 0, -10000000, 0},
135 {0, 0, -1, -100000000, 0},
136 {-1, 0, 0, 0, 1000},
137 {0, -100000000, 0, 0, 100},
138 {-1, -100000000, 0, 0, 1100},
139 {0, 0, -1, 2000000000, 1000},
140 {0, 0, -2, 2000000000, 0},
141 {0, 0, -2, 2100000000, 100}
143 int i;
144 MSVCRT_long ret;
145 xtime t1, t2;
147 for(i = 0; i < sizeof(tests) / sizeof(tests[0]); ++ i)
149 t1.sec = tests[i].sec_before;
150 t1.nsec = tests[i].nsec_before;
151 t2.sec = tests[i].sec_after;
152 t2.nsec = tests[i].nsec_after;
153 ret = p__Xtime_diff_to_millis2(&t2, &t1);
154 ok(ret == tests[i].expect,
155 "_Xtime_diff_to_millis2(): test: %d expect: %d, got: %d\n",
156 i, tests[i].expect, ret);
160 static void test_xtime_get(void)
162 static const MSVCRT_long tests[] = {1, 50, 100, 200, 500};
163 MSVCRT_long diff;
164 xtime before, after;
165 int i;
167 for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i ++)
169 p_xtime_get(&before, 1);
170 Sleep(tests[i]);
171 p_xtime_get(&after, 1);
173 diff = p__Xtime_diff_to_millis2(&after, &before);
175 ok(diff >= tests[i],
176 "xtime_get() not functioning correctly, test: %d, expect: ge %d, got: %d\n",
177 i, tests[i], diff);
180 /* Test parameter and return value */
181 before.sec = 0xdeadbeef, before.nsec = 0xdeadbeef;
182 i = p_xtime_get(&before, 0);
183 ok(i == 0, "expect xtime_get() to return 0, got: %d\n", i);
184 ok(before.sec == 0xdeadbeef && before.nsec == 0xdeadbeef,
185 "xtime_get() shouldn't have modified the xtime struct with the given option\n");
187 before.sec = 0xdeadbeef, before.nsec = 0xdeadbeef;
188 i = p_xtime_get(&before, 1);
189 ok(i == 1, "expect xtime_get() to return 1, got: %d\n", i);
190 ok(before.sec != 0xdeadbeef && before.nsec != 0xdeadbeef,
191 "xtime_get() should have modified the xtime struct with the given option\n");
194 static void test__Getcvt(void)
196 _Cvtvec cvtvec;
197 int i;
199 p__Getcvt(&cvtvec);
200 ok(cvtvec.page == 0, "cvtvec.page = %d\n", cvtvec.page);
201 ok(cvtvec.mb_max == 1, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
202 todo_wine ok(cvtvec.unk == 1, "cvtvec.unk = %d\n", cvtvec.unk);
203 for(i=0; i<32; i++)
204 ok(cvtvec.isleadbyte[i] == 0, "cvtvec.isleadbyte[%d] = %x\n", i, cvtvec.isleadbyte[i]);
206 if(!p_setlocale(LC_ALL, ".936")) {
207 win_skip("_Getcvt tests\n");
208 return;
210 p__Getcvt(&cvtvec);
211 ok(cvtvec.page == 936, "cvtvec.page = %d\n", cvtvec.page);
212 ok(cvtvec.mb_max == 2, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
213 ok(cvtvec.unk == 0, "cvtvec.unk = %d\n", cvtvec.unk);
214 for(i=0; i<32; i++)
215 ok(cvtvec.isleadbyte[i] == 0, "cvtvec.isleadbyte[%d] = %x\n", i, cvtvec.isleadbyte[i]);
217 p__setmbcp(936);
218 p__Getcvt(&cvtvec);
219 ok(cvtvec.page == 936, "cvtvec.page = %d\n", cvtvec.page);
220 ok(cvtvec.mb_max == 2, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
221 ok(cvtvec.unk == 0, "cvtvec.unk = %d\n", cvtvec.unk);
222 for(i=0; i<32; i++) {
223 BYTE b = 0;
224 int j;
226 for(j=0; j<8; j++)
227 b |= (p_isleadbyte(i*8+j) ? 1 : 0) << j;
228 ok(cvtvec.isleadbyte[i] ==b, "cvtvec.isleadbyte[%d] = %x (%x)\n", i, cvtvec.isleadbyte[i], b);
232 static int cnt;
233 static int once;
235 static void __cdecl call_once_func(void)
237 ok(!once, "once != 0\n");
238 cnt += 0x10000;
241 static void __cdecl call_once_ex_func(void *arg)
243 int *i = arg;
245 ok(!once, "once != 0\n");
246 (*i)++;
249 static DWORD WINAPI call_once_thread(void *arg)
251 p__Call_once(&once, call_once_func);
252 return 0;
255 static DWORD WINAPI call_once_ex_thread(void *arg)
257 p__Call_onceEx(&once, call_once_ex_func, &cnt);
258 return 0;
261 static void test__Call_once(void)
263 HANDLE h[4];
264 int i;
266 for(i=0; i<4; i++)
267 h[i] = CreateThread(NULL, 0, call_once_thread, &once, 0, NULL);
268 ok(WaitForMultipleObjects(4, h, TRUE, INFINITE) == WAIT_OBJECT_0,
269 "error waiting for all threads to finish\n");
270 ok(cnt == 0x10000, "cnt = %x\n", cnt);
271 ok(once == 1, "once = %x\n", once);
273 once = cnt = 0;
274 for(i=0; i<4; i++)
275 h[i] = CreateThread(NULL, 0, call_once_ex_thread, &once, 0, NULL);
276 ok(WaitForMultipleObjects(4, h, TRUE, INFINITE) == WAIT_OBJECT_0,
277 "error waiting for all threads to finish\n");
278 ok(cnt == 1, "cnt = %x\n", cnt);
279 ok(once == 1, "once = %x\n", once);
282 static void **vtbl_func0;
283 #ifdef __i386__
284 /* TODO: this should be a __thiscall function */
285 static void __stdcall thiscall_func(void)
287 cnt = 1;
289 #else
290 static void __cdecl thiscall_func(void *this)
292 ok(this == &vtbl_func0, "incorrect this value\n");
293 cnt = 1;
295 #endif
297 static void test__Do_call(void)
299 void *pfunc = thiscall_func;
301 cnt = 0;
302 vtbl_func0 = &pfunc;
303 p__Do_call(&vtbl_func0);
304 ok(cnt == 1, "func was not called\n");
307 static void test_tr2_sys__File_size(void)
309 ULONGLONG val;
310 HANDLE file;
311 LARGE_INTEGER file_size = {{7, 0}};
312 CreateDirectoryA("tr2_test_dir", NULL);
314 file = CreateFileA("tr2_test_dir/f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
315 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
316 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
317 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
318 CloseHandle(file);
319 val = p_tr2_sys__File_size("tr2_test_dir/f1");
320 ok(val == 7, "file_size is %s\n", debugstr_longlong(val));
322 file = CreateFileA("tr2_test_dir/f2", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
323 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
324 CloseHandle(file);
325 val = p_tr2_sys__File_size("tr2_test_dir/f2");
326 ok(val == 0, "file_size is %s\n", debugstr_longlong(val));
328 val = p_tr2_sys__File_size("tr2_test_dir");
329 ok(val == 0, "file_size is %s\n", debugstr_longlong(val));
331 errno = 0xdeadbeef;
332 val = p_tr2_sys__File_size("tr2_test_dir/not_exists_file");
333 ok(val == 0, "file_size is %s\n", debugstr_longlong(val));
334 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
336 errno = 0xdeadbeef;
337 val = p_tr2_sys__File_size(NULL);
338 ok(val == 0, "file_size is %s\n", debugstr_longlong(val));
339 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
341 ok(DeleteFileA("tr2_test_dir/f1"), "Expected tr2_test_dir/f1 to exist\n");
342 ok(DeleteFileA("tr2_test_dir/f2"), "Expected tr2_test_dir/f2 to exist\n");
343 ok(RemoveDirectoryA("tr2_test_dir"), "Expected tr2_test_dir to exist\n");
346 static void test_tr2_sys__Equivalent(void)
348 int val, i;
349 HANDLE file;
350 char temp_path[MAX_PATH], current_path[MAX_PATH];
351 struct {
352 char const *path1;
353 char const *path2;
354 int equivalent;
355 } tests[] = {
356 { NULL, NULL, -1 },
357 { NULL, "f1", -1 },
358 { "f1", NULL, -1 },
359 { "f1", "tr2_test_dir", -1 },
360 { "tr2_test_dir", "f1", -1 },
361 { "tr2_test_dir", "tr2_test_dir", -1 },
362 { "tr2_test_dir/./f1", "tr2_test_dir/f2", 0 },
363 { "tr2_test_dir/f1" , "tr2_test_dir/f1", 1 },
364 { "not_exists_file" , "tr2_test_dir/f1", 0 },
365 { "tr2_test_dir\\f1" , "tr2_test_dir/./f1", 1 },
366 { "not_exists_file" , "not_exists_file", -1 },
367 { "tr2_test_dir/f1" , "not_exists_file", 0 },
368 { "tr2_test_dir/../tr2_test_dir/f1", "tr2_test_dir/f1", 1 }
371 memset(current_path, 0, MAX_PATH);
372 GetCurrentDirectoryA(MAX_PATH, current_path);
373 memset(temp_path, 0, MAX_PATH);
374 GetTempPathA(MAX_PATH, temp_path);
375 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
376 CreateDirectoryA("tr2_test_dir", NULL);
378 file = CreateFileA("tr2_test_dir/f1", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
379 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
380 CloseHandle(file);
381 file = CreateFileA("tr2_test_dir/f2", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
382 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
383 CloseHandle(file);
385 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
386 errno = 0xdeadbeef;
387 val = p_tr2_sys__Equivalent(tests[i].path1, tests[i].path2);
388 ok(tests[i].equivalent == val, "tr2_sys__Equivalent(): test %d expect: %d, got %d\n", i+1, tests[i].equivalent, val);
389 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
392 ok(DeleteFileA("tr2_test_dir/f1"), "Expected tr2_test_dir/f1 to exist\n");
393 ok(DeleteFileA("tr2_test_dir/f2"), "Expected tr2_test_dir/f2 to exist\n");
394 ok(RemoveDirectoryA("tr2_test_dir"), "Expected tr2_test_dir to exist\n");
395 ok(SetCurrentDirectoryA(current_path), "SetCurrentDirectoryA failed\n");
398 START_TEST(msvcp120)
400 if(!init()) return;
401 test__Xtime_diff_to_millis2();
402 test_xtime_get();
403 test__Getcvt();
404 test__Call_once();
405 test__Do_call();
407 test_tr2_sys__File_size();
408 test_tr2_sys__Equivalent();
409 FreeLibrary(msvcp);