VirtualBox

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

Last change on this file since 38636 was 38636, checked in by vboxsync, 13 years ago

*,IPRT: Redid the ring-3 init to always convert the arguments to UTF-8.

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