diff options
author | Johnny Chen <johnny.chen@apple.com> | 2011-07-25 19:32:35 +0000 |
---|---|---|
committer | Johnny Chen <johnny.chen@apple.com> | 2011-07-25 19:32:35 +0000 |
commit | 482250533847640bb98500e04ba6af3bb968228a (patch) | |
tree | 51b43c160cb1d832606c70ea7e5fd30942cf7c94 /lldb/test/python_api | |
parent | 875ebd5f5d6fa0d447244d376cc95853b652bca6 (diff) | |
download | bcm5719-llvm-482250533847640bb98500e04ba6af3bb968228a.tar.gz bcm5719-llvm-482250533847640bb98500e04ba6af3bb968228a.zip |
Provide an add-on API to SBValue class by post-processing to provide a way
to iterate through an SBValue instance by treating it as the head of a linked
list. API program must provide two args to the linked_list_iter() method:
the first being the child member name which points to the next item on the list
and the second being a Python function which an SBValue (for the next item) and
returns True if end of list is reached, otherwise it returns False.
For example, suppose we have the following sample program.
#include <stdio.h>
class Task {
public:
int id;
Task *next;
Task(int i, Task *n):
id(i),
next(n)
{}
};
int main (int argc, char const *argv[])
{
Task *task_head = new Task(-1, NULL);
Task *task1 = new Task(1, NULL);
Task *task2 = new Task(2, NULL);
Task *task3 = new Task(3, NULL); // Orphaned.
Task *task4 = new Task(4, NULL);
Task *task5 = new Task(5, NULL);
task_head->next = task1;
task1->next = task2;
task2->next = task4;
task4->next = task5;
int total = 0; // Break at this line
Task *t = task_head;
while (t != NULL) {
if (t->id >= 0)
++total;
t = t->next;
}
printf("We have a total number of %d tasks\n", total);
return 0;
}
The test program produces the following output while exercising the linked_list_iter() SBVAlue API:
task_head:
TypeName -> Task *
ByteSize -> 8
NumChildren -> 2
Value -> 0x0000000106400380
ValueType -> local_variable
Summary -> None
IsPointerType -> True
Location -> 0x00007fff65f06e60
(Task *) next = 0x0000000106400390
(int) id = 1
(Task *) next = 0x00000001064003a0
(Task *) next = 0x00000001064003a0
(int) id = 2
(Task *) next = 0x00000001064003c0
(Task *) next = 0x00000001064003c0
(int) id = 4
(Task *) next = 0x00000001064003d0
(Task *) next = 0x00000001064003d0
(int) id = 5
(Task *) next = 0x0000000000000000
llvm-svn: 135938
Diffstat (limited to 'lldb/test/python_api')
-rw-r--r-- | lldb/test/python_api/value/linked_list/Makefile | 5 | ||||
-rw-r--r-- | lldb/test/python_api/value/linked_list/TestValueAPILinkedList.py | 96 | ||||
-rw-r--r-- | lldb/test/python_api/value/linked_list/main.cpp | 45 |
3 files changed, 146 insertions, 0 deletions
diff --git a/lldb/test/python_api/value/linked_list/Makefile b/lldb/test/python_api/value/linked_list/Makefile new file mode 100644 index 00000000000..314f1cb2f07 --- /dev/null +++ b/lldb/test/python_api/value/linked_list/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/test/python_api/value/linked_list/TestValueAPILinkedList.py b/lldb/test/python_api/value/linked_list/TestValueAPILinkedList.py new file mode 100644 index 00000000000..2720b2cef23 --- /dev/null +++ b/lldb/test/python_api/value/linked_list/TestValueAPILinkedList.py @@ -0,0 +1,96 @@ +""" +Test SBValue API linked_list_iter which treats the SBValue as a linked list and +supports iteration till the end of list is reached. +""" + +import os, time +import re +import unittest2 +import lldb, lldbutil +from lldbtest import * + +class ValueAsLinkedListTestCase(TestBase): + + mydir = os.path.join("python_api", "value", "linked_list") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @python_api_test + def test_with_dsym(self): + """Exercise SBValue API linked_list_iter.""" + d = {'EXE': self.exe_name} + self.buildDsym(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.linked_list_api(self.exe_name) + + @python_api_test + def test_with_dwarf(self): + """Exercise SBValue API linked_list_iter.""" + d = {'EXE': self.exe_name} + self.buildDwarf(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.linked_list_api(self.exe_name) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # We'll use the test method name as the exe_name. + self.exe_name = self.testMethodName + # Find the line number to break at. + self.line = line_number('main.cpp', '// Break at this line') + + def linked_list_api(self, exe_name): + """Exercise SBValue API linked_list-iter.""" + exe = os.path.join(os.getcwd(), exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint inside function 'main'. + breakpoint = target.BreakpointCreateByLocation('main.cpp', self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple(None, None, os.getcwd()) + self.assertTrue(process, PROCESS_IS_VALID) + + def eol(val): + """Test to determine end of list.""" + if not val: + return True + try: + id = val.GetChildMemberWithName("id") + if int(id.GetValue()) > 0: + return False + except: + #exc_type, exc_value, exc_tb = sys.exc_info() + #traceback.print_exception(exc_type, exc_value, exc_tb) + pass + + # If we fall through to here. It could be that exception + # occurred or the "id" child member does not qualify as a + # valid item. Return True for EOL. + return True + + # Get Frame #0. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + + # Get variable 'task_head'. + task_head = frame0.FindVariable('task_head') + self.assertTrue(task_head, VALID_VARIABLE) + self.DebugSBValue(task_head) + + cvf = lldbutil.ChildVisitingFormatter(indent_child=2) + for t in task_head.linked_list_iter('next', eol): + self.assertTrue(t, VALID_VARIABLE) + if self.TraceOn(): + print cvf.format(t) + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/python_api/value/linked_list/main.cpp b/lldb/test/python_api/value/linked_list/main.cpp new file mode 100644 index 00000000000..772d5ed5d1b --- /dev/null +++ b/lldb/test/python_api/value/linked_list/main.cpp @@ -0,0 +1,45 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +class Task { +public: + int id; + Task *next; + Task(int i, Task *n): + id(i), + next(n) + {} +}; + + +int main (int argc, char const *argv[]) +{ + Task *task_head = new Task(-1, NULL); + Task *task1 = new Task(1, NULL); + Task *task2 = new Task(2, NULL); + Task *task3 = new Task(3, NULL); // Orphaned. + Task *task4 = new Task(4, NULL); + Task *task5 = new Task(5, NULL); + + task_head->next = task1; + task1->next = task2; + task2->next = task4; + task4->next = task5; + + int total = 0; // Break at this line + Task *t = task_head; + while (t != NULL) { + if (t->id >= 0) + ++total; + t = t->next; + } + printf("We have a total number of %d tasks\n", total); + return 0; +} |