VirtualBox

source: vbox/trunk/src/VBox/Debugger/testcase/tstDBGCParser.cpp@ 37989

Last change on this file since 37989 was 35629, checked in by vboxsync, 14 years ago

tstDBGCParse: more tests.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 14.6 KB
Line 
1/* $Id: tstDBGCParser.cpp 35629 2011-01-19 15:15:21Z vboxsync $ */
2/** @file
3 * DBGC Testcase - Command Parser.
4 */
5
6/*
7 * Copyright (C) 2006-2011 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* Header Files *
20*******************************************************************************/
21#include <VBox/dbg.h>
22#include "../DBGCInternal.h"
23
24#include <iprt/string.h>
25#include <iprt/test.h>
26
27
28/*******************************************************************************
29* Internal Functions *
30*******************************************************************************/
31static DECLCALLBACK(bool) tstDBGCBackInput(PDBGCBACK pBack, uint32_t cMillies);
32static DECLCALLBACK(int) tstDBGCBackRead(PDBGCBACK pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead);
33static DECLCALLBACK(int) tstDBGCBackWrite(PDBGCBACK pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten);
34static DECLCALLBACK(void) tstDBGCBackSetReady(PDBGCBACK pBack, bool fReady);
35
36
37/*******************************************************************************
38* Global Variables *
39*******************************************************************************/
40/** The test handle. */
41static RTTEST g_hTest = NIL_RTTEST;
42
43/** The DBGC backend structure for use in this testcase. */
44static DBGCBACK g_tstBack =
45{
46 tstDBGCBackInput,
47 tstDBGCBackRead,
48 tstDBGCBackWrite,
49 tstDBGCBackSetReady
50};
51/** For keeping track of output prefixing. */
52static bool g_fPendingPrefix = true;
53/** Pointer to the current input position. */
54const char *g_pszInput = NULL;
55/** The output of the last command. */
56static char g_szOutput[1024];
57/** The current offset into g_szOutput. */
58static size_t g_offOutput = 0;
59
60
61/**
62 * Checks if there is input.
63 *
64 * @returns true if there is input ready.
65 * @returns false if there not input ready.
66 * @param pBack Pointer to the backend structure supplied by
67 * the backend. The backend can use this to find
68 * it's instance data.
69 * @param cMillies Number of milliseconds to wait on input data.
70 */
71static DECLCALLBACK(bool) tstDBGCBackInput(PDBGCBACK pBack, uint32_t cMillies)
72{
73 return g_pszInput != NULL
74 && *g_pszInput != '\0';
75}
76
77
78/**
79 * Read input.
80 *
81 * @returns VBox status code.
82 * @param pBack Pointer to the backend structure supplied by
83 * the backend. The backend can use this to find
84 * it's instance data.
85 * @param pvBuf Where to put the bytes we read.
86 * @param cbBuf Maximum nymber of bytes to read.
87 * @param pcbRead Where to store the number of bytes actually read.
88 * If NULL the entire buffer must be filled for a
89 * successful return.
90 */
91static DECLCALLBACK(int) tstDBGCBackRead(PDBGCBACK pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead)
92{
93 if (g_pszInput && *g_pszInput)
94 {
95 size_t cb = strlen(g_pszInput);
96 if (cb > cbBuf)
97 cb = cbBuf;
98 *pcbRead = cb;
99 memcpy(pvBuf, g_pszInput, cb);
100 g_pszInput += cb;
101 }
102 else
103 *pcbRead = 0;
104 return VINF_SUCCESS;
105}
106
107
108/**
109 * Write (output).
110 *
111 * @returns VBox status code.
112 * @param pBack Pointer to the backend structure supplied by
113 * the backend. The backend can use this to find
114 * it's instance data.
115 * @param pvBuf What to write.
116 * @param cbBuf Number of bytes to write.
117 * @param pcbWritten Where to store the number of bytes actually written.
118 * If NULL the entire buffer must be successfully written.
119 */
120static DECLCALLBACK(int) tstDBGCBackWrite(PDBGCBACK pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
121{
122 const char *pch = (const char *)pvBuf;
123 if (pcbWritten)
124 *pcbWritten = cbBuf;
125 while (cbBuf-- > 0)
126 {
127 /* screen/log output */
128 if (g_fPendingPrefix)
129 {
130 RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "OUTPUT: ");
131 g_fPendingPrefix = false;
132 }
133 if (*pch == '\n')
134 g_fPendingPrefix = true;
135 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "%c", *pch);
136
137 /* buffer output */
138 if (g_offOutput < sizeof(g_szOutput) - 1)
139 {
140 g_szOutput[g_offOutput++] = *pch;
141 g_szOutput[g_offOutput] = '\0';
142 }
143
144 /* advance */
145 pch++;
146 }
147 return VINF_SUCCESS;
148}
149
150
151/**
152 * Ready / busy notification.
153 *
154 * @param pBack Pointer to the backend structure supplied by
155 * the backend. The backend can use this to find
156 * it's instance data.
157 * @param fReady Whether it's ready (true) or busy (false).
158 */
159static DECLCALLBACK(void) tstDBGCBackSetReady(PDBGCBACK pBack, bool fReady)
160{
161}
162
163
164/**
165 * Completes the output, making sure that we're in
166 * the 1 position of a new line.
167 */
168static void tstCompleteOutput(void)
169{
170 if (!g_fPendingPrefix)
171 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "\n");
172 g_fPendingPrefix = true;
173}
174
175
176/**
177 * Tries one command string.
178 * @param pDbgc Pointer to the debugger instance.
179 * @param pszCmds The command to test.
180 * @param rcCmd The expected result.
181 * @param fNoExecute When set, the command is not executed.
182 * @param pszExpected Expected output. This does not need to include all
183 * of the output, just the start of it. Thus the
184 * prompt can be omitted.
185 */
186static void tstTryEx(PDBGC pDbgc, const char *pszCmds, int rcCmd, bool fNoExecute, const char *pszExpected)
187{
188 RT_ZERO(g_szOutput);
189 g_offOutput = 0;
190 g_pszInput = pszCmds;
191 if (strchr(pszCmds, '\0')[-1] == '\n')
192 RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s", pszCmds);
193 else
194 RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s\n", pszCmds);
195
196 pDbgc->rcCmd = VERR_INTERNAL_ERROR;
197 dbgcProcessInput(pDbgc, fNoExecute);
198 tstCompleteOutput();
199
200 if (pDbgc->rcCmd != rcCmd)
201 RTTestFailed(g_hTest, "rcCmd=%Rrc expected =%Rrc\n", pDbgc->rcCmd, rcCmd);
202 else if ( !fNoExecute
203 && pszExpected
204 && strncmp(pszExpected, g_szOutput, strlen(pszExpected)))
205 RTTestFailed(g_hTest, "Wrong output - expected \"%s\"", pszExpected);
206}
207
208
209/**
210 * Tries one command string without executing it.
211 *
212 * @param pDbgc Pointer to the debugger instance.
213 * @param pszCmds The command to test.
214 * @param rcCmd The expected result.
215 */
216static void tstTry(PDBGC pDbgc, const char *pszCmds, int rcCmd)
217{
218 return tstTryEx(pDbgc, pszCmds, rcCmd, true /*fNoExecute*/, NULL);
219}
220
221
222/**
223 * Tries to execute one command string.
224 * @param pDbgc Pointer to the debugger instance.
225 * @param pszCmds The command to test.
226 * @param rcCmd The expected result.
227 * @param pszExpected Expected output. This does not need to include all
228 * of the output, just the start of it. Thus the
229 * prompt can be omitted.
230 */
231static void tstTryExec(PDBGC pDbgc, const char *pszCmds, int rcCmd, const char *pszExpected)
232{
233 return tstTryEx(pDbgc, pszCmds, rcCmd, false /*fNoExecute*/, pszExpected);
234}
235
236
237/**
238 * Test an operator on an expression resulting a plain number.
239 *
240 * @param pDbgc Pointer to the debugger instance.
241 * @param pszExpr The express to test.
242 * @param u64Expect The expected result.
243 */
244static void tstNumOp(PDBGC pDbgc, const char *pszExpr, uint64_t u64Expect)
245{
246 char szCmd[80];
247 RTStrPrintf(szCmd, sizeof(szCmd), "format %s\n", pszExpr);
248
249 char szExpected[80];
250 RTStrPrintf(szExpected, sizeof(szExpected),
251 "Number: hex %llx dec 0i%lld oct 0t%llo", u64Expect, u64Expect, u64Expect);
252
253 return tstTryEx(pDbgc, szCmd, VINF_SUCCESS, false /*fNoExecute*/, szExpected);
254}
255
256
257
258int main()
259{
260 /*
261 * Init.
262 */
263 int rc = RTTestInitAndCreate("tstDBGCParser", &g_hTest);
264 if (rc)
265 return rc;
266 RTTestBanner(g_hTest);
267
268 /*
269 * Create a DBGC instance.
270 */
271 RTTestSub(g_hTest, "dbgcCreate");
272 PDBGC pDbgc;
273 rc = dbgcCreate(&pDbgc, &g_tstBack, 0);
274 if (RT_SUCCESS(rc))
275 {
276 rc = dbgcProcessInput(pDbgc, true /* fNoExecute */);
277 tstCompleteOutput();
278 if (RT_SUCCESS(rc))
279 {
280 RTTestSub(g_hTest, "basic parsing");
281 tstTry(pDbgc, "stop\n", VINF_SUCCESS);
282 tstTry(pDbgc, "format 1\n", VINF_SUCCESS);
283 tstTry(pDbgc, "format \n", VERR_PARSE_TOO_FEW_ARGUMENTS);
284 tstTry(pDbgc, "format 0 1 23 4\n", VERR_PARSE_TOO_MANY_ARGUMENTS);
285 tstTry(pDbgc, "sa 3 23 4 'q' \"21123123\" 'b' \n", VINF_SUCCESS);
286
287 if (RTTestErrorCount(g_hTest) == 0)
288 {
289 RTTestSub(g_hTest, "Operators");
290 tstNumOp(pDbgc, "1", 1);
291 tstNumOp(pDbgc, "1", 1);
292 tstNumOp(pDbgc, "1", 1);
293
294 tstNumOp(pDbgc, "+1", 1);
295 tstNumOp(pDbgc, "++++++1", 1);
296
297 tstNumOp(pDbgc, "-1", UINT64_MAX);
298 tstNumOp(pDbgc, "--1", 1);
299 tstNumOp(pDbgc, "---1", UINT64_MAX);
300 tstNumOp(pDbgc, "----1", 1);
301
302 tstNumOp(pDbgc, "~0", UINT64_MAX);
303 tstNumOp(pDbgc, "~1", UINT64_MAX-1);
304 tstNumOp(pDbgc, "~~0", 0);
305 tstNumOp(pDbgc, "~~1", 1);
306
307 tstNumOp(pDbgc, "!1", 0);
308 tstNumOp(pDbgc, "!0", 1);
309 tstNumOp(pDbgc, "!42", 0);
310 tstNumOp(pDbgc, "!!42", 1);
311 tstNumOp(pDbgc, "!!!42", 0);
312 tstNumOp(pDbgc, "!!!!42", 1);
313
314 tstNumOp(pDbgc, "1 +1", 2);
315 tstNumOp(pDbgc, "1 + 1", 2);
316 tstNumOp(pDbgc, "1+1", 2);
317 tstNumOp(pDbgc, "1+ 1", 2);
318
319 tstNumOp(pDbgc, "1 - 1", 0);
320 tstNumOp(pDbgc, "99 - 90", 9);
321
322 tstNumOp(pDbgc, "2 * 2", 4);
323
324 tstNumOp(pDbgc, "2 / 2", 1);
325 tstNumOp(pDbgc, "2 / 0", UINT64_MAX);
326 tstNumOp(pDbgc, "0i1024 / 0i4", 256);
327
328 tstNumOp(pDbgc, "1<<1", 2);
329 tstNumOp(pDbgc, "1<<0i32", UINT64_C(0x0000000100000000));
330 tstNumOp(pDbgc, "1<<0i48", UINT64_C(0x0001000000000000));
331 tstNumOp(pDbgc, "1<<0i63", UINT64_C(0x8000000000000000));
332
333 tstNumOp(pDbgc, "fedcba0987654321>>0i04", UINT64_C(0x0fedcba098765432));
334 tstNumOp(pDbgc, "fedcba0987654321>>0i32", UINT64_C(0xfedcba09));
335 tstNumOp(pDbgc, "fedcba0987654321>>0i48", UINT64_C(0x0000fedc));
336
337 tstNumOp(pDbgc, "0ef & 4", 4);
338 tstNumOp(pDbgc, "01234567891 & fff", UINT64_C(0x00000000891));
339 tstNumOp(pDbgc, "01234567891 & ~fff", UINT64_C(0x01234567000));
340
341 tstNumOp(pDbgc, "1 | 1", 1);
342 tstNumOp(pDbgc, "0 | 4", 4);
343 tstNumOp(pDbgc, "4 | 0", 4);
344 tstNumOp(pDbgc, "4 | 4", 4);
345 tstNumOp(pDbgc, "1 | 4 | 2", 7);
346
347 tstNumOp(pDbgc, "1 ^ 1", 0);
348 tstNumOp(pDbgc, "1 ^ 0", 1);
349 tstNumOp(pDbgc, "0 ^ 1", 1);
350 tstNumOp(pDbgc, "3 ^ 1", 2);
351 tstNumOp(pDbgc, "7 ^ 3", 4);
352
353 tstNumOp(pDbgc, "7 || 3", 1);
354 tstNumOp(pDbgc, "1 || 0", 1);
355 tstNumOp(pDbgc, "0 || 1", 1);
356 tstNumOp(pDbgc, "0 || 0", 0);
357
358 tstNumOp(pDbgc, "0 && 0", 0);
359 tstNumOp(pDbgc, "1 && 0", 0);
360 tstNumOp(pDbgc, "0 && 1", 0);
361 tstNumOp(pDbgc, "1 && 1", 1);
362 tstNumOp(pDbgc, "4 && 1", 1);
363 }
364
365 if (RTTestErrorCount(g_hTest) == 0)
366 {
367 RTTestSub(g_hTest, "Odd cases");
368 tstTry(pDbgc, "r @rax\n", VINF_SUCCESS);
369 tstTry(pDbgc, "r @eax\n", VINF_SUCCESS);
370 tstTry(pDbgc, "r @ah\n", VINF_SUCCESS);
371 }
372 }
373
374 dbgcDestroy(pDbgc);
375 }
376
377 /*
378 * Summary
379 */
380 return RTTestSummaryAndDestroy(g_hTest);
381}
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