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

Reply via email to