Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit