#!/usr/bin/env python
+import argparse
+import binascii
import os
+import random
+import re
import sys
-import argparse
import tempfile
import time
-import random
-import binascii
import traceback
import testlib
Exception.__init__(self)
self.message = message
-def run_all_tests(target, tests):
+def run_all_tests(target, tests, fail_fast):
+ good_results = set(('pass', 'not_applicable'))
+
results = {}
module = sys.modules[__name__]
for name in dir(module):
instance = definition(target)
result = instance.run()
results.setdefault(result, []).append(name)
+ if result not in good_results and fail_fast:
+ break
print ":" * 40
- good_results = set(('pass', 'not_applicable'))
-
result = 0
for key, value in results.iteritems():
print "%d tests returned %s" % (len(value), key)
if not a:
raise TestFailed("%r is not True" % a)
+def assertRegexpMatches(text, regexp):
+ if not re.search(regexp, text):
+ raise TestFailed("can't find %r in %r" % (regexp, text))
+
class SimpleRegisterTest(GdbTest):
def check_reg(self, name):
a = random.randrange(1<<self.target.xlen)
def test(self):
self.access_test(8, 'long long')
+class MemTestReadInvalid(SimpleMemoryTest):
+ def test(self):
+ # This test relies on 'gdb_report_data_abort enable' being executed in
+ # the openocd.cfg file.
+ try:
+ self.gdb.p("*((int*)0xdeadbeef)")
+ assert False, "Read should have failed."
+ except testlib.CannotAccess as e:
+ assertEqual(e.address, 0xdeadbeef)
+ self.gdb.p("*((int*)0x%x)" % self.target.ram)
+
+class MemTestWriteInvalid(SimpleMemoryTest):
+ def test(self):
+ # This test relies on 'gdb_report_data_abort enable' being executed in
+ # the openocd.cfg file.
+ try:
+ self.gdb.p("*((int*)0xdeadbeef)=8675309")
+ assert False, "Write should have failed."
+ except testlib.CannotAccess as e:
+ assertEqual(e.address, 0xdeadbeef)
+ self.gdb.p("*((int*)0x%x)=6874742" % self.target.ram)
+
class MemTestBlock(GdbTest):
def test(self):
length = 1024
for _ in range(2):
output = self.gdb.c()
self.gdb.p("$pc")
- assertIn("Breakpoint ", output)
+ assertRegexpMatches(output, r"[bB]reakpoint")
assertIn("rot13 ", output)
self.exit()
for expected in ("main", "rot13", "rot13"):
output = self.gdb.c()
self.gdb.p("$pc")
- assertIn("Breakpoint ", output)
+ assertRegexpMatches(output, r"[bB]reakpoint")
assertIn("%s " % expected, output)
self.exit()
assertIn("_exit", output)
class TriggerExecuteInstant(TriggerTest):
+ """Test an execute breakpoint on the first instruction executed out of
+ debug mode."""
def test(self):
- """Test an execute breakpoint on the first instruction executed out of
- debug mode."""
main_address = self.gdb.p("$pc")
self.gdb.command("hbreak *0x%x" % (main_address + 4))
self.gdb.c()
self.exit()
class TriggerLoadAddressInstant(TriggerTest):
+ """Test a load address breakpoint on the first instruction executed out of
+ debug mode."""
def test(self):
- """Test a load address breakpoint on the first instruction executed out
- of debug mode."""
self.gdb.command("b just_before_read_loop")
self.gdb.c()
read_loop = self.gdb.p("&read_loop")
self.gdb.p("(&data)+3"))
self.exit()
-class TriggerStoreAddressInstance(TriggerTest):
+class TriggerStoreAddressInstant(TriggerTest):
def test(self):
"""Test a store address breakpoint on the first instruction executed out
of debug mode."""
assertEqual(self.gdb.p("$a0"), self.gdb.p("&data"))
class TriggerDmode(TriggerTest):
+ def check_triggers(self, tdata1_lsbs, tdata2):
+ dmode = 1 << (self.target.xlen-5)
+
+ triggers = []
+
+ if self.target.xlen == 32:
+ xlen_type = 'int'
+ elif self.target.xlen == 64:
+ xlen_type = 'long long'
+ else:
+ raise NotImplementedError
+
+ dmode_count = 0
+ i = 0
+ for i in range(16):
+ tdata1 = self.gdb.p("((%s *)&data)[%d]" % (xlen_type, 2*i))
+ if tdata1 == 0:
+ break
+ tdata2 = self.gdb.p("((%s *)&data)[%d]" % (xlen_type, 2*i+1))
+
+ if tdata1 & dmode:
+ dmode_count += 1
+ else:
+ assertEqual(tdata1 & 0xffff, tdata1_lsbs)
+ assertEqual(tdata2, tdata2)
+
+ assertGreater(i, 1)
+ assertEqual(dmode_count, 1)
+
+ return triggers
+
def test(self):
- self.gdb.command("hbreak handle_trap")
- self.gdb.p("$pc=write_valid")
+ self.gdb.command("hbreak write_load_trigger")
+ self.gdb.b("clear_triggers")
+ self.gdb.p("$pc=write_store_trigger")
+ output = self.gdb.c()
+ assertIn("write_load_trigger", output)
+ self.check_triggers((1<<6) | (1<<1), 0xdeadbee0)
output = self.gdb.c()
- assertIn("handle_trap", output)
- assertIn("mcause=2", output)
- assertIn("mepc=%d" % self.gdb.p("&write_invalid_illegal"), output)
+ assertIn("clear_triggers", output)
+ self.check_triggers((1<<6) | (1<<0), 0xfeedac00)
class RegsTest(GdbTest):
compile_args = ("programs/regs.S", )
"the same time. This may make it harder to debug a failure if it "
"does occur.")
+ parser.add_argument("--fail-fast", "-f", action="store_true",
+ help="Exit as soon as any test fails.")
+
parser.add_argument("test", nargs='*',
help="Run only tests that are named here.")
if parsed.xlen:
target.xlen = parsed.xlen
- return run_all_tests(target, parsed.test)
+ return run_all_tests(target, parsed.test, parsed.fail_fast)
# TROUBLESHOOTING TIPS
# If a particular test fails, run just that one test, eg.: