forked from OSchip/llvm-project
<rdar://problem/12523238> Commit 3 of 3
Changed all relevant test cases to verify that MightHaveChildren() works correctly for objects of interest Added a bunch of convenience methods for test cases to use: target(), process(), thread() and frame() which mimic the lldb.X convenience variables As a bonus, edited the documentation on the website to describe the new method available for synthetic children providers writers to implement! That's all folks! llvm-svn: 166535
This commit is contained in:
parent
53e767bf6b
commit
44818163ed
|
@ -141,6 +141,9 @@ class LibcxxListDataFormatterTestCase(TestBase):
|
||||||
'[2] = ', '3',
|
'[2] = ', '3',
|
||||||
'[3] = ', '4'])
|
'[3] = ', '4'])
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("numbers_list").MightHaveChildren(), "numbers_list.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
self.runCmd("type format delete int")
|
self.runCmd("type format delete int")
|
||||||
|
|
||||||
self.runCmd("c")
|
self.runCmd("c")
|
||||||
|
@ -151,6 +154,9 @@ class LibcxxListDataFormatterTestCase(TestBase):
|
||||||
'[1]', 'is',
|
'[1]', 'is',
|
||||||
'[2]', 'smart'])
|
'[2]', 'smart'])
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("text_list").MightHaveChildren(), "text_list.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
self.expect("p text_list",
|
self.expect("p text_list",
|
||||||
substrs = ['list has 3 items',
|
substrs = ['list has 3 items',
|
||||||
'\"goofy\"',
|
'\"goofy\"',
|
||||||
|
|
|
@ -118,6 +118,9 @@ class LibcxxMapDataFormatterTestCase(TestBase):
|
||||||
substrs = ['first =',
|
substrs = ['first =',
|
||||||
'second =']);
|
'second =']);
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("ii").MightHaveChildren(), "ii.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
# check that the expression parser does not make use of
|
# check that the expression parser does not make use of
|
||||||
# synthetic children instead of running code
|
# synthetic children instead of running code
|
||||||
# TOT clang has a fix for this, which makes the expression command here succeed
|
# TOT clang has a fix for this, which makes the expression command here succeed
|
||||||
|
@ -180,6 +183,9 @@ class LibcxxMapDataFormatterTestCase(TestBase):
|
||||||
'first = \"three\"',
|
'first = \"three\"',
|
||||||
'second = 3'])
|
'second = 3'])
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("si").MightHaveChildren(), "si.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
# check access-by-index
|
# check access-by-index
|
||||||
self.expect("frame variable si[0]",
|
self.expect("frame variable si[0]",
|
||||||
substrs = ['first = ', 'one',
|
substrs = ['first = ', 'one',
|
||||||
|
@ -238,6 +244,9 @@ class LibcxxMapDataFormatterTestCase(TestBase):
|
||||||
'second = \"!!!\"',
|
'second = \"!!!\"',
|
||||||
'first = 3'])
|
'first = 3'])
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("is").MightHaveChildren(), "is.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
# check access-by-index
|
# check access-by-index
|
||||||
self.expect("frame variable is[0]",
|
self.expect("frame variable is[0]",
|
||||||
substrs = ['first = ',
|
substrs = ['first = ',
|
||||||
|
@ -291,6 +300,9 @@ class LibcxxMapDataFormatterTestCase(TestBase):
|
||||||
'second = \"cat\"',
|
'second = \"cat\"',
|
||||||
'first = \"gatto\"'])
|
'first = \"gatto\"'])
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("ss").MightHaveChildren(), "ss.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
# check access-by-index
|
# check access-by-index
|
||||||
self.expect("frame variable ss[2]",
|
self.expect("frame variable ss[2]",
|
||||||
substrs = ['gatto', 'cat']);
|
substrs = ['gatto', 'cat']);
|
||||||
|
|
|
@ -132,6 +132,9 @@ class StdListDataFormatterTestCase(TestBase):
|
||||||
self.expect("expression numbers_list[0]", matching=False, error=True,
|
self.expect("expression numbers_list[0]", matching=False, error=True,
|
||||||
substrs = ['0x12345678'])
|
substrs = ['0x12345678'])
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("numbers_list").MightHaveChildren(), "numbers_list.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
self.runCmd("n")
|
self.runCmd("n")
|
||||||
|
|
||||||
self.expect("frame variable numbers_list",
|
self.expect("frame variable numbers_list",
|
||||||
|
@ -181,6 +184,9 @@ class StdListDataFormatterTestCase(TestBase):
|
||||||
self.expect("expression text_list[0]", matching=False, error=True,
|
self.expect("expression text_list[0]", matching=False, error=True,
|
||||||
substrs = ['goofy'])
|
substrs = ['goofy'])
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("text_list").MightHaveChildren(), "text_list.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import atexit
|
import atexit
|
||||||
lldb.SBDebugger.Initialize()
|
lldb.SBDebugger.Initialize()
|
||||||
|
|
|
@ -118,6 +118,9 @@ class StdMapDataFormatterTestCase(TestBase):
|
||||||
self.expect("frame variable ii[8]", matching=True,
|
self.expect("frame variable ii[8]", matching=True,
|
||||||
substrs = ['1234567'])
|
substrs = ['1234567'])
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("ii").MightHaveChildren(), "ii.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
# check that the expression parser does not make use of
|
# check that the expression parser does not make use of
|
||||||
# synthetic children instead of running code
|
# synthetic children instead of running code
|
||||||
# TOT clang has a fix for this, which makes the expression command here succeed
|
# TOT clang has a fix for this, which makes the expression command here succeed
|
||||||
|
@ -189,7 +192,10 @@ class StdMapDataFormatterTestCase(TestBase):
|
||||||
self.expect("frame variable si[0]",
|
self.expect("frame variable si[0]",
|
||||||
substrs = ['first = ', 'four',
|
substrs = ['first = ', 'four',
|
||||||
'second = 4']);
|
'second = 4']);
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("si").MightHaveChildren(), "si.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
# check that the expression parser does not make use of
|
# check that the expression parser does not make use of
|
||||||
# synthetic children instead of running code
|
# synthetic children instead of running code
|
||||||
# TOT clang has a fix for this, which makes the expression command here succeed
|
# TOT clang has a fix for this, which makes the expression command here succeed
|
||||||
|
@ -247,7 +253,10 @@ class StdMapDataFormatterTestCase(TestBase):
|
||||||
self.expect("frame variable is[0]",
|
self.expect("frame variable is[0]",
|
||||||
substrs = ['first = ',
|
substrs = ['first = ',
|
||||||
'second =']);
|
'second =']);
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("is").MightHaveChildren(), "is.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
# check that the expression parser does not make use of
|
# check that the expression parser does not make use of
|
||||||
# synthetic children instead of running code
|
# synthetic children instead of running code
|
||||||
# TOT clang has a fix for this, which makes the expression command here succeed
|
# TOT clang has a fix for this, which makes the expression command here succeed
|
||||||
|
@ -304,6 +313,9 @@ class StdMapDataFormatterTestCase(TestBase):
|
||||||
# check access-by-index
|
# check access-by-index
|
||||||
self.expect("frame variable ss[3]",
|
self.expect("frame variable ss[3]",
|
||||||
substrs = ['gatto', 'cat']);
|
substrs = ['gatto', 'cat']);
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("ss").MightHaveChildren(), "ss.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
# check that the expression parser does not make use of
|
# check that the expression parser does not make use of
|
||||||
# synthetic children instead of running code
|
# synthetic children instead of running code
|
||||||
|
|
|
@ -143,6 +143,9 @@ class StdVectorDataFormatterTestCase(TestBase):
|
||||||
self.expect("expression numbers[6]", matching=False, error=True,
|
self.expect("expression numbers[6]", matching=False, error=True,
|
||||||
substrs = ['1234567'])
|
substrs = ['1234567'])
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("numbers").MightHaveChildren(), "numbers.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
# clear out the vector and see that we do the right thing once again
|
# clear out the vector and see that we do the right thing once again
|
||||||
self.runCmd("n")
|
self.runCmd("n")
|
||||||
|
|
||||||
|
@ -204,6 +207,9 @@ class StdVectorDataFormatterTestCase(TestBase):
|
||||||
self.expect("expression strings[0]", matching=False, error=True,
|
self.expect("expression strings[0]", matching=False, error=True,
|
||||||
substrs = ['goofy'])
|
substrs = ['goofy'])
|
||||||
|
|
||||||
|
# check that MightHaveChildren() gets it right
|
||||||
|
self.assertTrue(self.frame().FindVariable("strings").MightHaveChildren(), "strings.MightHaveChildren() says False for non empty!")
|
||||||
|
|
||||||
self.runCmd("n")
|
self.runCmd("n")
|
||||||
|
|
||||||
self.expect("frame variable strings",
|
self.expect("frame variable strings",
|
||||||
|
|
|
@ -72,6 +72,9 @@ class DataFormatterRdar11086338TestCase(TestBase):
|
||||||
self.expect('frame variable other_arr --ptr-depth 2 -d no-run-target',
|
self.expect('frame variable other_arr --ptr-depth 2 -d no-run-target',
|
||||||
substrs = ['@"4 objects"','@"6 objects" {','@"hello"','@"world"','@"this"','@"is"','@"me"','@"http://www.apple.com'])
|
substrs = ['@"4 objects"','@"6 objects" {','@"hello"','@"world"','@"this"','@"is"','@"me"','@"http://www.apple.com'])
|
||||||
|
|
||||||
|
self.assertTrue(self.frame().FindVariable("arr").MightHaveChildren(), "arr says it does not have children!")
|
||||||
|
self.assertTrue(self.frame().FindVariable("other_arr").MightHaveChildren(), "arr says it does not have children!")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import atexit
|
import atexit
|
||||||
|
|
|
@ -74,6 +74,9 @@ class DataFormatterRdar11988289TestCase(TestBase):
|
||||||
self.expect('frame variable mutable --ptr-depth 3 -d no-run-target',
|
self.expect('frame variable mutable --ptr-depth 3 -d no-run-target',
|
||||||
substrs = ['4 key/value pairs','(int)23','@"123"','@"http://www.apple.com"','@"puartist"','3 key/value pairs {','@"bar"','@"2 objects"','(int)1','@"two"'])
|
substrs = ['4 key/value pairs','(int)23','@"123"','@"http://www.apple.com"','@"puartist"','3 key/value pairs {','@"bar"','@"2 objects"','(int)1','@"two"'])
|
||||||
|
|
||||||
|
self.assertTrue(self.frame().FindVariable("dictionary").MightHaveChildren(), "dictionary says it does not have children!")
|
||||||
|
self.assertTrue(self.frame().FindVariable("mutable").MightHaveChildren(), "mutable says it does not have children!")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import atexit
|
import atexit
|
||||||
|
|
|
@ -1021,6 +1021,27 @@ class TestBase(Base):
|
||||||
if lldb.pre_flight:
|
if lldb.pre_flight:
|
||||||
lldb.pre_flight(self)
|
lldb.pre_flight(self)
|
||||||
|
|
||||||
|
# utility methods that tests can use to access the current objects
|
||||||
|
def target(self):
|
||||||
|
if not self.dbg:
|
||||||
|
raise Exception('Invalid debugger instance')
|
||||||
|
return self.dbg.GetSelectedTarget()
|
||||||
|
|
||||||
|
def process(self):
|
||||||
|
if not self.dbg:
|
||||||
|
raise Exception('Invalid debugger instance')
|
||||||
|
return self.dbg.GetSelectedTarget().GetProcess()
|
||||||
|
|
||||||
|
def thread(self):
|
||||||
|
if not self.dbg:
|
||||||
|
raise Exception('Invalid debugger instance')
|
||||||
|
return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread()
|
||||||
|
|
||||||
|
def frame(self):
|
||||||
|
if not self.dbg:
|
||||||
|
raise Exception('Invalid debugger instance')
|
||||||
|
return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
#import traceback
|
#import traceback
|
||||||
#traceback.print_stack()
|
#traceback.print_stack()
|
||||||
|
|
|
@ -1039,8 +1039,12 @@ def function (valobj,internal_dict):<br/>
|
||||||
<i>this call should return a new LLDB SBValue object representing the child at the index given as argument</i> <br/>
|
<i>this call should return a new LLDB SBValue object representing the child at the index given as argument</i> <br/>
|
||||||
<font color=blue>def</font> update(self): <br/>
|
<font color=blue>def</font> update(self): <br/>
|
||||||
<i>this call should be used to update the internal state of this Python object whenever the state of the variables in LLDB changes.</i><sup>[1]</sup><br/>
|
<i>this call should be used to update the internal state of this Python object whenever the state of the variables in LLDB changes.</i><sup>[1]</sup><br/>
|
||||||
|
<font color=blue>def</font> has_children(self): <br/>
|
||||||
|
<i>this call should return True if this object might have children, and False if this object can be guaranteed not to have children.</i><sup>[2]</sup><br/>
|
||||||
</code>
|
</code>
|
||||||
<sup>[1]</sup> This method is optional. Also, it may optionally choose to return a value (starting with LLDB SVN rev153061/LLDB-134). If it returns a value, and that value is <font color=blue><code>True</code></font>, LLDB will be allowed to cache the children and the children count it previously obtained, and will not return to the provider class to ask. If nothing, <font color=blue><code>None</code></font>, or anything other than <font color=blue><code>True</code></font> is returned, LLDB will discard the cached information and ask. Regardless, whenever necessary LLDB will call <code>update</code>.
|
<sup>[1]</sup> This method is optional. Also, it may optionally choose to return a value (starting with LLDB SVN rev153061/LLDB-134). If it returns a value, and that value is <font color=blue><code>True</code></font>, LLDB will be allowed to cache the children and the children count it previously obtained, and will not return to the provider class to ask. If nothing, <font color=blue><code>None</code></font>, or anything other than <font color=blue><code>True</code></font> is returned, LLDB will discard the cached information and ask. Regardless, whenever necessary LLDB will call <code>update</code>.
|
||||||
|
<br/>
|
||||||
|
<sup>[2]</sup> This method is optional, and LLDB will honor it starting with SVN rev166495. While implementing it in terms of <code>num_children</code> is acceptable, implementors are encouraged to look for optimized coding alternatives whenever reasonable. For an example, see the <code>std::list</code> providers shipping with LLDB.
|
||||||
<p>For examples of how synthetic children are created, you are encouraged to look at <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/synthetic/">examples/synthetic</a> in the LLDB trunk.
|
<p>For examples of how synthetic children are created, you are encouraged to look at <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/synthetic/">examples/synthetic</a> in the LLDB trunk.
|
||||||
You may especially want to begin looking at <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/synthetic/bitfield">this example</a> to get
|
You may especially want to begin looking at <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/synthetic/bitfield">this example</a> to get
|
||||||
a feel for this feature, as it is a very easy and well commented example.</p>
|
a feel for this feature, as it is a very easy and well commented example.</p>
|
||||||
|
|
Loading…
Reference in New Issue