1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Test for CHeapPtrList 5 * COPYRIGHT: Copyright 2020 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8 #ifdef HAVE_APITEST 9 #include <apitest.h> 10 #else 11 #include "atltest.h" 12 #endif 13 #include <atlcoll.h> 14 15 static PDWORD 16 test_Alloc(DWORD value) 17 { 18 PDWORD ptr = (PDWORD)::CoTaskMemAlloc(sizeof(DWORD)); 19 *ptr = value; 20 return ptr; 21 } 22 23 // We use the CComAllocator, so we can easily spy on it 24 template <typename T> 25 class CComHeapPtrList : 26 public CHeapPtrList<T, CComAllocator> 27 { 28 public: 29 CComHeapPtrList(_In_ UINT nBlockSize = 10) throw() 30 :CHeapPtrList<T, CComAllocator>(nBlockSize) 31 { 32 } 33 }; 34 35 36 37 static LONG g_OpenAllocations = 0; 38 static LONG g_Reallocations = 0; 39 40 struct CHeapPtrListMallocSpy : public IMallocSpy 41 { 42 STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) 43 { 44 if (IsEqualGUID(riid, IID_IMallocSpy)) 45 { 46 *ppvObject = this; 47 } 48 return S_OK; 49 } 50 51 virtual ULONG STDMETHODCALLTYPE AddRef() { return 1; } 52 virtual ULONG STDMETHODCALLTYPE Release() { return 1; } 53 virtual SIZE_T STDMETHODCALLTYPE PreAlloc(SIZE_T cbRequest) { return cbRequest; } 54 virtual LPVOID STDMETHODCALLTYPE PostAlloc(LPVOID pActual) 55 { 56 InterlockedIncrement(&g_OpenAllocations); 57 return pActual; 58 } 59 virtual LPVOID STDMETHODCALLTYPE PreFree(LPVOID pRequest, BOOL) { return pRequest; } 60 virtual void STDMETHODCALLTYPE PostFree(BOOL fSpyed) 61 { 62 if (fSpyed) 63 InterlockedDecrement(&g_OpenAllocations); 64 } 65 virtual SIZE_T STDMETHODCALLTYPE PreRealloc(LPVOID pRequest, SIZE_T cbRequest, LPVOID *ppNewRequest, BOOL) 66 { 67 *ppNewRequest = pRequest; 68 return cbRequest; 69 } 70 virtual LPVOID STDMETHODCALLTYPE PostRealloc(LPVOID pActual, BOOL fSpyed) 71 { 72 if (fSpyed) 73 InterlockedIncrement(&g_Reallocations); 74 return pActual; 75 } 76 virtual LPVOID STDMETHODCALLTYPE PreGetSize(LPVOID pRequest, BOOL) { return pRequest; } 77 virtual SIZE_T STDMETHODCALLTYPE PostGetSize(SIZE_T cbActual, BOOL) { return cbActual; } 78 virtual LPVOID STDMETHODCALLTYPE PreDidAlloc(LPVOID pRequest, BOOL) { return pRequest; } 79 virtual int STDMETHODCALLTYPE PostDidAlloc(LPVOID, BOOL, int fActual) { return fActual; } 80 virtual void STDMETHODCALLTYPE PreHeapMinimize() {} 81 virtual void STDMETHODCALLTYPE PostHeapMinimize() {} 82 }; 83 84 static CHeapPtrListMallocSpy g_Spy; 85 86 87 START_TEST(CHeapPtrList) 88 { 89 HRESULT hr = CoRegisterMallocSpy(&g_Spy); 90 ok(SUCCEEDED(hr), "Expected CoRegisterMallocSpy to succeed, but it failed: 0x%lx\n", hr); 91 92 { 93 ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations); 94 CComHeapPtrList<DWORD> heapPtr1; 95 ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations); 96 PDWORD Ptr = test_Alloc(0x11111111); 97 ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations); 98 CComHeapPtr<DWORD> tmp(Ptr); 99 ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations); 100 heapPtr1.AddTail(tmp); 101 ok(tmp.m_pData == NULL, "Expected m_pData to be transfered\n"); 102 ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations); 103 Ptr = test_Alloc(0x22222222); 104 ok(g_OpenAllocations == 2, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations); 105 #if defined(_MSC_VER) && !defined(__clang__) 106 heapPtr1.AddTail(CComHeapPtr<DWORD>(Ptr)); 107 #else 108 CComHeapPtr<DWORD> xxx(Ptr); 109 heapPtr1.AddTail(xxx); 110 #endif 111 ok(g_OpenAllocations == 2, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations); 112 } 113 ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations); 114 115 hr = CoRevokeMallocSpy(); 116 ok(SUCCEEDED(hr), "Expected CoRevokeMallocSpy to succeed, but it failed: 0x%lx\n", hr); 117 } 118