Added test cases to FoundationTestCase to exercise lookup of objc data types and

to evaluate expressions.  Marked with @expectedFailure decorators for the time
being.

Enhanced the lldbtest.TestBase.expect() API to allow an additional keyword arg
named "error".  If the client passes "error=True", it signifies that an error
while running the command is expected.  The golden input is then compared
against the return object's error output.

llvm-svn: 114228
This commit is contained in:
Johnny Chen 2010-09-17 22:28:51 +00:00
parent e53ab6dffc
commit b330786d1f
2 changed files with 81 additions and 5 deletions

View File

@ -1,4 +1,7 @@
"""Set breakpoints on objective-c class and instance methods in foundation."""
"""
Set breakpoints on objective-c class and instance methods in foundation.
Also lookup objective-c data types and evaluate expressions.
"""
import os, time
import unittest2
@ -20,6 +23,18 @@ class FoundationTestCase(TestBase):
self.buildDwarf()
self.break_on_objc_methods()
@unittest2.expectedFailure
def test_data_type_and_expr_with_dsym(self):
"""Lookup objective-c data types and evaluate expressions."""
self.buildDsym()
self.data_type_and_expr_objc()
@unittest2.expectedFailure
def test_data_type_and_expr_with_dwarf(self):
"""Lookup objective-c data types and evaluate expressions."""
self.buildDwarf()
self.data_type_and_expr_objc()
def break_on_objc_methods(self):
"""Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'."""
exe = os.path.join(os.getcwd(), "a.out")
@ -65,6 +80,56 @@ class FoundationTestCase(TestBase):
self.expect("thread backtrace", "Stop at -[NSAutoreleasePool release]",
substrs = ["Foundation`-[NSAutoreleasePool release]"])
def data_type_and_expr_objc(self):
"""Lookup objective-c data types and evaluate expressions."""
exe = os.path.join(os.getcwd(), "a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
# Stop at -[MyString description].
self.expect("breakpoint set -n '-[MyString description]", BREAKPOINT_CREATED,
startstr = "Breakpoint created: 1: name = '-[MyString description]', locations = 1")
self.runCmd("run", RUN_SUCCEEDED)
# The backtrace should show we stop at -[MyString description].
self.expect("thread backtrace", "Stop at -[MyString description]",
substrs = ["a.out`-[MyString description]"])
# Lookup objc data type MyString and evaluate some expressions.
self.expect("image lookup -t NSString", DATA_TYPES_DISPLAYED_CORRECTLY,
substrs = ["@interface NSString : NSObject@end"])
self.expect("image lookup -t MyString", DATA_TYPES_DISPLAYED_CORRECTLY,
substrs = ["@interface MyString : NSObject",
"NSString * str;",
"NSDate * date;"])
self.expect("frame variable -s", VARIABLES_DISPLAYED_CORRECTLY,
substrs = ["ARG: (MyString *) self",
"ARG: (struct objc_selector *) _cmd"])
self.expect("expr self->non_existent_member", VARIABLES_DISPLAYED_CORRECTLY, error=True,
startstr = "error: 'MyString' does not have a member named 'non_existent_member'")
self.expect("frame variable self->str", VARIABLES_DISPLAYED_CORRECTLY,
startstr = "(NSString *) self->str")
# rdar://problem/8447030
# 'frame variable self->date' displays the wrong data member
self.expect("frame variable self->date", VARIABLES_DISPLAYED_CORRECTLY,
startstr = "(NSDate *) self->date")
# TODO: use expression parser.
# (lldb) expr self->str
# error: instance variable 'str' is protected
# error: 1 errors parsing expression
# Couldn't parse the expresssion
# (lldb) expr self->date
# error: instance variable 'date' is protected
# error: 1 errors parsing expression
# Couldn't parse the expresssion
if __name__ == '__main__':
import atexit

View File

@ -397,7 +397,7 @@ 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):
def expect(self, cmd, msg=None, startstr=None, substrs=None, trace=False, error=False):
"""
Similar to runCmd; with additional expect style output matching ability.
@ -405,14 +405,25 @@ class TestBase(unittest2.TestCase):
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'.
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 againt the golden
input, instead.
"""
trace = (True if traceAlways else trace)
# First run the command.
self.runCmd(cmd, trace = (True if trace else False))
# First run the command. If we are expecting error, set check=False.
self.runCmd(cmd, trace = (True if trace else False), check = not error)
# Then compare the output against expected strings.
output = self.res.GetOutput()
output = self.res.GetError() if error else self.res.GetOutput()
# If error is True, the API client expects the command to fail!
if error:
self.assertFalse(self.res.Succeeded(),
"Command '" + cmd + "' is expected to fail!")
matched = output.startswith(startstr) if startstr else True
if startstr and trace: