VirtualBox

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

Last change on this file since 62489 was 62478, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.8 KB
Line 
1/* $Id: tstVMREQ.cpp 62478 2016-07-22 18:29:06Z vboxsync $ */
2/** @file
3 * VMM Testcase.
4 */
5
6/*
7 * Copyright (C) 2006-2016 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, void *pvUser)
213{
214 NOREF(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 RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
224 RTPrintf(TESTCASE ": TESTING...\n");
225 RTStrmFlush(g_pStdOut);
226
227 /*
228 * Create empty VM.
229 */
230 PUVM pUVM;
231 int rc = VMR3Create(1, NULL, NULL, NULL, tstVMREQConfigConstructor, NULL, NULL, &pUVM);
232 if (RT_SUCCESS(rc))
233 {
234 /*
235 * Do testing.
236 */
237 uint64_t u64StartTS = RTTimeNanoTS();
238 RTTHREAD Thread0;
239 rc = RTThreadCreate(&Thread0, Thread, pUVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
240 if (RT_SUCCESS(rc))
241 {
242 RTTHREAD Thread1;
243 rc = RTThreadCreate(&Thread1, Thread, pUVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
244 if (RT_SUCCESS(rc))
245 {
246 int rcThread1;
247 rc = RTThreadWait(Thread1, RT_INDEFINITE_WAIT, &rcThread1);
248 if (RT_FAILURE(rc))
249 {
250 RTPrintf(TESTCASE ": RTThreadWait(Thread1,,) failed, rc=%Rrc\n", rc);
251 g_cErrors++;
252 }
253 if (RT_FAILURE(rcThread1))
254 g_cErrors++;
255 }
256 else
257 {
258 RTPrintf(TESTCASE ": RTThreadCreate(&Thread1,,,,) failed, rc=%Rrc\n", rc);
259 g_cErrors++;
260 }
261
262 int rcThread0;
263 rc = RTThreadWait(Thread0, RT_INDEFINITE_WAIT, &rcThread0);
264 if (RT_FAILURE(rc))
265 {
266 RTPrintf(TESTCASE ": RTThreadWait(Thread1,,) failed, rc=%Rrc\n", rc);
267 g_cErrors++;
268 }
269 if (RT_FAILURE(rcThread0))
270 g_cErrors++;
271 }
272 else
273 {
274 RTPrintf(TESTCASE ": RTThreadCreate(&Thread0,,,,) failed, rc=%Rrc\n", rc);
275 g_cErrors++;
276 }
277 uint64_t u64ElapsedTS = RTTimeNanoTS() - u64StartTS;
278 RTPrintf(TESTCASE ": %llu ns elapsed\n", u64ElapsedTS);
279 RTStrmFlush(g_pStdOut);
280
281 /*
282 * Print stats.
283 */
284 STAMR3Print(pUVM, "/VM/Req/*");
285
286 /*
287 * Testing va_list fun.
288 */
289 RTPrintf(TESTCASE ": va_list argument test...\n"); RTStrmFlush(g_pStdOut);
290 PassVA(pUVM, "hello %s", "world");
291 VMR3AtRuntimeErrorRegister(pUVM, MyAtRuntimeError, (void *)"user argument");
292 VMSetRuntimeError(VMR3GetVM(pUVM), 0 /*fFlags*/, "enum", "some %s string", "error");
293
294 /*
295 * Cleanup.
296 */
297 rc = VMR3PowerOff(pUVM);
298 if (!RT_SUCCESS(rc))
299 {
300 RTPrintf(TESTCASE ": error: failed to power off vm! rc=%Rrc\n", rc);
301 g_cErrors++;
302 }
303 rc = VMR3Destroy(pUVM);
304 if (!RT_SUCCESS(rc))
305 {
306 RTPrintf(TESTCASE ": error: failed to destroy vm! rc=%Rrc\n", rc);
307 g_cErrors++;
308 }
309 VMR3ReleaseUVM(pUVM);
310 }
311 else
312 {
313 RTPrintf(TESTCASE ": fatal error: failed to create vm! rc=%Rrc\n", rc);
314 g_cErrors++;
315 }
316
317 /*
318 * Summary and return.
319 */
320 if (!g_cErrors)
321 RTPrintf(TESTCASE ": SUCCESS\n");
322 else
323 RTPrintf(TESTCASE ": FAILURE - %d errors\n", g_cErrors);
324
325 return !!g_cErrors;
326}
327
328
329#if !defined(VBOX_WITH_HARDENING) || !defined(RT_OS_WINDOWS)
330/**
331 * Main entry point.
332 */
333int main(int argc, char **argv, char **envp)
334{
335 return TrustedMain(argc, argv, envp);
336}
337#endif
338
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