VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTR0Common.h@ 106579

Last change on this file since 106579 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: 8.4 KB
Line 
1/* $Id: tstRTR0Common.h 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT R0 Testcase - Common header.
4 */
5
6/*
7 * Copyright (C) 2010-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#ifndef IPRT_INCLUDED_SRC_testcase_tstRTR0Common_h
38#define IPRT_INCLUDED_SRC_testcase_tstRTR0Common_h
39#ifndef RT_WITHOUT_PRAGMA_ONCE
40# pragma once
41#endif
42
43#include <iprt/stdarg.h>
44#include <iprt/string.h>
45#include "tstRTR0CommonReq.h"
46
47
48/*******************************************************************************
49* Global Variables *
50*******************************************************************************/
51/** Global error buffer used by macros and inline functions in this file. */
52static char g_szErr[2048];
53/** The number of errors reported in this g_szErr. */
54static uint32_t volatile g_cErrors;
55
56
57/**
58 * Service request handler prolog.
59 *
60 * Returns if the input is invalid. Initializes the return packet as well as
61 * the globals (g_szErr, g_cErrors).
62 *
63 * @param pReqHdr The request packet header.
64 */
65#define RTR0TESTR0_SRV_REQ_PROLOG_RET(pReqHdr) \
66 do \
67 { \
68 if (!RT_VALID_PTR(pReqHdr)) \
69 return VERR_INVALID_PARAMETER; \
70 \
71 PRTTSTR0REQ pReq = (PRTTSTR0REQ)(pReqHdr); \
72 size_t cchErr = pReqHdr->cbReq - sizeof(pReq->Hdr); \
73 if (cchErr < 32 || cchErr >= 0x10000) \
74 return VERR_INVALID_PARAMETER; \
75 pReq->szMsg[0] = '\0'; \
76 \
77 /* Initialize the global buffer. */ \
78 memset(&g_szErr[0], 0, sizeof(g_szErr)); \
79 ASMAtomicWriteU32(&g_cErrors, 0); \
80 } while (0)
81
82
83/**
84 * Service request handler epilog.
85 *
86 * Copies any errors or messages into the request packet.
87 *
88 * @param pReqHdr The request packet header.
89 */
90#define RTR0TESTR0_SRV_REQ_EPILOG(pReqHdr) \
91 do \
92 { \
93 PRTTSTR0REQ pReq = (PRTTSTR0REQ)(pReqHdr); \
94 size_t cbErr = pReqHdr->cbReq - sizeof(pReq->Hdr); \
95 if (g_szErr[0] && pReq->szMsg[0] != '!') \
96 RTStrCopyEx(pReq->szMsg, (cbErr), g_szErr, sizeof(g_szErr) - 1); \
97 } while (0)
98
99
100/**
101 * Implement the sanity check switch-cases of a service request handler.
102 */
103#define RTR0TESTR0_IMPLEMENT_SANITY_CASES() \
104 case RTTSTR0REQ_SANITY_OK: \
105 break; \
106 case RTTSTR0REQ_SANITY_FAILURE: \
107 RTR0TestR0Error("42failure42%4096s", ""); \
108 break
109
110/**
111 * Implements the default switch-case of a service request handler.
112 * @param uOperation The operation.
113 */
114#define RTR0TESTR0_IMPLEMENT_DEFAULT_CASE(uOperation) \
115 default: \
116 RTR0TestR0Error("Unknown test #%d", (uOperation)); \
117 break
118
119
120/**
121 * Macro for checking the return code of an API in the ring-0 testcase.
122 *
123 * Similar to RTTESTI_CHECK_RC.
124 *
125 * @param rcExpr The expression producing the return code. Only
126 * evaluated once.
127 * @param rcExpect The expected result. Evaluated multiple times.
128 */
129#define RTR0TESTR0_CHECK_RC(rcExpr, rcExpect) \
130 do { \
131 int rcCheck = (rcExpr); \
132 if (rcCheck != (rcExpect)) \
133 RTR0TestR0Error("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
134 } while (0)
135
136/**
137 * Same as RTR0TESTR0_CHECK_RC + break.
138 */
139#define RTR0TESTR0_CHECK_RC_BREAK(rcExpr, rcExpect) \
140 if (1) \
141 { \
142 int rcCheck = (rcExpr); \
143 if (rcCheck != (rcExpect)) \
144 { \
145 RTR0TestR0Error("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
146 break; \
147 } \
148 } else do { } while (0)
149
150/**
151 * Macro for checking the return code of an API in the ring-0 testcase.
152 *
153 * Similar to RTTESTI_CHECK_MSG
154 *
155 * @param expr The expression to evaluate.
156 * @param DetailsArgs Format string + arguments - in parenthesis.
157 */
158#define RTR0TESTR0_CHECK_MSG(expr, DetailsArgs) \
159 do { \
160 if (!(expr)) \
161 { \
162 RTR0TestR0Error("line %u: expression failed: %s - ", __LINE__, #expr); \
163 RTR0TestR0AppendDetails DetailsArgs; \
164 } \
165 } while (0)
166
167/**
168 * Same as RTR0TESTR0_CHECK_MSG + break.
169 */
170#define RTR0TESTR0_CHECK_MSG_BREAK(expr, DetailsArgs) \
171 if (!(expr)) \
172 { \
173 RTR0TestR0Error("line %u: expression failed: %s - ", __LINE__, #expr); \
174 RTR0TestR0AppendDetails DetailsArgs; \
175 break; \
176 } else do { } while (0)
177
178/**
179 * Same as RTR0TESTR0_CHECK_MSG + return @a rcRete.
180 */
181#define RTR0TESTR0_CHECK_MSG_RET(expr, DetailsArgs, rcRet) \
182 do { \
183 if (!(expr)) \
184 { \
185 RTR0TestR0Error("line %u: expression failed: %s - ", __LINE__, #expr); \
186 RTR0TestR0AppendDetails DetailsArgs; \
187 return (rcRet); \
188 } \
189 } while (0)
190
191/**
192 * Macro for skipping a test in the ring-0 testcase.
193 */
194#define RTR0TESTR0_SKIP() \
195 do { \
196 RTR0TestR0Skip("line %u: SKIPPED", __LINE__); \
197 } while (0)
198
199/**
200 * Same as RTR0TESTR0_SKIP + break.
201 */
202#define RTR0TESTR0_SKIP_BREAK() \
203 if (1) \
204 { \
205 RTR0TestR0Skip("line %u: SKIPPED", __LINE__); \
206 break; \
207 } else do { } while (0)
208
209
210/**
211 * Report an error.
212 */
213DECLINLINE(void) RTR0TestR0Error(const char *pszFormat, ...)
214{
215 size_t off = RTStrNLen(g_szErr, sizeof(g_szErr) - 1);
216 size_t cbLeft = sizeof(g_szErr) - off;
217 if (cbLeft > 10)
218 {
219 char *psz = &g_szErr[off];
220 if (off)
221 {
222 *psz++ = '\n';
223 *psz++ = '\n';
224 cbLeft -= 2;
225 }
226 *psz++ = '!';
227 cbLeft--;
228
229 va_list va;
230 va_start(va, pszFormat);
231 RTStrPrintfV(psz, cbLeft, pszFormat, va);
232 va_end(va);
233 }
234 ASMAtomicIncU32(&g_cErrors);
235}
236
237
238/**
239 * Append error details.
240 */
241static void RTR0TestR0AppendDetails(const char *pszFormat, ...)
242{
243 size_t off = RTStrNLen(g_szErr, sizeof(g_szErr) - 1);
244 va_list va;
245 va_start(va, pszFormat);
246 RTStrPrintfV(&g_szErr[off], sizeof(g_szErr) - off, pszFormat, va);
247 va_end(va);
248}
249
250
251/**
252 * Informational message.
253 */
254DECLINLINE(void) RTR0TestR0Info(const char *pszFormat, ...)
255{
256 size_t off = RTStrNLen(g_szErr, sizeof(g_szErr) - 1);
257 size_t cbLeft = sizeof(g_szErr) - off;
258 if (cbLeft > 10)
259 {
260 char *psz = &g_szErr[off];
261 if (off)
262 {
263 *psz++ = '\n';
264 *psz++ = '\n';
265 cbLeft -= 2;
266 }
267 *psz++ = '?';
268 cbLeft--;
269
270 va_list va;
271 va_start(va, pszFormat);
272 RTStrPrintfV(psz, cbLeft, pszFormat, va);
273 va_end(va);
274 }
275}
276
277
278/**
279 * Report an error.
280 */
281DECLINLINE(void) RTR0TestR0Skip(const char *pszFormat, ...)
282{
283 size_t off = RTStrNLen(g_szErr, sizeof(g_szErr) - 1);
284 size_t cbLeft = sizeof(g_szErr) - off;
285 if (cbLeft > 10)
286 {
287 char *psz = &g_szErr[off];
288 if (off)
289 {
290 *psz++ = '\n';
291 *psz++ = '\n';
292 cbLeft -= 2;
293 }
294 *psz++ = '$';
295 cbLeft--;
296
297 va_list va;
298 va_start(va, pszFormat);
299 RTStrPrintfV(psz, cbLeft, pszFormat, va);
300 va_end(va);
301 }
302 ASMAtomicIncU32(&g_cErrors);
303}
304
305
306/**
307 * Checks if we have any error reports.
308 *
309 * @returns true if there are errors, false if none.
310 */
311DECLINLINE(bool) RTR0TestR0HaveErrors(void)
312{
313 return ASMAtomicUoReadU32(&g_cErrors) > 0;
314}
315
316#endif /* !IPRT_INCLUDED_SRC_testcase_tstRTR0Common_h */
317
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