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