Fuzz testing debug tool
Add code to run a fuzz tester, simulating (more-or-less) random keyboard mashing. There's no option to turn it on, you need to set iflags.debug_fuzzer on via a debugger or something along those lines.
This commit is contained in:
@@ -172,6 +172,7 @@ E boolean NDECL(status_hilite_menu);
|
|||||||
|
|
||||||
/* ### cmd.c ### */
|
/* ### cmd.c ### */
|
||||||
|
|
||||||
|
E char NDECL(randomkey);
|
||||||
E int NDECL(doconduct);
|
E int NDECL(doconduct);
|
||||||
E int NDECL(domonability);
|
E int NDECL(domonability);
|
||||||
E char FDECL(cmd_from_func, (int NDECL((*))));
|
E char FDECL(cmd_from_func, (int NDECL((*))));
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ struct instance_flags {
|
|||||||
* behaviour of various NetHack functions and probably warrant
|
* behaviour of various NetHack functions and probably warrant
|
||||||
* a structure of their own elsewhere some day.
|
* a structure of their own elsewhere some day.
|
||||||
*/
|
*/
|
||||||
|
boolean debug_fuzzer; /* fuzz testing */
|
||||||
boolean defer_plname; /* X11 hack: askname() might not set plname */
|
boolean defer_plname; /* X11 hack: askname() might not set plname */
|
||||||
boolean herecmd_menu; /* use menu when mouseclick on yourself */
|
boolean herecmd_menu; /* use menu when mouseclick on yourself */
|
||||||
boolean invis_goldsym; /* gold symbol is ' '? */
|
boolean invis_goldsym; /* gold symbol is ' '? */
|
||||||
|
|||||||
+1
-1
@@ -389,7 +389,7 @@ boolean resuming;
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iflags.sanity_check)
|
if (iflags.sanity_check || iflags.debug_fuzzer)
|
||||||
sanity_check();
|
sanity_check();
|
||||||
|
|
||||||
#ifdef CLIPPING
|
#ifdef CLIPPING
|
||||||
|
|||||||
@@ -298,6 +298,8 @@ pgetchar() /* courtesy of aeb@cwi.nl */
|
|||||||
{
|
{
|
||||||
register int ch;
|
register int ch;
|
||||||
|
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return randomkey();
|
||||||
if (!(ch = popch()))
|
if (!(ch = popch()))
|
||||||
ch = nhgetch();
|
ch = nhgetch();
|
||||||
return (char) ch;
|
return (char) ch;
|
||||||
@@ -942,6 +944,11 @@ wiz_level_change(VOID_ARGS)
|
|||||||
STATIC_PTR int
|
STATIC_PTR int
|
||||||
wiz_panic(VOID_ARGS)
|
wiz_panic(VOID_ARGS)
|
||||||
{
|
{
|
||||||
|
if (iflags.debug_fuzzer) {
|
||||||
|
u.uhp = u.uhpmax = 1000;
|
||||||
|
u.uen = u.uenmax = 1000;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (yn("Do you want to call panic() and end your game?") == 'y')
|
if (yn("Do you want to call panic() and end your game?") == 'y')
|
||||||
panic("Crash test.");
|
panic("Crash test.");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -4354,6 +4361,29 @@ int NDECL((*cmd_func));
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char
|
||||||
|
randomkey()
|
||||||
|
{
|
||||||
|
static int i = 0;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
switch (rn2(12)) {
|
||||||
|
default: c = '\033'; break;
|
||||||
|
case 0: c = '\n'; break;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4: c = (char)(' ' + rn2((int)('~' - ' '))); break;
|
||||||
|
case 5: c = '\t'; break;
|
||||||
|
case 6: c = (char)('a' + rn2((int)('z' - 'a'))); break;
|
||||||
|
case 7: c = (char)('A' + rn2((int)('Z' - 'A'))); break;
|
||||||
|
case 8: c = extcmdlist[(i++) % SIZE(extcmdlist)].key; break;
|
||||||
|
case 9: c = '#'; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ch2spkeys(c, start, end)
|
ch2spkeys(c, start, end)
|
||||||
char c;
|
char c;
|
||||||
@@ -5563,6 +5593,8 @@ readchar()
|
|||||||
register int sym;
|
register int sym;
|
||||||
int x = u.ux, y = u.uy, mod = 0;
|
int x = u.ux, y = u.uy, mod = 0;
|
||||||
|
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return randomkey();
|
||||||
if (*readchar_queue)
|
if (*readchar_queue)
|
||||||
sym = *readchar_queue++;
|
sym = *readchar_queue++;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1061,6 +1061,8 @@ doup()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (ledger_no(&u.uz) == 1) {
|
if (ledger_no(&u.uz) == 1) {
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return 0;
|
||||||
if (yn("Beware, there will be no return! Still climb?") != 'y')
|
if (yn("Beware, there will be no return! Still climb?") != 'y')
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -330,6 +330,8 @@ int sig_unused UNUSED;
|
|||||||
int
|
int
|
||||||
done2()
|
done2()
|
||||||
{
|
{
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return 0;
|
||||||
if (!paranoid_query(ParanoidQuit, "Really quit?")) {
|
if (!paranoid_query(ParanoidQuit, "Really quit?")) {
|
||||||
#ifndef NO_SIGNAL
|
#ifndef NO_SIGNAL
|
||||||
(void) signal(SIGINT, (SIG_RET_TYPE) done1);
|
(void) signal(SIGINT, (SIG_RET_TYPE) done1);
|
||||||
@@ -602,7 +604,7 @@ VA_DECL(const char *, str)
|
|||||||
/* XXX can we move this above the prints? Then we'd be able to
|
/* XXX can we move this above the prints? Then we'd be able to
|
||||||
* suppress "it may be possible to rebuild" based on dosave0()
|
* suppress "it may be possible to rebuild" based on dosave0()
|
||||||
* or say it's NOT possible to rebuild. */
|
* or say it's NOT possible to rebuild. */
|
||||||
if (program_state.something_worth_saving) {
|
if (program_state.something_worth_saving && !iflags.debug_fuzzer) {
|
||||||
set_error_savefile();
|
set_error_savefile();
|
||||||
if (dosave0()) {
|
if (dosave0()) {
|
||||||
/* os/win port specific recover instructions */
|
/* os/win port specific recover instructions */
|
||||||
@@ -1043,6 +1045,14 @@ int how;
|
|||||||
bot();
|
bot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iflags.debug_fuzzer) {
|
||||||
|
if (!(program_state.panicking || how == PANICKED)) {
|
||||||
|
savelife(how);
|
||||||
|
killer.name[0] = 0;
|
||||||
|
killer.format = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
if (how == ASCENDED || (!killer.name[0] && how == GENOCIDED))
|
if (how == ASCENDED || (!killer.name[0] && how == GENOCIDED))
|
||||||
killer.format = NO_KILLER_PREFIX;
|
killer.format = NO_KILLER_PREFIX;
|
||||||
/* Avoid killed by "a" burning or "a" starvation */
|
/* Avoid killed by "a" burning or "a" starvation */
|
||||||
|
|||||||
@@ -642,6 +642,8 @@ struct obj *otmp UNUSED;
|
|||||||
return;
|
return;
|
||||||
#endif /* SIMPLE_MAIL */
|
#endif /* SIMPLE_MAIL */
|
||||||
#ifdef DEF_MAILREADER /* This implies that UNIX is defined */
|
#ifdef DEF_MAILREADER /* This implies that UNIX is defined */
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return;
|
||||||
display_nhwindow(WIN_MESSAGE, FALSE);
|
display_nhwindow(WIN_MESSAGE, FALSE);
|
||||||
if (!(mr = nh_getenv("MAILREADER")))
|
if (!(mr = nh_getenv("MAILREADER")))
|
||||||
mr = DEF_MAILREADER;
|
mr = DEF_MAILREADER;
|
||||||
@@ -674,6 +676,8 @@ ckmailstatus()
|
|||||||
{
|
{
|
||||||
struct mail_info *brdcst;
|
struct mail_info *brdcst;
|
||||||
|
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return;
|
||||||
if (u.uswallow || !flags.biff)
|
if (u.uswallow || !flags.biff)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -453,6 +453,8 @@ VA_DECL(const char *, s)
|
|||||||
Vsprintf(pbuf, s, VA_ARGS);
|
Vsprintf(pbuf, s, VA_ARGS);
|
||||||
pbuf[BUFSZ - 1] = '\0'; /* sanity */
|
pbuf[BUFSZ - 1] = '\0'; /* sanity */
|
||||||
paniclog("impossible", pbuf);
|
paniclog("impossible", pbuf);
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
panic(pbuf);
|
||||||
pline("%s", VA_PASS1(pbuf));
|
pline("%s", VA_PASS1(pbuf));
|
||||||
pline(VA_PASS1(
|
pline(VA_PASS1(
|
||||||
"Program in disorder! (Saving and reloading may fix this problem.)"));
|
"Program in disorder! (Saving and reloading may fix this problem.)"));
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ static unsigned ustuck_id = 0, usteed_id = 0;
|
|||||||
int
|
int
|
||||||
dosave()
|
dosave()
|
||||||
{
|
{
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return 0;
|
||||||
clear_nhwindow(WIN_MESSAGE);
|
clear_nhwindow(WIN_MESSAGE);
|
||||||
if (yn("Really save?") == 'n') {
|
if (yn("Really save?") == 'n') {
|
||||||
clear_nhwindow(WIN_MESSAGE);
|
clear_nhwindow(WIN_MESSAGE);
|
||||||
|
|||||||
@@ -608,6 +608,8 @@ level_tele()
|
|||||||
char buf[BUFSZ];
|
char buf[BUFSZ];
|
||||||
boolean force_dest = FALSE;
|
boolean force_dest = FALSE;
|
||||||
|
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
goto random_levtport;
|
||||||
if ((u.uhave.amulet || In_endgame(&u.uz) || In_sokoban(&u.uz))
|
if ((u.uhave.amulet || In_endgame(&u.uz) || In_sokoban(&u.uz))
|
||||||
&& !wizard) {
|
&& !wizard) {
|
||||||
You_feel("very disoriented for a moment.");
|
You_feel("very disoriented for a moment.");
|
||||||
@@ -750,6 +752,8 @@ level_tele()
|
|||||||
|
|
||||||
killer.name[0] = 0; /* still alive, so far... */
|
killer.name[0] = 0; /* still alive, so far... */
|
||||||
|
|
||||||
|
if (iflags.debug_fuzzer && newlev < 0)
|
||||||
|
goto random_levtport;
|
||||||
if (newlev < 0 && !force_dest) {
|
if (newlev < 0 && !force_dest) {
|
||||||
if (*u.ushops0) {
|
if (*u.ushops0) {
|
||||||
/* take unpaid inventory items off of shop bills */
|
/* take unpaid inventory items off of shop bills */
|
||||||
|
|||||||
+8
-1
@@ -433,6 +433,8 @@ tgetch()
|
|||||||
coord cc;
|
coord cc;
|
||||||
DWORD count;
|
DWORD count;
|
||||||
really_move_cursor();
|
really_move_cursor();
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return randomkey();
|
||||||
return (program_state.done_hup)
|
return (program_state.done_hup)
|
||||||
? '\033'
|
? '\033'
|
||||||
: keyboard_handler.pCheckInput(
|
: keyboard_handler.pCheckInput(
|
||||||
@@ -447,6 +449,8 @@ int *x, *y, *mod;
|
|||||||
coord cc;
|
coord cc;
|
||||||
DWORD count;
|
DWORD count;
|
||||||
really_move_cursor();
|
really_move_cursor();
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return randomkey();
|
||||||
ch = (program_state.done_hup)
|
ch = (program_state.done_hup)
|
||||||
? '\033'
|
? '\033'
|
||||||
: keyboard_handler.pCheckInput(
|
: keyboard_handler.pCheckInput(
|
||||||
@@ -704,7 +708,7 @@ cl_eos()
|
|||||||
void
|
void
|
||||||
tty_nhbell()
|
tty_nhbell()
|
||||||
{
|
{
|
||||||
if (flags.silent)
|
if (flags.silent || iflags.debug_fuzzer)
|
||||||
return;
|
return;
|
||||||
Beep(8000, 500);
|
Beep(8000, 500);
|
||||||
}
|
}
|
||||||
@@ -718,6 +722,9 @@ tty_delay_output()
|
|||||||
clock_t goal;
|
clock_t goal;
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return;
|
||||||
|
|
||||||
goal = 50 + clock();
|
goal = 50 + clock();
|
||||||
back_buffer_flip();
|
back_buffer_flip();
|
||||||
while (goal > clock()) {
|
while (goal > clock()) {
|
||||||
|
|||||||
@@ -748,6 +748,8 @@ tty_delay_output()
|
|||||||
#if defined(MICRO)
|
#if defined(MICRO)
|
||||||
register int i;
|
register int i;
|
||||||
#endif
|
#endif
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return;
|
||||||
#ifdef TIMED_DELAY
|
#ifdef TIMED_DELAY
|
||||||
if (flags.nap) {
|
if (flags.nap) {
|
||||||
(void) fflush(stdout);
|
(void) fflush(stdout);
|
||||||
|
|||||||
@@ -186,6 +186,8 @@ more()
|
|||||||
/* avoid recursion -- only happens from interrupts */
|
/* avoid recursion -- only happens from interrupts */
|
||||||
if (ttyDisplay->inmore++)
|
if (ttyDisplay->inmore++)
|
||||||
return;
|
return;
|
||||||
|
if (iflags.debug_fuzzer)
|
||||||
|
return;
|
||||||
|
|
||||||
if (ttyDisplay->toplin) {
|
if (ttyDisplay->toplin) {
|
||||||
tty_curs(BASE_WINDOW, cw->curx + 1, cw->cury);
|
tty_curs(BASE_WINDOW, cw->curx + 1, cw->cury);
|
||||||
|
|||||||
@@ -3344,6 +3344,9 @@ tty_nhgetch()
|
|||||||
*/
|
*/
|
||||||
if (WIN_MESSAGE != WIN_ERR && wins[WIN_MESSAGE])
|
if (WIN_MESSAGE != WIN_ERR && wins[WIN_MESSAGE])
|
||||||
wins[WIN_MESSAGE]->flags &= ~WIN_STOP;
|
wins[WIN_MESSAGE]->flags &= ~WIN_STOP;
|
||||||
|
if (iflags.debug_fuzzer) {
|
||||||
|
i = randomkey();
|
||||||
|
} else {
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
i = (++nesting == 1) ? tgetch()
|
i = (++nesting == 1) ? tgetch()
|
||||||
: (read(fileno(stdin), (genericptr_t) &nestbuf, 1)
|
: (read(fileno(stdin), (genericptr_t) &nestbuf, 1)
|
||||||
@@ -3352,6 +3355,7 @@ tty_nhgetch()
|
|||||||
#else
|
#else
|
||||||
i = tgetch();
|
i = tgetch();
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
if (!i)
|
if (!i)
|
||||||
i = '\033'; /* map NUL to ESC since nethack doesn't expect NUL */
|
i = '\033'; /* map NUL to ESC since nethack doesn't expect NUL */
|
||||||
else if (i == EOF)
|
else if (i == EOF)
|
||||||
|
|||||||
Reference in New Issue
Block a user