ReactOS 0.4.16-dev-2332-g4cba65d
perf.c
Go to the documentation of this file.
1/*
2 * Unit tests for Perflib functions
3 *
4 * Copyright (c) 2021 Paul Gofman for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdarg.h>
22
23#include "windef.h"
24#include "winbase.h"
25#include "winerror.h"
26#include "perflib.h"
27#include "winperf.h"
28#include "winternl.h"
29
30#include "wine/test.h"
31
32#include "initguid.h"
33
34ULONG (WINAPI *pPerfCloseQueryHandle)(HANDLE);
35ULONG (WINAPI *pPerfOpenQueryHandle)(const WCHAR*, HANDLE*);
37ULONG (WINAPI *pPerfQueryCounterData)(HANDLE, PERF_DATA_HEADER*, DWORD, DWORD*);
38
39static void init_functions(void)
40{
41 HANDLE hadvapi = GetModuleHandleA("advapi32.dll");
42
43#define GET_FUNCTION(name) p##name = (void *)GetProcAddress(hadvapi, #name)
48#undef GET_FUNCTION
49}
50
52{
53 ok(0, "Provider callback called.\n");
54 return ERROR_SUCCESS;
55}
56
58{
59#ifdef __REACTOS__
60 skip("test_provider_init() can't be built until ReactOS has implementations for Perf* functions.\n");
61#else
62 static GUID test_set_guid = {0xdeadbeef, 0x0002, 0x0003, {0x0f, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00 ,0x0a}};
63 static GUID test_set_guid2 = {0xdeadbeef, 0x0003, 0x0003, {0x0f, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00 ,0x0a}};
64 static GUID test_guid = {0xdeadbeef, 0x0001, 0x0002, {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00 ,0x0a}};
65 static struct
66 {
67 PERF_COUNTERSET_INFO counterset;
69 }
70 pc_template =
71 {
72 {{0}},
73 {
75 PERF_DETAIL_NOVICE, 0, 0xdeadbeef},
77 PERF_DETAIL_NOVICE, 0, 0xdeadbeef},
78 },
79 };
80
82 PERF_PROVIDER_CONTEXT prov_context;
83 UINT64 counter1, counter2;
84 HANDLE prov, prov2;
85 ULONG ret, size;
86 BOOL bret;
87
88 prov = (HANDLE)0xdeadbeef;
90 ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
91 ok(prov == (HANDLE)0xdeadbeef, "Got unexpected prov %p.\n", prov);
92
93 prov = (HANDLE)0xdeadbeef;
95 ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
96 ok(prov == (HANDLE)0xdeadbeef, "Got unexpected prov %p.\n", prov);
97
98 prov = (HANDLE)0xdeadbeef;
99 ret = PerfStartProvider(&test_guid, test_provider_callback, &prov);
100 ok(!ret, "Got unexpected ret %lu.\n", ret);
101 ok(prov != (HANDLE)0xdeadbeef, "Provider handle is not set.\n");
102
103 prov2 = prov;
104 ret = PerfStartProvider(&test_guid, test_provider_callback, &prov2);
105 ok(!ret, "Got unexpected ret %lu.\n", ret);
106 ok(prov2 != prov, "Got the same provider handle.\n");
107
108 ret = PerfStopProvider(prov2);
109 ok(!ret, "Got unexpected ret %lu.\n", ret);
110
111 if (0)
112 {
113 /* Access violation on Windows. */
114 PerfStopProvider(prov2);
115 }
116
117 /* Provider handle is a pointer and not a kernel object handle. */
119 ok(!bret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected bret %d, err %lu.\n", bret, GetLastError());
120 bret = IsBadWritePtr(prov, 8);
121 ok(!bret, "Handle does not point to the data.\n");
122
123 pc_template.counterset.CounterSetGuid = test_set_guid;
124 pc_template.counterset.ProviderGuid = test_guid;
125 pc_template.counterset.NumCounters = 0;
126 pc_template.counterset.InstanceType = PERF_COUNTERSET_SINGLE_INSTANCE;
127 ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template.counterset));
128 ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
129
130 pc_template.counterset.CounterSetGuid = test_set_guid;
131 pc_template.counterset.ProviderGuid = test_guid;
132 pc_template.counterset.NumCounters = 2;
133 pc_template.counterset.InstanceType = PERF_COUNTERSET_SINGLE_INSTANCE;
134 ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
135 ok(!ret, "Got unexpected ret %lu.\n", ret);
136
137 pc_template.counterset.CounterSetGuid = test_set_guid2;
138 /* Looks like ProviderGuid doesn't need to match provider. */
139 pc_template.counterset.ProviderGuid = test_set_guid;
140 pc_template.counterset.NumCounters = 1;
141 pc_template.counterset.InstanceType = PERF_COUNTERSET_SINGLE_INSTANCE;
142 ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
143 ok(!ret, "Got unexpected ret %lu.\n", ret);
144
145 ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
146 ok(ret == ERROR_ALREADY_EXISTS, "Got unexpected ret %lu.\n", ret);
147
148 SetLastError(0xdeadbeef);
149 instance = PerfCreateInstance(prov, NULL, L"1", 1);
150 ok(!instance, "Got unexpected instance %p.\n", instance);
151 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %lu.\n", GetLastError());
152
153 SetLastError(0xdeadbeef);
154 instance = PerfCreateInstance(prov, &test_guid, L"1", 1);
155 ok(!instance, "Got unexpected instance %p.\n", instance);
156 ok(GetLastError() == ERROR_NOT_FOUND, "Got unexpected error %lu.\n", GetLastError());
157
158 SetLastError(0xdeadbeef);
159 instance = PerfCreateInstance(prov, &test_guid, NULL, 1);
160 ok(!instance, "Got unexpected instance %p.\n", instance);
161 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %lu.\n", GetLastError());
162
163 SetLastError(0xdeadbeef);
164 instance = PerfCreateInstance(prov, &test_set_guid, L"11", 1);
165 ok(!!instance, "Got NULL instance.\n");
166 ok(GetLastError() == 0xdeadbeef, "Got unexpected error %lu.\n", GetLastError());
167 ok(instance->InstanceId == 1, "Got unexpected InstanceId %lu.\n", instance->InstanceId);
168 ok(instance->InstanceNameSize == 6, "Got unexpected InstanceNameSize %lu.\n", instance->InstanceNameSize);
169 ok(IsEqualGUID(&instance->CounterSetGuid, &test_set_guid), "Got unexpected guid %s.\n",
170 debugstr_guid(&instance->CounterSetGuid));
171
172 ok(instance->InstanceNameOffset == sizeof(*instance) + sizeof(UINT64) * 2,
173 "Got unexpected InstanceNameOffset %lu.\n", instance->InstanceNameOffset);
174 ok(!lstrcmpW((WCHAR *)((BYTE *)instance + instance->InstanceNameOffset), L"11"),
175 "Got unexpected instance name %s.\n",
176 debugstr_w((WCHAR *)((BYTE *)instance + instance->InstanceNameOffset)));
177 size = ((sizeof(*instance) + sizeof(UINT64) * 2 + instance->InstanceNameSize) + 7) & ~7;
178 ok(size == instance->dwSize, "Got unexpected size %lu, instance->dwSize %lu.\n", size, instance->dwSize);
179
180 ret = PerfSetCounterRefValue(prov, instance, 1, &counter1);
181 ok(!ret, "Got unexpected ret %lu.\n", ret);
182 ret = PerfSetCounterRefValue(prov, instance, 2, &counter2);
183 ok(!ret, "Got unexpected ret %lu.\n", ret);
184
185 ret = PerfSetCounterRefValue(prov, instance, 0, &counter2);
186 ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %lu.\n", ret);
187
188 ok(*(void **)(instance + 1) == &counter1, "Got unexpected counter value %p.\n",
189 *(void **)(instance + 1));
190 ok(*(void **)((BYTE *)instance + sizeof(*instance) + sizeof(UINT64)) == &counter2,
191 "Got unexpected counter value %p.\n", *(void **)(instance + 1));
192
194 ok(!ret, "Got unexpected ret %lu.\n", ret);
195
196 ret = PerfStopProvider(prov);
197 ok(!ret, "Got unexpected ret %lu.\n", ret);
198
199 memset( &prov_context, 0, sizeof(prov_context) );
200 prov = (HANDLE)0xdeadbeef;
201 ret = PerfStartProviderEx( &test_guid, &prov_context, &prov );
202 ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
203 ok(prov == (HANDLE)0xdeadbeef, "Got unexpected prov %p.\n", prov);
204
205 prov_context.ContextSize = sizeof(prov_context) + 1;
206 ret = PerfStartProviderEx( &test_guid, &prov_context, &prov );
207 ok(!ret, "Got unexpected ret %lu.\n", ret);
208 ok(prov != (HANDLE)0xdeadbeef, "Provider handle is not set.\n");
209
210 ret = PerfStopProvider(prov);
211 ok(!ret, "Got unexpected ret %lu.\n", ret);
212#endif
213}
214
215DEFINE_GUID(TestCounterGUID, 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33);
216
218{
219 return (t / 10000) * 10000;
220}
221
222static void test_perf_counters(void)
223{
224 LARGE_INTEGER freq, qpc1, qpc2, nttime1, nttime2, systime;
225 char buffer[sizeof(PERF_COUNTER_IDENTIFIER) + 8];
226 PERF_COUNTER_IDENTIFIER *counter_id;
229 DWORD size;
230 ULONG ret;
231
232 if (!pPerfOpenQueryHandle)
233 {
234 win_skip("PerfOpenQueryHandle not found.\n");
235 return;
236 }
237
238 ret = pPerfOpenQueryHandle(NULL, NULL);
239 ok(ret == ERROR_INVALID_PARAMETER, "got ret %lu.\n", ret);
240 ret = pPerfOpenQueryHandle(NULL, &query);
241 ok(!ret, "got ret %lu.\n", ret);
242
243 counter_id = (PERF_COUNTER_IDENTIFIER *)buffer;
244 memset(buffer, 0, sizeof(buffer));
245
246 counter_id->CounterSetGuid = TestCounterGUID;
247 counter_id->CounterId = PERF_WILDCARD_COUNTER;
248 counter_id->InstanceId = PERF_WILDCARD_COUNTER;
249
250 ret = pPerfAddCounters(query, counter_id, sizeof(*counter_id));
251 ok(ret == ERROR_INVALID_PARAMETER, "got ret %lu.\n", ret);
252
253 counter_id->Size = sizeof(*counter_id);
254 ret = pPerfAddCounters(query, counter_id, 8);
255 ok(ret == ERROR_INVALID_PARAMETER, "got ret %lu.\n", ret);
256 ret = pPerfAddCounters(query, counter_id, sizeof(*counter_id));
257 ok(!ret, "got ret %lu.\n", ret);
258 ok(counter_id->Status == ERROR_WMI_GUID_NOT_FOUND, "got Status %#lx.\n", counter_id->Status);
259
260 ret = pPerfQueryCounterData(query, NULL, 0, NULL);
261 ok(ret == ERROR_INVALID_PARAMETER, "got ret %lu.\n", ret);
262
263 size = 0xdeadbeef;
264 ret = pPerfQueryCounterData(query, NULL, 0, &size);
265 ok(ret == ERROR_NOT_ENOUGH_MEMORY, "got ret %lu.\n", ret);
266 ok(size == sizeof(dh), "got size %lu.\n", size);
267
268 ret = pPerfQueryCounterData(query, &dh, sizeof(dh), NULL);
269 ok(ret == ERROR_INVALID_PARAMETER, "got ret %lu.\n", ret);
270
273 NtQuerySystemTime(&nttime1);
274
275 size = 0xdeadbeef;
276 ret = pPerfQueryCounterData(query, &dh, sizeof(dh), &size);
278 NtQuerySystemTime(&nttime2);
279 SystemTimeToFileTime(&dh.SystemTime, (FILETIME *)&systime);
280 ok(!ret, "got ret %lu.\n", ret);
281 ok(size == sizeof(dh), "got size %lu.\n", size);
282 ok(dh.dwTotalSize == sizeof(dh), "got dwTotalSize %lu.\n", dh.dwTotalSize);
283 ok(!dh.dwNumCounters, "got dwNumCounters %lu.\n", dh.dwNumCounters);
284 ok(dh.PerfFreq == freq.QuadPart, "got PerfFreq %I64u.\n", dh.PerfFreq);
285 ok(dh.PerfTimeStamp >= qpc1.QuadPart && dh.PerfTimeStamp <= qpc2.QuadPart,
286 "got PerfTimeStamp %I64u, qpc1 %I64u, qpc2 %I64u.\n",
287 dh.PerfTimeStamp, qpc1.QuadPart, qpc2.QuadPart);
288 ok(dh.PerfTime100NSec >= nttime1.QuadPart && dh.PerfTime100NSec <= nttime2.QuadPart,
289 "got PerfTime100NSec %I64u, nttime1 %I64u, nttime2 %I64u.\n",
290 dh.PerfTime100NSec, nttime1.QuadPart, nttime2.QuadPart);
291 ok(systime.QuadPart >= trunc_nttime_ms(nttime1.QuadPart) && systime.QuadPart <= trunc_nttime_ms(nttime2.QuadPart),
292 "got systime %I64u, nttime1 %I64u, nttime2 %I64u, %d.\n",
293 systime.QuadPart, nttime1.QuadPart, nttime2.QuadPart, dh.SystemTime.wMilliseconds);
294
295 ret = pPerfCloseQueryHandle(query);
296 ok(!ret, "got ret %lu.\n", ret);
297}
298
300{
302
305}
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
static HINSTANCE instance
Definition: main.c:40
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define GetCurrentProcess()
Definition: compat.h:759
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
BOOL NTAPI IsBadWritePtr(IN LPVOID lp, IN UINT_PTR ucb)
Definition: except.c:883
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
BOOL WINAPI QueryPerformanceFrequency(OUT PLARGE_INTEGER lpFrequency)
Definition: perfcnt.c:45
BOOL WINAPI QueryPerformanceCounter(OUT PLARGE_INTEGER lpPerformanceCount)
Definition: perfcnt.c:23
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:158
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4152
ULONG WINAPI PerfStopProvider(HANDLE handle)
Definition: main.c:380
ULONG WINAPI PerfDeleteInstance(HANDLE provider, PERF_COUNTERSET_INSTANCE *block)
Definition: main.c:248
PERF_COUNTERSET_INSTANCE WINAPI * PerfCreateInstance(HANDLE handle, const GUID *guid, const WCHAR *name, ULONG id)
Definition: main.c:185
ULONG WINAPI PerfStartProvider(GUID *guid, PERFLIBREQUEST callback, HANDLE *provider)
Definition: main.c:340
ULONG WINAPI PerfSetCounterRefValue(HANDLE provider, PERF_COUNTERSET_INSTANCE *instance, ULONG counterid, void *address)
Definition: main.c:312
ULONG WINAPI PerfSetCounterSetInfo(HANDLE handle, PERF_COUNTERSET_INFO *template, ULONG size)
Definition: main.c:267
ULONG WINAPI PerfStartProviderEx(GUID *guid, PERF_PROVIDER_CONTEXT *context, HANDLE *provider)
Definition: main.c:356
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLdouble GLdouble t
Definition: gl.h:2047
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
#define win_skip
Definition: minitest.h:67
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
unsigned __int64 ULONG64
Definition: imports.h:198
NTSTATUS NTAPI NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
Definition: time.c:569
static void test_perf_counters(void)
Definition: perf.c:222
void test_provider_init(void)
Definition: perf.c:57
HANDLE PERF_COUNTER_IDENTIFIER DWORD
Definition: perf.c:36
static ULONG64 trunc_nttime_ms(ULONG64 t)
Definition: perf.c:217
PERF_DATA_HEADER DWORD *static void init_functions(void)
Definition: perf.c:39
static ULONG WINAPI test_provider_callback(ULONG code, void *buffer, ULONG size)
Definition: perf.c:51
#define GET_FUNCTION(name)
struct _PERF_COUNTER_INFO PERF_COUNTER_INFO
ULONG WINAPI PerfAddCounters(HANDLE, PERF_COUNTER_IDENTIFIER *, DWORD)
ULONG WINAPI PerfOpenQueryHandle(const WCHAR *, HANDLE *)
#define PERF_COUNTERSET_SINGLE_INSTANCE
Definition: perflib.h:43
ULONG WINAPI PerfQueryCounterData(HANDLE, PERF_DATA_HEADER *, DWORD, DWORD *)
#define PERF_ATTRIB_BY_REFERENCE
Definition: perflib.h:69
struct _PERF_COUNTER_IDENTIFIER PERF_COUNTER_IDENTIFIER
ULONG WINAPI PerfCloseQueryHandle(HANDLE)
#define PERF_WILDCARD_COUNTER
Definition: perflib.h:94
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
Definition: guiddef.h:68
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define memset(x, y, z)
Definition: compat.h:39
SYSTEMTIME SystemTime
Definition: perflib.h:103
LONGLONG PerfTime100NSec
Definition: perflib.h:101
LONGLONG PerfFreq
Definition: perflib.h:102
LONGLONG PerfTimeStamp
Definition: perflib.h:100
ULONG dwNumCounters
Definition: perflib.h:99
ULONG dwTotalSize
Definition: perflib.h:98
DWORD ContextSize
Definition: perflib.h:76
WORD wMilliseconds
Definition: minwinbase.h:263
Definition: inflate.c:139
PVOID HANDLE
Definition: typedefs.h:73
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WINAPI
Definition: msvc.h:6
#define ERROR_WMI_GUID_NOT_FOUND
Definition: winerror.h:1653
#define ERROR_NOT_FOUND
Definition: winerror.h:1014
#define PERF_DETAIL_NOVICE
Definition: winperf.h:48
#define PERF_COUNTER_COUNTER
Definition: winperf.h:52
#define DUPLICATE_SAME_ACCESS
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193