Home | History | Annotate | Download | only in linked_list
      1 """
      2 Test SBValue API linked_list_iter which treats the SBValue as a linked list and
      3 supports iteration till the end of list is reached.
      4 """
      5 
      6 import os, time
      7 import re
      8 import unittest2
      9 import lldb, lldbutil
     10 from lldbtest import *
     11 
     12 class ValueAsLinkedListTestCase(TestBase):
     13 
     14     mydir = os.path.join("python_api", "value", "linked_list")
     15 
     16     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     17     @python_api_test
     18     @dsym_test
     19     def test_with_dsym(self):
     20         """Exercise SBValue API linked_list_iter."""
     21         d = {'EXE': self.exe_name}
     22         self.buildDsym(dictionary=d)
     23         self.setTearDownCleanup(dictionary=d)
     24         self.linked_list_api(self.exe_name)
     25 
     26     @python_api_test
     27     @dwarf_test
     28     def test_with_dwarf(self):
     29         """Exercise SBValue API linked_list_iter."""
     30         d = {'EXE': self.exe_name}
     31         self.buildDwarf(dictionary=d)
     32         self.setTearDownCleanup(dictionary=d)
     33         self.linked_list_api(self.exe_name)
     34 
     35     def setUp(self):
     36         # Call super's setUp().
     37         TestBase.setUp(self)
     38         # We'll use the test method name as the exe_name.
     39         self.exe_name = self.testMethodName
     40         # Find the line number to break at.
     41         self.line = line_number('main.cpp', '// Break at this line')
     42 
     43     def linked_list_api(self, exe_name):
     44         """Exercise SBValue API linked_list-iter."""
     45         exe = os.path.join(os.getcwd(), exe_name)
     46 
     47         # Create a target by the debugger.
     48         target = self.dbg.CreateTarget(exe)
     49         self.assertTrue(target, VALID_TARGET)
     50 
     51         # Create the breakpoint inside function 'main'.
     52         breakpoint = target.BreakpointCreateByLocation('main.cpp', self.line)
     53         self.assertTrue(breakpoint, VALID_BREAKPOINT)
     54 
     55         # Now launch the process, and do not stop at entry point.
     56         process = target.LaunchSimple(None, None, os.getcwd())
     57         self.assertTrue(process, PROCESS_IS_VALID)
     58 
     59         # Get Frame #0.
     60         self.assertTrue(process.GetState() == lldb.eStateStopped)
     61         thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
     62         self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
     63         frame0 = thread.GetFrameAtIndex(0)
     64 
     65         # Get variable 'task_head'.
     66         task_head = frame0.FindVariable('task_head')
     67         self.assertTrue(task_head, VALID_VARIABLE)
     68         self.DebugSBValue(task_head)
     69 
     70         # By design (see main.cpp), the visited id's are: [1, 2, 4, 5].
     71         visitedIDs = [1, 2, 4, 5]
     72         list = []
     73 
     74         cvf = lldbutil.ChildVisitingFormatter(indent_child=2)
     75         for t in task_head.linked_list_iter('next'):
     76             self.assertTrue(t, VALID_VARIABLE)
     77             # Make sure that 'next' corresponds to an SBValue with pointer type.
     78             self.assertTrue(t.TypeIsPointerType())
     79             if self.TraceOn():
     80                 print cvf.format(t)
     81             list.append(int(t.GetChildMemberWithName("id").GetValue()))
     82 
     83         # Sanity checks that the we visited all the items (no more, no less).
     84         if self.TraceOn():
     85             print "visited IDs:", list
     86         self.assertTrue(visitedIDs == list)
     87 
     88         # Let's exercise the linked_list_iter() API again, this time supplying
     89         # our end of list test function.
     90         def eol(val):
     91             """Test function to determine end of list."""
     92             # End of list is reached if either the value object is invalid
     93             # or it corresponds to a null pointer.
     94             if not val or int(val.GetValue(), 16) == 0:
     95                 return True
     96             # Also check the "id" for correct semantics.  If id <= 0, the item
     97             # is corrupted, let's return True to signify end of list.
     98             if int(val.GetChildMemberWithName("id").GetValue(), 0) <= 0:
     99                 return True
    100 
    101             # Otherwise, return False.
    102             return False
    103 
    104         list = []
    105         for t in task_head.linked_list_iter('next', eol):
    106             self.assertTrue(t, VALID_VARIABLE)
    107             # Make sure that 'next' corresponds to an SBValue with pointer type.
    108             self.assertTrue(t.TypeIsPointerType())
    109             if self.TraceOn():
    110                 print cvf.format(t)
    111             list.append(int(t.GetChildMemberWithName("id").GetValue()))
    112 
    113         # Sanity checks that the we visited all the items (no more, no less).
    114         if self.TraceOn():
    115             print "visited IDs:", list
    116         self.assertTrue(visitedIDs == list)
    117         
    118         # Get variable 'empty_task_head'.
    119         empty_task_head = frame0.FindVariable('empty_task_head')
    120         self.assertTrue(empty_task_head, VALID_VARIABLE)
    121         self.DebugSBValue(empty_task_head)
    122 
    123         list = []
    124         # There is no iterable item from empty_task_head.linked_list_iter().
    125         for t in empty_task_head.linked_list_iter('next', eol):
    126             if self.TraceOn():
    127                 print cvf.format(t)
    128             list.append(int(t.GetChildMemberWithName("id").GetValue()))
    129 
    130         self.assertTrue(len(list) == 0)
    131 
    132         # Get variable 'task_evil'.
    133         task_evil = frame0.FindVariable('task_evil')
    134         self.assertTrue(task_evil, VALID_VARIABLE)
    135         self.DebugSBValue(task_evil)
    136 
    137         list = []
    138         # There 3 iterable items from task_evil.linked_list_iter(). :-)
    139         for t in task_evil.linked_list_iter('next'):
    140             if self.TraceOn():
    141                 print cvf.format(t)
    142             list.append(int(t.GetChildMemberWithName("id").GetValue()))
    143 
    144         self.assertTrue(len(list) == 3)
    145 
    146 if __name__ == '__main__':
    147     import atexit
    148     lldb.SBDebugger.Initialize()
    149     atexit.register(lambda: lldb.SBDebugger.Terminate())
    150     unittest2.main()
    151