[CRT_APITEST]
[reactos.git] / rostests / apitests / crt / static_construct.cpp
1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for static C++ object construction
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 * Mark Jansen
7 */
8
9 #include <apitest.h>
10 #include <strsafe.h>
11 #include "dll_startup.h"
12
13 extern "C"
14 {
15 extern int static_init_counter;
16
17 static int static_init_counter_at_startup;
18 static int static_construct_counter_at_startup;
19 static int m_uninit_at_startup;
20
21 int static_construct_counter = 789;
22 }
23
24 static struct init_static
25 {
26 int m_uninit;
27 int m_counter;
28
29 init_static() :
30 m_counter(2)
31 {
32 static_init_counter_at_startup = static_init_counter;
33 static_construct_counter_at_startup = static_construct_counter;
34 m_uninit_at_startup = m_uninit;
35 static_construct_counter++;
36 m_uninit++;
37 }
38 } init_static;
39
40 static
41 VOID
42 TestInitStatic(VOID)
43 {
44 ok(static_init_counter_at_startup == 123, "static_init_counter at startup: %d\n", static_init_counter_at_startup);
45 ok(static_construct_counter_at_startup == 789, "static_construct_counter at startup: %d\n", static_construct_counter_at_startup);
46 ok(m_uninit_at_startup == 0, "init_static.m_uninit at startup: %d\n", m_uninit_at_startup);
47
48 ok(static_init_counter == 123, "static_init_counter: %d\n", static_init_counter);
49
50 ok(static_construct_counter == 790, "static_construct_counter: %d\n", static_construct_counter);
51 ok(init_static.m_counter == 2, "init_static.m_counter: %d\n", init_static.m_counter);
52 ok(init_static.m_uninit == 1, "init_static.m_uninit: %d\n", init_static.m_uninit);
53 }
54
55 static
56 VOID
57 TestDllStartup(VOID)
58 {
59 #if defined(TEST_MSVCRT)
60 const PCWSTR DllName = L"msvcrt_crt_dll_startup.dll";
61 #elif defined(TEST_STATIC_CRT)
62 const PCWSTR DllName = L"static_crt_dll_startup.dll";
63 #else
64 #error This test only makes sense for static CRT and msvcrt.dll
65 #endif
66 WCHAR DllPath[MAX_PATH];
67 GetModuleFileNameW(NULL, DllPath, _countof(DllPath));
68 wcsrchr(DllPath, L'\\')[1] = UNICODE_NULL;
69 StringCchCatW(DllPath, _countof(DllPath), DllName);
70
71 HMODULE hDll = LoadLibraryW(DllPath);
72 if (hDll == NULL)
73 {
74 skip("Helper dll not found\n");
75 return;
76 }
77 SET_COUNTER_VALUES_POINTER *pSetCounterValuesPointer = reinterpret_cast<SET_COUNTER_VALUES_POINTER*>(GetProcAddress(hDll, "SetCounterValuesPointer"));
78 if (pSetCounterValuesPointer == NULL)
79 {
80 skip("Helper function not found\n");
81 FreeLibrary(hDll);
82 return;
83 }
84 counter_values values;
85 pSetCounterValuesPointer(&values);
86 ok(values.m_uninit_at_startup == 0, "m_uninit_at_startup = %d\n", values.m_uninit_at_startup);
87 ok(values.m_uninit == 1, "m_uninit = %d\n", values.m_uninit);
88 ok(values.m_counter == 2, "m_counter = %d\n", values.m_counter);
89 ok(values.static_construct_counter_at_startup == 5656, "static_construct_counter_at_startup = %d\n", values.static_construct_counter_at_startup);
90 ok(values.static_construct_counter == 5657, "static_construct_counter = %d\n", values.static_construct_counter);
91 ok(values.dtor_counter_at_detach == 0, "dtor_counter_at_detach = %d\n", values.dtor_counter_at_detach);
92 ok(values.dtor_counter == 0, "dtor_counter = %d\n", values.dtor_counter);
93 values.dtor_counter_at_detach = 78789;
94 values.dtor_counter = 7878;
95 FreeLibrary(hDll);
96 ok(values.m_uninit_at_startup == 0, "m_uninit_at_startup = %d\n", values.m_uninit_at_startup);
97 ok(values.m_uninit == 1, "m_uninit = %d\n", values.m_uninit);
98 ok(values.m_counter == 2, "m_counter = %d\n", values.m_counter);
99 ok(values.static_construct_counter_at_startup == 5656, "static_construct_counter_at_startup = %d\n", values.static_construct_counter_at_startup);
100 ok(values.static_construct_counter == 5657, "static_construct_counter = %d\n", values.static_construct_counter);
101 ok(values.dtor_counter_at_detach == 7878, "dtor_counter_at_detach = %d\n", values.dtor_counter_at_detach);
102 ok(values.dtor_counter == 7879, "dtor_counter = %d\n", values.dtor_counter);
103 }
104
105 struct shared_memory
106 {
107 int init_count;
108 int uninit_count;
109 };
110
111 static HANDLE g_FileMapping = NULL;
112 static BOOL g_CreatedFileMapping = FALSE;
113 static shared_memory* g_Memory = NULL;
114
115 #define MAPPING_NAME L"crt_apitest_static_construct"
116
117 static void map_memory()
118 {
119 if (g_FileMapping)
120 return;
121
122 g_FileMapping = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, MAPPING_NAME);
123 if (g_FileMapping)
124 {
125 g_CreatedFileMapping = FALSE;
126 }
127 else
128 {
129 g_FileMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shared_memory), MAPPING_NAME);
130 g_CreatedFileMapping = TRUE;
131 }
132 if (g_FileMapping == NULL)
133 {
134 skip("Could not map shared memory\n");
135 return;
136 }
137 g_Memory = static_cast<shared_memory*>(MapViewOfFile(g_FileMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(shared_memory)));
138 if (g_Memory == NULL)
139 {
140 skip("Could not map view of shared memory\n");
141 CloseHandle(g_FileMapping);
142 g_FileMapping = NULL;
143 }
144 if (g_CreatedFileMapping)
145 ZeroMemory(g_Memory, sizeof(shared_memory));
146 }
147
148 static void unmap_memory()
149 {
150 // we do not clean the mapping in the child, since we want to count all dtor's!
151 if (g_FileMapping && g_CreatedFileMapping)
152 {
153 UnmapViewOfFile(g_Memory);
154 CloseHandle(g_FileMapping);
155 g_Memory = NULL;
156 g_FileMapping = NULL;
157 }
158 }
159
160 static struct shared_mem_static
161 {
162 shared_mem_static()
163 {
164 map_memory();
165 if (g_Memory)
166 g_Memory->init_count++;
167 }
168
169 ~shared_mem_static()
170 {
171 if (g_Memory)
172 g_Memory->uninit_count++;
173 unmap_memory();
174 }
175
176 } shared_mem_static;
177
178 static
179 VOID
180 TestStaticDestruct(VOID)
181 {
182 ok(g_Memory != NULL, "Expected the mapping to be in place\n");
183 ok(g_CreatedFileMapping == TRUE, "Expected to create a new shared section!\n");
184 if (g_Memory == NULL)
185 {
186 skip("Can't proceed without file mapping\n");
187 return;
188 }
189 ok(g_Memory->init_count == 1, "Expected init_count to be 1, was: %d\n", g_Memory->init_count);
190 ok(g_Memory->uninit_count == 0, "Expected uninit_count to be 0, was: %d\n", g_Memory->uninit_count);
191
192 WCHAR path[MAX_PATH];
193 // we just need an extra argument to tell the test it's only running to increment the dtor count :)
194 GetModuleFileNameW(NULL, path, _countof(path));
195 WCHAR buf[MAX_PATH+40];
196 StringCchPrintfW(buf, _countof(buf), L"\"%ls\" static_construct dummy", path);
197
198 STARTUPINFOW si = { sizeof(si) };
199 PROCESS_INFORMATION pi;
200 BOOL created = CreateProcessW(NULL, buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
201 ok(created, "Expected CreateProcess to succeed\n");
202 if (created)
203 {
204 winetest_wait_child_process(pi.hProcess);
205 CloseHandle(pi.hThread);
206 CloseHandle(pi.hProcess);
207 ok(g_Memory->init_count == 2, "Expected init_count to be 2, was: %d\n", g_Memory->init_count);
208 ok(g_Memory->uninit_count == 1, "Expected uninit_count to be 1, was: %d\n", g_Memory->uninit_count);
209 }
210 }
211
212 START_TEST(static_construct)
213 {
214 char **argv;
215 int argc = winetest_get_mainargs(&argv);
216
217 if (argc >= 3)
218 {
219 // we are just here to increment the reference count in the shared section!
220 ok(g_Memory != NULL, "Expected the shared memory to be mapped!\n");
221 ok(g_CreatedFileMapping == FALSE, "Expected the shared memory to be created by my parent!\n");
222 return;
223 }
224
225 TestInitStatic();
226 TestDllStartup();
227 TestStaticDestruct();
228 }