Skip to content

Commit 325bd80

Browse files
committed
Refactor test parameters and make activation factories counted objects
1 parent 40d7274 commit 325bd80

16 files changed

+406
-228
lines changed

src/ComInprocTestbed/Tests.cpp

Lines changed: 232 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,258 @@
22
// Licensed under the MIT License.
33
#include "pch.h"
44
#include "Tests.h"
5+
#include "PackageManager.h"
56

67
using namespace std::string_view_literals;
78

8-
BOOL CALLBACK CheckForWinGetWindow(HWND hwnd, LPARAM param)
9+
namespace
910
{
10-
bool* result = reinterpret_cast<bool*>(param);
11+
#define ADVANCE_ARG_PARAMETER if (++i >= argc) { winrt::throw_hresult(E_INVALIDARG); }
1112

12-
int textLength = GetWindowTextLengthW(hwnd) + 1;
13-
std::wstring windowText(textLength, '\0');
14-
textLength = GetWindowTextW(hwnd, &windowText[0], textLength);
15-
windowText.resize(textLength);
16-
17-
if (L"WingetMessageOnlyWindow"sv == windowText)
13+
std::string ToLower(std::string_view in)
1814
{
19-
*result = true;
20-
return FALSE;
15+
std::string result(in);
16+
std::transform(result.begin(), result.end(), result.begin(),
17+
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
18+
return result;
2119
}
2220

23-
return TRUE;
24-
}
21+
#define BEGIN_ENUM_PARSE_FUNC(_type_) \
22+
_type_ Parse ## _type_(const char* input) \
23+
{ \
24+
auto lower = ToLower(input); \
25+
if (lower.empty()) {}
2526

26-
// Look for the set of well known objects that should be present after we have spun everything up.
27-
// Returns true if all well known objects are found in the expected state.
28-
bool SearchForWellKnownObjects(bool expectExist)
29-
{
30-
bool result = true;
27+
#define ITEM_ENUM_PARSE_FUNC(_type_, _value_) \
28+
else if (ToLower(#_value_) == lower) \
29+
{ \
30+
return _type_ ## :: ## _value_; \
31+
}
3132

32-
auto coreApplicationProperties = winrt::Windows::ApplicationModel::Core::CoreApplication::Properties();
33+
#define END_ENUM_PARSE_FUNC \
34+
winrt::throw_hresult(E_INVALIDARG); \
35+
}
3336

34-
// COM statics
35-
for (std::wstring_view item : {
36-
L"WindowsPackageManager.CachedInstalledIndex"sv,
37-
L"WindowsPackageManager.TerminationSignalHandler"sv,
38-
})
37+
#define BEGIN_ENUM_NAME_FUNC(_type_) \
38+
std::string_view ToString(_type_); \
39+
std::ostream& operator<<(std::ostream& o, _type_ input) { return (o << ToString(input)); } \
40+
std::string_view ToString(_type_ input) \
41+
{ \
42+
switch (input) {
43+
44+
#define ITEM_ENUM_NAME_FUNC(_type_, _value_) \
45+
case _type_ ## :: ## _value_: return #_value_;
46+
47+
#define END_ENUM_NAME_FUNC \
48+
} \
49+
return "Unknown"; \
50+
}
51+
52+
BEGIN_ENUM_PARSE_FUNC(ComInitializationType)
53+
ITEM_ENUM_PARSE_FUNC(ComInitializationType, STA)
54+
ITEM_ENUM_PARSE_FUNC(ComInitializationType, MTA)
55+
END_ENUM_PARSE_FUNC
56+
57+
BEGIN_ENUM_NAME_FUNC(ComInitializationType)
58+
ITEM_ENUM_NAME_FUNC(ComInitializationType, STA)
59+
ITEM_ENUM_NAME_FUNC(ComInitializationType, MTA)
60+
END_ENUM_NAME_FUNC
61+
62+
BEGIN_ENUM_PARSE_FUNC(UnloadBehavior)
63+
ITEM_ENUM_PARSE_FUNC(UnloadBehavior, Allow)
64+
ITEM_ENUM_PARSE_FUNC(UnloadBehavior, AtExit)
65+
ITEM_ENUM_PARSE_FUNC(UnloadBehavior, Never)
66+
END_ENUM_PARSE_FUNC
67+
68+
BEGIN_ENUM_NAME_FUNC(UnloadBehavior)
69+
ITEM_ENUM_NAME_FUNC(UnloadBehavior, Allow)
70+
ITEM_ENUM_NAME_FUNC(UnloadBehavior, AtExit)
71+
ITEM_ENUM_NAME_FUNC(UnloadBehavior, Never)
72+
END_ENUM_NAME_FUNC
73+
74+
BEGIN_ENUM_PARSE_FUNC(ActivationType)
75+
ITEM_ENUM_PARSE_FUNC(ActivationType, ClassName)
76+
ITEM_ENUM_PARSE_FUNC(ActivationType, CLSID_WinRT)
77+
ITEM_ENUM_PARSE_FUNC(ActivationType, CLSID_CoCreateInstance)
78+
END_ENUM_PARSE_FUNC
79+
80+
BEGIN_ENUM_NAME_FUNC(ActivationType)
81+
ITEM_ENUM_NAME_FUNC(ActivationType, ClassName)
82+
ITEM_ENUM_NAME_FUNC(ActivationType, CLSID_WinRT)
83+
ITEM_ENUM_NAME_FUNC(ActivationType, CLSID_CoCreateInstance)
84+
END_ENUM_NAME_FUNC
85+
86+
BOOL CALLBACK CheckForWinGetWindow(HWND hwnd, LPARAM param)
3987
{
40-
bool present = coreApplicationProperties.HasKey(item);
88+
bool* result = reinterpret_cast<bool*>(param);
89+
90+
int textLength = GetWindowTextLengthW(hwnd) + 1;
91+
std::wstring windowText(textLength, '\0');
92+
textLength = GetWindowTextW(hwnd, &windowText[0], textLength);
93+
windowText.resize(textLength);
94+
95+
if (L"WingetMessageOnlyWindow"sv == windowText)
96+
{
97+
*result = true;
98+
return FALSE;
99+
}
100+
101+
return TRUE;
102+
}
103+
104+
// Look for the set of well known objects that should be present after we have spun everything up.
105+
// Returns true if all well known objects are found in the expected state.
106+
bool SearchForWellKnownObjects(bool expectExist)
107+
{
108+
bool result = true;
109+
110+
auto coreApplicationProperties = winrt::Windows::ApplicationModel::Core::CoreApplication::Properties();
111+
112+
// COM statics
113+
for (std::wstring_view item : {
114+
L"WindowsPackageManager.CachedInstalledIndex"sv,
115+
L"WindowsPackageManager.TerminationSignalHandler"sv,
116+
})
117+
{
118+
bool present = coreApplicationProperties.HasKey(item);
41119

42-
if (present != expectExist)
120+
if (present != expectExist)
121+
{
122+
std::cout << "CoreApplication property `" << winrt::to_string(item) << "` was not in expected state [" << (expectExist ? "should exist" : "should not exist") << "]\n";
123+
result = false;
124+
}
125+
}
126+
127+
// Shutdown monitoring window
128+
bool foundWindow = false;
129+
EnumWindows(CheckForWinGetWindow, reinterpret_cast<LPARAM>(&foundWindow));
130+
131+
if (foundWindow != expectExist)
43132
{
44-
std::cout << "CoreApplication property `" << winrt::to_string(item) << "` was not in expected state [" << (expectExist ? "should exist" : "should not exist") << "]\n";
133+
std::cout << "WinGet Window `WingetMessageOnlyWindow` was not in expected state [" << (expectExist ? "should exist" : "should not exist") << "]\n";
45134
result = false;
46135
}
136+
137+
return result;
47138
}
139+
}
48140

49-
// Shutdown monitoring window
50-
bool foundWindow = false;
51-
EnumWindows(CheckForWinGetWindow, reinterpret_cast<LPARAM>(&foundWindow));
141+
TestParameters::TestParameters(int argc, const char** argv)
142+
{
143+
for (int i = 0; i < argc; ++i)
144+
{
145+
if ("-test"sv == argv[i])
146+
{
147+
ADVANCE_ARG_PARAMETER
148+
TestToRun = ToLower(argv[i]);
149+
}
150+
else if ("-com"sv == argv[i])
151+
{
152+
ADVANCE_ARG_PARAMETER
153+
ComInit = ParseComInitializationType(argv[i]);
154+
}
155+
else if ("-leak-com"sv == argv[i])
156+
{
157+
LeakCOM = true;
158+
}
159+
else if ("-itr"sv == argv[i])
160+
{
161+
ADVANCE_ARG_PARAMETER
162+
Iterations = atoi(argv[i]);
163+
}
164+
else if ("-pkg"sv == argv[i])
165+
{
166+
ADVANCE_ARG_PARAMETER
167+
PackageName = argv[i];
168+
}
169+
else if ("-unload"sv == argv[i])
170+
{
171+
ADVANCE_ARG_PARAMETER
172+
UnloadBehavior = ParseUnloadBehavior(argv[i]);
173+
}
174+
else if ("-activation"sv == argv[i])
175+
{
176+
ADVANCE_ARG_PARAMETER
177+
ActivationType = ParseActivationType(argv[i]);
178+
}
179+
else if ("-clear-factories"sv == argv[i])
180+
{
181+
ClearFactories = true;
182+
}
183+
}
184+
}
185+
186+
void TestParameters::OutputDetails() const
187+
{
188+
std::cout << "Running inproc testbed with:\n"
189+
" COM Init : " << ComInit << "\n"
190+
" Activate : " << ActivationType << "\n"
191+
" Clear : " << std::boolalpha << ClearFactories << "\n"
192+
" Leak COM : " << std::boolalpha << LeakCOM << "\n"
193+
" Unload : " << UnloadBehavior << "\n"
194+
" Test : " << TestToRun << "\n"
195+
" Package : " << PackageName << "\n"
196+
" Passes : " << Iterations << std::endl;
197+
}
198+
199+
bool TestParameters::InitializeTestState() const
200+
{
201+
HRESULT hr = S_OK;
52202

53-
if (foundWindow != expectExist)
203+
if (ComInitializationType::STA == ComInit)
54204
{
55-
std::cout << "WinGet Window `WingetMessageOnlyWindow` was not in expected state [" << (expectExist ? "should exist" : "should not exist") << "]\n";
56-
result = false;
205+
hr = RoInitialize(RO_INIT_SINGLETHREADED);
206+
}
207+
else if (ComInitializationType::MTA == ComInit)
208+
{
209+
hr = RoInitialize(RO_INIT_MULTITHREADED);
57210
}
58211

59-
return result;
212+
if (FAILED(hr))
213+
{
214+
std::cout << "RoInitialize returned " << hr << std::endl;
215+
return false;
216+
}
217+
218+
if (UnloadBehavior::Never == UnloadBehavior || UnloadBehavior::AtExit == UnloadBehavior)
219+
{
220+
SetUnloadPreference(false);
221+
}
222+
223+
return true;
224+
}
225+
226+
std::unique_ptr<ITest> TestParameters::CreateTest() const
227+
{
228+
if ("unload_check"sv == TestToRun)
229+
{
230+
return std::make_unique<UnloadAndCheckForLeaks>(*this);
231+
}
232+
233+
return {};
234+
}
235+
236+
void TestParameters::UninitializeTestState() const
237+
{
238+
if (!LeakCOM)
239+
{
240+
RoUninitialize();
241+
}
242+
243+
if (UnloadBehavior::AtExit == UnloadBehavior)
244+
{
245+
SetUnloadPreference(true);
246+
}
247+
}
248+
249+
bool TestParameters::UnloadExpected() const
250+
{
251+
bool shouldUnload = true;
252+
if (UnloadBehavior::Never == UnloadBehavior || UnloadBehavior::AtExit == UnloadBehavior)
253+
{
254+
shouldUnload = false;
255+
}
256+
return shouldUnload;
60257
}
61258

62259
Snapshot::Snapshot()
@@ -97,7 +294,7 @@ Snapshot::Snapshot()
97294
CloseHandle(snapshot);
98295
}
99296

100-
UnloadAndCheckForLeaks::UnloadAndCheckForLeaks(bool shouldUnload) : m_shouldUnload(shouldUnload)
297+
UnloadAndCheckForLeaks::UnloadAndCheckForLeaks(const TestParameters& parameters) : m_parameters(parameters)
101298
{
102299
}
103300

@@ -114,7 +311,7 @@ bool UnloadAndCheckForLeaks::RunIteration()
114311

115312
m_iterationSnapshots.emplace_back(beforeUnload, Snapshot{});
116313

117-
if (!SearchForWellKnownObjects(!m_shouldUnload))
314+
if (!SearchForWellKnownObjects(!m_parameters.UnloadExpected()))
118315
{
119316
return false;
120317
}

0 commit comments

Comments
 (0)