VirtualBox

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

Last change on this file since 52066 was 51906, checked in by vboxsync, 10 years ago

Fixing testcases on windows.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.8 KB
Line 
1/* $Id: tstVMREQ.cpp 51906 2014-07-07 16:28:37Z vboxsync $ */
2/** @file
3 * VMM Testcase.
4 */
5
6/*
7 * Copyright (C) 2006-2013 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* Global Variables *
43*******************************************************************************/
44/** the error count. */
45static int g_cErrors = 0;
46
47
48/**
49 * Testings va_list passing in VMSetRuntimeError.
50 */
51static DECLCALLBACK(void) MyAtRuntimeError(PUVM pUVM, void *pvUser, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
52{
53 NOREF(pUVM);
54 if (strcmp((const char *)pvUser, "user argument"))
55 {
56 RTPrintf(TESTCASE ": pvUser=%p:{%s}!\n", pvUser, (const char *)pvUser);
57 g_cErrors++;
58 }
59 if (fFlags)
60 {
61 RTPrintf(TESTCASE ": fFlags=%#x!\n", fFlags);
62 g_cErrors++;
63 }
64 if (strcmp(pszErrorId, "enum"))
65 {
66 RTPrintf(TESTCASE ": pszErrorId=%p:{%s}!\n", pszErrorId, pszErrorId);
67 g_cErrors++;
68 }
69 if (strcmp(pszFormat, "some %s string"))
70 {
71 RTPrintf(TESTCASE ": pszFormat=%p:{%s}!\n", pszFormat, pszFormat);
72 g_cErrors++;
73 }
74
75 char szBuf[1024];
76 RTStrPrintfV(szBuf, sizeof(szBuf), pszFormat, va);
77 if (strcmp(szBuf, "some error string"))
78 {
79 RTPrintf(TESTCASE ": RTStrPrintfV -> '%s'!\n", szBuf);
80 g_cErrors++;
81 }
82}
83
84
85/**
86 * The function PassVA and PassVA2 calls.
87 */
88static DECLCALLBACK(int) PassVACallback(PUVM pUVM, unsigned u4K, unsigned u1G, const char *pszFormat, va_list *pva)
89{
90 NOREF(pUVM);
91 if (u4K != _4K)
92 {
93 RTPrintf(TESTCASE ": u4K=%#x!\n", u4K);
94 g_cErrors++;
95 }
96 if (u1G != _1G)
97 {
98 RTPrintf(TESTCASE ": u1G=%#x!\n", u1G);
99 g_cErrors++;
100 }
101
102 if (strcmp(pszFormat, "hello %s"))
103 {
104 RTPrintf(TESTCASE ": pszFormat=%p:{%s}!\n", pszFormat, pszFormat);
105 g_cErrors++;
106 }
107
108 char szBuf[1024];
109 RTStrPrintfV(szBuf, sizeof(szBuf), pszFormat, *pva);
110 if (strcmp(szBuf, "hello world"))
111 {
112 RTPrintf(TESTCASE ": RTStrPrintfV -> '%s'!\n", szBuf);
113 g_cErrors++;
114 }
115
116 return VINF_SUCCESS;
117}
118
119
120/**
121 * Functions that tests passing a va_list * argument in a request,
122 * similar to VMSetRuntimeError.
123 */
124static void PassVA2(PUVM pUVM, const char *pszFormat, va_list va)
125{
126#if 0 /** @todo test if this is a GCC problem only or also happens with AMD64+VCC80... */
127 void *pvVA = &va;
128#else
129 va_list va2;
130 va_copy(va2, va);
131 void *pvVA = &va2;
132#endif
133
134 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)PassVACallback, 5, pUVM, _4K, _1G, pszFormat, pvVA);
135 NOREF(rc);
136
137#if 1
138 va_end(va2);
139#endif
140}
141
142
143/**
144 * Functions that tests passing a va_list * argument in a request,
145 * similar to VMSetRuntimeError.
146 */
147static void PassVA(PUVM pUVM, const char *pszFormat, ...)
148{
149 /* 1st test */
150 va_list va1;
151 va_start(va1, pszFormat);
152 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)PassVACallback, 5, pUVM, _4K, _1G, pszFormat, &va1);
153 va_end(va1);
154 NOREF(rc);
155
156 /* 2nd test */
157 va_list va2;
158 va_start(va2, pszFormat);
159 PassVA2(pUVM, pszFormat, va2);
160 va_end(va2);
161}
162
163
164/**
165 * Thread function which allocates and frees requests like wildfire.
166 */
167static DECLCALLBACK(int) Thread(RTTHREAD hThreadSelf, void *pvUser)
168{
169 int rc = VINF_SUCCESS;
170 PUVM pUVM = (PUVM)pvUser;
171 NOREF(hThreadSelf);
172
173 for (unsigned i = 0; i < 100000; i++)
174 {
175 PVMREQ apReq[17];
176 const unsigned cReqs = i % RT_ELEMENTS(apReq);
177 unsigned iReq;
178 for (iReq = 0; iReq < cReqs; iReq++)
179 {
180 rc = VMR3ReqAlloc(pUVM, &apReq[iReq], VMREQTYPE_INTERNAL, VMCPUID_ANY);
181 if (RT_FAILURE(rc))
182 {
183 RTPrintf(TESTCASE ": i=%d iReq=%d cReqs=%d rc=%Rrc (alloc)\n", i, iReq, cReqs, rc);
184 return rc;
185 }
186 apReq[iReq]->iStatus = iReq + i;
187 }
188
189 for (iReq = 0; iReq < cReqs; iReq++)
190 {
191 if (apReq[iReq]->iStatus != (int)(iReq + i))
192 {
193 RTPrintf(TESTCASE ": i=%d iReq=%d cReqs=%d: iStatus=%d != %d\n", i, iReq, cReqs, apReq[iReq]->iStatus, iReq + i);
194 return VERR_GENERAL_FAILURE;
195 }
196 rc = VMR3ReqFree(apReq[iReq]);
197 if (RT_FAILURE(rc))
198 {
199 RTPrintf(TESTCASE ": i=%d iReq=%d cReqs=%d rc=%Rrc (free)\n", i, iReq, cReqs, rc);
200 return rc;
201 }
202 }
203 //if (!(i % 10000))
204 // RTPrintf(TESTCASE ": i=%d\n", i);
205 }
206
207 return VINF_SUCCESS;
208}
209
210static DECLCALLBACK(int)
211tstVMREQConfigConstructor(PUVM pUVM, PVM pVM, void *pvUser)
212{
213 NOREF(pvUser);
214 int rc = CFGMR3ConstructDefaultTree(pVM);
215 if (RT_SUCCESS(rc))
216 {
217 /* Disable HM, otherwise it will fail on machines without unrestricted guest execution
218 * because the allocation of HM_VTX_TOTAL_DEVHEAP_MEM will fail -- no VMMDev */
219 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
220 rc = CFGMR3InsertInteger(pRoot, "HMEnabled", false);
221 if (RT_FAILURE(rc))
222 RTPrintf("CFGMR3InsertInteger(pRoot,\"HMEnabled\",) -> %Rrc\n", rc);
223 }
224 return rc;
225}
226
227/**
228 * Entry point.
229 */
230extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
231{
232 RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
233 RTPrintf(TESTCASE ": TESTING...\n");
234 RTStrmFlush(g_pStdOut);
235
236 /*
237 * Create empty VM.
238 */
239 PUVM pUVM;
240 int rc = VMR3Create(1, NULL, NULL, NULL, tstVMREQConfigConstructor, NULL, NULL, &pUVM);
241 if (RT_SUCCESS(rc))
242 {
243 /*
244 * Do testing.
245 */
246 uint64_t u64StartTS = RTTimeNanoTS();
247 RTTHREAD Thread0;
248 rc = RTThreadCreate(&Thread0, Thread, pUVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
249 if (RT_SUCCESS(rc))
250 {
251 RTTHREAD Thread1;
252 rc = RTThreadCreate(&Thread1, Thread, pUVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
253 if (RT_SUCCESS(rc))
254 {
255 int rcThread1;
256 rc = RTThreadWait(Thread1, RT_INDEFINITE_WAIT, &rcThread1);
257 if (RT_FAILURE(rc))
258 {
259 RTPrintf(TESTCASE ": RTThreadWait(Thread1,,) failed, rc=%Rrc\n", rc);
260 g_cErrors++;
261 }
262 if (RT_FAILURE(rcThread1))
263 g_cErrors++;
264 }
265 else
266 {
267 RTPrintf(TESTCASE ": RTThreadCreate(&Thread1,,,,) failed, rc=%Rrc\n", rc);
268 g_cErrors++;
269 }
270
271 int rcThread0;
272 rc = RTThreadWait(Thread0, RT_INDEFINITE_WAIT, &rcThread0);
273 if (RT_FAILURE(rc))
274 {
275 RTPrintf(TESTCASE ": RTThreadWait(Thread1,,) failed, rc=%Rrc\n", rc);
276 g_cErrors++;
277 }
278 if (RT_FAILURE(rcThread0))
279 g_cErrors++;
280 }
281 else
282 {
283 RTPrintf(TESTCASE ": RTThreadCreate(&Thread0,,,,) failed, rc=%Rrc\n", rc);
284 g_cErrors++;
285 }
286 uint64_t u64ElapsedTS = RTTimeNanoTS() - u64StartTS;
287 RTPrintf(TESTCASE ": %llu ns elapsed\n", u64ElapsedTS);
288 RTStrmFlush(g_pStdOut);
289
290 /*
291 * Print stats.
292 */
293 STAMR3Print(pUVM, "/VM/Req/*");
294
295 /*
296 * Testing va_list fun.
297 */
298 RTPrintf(TESTCASE ": va_list argument test...\n"); RTStrmFlush(g_pStdOut);
299 PassVA(pUVM, "hello %s", "world");
300 VMR3AtRuntimeErrorRegister(pUVM, MyAtRuntimeError, (void *)"user argument");
301 VMSetRuntimeError(VMR3GetVM(pUVM), 0 /*fFlags*/, "enum", "some %s string", "error");
302
303 /*
304 * Cleanup.
305 */
306 rc = VMR3PowerOff(pUVM);
307 if (!RT_SUCCESS(rc))
308 {
309 RTPrintf(TESTCASE ": error: failed to power off vm! rc=%Rrc\n", rc);
310 g_cErrors++;
311 }
312 rc = VMR3Destroy(pUVM);
313 if (!RT_SUCCESS(rc))
314 {
315 RTPrintf(TESTCASE ": error: failed to destroy vm! rc=%Rrc\n", rc);
316 g_cErrors++;
317 }
318 VMR3ReleaseUVM(pUVM);
319 }
320 else
321 {
322 RTPrintf(TESTCASE ": fatal error: failed to create vm! rc=%Rrc\n", rc);
323 g_cErrors++;
324 }
325
326 /*
327 * Summary and return.
328 */
329 if (!g_cErrors)
330 RTPrintf(TESTCASE ": SUCCESS\n");
331 else
332 RTPrintf(TESTCASE ": FAILURE - %d errors\n", g_cErrors);
333
334 return !!g_cErrors;
335}
336
337
338#if !defined(VBOX_WITH_HARDENING) || !defined(RT_OS_WINDOWS)
339/**
340 * Main entry point.
341 */
342int main(int argc, char **argv, char **envp)
343{
344 return TrustedMain(argc, argv, envp);
345}
346#endif
347
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