[comctl32] New DPA testsuite

Felix Nawothnig felix.nawothnig at t-online.de
Sat Jul 2 17:19:51 CDT 2005


Tested on Win98, WinXP & Win2k3.

ChangeLog:
Rewrote the DPA testsuite.
-------------- next part --------------
Index: Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/tests/Makefile.in,v
retrieving revision 1.7
diff -u -r1.7 Makefile.in
--- Makefile.in	13 Jun 2005 12:23:01 -0000	1.7
+++ Makefile.in	2 Jul 2005 22:13:59 -0000
@@ -3,7 +3,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 TESTDLL   = comctl32.dll
-IMPORTS   = comctl32 shlwapi user32 gdi32 advapi32
+IMPORTS   = comctl32 shlwapi user32 gdi32 advapi32 ole32
 
 CTESTS = \
 	dpa.c \
Index: dpa.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/tests/dpa.c,v
retrieving revision 1.7
diff -u -r1.7 dpa.c
--- dpa.c	9 Jun 2005 09:50:56 -0000	1.7
+++ dpa.c	2 Jul 2005 22:14:03 -0000
@@ -2,6 +2,7 @@
  * Unit tests for DPA functions
  *
  * Copyright 2003 Uwe Bonnes
+ * Copyright 2005 Felix Nawothnig
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,64 +19,413 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#define COBJMACROS
+
 #include <stdarg.h>
 
 #include "windef.h"
 #include "winbase.h"
 #include "winuser.h"
 #include "commctrl.h"
+#include "objidl.h"
 
 #include "wine/test.h"
 
