[THEMES]
[reactos.git] / rostests / winetests / qmgr / job.c
1 /*
2 * Unit test suite for Background Copy Job Interface
3 *
4 * Copyright 2007 Google (Roy Shea)
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 //#include <stdio.h>
22
23 #define WIN32_NO_STATUS
24 #define _INC_WINDOWS
25 #define COM_NO_WINDOWS_H
26
27 #define COBJMACROS
28
29 #include <wine/test.h>
30 #include <objbase.h>
31 #include <bits.h>
32 #include <initguid.h>
33
34 /* Globals used by many tests */
35 static const WCHAR test_displayName[] = {'T', 'e', 's', 't', 0};
36 static WCHAR test_remotePathA[MAX_PATH];
37 static WCHAR test_remotePathB[MAX_PATH];
38 static WCHAR test_localPathA[MAX_PATH];
39 static WCHAR test_localPathB[MAX_PATH];
40 static IBackgroundCopyManager *test_manager;
41 static IBackgroundCopyJob *test_job;
42 static GUID test_jobId;
43 static BG_JOB_TYPE test_type;
44
45 static VOID init_paths(void)
46 {
47 WCHAR tmpDir[MAX_PATH];
48 WCHAR prefix[] = {'q', 'm', 'g', 'r', 0};
49
50 GetTempPathW(MAX_PATH, tmpDir);
51
52 GetTempFileNameW(tmpDir, prefix, 0, test_localPathA);
53 GetTempFileNameW(tmpDir, prefix, 0, test_localPathB);
54 GetTempFileNameW(tmpDir, prefix, 0, test_remotePathA);
55 GetTempFileNameW(tmpDir, prefix, 0, test_remotePathB);
56 }
57
58 /* Generic test setup */
59 static BOOL setup(void)
60 {
61 HRESULT hres;
62
63 test_manager = NULL;
64 test_job = NULL;
65 memset(&test_jobId, 0, sizeof test_jobId);
66 test_type = BG_JOB_TYPE_DOWNLOAD;
67
68 hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL,
69 CLSCTX_LOCAL_SERVER,
70 &IID_IBackgroundCopyManager,
71 (void **) &test_manager);
72 if(hres != S_OK)
73 return FALSE;
74
75 hres = IBackgroundCopyManager_CreateJob(test_manager, test_displayName,
76 test_type, &test_jobId, &test_job);
77 if(hres != S_OK)
78 {
79 IBackgroundCopyManager_Release(test_manager);
80 return FALSE;
81 }
82
83 return TRUE;
84 }
85
86 /* Generic test cleanup */
87 static void teardown(void)
88 {
89 IBackgroundCopyJob_Release(test_job);
90 IBackgroundCopyManager_Release(test_manager);
91 }
92
93 /* FIXME: Remove when Wine has implemented this */
94 DEFINE_GUID(CLSID_BackgroundCopyManager2_0, 0x6d18ad12, 0xbde3, 0x4393, 0xb3,0x11, 0x09,0x9c,0x34,0x6e,0x6d,0xf9);
95
96 static BOOL check_bits20(void)
97 {
98 HRESULT hres;
99 IBackgroundCopyManager *manager;
100 BOOL ret = TRUE;
101
102 hres = CoCreateInstance(&CLSID_BackgroundCopyManager2_0, NULL,
103 CLSCTX_LOCAL_SERVER,
104 &IID_IBackgroundCopyManager,
105 (void **) &manager);
106
107 if (hres == REGDB_E_CLASSNOTREG)
108 {
109 ret = FALSE;
110
111 /* FIXME: Wine implements 2.0 functionality but doesn't advertise 2.0
112 *
113 * Remove when Wine is fixed
114 */
115 if (setup())
116 {
117 HRESULT hres2;
118
119 hres2 = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
120 test_localPathA);
121 if (hres2 == S_OK)
122 {
123 trace("Running on Wine, claim 2.0 is present\n");
124 ret = TRUE;
125 }
126 teardown();
127 }
128 }
129
130 if (manager)
131 IBackgroundCopyManager_Release(manager);
132
133 return ret;
134 }
135
136 /* Test that the jobId is properly set */
137 static void test_GetId(void)
138 {
139 HRESULT hres;
140 GUID tmpId;
141
142 hres = IBackgroundCopyJob_GetId(test_job, &tmpId);
143 ok(hres == S_OK, "GetId failed: %08x\n", hres);
144 if(hres != S_OK)
145 {
146 skip("Unable to get ID of test_job.\n");
147 return;
148 }
149 ok(memcmp(&tmpId, &test_jobId, sizeof tmpId) == 0, "Got incorrect GUID\n");
150 }
151
152 /* Test that the type is properly set */
153 static void test_GetType(void)
154 {
155 HRESULT hres;
156 BG_JOB_TYPE type;
157
158 hres = IBackgroundCopyJob_GetType(test_job, &type);
159 ok(hres == S_OK, "GetType failed: %08x\n", hres);
160 if(hres != S_OK)
161 {
162 skip("Unable to get type of test_job.\n");
163 return;
164 }
165 ok(type == test_type, "Got incorrect type\n");
166 }
167
168 /* Test that the display name is properly set */
169 static void test_GetName(void)
170 {
171 HRESULT hres;
172 LPWSTR displayName;
173
174 hres = IBackgroundCopyJob_GetDisplayName(test_job, &displayName);
175 ok(hres == S_OK, "GetName failed: %08x\n", hres);
176 if(hres != S_OK)
177 {
178 skip("Unable to get display name of test_job.\n");
179 return;
180 }
181 ok(lstrcmpW(displayName, test_displayName) == 0, "Got incorrect type\n");
182 CoTaskMemFree(displayName);
183 }
184
185 /* Test adding a file */
186 static void test_AddFile(void)
187 {
188 HRESULT hres;
189
190 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
191 test_localPathA);
192 ok(hres == S_OK, "First call to AddFile failed: 0x%08x\n", hres);
193 if (hres != S_OK)
194 {
195 skip("Unable to add first file to job\n");
196 return;
197 }
198
199 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathB,
200 test_localPathB);
201 ok(hres == S_OK, "Second call to AddFile failed: 0x%08x\n", hres);
202 }
203
204 /* Test adding a set of files */
205 static void test_AddFileSet(void)
206 {
207 HRESULT hres;
208 BG_FILE_INFO files[2] =
209 {
210 {test_remotePathA, test_localPathA},
211 {test_remotePathB, test_localPathB}
212 };
213 hres = IBackgroundCopyJob_AddFileSet(test_job, 2, files);
214 ok(hres == S_OK, "AddFileSet failed: 0x%08x\n", hres);
215 }
216
217 /* Test creation of a job enumerator */
218 static void test_EnumFiles(void)
219 {
220 HRESULT hres;
221 IEnumBackgroundCopyFiles *enumFiles;
222 ULONG res;
223
224 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
225 test_localPathA);
226 if (hres != S_OK)
227 {
228 skip("Unable to add file to job\n");
229 return;
230 }
231
232 hres = IBackgroundCopyJob_EnumFiles(test_job, &enumFiles);
233 ok(hres == S_OK, "EnumFiles failed: 0x%08x\n", hres);
234 if(hres != S_OK)
235 {
236 skip("Unable to create file enumerator.\n");
237 return;
238 }
239
240 res = IEnumBackgroundCopyFiles_Release(enumFiles);
241 ok(res == 0, "Bad ref count on release: %u\n", res);
242 }
243
244 /* Test getting job progress */
245 static void test_GetProgress_preTransfer(void)
246 {
247 HRESULT hres;
248 BG_JOB_PROGRESS progress;
249
250 hres = IBackgroundCopyJob_GetProgress(test_job, &progress);
251 ok(hres == S_OK, "GetProgress failed: 0x%08x\n", hres);
252 if (hres != S_OK)
253 {
254 skip("Unable to get job progress\n");
255 teardown();
256 return;
257 }
258
259 ok(progress.BytesTotal == 0, "Incorrect BytesTotal: %x%08x\n",
260 (DWORD)(progress.BytesTotal >> 32), (DWORD)progress.BytesTotal);
261 ok(progress.BytesTransferred == 0, "Incorrect BytesTransferred: %x%08x\n",
262 (DWORD)(progress.BytesTransferred >> 32), (DWORD)progress.BytesTransferred);
263 ok(progress.FilesTotal == 0, "Incorrect FilesTotal: %u\n", progress.FilesTotal);
264 ok(progress.FilesTransferred == 0, "Incorrect FilesTransferred %u\n", progress.FilesTransferred);
265 }
266
267 /* Test getting job state */
268 static void test_GetState(void)
269 {
270 HRESULT hres;
271 BG_JOB_STATE state;
272
273 state = BG_JOB_STATE_ERROR;
274 hres = IBackgroundCopyJob_GetState(test_job, &state);
275 ok(hres == S_OK, "GetState failed: 0x%08x\n", hres);
276 if (hres != S_OK)
277 {
278 skip("Unable to get job state\n");
279 return;
280 }
281 ok(state == BG_JOB_STATE_SUSPENDED, "Incorrect job state: %d\n", state);
282 }
283
284 /* Test resuming a job */
285 static void test_ResumeEmpty(void)
286 {
287 HRESULT hres;
288 BG_JOB_STATE state;
289
290 hres = IBackgroundCopyJob_Resume(test_job);
291 ok(hres == BG_E_EMPTY, "Resume failed to return BG_E_EMPTY error: 0x%08x\n", hres);
292 if (hres != BG_E_EMPTY)
293 {
294 skip("Failed calling resume job\n");
295 return;
296 }
297
298 state = BG_JOB_STATE_ERROR;
299 hres = IBackgroundCopyJob_GetState(test_job, &state);
300 if (hres != S_OK)
301 {
302 skip("Unable to get job state\n");
303 return;
304 }
305 ok(state == BG_JOB_STATE_SUSPENDED, "Incorrect job state: %d\n", state);
306 }
307
308 static void makeFile(WCHAR *name, const char *contents)
309 {
310 HANDLE file;
311 DWORD w, len = strlen(contents);
312
313 DeleteFileW(name);
314 file = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
315 FILE_ATTRIBUTE_NORMAL, NULL);
316 ok(file != INVALID_HANDLE_VALUE, "CreateFile\n");
317 ok(WriteFile(file, contents, len, &w, NULL), "WriteFile\n");
318 CloseHandle(file);
319 }
320
321 static void compareFiles(WCHAR *n1, WCHAR *n2)
322 {
323 char b1[256];
324 char b2[256];
325 DWORD s1, s2;
326 HANDLE f1, f2;
327
328 f1 = CreateFileW(n1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
329 FILE_ATTRIBUTE_NORMAL, NULL);
330 ok(f1 != INVALID_HANDLE_VALUE, "CreateFile\n");
331
332 f2 = CreateFileW(n2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
333 FILE_ATTRIBUTE_NORMAL, NULL);
334 ok(f2 != INVALID_HANDLE_VALUE, "CreateFile\n");
335
336 /* Neither of these files is very big */
337 ok(ReadFile(f1, b1, sizeof b1, &s1, NULL), "ReadFile\n");
338 ok(ReadFile(f2, b2, sizeof b2, &s2, NULL), "ReadFile\n");
339
340 CloseHandle(f1);
341 CloseHandle(f2);
342
343 ok(s1 == s2, "Files differ in length\n");
344 ok(memcmp(b1, b2, s1) == 0, "Files differ in contents\n");
345 }
346
347 /* Test a complete transfer for local files */
348 static void test_CompleteLocal(void)
349 {
350 static const int timeout_sec = 30;
351 HRESULT hres;
352 BG_JOB_STATE state;
353 int i;
354
355 DeleteFileW(test_localPathA);
356 DeleteFileW(test_localPathB);
357 makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
358 makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
359
360 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
361 test_localPathA);
362 if (hres != S_OK)
363 {
364 skip("Unable to add file to job\n");
365 return;
366 }
367
368 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathB,
369 test_localPathB);
370 if (hres != S_OK)
371 {
372 skip("Unable to add file to job\n");
373 return;
374 }
375
376 hres = IBackgroundCopyJob_Resume(test_job);
377 ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
378
379 for (i = 0; i < timeout_sec; ++i)
380 {
381 hres = IBackgroundCopyJob_GetState(test_job, &state);
382 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
383 ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
384 || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED,
385 "Bad state: %d\n", state);
386 if (state == BG_JOB_STATE_TRANSFERRED)
387 break;
388 Sleep(1000);
389 }
390
391 ok(i < timeout_sec, "BITS jobs timed out\n");
392 hres = IBackgroundCopyJob_Complete(test_job);
393 ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
394 hres = IBackgroundCopyJob_GetState(test_job, &state);
395 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
396 ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
397
398 compareFiles(test_remotePathA, test_localPathA);
399 compareFiles(test_remotePathB, test_localPathB);
400
401 ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
402 ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
403 DeleteFileW(test_localPathA);
404 DeleteFileW(test_localPathB);
405 }
406
407 /* Test a complete transfer for local files */
408 static void test_CompleteLocalURL(void)
409 {
410 static const WCHAR prot[] = {'f','i','l','e',':','/','/', 0};
411 static const int timeout_sec = 30;
412 WCHAR *urlA, *urlB;
413 HRESULT hres;
414 BG_JOB_STATE state;
415 int i;
416
417 DeleteFileW(test_localPathA);
418 DeleteFileW(test_localPathB);
419 makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
420 makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
421
422 urlA = HeapAlloc(GetProcessHeap(), 0,
423 (7 + lstrlenW(test_remotePathA) + 1) * sizeof urlA[0]);
424 urlB = HeapAlloc(GetProcessHeap(), 0,
425 (7 + lstrlenW(test_remotePathB) + 1) * sizeof urlB[0]);
426 if (!urlA || !urlB)
427 {
428 skip("Unable to allocate memory for URLs\n");
429 HeapFree(GetProcessHeap(), 0, urlA);
430 HeapFree(GetProcessHeap(), 0, urlB);
431 return;
432 }
433
434 lstrcpyW(urlA, prot);
435 lstrcatW(urlA, test_remotePathA);
436 lstrcpyW(urlB, prot);
437 lstrcatW(urlB, test_remotePathB);
438
439 hres = IBackgroundCopyJob_AddFile(test_job, urlA, test_localPathA);
440 if (hres != S_OK)
441 {
442 skip("Unable to add file to job\n");
443 HeapFree(GetProcessHeap(), 0, urlA);
444 HeapFree(GetProcessHeap(), 0, urlB);
445 return;
446 }
447
448 hres = IBackgroundCopyJob_AddFile(test_job, urlB, test_localPathB);
449 if (hres != S_OK)
450 {
451 skip("Unable to add file to job\n");
452 HeapFree(GetProcessHeap(), 0, urlA);
453 HeapFree(GetProcessHeap(), 0, urlB);
454 return;
455 }
456
457 hres = IBackgroundCopyJob_Resume(test_job);
458 ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
459
460 for (i = 0; i < timeout_sec; ++i)
461 {
462 hres = IBackgroundCopyJob_GetState(test_job, &state);
463 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
464 ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
465 || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED,
466 "Bad state: %d\n", state);
467 if (state == BG_JOB_STATE_TRANSFERRED)
468 break;
469 Sleep(1000);
470 }
471
472 ok(i < timeout_sec, "BITS jobs timed out\n");
473 hres = IBackgroundCopyJob_Complete(test_job);
474 ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
475 hres = IBackgroundCopyJob_GetState(test_job, &state);
476 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
477 ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
478
479 compareFiles(test_remotePathA, test_localPathA);
480 compareFiles(test_remotePathB, test_localPathB);
481
482 ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
483 ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
484 DeleteFileW(test_localPathA);
485 DeleteFileW(test_localPathB);
486
487 HeapFree(GetProcessHeap(), 0, urlA);
488 HeapFree(GetProcessHeap(), 0, urlB);
489 }
490
491 typedef void (*test_t)(void);
492
493 START_TEST(job)
494 {
495 static const test_t tests[] = {
496 test_GetId,
497 test_GetType,
498 test_GetName,
499 test_GetProgress_preTransfer,
500 test_GetState,
501 test_ResumeEmpty,
502 0
503 };
504 static const test_t tests_bits20[] = {
505 test_AddFile,
506 test_AddFileSet,
507 test_EnumFiles,
508 test_CompleteLocal,
509 test_CompleteLocalURL,
510 0
511 };
512 const test_t *test;
513
514 init_paths();
515
516 CoInitialize(NULL);
517
518 for (test = tests; *test; ++test)
519 {
520 /* Keep state separate between tests. */
521 if (!setup())
522 {
523 skip("Unable to setup test\n");
524 break;
525 }
526 (*test)();
527 teardown();
528 }
529
530 if (check_bits20())
531 {
532 for (test = tests_bits20; *test; ++test)
533 {
534 /* Keep state separate between tests. */
535 if (!setup())
536 {
537 skip("Unable to setup test\n");
538 break;
539 }
540 (*test)();
541 teardown();
542 }
543 }
544 else
545 {
546 win_skip("Tests need BITS 2.0 or higher\n");
547 }
548
549 CoUninitialize();
550 }