105ddda96d33cb11b8e574ad2252c06ed2d54306
[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 HRESULT test_create_manager(void)
46 {
47 HRESULT hres;
48 IBackgroundCopyManager *manager = NULL;
49
50 /* Creating BITS instance */
51 hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL, CLSCTX_LOCAL_SERVER,
52 &IID_IBackgroundCopyManager, (void **) &manager);
53
54 if(hres == HRESULT_FROM_WIN32(ERROR_SERVICE_DISABLED)) {
55 win_skip("Needed Service is disabled\n");
56 return hres;
57 }
58
59 if (hres == S_OK)
60 IBackgroundCopyManager_Release(manager);
61
62 return hres;
63 }
64
65 static void init_paths(void)
66 {
67 WCHAR tmpDir[MAX_PATH];
68 WCHAR prefix[] = {'q', 'm', 'g', 'r', 0};
69
70 GetTempPathW(MAX_PATH, tmpDir);
71
72 GetTempFileNameW(tmpDir, prefix, 0, test_localPathA);
73 GetTempFileNameW(tmpDir, prefix, 0, test_localPathB);
74 GetTempFileNameW(tmpDir, prefix, 0, test_remotePathA);
75 GetTempFileNameW(tmpDir, prefix, 0, test_remotePathB);
76 }
77
78 /* Generic test setup */
79 static BOOL setup(void)
80 {
81 HRESULT hres;
82
83 test_manager = NULL;
84 test_job = NULL;
85 memset(&test_jobId, 0, sizeof test_jobId);
86 test_type = BG_JOB_TYPE_DOWNLOAD;
87
88 hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL,
89 CLSCTX_LOCAL_SERVER,
90 &IID_IBackgroundCopyManager,
91 (void **) &test_manager);
92 if(hres != S_OK)
93 return FALSE;
94
95 hres = IBackgroundCopyManager_CreateJob(test_manager, test_displayName,
96 test_type, &test_jobId, &test_job);
97 if(hres != S_OK)
98 {
99 IBackgroundCopyManager_Release(test_manager);
100 return FALSE;
101 }
102
103 return TRUE;
104 }
105
106 /* Generic test cleanup */
107 static void teardown(void)
108 {
109 IBackgroundCopyJob_Release(test_job);
110 IBackgroundCopyManager_Release(test_manager);
111 }
112
113 /* FIXME: Remove when Wine has implemented this */
114 DEFINE_GUID(CLSID_BackgroundCopyManager2_0, 0x6d18ad12, 0xbde3, 0x4393, 0xb3,0x11, 0x09,0x9c,0x34,0x6e,0x6d,0xf9);
115
116 static BOOL check_bits20(void)
117 {
118 HRESULT hres;
119 IBackgroundCopyManager *manager;
120 BOOL ret = TRUE;
121
122 hres = CoCreateInstance(&CLSID_BackgroundCopyManager2_0, NULL,
123 CLSCTX_LOCAL_SERVER,
124 &IID_IBackgroundCopyManager,
125 (void **) &manager);
126
127 if (hres == REGDB_E_CLASSNOTREG)
128 {
129 ret = FALSE;
130
131 /* FIXME: Wine implements 2.0 functionality but doesn't advertise 2.0
132 *
133 * Remove when Wine is fixed
134 */
135 if (setup())
136 {
137 HRESULT hres2;
138
139 hres2 = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
140 test_localPathA);
141 if (hres2 == S_OK)
142 {
143 trace("Running on Wine, claim 2.0 is present\n");
144 ret = TRUE;
145 }
146 teardown();
147 }
148 }
149
150 if (manager)
151 IBackgroundCopyManager_Release(manager);
152
153 return ret;
154 }
155
156 /* Test that the jobId is properly set */
157 static void test_GetId(void)
158 {
159 HRESULT hres;
160 GUID tmpId;
161
162 hres = IBackgroundCopyJob_GetId(test_job, &tmpId);
163 ok(hres == S_OK, "GetId failed: %08x\n", hres);
164 ok(memcmp(&tmpId, &test_jobId, sizeof tmpId) == 0, "Got incorrect GUID\n");
165 }
166
167 /* Test that the type is properly set */
168 static void test_GetType(void)
169 {
170 HRESULT hres;
171 BG_JOB_TYPE type;
172
173 hres = IBackgroundCopyJob_GetType(test_job, &type);
174 ok(hres == S_OK, "GetType failed: %08x\n", hres);
175 ok(type == test_type, "Got incorrect type\n");
176 }
177
178 /* Test that the display name is properly set */
179 static void test_GetName(void)
180 {
181 HRESULT hres;
182 LPWSTR displayName;
183
184 hres = IBackgroundCopyJob_GetDisplayName(test_job, &displayName);
185 ok(hres == S_OK, "GetName failed: %08x\n", hres);
186 ok(lstrcmpW(displayName, test_displayName) == 0, "Got incorrect type\n");
187 CoTaskMemFree(displayName);
188 }
189
190 /* Test adding a file */
191 static void test_AddFile(void)
192 {
193 HRESULT hres;
194
195 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
196 test_localPathA);
197 ok(hres == S_OK, "First call to AddFile failed: 0x%08x\n", hres);
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 ok(hres == S_OK, "got 0x%08x\n", hres);
227
228 hres = IBackgroundCopyJob_EnumFiles(test_job, &enumFiles);
229 ok(hres == S_OK, "EnumFiles failed: 0x%08x\n", hres);
230
231 res = IEnumBackgroundCopyFiles_Release(enumFiles);
232 ok(res == 0, "Bad ref count on release: %u\n", res);
233 }
234
235 /* Test getting job progress */
236 static void test_GetProgress_preTransfer(void)
237 {
238 HRESULT hres;
239 BG_JOB_PROGRESS progress;
240
241 hres = IBackgroundCopyJob_GetProgress(test_job, &progress);
242 ok(hres == S_OK, "GetProgress failed: 0x%08x\n", hres);
243
244 ok(progress.BytesTotal == 0, "Incorrect BytesTotal: %x%08x\n",
245 (DWORD)(progress.BytesTotal >> 32), (DWORD)progress.BytesTotal);
246 ok(progress.BytesTransferred == 0, "Incorrect BytesTransferred: %x%08x\n",
247 (DWORD)(progress.BytesTransferred >> 32), (DWORD)progress.BytesTransferred);
248 ok(progress.FilesTotal == 0, "Incorrect FilesTotal: %u\n", progress.FilesTotal);
249 ok(progress.FilesTransferred == 0, "Incorrect FilesTransferred %u\n", progress.FilesTransferred);
250 }
251
252 /* Test getting job state */
253 static void test_GetState(void)
254 {
255 HRESULT hres;
256 BG_JOB_STATE state;
257
258 state = BG_JOB_STATE_ERROR;
259 hres = IBackgroundCopyJob_GetState(test_job, &state);
260 ok(hres == S_OK, "GetState failed: 0x%08x\n", hres);
261 ok(state == BG_JOB_STATE_SUSPENDED, "Incorrect job state: %d\n", state);
262 }
263
264 /* Test resuming a job */
265 static void test_ResumeEmpty(void)
266 {
267 HRESULT hres;
268 BG_JOB_STATE state;
269
270 hres = IBackgroundCopyJob_Resume(test_job);
271 ok(hres == BG_E_EMPTY, "Resume failed to return BG_E_EMPTY error: 0x%08x\n", hres);
272
273 state = BG_JOB_STATE_ERROR;
274 hres = IBackgroundCopyJob_GetState(test_job, &state);
275 ok(hres == S_OK, "got 0x%08x\n", hres);
276 ok(state == BG_JOB_STATE_SUSPENDED, "Incorrect job state: %d\n", state);
277 }
278
279 static void makeFile(WCHAR *name, const char *contents)
280 {
281 HANDLE file;
282 DWORD w, len = strlen(contents);
283
284 DeleteFileW(name);
285 file = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
286 FILE_ATTRIBUTE_NORMAL, NULL);
287 ok(file != INVALID_HANDLE_VALUE, "CreateFile\n");
288 ok(WriteFile(file, contents, len, &w, NULL), "WriteFile\n");
289 CloseHandle(file);
290 }
291
292 static void compareFiles(WCHAR *n1, WCHAR *n2)
293 {
294 char b1[256];
295 char b2[256];
296 DWORD s1, s2;
297 HANDLE f1, f2;
298
299 f1 = CreateFileW(n1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
300 FILE_ATTRIBUTE_NORMAL, NULL);
301 ok(f1 != INVALID_HANDLE_VALUE, "CreateFile\n");
302
303 f2 = CreateFileW(n2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
304 FILE_ATTRIBUTE_NORMAL, NULL);
305 ok(f2 != INVALID_HANDLE_VALUE, "CreateFile\n");
306
307 /* Neither of these files is very big */
308 ok(ReadFile(f1, b1, sizeof b1, &s1, NULL), "ReadFile\n");
309 ok(ReadFile(f2, b2, sizeof b2, &s2, NULL), "ReadFile\n");
310
311 CloseHandle(f1);
312 CloseHandle(f2);
313
314 ok(s1 == s2, "Files differ in length\n");
315 ok(memcmp(b1, b2, s1) == 0, "Files differ in contents\n");
316 }
317
318 /* Test a complete transfer for local files */
319 static void test_CompleteLocal(void)
320 {
321 static const int timeout_sec = 30;
322 HRESULT hres;
323 BG_JOB_STATE state;
324 int i;
325
326 DeleteFileW(test_localPathA);
327 DeleteFileW(test_localPathB);
328 makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
329 makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
330
331 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
332 test_localPathA);
333 ok(hres == S_OK, "got 0x%08x\n", hres);
334
335 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathB,
336 test_localPathB);
337 ok(hres == S_OK, "got 0x%08x\n", hres);
338
339 hres = IBackgroundCopyJob_Resume(test_job);
340 ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
341
342 for (i = 0; i < timeout_sec; ++i)
343 {
344 hres = IBackgroundCopyJob_GetState(test_job, &state);
345 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
346 ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
347 || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED,
348 "Bad state: %d\n", state);
349 if (state == BG_JOB_STATE_TRANSFERRED)
350 break;
351 Sleep(1000);
352 }
353
354 ok(i < timeout_sec, "BITS jobs timed out\n");
355 hres = IBackgroundCopyJob_Complete(test_job);
356 ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
357 hres = IBackgroundCopyJob_GetState(test_job, &state);
358 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
359 ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
360
361 compareFiles(test_remotePathA, test_localPathA);
362 compareFiles(test_remotePathB, test_localPathB);
363
364 ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
365 ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
366 DeleteFileW(test_localPathA);
367 DeleteFileW(test_localPathB);
368 }
369
370 /* Test a complete transfer for local files */
371 static void test_CompleteLocalURL(void)
372 {
373 static const WCHAR prot[] = {'f','i','l','e',':','/','/', 0};
374 static const int timeout_sec = 30;
375 WCHAR *urlA, *urlB;
376 HRESULT hres;
377 BG_JOB_STATE state;
378 int i;
379
380 DeleteFileW(test_localPathA);
381 DeleteFileW(test_localPathB);
382 makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
383 makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
384
385 urlA = HeapAlloc(GetProcessHeap(), 0,
386 (7 + lstrlenW(test_remotePathA) + 1) * sizeof urlA[0]);
387 urlB = HeapAlloc(GetProcessHeap(), 0,
388 (7 + lstrlenW(test_remotePathB) + 1) * sizeof urlB[0]);
389 if (!urlA || !urlB)
390 {
391 skip("Unable to allocate memory for URLs\n");
392 HeapFree(GetProcessHeap(), 0, urlA);
393 HeapFree(GetProcessHeap(), 0, urlB);
394 return;
395 }
396
397 lstrcpyW(urlA, prot);
398 lstrcatW(urlA, test_remotePathA);
399 lstrcpyW(urlB, prot);
400 lstrcatW(urlB, test_remotePathB);
401
402 hres = IBackgroundCopyJob_AddFile(test_job, urlA, test_localPathA);
403 ok(hres == S_OK, "got 0x%08x\n", hres);
404
405 hres = IBackgroundCopyJob_AddFile(test_job, urlB, test_localPathB);
406 ok(hres == S_OK, "got 0x%08x\n", hres);
407
408 hres = IBackgroundCopyJob_Resume(test_job);
409 ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
410
411 for (i = 0; i < timeout_sec; ++i)
412 {
413 hres = IBackgroundCopyJob_GetState(test_job, &state);
414 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
415 ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
416 || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED,
417 "Bad state: %d\n", state);
418 if (state == BG_JOB_STATE_TRANSFERRED)
419 break;
420 Sleep(1000);
421 }
422
423 ok(i < timeout_sec, "BITS jobs timed out\n");
424 hres = IBackgroundCopyJob_Complete(test_job);
425 ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
426 hres = IBackgroundCopyJob_GetState(test_job, &state);
427 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
428 ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
429
430 compareFiles(test_remotePathA, test_localPathA);
431 compareFiles(test_remotePathB, test_localPathB);
432
433 ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
434 ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
435 DeleteFileW(test_localPathA);
436 DeleteFileW(test_localPathB);
437
438 HeapFree(GetProcessHeap(), 0, urlA);
439 HeapFree(GetProcessHeap(), 0, urlB);
440 }
441
442 static void test_NotifyFlags(void)
443 {
444 ULONG flags;
445 HRESULT hr;
446
447 /* check default flags */
448 flags = 0;
449 hr = IBackgroundCopyJob_GetNotifyFlags(test_job, &flags);
450 ok(hr == S_OK, "got 0x%08x\n", hr);
451 ok(flags == (BG_NOTIFY_JOB_ERROR | BG_NOTIFY_JOB_TRANSFERRED), "flags 0x%08x\n", flags);
452 }
453
454 static void test_NotifyInterface(void)
455 {
456 HRESULT hr;
457 IUnknown *unk;
458
459 unk = (IUnknown*)0xdeadbeef;
460 hr = IBackgroundCopyJob_GetNotifyInterface(test_job, &unk);
461 ok(hr == S_OK, "got 0x%08x\n", hr);
462 ok(unk == NULL, "got %p\n", unk);
463 }
464
465 typedef void (*test_t)(void);
466
467 START_TEST(job)
468 {
469 static const test_t tests[] = {
470 test_GetId,
471 test_GetType,
472 test_GetName,
473 test_GetProgress_preTransfer,
474 test_GetState,
475 test_ResumeEmpty,
476 test_NotifyFlags,
477 test_NotifyInterface,
478 0
479 };
480 static const test_t tests_bits20[] = {
481 test_AddFile,
482 test_AddFileSet,
483 test_EnumFiles,
484 test_CompleteLocal,
485 test_CompleteLocalURL,
486 0
487 };
488 const test_t *test;
489 int i;
490
491 init_paths();
492
493 CoInitialize(NULL);
494
495 if (FAILED(test_create_manager()))
496 {
497 CoUninitialize();
498 win_skip("Failed to create Manager instance, skipping tests\n");
499 return;
500 }
501
502 for (test = tests, i = 0; *test; ++test, ++i)
503 {
504 /* Keep state separate between tests. */
505 if (!setup())
506 {
507 ok(0, "tests:%d: Unable to setup test\n", i);
508 break;
509 }
510 (*test)();
511 teardown();
512 }
513
514 if (check_bits20())
515 {
516 for (test = tests_bits20, i = 0; *test; ++test, ++i)
517 {
518 /* Keep state separate between tests. */
519 if (!setup())
520 {
521 ok(0, "tests_bits20:%d: Unable to setup test\n", i);
522 break;
523 }
524 (*test)();
525 teardown();
526 }
527 }
528 else
529 {
530 win_skip("Tests need BITS 2.0 or higher\n");
531 }
532
533 CoUninitialize();
534 }