forked from OSchip/llvm-project
Added a more complex test case of breakpoint commands, which executes a sequence
of 'breakpoint command add/list/remove' commands to set breakpoint callbacks, list them, and then remove one. Modified the lldbtest.TestBase.expect() method to add two additional keyword arguments: o matching (default to True), which, if set to False, reverses the semantics of 'expect' to 'expect not' o patterns (default to None), which specifies a list of regexp patterns to match against the output from running the command TestBreakpointCommand.py uses the matching=False and the patterns=[...] expect() API. llvm-svn: 114480
This commit is contained in:
parent
99ff76212a
commit
ea88e94318
|
@ -0,0 +1,5 @@
|
|||
LEVEL = ../make
|
||||
|
||||
C_SOURCES := main.c
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,115 @@
|
|||
"""
|
||||
Test lldb breakpoint command add/list/remove.
|
||||
"""
|
||||
|
||||
import os, time
|
||||
import unittest2
|
||||
import lldb
|
||||
from lldbtest import *
|
||||
|
||||
class BreakpointCommandTestCase(TestBase):
|
||||
|
||||
mydir = "breakpoint_command"
|
||||
|
||||
@classmethod
|
||||
def classCleanup(cls):
|
||||
system(["/bin/sh", "-c", "rm output.txt"])
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
def test_with_dsym(self):
|
||||
"""Test a sequence of breakpoint command add, list, and remove."""
|
||||
self.buildDsym()
|
||||
self.breakpoint_command_sequence()
|
||||
|
||||
def test_with_dwarf(self):
|
||||
"""Test a sequence of breakpoint command add, list, and remove."""
|
||||
self.buildDwarf()
|
||||
self.breakpoint_command_sequence()
|
||||
|
||||
def breakpoint_command_sequence(self):
|
||||
"""Test a sequence of breakpoint command add, list, and remove."""
|
||||
exe = os.path.join(os.getcwd(), "a.out")
|
||||
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
|
||||
|
||||
# Add two breakpoints on the same line.
|
||||
self.expect("breakpoint set -f main.c -l 12", BREAKPOINT_CREATED,
|
||||
startstr = "Breakpoint created: 1: file ='main.c', line = 12, locations = 1")
|
||||
self.expect("breakpoint set -f main.c -l 12", BREAKPOINT_CREATED,
|
||||
startstr = "Breakpoint created: 2: file ='main.c', line = 12, locations = 1")
|
||||
|
||||
# Now add callbacks for the breakpoints just created.
|
||||
self.runCmd("breakpoint command add -c -o 'frame variable -s' 1")
|
||||
self.runCmd("breakpoint command add -p -o 'here = open(\"output.txt\", \"w\"); print >> here, \"lldb\"; here.close()' 2")
|
||||
|
||||
# Check that the breakpoint commands are correctly set.
|
||||
|
||||
# The breakpoint list now only contains breakpoint 1.
|
||||
self.expect("breakpoint list", "Breakpoints 1 & 2 created",
|
||||
substrs = ["1: file ='main.c', line = 12, locations = 1",
|
||||
"2: file ='main.c', line = 12, locations = 1"],
|
||||
patterns = ["1.1: .+at main.c:12, .+unresolved, hit count = 0",
|
||||
"2.1: .+at main.c:12, .+unresolved, hit count = 0"])
|
||||
|
||||
self.expect("breakpoint command list 1", "Breakpoint 1 command ok",
|
||||
substrs = ["Breakpoint commands:",
|
||||
"frame variable -s"])
|
||||
self.expect("breakpoint command list 2", "Breakpoint 2 command ok",
|
||||
substrs = ["Breakpoint commands:",
|
||||
"here = open",
|
||||
"print >> here",
|
||||
"here.close()"])
|
||||
|
||||
# Run the program.
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
|
||||
# Check that the file 'output.txt' exists and contains the string "lldb".
|
||||
|
||||
# Read the output file produced by running the program.
|
||||
output = open('output.txt', 'r').read()
|
||||
|
||||
self.assertTrue(output.startswith("lldb"),
|
||||
"File 'output.txt' and the content matches")
|
||||
|
||||
# Finish the program.
|
||||
self.runCmd("process continue")
|
||||
|
||||
# Remove the breakpoint command associated with breakpoint 1.
|
||||
self.runCmd("breakpoint command remove 1")
|
||||
|
||||
# Remove breakpoint 2.
|
||||
self.runCmd("breakpoint delete 2")
|
||||
|
||||
self.expect("breakpoint command list 1",
|
||||
startstr = "Breakpoint 1 does not have an associated command.")
|
||||
self.expect("breakpoint command list 2", error=True,
|
||||
startstr = "error: '2' is not a currently valid breakpoint id.")
|
||||
|
||||
# The breakpoint list now only contains breakpoint 1.
|
||||
self.expect("breakpoint list", "Breakpoint 1 exists",
|
||||
substrs = ["1: file ='main.c', line = 12, locations = 1, resolved = 1",
|
||||
"hit count = 1"])
|
||||
|
||||
# Not breakpoint 2.
|
||||
self.expect("breakpoint list", "No more breakpoint 2", matching=False,
|
||||
substrs = ["2: file ='main.c', line = 12, locations = 1, resolved = 1"])
|
||||
|
||||
# Run the program again, with breakpoint 1 remaining.
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
|
||||
# We should be stopped again due to breakpoint 1.
|
||||
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs = ['state is Stopped',
|
||||
'stop reason = breakpoint'])
|
||||
|
||||
# The breakpoint should have a hit count of 2.
|
||||
self.expect("breakpoint list", BREAKPOINT_HIT_ONCE,
|
||||
substrs = ['resolved, hit count = 2'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
|
@ -0,0 +1,13 @@
|
|||
//===-- main.c --------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
int main (int argc, char const *argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -97,6 +97,7 @@ $
|
|||
"""
|
||||
|
||||
import os, sys
|
||||
import re
|
||||
from subprocess import *
|
||||
import time
|
||||
import types
|
||||
|
@ -399,19 +400,24 @@ class TestBase(unittest2.TestCase):
|
|||
self.assertTrue(self.res.Succeeded(),
|
||||
msg if msg else CMD_MSG(cmd))
|
||||
|
||||
def expect(self, cmd, msg=None, startstr=None, substrs=None, trace=False, error=False):
|
||||
def expect(self, cmd, msg=None, patterns=None, startstr=None, substrs=None, trace=False, error=False, matching=True):
|
||||
"""
|
||||
Similar to runCmd; with additional expect style output matching ability.
|
||||
|
||||
Ask the command interpreter to handle the command and then check its
|
||||
return status. The 'msg' parameter specifies an informational assert
|
||||
message. We expect the output from running the command to start with
|
||||
'startstr' and matches the substrings contained in 'substrs'.
|
||||
'startstr', matches the substrings contained in 'substrs', and regexp
|
||||
matches the patterns contained in 'patterns'.
|
||||
|
||||
If the keyword argument error is set to True, it signifies that the API
|
||||
client is expecting the command to fail. In this case, the error stream
|
||||
from running the command is retrieved and compared against the golden
|
||||
input, instead.
|
||||
|
||||
If the keyword argument matching is set to False, it signifies that the API
|
||||
client is expecting the output of the command not to match the golden
|
||||
input.
|
||||
"""
|
||||
trace = (True if traceAlways else trace)
|
||||
|
||||
|
@ -426,25 +432,50 @@ class TestBase(unittest2.TestCase):
|
|||
self.assertFalse(self.res.Succeeded(),
|
||||
"Command '" + cmd + "' is expected to fail!")
|
||||
|
||||
matched = output.startswith(startstr) if startstr else True
|
||||
# The heading says either "Expecting" or "Not expecting".
|
||||
if trace:
|
||||
heading = "Expecting" if matching else "Not expecting"
|
||||
|
||||
# Start from the startstr, if specified.
|
||||
# If there's no startstr, set the initial state appropriately.
|
||||
matched = output.startswith(startstr) if startstr else (True if matching else False)
|
||||
|
||||
if startstr and trace:
|
||||
print >> sys.stderr, "Expecting start string:", startstr
|
||||
print >> sys.stderr, "%s start string: %s" % (heading, startstr)
|
||||
print >> sys.stderr, "Matched" if matched else "Not matched"
|
||||
print >> sys.stderr
|
||||
|
||||
if substrs and matched:
|
||||
# Look for sub strings, if specified.
|
||||
keepgoing = matched if matching else not matched
|
||||
if substrs and keepgoing:
|
||||
for str in substrs:
|
||||
matched = output.find(str) > 0
|
||||
if trace:
|
||||
print >> sys.stderr, "Expecting sub string:", str
|
||||
print >> sys.stderr, "%s sub string: %s" % (heading, str)
|
||||
print >> sys.stderr, "Matched" if matched else "Not matched"
|
||||
if not matched:
|
||||
keepgoing = matched if matching else not matched
|
||||
if not keepgoing:
|
||||
break
|
||||
if trace:
|
||||
print >> sys.stderr
|
||||
|
||||
self.assertTrue(matched, msg if msg else CMD_MSG(cmd))
|
||||
# Search for regular expression patterns, if specified.
|
||||
keepgoing = matched if matching else not matched
|
||||
if patterns and keepgoing:
|
||||
for pattern in patterns:
|
||||
# Match Objects always have a boolean value of True.
|
||||
matched = bool(re.search(pattern, output))
|
||||
if trace:
|
||||
print >> sys.stderr, "%s pattern: %s" % (heading, pattern)
|
||||
print >> sys.stderr, "Matched" if matched else "Not matched"
|
||||
keepgoing = matched if matching else not matched
|
||||
if not keepgoing:
|
||||
break
|
||||
if trace:
|
||||
print >> sys.stderr
|
||||
|
||||
self.assertTrue(matched if matching else not matched,
|
||||
msg if msg else CMD_MSG(cmd))
|
||||
|
||||
def invoke(self, obj, name, trace=False):
|
||||
"""Use reflection to call a method dynamically with no argument."""
|
||||
|
|
Loading…
Reference in New Issue