Author: Armin Rigo <ar...@tunes.org> Branch: reverse-debugger Changeset: r85084:2f0463f67465 Date: 2016-06-11 08:38 +0200 http://bitbucket.org/pypy/pypy/changeset/2f0463f67465/
Log: 'forward' command diff --git a/rpython/translator/revdb/rdb-src/revdb.c b/rpython/translator/revdb/rdb-src/revdb.c --- a/rpython/translator/revdb/rdb-src/revdb.c +++ b/rpython/translator/revdb/rdb-src/revdb.c @@ -184,7 +184,8 @@ static int frozen_pipe_signal[2]; enum { PK_MAIN_PROCESS, PK_FROZEN_PROCESS, PK_DEBUG_PROCESS }; -static int process_kind = PK_MAIN_PROCESS; +static unsigned char process_kind = PK_MAIN_PROCESS; +static unsigned char flag_exit_run_debug_process; static uint64_t latest_fork; static uint64_t total_stop_points; @@ -316,6 +317,8 @@ a++; } if (a->name != NULL) { + while (isspace(*p)) + p++; a->act(p); } else if (strcmp(input, "help") == 0) { @@ -356,11 +359,25 @@ return 0; } +static void cmd_go(uint64_t target_time) +{ + assert(process_kind == PK_DEBUG_PROCESS); + write_pipe(frozen_pipe_signal[WR_SIDE], &target_time, + sizeof(target_time)); + exit(0); +} + static void check_at_end(uint64_t stop_points) { char dummy[1]; uint64_t target_time; + if (process_kind == PK_DEBUG_PROCESS) { + printf("At end.\n"); + cmd_go(rpy_revdb.stop_point_seen); + abort(); /* unreachable */ + } + if (process_kind != PK_MAIN_PROCESS) { fprintf(stderr, "[%d] Unexpectedly falling off the end\n", process_kind); @@ -502,6 +519,8 @@ rpy_revdb.stop_point_break = total_stop_points; else rpy_revdb.stop_point_break += delta; + if (rpy_revdb.stop_point_seen == rpy_revdb.stop_point_break) + rpy_revdb.stop_point_break++; close(fds[RD_SIDE]); fds[RD_SIDE] = -1; } @@ -509,22 +528,17 @@ static void act_quit(char *p) { - uint64_t target_time = (uint64_t)-1; - write_pipe(frozen_pipe_signal[WR_SIDE], &target_time, - sizeof(target_time)); - exit(0); + cmd_go((uint64_t)-1); } static void act_go(char *p) { - uint64_t target_time = strtoull(p, NULL, 10); - if (target_time == 0) { - printf("usage: go <target time>\n"); + int64_t target_time = strtoll(p, NULL, 10); + if (target_time <= 0) { + printf("usage: go <target_time>\n"); return; } - write_pipe(frozen_pipe_signal[WR_SIDE], &target_time, - sizeof(target_time)); - exit(0); + cmd_go(target_time); } static void act_info_fork(char *p) @@ -545,16 +559,30 @@ { } +static void act_forward(char *p) +{ + int64_t delta = strtoll(p, NULL, 10); + if (delta <= 0) { + if (delta < 0 || *p == 0) + printf("usage: forward <time_steps>\n"); + return; + } + rpy_revdb.stop_point_break = rpy_revdb.stop_point_seen + delta; + flag_exit_run_debug_process = 1; +} + static void run_debug_process(void) { static struct action_s actions_1[] = { { "go", act_go }, + { "forward", act_forward }, { "info", act_info }, { "quit", act_quit }, { "", act_nop }, { NULL } }; - while (1) { + flag_exit_run_debug_process = 0; + while (!flag_exit_run_debug_process) { char input[256]; printf("(%llu)$ ", (unsigned long long)rpy_revdb.stop_point_seen); fflush(stdout); @@ -569,12 +597,13 @@ RPY_EXTERN void rpy_reverse_db_break(long stop_point) { - if (process_kind == PK_MAIN_PROCESS) + if (process_kind == PK_MAIN_PROCESS) { make_new_frozen_process(); - - if (process_kind == PK_DEBUG_PROCESS) - if (rpy_revdb.stop_point_seen == rpy_revdb.stop_point_break) - run_debug_process(); + if (rpy_revdb.stop_point_seen != rpy_revdb.stop_point_break) + return; + } + assert(process_kind == PK_DEBUG_PROCESS); + run_debug_process(); } diff --git a/rpython/translator/revdb/test/test_basic.py b/rpython/translator/revdb/test/test_basic.py --- a/rpython/translator/revdb/test/test_basic.py +++ b/rpython/translator/revdb/test/test_basic.py @@ -5,6 +5,11 @@ from rpython.translator.interactive import Translation from rpython.rlib.rarithmetic import LONG_BIT from rpython.rlib import revdb +""" +These tests require pexpect (UNIX-only). +http://pexpect.sourceforge.net/ +""" +import pexpect class RDB(object): @@ -32,34 +37,39 @@ return self.cur == len(self.buffer) +def compile(self, entry_point, argtypes, backendopt=True): + t = Translation(entry_point, None, gc="boehm") + self.t = t + t.config.translation.reverse_debugger = True + t.config.translation.rweakref = False + t.config.translation.lldebug0 = True + if not backendopt: + t.disable(["backendopt_lltype"]) + t.annotate() + t.rtype() + if t.backendopt: + t.backendopt() + self.exename = t.compile_c() + self.rdbname = os.path.join(os.path.dirname(str(self.exename)), + 'log.rdb') + +def run(self, *argv): + env = os.environ.copy() + env['PYPYREVDB'] = self.rdbname + t = self.t + stdout, stderr = t.driver.cbuilder.cmdexec(' '.join(argv), env=env, + expect_crash=9) + print >> sys.stderr, stderr + return stdout + +def fetch_rdb(self): + return RDB(self.rdbname) + + class BaseTests(object): - - def compile(self, entry_point, argtypes, backendopt=True): - t = Translation(entry_point, None, gc="boehm") - self.t = t - t.config.translation.reverse_debugger = True - t.config.translation.rweakref = False - if not backendopt: - t.disable(["backendopt_lltype"]) - t.annotate() - t.rtype() - if t.backendopt: - t.backendopt() - self.exename = t.compile_c() - self.rdbname = os.path.join(os.path.dirname(str(self.exename)), - 'log.rdb') - - def run(self, *argv): - env = os.environ.copy() - env['PYPYREVDB'] = self.rdbname - t = self.t - stdout, stderr = t.driver.cbuilder.cmdexec(' '.join(argv), env=env, - expect_crash=9) - print >> sys.stderr, stderr - return stdout - - def fetch_rdb(self): - return RDB(self.rdbname) + compile = compile + run = run + fetch_rdb = fetch_rdb class TestRecording(BaseTests): @@ -99,50 +109,75 @@ assert got == [self.exename, 'abc', 'd'] -class TestInteraction(BaseTests): - """ - These tests require pexpect (UNIX-only). - http://pexpect.sourceforge.net/ - """ +class InteractiveTests(object): + EOF = pexpect.EOF + def replay(self, **kwds): - import pexpect - self.EOF = pexpect.EOF kwds.setdefault('timeout', 10) child = pexpect.spawn(str(self.exename), ['--replay', str(self.rdbname)], **kwds) child.logfile = sys.stdout + def expectx(s): + child.expect(re.escape(s)) + assert not hasattr(child, 'expectx') + child.expectx = expectx return child - def test_simple_interpreter(self): + +class TestSimpleInterpreter(InteractiveTests): + + def setup_class(cls): def main(argv): for op in argv[1:]: revdb.stop_point(42) print op return 9 - self.compile(main, [], backendopt=False) - assert self.run('abc d ef') == 'abc\nd\nef\n' - assert self.fetch_rdb().number_of_stop_points() == 3 + compile(cls, main, [], backendopt=False) + assert run(cls, 'abc d ef') == 'abc\nd\nef\n' + assert fetch_rdb(cls).number_of_stop_points() == 3 + def test_go(self): child = self.replay() + child.expectx('stop_points=3\r\n') + child.expectx('(3)$ ') + child.sendline('go 1') + child.expectx('(1)$ ') + child.sendline('') + child.expectx('(1)$ ') + child.sendline('go 52') + child.expectx('(3)$ ') - def wait(s): - child.expect(re.escape(s)) + def test_help(self): + child = self.replay() + child.sendline('help') + child.expectx('select command:\r\n') + # ... + child.expectx('(3)$ ') + child.sendline('info') + child.expectx("bad category '', try 'help'\r\n") - wait('stop_points=3\r\n') - wait('(3)$ ') - child.sendline('go 1') - wait('(1)$ ') - child.sendline('') - wait('(1)$ ') - child.sendline('go 52') - wait('(3)$ ') - child.sendline('help') - wait('select command:\r\n') - # ... - wait('(3)$ ') - child.sendline('info') - wait("bad category '', try 'help'\r\n") + def test_info_fork(self): + child = self.replay() child.sendline('info fork') - wait('latest_fork=3\r\n') + child.expectx('latest_fork=3\r\n') + + def test_quit(self): + child = self.replay() child.sendline('quit') child.expect(self.EOF) + + def test_forward(self): + child = self.replay() + child.sendline('go 1') + child.expectx('(1)$ ') + child.sendline('forward 1') + child.expectx('(2)$ ') + child.sendline('forward 1') + child.expectx('(3)$ ') + child.sendline('info fork') + child.expectx('latest_fork=1\r\n') + child.sendline('forward 1') + child.expectx('At end.\r\n') + child.expectx('(3)$ ') + child.sendline('info fork') + child.expectx('latest_fork=3\r\n') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit