VirtualBox

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

Last change on this file since 96407 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 38.1 KB
Line 
1/* $Id: tstDBGCParser.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * DBGC Testcase - Command Parser.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <VBox/dbg.h>
33#include "../DBGCInternal.h"
34
35#include <iprt/string.h>
36#include <iprt/test.h>
37#include <VBox/err.h>
38
39
40/*********************************************************************************************************************************
41* Internal Functions *
42*********************************************************************************************************************************/
43static DECLCALLBACK(bool) tstDBGCBackInput(PCDBGCIO pBack, uint32_t cMillies);
44static DECLCALLBACK(int) tstDBGCBackRead(PCDBGCIO pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead);
45static DECLCALLBACK(int) tstDBGCBackWrite(PCDBGCIO pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten);
46static DECLCALLBACK(void) tstDBGCBackSetReady(PCDBGCIO pBack, bool fReady);
47
48
49/*********************************************************************************************************************************
50* Global Variables *
51*********************************************************************************************************************************/
52/** The test handle. */
53static RTTEST g_hTest = NIL_RTTEST;
54
55/** The DBGC I/O structure for use in this testcase. */
56static DBGCIO g_tstBack =
57{
58 NULL, /**pfnDestroy*/
59 tstDBGCBackInput,
60 tstDBGCBackRead,
61 tstDBGCBackWrite,
62 tstDBGCBackSetReady
63};
64/** For keeping track of output prefixing. */
65static bool g_fPendingPrefix = true;
66/** Pointer to the current input position. */
67const char *g_pszInput = NULL;
68/** The output of the last command. */
69static char g_szOutput[1024];
70/** The current offset into g_szOutput. */
71static size_t g_offOutput = 0;
72
73
74/**
75 * Checks if there is input.
76 *
77 * @returns true if there is input ready.
78 * @returns false if there not input ready.
79 * @param pBack Pointer to the backend structure supplied by
80 * the backend. The backend can use this to find
81 * it's instance data.
82 * @param cMillies Number of milliseconds to wait on input data.
83 */
84static DECLCALLBACK(bool) tstDBGCBackInput(PCDBGCIO pBack, uint32_t cMillies)
85{
86 return g_pszInput != NULL
87 && *g_pszInput != '\0';
88}
89
90
91/**
92 * Read input.
93 *
94 * @returns VBox status code.
95 * @param pBack Pointer to the backend structure supplied by
96 * the backend. The backend can use this to find
97 * it's instance data.
98 * @param pvBuf Where to put the bytes we read.
99 * @param cbBuf Maximum nymber of bytes to read.
100 * @param pcbRead Where to store the number of bytes actually read.
101 * If NULL the entire buffer must be filled for a
102 * successful return.
103 */
104static DECLCALLBACK(int) tstDBGCBackRead(PCDBGCIO pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead)
105{
106 if (g_pszInput && *g_pszInput)
107 {
108 size_t cb = strlen(g_pszInput);
109 if (cb > cbBuf)
110 cb = cbBuf;
111 *pcbRead = cb;
112 memcpy(pvBuf, g_pszInput, cb);
113 g_pszInput += cb;
114 }
115 else
116 *pcbRead = 0;
117 return VINF_SUCCESS;
118}
119
120
121/**
122 * Write (output).
123 *
124 * @returns VBox status code.
125 * @param pBack Pointer to the backend structure supplied by
126 * the backend. The backend can use this to find
127 * it's instance data.
128 * @param pvBuf What to write.
129 * @param cbBuf Number of bytes to write.
130 * @param pcbWritten Where to store the number of bytes actually written.
131 * If NULL the entire buffer must be successfully written.
132 */
133static DECLCALLBACK(int) tstDBGCBackWrite(PCDBGCIO pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
134{
135 const char *pch = (const char *)pvBuf;
136 if (pcbWritten)
137 *pcbWritten = cbBuf;
138 while (cbBuf-- > 0)
139 {
140 /* screen/log output */
141 if (g_fPendingPrefix)
142 {
143 RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "OUTPUT: ");
144 g_fPendingPrefix = false;
145 }
146 if (*pch == '\n')
147 g_fPendingPrefix = true;
148 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "%c", *pch);
149
150 /* buffer output */
151 if (g_offOutput < sizeof(g_szOutput) - 1)
152 {
153 g_szOutput[g_offOutput++] = *pch;
154 g_szOutput[g_offOutput] = '\0';
155 }
156
157 /* advance */
158 pch++;
159 }
160 return VINF_SUCCESS;
161}
162
163
164/**
165 * Ready / busy notification.
166 *
167 * @param pBack Pointer to the backend structure supplied by
168 * the backend. The backend can use this to find
169 * it's instance data.
170 * @param fReady Whether it's ready (true) or busy (false).
171 */
172static DECLCALLBACK(void) tstDBGCBackSetReady(PCDBGCIO pBack, bool fReady)
173{
174}
175
176
177/**
178 * Completes the output, making sure that we're in
179 * the 1 position of a new line.
180 */
181static void tstCompleteOutput(void)
182{
183 if (!g_fPendingPrefix)
184 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "\n");
185 g_fPendingPrefix = true;
186}
187
188
189/**
190 * Checks if two DBGC variables are identical
191 *
192 * @returns
193 * @param pVar1 .
194 * @param pVar2 .
195 */
196bool DBGCVarAreIdentical(PCDBGCVAR pVar1, PCDBGCVAR pVar2)
197{
198 if (!pVar1)
199 return false;
200 if (pVar1 == pVar2)
201 return true;
202
203 if (pVar1->enmType != pVar2->enmType)
204 return false;
205 switch (pVar1->enmType)
206 {
207 case DBGCVAR_TYPE_GC_FLAT:
208 if (pVar1->u.GCFlat != pVar2->u.GCFlat)
209 return false;
210 break;
211 case DBGCVAR_TYPE_GC_FAR:
212 if (pVar1->u.GCFar.off != pVar2->u.GCFar.off)
213 return false;
214 if (pVar1->u.GCFar.sel != pVar2->u.GCFar.sel)
215 return false;
216 break;
217 case DBGCVAR_TYPE_GC_PHYS:
218 if (pVar1->u.GCPhys != pVar2->u.GCPhys)
219 return false;
220 break;
221 case DBGCVAR_TYPE_HC_FLAT:
222 if (pVar1->u.pvHCFlat != pVar2->u.pvHCFlat)
223 return false;
224 break;
225 case DBGCVAR_TYPE_HC_PHYS:
226 if (pVar1->u.HCPhys != pVar2->u.HCPhys)
227 return false;
228 break;
229 case DBGCVAR_TYPE_NUMBER:
230 if (pVar1->u.u64Number != pVar2->u.u64Number)
231 return false;
232 break;
233 case DBGCVAR_TYPE_STRING:
234 case DBGCVAR_TYPE_SYMBOL:
235 if (RTStrCmp(pVar1->u.pszString, pVar2->u.pszString) != 0)
236 return false;
237 break;
238 default:
239 AssertFailedReturn(false);
240 }
241
242 if (pVar1->enmRangeType != pVar2->enmRangeType)
243 return false;
244 switch (pVar1->enmRangeType)
245 {
246 case DBGCVAR_RANGE_NONE:
247 break;
248
249 case DBGCVAR_RANGE_ELEMENTS:
250 case DBGCVAR_RANGE_BYTES:
251 if (pVar1->u64Range != pVar2->u64Range)
252 return false;
253 break;
254 default:
255 AssertFailedReturn(false);
256 }
257
258 return true;
259}
260
261/**
262 * Tries one command string.
263 * @param pDbgc Pointer to the debugger instance.
264 * @param pszCmds The command to test.
265 * @param rcCmd The expected result.
266 * @param fNoExecute When set, the command is not executed.
267 * @param pszExpected Expected output. This does not need to include all
268 * of the output, just the start of it. Thus the
269 * prompt can be omitted.
270 * @param cArgs The number of expected arguments. -1 if we don't
271 * want to check the parsed arguments.
272 * @param va Info about expected parsed arguments. For each
273 * argument a DBGCVARTYPE, value (depends on type),
274 * DBGCVARRANGETYPE and optionally range value.
275 */
276static void tstTryExV(PDBGC pDbgc, const char *pszCmds, int rcCmd, bool fNoExecute, const char *pszExpected,
277 int32_t cArgs, va_list va)
278{
279 RT_ZERO(g_szOutput);
280 g_offOutput = 0;
281 g_pszInput = pszCmds;
282 if (strchr(pszCmds, '\0')[-1] == '\n')
283 RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s", pszCmds);
284 else
285 RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s\n", pszCmds);
286
287 pDbgc->rcCmd = VERR_INTERNAL_ERROR;
288 dbgcProcessInput(pDbgc, fNoExecute);
289 tstCompleteOutput();
290
291 if (pDbgc->rcCmd != rcCmd)
292 RTTestFailed(g_hTest, "rcCmd=%Rrc expected =%Rrc\n", pDbgc->rcCmd, rcCmd);
293 else if ( !fNoExecute
294 && pszExpected
295 && strncmp(pszExpected, g_szOutput, strlen(pszExpected)))
296 RTTestFailed(g_hTest, "Wrong output - expected \"%s\"", pszExpected);
297
298 if (cArgs >= 0)
299 {
300 PCDBGCVAR paArgs = pDbgc->aArgs;
301 for (int32_t iArg = 0; iArg < cArgs; iArg++)
302 {
303 DBGCVAR ExpectedArg;
304 ExpectedArg.enmType = (DBGCVARTYPE)va_arg(va, int/*DBGCVARTYPE*/);
305 switch (ExpectedArg.enmType)
306 {
307 case DBGCVAR_TYPE_GC_FLAT: ExpectedArg.u.GCFlat = va_arg(va, RTGCPTR); break;
308 case DBGCVAR_TYPE_GC_FAR: ExpectedArg.u.GCFar.sel = va_arg(va, int /*RTSEL*/);
309 ExpectedArg.u.GCFar.off = va_arg(va, uint32_t); break;
310 case DBGCVAR_TYPE_GC_PHYS: ExpectedArg.u.GCPhys = va_arg(va, RTGCPHYS); break;
311 case DBGCVAR_TYPE_HC_FLAT: ExpectedArg.u.pvHCFlat = va_arg(va, void *); break;
312 case DBGCVAR_TYPE_HC_PHYS: ExpectedArg.u.HCPhys = va_arg(va, RTHCPHYS); break;
313 case DBGCVAR_TYPE_NUMBER: ExpectedArg.u.u64Number = va_arg(va, uint64_t); break;
314 case DBGCVAR_TYPE_STRING: ExpectedArg.u.pszString = va_arg(va, const char *); break;
315 case DBGCVAR_TYPE_SYMBOL: ExpectedArg.u.pszString = va_arg(va, const char *); break;
316 default:
317 RTTestFailed(g_hTest, "enmType=%u iArg=%u\n", ExpectedArg.enmType, iArg);
318 ExpectedArg.u.u64Number = 0;
319 break;
320 }
321 ExpectedArg.enmRangeType = (DBGCVARRANGETYPE)va_arg(va, int /*DBGCVARRANGETYPE*/);
322 switch (ExpectedArg.enmRangeType)
323 {
324 case DBGCVAR_RANGE_NONE: ExpectedArg.u64Range = 0; break;
325 case DBGCVAR_RANGE_ELEMENTS: ExpectedArg.u64Range = va_arg(va, uint64_t); break;
326 case DBGCVAR_RANGE_BYTES: ExpectedArg.u64Range = va_arg(va, uint64_t); break;
327 default:
328 RTTestFailed(g_hTest, "enmRangeType=%u iArg=%u\n", ExpectedArg.enmRangeType, iArg);
329 ExpectedArg.u64Range = 0;
330 break;
331 }
332
333 if (!DBGCVarAreIdentical(&ExpectedArg, &paArgs[iArg]))
334 RTTestFailed(g_hTest,
335 "Arg #%u\n"
336 "actual: enmType=%u u64=%#RX64 enmRangeType=%u u64Range=%#RX64\n"
337 "expected: enmType=%u u64=%#RX64 enmRangeType=%u u64Range=%#RX64\n",
338 iArg,
339 paArgs[iArg].enmType, paArgs[iArg].u.u64Number, paArgs[iArg].enmRangeType, paArgs[iArg].u64Range,
340 ExpectedArg.enmType, ExpectedArg.u.u64Number, ExpectedArg.enmRangeType, ExpectedArg.u64Range);
341 }
342 }
343}
344
345/**
346 * Tries one command string.
347 *
348 * @param pDbgc Pointer to the debugger instance.
349 * @param pszCmds The command to test.
350 * @param rcCmd The expected result.
351 * @param fNoExecute When set, the command is not executed.
352 * @param pszExpected Expected output. This does not need to include all
353 * of the output, just the start of it. Thus the
354 * prompt can be omitted.
355 * @param cArgs The number of expected arguments. -1 if we don't
356 * want to check the parsed arguments.
357 * @param ... Info about expected parsed arguments. For each
358 * argument a DBGCVARTYPE, value (depends on type),
359 * DBGCVARRANGETYPE and optionally range value.
360 */
361static void tstTryEx(PDBGC pDbgc, const char *pszCmds, int rcCmd, bool fNoExecute, const char *pszExpected, int32_t cArgs, ...)
362{
363 va_list va;
364 va_start(va, cArgs);
365 tstTryExV(pDbgc, pszCmds, rcCmd, fNoExecute, pszExpected, cArgs, va);
366 va_end(va);
367}
368
369
370/**
371 * Tries one command string without executing it.
372 *
373 * @param pDbgc Pointer to the debugger instance.
374 * @param pszCmds The command to test.
375 * @param rcCmd The expected result.
376 */
377static void tstTry(PDBGC pDbgc, const char *pszCmds, int rcCmd)
378{
379 return tstTryEx(pDbgc, pszCmds, rcCmd, true /*fNoExecute*/, NULL, -1);
380}
381
382
383#ifdef SOME_UNUSED_FUNCTION
384/**
385 * Tries to execute one command string.
386 * @param pDbgc Pointer to the debugger instance.
387 * @param pszCmds The command to test.
388 * @param rcCmd The expected result.
389 * @param pszExpected Expected output. This does not need to include all
390 * of the output, just the start of it. Thus the
391 * prompt can be omitted.
392 */
393static void tstTryExec(PDBGC pDbgc, const char *pszCmds, int rcCmd, const char *pszExpected)
394{
395 return tstTryEx(pDbgc, pszCmds, rcCmd, false /*fNoExecute*/, pszExpected, -1);
396}
397#endif
398
399
400/**
401 * Test an operator on an expression resulting a plain number.
402 *
403 * @param pDbgc Pointer to the debugger instance.
404 * @param pszExpr The express to test.
405 * @param u64Expect The expected result.
406 */
407static void tstNumOp(PDBGC pDbgc, const char *pszExpr, uint64_t u64Expect)
408{
409 char szCmd[80];
410 RTStrPrintf(szCmd, sizeof(szCmd), "format %s\n", pszExpr);
411
412 char szExpected[80];
413 RTStrPrintf(szExpected, sizeof(szExpected),
414 "Number: hex %llx dec 0i%lld oct 0t%llo", u64Expect, u64Expect, u64Expect);
415
416 return tstTryEx(pDbgc, szCmd, VINF_SUCCESS, false /*fNoExecute*/, szExpected, -1);
417}
418
419
420/*
421 *
422 * CodeView emulation commands.
423 * CodeView emulation commands.
424 * CodeView emulation commands.
425 *
426 */
427
428
429static void testCodeView_ba(PDBGC pDbgc)
430{
431 RTTestISub("codeview - ba");
432 tstTry(pDbgc, "ba x 1 0f000:0000\n", VINF_SUCCESS);
433 tstTry(pDbgc, "ba x 1 0f000:0000 0\n", VINF_SUCCESS);
434 tstTry(pDbgc, "ba x 1 0f000:0000 0 ~0\n", VINF_SUCCESS);
435 tstTry(pDbgc, "ba x 1 0f000:0000 0 ~0 \"command\"\n", VINF_SUCCESS);
436 tstTry(pDbgc, "ba x 1 0f000:0000 0 ~0 \"command\" too_many\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
437 tstTry(pDbgc, "ba x 1\n", VERR_DBGC_PARSE_TOO_FEW_ARGUMENTS);
438
439 tstTryEx(pDbgc, "ba x 1 0f000:1234 5 1000 \"command\"\n", VINF_SUCCESS,
440 true /*fNoExecute*/, NULL /*pszExpected*/, 6 /*cArgs*/,
441 DBGCVAR_TYPE_STRING, "x", DBGCVAR_RANGE_BYTES, UINT64_C(1),
442 DBGCVAR_TYPE_NUMBER, UINT64_C(1), DBGCVAR_RANGE_NONE,
443 DBGCVAR_TYPE_GC_FAR, 0xf000, UINT32_C(0x1234), DBGCVAR_RANGE_NONE,
444 DBGCVAR_TYPE_NUMBER, UINT64_C(0x5), DBGCVAR_RANGE_NONE,
445 DBGCVAR_TYPE_NUMBER, UINT64_C(0x1000), DBGCVAR_RANGE_NONE,
446 DBGCVAR_TYPE_STRING, "command", DBGCVAR_RANGE_BYTES, UINT64_C(7));
447
448 tstTryEx(pDbgc, "ba x 1 %0f000:1234 5 1000 \"command\"\n", VINF_SUCCESS,
449 true /*fNoExecute*/, NULL /*pszExpected*/, 6 /*cArgs*/,
450 DBGCVAR_TYPE_STRING, "x", DBGCVAR_RANGE_BYTES, UINT64_C(1),
451 DBGCVAR_TYPE_NUMBER, UINT64_C(1), DBGCVAR_RANGE_NONE,
452 DBGCVAR_TYPE_GC_FLAT, UINT64_C(0xf1234), DBGCVAR_RANGE_NONE,
453 DBGCVAR_TYPE_NUMBER, UINT64_C(0x5), DBGCVAR_RANGE_NONE,
454 DBGCVAR_TYPE_NUMBER, UINT64_C(0x1000), DBGCVAR_RANGE_NONE,
455 DBGCVAR_TYPE_STRING, "command", DBGCVAR_RANGE_BYTES, UINT64_C(7));
456
457 tstTry(pDbgc, "ba x 1 bad:bad 5 1000 \"command\"\n", VINF_SUCCESS);
458 tstTry(pDbgc, "ba x 1 %bad:bad 5 1000 \"command\"\n", VERR_DBGC_PARSE_CONVERSION_FAILED);
459
460 tstTryEx(pDbgc, "ba f 1 0f000:1234 5 1000 \"command\"\n", VINF_SUCCESS,
461 true /*fNoExecute*/, NULL /*pszExpected*/, 6 /*cArgs*/,
462 DBGCVAR_TYPE_STRING, "f", DBGCVAR_RANGE_BYTES, UINT64_C(1),
463 DBGCVAR_TYPE_NUMBER, UINT64_C(1), DBGCVAR_RANGE_NONE,
464 DBGCVAR_TYPE_GC_FAR, 0xf000, UINT32_C(0x1234), DBGCVAR_RANGE_NONE,
465 DBGCVAR_TYPE_NUMBER, UINT64_C(0x5), DBGCVAR_RANGE_NONE,
466 DBGCVAR_TYPE_NUMBER, UINT64_C(0x1000), DBGCVAR_RANGE_NONE,
467 DBGCVAR_TYPE_STRING, "command", DBGCVAR_RANGE_BYTES, UINT64_C(7));
468
469 tstTry(pDbgc, "ba x 1 0f000:1234 qnx 1000 \"command\"\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
470 tstTry(pDbgc, "ba x 1 0f000:1234 5 qnx \"command\"\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
471 tstTry(pDbgc, "ba x qnx 0f000:1234 5 1000 \"command\"\n", VERR_DBGC_PARSE_INVALID_NUMBER);
472 tstTry(pDbgc, "ba x 1 qnx 5 1000 \"command\"\n", VERR_DBGC_PARSE_INVALID_NUMBER);
473}
474
475
476static void testCodeView_bc(PDBGC pDbgc)
477{
478 RTTestISub("codeview - bc");
479}
480
481
482static void testCodeView_bd(PDBGC pDbgc)
483{
484 RTTestISub("codeview - bc");
485}
486
487
488static void testCodeView_be(PDBGC pDbgc)
489{
490 RTTestISub("codeview - be");
491}
492
493
494static void testCodeView_bl(PDBGC pDbgc)
495{
496 RTTestISub("codeview - bl");
497}
498
499
500static void testCodeView_bp(PDBGC pDbgc)
501{
502 RTTestISub("codeview - bp");
503}
504
505
506static void testCodeView_br(PDBGC pDbgc)
507{
508 RTTestISub("codeview - br");
509}
510
511
512static void testCodeView_d(PDBGC pDbgc)
513{
514 RTTestISub("codeview - d");
515}
516
517
518static void testCodeView_da(PDBGC pDbgc)
519{
520 RTTestISub("codeview - da");
521}
522
523
524static void testCodeView_db(PDBGC pDbgc)
525{
526 RTTestISub("codeview - db");
527}
528
529
530static void testCodeView_dd(PDBGC pDbgc)
531{
532 RTTestISub("codeview - dd");
533}
534
535
536static void testCodeView_dg(PDBGC pDbgc)
537{
538 RTTestISub("codeview - dg");
539}
540
541
542static void testCodeView_dga(PDBGC pDbgc)
543{
544 RTTestISub("codeview - dga");
545}
546
547
548static void testCodeView_di(PDBGC pDbgc)
549{
550 RTTestISub("codeview - di");
551}
552
553
554static void testCodeView_dia(PDBGC pDbgc)
555{
556 RTTestISub("codeview - dia");
557}
558
559
560static void testCodeView_dl(PDBGC pDbgc)
561{
562 RTTestISub("codeview - dl");
563}
564
565
566static void testCodeView_dla(PDBGC pDbgc)
567{
568 RTTestISub("codeview - dla");
569}
570
571
572static void testCodeView_dpd(PDBGC pDbgc)
573{
574 RTTestISub("codeview - dpd");
575}
576
577
578static void testCodeView_dpda(PDBGC pDbgc)
579{
580 RTTestISub("codeview - dpda");
581}
582
583
584static void testCodeView_dpdb(PDBGC pDbgc)
585{
586 RTTestISub("codeview - dpdb");
587}
588
589
590static void testCodeView_dpdg(PDBGC pDbgc)
591{
592 RTTestISub("codeview - dpdg");
593}
594
595
596static void testCodeView_dpdh(PDBGC pDbgc)
597{
598 RTTestISub("codeview - dpdh");
599}
600
601
602static void testCodeView_dph(PDBGC pDbgc)
603{
604 RTTestISub("codeview - dph");
605}
606
607
608static void testCodeView_dphg(PDBGC pDbgc)
609{
610 RTTestISub("codeview - dphg");
611}
612
613
614static void testCodeView_dphh(PDBGC pDbgc)
615{
616 RTTestISub("codeview - dphh");
617}
618
619
620static void testCodeView_dq(PDBGC pDbgc)
621{
622 RTTestISub("codeview - dq");
623}
624
625
626static void testCodeView_dt(PDBGC pDbgc)
627{
628 RTTestISub("codeview - dt");
629}
630
631
632static void testCodeView_dt16(PDBGC pDbgc)
633{
634 RTTestISub("codeview - dt16");
635}
636
637
638static void testCodeView_dt32(PDBGC pDbgc)
639{
640 RTTestISub("codeview - dt32");
641}
642
643
644static void testCodeView_dt64(PDBGC pDbgc)
645{
646 RTTestISub("codeview - dt64");
647}
648
649
650static void testCodeView_dw(PDBGC pDbgc)
651{
652 RTTestISub("codeview - dw");
653}
654
655
656static void testCodeView_eb(PDBGC pDbgc)
657{
658 RTTestISub("codeview - eb");
659}
660
661
662static void testCodeView_ew(PDBGC pDbgc)
663{
664 RTTestISub("codeview - ew");
665}
666
667
668static void testCodeView_ed(PDBGC pDbgc)
669{
670 RTTestISub("codeview - ed");
671}
672
673
674static void testCodeView_eq(PDBGC pDbgc)
675{
676 RTTestISub("codeview - eq");
677}
678
679
680static void testCodeView_g(PDBGC pDbgc)
681{
682 RTTestISub("codeview - g");
683}
684
685
686static void testCodeView_k(PDBGC pDbgc)
687{
688 RTTestISub("codeview - k");
689}
690
691
692static void testCodeView_kg(PDBGC pDbgc)
693{
694 RTTestISub("codeview - kg");
695}
696
697
698static void testCodeView_kh(PDBGC pDbgc)
699{
700 RTTestISub("codeview - kh");
701}
702
703
704static void testCodeView_lm(PDBGC pDbgc)
705{
706 RTTestISub("codeview - lm");
707}
708
709
710static void testCodeView_lmo(PDBGC pDbgc)
711{
712 RTTestISub("codeview - lmo");
713}
714
715
716static void testCodeView_ln(PDBGC pDbgc)
717{
718 RTTestISub("codeview - ln");
719}
720
721
722static void testCodeView_ls(PDBGC pDbgc)
723{
724 RTTestISub("codeview - ls");
725}
726
727
728static void testCodeView_m(PDBGC pDbgc)
729{
730 RTTestISub("codeview - m");
731}
732
733
734static void testCodeView_r(PDBGC pDbgc)
735{
736 RTTestISub("codeview - r");
737}
738
739
740static void testCodeView_rg(PDBGC pDbgc)
741{
742 RTTestISub("codeview - rg");
743}
744
745
746static void testCodeView_rg32(PDBGC pDbgc)
747{
748 RTTestISub("codeview - rg32");
749}
750
751
752static void testCodeView_rg64(PDBGC pDbgc)
753{
754 RTTestISub("codeview - rg64");
755}
756
757
758static void testCodeView_rh(PDBGC pDbgc)
759{
760 RTTestISub("codeview - rh");
761}
762
763
764static void testCodeView_rt(PDBGC pDbgc)
765{
766 RTTestISub("codeview - rt");
767}
768
769
770static void testCodeView_s(PDBGC pDbgc)
771{
772 RTTestISub("codeview - s");
773}
774
775
776static void testCodeView_sa(PDBGC pDbgc)
777{
778 RTTestISub("codeview - sa");
779}
780
781
782static void testCodeView_sb(PDBGC pDbgc)
783{
784 RTTestISub("codeview - sb");
785}
786
787
788static void testCodeView_sd(PDBGC pDbgc)
789{
790 RTTestISub("codeview - sd");
791}
792
793
794static void testCodeView_sq(PDBGC pDbgc)
795{
796 RTTestISub("codeview - sq");
797}
798
799
800static void testCodeView_su(PDBGC pDbgc)
801{
802 RTTestISub("codeview - su");
803}
804
805
806static void testCodeView_sw(PDBGC pDbgc)
807{
808 RTTestISub("codeview - sw");
809}
810
811
812static void testCodeView_t(PDBGC pDbgc)
813{
814 RTTestISub("codeview - t");
815}
816
817
818static void testCodeView_y(PDBGC pDbgc)
819{
820 RTTestISub("codeview - y");
821}
822
823
824static void testCodeView_u64(PDBGC pDbgc)
825{
826 RTTestISub("codeview - u64");
827}
828
829
830static void testCodeView_u32(PDBGC pDbgc)
831{
832 RTTestISub("codeview - u32");
833}
834
835
836static void testCodeView_u16(PDBGC pDbgc)
837{
838 RTTestISub("codeview - u16");
839}
840
841
842static void testCodeView_uv86(PDBGC pDbgc)
843{
844 RTTestISub("codeview - uv86");
845}
846
847
848/*
849 * Common commands.
850 */
851
852static void testCommon_bye_exit_quit(PDBGC pDbgc)
853{
854 RTTestISub("common - bye/exit/quit");
855 /* These have the same parameter descriptor and handler, the command really
856 just has a couple of aliases.*/
857 tstTry(pDbgc, "bye\n", VINF_SUCCESS);
858 tstTry(pDbgc, "bye x\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
859 tstTry(pDbgc, "bye 1\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
860 tstTry(pDbgc, "bye %bad:bad\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
861 tstTry(pDbgc, "exit\n", VINF_SUCCESS);
862 tstTry(pDbgc, "quit\n", VINF_SUCCESS);
863}
864
865
866static void testCommon_cpu(PDBGC pDbgc)
867{
868 RTTestISub("common - cpu");
869 tstTry(pDbgc, "cpu\n", VINF_SUCCESS);
870 tstTry(pDbgc, "cpu 1\n", VINF_SUCCESS);
871 tstTry(pDbgc, "cpu 1 1\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
872 tstTry(pDbgc, "cpu emt\n", VERR_DBGC_PARSE_INVALID_NUMBER);
873 tstTry(pDbgc, "cpu @eax\n", VINF_SUCCESS);
874 tstTry(pDbgc, "cpu %bad:bad\n", VERR_DBGC_PARSE_CONVERSION_FAILED);
875 tstTry(pDbgc, "cpu '1'\n", VERR_DBGC_PARSE_INVALID_NUMBER);
876}
877
878
879static void testCommon_echo(PDBGC pDbgc)
880{
881 RTTestISub("common - echo");
882 tstTry(pDbgc, "echo\n", VERR_DBGC_PARSE_TOO_FEW_ARGUMENTS);
883 tstTry(pDbgc, "echo 1\n", VINF_SUCCESS);
884 tstTryEx(pDbgc, "echo 1 2 3 4 5 6\n", VINF_SUCCESS, false, "1 2 3 4 5 6", -1);
885
886 /* The idea here is that since the prefered input is a string, we
887 definitely won't be confused by the number like beginning. */
888 tstTryEx(pDbgc, "echo 1234567890abcdefghijklmn\n", VINF_SUCCESS, false, "1234567890abcdefghijklmn", -1);
889
890 /* The idea here is that we'll perform the + operation and then convert the
891 result to a string (hex). */
892 tstTryEx(pDbgc, "echo 1 + 1\n", VINF_SUCCESS, false, "2", -1);
893 tstTryEx(pDbgc, "echo \"1 + 1\"\n", VINF_SUCCESS, false, "1 + 1", -1);
894
895 tstTryEx(pDbgc, "echo 0i10 + 6\n", VINF_SUCCESS, false, "10", -1);
896 tstTryEx(pDbgc, "echo \"0i10 + 6\"\n", VINF_SUCCESS, false, "0i10 + 6", -1);
897
898 tstTryEx(pDbgc, "echo %f000:0010\n", VINF_SUCCESS, false, "%00000000000f0010", -1);
899 tstTryEx(pDbgc, "echo \"%f000:0010\"\n", VINF_SUCCESS, false, "%f000:0010", -1);
900
901 tstTry(pDbgc, "echo %bad:bad\n", VERR_DBGC_PARSE_CONVERSION_FAILED);
902}
903
904
905static void testCommon_format(PDBGC pDbgc)
906{
907 RTTestISub("common - format");
908}
909
910
911static void testCommon_detect(PDBGC pDbgc)
912{
913 RTTestISub("common - detect");
914}
915
916
917static void testCommon_harakiri(PDBGC pDbgc)
918{
919 RTTestISub("common - harakiri");
920}
921
922
923static void testCommon_help(PDBGC pDbgc)
924{
925 RTTestISub("common - help");
926}
927
928
929static void testCommon_info(PDBGC pDbgc)
930{
931 RTTestISub("common - info");
932 tstTry(pDbgc, "info 12fg\n", VINF_SUCCESS);
933 tstTry(pDbgc, "info fflags argument\n", VINF_SUCCESS);
934}
935
936
937static void testCommon_loadimage(PDBGC pDbgc)
938{
939 RTTestISub("common - loadimage");
940}
941
942
943static void testCommon_loadmap(PDBGC pDbgc)
944{
945 RTTestISub("common - loadmap");
946}
947
948
949static void testCommon_loadplugin(PDBGC pDbgc)
950{
951 RTTestISub("common - loadplugin");
952}
953
954
955static void testCommon_loadseg(PDBGC pDbgc)
956{
957 RTTestISub("common - loadseg");
958}
959
960
961static void testCommon_loadsyms(PDBGC pDbgc)
962{
963 RTTestISub("common - loadsyms");
964}
965
966
967static void testCommon_loadvars(PDBGC pDbgc)
968{
969 RTTestISub("common - loadvars");
970}
971
972
973static void testCommon_log(PDBGC pDbgc)
974{
975 RTTestISub("common - log");
976}
977
978
979static void testCommon_logdest(PDBGC pDbgc)
980{
981 RTTestISub("common - logdest");
982}
983
984
985static void testCommon_logflags(PDBGC pDbgc)
986{
987 RTTestISub("common - logflags");
988}
989
990
991static void testCommon_runscript(PDBGC pDbgc)
992{
993 RTTestISub("common - runscript");
994}
995
996
997static void testCommon_set(PDBGC pDbgc)
998{
999 RTTestISub("common - set");
1000}
1001
1002
1003static void testCommon_showplugins(PDBGC pDbgc)
1004{
1005 RTTestISub("common - showplugins");
1006}
1007
1008
1009static void testCommon_showvars(PDBGC pDbgc)
1010{
1011 RTTestISub("common - showvars");
1012}
1013
1014
1015static void testCommon_stop(PDBGC pDbgc)
1016{
1017 RTTestISub("common - stop");
1018}
1019
1020
1021static void testCommon_unloadplugin(PDBGC pDbgc)
1022{
1023 RTTestISub("common - unloadplugin");
1024}
1025
1026
1027static void testCommon_unset(PDBGC pDbgc)
1028{
1029 RTTestISub("common - unset");
1030}
1031
1032
1033static void testCommon_writecore(PDBGC pDbgc)
1034{
1035 RTTestISub("common - writecore");
1036}
1037
1038
1039
1040/*
1041 * Basic tests.
1042 */
1043
1044static void testBasicsOddCases(PDBGC pDbgc)
1045{
1046 RTTestISub("Odd cases");
1047 tstTry(pDbgc, "r @rax\n", VINF_SUCCESS);
1048 tstTry(pDbgc, "r @eax\n", VINF_SUCCESS);
1049 tstTry(pDbgc, "r @ah\n", VINF_SUCCESS);
1050 tstTry(pDbgc, "r @notavalidregister\n", VERR_DBGF_REGISTER_NOT_FOUND);
1051}
1052
1053
1054static void testBasicsOperators(PDBGC pDbgc)
1055{
1056 RTTestISub("Operators");
1057 tstNumOp(pDbgc, "1", 1);
1058 tstNumOp(pDbgc, "1", 1);
1059 tstNumOp(pDbgc, "1", 1);
1060
1061 tstNumOp(pDbgc, "+1", 1);
1062 tstNumOp(pDbgc, "++++++1", 1);
1063
1064 tstNumOp(pDbgc, "-1", UINT64_MAX);
1065 tstNumOp(pDbgc, "--1", 1);
1066 tstNumOp(pDbgc, "---1", UINT64_MAX);
1067 tstNumOp(pDbgc, "----1", 1);
1068
1069 tstNumOp(pDbgc, "~0", UINT64_MAX);
1070 tstNumOp(pDbgc, "~1", UINT64_MAX-1);
1071 tstNumOp(pDbgc, "~~0", 0);
1072 tstNumOp(pDbgc, "~~1", 1);
1073
1074 tstNumOp(pDbgc, "!1", 0);
1075 tstNumOp(pDbgc, "!0", 1);
1076 tstNumOp(pDbgc, "!42", 0);
1077 tstNumOp(pDbgc, "!!42", 1);
1078 tstNumOp(pDbgc, "!!!42", 0);
1079 tstNumOp(pDbgc, "!!!!42", 1);
1080
1081 tstNumOp(pDbgc, "1 +1", 2);
1082 tstNumOp(pDbgc, "1 + 1", 2);
1083 tstNumOp(pDbgc, "1+1", 2);
1084 tstNumOp(pDbgc, "1+ 1", 2);
1085
1086 tstNumOp(pDbgc, "1 - 1", 0);
1087 tstNumOp(pDbgc, "99 - 90", 9);
1088
1089 tstNumOp(pDbgc, "2 * 2", 4);
1090
1091 tstNumOp(pDbgc, "2 / 2", 1);
1092 tstNumOp(pDbgc, "2 / 0", UINT64_MAX);
1093 tstNumOp(pDbgc, "0i1024 / 0i4", 256);
1094
1095 tstNumOp(pDbgc, "8 mod 7", 1);
1096
1097 tstNumOp(pDbgc, "1<<1", 2);
1098 tstNumOp(pDbgc, "1<<0i32", UINT64_C(0x0000000100000000));
1099 tstNumOp(pDbgc, "1<<0i48", UINT64_C(0x0001000000000000));
1100 tstNumOp(pDbgc, "1<<0i63", UINT64_C(0x8000000000000000));
1101
1102 tstNumOp(pDbgc, "fedcba0987654321>>0i04", UINT64_C(0x0fedcba098765432));
1103 tstNumOp(pDbgc, "fedcba0987654321>>0i32", UINT64_C(0xfedcba09));
1104 tstNumOp(pDbgc, "fedcba0987654321>>0i48", UINT64_C(0x0000fedc));
1105
1106 tstNumOp(pDbgc, "0ef & 4", 4);
1107 tstNumOp(pDbgc, "01234567891 & fff", UINT64_C(0x00000000891));
1108 tstNumOp(pDbgc, "01234567891 & ~fff", UINT64_C(0x01234567000));
1109
1110 tstNumOp(pDbgc, "1 | 1", 1);
1111 tstNumOp(pDbgc, "0 | 4", 4);
1112 tstNumOp(pDbgc, "4 | 0", 4);
1113 tstNumOp(pDbgc, "4 | 4", 4);
1114 tstNumOp(pDbgc, "1 | 4 | 2", 7);
1115
1116 tstNumOp(pDbgc, "1 ^ 1", 0);
1117 tstNumOp(pDbgc, "1 ^ 0", 1);
1118 tstNumOp(pDbgc, "0 ^ 1", 1);
1119 tstNumOp(pDbgc, "3 ^ 1", 2);
1120 tstNumOp(pDbgc, "7 ^ 3", 4);
1121
1122 tstNumOp(pDbgc, "7 || 3", 1);
1123 tstNumOp(pDbgc, "1 || 0", 1);
1124 tstNumOp(pDbgc, "0 || 1", 1);
1125 tstNumOp(pDbgc, "0 || 0", 0);
1126
1127 tstNumOp(pDbgc, "0 && 0", 0);
1128 tstNumOp(pDbgc, "1 && 0", 0);
1129 tstNumOp(pDbgc, "0 && 1", 0);
1130 tstNumOp(pDbgc, "1 && 1", 1);
1131 tstNumOp(pDbgc, "4 && 1", 1);
1132}
1133
1134
1135static void testBasicsFundametalParsing(PDBGC pDbgc)
1136{
1137 RTTestISub("Fundamental parsing");
1138 tstTry(pDbgc, "stop\n", VINF_SUCCESS);
1139 tstTry(pDbgc, "format 1\n", VINF_SUCCESS);
1140 tstTry(pDbgc, "format \n", VERR_DBGC_PARSE_TOO_FEW_ARGUMENTS);
1141 tstTry(pDbgc, "format 0 1 23 4\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
1142 tstTry(pDbgc, "format 'x'\n", VINF_SUCCESS);
1143 tstTry(pDbgc, "format 'x' 'x'\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
1144 tstTry(pDbgc, "format 'x''x'\n", VINF_SUCCESS);
1145 tstTry(pDbgc, "format 'x'\"x\"\n", VERR_DBGC_PARSE_EXPECTED_BINARY_OP);
1146 tstTry(pDbgc, "format 'x'1\n", VERR_DBGC_PARSE_EXPECTED_BINARY_OP);
1147 tstTry(pDbgc, "format (1)1\n", VERR_DBGC_PARSE_EXPECTED_BINARY_OP);
1148 tstTry(pDbgc, "format (1)(1)\n", VERR_DBGC_PARSE_EXPECTED_BINARY_OP);
1149 tstTry(pDbgc, "format (1)''\n", VERR_DBGC_PARSE_EXPECTED_BINARY_OP);
1150 tstTry(pDbgc, "format nosuchfunction(1)\n", VERR_DBGC_PARSE_FUNCTION_NOT_FOUND);
1151 tstTry(pDbgc, "format nosuchfunction(1,2,3)\n", VERR_DBGC_PARSE_FUNCTION_NOT_FOUND);
1152 tstTry(pDbgc, "format nosuchfunction()\n", VERR_DBGC_PARSE_FUNCTION_NOT_FOUND);
1153 tstTry(pDbgc, "format randu32()\n", VINF_SUCCESS);
1154 tstTryEx(pDbgc, "format %0\n", VINF_SUCCESS, false, "Guest flat address: %00000000", -1);
1155 tstTryEx(pDbgc, "format %eax\n", VINF_SUCCESS, false, "Guest flat address: %cafebabe", -1);
1156 tstTry(pDbgc, "sa 3 23 4 'q' \"21123123\" 'b' \n", VINF_SUCCESS);
1157 tstTry(pDbgc, "sa 3,23, 4,'q' ,\"21123123\" , 'b' \n", VINF_SUCCESS);
1158}
1159
1160
1161int main()
1162{
1163 /*
1164 * Init.
1165 */
1166 int rc = RTTestInitAndCreate("tstDBGCParser", &g_hTest);
1167 if (rc)
1168 return rc;
1169 RTTestBanner(g_hTest);
1170
1171 /*
1172 * Create a DBGC instance.
1173 */
1174 RTTestSub(g_hTest, "dbgcCreate");
1175 PDBGC pDbgc;
1176 rc = dbgcCreate(&pDbgc, &g_tstBack, 0);
1177 if (RT_SUCCESS(rc))
1178 {
1179 pDbgc->pVM = (PVM)pDbgc;
1180 pDbgc->pUVM = (PUVM)pDbgc;
1181 rc = dbgcProcessInput(pDbgc, true /* fNoExecute */);
1182 tstCompleteOutput();
1183 if (RT_SUCCESS(rc))
1184 {
1185 /*
1186 * Perform basic tests first.
1187 */
1188 testBasicsFundametalParsing(pDbgc);
1189 if (RTTestErrorCount(g_hTest) == 0)
1190 testBasicsOperators(pDbgc);
1191 if (RTTestErrorCount(g_hTest) == 0)
1192 testBasicsOddCases(pDbgc);
1193
1194 /*
1195 * Test commands.
1196 */
1197 if (RTTestErrorCount(g_hTest) == 0)
1198 {
1199 testCodeView_ba(pDbgc);
1200 testCodeView_bc(pDbgc);
1201 testCodeView_bd(pDbgc);
1202 testCodeView_be(pDbgc);
1203 testCodeView_bl(pDbgc);
1204 testCodeView_bp(pDbgc);
1205 testCodeView_br(pDbgc);
1206 testCodeView_d(pDbgc);
1207 testCodeView_da(pDbgc);
1208 testCodeView_db(pDbgc);
1209 testCodeView_dd(pDbgc);
1210 testCodeView_dg(pDbgc);
1211 testCodeView_dga(pDbgc);
1212 testCodeView_di(pDbgc);
1213 testCodeView_dia(pDbgc);
1214 testCodeView_dl(pDbgc);
1215 testCodeView_dla(pDbgc);
1216 testCodeView_dpd(pDbgc);
1217 testCodeView_dpda(pDbgc);
1218 testCodeView_dpdb(pDbgc);
1219 testCodeView_dpdg(pDbgc);
1220 testCodeView_dpdh(pDbgc);
1221 testCodeView_dph(pDbgc);
1222 testCodeView_dphg(pDbgc);
1223 testCodeView_dphh(pDbgc);
1224 testCodeView_dq(pDbgc);
1225 testCodeView_dt(pDbgc);
1226 testCodeView_dt16(pDbgc);
1227 testCodeView_dt32(pDbgc);
1228 testCodeView_dt64(pDbgc);
1229 testCodeView_dw(pDbgc);
1230 testCodeView_eb(pDbgc);
1231 testCodeView_ew(pDbgc);
1232 testCodeView_ed(pDbgc);
1233 testCodeView_eq(pDbgc);
1234 testCodeView_g(pDbgc);
1235 testCodeView_k(pDbgc);
1236 testCodeView_kg(pDbgc);
1237 testCodeView_kh(pDbgc);
1238 testCodeView_lm(pDbgc);
1239 testCodeView_lmo(pDbgc);
1240 testCodeView_ln(pDbgc);
1241 testCodeView_ls(pDbgc);
1242 testCodeView_m(pDbgc);
1243 testCodeView_r(pDbgc);
1244 testCodeView_rg(pDbgc);
1245 testCodeView_rg32(pDbgc);
1246 testCodeView_rg64(pDbgc);
1247 testCodeView_rh(pDbgc);
1248 testCodeView_rt(pDbgc);
1249 testCodeView_s(pDbgc);
1250 testCodeView_sa(pDbgc);
1251 testCodeView_sb(pDbgc);
1252 testCodeView_sd(pDbgc);
1253 testCodeView_sq(pDbgc);
1254 testCodeView_su(pDbgc);
1255 testCodeView_sw(pDbgc);
1256 testCodeView_t(pDbgc);
1257 testCodeView_y(pDbgc);
1258 testCodeView_u64(pDbgc);
1259 testCodeView_u32(pDbgc);
1260 testCodeView_u16(pDbgc);
1261 testCodeView_uv86(pDbgc);
1262
1263 testCommon_bye_exit_quit(pDbgc);
1264 testCommon_cpu(pDbgc);
1265 testCommon_echo(pDbgc);
1266 testCommon_format(pDbgc);
1267 testCommon_detect(pDbgc);
1268 testCommon_harakiri(pDbgc);
1269 testCommon_help(pDbgc);
1270 testCommon_info(pDbgc);
1271 testCommon_loadimage(pDbgc);
1272 testCommon_loadmap(pDbgc);
1273 testCommon_loadplugin(pDbgc);
1274 testCommon_loadseg(pDbgc);
1275 testCommon_loadsyms(pDbgc);
1276 testCommon_loadvars(pDbgc);
1277 testCommon_log(pDbgc);
1278 testCommon_logdest(pDbgc);
1279 testCommon_logflags(pDbgc);
1280 testCommon_runscript(pDbgc);
1281 testCommon_set(pDbgc);
1282 testCommon_showplugins(pDbgc);
1283 testCommon_showvars(pDbgc);
1284 testCommon_stop(pDbgc);
1285 testCommon_unloadplugin(pDbgc);
1286 testCommon_unset(pDbgc);
1287 testCommon_writecore(pDbgc);
1288 }
1289 }
1290
1291 dbgcDestroy(pDbgc);
1292 }
1293
1294 /*
1295 * Summary
1296 */
1297 return RTTestSummaryAndDestroy(g_hTest);
1298}
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