include: Add missing enum XHR_PROP_ values.
[wine.git] / dlls / qmgr / tests / job.c
blobc106014bcfe68ebc4e866e3cd56e5d203de2baf5
1 /*
2 * Unit test suite for Background Copy Job Interface
4 * Copyright 2007 Google (Roy Shea)
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.
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.
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
21 #include <stdio.h>
23 #define COBJMACROS
25 #include "wine/test.h"
26 #include "bits.h"
27 #include "initguid.h"
28 #include "bits2_0.h"
29 #include "bits2_5.h"
30 #include "bits5_0.h"
32 /* Globals used by many tests */
33 static WCHAR test_remotePathA[MAX_PATH];
34 static WCHAR test_remotePathB[MAX_PATH];
35 static WCHAR test_localPathA[MAX_PATH];
36 static WCHAR test_localPathB[MAX_PATH];
37 static IBackgroundCopyManager *test_manager;
38 static IBackgroundCopyJob *test_job;
39 static GUID test_jobId;
40 static BG_JOB_TYPE test_type;
42 typedef struct IBackgroundCopyCallback2Impl {
43 IBackgroundCopyCallback2 IBackgroundCopyCallback2_iface;
44 LONG ref;
45 } IBackgroundCopyCallback2Impl;
47 static inline IBackgroundCopyCallback2Impl *impl_from_IBackgroundCopyCallback2(IBackgroundCopyCallback2 *iface)
49 return CONTAINING_RECORD(iface, IBackgroundCopyCallback2Impl, IBackgroundCopyCallback2_iface);
52 static HRESULT WINAPI IBackgroundCopyCallback2Impl_QueryInterface(IBackgroundCopyCallback2 *iface, REFIID riid, void **ppv)
54 IBackgroundCopyCallback2Impl *This = impl_from_IBackgroundCopyCallback2(iface);
56 if (!ppv)
58 return E_INVALIDARG;
61 *ppv = NULL;
63 if (IsEqualIID(riid, &IID_IUnknown) ||
64 IsEqualIID(riid, &IID_IBackgroundCopyCallback) ||
65 IsEqualIID(riid, &IID_IBackgroundCopyCallback2))
67 *ppv = &This->IBackgroundCopyCallback2_iface;
69 else
71 return E_NOINTERFACE;
74 IUnknown_AddRef((IUnknown*)*ppv);
75 return S_OK;
78 static ULONG WINAPI IBackgroundCopyCallback2Impl_AddRef(IBackgroundCopyCallback2 *iface)
80 IBackgroundCopyCallback2Impl *This = impl_from_IBackgroundCopyCallback2(iface);
81 ULONG ref = InterlockedIncrement(&This->ref);
83 trace("IBackgroundCopyCallback2Impl_AddRef called (%p, ref = %ld)\n", This, ref);
84 return ref;
87 static ULONG WINAPI IBackgroundCopyCallback2Impl_Release(IBackgroundCopyCallback2 *iface)
89 IBackgroundCopyCallback2Impl *This = impl_from_IBackgroundCopyCallback2(iface);
90 ULONG ref = InterlockedDecrement(&This->ref);
92 trace("IBackgroundCopyCallback2Impl_Release called (%p, ref = %ld)\n", This, ref);
94 if (ref == 0)
96 HeapFree(GetProcessHeap(), 0, This);
99 return ref;
102 static HRESULT WINAPI IBackgroundCopyCallback2Impl_JobError(IBackgroundCopyCallback2 *iface, IBackgroundCopyJob *pJob, IBackgroundCopyError *pError)
104 trace("IBackgroundCopyCallback2Impl_JobError called (%p, %p, %p)\n", iface, pJob, pError);
105 return S_OK;
108 static HRESULT WINAPI IBackgroundCopyCallback2Impl_JobModification(IBackgroundCopyCallback2 *iface, IBackgroundCopyJob *pJob, DWORD dwReserved)
110 trace("IBackgroundCopyCallback2Impl_JobModification called (%p, %p)\n", iface, pJob);
111 return S_OK;
114 static HRESULT WINAPI IBackgroundCopyCallback2Impl_JobTransferred(IBackgroundCopyCallback2 *iface, IBackgroundCopyJob *pJob)
116 trace("IBackgroundCopyCallback2Impl_JobTransferred called (%p, %p)\n", iface, pJob);
117 return S_OK;
120 static HRESULT WINAPI IBackgroundCopyCallback2Impl_FileTransferred(IBackgroundCopyCallback2 *iface, IBackgroundCopyJob *pJob, IBackgroundCopyFile *pFile)
122 trace("IBackgroundCopyCallback2Impl_FileTransferred called (%p, %p, %p)\n", iface, pJob, pFile);
123 return S_OK;
127 static const IBackgroundCopyCallback2Vtbl copyCallback_vtbl =
129 IBackgroundCopyCallback2Impl_QueryInterface,
130 IBackgroundCopyCallback2Impl_AddRef,
131 IBackgroundCopyCallback2Impl_Release,
132 IBackgroundCopyCallback2Impl_JobTransferred,
133 IBackgroundCopyCallback2Impl_JobError,
134 IBackgroundCopyCallback2Impl_JobModification,
135 IBackgroundCopyCallback2Impl_FileTransferred
138 static BOOL create_background_copy_callback2(IBackgroundCopyCallback2 **copyCallback)
140 IBackgroundCopyCallback2Impl *obj;
141 *copyCallback = NULL;
143 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj));
145 if (!obj)
147 trace("Out of memory creating IBackgroundCopyCallback2\n");
148 return FALSE;
151 obj->IBackgroundCopyCallback2_iface.lpVtbl = &copyCallback_vtbl;
152 obj->ref = 1;
154 *copyCallback = &obj->IBackgroundCopyCallback2_iface;
156 return TRUE;
159 static HRESULT test_create_manager(void)
161 HRESULT hres;
162 IBackgroundCopyManager *manager = NULL;
164 /* Creating BITS instance */
165 hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL, CLSCTX_LOCAL_SERVER,
166 &IID_IBackgroundCopyManager, (void **) &manager);
168 if(hres == HRESULT_FROM_WIN32(ERROR_SERVICE_DISABLED)) {
169 win_skip("Needed Service is disabled\n");
170 return hres;
173 if (hres == S_OK)
174 IBackgroundCopyManager_Release(manager);
176 return hres;
179 static void init_paths(void)
181 WCHAR tmpDir[MAX_PATH];
182 WCHAR prefix[] = L"qmgr";
184 GetTempPathW(MAX_PATH, tmpDir);
186 GetTempFileNameW(tmpDir, prefix, 0, test_localPathA);
187 GetTempFileNameW(tmpDir, prefix, 0, test_localPathB);
188 GetTempFileNameW(tmpDir, prefix, 0, test_remotePathA);
189 GetTempFileNameW(tmpDir, prefix, 0, test_remotePathB);
192 /* Generic test setup */
193 static BOOL setup(void)
195 HRESULT hres;
196 IBackgroundCopyJob5* test_job_5;
197 BITS_JOB_PROPERTY_VALUE prop_val;
199 test_manager = NULL;
200 test_job = NULL;
201 memset(&test_jobId, 0, sizeof test_jobId);
202 test_type = BG_JOB_TYPE_DOWNLOAD;
204 hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL,
205 CLSCTX_LOCAL_SERVER,
206 &IID_IBackgroundCopyManager,
207 (void **) &test_manager);
208 if(hres != S_OK)
209 return FALSE;
211 hres = IBackgroundCopyManager_CreateJob(test_manager, L"Test", test_type, &test_jobId, &test_job);
212 if(hres != S_OK)
214 IBackgroundCopyManager_Release(test_manager);
215 return FALSE;
218 /* The Wine TestBot Windows 10 VMs disable Windows Update by putting
219 the network connection in metered mode.
221 Unfortunately, this will make BITS jobs fail, since the default transfer policy
222 on Windows 10 prevents BITs job from running over a metered network
224 To allow these tests in this file to run on the testbot, we
225 set the BITS_JOB_PROPERTY_ID_COST_FLAGS property to BITS_COST_STATE_TRANSFER_ALWAYS,
226 ensuring that BITS will still try to run the job on a metered network */
227 prop_val.Dword = BITS_COST_STATE_TRANSFER_ALWAYS;
228 hres = IBackgroundCopyJob_QueryInterface(test_job, &IID_IBackgroundCopyJob5, (void **)&test_job_5);
229 /* BackgroundCopyJob5 was added in Windows 8, so this may not exist. The metered connection
230 workaround is only applied on Windows 10, so it's fine if this fails. */
231 if (SUCCEEDED(hres)) {
232 hres = IBackgroundCopyJob5_SetProperty(test_job_5, BITS_JOB_PROPERTY_ID_COST_FLAGS, prop_val);
233 ok(hres == S_OK, "Failed to set the cost flags: %08lx\n", hres);
234 IBackgroundCopyJob5_Release(test_job_5);
237 return TRUE;
240 /* Generic test cleanup */
241 static void teardown(void)
243 IBackgroundCopyJob_Cancel(test_job);
244 IBackgroundCopyJob_Release(test_job);
245 IBackgroundCopyManager_Release(test_manager);
248 static BOOL check_bits20(void)
250 HRESULT hres;
251 IBackgroundCopyManager *manager;
252 IBackgroundCopyJob *job, *job3;
254 hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL,
255 CLSCTX_LOCAL_SERVER, &IID_IBackgroundCopyManager,
256 (void **)&manager);
257 if (hres != S_OK) return FALSE;
259 hres = IBackgroundCopyManager_CreateJob(manager, L"Test", test_type, &test_jobId, &job);
260 if (hres != S_OK)
262 IBackgroundCopyManager_Release(manager);
263 return FALSE;
266 hres = IBackgroundCopyJob_QueryInterface(job, &IID_IBackgroundCopyJob3, (void **)&job3);
267 IBackgroundCopyJob_Cancel(job);
268 IBackgroundCopyJob_Release(job);
269 if (hres != S_OK)
271 IBackgroundCopyManager_Release(manager);
272 return FALSE;
275 IBackgroundCopyJob_Release(job3);
276 IBackgroundCopyManager_Release(manager);
277 return TRUE;
280 static BOOL check_bits25(void)
282 HRESULT hres;
283 IBackgroundCopyManager *manager;
284 IBackgroundCopyJob *job;
285 IBackgroundCopyJobHttpOptions *options;
287 hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL,
288 CLSCTX_LOCAL_SERVER, &IID_IBackgroundCopyManager,
289 (void **)&manager);
290 if (hres != S_OK) return FALSE;
292 hres = IBackgroundCopyManager_CreateJob(manager, L"Test", test_type, &test_jobId, &job);
293 if (hres != S_OK)
295 IBackgroundCopyManager_Release(manager);
296 return FALSE;
299 hres = IBackgroundCopyJob_QueryInterface(job, &IID_IBackgroundCopyJobHttpOptions, (void **)&options);
300 IBackgroundCopyJob_Cancel(job);
301 IBackgroundCopyJob_Release(job);
302 if (hres != S_OK)
304 IBackgroundCopyManager_Release(manager);
305 return FALSE;
308 IBackgroundCopyJobHttpOptions_Release(options);
309 IBackgroundCopyManager_Release(manager);
310 return TRUE;
313 /* Test that the jobId is properly set */
314 static void test_GetId(void)
316 HRESULT hres;
317 GUID tmpId;
319 hres = IBackgroundCopyJob_GetId(test_job, &tmpId);
320 ok(hres == S_OK, "GetId failed: %08lx\n", hres);
321 ok(memcmp(&tmpId, &test_jobId, sizeof tmpId) == 0, "Got incorrect GUID\n");
324 /* Test that the type is properly set */
325 static void test_GetType(void)
327 HRESULT hres;
328 BG_JOB_TYPE type;
330 hres = IBackgroundCopyJob_GetType(test_job, &type);
331 ok(hres == S_OK, "GetType failed: %08lx\n", hres);
332 ok(type == test_type, "Got incorrect type\n");
335 /* Test that the display name is properly set */
336 static void test_GetName(void)
338 HRESULT hres;
339 LPWSTR displayName;
341 hres = IBackgroundCopyJob_GetDisplayName(test_job, &displayName);
342 ok(hres == S_OK, "GetName failed: %08lx\n", hres);
343 ok(lstrcmpW(displayName, L"Test") == 0, "Got incorrect type\n");
344 CoTaskMemFree(displayName);
347 /* Test adding a file */
348 static void test_AddFile(void)
350 HRESULT hres;
352 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
353 test_localPathA);
354 ok(hres == S_OK, "First call to AddFile failed: 0x%08lx\n", hres);
356 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathB,
357 test_localPathB);
358 ok(hres == S_OK, "Second call to AddFile failed: 0x%08lx\n", hres);
361 /* Test adding a set of files */
362 static void test_AddFileSet(void)
364 HRESULT hres;
365 BG_FILE_INFO files[2] =
367 {test_remotePathA, test_localPathA},
368 {test_remotePathB, test_localPathB}
370 hres = IBackgroundCopyJob_AddFileSet(test_job, 2, files);
371 ok(hres == S_OK, "AddFileSet failed: 0x%08lx\n", hres);
374 /* Test creation of a job enumerator */
375 static void test_EnumFiles(void)
377 HRESULT hres;
378 IEnumBackgroundCopyFiles *enumFiles;
379 ULONG res;
381 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
382 test_localPathA);
383 ok(hres == S_OK, "got 0x%08lx\n", hres);
385 hres = IBackgroundCopyJob_EnumFiles(test_job, &enumFiles);
386 ok(hres == S_OK, "EnumFiles failed: 0x%08lx\n", hres);
388 res = IEnumBackgroundCopyFiles_Release(enumFiles);
389 ok(res == 0, "Bad ref count on release: %lu\n", res);
392 /* Test getting job progress */
393 static void test_GetProgress_preTransfer(void)
395 HRESULT hres;
396 BG_JOB_PROGRESS progress;
398 hres = IBackgroundCopyJob_GetProgress(test_job, &progress);
399 ok(hres == S_OK, "GetProgress failed: 0x%08lx\n", hres);
401 ok(progress.BytesTotal == 0, "Incorrect BytesTotal: %s\n",
402 wine_dbgstr_longlong(progress.BytesTotal));
403 ok(progress.BytesTransferred == 0, "Incorrect BytesTransferred: %s\n",
404 wine_dbgstr_longlong(progress.BytesTransferred));
405 ok(progress.FilesTotal == 0, "Incorrect FilesTotal: %lu\n", progress.FilesTotal);
406 ok(progress.FilesTransferred == 0, "Incorrect FilesTransferred %lu\n", progress.FilesTransferred);
409 /* Test getting job state */
410 static void test_GetState(void)
412 HRESULT hres;
413 BG_JOB_STATE state;
415 state = BG_JOB_STATE_ERROR;
416 hres = IBackgroundCopyJob_GetState(test_job, &state);
417 ok(hres == S_OK, "GetState failed: 0x%08lx\n", hres);
418 ok(state == BG_JOB_STATE_SUSPENDED, "Incorrect job state: %d\n", state);
421 /* Test resuming a job */
422 static void test_ResumeEmpty(void)
424 HRESULT hres;
425 BG_JOB_STATE state;
427 hres = IBackgroundCopyJob_Resume(test_job);
428 ok(hres == BG_E_EMPTY, "Resume failed to return BG_E_EMPTY error: 0x%08lx\n", hres);
430 state = BG_JOB_STATE_ERROR;
431 hres = IBackgroundCopyJob_GetState(test_job, &state);
432 ok(hres == S_OK, "got 0x%08lx\n", hres);
433 ok(state == BG_JOB_STATE_SUSPENDED, "Incorrect job state: %d\n", state);
436 static void makeFile(WCHAR *name, const char *contents)
438 HANDLE file;
439 DWORD w, len = strlen(contents);
441 DeleteFileW(name);
442 file = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
443 FILE_ATTRIBUTE_NORMAL, NULL);
444 ok(file != INVALID_HANDLE_VALUE, "CreateFile\n");
445 ok(WriteFile(file, contents, len, &w, NULL), "WriteFile\n");
446 CloseHandle(file);
449 static void compareFiles(WCHAR *n1, WCHAR *n2)
451 char b1[256];
452 char b2[256];
453 DWORD s1, s2;
454 HANDLE f1, f2;
456 f1 = CreateFileW(n1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
457 FILE_ATTRIBUTE_NORMAL, NULL);
458 ok(f1 != INVALID_HANDLE_VALUE, "CreateFile\n");
460 f2 = CreateFileW(n2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
461 FILE_ATTRIBUTE_NORMAL, NULL);
462 ok(f2 != INVALID_HANDLE_VALUE, "CreateFile\n");
464 /* Neither of these files is very big */
465 ok(ReadFile(f1, b1, sizeof b1, &s1, NULL), "ReadFile\n");
466 ok(ReadFile(f2, b2, sizeof b2, &s2, NULL), "ReadFile\n");
468 CloseHandle(f1);
469 CloseHandle(f2);
471 ok(s1 == s2, "Files differ in length\n");
472 ok(memcmp(b1, b2, s1) == 0, "Files differ in contents\n");
475 /* Handles a timeout in the BG_JOB_STATE_ERROR or BG_JOB_STATE_TRANSIENT_ERROR state */
476 static void handle_job_err(void)
478 HRESULT hres;
479 IBackgroundCopyError *err;
480 BG_ERROR_CONTEXT errContext;
481 HRESULT errCode;
482 LPWSTR contextDesc;
483 LPWSTR errDesc;
485 hres = IBackgroundCopyJob_GetError(test_job, &err);
486 if (SUCCEEDED(hres)) {
487 hres = IBackgroundCopyError_GetError(err, &errContext, &errCode);
488 if (SUCCEEDED(hres)) {
489 ok(0, "Got context: %d code: %ld\n", errContext, errCode);
490 } else {
491 ok(0, "Failed to get error info: 0x%08lx\n", hres);
494 hres = IBackgroundCopyError_GetErrorContextDescription(err, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &contextDesc);
495 if (SUCCEEDED(hres)) {
496 ok(0, "Got context desc: %s\n", wine_dbgstr_w(contextDesc));
497 } else {
498 ok(0, "Failed to get context desc: 0x%08lx\n", hres);
501 hres = IBackgroundCopyError_GetErrorDescription(err, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &errDesc);
502 if (SUCCEEDED(hres)) {
503 ok(0, "Got error desc: %s\n", wine_dbgstr_w(errDesc));
504 } else {
505 ok(0, "Failed to get error desc: 0x%08lx\n", hres);
507 } else {
508 ok(0, "Failed to get error: 0x%08lx\n", hres);
512 /* Test a complete transfer for local files */
513 static void test_CompleteLocal(void)
515 static const int timeout_sec = 30;
516 HRESULT hres;
517 BG_JOB_STATE state;
518 int i;
520 DeleteFileW(test_localPathA);
521 DeleteFileW(test_localPathB);
522 makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
523 makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
525 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
526 test_localPathA);
527 ok(hres == S_OK, "got 0x%08lx\n", hres);
529 hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathB,
530 test_localPathB);
531 ok(hres == S_OK, "got 0x%08lx\n", hres);
533 hres = IBackgroundCopyJob_Resume(test_job);
534 ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
536 for (i = 0; i < timeout_sec; ++i)
538 hres = IBackgroundCopyJob_GetState(test_job, &state);
539 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
540 ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
541 || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED
542 || state == BG_JOB_STATE_TRANSIENT_ERROR,
543 "Bad state: %d\n", state);
545 if (state == BG_JOB_STATE_TRANSIENT_ERROR) {
546 hres = IBackgroundCopyJob_Resume(test_job);
547 ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
550 if (state == BG_JOB_STATE_TRANSFERRED)
551 break;
552 Sleep(1000);
555 if (state == BG_JOB_STATE_ERROR || state == BG_JOB_STATE_TRANSIENT_ERROR)
556 handle_job_err();
558 ok(i < timeout_sec, "BITS jobs timed out\n");
559 hres = IBackgroundCopyJob_Complete(test_job);
560 ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
561 hres = IBackgroundCopyJob_GetState(test_job, &state);
562 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
563 ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
565 compareFiles(test_remotePathA, test_localPathA);
566 compareFiles(test_remotePathB, test_localPathB);
568 ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
569 ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
570 DeleteFileW(test_localPathA);
571 DeleteFileW(test_localPathB);
574 /* Test a complete transfer for local files */
575 static void test_CompleteLocalURL(void)
577 static const int timeout_sec = 30;
578 WCHAR *urlA, *urlB;
579 HRESULT hres;
580 BG_JOB_STATE state;
581 int i;
583 DeleteFileW(test_localPathA);
584 DeleteFileW(test_localPathB);
585 makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
586 makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
588 urlA = HeapAlloc(GetProcessHeap(), 0,
589 (7 + lstrlenW(test_remotePathA) + 1) * sizeof urlA[0]);
590 urlB = HeapAlloc(GetProcessHeap(), 0,
591 (7 + lstrlenW(test_remotePathB) + 1) * sizeof urlB[0]);
592 if (!urlA || !urlB)
594 skip("Unable to allocate memory for URLs\n");
595 HeapFree(GetProcessHeap(), 0, urlA);
596 HeapFree(GetProcessHeap(), 0, urlB);
597 return;
600 lstrcpyW(urlA, L"file://");
601 lstrcatW(urlA, test_remotePathA);
602 lstrcpyW(urlB, L"file://");
603 lstrcatW(urlB, test_remotePathB);
605 hres = IBackgroundCopyJob_AddFile(test_job, urlA, test_localPathA);
606 ok(hres == S_OK, "got 0x%08lx\n", hres);
608 hres = IBackgroundCopyJob_AddFile(test_job, urlB, test_localPathB);
609 ok(hres == S_OK, "got 0x%08lx\n", hres);
611 hres = IBackgroundCopyJob_Resume(test_job);
612 ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
614 for (i = 0; i < timeout_sec; ++i)
616 hres = IBackgroundCopyJob_GetState(test_job, &state);
617 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
618 ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
619 || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED
620 || state == BG_JOB_STATE_TRANSIENT_ERROR,
621 "Bad state: %d\n", state);
623 if (state == BG_JOB_STATE_TRANSIENT_ERROR) {
624 hres = IBackgroundCopyJob_Resume(test_job);
625 ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
628 if (state == BG_JOB_STATE_TRANSFERRED)
629 break;
630 Sleep(1000);
633 if (state == BG_JOB_STATE_ERROR || state == BG_JOB_STATE_TRANSIENT_ERROR)
634 handle_job_err();
637 ok(i < timeout_sec, "BITS jobs timed out\n");
638 hres = IBackgroundCopyJob_Complete(test_job);
639 ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
640 hres = IBackgroundCopyJob_GetState(test_job, &state);
641 ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
642 ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
644 compareFiles(test_remotePathA, test_localPathA);
645 compareFiles(test_remotePathB, test_localPathB);
647 ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
648 ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
649 DeleteFileW(test_localPathA);
650 DeleteFileW(test_localPathB);
652 HeapFree(GetProcessHeap(), 0, urlA);
653 HeapFree(GetProcessHeap(), 0, urlB);
656 static void test_NotifyFlags(void)
658 ULONG flags;
659 HRESULT hr;
661 /* check default flags */
662 flags = 0;
663 hr = IBackgroundCopyJob_GetNotifyFlags(test_job, &flags);
664 ok(hr == S_OK, "got 0x%08lx\n", hr);
665 ok(flags == (BG_NOTIFY_JOB_ERROR | BG_NOTIFY_JOB_TRANSFERRED), "flags 0x%08lx\n", flags);
668 static void test_NotifyInterface(void)
670 HRESULT hr;
671 IUnknown *unk;
673 unk = (IUnknown*)0xdeadbeef;
674 hr = IBackgroundCopyJob_GetNotifyInterface(test_job, &unk);
675 ok(hr == S_OK, "got 0x%08lx\n", hr);
676 ok(unk == NULL, "got %p\n", unk);
679 static void test_Cancel(void)
681 HRESULT hr;
682 BG_JOB_STATE state;
684 state = BG_JOB_STATE_ERROR;
685 hr = IBackgroundCopyJob_GetState(test_job, &state);
686 ok(hr == S_OK, "got 0x%08lx\n", hr);
687 ok(state != BG_JOB_STATE_CANCELLED, "got %u\n", state);
689 hr = IBackgroundCopyJob_Cancel(test_job);
690 ok(hr == S_OK, "got 0x%08lx\n", hr);
692 state = BG_JOB_STATE_ERROR;
693 hr = IBackgroundCopyJob_GetState(test_job, &state);
694 ok(hr == S_OK, "got 0x%08lx\n", hr);
695 ok(state == BG_JOB_STATE_CANCELLED, "got %u\n", state);
697 hr = IBackgroundCopyJob_Cancel(test_job);
698 ok(hr == BG_E_INVALID_STATE, "got 0x%08lx\n", hr);
701 static void test_HttpOptions(void)
703 static const WCHAR winetestW[] = L"Wine: test\r\n";
704 static const unsigned int timeout = 30;
705 HRESULT hr;
706 IBackgroundCopyJobHttpOptions *options;
707 IBackgroundCopyError *error;
708 BG_JOB_STATE state;
709 unsigned int i;
710 WCHAR *headers;
711 ULONG flags, orig_flags;
712 IBackgroundCopyCallback2 *copyCallback;
713 IUnknown *copyCallbackUnknown;
715 ok(create_background_copy_callback2(&copyCallback) == TRUE, "create_background_copy_callback2 failed\n");
717 hr = IBackgroundCopyCallback2_QueryInterface(copyCallback, &IID_IUnknown, (LPVOID*)&copyCallbackUnknown);
718 ok(hr == S_OK,"IBackgroundCopyCallback_QueryInterface(IID_IUnknown) failed: %08lx\n", hr);
720 hr = IBackgroundCopyJob_SetNotifyInterface(test_job, copyCallbackUnknown);
721 ok(hr == S_OK,"IBackgroundCopyCallback_SetNotifyInterface failed: %08lx\n", hr);
723 hr = IBackgroundCopyJob_SetNotifyFlags(test_job, BG_NOTIFY_JOB_TRANSFERRED | BG_NOTIFY_JOB_ERROR | BG_NOTIFY_DISABLE | BG_NOTIFY_JOB_MODIFICATION | BG_NOTIFY_FILE_TRANSFERRED);
724 ok(hr == S_OK,"IBackgroundCopyCallback_SetNotifyFlags failed: %08lx\n", hr);
727 DeleteFileW(test_localPathA);
728 hr = IBackgroundCopyJob_AddFile(test_job, L"http://test.winehq.org/", test_localPathA);
729 ok(hr == S_OK, "got 0x%08lx\n", hr);
731 hr = IBackgroundCopyJob_QueryInterface(test_job, &IID_IBackgroundCopyJobHttpOptions, (void **)&options);
732 ok(hr == S_OK, "got 0x%08lx\n", hr);
734 if (options)
736 headers = (WCHAR *)0xdeadbeef;
737 hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
738 ok(hr == S_FALSE, "got 0x%08lx\n", hr);
739 ok(headers == NULL, "got %p\n", headers);
741 hr = IBackgroundCopyJobHttpOptions_SetCustomHeaders(options, winetestW);
742 ok(hr == S_OK, "got 0x%08lx\n", hr);
744 headers = (WCHAR *)0xdeadbeef;
745 hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
746 ok(hr == S_OK, "got 0x%08lx\n", hr);
747 if (hr == S_OK)
749 ok(!lstrcmpW(headers, winetestW), "got %s\n", wine_dbgstr_w(headers));
750 CoTaskMemFree(headers);
753 hr = IBackgroundCopyJobHttpOptions_SetCustomHeaders(options, NULL);
754 ok(hr == S_OK, "got 0x%08lx\n", hr);
756 headers = (WCHAR *)0xdeadbeef;
757 hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
758 ok(hr == S_FALSE, "got 0x%08lx\n", hr);
759 ok(headers == NULL, "got %p\n", headers);
761 orig_flags = 0xdeadbeef;
762 hr = IBackgroundCopyJobHttpOptions_GetSecurityFlags(options, &orig_flags);
763 ok(hr == S_OK, "got 0x%08lx\n", hr);
764 ok(!orig_flags, "got 0x%08lx\n", orig_flags);
766 hr = IBackgroundCopyJobHttpOptions_SetSecurityFlags(options, 0);
767 ok(hr == S_OK, "got 0x%08lx\n", hr);
769 flags = 0xdeadbeef;
770 hr = IBackgroundCopyJobHttpOptions_GetSecurityFlags(options, &flags);
771 ok(hr == S_OK, "got 0x%08lx\n", hr);
772 ok(!flags, "got 0x%08lx\n", flags);
775 hr = IBackgroundCopyJob_Resume(test_job);
776 ok(hr == S_OK, "got 0x%08lx\n", hr);
778 for (i = 0; i < timeout; i++)
780 hr = IBackgroundCopyJob_GetState(test_job, &state);
781 ok(hr == S_OK, "got 0x%08lx\n", hr);
783 ok(state == BG_JOB_STATE_QUEUED ||
784 state == BG_JOB_STATE_CONNECTING ||
785 state == BG_JOB_STATE_TRANSFERRING ||
786 state == BG_JOB_STATE_TRANSFERRED ||
787 state == BG_JOB_STATE_TRANSIENT_ERROR, "unexpected state: %u\n", state);
789 if (state == BG_JOB_STATE_TRANSIENT_ERROR) {
790 hr = IBackgroundCopyJob_Resume(test_job);
791 ok(hr == S_OK, "IBackgroundCopyJob_Resume\n");
794 if (state == BG_JOB_STATE_TRANSFERRED) break;
795 Sleep(1000);
798 if (state == BG_JOB_STATE_ERROR || state == BG_JOB_STATE_TRANSIENT_ERROR)
799 handle_job_err();
802 ok(i < timeout, "BITS job timed out\n");
803 if (i < timeout)
805 hr = IBackgroundCopyJob_GetError(test_job, &error);
806 ok(hr == BG_E_ERROR_INFORMATION_UNAVAILABLE, "got 0x%08lx\n", hr);
809 if (options)
811 headers = (WCHAR *)0xdeadbeef;
812 hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
813 ok(hr == S_FALSE, "got 0x%08lx\n", hr);
814 ok(headers == NULL, "got %p\n", headers);
816 hr = IBackgroundCopyJobHttpOptions_SetCustomHeaders(options, NULL);
817 ok(hr == S_OK, "got 0x%08lx\n", hr);
819 hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
820 ok(hr == S_FALSE, "got 0x%08lx\n", hr);
822 flags = 0xdeadbeef;
823 hr = IBackgroundCopyJobHttpOptions_GetSecurityFlags(options, &flags);
824 ok(hr == S_OK, "got 0x%08lx\n", hr);
825 ok(!flags, "got 0x%08lx\n", flags);
827 hr = IBackgroundCopyJobHttpOptions_SetSecurityFlags(options, orig_flags);
828 ok(hr == S_OK, "got 0x%08lx\n", hr);
830 IBackgroundCopyJobHttpOptions_Release(options);
833 hr = IBackgroundCopyJob_Complete(test_job);
834 ok(hr == S_OK, "got 0x%08lx\n", hr);
836 hr = IBackgroundCopyJob_GetState(test_job, &state);
837 ok(hr == S_OK, "got 0x%08lx\n", hr);
838 ok(state == BG_JOB_STATE_ACKNOWLEDGED, "unexpected state: %u\n", state);
840 hr = IBackgroundCopyJob_Complete(test_job);
841 ok(hr == BG_E_INVALID_STATE, "got 0x%08lx\n", hr);
843 DeleteFileW(test_localPathA);
845 hr = IBackgroundCopyJob_SetNotifyInterface(test_job, NULL);
846 ok(hr == BG_E_INVALID_STATE, "got 0x%08lx\n", hr);
848 IUnknown_Release(copyCallbackUnknown);
849 IBackgroundCopyCallback2_Release(copyCallback);
852 typedef void (*test_t)(void);
854 START_TEST(job)
856 static const test_t tests[] = {
857 test_GetId,
858 test_GetType,
859 test_GetName,
860 test_GetProgress_preTransfer,
861 test_GetState,
862 test_ResumeEmpty,
863 test_NotifyFlags,
864 test_NotifyInterface,
867 static const test_t tests_bits20[] = {
868 test_AddFile,
869 test_AddFileSet,
870 test_EnumFiles,
871 test_CompleteLocal,
872 test_CompleteLocalURL,
873 test_Cancel, /* must be last */
876 static const test_t tests_bits25[] = {
877 test_HttpOptions,
880 const test_t *test;
881 int i;
882 HRESULT hres;
884 init_paths();
886 /* CoInitializeEx and CoInitializeSecurity with RPC_C_IMP_LEVEL_IMPERSONATE
887 * are required to set the job transfer policy
889 hres = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
890 if (FAILED(hres)) {
891 ok(0, "CoInitializeEx failed: %0lx\n", hres);
892 return;
895 hres = CoInitializeSecurity(NULL, -1, NULL, NULL,
896 RPC_C_AUTHN_LEVEL_CONNECT,
897 RPC_C_IMP_LEVEL_IMPERSONATE,
898 NULL, EOAC_NONE, 0);
899 if (FAILED(hres)) {
900 ok(0, "CoInitializeSecurity failed: %0lx\n", hres);
901 return;
904 if (FAILED(test_create_manager()))
906 CoUninitialize();
907 win_skip("Failed to create Manager instance, skipping tests\n");
908 return;
911 for (test = tests, i = 0; *test; ++test, ++i)
913 /* Keep state separate between tests. */
914 if (!setup())
916 ok(0, "tests:%d: Unable to setup test\n", i);
917 break;
919 (*test)();
920 teardown();
923 if (check_bits20())
925 for (test = tests_bits20, i = 0; *test; ++test, ++i)
927 /* Keep state separate between tests. */
928 if (!setup())
930 ok(0, "tests_bits20:%d: Unable to setup test\n", i);
931 break;
933 (*test)();
934 teardown();
937 else
939 win_skip("Tests need BITS 2.0 or higher\n");
942 if (check_bits25())
944 for (test = tests_bits25, i = 0; *test; ++test, ++i)
946 /* Keep state separate between tests. */
947 if (!setup())
949 ok(0, "tests_bits25:%d: Unable to setup test\n", i);
950 break;
952 (*test)();
953 teardown();
956 else
958 win_skip("Tests need BITS 2.5 or higher\n");
961 CoUninitialize();