VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTTraceLog.cpp@ 107044

Last change on this file since 107044 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.3 KB
Line 
1/* $Id: tstRTTraceLog.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTTraceLog.
4 */
5
6/*
7 * Copyright (C) 2018-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/tracelog.h>
42
43#include <iprt/err.h>
44#include <iprt/file.h>
45#include <iprt/mem.h>
46#include <iprt/string.h>
47#include <iprt/test.h>
48#include <iprt/time.h>
49
50
51/**
52 * Trace log buffer.
53 */
54typedef struct TSTRTTRACELOGBUF
55{
56 /** Size of the buffer. */
57 size_t cbBuf;
58 /** Current write offset. */
59 size_t offBuf;
60 /** Streamed data - variable in size. */
61 uint8_t abBuf[1];
62} TSTRTTRACELOGBUF;
63/** Pointer to a trace log buffer. */
64typedef TSTRTTRACELOGBUF *PTSTRTTRACELOGBUF;
65
66
67/**
68 * Structure matching the event descriptor.
69 */
70typedef struct RTTESTTRACELOGEVTDATA
71{
72 /** Test pointer. */
73 uintptr_t ptr;
74 /** Test size_t value. */
75 size_t sz;
76 /** Test 32bit value. */
77 uint32_t u32;
78 /** Test boolean. */
79 bool f;
80 /** Test raw data. */
81 uint8_t abRaw[42];
82} RTTESTTRACELOGEVTDATA;
83/** Pointer to event data. */
84typedef RTTESTTRACELOGEVTDATA *PRTTESTTRACELOGEVTDATA;
85
86
87/**
88 * Test event item descriptor.
89 */
90static RTTRACELOGEVTITEMDESC g_EvtItemDesc[] =
91{
92 {"TestPtr", NULL, RTTRACELOGTYPE_POINTER, 0},
93 {"TestSz", NULL, RTTRACELOGTYPE_SIZE, 0},
94 {"TestU32", NULL, RTTRACELOGTYPE_UINT32, 0},
95 {"TestBool", "This is a test description", RTTRACELOGTYPE_BOOL, 0},
96 {"TestRawStatic", NULL, RTTRACELOGTYPE_RAWDATA, 42}
97};
98
99
100/**
101 * Test event descriptor.
102 */
103static RTTRACELOGEVTDESC g_EvtDesc =
104{
105 "idTest",
106 "This is a test event",
107 RTTRACELOGEVTSEVERITY_INFO,
108 RT_ELEMENTS(g_EvtItemDesc),
109 g_EvtItemDesc
110};
111
112
113
114/**
115 * Allocates a new buffer for the raw trace log stream.
116 *
117 * @returns IPRT status code.
118 * @param cbBuf Size of the buffer in bytes.
119 * @param ppBuf Where to store the pointer to the buffer on success.
120 */
121static int tstRTTraceLogBufAlloc(size_t cbBuf, PTSTRTTRACELOGBUF *ppBuf)
122{
123 PTSTRTTRACELOGBUF pBuf = (PTSTRTTRACELOGBUF)RTMemAllocZ(RT_UOFFSETOF_DYN(TSTRTTRACELOGBUF, abBuf[cbBuf]));
124 if (RT_LIKELY(pBuf))
125 {
126 pBuf->cbBuf = cbBuf;
127 pBuf->offBuf = 0;
128 *ppBuf = pBuf;
129 return VINF_SUCCESS;
130 }
131
132 return VERR_NO_MEMORY;
133}
134
135
136/**
137 * @copydoc{FNRTTRACELOGWRSTREAM}
138 */
139static DECLCALLBACK(int) tstRTTraceLogStreamOut(void *pvUser, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
140{
141 PTSTRTTRACELOGBUF pBuf = (PTSTRTTRACELOGBUF)pvUser;
142
143 if (pBuf)
144 {
145 size_t cbWrite = RT_MIN(cbBuf, pBuf->cbBuf - pBuf->offBuf);
146 if ( cbWrite != 0
147 && ( cbWrite >= cbBuf
148 || pcbWritten))
149 {
150 memcpy(&pBuf->abBuf[pBuf->offBuf], pvBuf, cbWrite);
151 pBuf->offBuf += cbWrite;
152 if (pcbWritten)
153 *pcbWritten = cbWrite;
154 return VINF_SUCCESS;
155 }
156
157 return VERR_DISK_FULL;
158 }
159
160 /* Benchmark mode, forget everything immediately. */
161 return VINF_SUCCESS;
162}
163
164
165/**
166 * @copydoc{FNRTTRACELOGRDRSTREAM}
167 */
168static DECLCALLBACK(int) tstRTTraceLogStreamIn(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbRead,
169 RTMSINTERVAL cMsTimeout)
170{
171 RT_NOREF(cMsTimeout);
172 PTSTRTTRACELOGBUF pBuf = (PTSTRTTRACELOGBUF)pvUser;
173
174 size_t cbRead = RT_MIN(cbBuf, pBuf->cbBuf - pBuf->offBuf);
175 if ( cbRead != 0
176 && ( cbRead >= cbBuf
177 || pcbRead))
178 {
179 memcpy(pvBuf, &pBuf->abBuf[pBuf->offBuf], cbRead);
180 pBuf->offBuf += cbRead;
181 if (pcbRead)
182 *pcbRead = cbRead;
183 return VINF_SUCCESS;
184 }
185
186 return VERR_EOF;
187}
188
189
190/**
191 * @copydoc{FNRTTRACELOGSTREAMCLOSE}
192 */
193static DECLCALLBACK(int) tstRTTraceLogStreamClose(void *pvUser)
194{
195 RT_NOREF(pvUser);
196 return VINF_SUCCESS;
197}
198
199
200static PTSTRTTRACELOGBUF tstRTTraceLogWriter(void)
201{
202 RTTRACELOGWR hTraceLogWr = NIL_RTTRACELOGWR;
203 PTSTRTTRACELOGBUF pLogBuf = NULL;
204 RTTESTTRACELOGEVTDATA EvtData;
205
206 EvtData.ptr = (uintptr_t)&EvtData;
207 EvtData.sz = 0xdeadcafe;
208 EvtData.u32 = 0;
209 EvtData.f = true;
210 memset(&EvtData.abRaw[0], 0x42, sizeof(EvtData.abRaw));
211
212 /*
213 * Bad set pointer and handle values.
214 */
215 RTTestSub(NIL_RTTEST, "Writer");
216 RTTESTI_CHECK_RC(RTTraceLogWrCreate(NULL, NULL, NULL, NULL, NULL), VERR_INVALID_POINTER);
217 RTTESTI_CHECK_RC(RTTraceLogWrCreate(&hTraceLogWr, NULL, NULL, NULL, NULL), VERR_INVALID_POINTER);
218 RTTRACELOGWR hTraceLogWrInvl = (RTTRACELOGWR)(intptr_t)-3;
219 RTTESTI_CHECK_RC(RTTraceLogWrDestroy(hTraceLogWrInvl), VERR_INVALID_HANDLE);
220 RTTESTI_CHECK_RC(RTTraceLogWrAddEvtDesc(hTraceLogWr, NULL), VERR_INVALID_HANDLE);
221 RTTESTI_CHECK_RC(RTTraceLogWrEvtAdd(hTraceLogWr, NULL, 0, 0, 0, NULL, NULL), VERR_INVALID_HANDLE);
222
223 RTTESTI_CHECK_RC_RET(tstRTTraceLogBufAlloc(_4K, &pLogBuf), VINF_SUCCESS, NULL);
224 RTTESTI_CHECK_RC_RET(RTTraceLogWrCreate(&hTraceLogWr, NULL, tstRTTraceLogStreamOut,
225 tstRTTraceLogStreamClose, pLogBuf), VINF_SUCCESS, NULL);
226 RTTESTI_CHECK_RC_RET(RTTraceLogWrAddEvtDesc(hTraceLogWr, &g_EvtDesc), VINF_SUCCESS, NULL);
227 RTTESTI_CHECK_RC_RET(RTTraceLogWrAddEvtDesc(hTraceLogWr, &g_EvtDesc), VERR_ALREADY_EXISTS, NULL);
228 RTTESTI_CHECK_RC_RET(RTTraceLogWrEvtAdd(hTraceLogWr, &g_EvtDesc, 0, 0, 0, &EvtData, NULL), VINF_SUCCESS, NULL);
229 RTTESTI_CHECK_RC_RET(RTTraceLogWrDestroy(hTraceLogWr), VINF_SUCCESS, NULL);
230
231 return pLogBuf;
232}
233
234
235static void tstRTTraceLogWriterBenchmark(void)
236{
237 RTTRACELOGWR hTraceLogWr = NIL_RTTRACELOGWR;
238 RTTESTTRACELOGEVTDATA EvtData;
239
240 EvtData.ptr = (uintptr_t)&EvtData;
241 EvtData.sz = 0xdeadcafe;
242 EvtData.u32 = 0;
243 EvtData.f = true;
244 memset(&EvtData.abRaw[0], 0x42, sizeof(EvtData.abRaw));
245
246 RTTestSub(NIL_RTTEST, "Writer Benchmark");
247 RTTESTI_CHECK_RC_RETV(RTTraceLogWrCreate(&hTraceLogWr, NULL, tstRTTraceLogStreamOut,
248 tstRTTraceLogStreamClose, NULL), VINF_SUCCESS);
249 RTTESTI_CHECK_RC_RETV(RTTraceLogWrAddEvtDesc(hTraceLogWr, &g_EvtDesc), VINF_SUCCESS);
250
251 uint64_t tsStart = RTTimeNanoTS();
252 for (uint32_t i = 0; i < 1000000; i++)
253 {
254 RTTESTI_CHECK_RC_BREAK(RTTraceLogWrEvtAdd(hTraceLogWr, &g_EvtDesc, 0, 0, 0, &EvtData, NULL), VINF_SUCCESS);
255 }
256 uint64_t tsRuntime = RTTimeNanoTS() - tsStart;
257 RTTestValue(NIL_RTTEST, "RTTraceLogWrEvtAdd()", tsRuntime / 1000000, RTTESTUNIT_NS_PER_CALL);
258 RTTESTI_CHECK_RC(RTTraceLogWrDestroy(hTraceLogWr), VINF_SUCCESS);
259}
260
261static void tstRTTraceLogReader(PTSTRTTRACELOGBUF pLogBuf)
262{
263 RTTRACELOGRDRPOLLEVT enmEvt = RTTRACELOGRDRPOLLEVT_INVALID;
264 RTTRACELOGRDR hTraceLogRdr = NIL_RTTRACELOGRDR;
265
266 RTTestSub(NIL_RTTEST, "Reader");
267
268 /*
269 * Bad set pointer and handle values.
270 */
271 RTTESTI_CHECK_RC(RTTraceLogRdrCreate(NULL, NULL, NULL, NULL), VERR_INVALID_POINTER);
272 RTTESTI_CHECK_RC(RTTraceLogRdrCreate(&hTraceLogRdr, NULL, NULL, NULL), VERR_INVALID_POINTER);
273 RTTRACELOGRDR hTraceLogRdrInvl = (RTTRACELOGRDR)(intptr_t)-3;
274 RTTESTI_CHECK_RC(RTTraceLogRdrDestroy(hTraceLogRdrInvl), VERR_INVALID_HANDLE);
275 RTTESTI_CHECK_RC(RTTraceLogRdrEvtPoll(hTraceLogRdrInvl, NULL, RT_INDEFINITE_WAIT), VERR_INVALID_HANDLE);
276
277 /*
278 * Test with log buffer created previously.
279 */
280 RTTESTI_CHECK_RC_RETV(RTTraceLogRdrCreate(&hTraceLogRdr, tstRTTraceLogStreamIn, tstRTTraceLogStreamClose, pLogBuf),
281 VINF_SUCCESS);
282 RTTESTI_CHECK_RC_RETV(RTTraceLogRdrEvtPoll(hTraceLogRdr, &enmEvt, RT_INDEFINITE_WAIT), VINF_SUCCESS);
283 RTTESTI_CHECK_RETV(enmEvt == RTTRACELOGRDRPOLLEVT_HDR_RECVD);
284 RTTESTI_CHECK_RC_RETV(RTTraceLogRdrEvtPoll(hTraceLogRdr, &enmEvt, RT_INDEFINITE_WAIT), VINF_SUCCESS);
285 RTTESTI_CHECK_RETV(enmEvt == RTTRACELOGRDRPOLLEVT_TRACE_EVENT_RECVD);
286 RTTESTI_CHECK_RC_RETV(RTTraceLogRdrDestroy(hTraceLogRdr), VINF_SUCCESS);
287}
288
289
290int main()
291{
292 RTTEST hTest;
293 int rc = RTTestInitAndCreate("tstRTTraceLog", &hTest);
294 if (rc)
295 return rc;
296 RTTestBanner(hTest);
297
298 /*
299 * The tests.
300 */
301 bool fMayPanic = RTAssertMayPanic();
302 bool fQuiet = RTAssertAreQuiet();
303 RTAssertSetMayPanic(false);
304 RTAssertSetQuiet(true);
305 PTSTRTTRACELOGBUF pLogBuf = tstRTTraceLogWriter();
306 if (RTTestErrorCount(hTest) == 0)
307 {
308 pLogBuf->offBuf = 0;
309 tstRTTraceLogReader(pLogBuf);
310 }
311 RTMemFree(pLogBuf);
312 tstRTTraceLogWriterBenchmark();
313 RTAssertSetQuiet(fQuiet);
314 RTAssertSetMayPanic(fMayPanic);
315
316 /*
317 * Summary.
318 */
319 return RTTestSummaryAndDestroy(hTest);
320}
321
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette