xref: /reactos/modules/rostests/winetests/qmgr/job.c (revision e26c8bc6)
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 COBJMACROS
24 
25 #include "wine/test.h"
26 #include "bits.h"
27 #include "initguid.h"
28 #include "bits2_0.h"
29 #include "bits2_5.h"
30 
31 /* Globals used by many tests */
32 static const WCHAR test_displayName[] = {'T', 'e', 's', 't', 0};
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;
41 
test_create_manager(void)42 static HRESULT test_create_manager(void)
43 {
44     HRESULT hres;
45     IBackgroundCopyManager *manager = NULL;
46 
47     /* Creating BITS instance */
48     hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL, CLSCTX_LOCAL_SERVER,
49                             &IID_IBackgroundCopyManager, (void **) &manager);
50 
51     if(hres == HRESULT_FROM_WIN32(ERROR_SERVICE_DISABLED)) {
52         win_skip("Needed Service is disabled\n");
53         return hres;
54     }
55 
56     if (hres == S_OK)
57         IBackgroundCopyManager_Release(manager);
58 
59     return hres;
60 }
61 
init_paths(void)62 static void init_paths(void)
63 {
64     WCHAR tmpDir[MAX_PATH];
65     WCHAR prefix[] = {'q', 'm', 'g', 'r', 0};
66 
67     GetTempPathW(MAX_PATH, tmpDir);
68 
69     GetTempFileNameW(tmpDir, prefix, 0, test_localPathA);
70     GetTempFileNameW(tmpDir, prefix, 0, test_localPathB);
71     GetTempFileNameW(tmpDir, prefix, 0, test_remotePathA);
72     GetTempFileNameW(tmpDir, prefix, 0, test_remotePathB);
73 }
74 
75 /* Generic test setup */
setup(void)76 static BOOL setup(void)
77 {
78     HRESULT hres;
79 
80     test_manager = NULL;
81     test_job = NULL;
82     memset(&test_jobId, 0, sizeof test_jobId);
83     test_type = BG_JOB_TYPE_DOWNLOAD;
84 
85     hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL,
86                             CLSCTX_LOCAL_SERVER,
87                             &IID_IBackgroundCopyManager,
88                             (void **) &test_manager);
89     if(hres != S_OK)
90         return FALSE;
91 
92     hres = IBackgroundCopyManager_CreateJob(test_manager, test_displayName,
93                                             test_type, &test_jobId, &test_job);
94     if(hres != S_OK)
95     {
96         IBackgroundCopyManager_Release(test_manager);
97         return FALSE;
98     }
99 
100     return TRUE;
101 }
102 
103 /* Generic test cleanup */
teardown(void)104 static void teardown(void)
105 {
106     IBackgroundCopyJob_Cancel(test_job);
107     IBackgroundCopyJob_Release(test_job);
108     IBackgroundCopyManager_Release(test_manager);
109 }
110 
check_bits20(void)111 static BOOL check_bits20(void)
112 {
113     HRESULT hres;
114     IBackgroundCopyManager *manager;
115     IBackgroundCopyJob *job, *job3;
116 
117     hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL,
118                             CLSCTX_LOCAL_SERVER, &IID_IBackgroundCopyManager,
119                             (void **)&manager);
120     if (hres != S_OK) return FALSE;
121 
122     hres = IBackgroundCopyManager_CreateJob(manager, test_displayName, test_type, &test_jobId, &job);
123     if (hres != S_OK)
124     {
125         IBackgroundCopyManager_Release(manager);
126         return FALSE;
127     }
128 
129     hres = IBackgroundCopyJob_QueryInterface(job, &IID_IBackgroundCopyJob3, (void **)&job3);
130     IBackgroundCopyJob_Cancel(job);
131     IBackgroundCopyJob_Release(job);
132     if (hres != S_OK)
133     {
134         IBackgroundCopyManager_Release(manager);
135         return FALSE;
136     }
137 
138     IBackgroundCopyJob_Release(job3);
139     IBackgroundCopyManager_Release(manager);
140     return TRUE;
141 }
142 
check_bits25(void)143 static BOOL check_bits25(void)
144 {
145     HRESULT hres;
146     IBackgroundCopyManager *manager;
147     IBackgroundCopyJob *job;
148     IBackgroundCopyJobHttpOptions *options;
149 
150     hres = CoCreateInstance(&CLSID_BackgroundCopyManager, NULL,
151                             CLSCTX_LOCAL_SERVER, &IID_IBackgroundCopyManager,
152                             (void **)&manager);
153     if (hres != S_OK) return FALSE;
154 
155     hres = IBackgroundCopyManager_CreateJob(manager, test_displayName, test_type, &test_jobId, &job);
156     if (hres != S_OK)
157     {
158         IBackgroundCopyManager_Release(manager);
159         return FALSE;
160     }
161 
162     hres = IBackgroundCopyJob_QueryInterface(job, &IID_IBackgroundCopyJobHttpOptions, (void **)&options);
163     IBackgroundCopyJob_Cancel(job);
164     IBackgroundCopyJob_Release(job);
165     if (hres != S_OK)
166     {
167         IBackgroundCopyManager_Release(manager);
168         return FALSE;
169     }
170 
171     IBackgroundCopyJobHttpOptions_Release(options);
172     IBackgroundCopyManager_Release(manager);
173     return TRUE;
174 }
175 
176 /* Test that the jobId is properly set */
test_GetId(void)177 static void test_GetId(void)
178 {
179     HRESULT hres;
180     GUID tmpId;
181 
182     hres = IBackgroundCopyJob_GetId(test_job, &tmpId);
183     ok(hres == S_OK, "GetId failed: %08x\n", hres);
184     ok(memcmp(&tmpId, &test_jobId, sizeof tmpId) == 0, "Got incorrect GUID\n");
185 }
186 
187 /* Test that the type is properly set */
test_GetType(void)188 static void test_GetType(void)
189 {
190     HRESULT hres;
191     BG_JOB_TYPE type;
192 
193     hres = IBackgroundCopyJob_GetType(test_job, &type);
194     ok(hres == S_OK, "GetType failed: %08x\n", hres);
195     ok(type == test_type, "Got incorrect type\n");
196 }
197 
198 /* Test that the display name is properly set */
test_GetName(void)199 static void test_GetName(void)
200 {
201     HRESULT hres;
202     LPWSTR displayName;
203 
204     hres = IBackgroundCopyJob_GetDisplayName(test_job, &displayName);
205     ok(hres == S_OK, "GetName failed: %08x\n", hres);
206     ok(lstrcmpW(displayName, test_displayName) == 0, "Got incorrect type\n");
207     CoTaskMemFree(displayName);
208 }
209 
210 /* Test adding a file */
test_AddFile(void)211 static void test_AddFile(void)
212 {
213     HRESULT hres;
214 
215     hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
216                                       test_localPathA);
217     ok(hres == S_OK, "First call to AddFile failed: 0x%08x\n", hres);
218 
219     hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathB,
220                                       test_localPathB);
221     ok(hres == S_OK, "Second call to AddFile failed: 0x%08x\n", hres);
222 }
223 
224 /* Test adding a set of files */
test_AddFileSet(void)225 static void test_AddFileSet(void)
226 {
227     HRESULT hres;
228     BG_FILE_INFO files[2] =
229         {
230             {test_remotePathA, test_localPathA},
231             {test_remotePathB, test_localPathB}
232         };
233     hres = IBackgroundCopyJob_AddFileSet(test_job, 2, files);
234     ok(hres == S_OK, "AddFileSet failed: 0x%08x\n", hres);
235 }
236 
237 /* Test creation of a job enumerator */
test_EnumFiles(void)238 static void test_EnumFiles(void)
239 {
240     HRESULT hres;
241     IEnumBackgroundCopyFiles *enumFiles;
242     ULONG res;
243 
244     hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
245                                       test_localPathA);
246     ok(hres == S_OK, "got 0x%08x\n", hres);
247 
248     hres = IBackgroundCopyJob_EnumFiles(test_job, &enumFiles);
249     ok(hres == S_OK, "EnumFiles failed: 0x%08x\n", hres);
250 
251     res = IEnumBackgroundCopyFiles_Release(enumFiles);
252     ok(res == 0, "Bad ref count on release: %u\n", res);
253 }
254 
255 /* Test getting job progress */
test_GetProgress_preTransfer(void)256 static void test_GetProgress_preTransfer(void)
257 {
258     HRESULT hres;
259     BG_JOB_PROGRESS progress;
260 
261     hres = IBackgroundCopyJob_GetProgress(test_job, &progress);
262     ok(hres == S_OK, "GetProgress failed: 0x%08x\n", hres);
263 
264     ok(progress.BytesTotal == 0, "Incorrect BytesTotal: %s\n",
265        wine_dbgstr_longlong(progress.BytesTotal));
266     ok(progress.BytesTransferred == 0, "Incorrect BytesTransferred: %s\n",
267        wine_dbgstr_longlong(progress.BytesTransferred));
268     ok(progress.FilesTotal == 0, "Incorrect FilesTotal: %u\n", progress.FilesTotal);
269     ok(progress.FilesTransferred == 0, "Incorrect FilesTransferred %u\n", progress.FilesTransferred);
270 }
271 
272 /* Test getting job state */
test_GetState(void)273 static void test_GetState(void)
274 {
275     HRESULT hres;
276     BG_JOB_STATE state;
277 
278     state = BG_JOB_STATE_ERROR;
279     hres = IBackgroundCopyJob_GetState(test_job, &state);
280     ok(hres == S_OK, "GetState failed: 0x%08x\n", hres);
281     ok(state == BG_JOB_STATE_SUSPENDED, "Incorrect job state: %d\n", state);
282 }
283 
284 /* Test resuming a job */
test_ResumeEmpty(void)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 
293     state = BG_JOB_STATE_ERROR;
294     hres = IBackgroundCopyJob_GetState(test_job, &state);
295     ok(hres == S_OK, "got 0x%08x\n", hres);
296     ok(state == BG_JOB_STATE_SUSPENDED, "Incorrect job state: %d\n", state);
297 }
298 
makeFile(WCHAR * name,const char * contents)299 static void makeFile(WCHAR *name, const char *contents)
300 {
301     HANDLE file;
302     DWORD w, len = strlen(contents);
303 
304     DeleteFileW(name);
305     file = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
306                        FILE_ATTRIBUTE_NORMAL, NULL);
307     ok(file != INVALID_HANDLE_VALUE, "CreateFile\n");
308     ok(WriteFile(file, contents, len, &w, NULL), "WriteFile\n");
309     CloseHandle(file);
310 }
311 
compareFiles(WCHAR * n1,WCHAR * n2)312 static void compareFiles(WCHAR *n1, WCHAR *n2)
313 {
314     char b1[256];
315     char b2[256];
316     DWORD s1, s2;
317     HANDLE f1, f2;
318 
319     f1 = CreateFileW(n1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
320                      FILE_ATTRIBUTE_NORMAL, NULL);
321     ok(f1 != INVALID_HANDLE_VALUE, "CreateFile\n");
322 
323     f2 = CreateFileW(n2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
324                      FILE_ATTRIBUTE_NORMAL, NULL);
325     ok(f2 != INVALID_HANDLE_VALUE, "CreateFile\n");
326 
327     /* Neither of these files is very big */
328     ok(ReadFile(f1, b1, sizeof b1, &s1, NULL), "ReadFile\n");
329     ok(ReadFile(f2, b2, sizeof b2, &s2, NULL), "ReadFile\n");
330 
331     CloseHandle(f1);
332     CloseHandle(f2);
333 
334     ok(s1 == s2, "Files differ in length\n");
335     ok(memcmp(b1, b2, s1) == 0, "Files differ in contents\n");
336 }
337 
338 /* Test a complete transfer for local files */
test_CompleteLocal(void)339 static void test_CompleteLocal(void)
340 {
341     static const int timeout_sec = 30;
342     HRESULT hres;
343     BG_JOB_STATE state;
344     int i;
345 
346     DeleteFileW(test_localPathA);
347     DeleteFileW(test_localPathB);
348     makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
349     makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
350 
351     hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
352                                       test_localPathA);
353     ok(hres == S_OK, "got 0x%08x\n", hres);
354 
355     hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathB,
356                                       test_localPathB);
357     ok(hres == S_OK, "got 0x%08x\n", hres);
358 
359     hres = IBackgroundCopyJob_Resume(test_job);
360     ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
361 
362     disable_success_count
363     for (i = 0; i < timeout_sec; ++i)
364     {
365         hres = IBackgroundCopyJob_GetState(test_job, &state);
366         ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
367         ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
368            || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED,
369            "Bad state: %d\n", state);
370         if (state == BG_JOB_STATE_TRANSFERRED)
371             break;
372         Sleep(1000);
373     }
374 
375     ok(i < timeout_sec, "BITS jobs timed out\n");
376     hres = IBackgroundCopyJob_Complete(test_job);
377     ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
378     hres = IBackgroundCopyJob_GetState(test_job, &state);
379     ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
380     ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
381 
382     compareFiles(test_remotePathA, test_localPathA);
383     compareFiles(test_remotePathB, test_localPathB);
384 
385     ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
386     ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
387     DeleteFileW(test_localPathA);
388     DeleteFileW(test_localPathB);
389 }
390 
391 /* Test a complete transfer for local files */
test_CompleteLocalURL(void)392 static void test_CompleteLocalURL(void)
393 {
394     static const WCHAR prot[] = {'f','i','l','e',':','/','/', 0};
395     static const int timeout_sec = 30;
396     WCHAR *urlA, *urlB;
397     HRESULT hres;
398     BG_JOB_STATE state;
399     int i;
400 
401     DeleteFileW(test_localPathA);
402     DeleteFileW(test_localPathB);
403     makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
404     makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
405 
406     urlA = HeapAlloc(GetProcessHeap(), 0,
407                      (7 + lstrlenW(test_remotePathA) + 1) * sizeof urlA[0]);
408     urlB = HeapAlloc(GetProcessHeap(), 0,
409                      (7 + lstrlenW(test_remotePathB) + 1) * sizeof urlB[0]);
410     if (!urlA || !urlB)
411     {
412         skip("Unable to allocate memory for URLs\n");
413         HeapFree(GetProcessHeap(), 0, urlA);
414         HeapFree(GetProcessHeap(), 0, urlB);
415         return;
416     }
417 
418     lstrcpyW(urlA, prot);
419     lstrcatW(urlA, test_remotePathA);
420     lstrcpyW(urlB, prot);
421     lstrcatW(urlB, test_remotePathB);
422 
423     hres = IBackgroundCopyJob_AddFile(test_job, urlA, test_localPathA);
424     ok(hres == S_OK, "got 0x%08x\n", hres);
425 
426     hres = IBackgroundCopyJob_AddFile(test_job, urlB, test_localPathB);
427     ok(hres == S_OK, "got 0x%08x\n", hres);
428 
429     hres = IBackgroundCopyJob_Resume(test_job);
430     ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
431 
432     disable_success_count
433     for (i = 0; i < timeout_sec; ++i)
434     {
435         hres = IBackgroundCopyJob_GetState(test_job, &state);
436         ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
437         ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
438            || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED,
439            "Bad state: %d\n", state);
440         if (state == BG_JOB_STATE_TRANSFERRED)
441             break;
442         Sleep(1000);
443     }
444 
445     ok(i < timeout_sec, "BITS jobs timed out\n");
446     hres = IBackgroundCopyJob_Complete(test_job);
447     ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
448     hres = IBackgroundCopyJob_GetState(test_job, &state);
449     ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
450     ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
451 
452     compareFiles(test_remotePathA, test_localPathA);
453     compareFiles(test_remotePathB, test_localPathB);
454 
455     ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
456     ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
457     DeleteFileW(test_localPathA);
458     DeleteFileW(test_localPathB);
459 
460     HeapFree(GetProcessHeap(), 0, urlA);
461     HeapFree(GetProcessHeap(), 0, urlB);
462 }
463 
test_NotifyFlags(void)464 static void test_NotifyFlags(void)
465 {
466     ULONG flags;
467     HRESULT hr;
468 
469     /* check default flags */
470     flags = 0;
471     hr = IBackgroundCopyJob_GetNotifyFlags(test_job, &flags);
472     ok(hr == S_OK, "got 0x%08x\n", hr);
473     ok(flags == (BG_NOTIFY_JOB_ERROR | BG_NOTIFY_JOB_TRANSFERRED), "flags 0x%08x\n", flags);
474 }
475 
test_NotifyInterface(void)476 static void test_NotifyInterface(void)
477 {
478     HRESULT hr;
479     IUnknown *unk;
480 
481     unk = (IUnknown*)0xdeadbeef;
482     hr = IBackgroundCopyJob_GetNotifyInterface(test_job, &unk);
483     ok(hr == S_OK, "got 0x%08x\n", hr);
484     ok(unk == NULL, "got %p\n", unk);
485 }
486 
test_Cancel(void)487 static void test_Cancel(void)
488 {
489     HRESULT hr;
490     BG_JOB_STATE state;
491 
492     state = BG_JOB_STATE_ERROR;
493     hr = IBackgroundCopyJob_GetState(test_job, &state);
494     ok(hr == S_OK, "got 0x%08x\n", hr);
495     ok(state != BG_JOB_STATE_CANCELLED, "got %u\n", state);
496 
497     hr = IBackgroundCopyJob_Cancel(test_job);
498     ok(hr == S_OK, "got 0x%08x\n", hr);
499 
500     state = BG_JOB_STATE_ERROR;
501     hr = IBackgroundCopyJob_GetState(test_job, &state);
502     ok(hr == S_OK, "got 0x%08x\n", hr);
503     ok(state == BG_JOB_STATE_CANCELLED, "got %u\n", state);
504 
505     hr = IBackgroundCopyJob_Cancel(test_job);
506     ok(hr == BG_E_INVALID_STATE, "got 0x%08x\n", hr);
507 }
508 
test_HttpOptions(void)509 static void test_HttpOptions(void)
510 {
511     static const WCHAR urlW[] =
512         {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',0};
513     static const WCHAR winetestW[] =
514         {'W','i','n','e',':',' ','t','e','s','t','\r','\n',0};
515     static const unsigned int timeout = 30;
516     HRESULT hr;
517     IBackgroundCopyJobHttpOptions *options;
518     IBackgroundCopyError *error;
519     BG_JOB_STATE state;
520     unsigned int i;
521     WCHAR *headers;
522     ULONG flags, orig_flags;
523 
524     DeleteFileW(test_localPathA);
525     hr = IBackgroundCopyJob_AddFile(test_job, urlW, test_localPathA);
526     ok(hr == S_OK, "got 0x%08x\n", hr);
527 
528     hr = IBackgroundCopyJob_QueryInterface(test_job, &IID_IBackgroundCopyJobHttpOptions, (void **)&options);
529     ok(hr == S_OK, "got 0x%08x\n", hr);
530 
531     if (options)
532     {
533         headers = (WCHAR *)0xdeadbeef;
534         hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
535         ok(hr == S_FALSE, "got 0x%08x\n", hr);
536         ok(headers == NULL, "got %p\n", headers);
537 
538         hr = IBackgroundCopyJobHttpOptions_SetCustomHeaders(options, winetestW);
539         ok(hr == S_OK, "got 0x%08x\n", hr);
540 
541         headers = (WCHAR *)0xdeadbeef;
542         hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
543         ok(hr == S_OK, "got 0x%08x\n", hr);
544         if (hr == S_OK)
545         {
546             ok(!lstrcmpW(headers, winetestW), "got %s\n", wine_dbgstr_w(headers));
547             CoTaskMemFree(headers);
548         }
549 
550         hr = IBackgroundCopyJobHttpOptions_SetCustomHeaders(options, NULL);
551         ok(hr == S_OK, "got 0x%08x\n", hr);
552 
553         headers = (WCHAR *)0xdeadbeef;
554         hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
555         ok(hr == S_FALSE, "got 0x%08x\n", hr);
556         ok(headers == NULL, "got %p\n", headers);
557 
558         orig_flags = 0xdeadbeef;
559         hr = IBackgroundCopyJobHttpOptions_GetSecurityFlags(options, &orig_flags);
560         ok(hr == S_OK, "got 0x%08x\n", hr);
561         ok(!orig_flags, "got 0x%08x\n", orig_flags);
562 
563         hr = IBackgroundCopyJobHttpOptions_SetSecurityFlags(options, 0);
564         ok(hr == S_OK, "got 0x%08x\n", hr);
565 
566         flags = 0xdeadbeef;
567         hr = IBackgroundCopyJobHttpOptions_GetSecurityFlags(options, &flags);
568         ok(hr == S_OK, "got 0x%08x\n", hr);
569         ok(!flags, "got 0x%08x\n", flags);
570     }
571 
572     hr = IBackgroundCopyJob_Resume(test_job);
573     ok(hr == S_OK, "got 0x%08x\n", hr);
574 
575     disable_success_count
576     for (i = 0; i < timeout; i++)
577     {
578         hr = IBackgroundCopyJob_GetState(test_job, &state);
579         ok(hr == S_OK, "got 0x%08x\n", hr);
580 
581         ok(state == BG_JOB_STATE_QUEUED ||
582            state == BG_JOB_STATE_CONNECTING ||
583            state == BG_JOB_STATE_TRANSFERRING ||
584            state == BG_JOB_STATE_TRANSFERRED, "unexpected state: %u\n", state);
585 
586         if (state == BG_JOB_STATE_TRANSFERRED) break;
587         Sleep(1000);
588     }
589     ok(i < timeout, "BITS job timed out\n");
590     if (i < timeout)
591     {
592         hr = IBackgroundCopyJob_GetError(test_job, &error);
593         ok(hr == BG_E_ERROR_INFORMATION_UNAVAILABLE, "got 0x%08x\n", hr);
594     }
595 
596     if (options)
597     {
598         headers = (WCHAR *)0xdeadbeef;
599         hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
600         ok(hr == S_FALSE, "got 0x%08x\n", hr);
601         ok(headers == NULL, "got %p\n", headers);
602 
603         hr = IBackgroundCopyJobHttpOptions_SetCustomHeaders(options, NULL);
604         ok(hr == S_OK, "got 0x%08x\n", hr);
605 
606         hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
607         ok(hr == S_FALSE, "got 0x%08x\n", hr);
608 
609         flags = 0xdeadbeef;
610         hr = IBackgroundCopyJobHttpOptions_GetSecurityFlags(options, &flags);
611         ok(hr == S_OK, "got 0x%08x\n", hr);
612         ok(!flags, "got 0x%08x\n", flags);
613 
614         hr = IBackgroundCopyJobHttpOptions_SetSecurityFlags(options, orig_flags);
615         ok(hr == S_OK, "got 0x%08x\n", hr);
616 
617         IBackgroundCopyJobHttpOptions_Release(options);
618     }
619 
620     hr = IBackgroundCopyJob_Complete(test_job);
621     ok(hr == S_OK, "got 0x%08x\n", hr);
622 
623     hr = IBackgroundCopyJob_GetState(test_job, &state);
624     ok(hr == S_OK, "got 0x%08x\n", hr);
625     ok(state == BG_JOB_STATE_ACKNOWLEDGED, "unexpected state: %u\n", state);
626 
627     hr = IBackgroundCopyJob_Complete(test_job);
628     ok(hr == BG_E_INVALID_STATE, "got 0x%08x\n", hr);
629 
630     DeleteFileW(test_localPathA);
631 }
632 
633 typedef void (*test_t)(void);
634 
START_TEST(job)635 START_TEST(job)
636 {
637     static const test_t tests[] = {
638         test_GetId,
639         test_GetType,
640         test_GetName,
641         test_GetProgress_preTransfer,
642         test_GetState,
643         test_ResumeEmpty,
644         test_NotifyFlags,
645         test_NotifyInterface,
646         0
647     };
648     static const test_t tests_bits20[] = {
649         test_AddFile,
650         test_AddFileSet,
651         test_EnumFiles,
652         test_CompleteLocal,
653         test_CompleteLocalURL,
654         test_Cancel, /* must be last */
655         0
656     };
657     static const test_t tests_bits25[] = {
658         test_HttpOptions,
659         0
660     };
661     const test_t *test;
662     int i;
663 
664     init_paths();
665 
666     CoInitialize(NULL);
667 
668     if (FAILED(test_create_manager()))
669     {
670         CoUninitialize();
671         win_skip("Failed to create Manager instance, skipping tests\n");
672         return;
673     }
674 
675     for (test = tests, i = 0; *test; ++test, ++i)
676     {
677         /* Keep state separate between tests. */
678         if (!setup())
679         {
680             ok(0, "tests:%d: Unable to setup test\n", i);
681             break;
682         }
683         (*test)();
684         teardown();
685     }
686 
687     if (check_bits20())
688     {
689         for (test = tests_bits20, i = 0; *test; ++test, ++i)
690         {
691             /* Keep state separate between tests. */
692             if (!setup())
693             {
694                 ok(0, "tests_bits20:%d: Unable to setup test\n", i);
695                 break;
696             }
697             (*test)();
698             teardown();
699         }
700     }
701     else
702     {
703         win_skip("Tests need BITS 2.0 or higher\n");
704     }
705 
706     if (check_bits25())
707     {
708         for (test = tests_bits25, i = 0; *test; ++test, ++i)
709         {
710             /* Keep state separate between tests. */
711             if (!setup())
712             {
713                 ok(0, "tests_bits25:%d: Unable to setup test\n", i);
714                 break;
715             }
716             (*test)();
717             teardown();
718         }
719     }
720     else
721     {
722         win_skip("Tests need BITS 2.5 or higher\n");
723     }
724 
725     CoUninitialize();
726 }
727