xref: /reactos/modules/rostests/winetests/qmgr/job.c (revision 407c54ba)
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 
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 
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 */
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 */
104 static void teardown(void)
105 {
106     IBackgroundCopyJob_Cancel(test_job);
107     IBackgroundCopyJob_Release(test_job);
108     IBackgroundCopyManager_Release(test_manager);
109 }
110 
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 
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 
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 
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 */
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     for (i = 0; i < timeout_sec; ++i)
363     {
364         hres = IBackgroundCopyJob_GetState(test_job, &state);
365         ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
366         ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
367            || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED,
368            "Bad state: %d\n", state);
369         if (state == BG_JOB_STATE_TRANSFERRED)
370             break;
371         Sleep(1000);
372     }
373 
374     ok(i < timeout_sec, "BITS jobs timed out\n");
375     hres = IBackgroundCopyJob_Complete(test_job);
376     ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
377     hres = IBackgroundCopyJob_GetState(test_job, &state);
378     ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
379     ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
380 
381     compareFiles(test_remotePathA, test_localPathA);
382     compareFiles(test_remotePathB, test_localPathB);
383 
384     ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
385     ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
386     DeleteFileW(test_localPathA);
387     DeleteFileW(test_localPathB);
388 }
389 
390 /* Test a complete transfer for local files */
391 static void test_CompleteLocalURL(void)
392 {
393     static const WCHAR prot[] = {'f','i','l','e',':','/','/', 0};
394     static const int timeout_sec = 30;
395     WCHAR *urlA, *urlB;
396     HRESULT hres;
397     BG_JOB_STATE state;
398     int i;
399 
400     DeleteFileW(test_localPathA);
401     DeleteFileW(test_localPathB);
402     makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
403     makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
404 
405     urlA = HeapAlloc(GetProcessHeap(), 0,
406                      (7 + lstrlenW(test_remotePathA) + 1) * sizeof urlA[0]);
407     urlB = HeapAlloc(GetProcessHeap(), 0,
408                      (7 + lstrlenW(test_remotePathB) + 1) * sizeof urlB[0]);
409     if (!urlA || !urlB)
410     {
411         skip("Unable to allocate memory for URLs\n");
412         HeapFree(GetProcessHeap(), 0, urlA);
413         HeapFree(GetProcessHeap(), 0, urlB);
414         return;
415     }
416 
417     lstrcpyW(urlA, prot);
418     lstrcatW(urlA, test_remotePathA);
419     lstrcpyW(urlB, prot);
420     lstrcatW(urlB, test_remotePathB);
421 
422     hres = IBackgroundCopyJob_AddFile(test_job, urlA, test_localPathA);
423     ok(hres == S_OK, "got 0x%08x\n", hres);
424 
425     hres = IBackgroundCopyJob_AddFile(test_job, urlB, test_localPathB);
426     ok(hres == S_OK, "got 0x%08x\n", hres);
427 
428     hres = IBackgroundCopyJob_Resume(test_job);
429     ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
430 
431     for (i = 0; i < timeout_sec; ++i)
432     {
433         hres = IBackgroundCopyJob_GetState(test_job, &state);
434         ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
435         ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
436            || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED,
437            "Bad state: %d\n", state);
438         if (state == BG_JOB_STATE_TRANSFERRED)
439             break;
440         Sleep(1000);
441     }
442 
443     ok(i < timeout_sec, "BITS jobs timed out\n");
444     hres = IBackgroundCopyJob_Complete(test_job);
445     ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
446     hres = IBackgroundCopyJob_GetState(test_job, &state);
447     ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
448     ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
449 
450     compareFiles(test_remotePathA, test_localPathA);
451     compareFiles(test_remotePathB, test_localPathB);
452 
453     ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
454     ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
455     DeleteFileW(test_localPathA);
456     DeleteFileW(test_localPathB);
457 
458     HeapFree(GetProcessHeap(), 0, urlA);
459     HeapFree(GetProcessHeap(), 0, urlB);
460 }
461 
462 static void test_NotifyFlags(void)
463 {
464     ULONG flags;
465     HRESULT hr;
466 
467     /* check default flags */
468     flags = 0;
469     hr = IBackgroundCopyJob_GetNotifyFlags(test_job, &flags);
470     ok(hr == S_OK, "got 0x%08x\n", hr);
471     ok(flags == (BG_NOTIFY_JOB_ERROR | BG_NOTIFY_JOB_TRANSFERRED), "flags 0x%08x\n", flags);
472 }
473 
474 static void test_NotifyInterface(void)
475 {
476     HRESULT hr;
477     IUnknown *unk;
478 
479     unk = (IUnknown*)0xdeadbeef;
480     hr = IBackgroundCopyJob_GetNotifyInterface(test_job, &unk);
481     ok(hr == S_OK, "got 0x%08x\n", hr);
482     ok(unk == NULL, "got %p\n", unk);
483 }
484 
485 static void test_Cancel(void)
486 {
487     HRESULT hr;
488     BG_JOB_STATE state;
489 
490     state = BG_JOB_STATE_ERROR;
491     hr = IBackgroundCopyJob_GetState(test_job, &state);
492     ok(hr == S_OK, "got 0x%08x\n", hr);
493     ok(state != BG_JOB_STATE_CANCELLED, "got %u\n", state);
494 
495     hr = IBackgroundCopyJob_Cancel(test_job);
496     ok(hr == S_OK, "got 0x%08x\n", hr);
497 
498     state = BG_JOB_STATE_ERROR;
499     hr = IBackgroundCopyJob_GetState(test_job, &state);
500     ok(hr == S_OK, "got 0x%08x\n", hr);
501     ok(state == BG_JOB_STATE_CANCELLED, "got %u\n", state);
502 
503     hr = IBackgroundCopyJob_Cancel(test_job);
504     ok(hr == BG_E_INVALID_STATE, "got 0x%08x\n", hr);
505 }
506 
507 static void test_HttpOptions(void)
508 {
509     static const WCHAR urlW[] =
510         {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',0};
511     static const WCHAR winetestW[] =
512         {'W','i','n','e',':',' ','t','e','s','t','\r','\n',0};
513     static const unsigned int timeout = 30;
514     HRESULT hr;
515     IBackgroundCopyJobHttpOptions *options;
516     IBackgroundCopyError *error;
517     BG_JOB_STATE state;
518     unsigned int i;
519     WCHAR *headers;
520     ULONG flags, orig_flags;
521 
522     DeleteFileW(test_localPathA);
523     hr = IBackgroundCopyJob_AddFile(test_job, urlW, test_localPathA);
524     ok(hr == S_OK, "got 0x%08x\n", hr);
525 
526     hr = IBackgroundCopyJob_QueryInterface(test_job, &IID_IBackgroundCopyJobHttpOptions, (void **)&options);
527     ok(hr == S_OK, "got 0x%08x\n", hr);
528 
529     if (options)
530     {
531         headers = (WCHAR *)0xdeadbeef;
532         hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
533         ok(hr == S_FALSE, "got 0x%08x\n", hr);
534         ok(headers == NULL, "got %p\n", headers);
535 
536         hr = IBackgroundCopyJobHttpOptions_SetCustomHeaders(options, winetestW);
537         ok(hr == S_OK, "got 0x%08x\n", hr);
538 
539         headers = (WCHAR *)0xdeadbeef;
540         hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
541         ok(hr == S_OK, "got 0x%08x\n", hr);
542         if (hr == S_OK)
543         {
544             ok(!lstrcmpW(headers, winetestW), "got %s\n", wine_dbgstr_w(headers));
545             CoTaskMemFree(headers);
546         }
547 
548         hr = IBackgroundCopyJobHttpOptions_SetCustomHeaders(options, NULL);
549         ok(hr == S_OK, "got 0x%08x\n", hr);
550 
551         headers = (WCHAR *)0xdeadbeef;
552         hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
553         ok(hr == S_FALSE, "got 0x%08x\n", hr);
554         ok(headers == NULL, "got %p\n", headers);
555 
556         orig_flags = 0xdeadbeef;
557         hr = IBackgroundCopyJobHttpOptions_GetSecurityFlags(options, &orig_flags);
558         ok(hr == S_OK, "got 0x%08x\n", hr);
559         ok(!orig_flags, "got 0x%08x\n", orig_flags);
560 
561         hr = IBackgroundCopyJobHttpOptions_SetSecurityFlags(options, 0);
562         ok(hr == S_OK, "got 0x%08x\n", hr);
563 
564         flags = 0xdeadbeef;
565         hr = IBackgroundCopyJobHttpOptions_GetSecurityFlags(options, &flags);
566         ok(hr == S_OK, "got 0x%08x\n", hr);
567         ok(!flags, "got 0x%08x\n", flags);
568     }
569 
570     hr = IBackgroundCopyJob_Resume(test_job);
571     ok(hr == S_OK, "got 0x%08x\n", hr);
572 
573     for (i = 0; i < timeout; i++)
574     {
575         hr = IBackgroundCopyJob_GetState(test_job, &state);
576         ok(hr == S_OK, "got 0x%08x\n", hr);
577 
578         ok(state == BG_JOB_STATE_QUEUED ||
579            state == BG_JOB_STATE_CONNECTING ||
580            state == BG_JOB_STATE_TRANSFERRING ||
581            state == BG_JOB_STATE_TRANSFERRED, "unexpected state: %u\n", state);
582 
583         if (state == BG_JOB_STATE_TRANSFERRED) break;
584         Sleep(1000);
585     }
586     ok(i < timeout, "BITS job timed out\n");
587     if (i < timeout)
588     {
589         hr = IBackgroundCopyJob_GetError(test_job, &error);
590         ok(hr == BG_E_ERROR_INFORMATION_UNAVAILABLE, "got 0x%08x\n", hr);
591     }
592 
593     if (options)
594     {
595         headers = (WCHAR *)0xdeadbeef;
596         hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
597         ok(hr == S_FALSE, "got 0x%08x\n", hr);
598         ok(headers == NULL, "got %p\n", headers);
599 
600         hr = IBackgroundCopyJobHttpOptions_SetCustomHeaders(options, NULL);
601         ok(hr == S_OK, "got 0x%08x\n", hr);
602 
603         hr = IBackgroundCopyJobHttpOptions_GetCustomHeaders(options, &headers);
604         ok(hr == S_FALSE, "got 0x%08x\n", hr);
605 
606         flags = 0xdeadbeef;
607         hr = IBackgroundCopyJobHttpOptions_GetSecurityFlags(options, &flags);
608         ok(hr == S_OK, "got 0x%08x\n", hr);
609         ok(!flags, "got 0x%08x\n", flags);
610 
611         hr = IBackgroundCopyJobHttpOptions_SetSecurityFlags(options, orig_flags);
612         ok(hr == S_OK, "got 0x%08x\n", hr);
613 
614         IBackgroundCopyJobHttpOptions_Release(options);
615     }
616 
617     hr = IBackgroundCopyJob_Complete(test_job);
618     ok(hr == S_OK, "got 0x%08x\n", hr);
619 
620     hr = IBackgroundCopyJob_GetState(test_job, &state);
621     ok(hr == S_OK, "got 0x%08x\n", hr);
622     ok(state == BG_JOB_STATE_ACKNOWLEDGED, "unexpected state: %u\n", state);
623 
624     hr = IBackgroundCopyJob_Complete(test_job);
625     ok(hr == BG_E_INVALID_STATE, "got 0x%08x\n", hr);
626 
627     DeleteFileW(test_localPathA);
628 }
629 
630 typedef void (*test_t)(void);
631 
632 START_TEST(job)
633 {
634     static const test_t tests[] = {
635         test_GetId,
636         test_GetType,
637         test_GetName,
638         test_GetProgress_preTransfer,
639         test_GetState,
640         test_ResumeEmpty,
641         test_NotifyFlags,
642         test_NotifyInterface,
643         0
644     };
645     static const test_t tests_bits20[] = {
646         test_AddFile,
647         test_AddFileSet,
648         test_EnumFiles,
649         test_CompleteLocal,
650         test_CompleteLocalURL,
651         test_Cancel, /* must be last */
652         0
653     };
654     static const test_t tests_bits25[] = {
655         test_HttpOptions,
656         0
657     };
658     const test_t *test;
659     int i;
660 
661     init_paths();
662 
663     CoInitialize(NULL);
664 
665     if (FAILED(test_create_manager()))
666     {
667         CoUninitialize();
668         win_skip("Failed to create Manager instance, skipping tests\n");
669         return;
670     }
671 
672     for (test = tests, i = 0; *test; ++test, ++i)
673     {
674         /* Keep state separate between tests. */
675         if (!setup())
676         {
677             ok(0, "tests:%d: Unable to setup test\n", i);
678             break;
679         }
680         (*test)();
681         teardown();
682     }
683 
684     if (check_bits20())
685     {
686         for (test = tests_bits20, i = 0; *test; ++test, ++i)
687         {
688             /* Keep state separate between tests. */
689             if (!setup())
690             {
691                 ok(0, "tests_bits20:%d: Unable to setup test\n", i);
692                 break;
693             }
694             (*test)();
695             teardown();
696         }
697     }
698     else
699     {
700         win_skip("Tests need BITS 2.0 or higher\n");
701     }
702 
703     if (check_bits25())
704     {
705         for (test = tests_bits25, i = 0; *test; ++test, ++i)
706         {
707             /* Keep state separate between tests. */
708             if (!setup())
709             {
710                 ok(0, "tests_bits25:%d: Unable to setup test\n", i);
711                 break;
712             }
713             (*test)();
714             teardown();
715         }
716     }
717     else
718     {
719         win_skip("Tests need BITS 2.5 or higher\n");
720     }
721 
722     CoUninitialize();
723 }
724