Add some tests that pass and test something.
authorTim Newsome <tim@sifive.com>
Sun, 13 Mar 2016 20:13:15 +0000 (13:13 -0700)
committerTim Newsome <tim@sifive.com>
Mon, 23 May 2016 19:12:10 +0000 (12:12 -0700)
Makefile.in
riscv/gdbserver.cc
tests/debug.c [new file with mode: 0644]
tests/gdbserver-smoke.py [new file with mode: 0755]
tests/testlib.py [new file with mode: 0644]

index 1e353ab9668cd379d3e2f3ccc4843644500431a7..a0f119ab34a60edc5ad31fcd1937ae50af3cb94e 100644 (file)
@@ -335,7 +335,7 @@ deps : $(deps)
 bintest_outs = $(bintests:=.out)
 junk += $(bintest_outs)
 %.out: % all
-       ./$^ < /dev/null 2>&1 | tee $@
+       ./$* < /dev/null 2>&1 | tee $@
 
 check-cpp : $(test_outs)
        echo; grep -h -e'Unit Tests' -e'FAILED' -e'Segmentation' $^ < /dev/null; echo
index 70dac13c6af4b82a15f3b3028df4bc6ac74ac1de..39bfdf85b3be5e61d32492f8187fa7a6c64eebd0 100644 (file)
@@ -529,7 +529,8 @@ void gdbserver_t::handle_breakpoint(const std::vector<uint8_t> &packet)
     return send_packet("E53");
   }
 
-  mmu_t* mmu = sim->debug_mmu;
+  processor_t *p = sim->get_core(0);
+  mmu_t* mmu = p->mmu;
   if (insert) {
     bp.insert(mmu);
     breakpoints[bp.address] = bp;
@@ -540,8 +541,7 @@ void gdbserver_t::handle_breakpoint(const std::vector<uint8_t> &packet)
     breakpoints.erase(bp.address);
   }
   mmu->flush_icache();
-  processor_t *p = sim->get_core(0);
-  p->mmu->flush_icache();
+  sim->debug_mmu->flush_icache();
   return send_packet("OK");
 }
 
diff --git a/tests/debug.c b/tests/debug.c
new file mode 100644 (file)
index 0000000..2cad88f
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+
+char c = 'x';
+
+void print_row(int length)
+{
+    for (int x=0; x<length; x++) {
+        printf("%c", c);
+    }
+    printf("\n");
+}
+
+int main()
+{
+    volatile int i = 42;
+    const char *text = "constant\n";
+    int threshold = 7;
+
+    // Wait for the debugger to get us out of this loop.
+    while (i)
+        ;
+
+    printf("%s", text);
+    for (int y=0; y < 10; y++) {
+        print_row(y);
+    }
+}
diff --git a/tests/gdbserver-smoke.py b/tests/gdbserver-smoke.py
new file mode 100755 (executable)
index 0000000..d9eae92
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+
+import os
+import testlib
+import unittest
+import tempfile
+import time
+
+class SmokeTest(unittest.TestCase):
+    def setUp(self):
+        self.tmpf = tempfile.NamedTemporaryFile()
+        testlib.compile("debug.c", self.tmpf.name)
+        self.spike = testlib.spike(self.tmpf.name, halted=False)
+        self.gdb = testlib.Gdb()
+        self.gdb.command("file %s" % self.tmpf.name)
+        self.gdb.command("target extended-remote localhost:9824")
+        self.gdb.command("p i");
+        self.gdb.command("p i=0");
+
+    def cleanUp(self):
+        self.spike.kill()
+
+    def test_turbostep(self):
+        """Single step until the program exits. TODO"""
+        last_pc = None
+        for _ in range(100):
+            self.gdb.command("stepi")
+            pc = self.gdb.command("p $pc")
+            self.assertNotEqual(last_pc, pc)
+            last_pc = pc
+
+    def test_exit(self):
+        output = self.gdb.command("c")
+        self.assertIn("Continuing", output)
+        self.assertIn("Remote connection closed", output)
+
+    def test_breakpoint(self):
+        self.gdb.command("b print_row")
+        # The breakpoint should be hit exactly 10 times.
+        for _ in range(10):
+            output = self.gdb.command("c")
+            self.assertIn("Continuing", output)
+            self.assertIn("Breakpoint 1", output)
+        output = self.gdb.command("c")
+        self.assertIn("Continuing", output)
+        self.assertIn("Remote connection closed", output)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/testlib.py b/tests/testlib.py
new file mode 100644 (file)
index 0000000..274ba6c
--- /dev/null
@@ -0,0 +1,46 @@
+import os.path
+import pexpect
+import subprocess
+import tempfile
+import testlib
+import unittest
+
+# Note that gdb comes with its own testsuite. I was unable to figure out how to
+# run that testsuite against the spike simulator.
+
+def find_file(path):
+    for directory in (os.getcwd(), os.path.dirname(testlib.__file__)):
+        fullpath = os.path.join(directory, path)
+        if os.path.exists(fullpath):
+            return fullpath
+    raise ValueError("Couldn't find %r." % path)
+
+def compile(src, dst):
+    """Compile a single .c file into a binary."""
+    cc = os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gcc")
+    return os.system("%s -g -o %s %s" % (cc, dst, find_file(src)))
+
+def spike(binary, halted=False):
+    cmd = [find_file("spike")]
+    if halted:
+        cmd.append('-H')
+    cmd += ['pk', binary]
+    logfile = open("spike.log", "w")
+    return subprocess.Popen(cmd, stdout=logfile, stderr=logfile)
+
+class Gdb(object):
+    def __init__(self):
+        path = os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gdb")
+        self.child = pexpect.spawn(path)
+        self.child.logfile = file("gdb.log", "w")
+        self.wait()
+
+    def wait(self):
+        """Wait for prompt."""
+        self.child.expect("\(gdb\)")
+
+    def command(self, command):
+        self.child.sendline(command)
+        self.child.expect("\n")
+        self.child.expect("\(gdb\)")
+        return self.child.before.strip()