Skip to content
Snippets Groups Projects
Commit ea88e943 authored by Johnny Chen's avatar Johnny Chen
Browse files

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
parent 99ff7621
No related branches found
No related tags found
No related merge requests found
LEVEL = ../make
C_SOURCES := main.c
include $(LEVEL)/Makefile.rules
"""
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()
//===-- 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 @@ $ ...@@ -97,6 +97,7 @@ $
""" """
import os, sys import os, sys
import re
from subprocess import * from subprocess import *
import time import time
import types import types
...@@ -399,19 +400,24 @@ class TestBase(unittest2.TestCase): ...@@ -399,19 +400,24 @@ class TestBase(unittest2.TestCase):
self.assertTrue(self.res.Succeeded(), self.assertTrue(self.res.Succeeded(),
msg if msg else CMD_MSG(cmd)) 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. Similar to runCmd; with additional expect style output matching ability.
Ask the command interpreter to handle the command and then check its Ask the command interpreter to handle the command and then check its
return status. The 'msg' parameter specifies an informational assert return status. The 'msg' parameter specifies an informational assert
message. We expect the output from running the command to start with 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 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 client is expecting the command to fail. In this case, the error stream
from running the command is retrieved and compared against the golden from running the command is retrieved and compared against the golden
input, instead. 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) trace = (True if traceAlways else trace)
...@@ -426,25 +432,50 @@ class TestBase(unittest2.TestCase): ...@@ -426,25 +432,50 @@ class TestBase(unittest2.TestCase):
self.assertFalse(self.res.Succeeded(), self.assertFalse(self.res.Succeeded(),
"Command '" + cmd + "' is expected to fail!") "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: 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, "Matched" if matched else "Not matched"
print >> sys.stderr 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: for str in substrs:
matched = output.find(str) > 0 matched = output.find(str) > 0
if trace: 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"
keepgoing = matched if matching else not matched
if not keepgoing:
break
if trace:
print >> sys.stderr
# 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" print >> sys.stderr, "Matched" if matched else "Not matched"
if not matched: keepgoing = matched if matching else not matched
if not keepgoing:
break break
if trace: if trace:
print >> sys.stderr print >> sys.stderr
self.assertTrue(matched, msg if msg else CMD_MSG(cmd)) self.assertTrue(matched if matching else not matched,
msg if msg else CMD_MSG(cmd))
def invoke(self, obj, name, trace=False): def invoke(self, obj, name, trace=False):
"""Use reflection to call a method dynamically with no argument.""" """Use reflection to call a method dynamically with no argument."""
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment