VirtualBox

source: vbox/trunk/src/VBox/VMM/testcase/tstVMREQ.cpp@ 93880

Last change on this file since 93880 was 93444, checked in by vboxsync, 3 years ago

VMM,Main,HostServices: Use a function table for accessing the VBoxVMM.dll/so/dylib functionality, and load it dynamically when the Console object is initialized. Also converted a few drivers in Main to use device helpers to get config values and such. bugref:10074

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 10.0 KB
Line 
1/* $Id: tstVMREQ.cpp 93444 2022-01-26 18:01:15Z vboxsync $ */
2/** @file
3 * VMM Testcase.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <VBox/vmm/vm.h>
23#include <VBox/vmm/vmm.h>
24#include <VBox/vmm/cpum.h>
25#include <VBox/err.h>
26#include <VBox/log.h>
27#include <iprt/assert.h>
28#include <iprt/initterm.h>
29#include <iprt/semaphore.h>
30#include <iprt/stream.h>
31#include <iprt/string.h>
32#include <iprt/thread.h>
33#include <iprt/time.h>
34
35
36/*********************************************************************************************************************************
37* Defined Constants And Macros *
38*********************************************************************************************************************************/
39#define TESTCASE "tstVMREQ"
40
41
42/*********************************************************************************************************************************
43* Global Variables *
44*********************************************************************************************************************************/
45/** the error count. */
46static int g_cErrors = 0;
47
48
49/**
50 * Testings va_list passing in VMSetRuntimeError.
51 */
52static DECLCALLBACK(void) MyAtRuntimeError(PUVM pUVM, void *pvUser, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
53{
54 NOREF(pUVM);
55 if (strcmp((const char *)pvUser, "user argument"))
56 {
57 RTPrintf(TESTCASE ": pvUser=%p:{%s}!\n", pvUser, (const char *)pvUser);
58 g_cErrors++;
59 }
60 if (fFlags)
61 {
62 RTPrintf(TESTCASE ": fFlags=%#x!\n", fFlags);
63 g_cErrors++;
64 }
65 if (strcmp(pszErrorId, "enum"))
66 {
67 RTPrintf(TESTCASE ": pszErrorId=%p:{%s}!\n", pszErrorId, pszErrorId);
68 g_cErrors++;
69 }
70 if (strcmp(pszFormat, "some %s string"))
71 {
72 RTPrintf(TESTCASE ": pszFormat=%p:{%s}!\n", pszFormat, pszFormat);
73 g_cErrors++;
74 }
75
76 char szBuf[1024];
77 RTStrPrintfV(szBuf, sizeof(szBuf), pszFormat, va);
78 if (strcmp(szBuf, "some error string"))
79 {
80 RTPrintf(TESTCASE ": RTStrPrintfV -> '%s'!\n", szBuf);
81 g_cErrors++;
82 }
83}
84
85
86/**
87 * The function PassVA and PassVA2 calls.
88 */
89static DECLCALLBACK(int) PassVACallback(PUVM pUVM, unsigned u4K, unsigned u1G, const char *pszFormat, va_list *pva)
90{
91 NOREF(pUVM);
92 if (u4K != _4K)
93 {
94 RTPrintf(TESTCASE ": u4K=%#x!\n", u4K);
95 g_cErrors++;
96 }
97 if (u1G != _1G)
98 {
99 RTPrintf(TESTCASE ": u1G=%#x!\n", u1G);
100 g_cErrors++;
101 }
102
103 if (strcmp(pszFormat, "hello %s"))
104 {
105 RTPrintf(TESTCASE ": pszFormat=%p:{%s}!\n", pszFormat, pszFormat);
106 g_cErrors++;
107 }
108
109 char szBuf[1024];
110 RTStrPrintfV(szBuf, sizeof(szBuf), pszFormat, *pva);
111 if (strcmp(szBuf, "hello world"))
112 {
113 RTPrintf(TESTCASE ": RTStrPrintfV -> '%s'!\n", szBuf);
114 g_cErrors++;
115 }
116
117 return VINF_SUCCESS;
118}
119
120
121/**
122 * Functions that tests passing a va_list * argument in a request,
123 * similar to VMSetRuntimeError.
124 */
125static void PassVA2(PUVM pUVM, const char *pszFormat, va_list va)
126{
127#if 0 /** @todo test if this is a GCC problem only or also happens with AMD64+VCC80... */
128 void *pvVA = &va;
129#else
130 va_list va2;
131 va_copy(va2, va);
132 void *pvVA = &va2;
133#endif
134
135 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)PassVACallback, 5, pUVM, _4K, _1G, pszFormat, pvVA);
136 NOREF(rc);
137
138#if 1
139 va_end(va2);
140#endif
141}
142
143
144/**
145 * Functions that tests passing a va_list * argument in a request,
146 * similar to VMSetRuntimeError.
147 */
148static void PassVA(PUVM pUVM, const char *pszFormat, ...)
149{
150 /* 1st test */
151 va_list va1;
152 va_start(va1, pszFormat);
153 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)PassVACallback, 5, pUVM, _4K, _1G, pszFormat, &va1);
154 va_end(va1);
155 NOREF(rc);
156
157 /* 2nd test */
158 va_list va2;
159 va_start(va2, pszFormat);
160 PassVA2(pUVM, pszFormat, va2);
161 va_end(va2);
162}
163
164
165/**
166 * Thread function which allocates and frees requests like wildfire.
167 */
168static DECLCALLBACK(int) Thread(RTTHREAD hThreadSelf, void *pvUser)
169{
170 int rc = VINF_SUCCESS;
171 PUVM pUVM = (PUVM)pvUser;
172 NOREF(hThreadSelf);
173
174 for (unsigned i = 0; i < 100000; i++)
175 {
176 PVMREQ apReq[17];
177 const unsigned cReqs = i % RT_ELEMENTS(apReq);
178 unsigned iReq;
179 for (iReq = 0; iReq < cReqs; iReq++)
180 {
181 rc = VMR3ReqAlloc(pUVM, &apReq[iReq], VMREQTYPE_INTERNAL, VMCPUID_ANY);
182 if (RT_FAILURE(rc))
183 {
184 RTPrintf(TESTCASE ": i=%d iReq=%d cReqs=%d rc=%Rrc (alloc)\n", i, iReq, cReqs, rc);
185 return rc;
186 }
187 apReq[iReq]->iStatus = iReq + i;
188 }
189
190 for (iReq = 0; iReq < cReqs; iReq++)
191 {
192 if (apReq[iReq]->iStatus != (int)(iReq + i))
193 {
194 RTPrintf(TESTCASE ": i=%d iReq=%d cReqs=%d: iStatus=%d != %d\n", i, iReq, cReqs, apReq[iReq]->iStatus, iReq + i);
195 return VERR_GENERAL_FAILURE;
196 }
197 rc = VMR3ReqFree(apReq[iReq]);
198 if (RT_FAILURE(rc))
199 {
200 RTPrintf(TESTCASE ": i=%d iReq=%d cReqs=%d rc=%Rrc (free)\n", i, iReq, cReqs, rc);
201 return rc;
202 }
203 }
204 //if (!(i % 10000))
205 // RTPrintf(TESTCASE ": i=%d\n", i);
206 }
207
208 return VINF_SUCCESS;
209}
210
211static DECLCALLBACK(int)
212tstVMREQConfigConstructor(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, void *pvUser)
213{
214 RT_NOREF(pUVM, pVMM, pvUser);
215 return CFGMR3ConstructDefaultTree(pVM);
216}
217
218/**
219 * Entry point.
220 */
221extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
222{
223 RT_NOREF1(envp);
224 RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_TRY_SUPLIB);
225 RTPrintf(TESTCASE ": TESTING...\n");
226 RTStrmFlush(g_pStdOut);
227
228 /*
229 * Create empty VM.
230 */
231 PUVM pUVM;
232 int rc = VMR3Create(1, NULL, NULL, NULL, tstVMREQConfigConstructor, NULL, NULL, &pUVM);
233 if (RT_SUCCESS(rc))
234 {
235 /*
236 * Do testing.
237 */
238 uint64_t u64StartTS = RTTimeNanoTS();
239 RTTHREAD Thread0;
240 rc = RTThreadCreate(&Thread0, Thread, pUVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
241 if (RT_SUCCESS(rc))
242 {
243 RTTHREAD Thread1;
244 rc = RTThreadCreate(&Thread1, Thread, pUVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
245 if (RT_SUCCESS(rc))
246 {
247 int rcThread1;
248 rc = RTThreadWait(Thread1, RT_INDEFINITE_WAIT, &rcThread1);
249 if (RT_FAILURE(rc))
250 {
251 RTPrintf(TESTCASE ": RTThreadWait(Thread1,,) failed, rc=%Rrc\n", rc);
252 g_cErrors++;
253 }
254 if (RT_FAILURE(rcThread1))
255 g_cErrors++;
256 }
257 else
258 {
259 RTPrintf(TESTCASE ": RTThreadCreate(&Thread1,,,,) failed, rc=%Rrc\n", rc);
260 g_cErrors++;
261 }
262
263 int rcThread0;
264 rc = RTThreadWait(Thread0, RT_INDEFINITE_WAIT, &rcThread0);
265 if (RT_FAILURE(rc))
266 {
267 RTPrintf(TESTCASE ": RTThreadWait(Thread1,,) failed, rc=%Rrc\n", rc);
268 g_cErrors++;
269 }
270 if (RT_FAILURE(rcThread0))
271 g_cErrors++;
272 }
273 else
274 {
275 RTPrintf(TESTCASE ": RTThreadCreate(&Thread0,,,,) failed, rc=%Rrc\n", rc);
276 g_cErrors++;
277 }
278 uint64_t u64ElapsedTS = RTTimeNanoTS() - u64StartTS;
279 RTPrintf(TESTCASE ": %llu ns elapsed\n", u64ElapsedTS);
280 RTStrmFlush(g_pStdOut);
281
282 /*
283 * Print stats.
284 */
285 STAMR3Print(pUVM, "/VM/Req/*");
286
287 /*
288 * Testing va_list fun.
289 */
290 RTPrintf(TESTCASE ": va_list argument test...\n"); RTStrmFlush(g_pStdOut);
291 PassVA(pUVM, "hello %s", "world");
292 VMR3AtRuntimeErrorRegister(pUVM, MyAtRuntimeError, (void *)"user argument");
293 VMSetRuntimeError(VMR3GetVM(pUVM), 0 /*fFlags*/, "enum", "some %s string", "error");
294
295 /*
296 * Cleanup.
297 */
298 rc = VMR3PowerOff(pUVM);
299 if (!RT_SUCCESS(rc))
300 {
301 RTPrintf(TESTCASE ": error: failed to power off vm! rc=%Rrc\n", rc);
302 g_cErrors++;
303 }
304 rc = VMR3Destroy(pUVM);
305 if (!RT_SUCCESS(rc))
306 {
307 RTPrintf(TESTCASE ": error: failed to destroy vm! rc=%Rrc\n", rc);
308 g_cErrors++;
309 }
310 VMR3ReleaseUVM(pUVM);
311 }
312 else if (rc == VERR_SVM_NO_SVM || rc == VERR_VMX_NO_VMX)
313 {
314 RTPrintf(TESTCASE ": Skipped: %Rrc\n", rc);
315 return RTEXITCODE_SKIPPED;
316 }
317 else
318 {
319 RTPrintf(TESTCASE ": fatal error: failed to create vm! rc=%Rrc\n", rc);
320 g_cErrors++;
321 }
322
323 /*
324 * Summary and return.
325 */
326 if (!g_cErrors)
327 RTPrintf(TESTCASE ": SUCCESS\n");
328 else
329 RTPrintf(TESTCASE ": FAILURE - %d errors\n", g_cErrors);
330
331 return !!g_cErrors;
332}
333
334
335#if !defined(VBOX_WITH_HARDENING) || !defined(RT_OS_WINDOWS)
336/**
337 * Main entry point.
338 */
339int main(int argc, char **argv, char **envp)
340{
341 return TrustedMain(argc, argv, envp);
342}
343#endif
344
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