-static HDPA (WINAPI *pDPA_Create)(int);
-static BOOL (WINAPI *pDPA_Grow)(const HDPA hdpa, INT nGrow);
-static BOOL (WINAPI *pDPA_Destroy)(const HDPA hdpa);
-static INT  (WINAPI *pDPA_Search)(HDPA, LPVOID, INT, PFNDPACOMPARE, LPARAM, UINT);
-static BOOL (WINAPI *pDPA_SetPtr)(const HDPA hdpa, INT i, LPVOID p);
-
-static INT CALLBACK dpa_strcmp(LPVOID pvstr1, LPVOID pvstr2, LPARAM flags)
-{
-  LPCSTR str1 = (LPCSTR)pvstr1;
-  LPCSTR str2 = (LPCSTR)pvstr2;
-
-  return lstrcmpA (str1, str2);
-}
-
-static void DPA_test(void)
-{
-  HDPA dpa_ret;
-  INT  int_ret;
-  CHAR test_str0[]="test0";
-
-  if (!pDPA_Create)
-      return;
-
-  dpa_ret = pDPA_Create(0);
-  ok((dpa_ret !=0), "DPA_Create failed\n");
-  int_ret = pDPA_Search(dpa_ret,test_str0,0, dpa_strcmp,0, DPAS_SORTED);
-  ok((int_ret == -1), "DPA_Search found invalid item\n");
-  int_ret = pDPA_Search(dpa_ret,test_str0,0, dpa_strcmp,0, DPAS_SORTED|DPAS_INSERTBEFORE);
-  ok((int_ret == 0), "DPA_Search proposed bad item\n");
-  int_ret = pDPA_Search(dpa_ret,test_str0,0, dpa_strcmp,0, DPAS_SORTED|DPAS_INSERTAFTER);
-  ok((int_ret == 0), "DPA_Search proposed bad item\n");
-  int_ret = pDPA_Grow(dpa_ret,0);
-  ok(int_ret != 0, "DPA_Grow failed\n");
-  int_ret = pDPA_SetPtr(dpa_ret, 0, (void*)0xdeadbeef);
-  ok(int_ret != 0, "DPA_SetPtr failed\n");
-  int_ret = pDPA_Destroy(dpa_ret);
-  ok(int_ret != 0, "DPA_Destory failed\n");
+#define DPAM_NOSORT 0x1
+#define DPAM_INSERT 0x4
+#define DPAM_DELETE 0x8
+
+typedef struct _ITEMDATA
+{
+    INT   iPos;
+    PVOID pvData;
+} ITEMDATA, *LPITEMDATA;
+
+typedef PVOID   (CALLBACK *PFNDPAMERGE)(UINT,PVOID,PVOID,LPARAM);
+typedef HRESULT (CALLBACK *PFNDPASTM)(LPITEMDATA,IStream*,LPARAM);
+
+static HDPA    (WINAPI *pDPA_Clone)(const HDPA,const HDPA);
+static HDPA    (WINAPI *pDPA_Create)(INT);
+static HDPA    (WINAPI *pDPA_CreateEx)(INT,HANDLE);
+static PVOID   (WINAPI *pDPA_DeleteAllPtrs)(const HDPA);
+static PVOID   (WINAPI *pDPA_DeletePtr)(const HDPA,INT);
+static BOOL    (WINAPI *pDPA_Destroy)(const HDPA);
+static VOID    (WINAPI *pDPA_DestroyCallback)(HDPA,PFNDPAENUMCALLBACK,PVOID);
+static VOID    (WINAPI *pDPA_EnumCallback)(HDPA,PFNDPAENUMCALLBACK,PVOID); 
+static INT     (WINAPI *pDPA_GetPtr)(const HDPA,INT);
+static INT     (WINAPI *pDPA_GetPtrIndex)(const HDPA,PVOID);
+static BOOL    (WINAPI *pDPA_Grow)(HDPA,INT);
+static INT     (WINAPI *pDPA_InsertPtr)(const HDPA,INT,PVOID);
+static HRESULT (WINAPI *pDPA_LoadStream)(HDPA*,PFNDPASTM,IStream*,LPARAM);
+static BOOL    (WINAPI *pDPA_Merge)(const HDPA,const HDPA,DWORD,PFNDPACOMPARE,PFNDPAMERGE,LPARAM);
+static HRESULT (WINAPI *pDPA_SaveStream)(HDPA,PFNDPASTM,IStream*,LPARAM);
+static INT     (WINAPI *pDPA_Search)(HDPA,PVOID,INT,PFNDPACOMPARE,LPARAM,UINT);
+static BOOL    (WINAPI *pDPA_SetPtr)(const HDPA,INT,PVOID);
+static BOOL    (WINAPI *pDPA_Sort)(const HDPA,PFNDPACOMPARE,LPARAM);
+
+#define COMCTL32_GET_PROC(func, ord) \
+  ((p ## func = (PVOID)GetProcAddress(hcomctl32,(LPCSTR)ord)) ? 1 \
+   : (trace( #func " not exported\n"), 0)) 
+
+static BOOL InitFunctionPtrs(HMODULE hcomctl32)
+{
+    /* 4.00+ */
+    if(COMCTL32_GET_PROC(DPA_Clone, 331) &&
+       COMCTL32_GET_PROC(DPA_Create, 328) &&
+       COMCTL32_GET_PROC(DPA_CreateEx, 340) &&
+       COMCTL32_GET_PROC(DPA_DeleteAllPtrs, 337) &&
+       COMCTL32_GET_PROC(DPA_DeletePtr, 336) &&
+       COMCTL32_GET_PROC(DPA_Destroy, 329) &&
+       COMCTL32_GET_PROC(DPA_GetPtr, 332) &&
+       COMCTL32_GET_PROC(DPA_GetPtrIndex, 333) &&
+       COMCTL32_GET_PROC(DPA_Grow, 330) &&
+       COMCTL32_GET_PROC(DPA_InsertPtr, 334) &&
+       COMCTL32_GET_PROC(DPA_Search, 339) &&
+       COMCTL32_GET_PROC(DPA_SetPtr, 335) &&
+       COMCTL32_GET_PROC(DPA_Sort, 338))
+    {
+        /* 4.71+ */
+        COMCTL32_GET_PROC(DPA_DestroyCallback, 386) &&
+        COMCTL32_GET_PROC(DPA_EnumCallback, 385) &&
+        COMCTL32_GET_PROC(DPA_LoadStream, 9);
+        COMCTL32_GET_PROC(DPA_Merge, 11);
+        COMCTL32_GET_PROC(DPA_SaveStream, 10);
+
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/* Callbacks */
+static INT CALLBACK CB_CmpLT(PVOID p1, PVOID p2, LPARAM lp)
+{
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    return p1 < p2 ? -1 : p1 > p2 ? 1 : 0;
+}
+
+static INT CALLBACK CB_CmpGT(PVOID p1, PVOID p2, LPARAM lp)
+{
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    return p1 > p2 ? -1 : p1 < p2 ? 1 : 0;
+}
+
+static PVOID CALLBACK CB_MergeInsertSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
+{
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    return p1;
+}        
+
+static PVOID CALLBACK CB_MergeDeleteOddSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
+{
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    return ((PCHAR)p2)+1;
+}
+
+static INT nEnum;
+
+static INT CALLBACK CB_EnumFirstThree(PVOID pItem, PVOID lp)
+{   
+    INT i;
+
+    i = pDPA_GetPtrIndex(lp, pItem);
+    ok(i == nEnum, "i=%d nEnum=%d\n", i, nEnum);
+    nEnum++;
+    pDPA_SetPtr(lp, i, (PVOID)7);
+    return pItem != (PVOID)3;
+}
+
+static HRESULT CALLBACK CB_Save(LPITEMDATA pInfo, IStream *pStm, LPARAM lp)
+{
+    HRESULT hRes;
+    
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    hRes = IStream_Write(pStm, &pInfo->iPos, sizeof(INT), NULL);
+    ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+    hRes = IStream_Write(pStm, &pInfo->pvData, sizeof(PVOID), NULL);
+    ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+    return S_OK;
+}
+
+static HRESULT CALLBACK CB_Load(LPITEMDATA pInfo, IStream *pStm, LPARAM lp)
+{
+    HRESULT hRes;
+    INT iOldPos;
+    
+    iOldPos = pInfo->iPos;
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    hRes = IStream_Read(pStm, &pInfo->iPos, sizeof(INT), NULL);
+    ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+    ok(pInfo->iPos == iOldPos, "iPos=%d iOldPos=%d\n", pInfo->iPos, iOldPos);
+    hRes = IStream_Read(pStm, &pInfo->pvData, sizeof(PVOID), NULL);
+    ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+    return S_OK;
+}
+
+static BOOL CheckDPA(HDPA dpa, DWORD dwIn, PDWORD pdwOut)
+{
+    DWORD dwOut = 0;
+    INT i;
+
+    for(i = 0; i < 8;)
+    {
+        ULONG_PTR ulItem = (ULONG_PTR)pDPA_GetPtr(dpa, i++);
+        if(!ulItem) break;
+        dwOut = dwOut << 4 | (ulItem & 0xf);
+    }
+    
+    *pdwOut = dwOut;
+
+    if(dwOut != dwIn)
+    {
+        pDPA_DeleteAllPtrs(dpa);
+        
+        do
+        {
+            pDPA_InsertPtr(dpa, 0, (PVOID)(dwIn & 0xf));
+            dwIn >>= 4;
+        }
+        while(dwIn);
+        
+        return FALSE;
+    }
+    
+    return TRUE;
+}
+
+static void test_dpa(void)
+{
+    SYSTEM_INFO si;
+    HANDLE hHeap;
+    HDPA dpa, dpa2, dpa3;
+    INT ret, i;
+    PVOID p;
+    DWORD dw, dw2, dw3;
+    HRESULT hRes;
+    
+    GetSystemInfo(&si);
+    hHeap = HeapCreate(0, 1, 2);
+    ok(hHeap != NULL, "error=%ld\n", GetLastError());
+    dpa3 = pDPA_CreateEx(0, hHeap);
+    ok(dpa3 != NULL, "\n");
+    ret = pDPA_Grow(dpa3, si.dwPageSize + 1);
+    todo_wine ok(!ret && GetLastError() == ERROR_NOT_ENOUGH_MEMORY, 
+       "ret=%d error=%ld\n", ret, GetLastError());
+        
+    dpa = pDPA_Create(0);
+    ok(dpa != NULL, "\n");
+
+    /* Set item with out of bound index */
+    ok(pDPA_SetPtr(dpa, 1, (PVOID)6), "\n");
+    /* Fill the greated gap */
+    ok(pDPA_SetPtr(dpa, 0, (PVOID)5), "\n");
+    ok(CheckDPA(dpa, 0x56, &dw), "dw=0x%lx\n", dw);
+    
+    /* Prepend item */
+    ret = pDPA_InsertPtr(dpa, 1, (PVOID)1);
+    ok(ret == 1, "ret=%d\n", ret);
+    /* Append item using correct index */
+    ret = pDPA_InsertPtr(dpa, 3, (PVOID)3);
+    ok(ret == 3, "ret=%d\n", ret);
+    /* Append item using out of bound index */
+    ret = pDPA_InsertPtr(dpa, 5, (PVOID)2);
+    todo_wine ok(ret == 4, "ret=%d\n", ret);
+    /* Append item using DPA_APPEND */ 
+    ret = pDPA_InsertPtr(dpa, DPA_APPEND, (PVOID)4);
+    todo_wine ok(ret == 5, "ret=%d\n", ret);
+
+    todo_wine ok(CheckDPA(dpa, 0x516324, &dw), "dw=0x%lx\n", dw);
+
+    for(i = 1; i <= 6; i++)
+    {
+        INT j, k;
+        k = pDPA_GetPtrIndex(dpa, (PVOID)i);
+        /* Linear searches should work on unsorted DPAs */
+        j = pDPA_Search(dpa, (PVOID)i, 0, CB_CmpLT, 0xdeadbeef, 0);
+        ok(j == k, "j=%d k=%d\n", j, k);
+    }
+
+    /* Sort DPA */
+    ok(pDPA_Sort(dpa, CB_CmpGT, 0xdeadbeef), "\n");
+    ok(CheckDPA(dpa, 0x654321, &dw), "dw=0x%lx\n", dw);
+    
+    /* Clone into a new DPA */
+    dpa2 = pDPA_Clone(dpa, NULL);
+    ok(dpa2 != NULL, "\n");
+    /* The old data should have been preserved */
+    ok(CheckDPA(dpa2, 0x654321, &dw2), "dw=0x%lx\n", dw2);
+    ok(pDPA_Sort(dpa, CB_CmpLT, 0xdeadbeef), "\n");
+    
+    /* Test if the DPA itself was really copied */
+    ok(CheckDPA(dpa,  0x123456, &dw),  "dw=0x%lx\n",  dw );
+    ok(CheckDPA(dpa2, 0x654321, &dw2), "dw2=0x%lx\n", dw2);
+
+    /* Clone into an old DPA */
+    p = NULL; SetLastError(ERROR_SUCCESS);
+    p = pDPA_Clone(dpa, dpa3);
+    ok(p == dpa3, "p=%p\n", p);
+    ok(CheckDPA(dpa3, 0x123456, &dw3), "dw3=0x%lx\n", dw3);
+
+    for(i = 1; i <= 6; i++)
+    {
+        INT j;
+
+        /* The array is in order so ptr == index+1 */
+        j = pDPA_GetPtrIndex(dpa, (PVOID)i);
+        ok(j+1 == i, "j=%d i=%d\n", j, i);
+        j = pDPA_Search(dpa, (PVOID)i, 0, CB_CmpLT, 0xdeadbeef, DPAS_SORTED);
+        if(i > 1) todo_wine ok(j+1 == i, "j=%d i=%d\n", j, i);
+
+        /* Linear searches respect iStart ... */
+        j = pDPA_Search(dpa, (PVOID)i, i+1, CB_CmpLT, 0xdeadbeef, 0);
+        ok(j == DPA_ERR, "j=%d\n", j);
+        /* ... but for a binary search it's ignored */
+        j = pDPA_Search(dpa, (PVOID)i, i+1, CB_CmpLT, 0xdeadbeef, DPAS_SORTED);
+        todo_wine ok(j+1 == i, "j=%d i=%d\n", j, i);
+    }
+    
+    /* Try to get the index of a non-existent item */
+    i = pDPA_GetPtrIndex(dpa, (PVOID)7);
+    ok(i == DPA_ERR, "i=%d\n", i);
+    
+    /* Try to delete out of bound indexes */
+    p = pDPA_DeletePtr(dpa, -1);
+    ok(p == NULL, "p=%p\n", p);
+    p = pDPA_DeletePtr(dpa, 6);
+    ok(p == NULL, "p=%p\n", p);
+
+    /* Delete the third item */
+    p = pDPA_DeletePtr(dpa, 2);
+    ok(p == (PVOID)3, "p=%p\n", p);
+    ok(CheckDPA(dpa, 0x12456, &dw), "dw=0x%lx\n", dw);
+
+    /* Check where to re-insert the deleted item */
+    i = pDPA_Search(dpa, (PVOID)3, 0, 
+                    CB_CmpLT, 0xdeadbeef, DPAS_SORTED|DPAS_INSERTAFTER);
+    ok(i == 2, "i=%d\n", i);
+    /* DPAS_INSERTBEFORE works just like DPAS_INSERTAFTER */
+    i = pDPA_Search(dpa, (PVOID)3, 0,
+                    CB_CmpLT, 0xdeadbeef, DPAS_SORTED|DPAS_INSERTBEFORE);
+    todo_wine ok(i == 2, "i=%d\n", i);
+
+    /* Re-insert the item */
+    ret = pDPA_InsertPtr(dpa, 2, (PVOID)3);
+    ok(ret == 2, "ret=%d i=%d\n", ret, 2);
+    ok(CheckDPA(dpa, 0x123456, &dw), "dw=0x%lx\n", dw);
+    
+    /* When doing a binary search while claiming reverse order all indexes
+     * should be bogus */
+    for(i = 0; i < 6; i++)
+    {
+        INT j = pDPA_Search(dpa, (PVOID)i, 0, CB_CmpGT, 0xdeadbeef,
+                            DPAS_SORTED|DPAS_INSERTBEFORE);
+        ok(j != i, "i=%d\n", i);
+    }
+
+    if(pDPA_Merge)
+    {
+        /* Delete all even entries from dpa */
+        p = pDPA_DeletePtr(dpa, 1);
+        p = pDPA_DeletePtr(dpa, 2);
+        p = pDPA_DeletePtr(dpa, 3);
+        ok(CheckDPA(dpa, 0x135, &dw), "dw=0x%lx\n", dw);
+    
+        /* Delete all odd entries from dpa2 */
+        pDPA_Merge(dpa2, dpa, DPAM_DELETE, 
+                   CB_CmpLT, CB_MergeDeleteOddSrc, 0xdeadbeef);
+        todo_wine ok(CheckDPA(dpa2, 0x246, &dw2), "dw=0x%lx\n", dw2);
+    
+        /* Merge dpa3 into dpa2 and dpa */
+        pDPA_Merge(dpa, dpa3, DPAM_INSERT|DPAM_NOSORT, 
+                   CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
+        pDPA_Merge(dpa2, dpa3, DPAM_INSERT|DPAM_NOSORT, 
+                   CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
+    
+        ok(CheckDPA(dpa,  0x123456, &dw ), "dw=0x%lx\n",  dw);
+        ok(CheckDPA(dpa2, 0x123456, &dw2), "dw2=0x%lx\n", dw2);
+        ok(CheckDPA(dpa3, 0x123456, &dw3), "dw3=0x%lx\n", dw3);
+    }
+
+    if(pDPA_EnumCallback)
+    {
+        nEnum = 0;
+        pDPA_EnumCallback(dpa2, CB_EnumFirstThree, (PVOID)dpa2);
+        ok(CheckDPA(dpa2, 0x777456, &dw2), "dw=0x%lx\n", dw2);
+        ok(nEnum == 3, "nEnum=%d\n", nEnum);
+    }
+    pDPA_DeleteAllPtrs(dpa2);
+    ok(CheckDPA(dpa2, 0, &dw2), "dw2=0x%lx\n", dw2);
+    pDPA_Destroy(dpa2);
+
+    if(pDPA_DestroyCallback)
+    {
+        nEnum = 0;
+        pDPA_DestroyCallback(dpa3, CB_EnumFirstThree, dpa3);
+        ok(nEnum == 3, "nEnum=%d\n", nEnum);
+    }
+    else pDPA_Destroy(dpa3);
+
+    if(!pDPA_SaveStream)
+        goto skip_stream_tests;
+
+    hRes = CoInitialize(NULL);
+    if(hRes == S_OK)
+    {
+        static const WCHAR szStg[] = { 'S','t','g',0 };
+        IStorage* pStg = NULL;
+        IStream* pStm = NULL;
+        LARGE_INTEGER liZero;
+        liZero.QuadPart = 0;
+        DWORD dwMode;
+
+        dwMode = STGM_DIRECT|STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
+        hRes = StgCreateDocfile(NULL, dwMode|STGM_DELETEONRELEASE, 0, &pStg);
+        ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+
+        hRes = IStorage_CreateStream(pStg, szStg, dwMode, 0, 0, &pStm);
+        ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+
+        hRes = pDPA_SaveStream(dpa, CB_Save, pStm, 0xdeadbeef);
+        todo_wine ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+        pDPA_Destroy(dpa);
+        
+        hRes = IStream_Seek(pStm, liZero, STREAM_SEEK_SET, NULL);
+        ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+        hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, 0xdeadbeef);
+        todo_wine ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+        todo_wine ok(CheckDPA(dpa, 0x123456, &dw), "dw=0x%lx\n", dw);
+        pDPA_Destroy(dpa);
+
+        ret = IStream_Release(pStm);
+        ok(!ret, "ret=%d\n", ret);
+	
+        ret = IStorage_Release(pStg);
+        ok(!ret, "ret=%d\n", ret);
+
+        CoUninitialize();
+    }
+    else ok(0, "hResult: %ld\n", hRes);
+
+skip_stream_tests:
+    pDPA_Destroy(dpa);
 }
 
 START_TEST(dpa)
 {
-    HMODULE hdll;
+    HMODULE hcomctl32;
+
+    hcomctl32 = GetModuleHandleA("comctl32.dll");
 
-    hdll=GetModuleHandleA("comctl32.dll");
-    pDPA_Create=(void*)GetProcAddress(hdll,(LPCSTR)328);
-    pDPA_Destroy=(void*)GetProcAddress(hdll,(LPCSTR)329);
-    pDPA_Grow=(void*)GetProcAddress(hdll,(LPCSTR)330);
-    pDPA_Search=(void*)GetProcAddress(hdll,(LPCSTR)339);
-    pDPA_SetPtr=(void*)GetProcAddress(hdll,(LPCSTR)335);
+    if(!hcomctl32)
+    {
+        ok(0, "error=%ld\n", GetLastError());
+        return;
+    }
+
+    if(InitFunctionPtrs(hcomctl32))
+        test_dpa();
+    else
+        trace("skipping tests\n");
 
-    DPA_test();
+    FreeLibrary(hcomctl32);
 }


More information about the wine-patches mailing list