VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTR0CommonDriver.h@ 96407

Last change on this file since 96407 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.6 KB
Line 
1/* $Id: tstRTR0CommonDriver.h 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * IPRT R0 Testcase - Common header for the testcase drivers.
4 */
5
6/*
7 * Copyright (C) 2010-2022 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_tstRTR0CommonDriver_h
38#define IPRT_INCLUDED_SRC_testcase_tstRTR0CommonDriver_h
39#ifndef RT_WITHOUT_PRAGMA_ONCE
40# pragma once
41#endif
42
43
44/*******************************************************************************
45* Header Files *
46*******************************************************************************/
47#include <iprt/ctype.h>
48#include <iprt/string.h>
49#include <VBox/sup.h>
50#include "tstRTR0CommonReq.h"
51
52
53/*******************************************************************************
54* Global Variables *
55*******************************************************************************/
56/** The test handle. */
57RTTEST g_hTest;
58/** The test & service name. */
59char g_szSrvName[64];
60/** The length of the service name. */
61size_t g_cchSrvName;
62/** The base address of the service module. */
63void *g_pvImageBase;
64
65
66/**
67 * Initializes the test driver.
68 *
69 * This means creating a test instance (RTTEST), initializing the support
70 * library, and loading the service module.
71 *
72 * @returns RTEXITCODE_SUCCESS on success, appropriate exit code on failure.
73 * @param pszTestServiceName The name of the test and service. This
74 * will be used when creating the test
75 * instance as well as when talking with the
76 * kernel side of the test.
77 *
78 * The ring-0 module name will be derived from
79 * this + '.r0'.
80 *
81 * The service request handler function name
82 * will be derived by upper casing the first
83 * chars and appending 'SrvReqHandler'.
84 *
85 */
86RTEXITCODE RTR3TestR0CommonDriverInit(const char *pszTestServiceName)
87{
88 /*
89 * Init the test.
90 */
91 RTEXITCODE rcExit = RTTestInitAndCreate(pszTestServiceName, &g_hTest);
92 if (rcExit != RTEXITCODE_SUCCESS)
93 return rcExit;
94 RTTestBanner(g_hTest);
95
96 /*
97 * Init the globals.
98 */
99 g_cchSrvName = strlen(pszTestServiceName);
100 int rc = RTStrCopy(g_szSrvName, sizeof(g_szSrvName), pszTestServiceName);
101 if (rc != VINF_SUCCESS)
102 {
103 RTTestFailed(g_hTest, "The test name is too long! (%zu bytes)", g_cchSrvName);
104 return RTTestSummaryAndDestroy(g_hTest);
105 }
106
107 /*
108 * Initialize the support driver session.
109 */
110 PSUPDRVSESSION pSession;
111 rc = SUPR3Init(&pSession);
112 if (RT_FAILURE(rc))
113 {
114 RTTestFailed(g_hTest, "SUPR3Init failed with rc=%Rrc\n", rc);
115 return RTTestSummaryAndDestroy(g_hTest);
116 }
117
118 char szPath[RTPATH_MAX + sizeof(".r0")];
119 rc = RTPathExecDir(szPath, RTPATH_MAX);
120 if (RT_SUCCESS(rc))
121 rc = RTPathAppend(szPath, RTPATH_MAX, pszTestServiceName);
122 if (RT_SUCCESS(rc))
123 strcat(szPath, ".r0");
124 if (RT_FAILURE(rc))
125 {
126 RTTestFailed(g_hTest, "Failed constructing .r0 filename (rc=%Rrc)", rc);
127 return RTTestSummaryAndDestroy(g_hTest);
128 }
129
130 char szSrvReqHandler[sizeof(g_szSrvName) + sizeof("SrvReqHandler")];
131 strcpy(szSrvReqHandler, pszTestServiceName);
132 strcat(szSrvReqHandler, "SrvReqHandler");
133 for (size_t off = 0; RT_C_IS_LOWER(szSrvReqHandler[off]); off++)
134 szSrvReqHandler[off] = RT_C_TO_UPPER(szSrvReqHandler[off]);
135
136 rc = SUPR3LoadServiceModule(szPath, pszTestServiceName, szSrvReqHandler, &g_pvImageBase);
137 if (RT_FAILURE(rc))
138 {
139 RTTestFailed(g_hTest, "SUPR3LoadServiceModule(%s,%s,%s,) failed with rc=%Rrc\n",
140 szPath, pszTestServiceName, szSrvReqHandler, rc);
141 return RTTestSummaryAndDestroy(g_hTest);
142 }
143
144 /*
145 * Do the sanity checks.
146 */
147 RTTestSub(g_hTest, "Sanity");
148 RTTSTR0REQ Req;
149 Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC;
150 Req.Hdr.cbReq = sizeof(Req);
151 memset(Req.szMsg, 0xef, sizeof(Req.szMsg));
152 RTTESTI_CHECK_RC(rc = SUPR3CallR0Service(g_szSrvName, g_cchSrvName, RTTSTR0REQ_SANITY_OK, 0, &Req.Hdr), VINF_SUCCESS);
153 if (RT_FAILURE(rc))
154 return RTTestSummaryAndDestroy(g_hTest);
155 RTTESTI_CHECK_MSG(Req.szMsg[0] == '\0', ("%s", Req.szMsg));
156 if (Req.szMsg[0] != '\0')
157 return RTTestSummaryAndDestroy(g_hTest);
158
159
160 Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC;
161 Req.Hdr.cbReq = sizeof(Req);
162 Req.szMsg[0] = '\0';
163 memset(Req.szMsg, 0xfe, sizeof(Req.szMsg));
164 RTTESTI_CHECK_RC(rc = SUPR3CallR0Service(g_szSrvName, g_cchSrvName, RTTSTR0REQ_SANITY_FAILURE, 0, &Req.Hdr), VINF_SUCCESS);
165 if (RT_FAILURE(rc))
166 return RTTestSummaryAndDestroy(g_hTest);
167 rc = !strncmp(Req.szMsg, "!42failure42", sizeof("!42failure42"));
168 if (rc)
169 {
170 RTTestFailed(g_hTest, "the negative sanity check failed");
171 return RTTestSummaryAndDestroy(g_hTest);
172 }
173 RTTestSubDone(g_hTest);
174
175 return RTEXITCODE_SUCCESS;
176}
177
178
179/**
180 * Processes the messages in the request.
181 *
182 * @returns true on success, false on failure.
183 * @param pReq The request.
184 */
185static bool rtR3TestR0ProcessMessages(PRTTSTR0REQ pReq)
186{
187 /*
188 * Process the message strings.
189 *
190 * We can have multiple failures and info messages packed into szMsg. They
191 * are separated by a double newline. The kind of message is indicated by
192 * the first character, '!' means error and '?' means info message. '$' means
193 * the test was skipped because a feature is not supported on the host.
194 */
195 bool fRc = true;
196 if (pReq->szMsg[0])
197 {
198 pReq->szMsg[sizeof(pReq->szMsg) - 1] = '\0'; /* paranoia */
199
200 char *pszNext = &pReq->szMsg[0];
201 do
202 {
203 char *pszCur = pszNext;
204 do
205 pszNext = strpbrk(pszNext + 1, "!?$");
206 while (pszNext && (pszNext[-1] != '\n' || pszNext[-2] != '\n'));
207
208 char *pszEnd = pszNext ? pszNext - 1 : strchr(pszCur, '\0');
209 while ( (uintptr_t)pszEnd > (uintptr_t)pszCur
210 && pszEnd[-1] == '\n')
211 *--pszEnd = '\0';
212
213 if (*pszCur == '!')
214 {
215 RTTestFailed(g_hTest, "%s", pszCur + 1);
216 fRc = false;
217 }
218 else if (*pszCur == '$')
219 {
220 RTTestSkipped(g_hTest, "%s", pszCur + 1);
221 }
222 else
223 RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "%s", pszCur + 1);
224 } while (pszNext);
225 }
226
227 return fRc;
228}
229
230
231/**
232 * Performs a simple test with an argument (@a u64Arg).
233 *
234 * @returns true on success, false on failure.
235 * @param uOperation The operation to perform.
236 * @param u64Arg 64-bit argument.
237 * @param pszTestFmt The sub-test name.
238 * @param ... Format arguments.
239 */
240bool RTR3TestR0SimpleTestWithArg(uint32_t uOperation, uint64_t u64Arg, const char *pszTestFmt, ...)
241{
242 va_list va;
243 va_start(va, pszTestFmt);
244 RTTestSubV(g_hTest, pszTestFmt, va);
245 va_end(va);
246
247 RTTSTR0REQ Req;
248 Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC;
249 Req.Hdr.cbReq = sizeof(Req);
250 RT_ZERO(Req.szMsg);
251 int rc = SUPR3CallR0Service(g_szSrvName, g_cchSrvName, uOperation, u64Arg, &Req.Hdr);
252 if (RT_FAILURE(rc))
253 {
254 RTTestFailed(g_hTest, "SUPR3CallR0Service failed with rc=%Rrc", rc);
255 return false;
256 }
257
258 return rtR3TestR0ProcessMessages(&Req);
259}
260
261
262/**
263 * Performs a simple test.
264 *
265 * @returns true on success, false on failure.
266 * @param uOperation The operation to perform.
267 * @param pszTestFmt The sub-test name.
268 * @param ... Format arguments.
269 */
270bool RTR3TestR0SimpleTest(uint32_t uOperation, const char *pszTestFmt, ...)
271{
272 va_list va;
273 va_start(va, pszTestFmt);
274 RTTestSubV(g_hTest, pszTestFmt, va);
275 va_end(va);
276
277 RTTSTR0REQ Req;
278 Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC;
279 Req.Hdr.cbReq = sizeof(Req);
280 RT_ZERO(Req.szMsg);
281 int rc = SUPR3CallR0Service(g_szSrvName, g_cchSrvName, uOperation, 0, &Req.Hdr);
282 if (RT_FAILURE(rc))
283 {
284 RTTestFailed(g_hTest, "SUPR3CallR0Service failed with rc=%Rrc", rc);
285 return false;
286 }
287
288 return rtR3TestR0ProcessMessages(&Req);
289}
290
291#endif /* !IPRT_INCLUDED_SRC_testcase_tstRTR0CommonDriver_h */
292
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