[6/6] qmgr: Implement BackgroundCopyJob_Complete.

Dan Hipschman dsh at linux.ucla.edu
Thu Mar 6 21:08:18 CST 2008


Implements IBackgroundCopyJob_Complete with test.

With this we can finally actually do some background downloading (or rather
copying since it's only implemented for local "remote" files so far).  Adding
HTTP downloads is not so far off now, just dealing with connecting to the
server and then use the SOCKET for a HANDLE.

---
 dlls/qmgr/job.c       |   39 ++++++++++++++++++-
 dlls/qmgr/tests/job.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 135 insertions(+), 2 deletions(-)

diff --git a/dlls/qmgr/job.c b/dlls/qmgr/job.c
index 43ba3b9..ea5917b 100644
--- a/dlls/qmgr/job.c
+++ b/dlls/qmgr/job.c
@@ -155,8 +155,40 @@ static HRESULT WINAPI BITS_IBackgroundCopyJob_Cancel(
 static HRESULT WINAPI BITS_IBackgroundCopyJob_Complete(
     IBackgroundCopyJob* iface)
 {
-    FIXME("Not implemented\n");
-    return E_NOTIMPL;
+    BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
+    HRESULT rv = S_OK;
+
+    WaitForSingleObject(This->mutex, INFINITE);
+
+    if (This->state == BG_JOB_STATE_CANCELLED
+        || This->state == BG_JOB_STATE_ACKNOWLEDGED)
+    {
+        rv = BG_E_INVALID_STATE;
+    }
+    else
+    {
+        BackgroundCopyFileImpl *file;
+        LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob)
+        {
+            if (file->fileProgress.Completed)
+            {
+                if (!MoveFileW(file->tempFileName, file->info.LocalName))
+                {
+                    ERR("Couldn't rename file %s -> %s; perhaps try a copy / delete?\n",
+                        debugstr_w(file->tempFileName),
+                        debugstr_w(file->info.LocalName));
+                    rv = BG_S_PARTIAL_COMPLETE;
+                }
+            }
+            else
+                rv = BG_S_PARTIAL_COMPLETE;
+        }
+    }
+
+    This->state = BG_JOB_STATE_ACKNOWLEDGED;
+    ReleaseMutex(This->mutex);
+
+    return rv;
 }
 
 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetId(
@@ -507,7 +539,10 @@ void processJob(IBackgroundCopyJob *job)
             }
         ReleaseMutex(This->mutex);
         if (done)
+        {
+            setJobStateAtomic(This, BG_JOB_STATE_TRANSFERRED);
             return;
+        }
 
         if (!processFile(file, This))
           return;
diff --git a/dlls/qmgr/tests/job.c b/dlls/qmgr/tests/job.c
index fab1c8d..726624a 100644
--- a/dlls/qmgr/tests/job.c
+++ b/dlls/qmgr/tests/job.c
@@ -280,6 +280,103 @@ static void test_ResumeEmpty(void)
     ok(state == BG_JOB_STATE_SUSPENDED, "Incorrect job state: %d\n", state);
 }
 
+static void makeFile(WCHAR *name, const char *contents)
+{
+    HANDLE file;
+    DWORD w, len = strlen(contents);
+
+    DeleteFileW(name);
+    file = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                       FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "CreateFile\n");
+    ok(WriteFile(file, contents, len, &w, NULL), "WriteFile\n");
+    CloseHandle(file);
+}
+
+static void compareFiles(WCHAR *n1, WCHAR *n2)
+{
+    char b1[256];
+    char b2[256];
+    DWORD s1, s2;
+    HANDLE f1, f2;
+
+    f1 = CreateFileW(n1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+                     FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(f1 != INVALID_HANDLE_VALUE, "CreateFile\n");
+
+    f2 = CreateFileW(n2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+                     FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(f1 != INVALID_HANDLE_VALUE, "CreateFile\n");
+
+    /* Neither of these files is very big */
+    ok(ReadFile(f1, b1, sizeof b1, &s1, NULL), "ReadFile\n");
+    ok(ReadFile(f2, b2, sizeof b2, &s2, NULL), "ReadFile\n");
+
+    CloseHandle(f1);
+    CloseHandle(f2);
+
+    ok(s1 == s2, "Files differ in length\n");
+    ok(memcmp(b1, b2, s1) == 0, "Files differ in contents\n");
+}
+
+/* Test a complete transfer for local files */
+static void test_CompleteLocal(void)
+{
+    static const int timeout_sec = 30;
+    HRESULT hres;
+    BG_JOB_STATE state;
+    int i;
+
+    DeleteFileW(test_localPathA);
+    DeleteFileW(test_localPathB);
+    makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
+    makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
+
+    hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathA,
+                                      test_localPathA);
+    if (hres != S_OK)
+    {
+        skip("Unable to add file to job\n");
+        return;
+    }
+
+    hres = IBackgroundCopyJob_AddFile(test_job, test_remotePathB,
+                                      test_localPathB);
+    if (hres != S_OK)
+    {
+        skip("Unable to add file to job\n");
+        return;
+    }
+
+    hres = IBackgroundCopyJob_Resume(test_job);
+    ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
+
+    for (i = 0; i < timeout_sec; ++i)
+    {
+        hres = IBackgroundCopyJob_GetState(test_job, &state);
+        ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
+        ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
+           || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED,
+           "Bad state: %d\n", state);
+        if (state == BG_JOB_STATE_TRANSFERRED)
+            break;
+        Sleep(1000);
+    }
+
+    ok(i < timeout_sec, "BITS jobs timed out\n");
+    hres = IBackgroundCopyJob_Complete(test_job);
+    ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
+    hres = IBackgroundCopyJob_GetState(test_job, &state);
+    ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
+    ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
+
+    compareFiles(test_remotePathA, test_localPathA);
+    compareFiles(test_remotePathB, test_localPathB);
+
+    ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
+    ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
+}
+
 typedef void (*test_t)(void);
 
 START_TEST(job)
@@ -293,6 +390,7 @@ START_TEST(job)
         test_GetProgress_preTransfer,
         test_GetState,
         test_ResumeEmpty,
+        test_CompleteLocal,
         0
     };
     const test_t *test;



More information about the wine-patches mailing list