[ATL_APITEST] Add test for CComQIPtr (or rather, our gcc hack that slightly looks...
[reactos.git] / modules / rostests / apitests / atl / CComQIPtr.cpp
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Test for CComQIPtr
5 * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #include <atlbase.h>
9 #include <atlcom.h>
10
11 #ifdef __REACTOS__
12 #include <apitest.h>
13 #else
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <stdarg.h>
17 int g_tests_executed = 0;
18 int g_tests_failed = 0;
19 void ok_func(const char *file, int line, BOOL value, const char *fmt, ...)
20 {
21 va_list va;
22 va_start(va, fmt);
23 if (!value)
24 {
25 printf("%s (%d): ", file, line);
26 vprintf(fmt, va);
27 g_tests_failed++;
28 }
29 g_tests_executed++;
30 va_end(va);
31 }
32 #undef ok
33 #define ok(value, ...) ok_func(__FILE__, __LINE__, value, __VA_ARGS__)
34 #define START_TEST(x) int main(void)
35 #endif
36
37
38 static LONG g_QI = 0;
39
40 class CQITestObject :
41 public IPersist,
42 public IStdMarshalInfo
43 {
44 public:
45 LONG m_dwRef;
46
47 CQITestObject()
48 :m_dwRef(1)
49 {
50 }
51 ~CQITestObject()
52 {
53 }
54
55 STDMETHOD_(ULONG, AddRef)()
56 {
57 InterlockedIncrement(&m_dwRef);
58 return 2;
59 }
60
61 STDMETHOD_(ULONG, Release)()
62 {
63 InterlockedDecrement(&m_dwRef);
64 return 1;
65 }
66
67 STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
68 {
69 InterlockedIncrement(&g_QI);
70 if (iid == IID_IUnknown || iid == IID_IPersist)
71 {
72 AddRef();
73 *ppvObject = static_cast<IPersist*>(this);
74 return S_OK;
75 }
76 else if (iid == IID_IStdMarshalInfo)
77 {
78 AddRef();
79 *ppvObject = static_cast<IStdMarshalInfo*>(this);
80 return S_OK;
81 }
82 return E_NOINTERFACE;
83 }
84
85 // *** IPersist methods ***
86 STDMETHOD(GetClassID)(CLSID *pClassID)
87 {
88 return E_NOTIMPL;
89 }
90
91 // *** IStdMarshalInfo methods ***
92 STDMETHOD(GetClassForHandler)(DWORD dwDestContext, void *pvDestContext, CLSID *pClsid)
93 {
94 return E_NOTIMPL;
95 }
96 };
97
98 // Yes this sucks, but we have to support GCC. (CORE-12710)
99 #ifdef __REACTOS__
100 #define DECLARE_QIPTR(type) CComQIIDPtr<I_ID(type)>
101 #else
102 #define DECLARE_QIPTR(type) CComQIPtr<type>
103 #endif
104
105 START_TEST(CComQIPtr)
106 {
107 CQITestObject testObject;
108 IUnknown* unk = static_cast<IPersist*>(&testObject);
109 ok(testObject.m_dwRef == 1, "Expected m_dwRef 1, got %lu\n", testObject.m_dwRef);
110 ok(g_QI == 0, "Expected g_QI 0, got %lu\n", g_QI);
111
112 {
113 DECLARE_QIPTR(IPersist) ppPersist(unk);
114 ok(testObject.m_dwRef == 2, "Expected m_dwRef 2, got %lu\n", testObject.m_dwRef);
115 ok(g_QI == 1, "Expected g_QI 1, got %lu\n", g_QI);
116
117 DECLARE_QIPTR(IStdMarshalInfo) ppMarshal(ppPersist);
118 ok(testObject.m_dwRef == 3, "Expected m_dwRef 3, got %lu\n", testObject.m_dwRef);
119 ok(g_QI == 2, "Expected g_QI 2, got %lu\n", g_QI);
120 }
121 ok(testObject.m_dwRef == 1, "Expected m_dwRef 1, got %lu\n", testObject.m_dwRef);
122 {
123 DECLARE_QIPTR(IStdMarshalInfo) ppMarshal;
124 ok(testObject.m_dwRef == 1, "Expected m_dwRef 1, got %lu\n", testObject.m_dwRef);
125 ok(g_QI == 2, "Expected g_QI 2, got %lu\n", g_QI);
126
127 ppMarshal = unk;
128 ok(testObject.m_dwRef == 2, "Expected m_dwRef 2, got %lu\n", testObject.m_dwRef);
129 ok(g_QI == 3, "Expected g_QI 3, got %lu\n", g_QI);
130
131 ppMarshal = static_cast<IUnknown*>(NULL);
132 ok(testObject.m_dwRef == 1, "Expected m_dwRef 1, got %lu\n", testObject.m_dwRef);
133 ok(g_QI == 3, "Expected g_QI 3, got %lu\n", g_QI);
134
135 CComPtr<IUnknown> spUnk(unk);
136 ok(testObject.m_dwRef == 2, "Expected m_dwRef 2, got %lu\n", testObject.m_dwRef);
137 ok(g_QI == 3, "Expected g_QI 3, got %lu\n", g_QI);
138
139 ppMarshal = spUnk;
140 ok(testObject.m_dwRef == 3, "Expected m_dwRef 3, got %lu\n", testObject.m_dwRef);
141 ok(g_QI == 4, "Expected g_QI 4, got %lu\n", g_QI);
142
143 spUnk.Release();
144 ok(testObject.m_dwRef == 2, "Expected m_dwRef 2, got %lu\n", testObject.m_dwRef);
145 ok(g_QI == 4, "Expected g_QI 4, got %lu\n", g_QI);
146
147 spUnk = ppMarshal;
148 ok(testObject.m_dwRef == 3, "Expected m_dwRef 3, got %lu\n", testObject.m_dwRef);
149 #ifdef __REACTOS__
150 // CORE-12710
151 todo_if(1)
152 #endif
153 ok(g_QI == 5, "Expected g_QI 5, got %lu\n", g_QI);
154 }
155
156 #ifndef __REACTOS__
157 printf("CComQIPtr: %i tests executed (0 marked as todo, %i failures), 0 skipped.\n", g_tests_executed, g_tests_failed);
158 return g_tests_failed;
159 #endif
160 }