VirtualBox

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

Last change on this file since 4672 was 4520, checked in by vboxsync, 17 years ago

Don't take the address of a va_list parameter. must va_copy it first or GCC/AMD64 won't work.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.7 KB
Line 
1/* $Id: tstVMREQ.cpp 4520 2007-09-05 07:17:14Z vboxsync $ */
2/** @file
3 * VMM Testcase.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <VBox/vm.h>
23#include <VBox/vmm.h>
24#include <VBox/cpum.h>
25#include <VBox/err.h>
26#include <VBox/log.h>
27#include <iprt/assert.h>
28#include <iprt/runtime.h>
29#include <iprt/semaphore.h>
30#include <iprt/stream.h>
31#include <iprt/thread.h>
32#include <iprt/time.h>
33
34
35/*******************************************************************************
36* Defined Constants And Macros *
37*******************************************************************************/
38#define TESTCASE "tstVMREQ"
39
40/*******************************************************************************
41* Global Variables *
42*******************************************************************************/
43/** the error count. */
44static int g_cErrors = 0;
45
46
47/**
48 * Testings va_list passing in VMSetRuntimeError.
49 */
50static DECLCALLBACK(void) MyAtRuntimeError(PVM pVM, void *pvUser, bool fFatal, const char *pszErrorId, const char *pszFormat, va_list va)
51{
52 if (strcmp((const char *)pvUser, "user argument"))
53 {
54 RTPrintf(TESTCASE ": pvUser=%p:{%s}!\n", pvUser, (const char *)pvUser);
55 g_cErrors++;
56 }
57 if (fFatal)
58 {
59 RTPrintf(TESTCASE ": fFatal=%d!\n", fFatal);
60 g_cErrors++;
61 }
62 if (strcmp(pszErrorId, "enum"))
63 {
64 RTPrintf(TESTCASE ": pszErrorId=%p:{%s}!\n", pszErrorId, pszErrorId);
65 g_cErrors++;
66 }
67 if (strcmp(pszFormat, "some %s string"))
68 {
69 RTPrintf(TESTCASE ": pszFormat=%p:{%s}!\n", pszFormat, pszFormat);
70 g_cErrors++;
71 }
72
73 char szBuf[1024];
74 RTStrPrintfV(szBuf, sizeof(szBuf), pszFormat, va);
75 if (strcmp(szBuf, "some error string"))
76 {
77 RTPrintf(TESTCASE ": RTStrPrintfV -> '%s'!\n", szBuf);
78 g_cErrors++;
79 }
80}
81
82
83/**
84 * The function PassVA and PassVA2 calls.
85 */
86static DECLCALLBACK(int) PassVACallback(PVM pVM, unsigned u4K, unsigned u1G, const char *pszFormat, va_list *pva)
87{
88 if (u4K != _4K)
89 {
90 RTPrintf(TESTCASE ": u4K=%#x!\n", u4K);
91 g_cErrors++;
92 }
93 if (u1G != _1G)
94 {
95 RTPrintf(TESTCASE ": u1G=%#x!\n", u1G);
96 g_cErrors++;
97 }
98
99 if (strcmp(pszFormat, "hello %s"))
100 {
101 RTPrintf(TESTCASE ": pszFormat=%p:{%s}!\n", pszFormat, pszFormat);
102 g_cErrors++;
103 }
104
105 char szBuf[1024];
106 RTStrPrintfV(szBuf, sizeof(szBuf), pszFormat, *pva);
107 if (strcmp(szBuf, "hello world"))
108 {
109 RTPrintf(TESTCASE ": RTStrPrintfV -> '%s'!\n", szBuf);
110 g_cErrors++;
111 }
112
113 return VINF_SUCCESS;
114}
115
116
117/**
118 * Functions that tests passing a va_list * argument in a request,
119 * similar to VMSetRuntimeError.
120 */
121static void PassVA2(PVM pVM, const char *pszFormat, va_list va)
122{
123#if 0 /** @todo test if this is a GCC problem only or also happens with AMD64+VCC80... */
124 void *pvVA = &va;
125#else
126 va_list va2;
127 va_copy(va2, va);
128 void *pvVA = va2;
129#endif
130
131 PVMREQ pReq;
132 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)PassVACallback, 5,
133 pVM, _4K, _1G, pszFormat, pvVA);
134 if (VBOX_SUCCESS(rc))
135 rc = pReq->iStatus;
136 VMR3ReqFree(pReq);
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(PVM pVM, const char *pszFormat, ...)
149{
150 /* 1st test */
151 va_list va1;
152 va_start(va1, pszFormat);
153 PVMREQ pReq;
154 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)PassVACallback, 5,
155 pVM, _4K, _1G, pszFormat, &va1);
156 if (VBOX_SUCCESS(rc))
157 rc = pReq->iStatus;
158 VMR3ReqFree(pReq);
159 va_end(va1);
160
161 /* 2nd test */
162 va_list va2;
163 va_start(va2, pszFormat);
164 PassVA2(pVM, pszFormat, va2);
165 va_end(va2);
166}
167
168
169/**
170 * Thread function which allocates and frees requests like wildfire.
171 */
172static DECLCALLBACK(int) Thread(RTTHREAD Thread, void *pvUser)
173{
174 int rc = VINF_SUCCESS;
175 PVM pVM = (PVM)pvUser;
176 for (unsigned i = 0; i < 100000; i++)
177 {
178 PVMREQ apReq[17];
179 const unsigned cReqs = i % ELEMENTS(apReq);
180 unsigned iReq;
181 for (iReq = 0; iReq < cReqs; iReq++)
182 {
183 rc = VMR3ReqAlloc(pVM, &apReq[iReq], VMREQTYPE_INTERNAL);
184 if (VBOX_FAILURE(rc))
185 {
186 RTPrintf(TESTCASE ": i=%d iReq=%d cReqs=%d rc=%Vrc (alloc)\n", i, iReq, cReqs, rc);
187 return rc;
188 }
189 apReq[iReq]->iStatus = iReq + i;
190 }
191
192 for (iReq = 0; iReq < cReqs; iReq++)
193 {
194 if (apReq[iReq]->iStatus != (int)(iReq + i))
195 {
196 RTPrintf(TESTCASE ": i=%d iReq=%d cReqs=%d: iStatus=%d != %d\n", i, iReq, cReqs, apReq[iReq]->iStatus, iReq + i);
197 return VERR_GENERAL_FAILURE;
198 }
199 rc = VMR3ReqFree(apReq[iReq]);
200 if (VBOX_FAILURE(rc))
201 {
202 RTPrintf(TESTCASE ": i=%d iReq=%d cReqs=%d rc=%Vrc (free)\n", i, iReq, cReqs, rc);
203 return rc;
204 }
205 }
206 //if (!(i % 10000))
207 // RTPrintf(TESTCASE ": i=%d\n", i);
208 }
209
210 return VINF_SUCCESS;
211}
212
213
214
215int main(int argc, char **argv)
216{
217 RTR3Init();
218 RTPrintf(TESTCASE ": TESTING...\n");
219
220 /*
221 * Create empty VM.
222 */
223 PVM pVM;
224 int rc = VMR3Create(NULL, NULL, NULL, NULL, &pVM);
225 if (VBOX_SUCCESS(rc))
226 {
227 /*
228 * Do testing.
229 */
230 uint64_t u64StartTS = RTTimeNanoTS();
231 RTTHREAD Thread0;
232 rc = RTThreadCreate(&Thread0, Thread, pVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
233 if (VBOX_SUCCESS(rc))
234 {
235 RTTHREAD Thread1;
236 rc = RTThreadCreate(&Thread1, Thread, pVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
237 if (VBOX_SUCCESS(rc))
238 {
239 int rcThread1;
240 rc = RTThreadWait(Thread1, RT_INDEFINITE_WAIT, &rcThread1);
241 if (VBOX_FAILURE(rc))
242 {
243 RTPrintf(TESTCASE ": RTThreadWait(Thread1,,) failed, rc=%Vrc\n", rc);
244 g_cErrors++;
245 }
246 if (VBOX_FAILURE(rcThread1))
247 g_cErrors++;
248 }
249 else
250 {
251 RTPrintf(TESTCASE ": RTThreadCreate(&Thread1,,,,) failed, rc=%Vrc\n", rc);
252 g_cErrors++;
253 }
254
255 int rcThread0;
256 rc = RTThreadWait(Thread0, RT_INDEFINITE_WAIT, &rcThread0);
257 if (VBOX_FAILURE(rc))
258 {
259 RTPrintf(TESTCASE ": RTThreadWait(Thread1,,) failed, rc=%Vrc\n", rc);
260 g_cErrors++;
261 }
262 if (VBOX_FAILURE(rcThread0))
263 g_cErrors++;
264 }
265 else
266 {
267 RTPrintf(TESTCASE ": RTThreadCreate(&Thread0,,,,) failed, rc=%Vrc\n", rc);
268 g_cErrors++;
269 }
270 uint64_t u64ElapsedTS = RTTimeNanoTS() - u64StartTS;
271 RTPrintf(TESTCASE ": %llu ns elapsed\n", u64ElapsedTS);
272
273 /*
274 * Print stats.
275 */
276 STAMR3Print(pVM, "/VM/Req/*");
277
278 /*
279 * Testing va_list fun.
280 */
281 RTPrintf(TESTCASE ": va_list argument test...\n");
282 PassVA(pVM, "hello %s", "world");
283 VMR3AtRuntimeErrorRegister(pVM, MyAtRuntimeError, (void *)"user argument");
284 VMSetRuntimeError(pVM, false, "enum", "some %s string", "error");
285
286 /*
287 * Cleanup.
288 */
289 rc = VMR3Destroy(pVM);
290 if (!VBOX_SUCCESS(rc))
291 {
292 RTPrintf(TESTCASE ": error: failed to destroy vm! rc=%Vrc\n", rc);
293 g_cErrors++;
294 }
295 }
296 else
297 {
298 RTPrintf(TESTCASE ": fatal error: failed to create vm! rc=%Vrc\n", rc);
299 g_cErrors++;
300 }
301
302 /*
303 * Summary and return.
304 */
305 if (!g_cErrors)
306 RTPrintf(TESTCASE ": SUCCESS\n");
307 else
308 RTPrintf(TESTCASE ": FAILURE - %d errors\n", g_cErrors);
309
310 return !!g_cErrors;
311}
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