| """ |
| Test lldb data formatter subsystem. |
| """ |
| |
| from __future__ import print_function |
| |
| |
| import os |
| import time |
| import lldb |
| from lldbsuite.test.decorators import * |
| from lldbsuite.test.lldbtest import * |
| from lldbsuite.test import lldbutil |
| |
| |
| class CategoriesDataFormatterTestCase(TestBase): |
| |
| mydir = TestBase.compute_mydir(__file__) |
| |
| def setUp(self): |
| # Call super's setUp(). |
| TestBase.setUp(self) |
| # Find the line number to break at. |
| self.line = line_number('main.cpp', '// Set break point at this line.') |
| |
| def test_with_run_command(self): |
| """Test that that file and class static variables display correctly.""" |
| self.build() |
| self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) |
| |
| lldbutil.run_break_set_by_file_and_line( |
| self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) |
| |
| self.runCmd("run", RUN_SUCCEEDED) |
| |
| # The stop reason of the thread should be breakpoint. |
| self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, |
| substrs=['stopped', |
| 'stop reason = breakpoint']) |
| |
| # This is the function to remove the custom formats in order to have a |
| # clean slate for the next test case (most of these categories do not |
| # exist anymore, but we just make sure we delete all of them) |
| def cleanup(): |
| self.runCmd('type format clear', check=False) |
| self.runCmd('type summary clear', check=False) |
| self.runCmd('type category delete Category1', check=False) |
| self.runCmd('type category delete Category2', check=False) |
| self.runCmd('type category delete NewCategory', check=False) |
| self.runCmd("type category delete CircleCategory", check=False) |
| self.runCmd( |
| "type category delete RectangleStarCategory", |
| check=False) |
| self.runCmd("type category delete BaseCategory", check=False) |
| |
| # Execute the cleanup function during test case tear down. |
| self.addTearDownHook(cleanup) |
| |
| # Add a summary to a new category and check that it works |
| self.runCmd( |
| "type summary add Rectangle --summary-string \"ARectangle\" -w NewCategory") |
| |
| self.expect("frame variable r1 r2 r3", matching=False, |
| substrs=['r1 = ARectangle', |
| 'r2 = ARectangle', |
| 'r3 = ARectangle']) |
| |
| self.runCmd("type category enable NewCategory") |
| |
| self.expect("frame variable r1 r2 r3", matching=True, |
| substrs=['r1 = ARectangle', |
| 'r2 = ARectangle', |
| 'r3 = ARectangle']) |
| |
| # Disable the category and check that the old stuff is there |
| self.runCmd("type category disable NewCategory") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = {', |
| 'r2 = {', |
| 'r3 = {']) |
| |
| # Re-enable the category and check that it works |
| self.runCmd("type category enable NewCategory") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = ARectangle', |
| 'r2 = ARectangle', |
| 'r3 = ARectangle']) |
| |
| # Delete the category and the old stuff should be there |
| self.runCmd("type category delete NewCategory") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = {', |
| 'r2 = {', |
| 'r3 = {']) |
| |
| # Add summaries to two different categories and check that we can |
| # switch |
| self.runCmd( |
| "type summary add --summary-string \"Width = ${var.w}, Height = ${var.h}\" Rectangle -w Category1") |
| self.runCmd("type summary add --python-script \"return 'Area = ' + str( int(valobj.GetChildMemberWithName('w').GetValue()) * int(valobj.GetChildMemberWithName('h').GetValue()) );\" Rectangle -w Category2") |
| |
| # check that enable A B is the same as enable B enable A |
| self.runCmd("type category enable Category1 Category2") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Width = ', |
| 'r2 = Width = ', |
| 'r3 = Width = ']) |
| |
| self.runCmd("type category disable Category1") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Area = ', |
| 'r2 = Area = ', |
| 'r3 = Area = ']) |
| |
| # switch again |
| |
| self.runCmd("type category enable Category1") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Width = ', |
| 'r2 = Width = ', |
| 'r3 = Width = ']) |
| |
| # Re-enable the category and show that the preference is persisted |
| self.runCmd("type category disable Category2") |
| self.runCmd("type category enable Category2") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Area = ', |
| 'r2 = Area = ', |
| 'r3 = Area = ']) |
| |
| # Now delete the favorite summary |
| self.runCmd("type summary delete Rectangle -w Category2") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Width = ', |
| 'r2 = Width = ', |
| 'r3 = Width = ']) |
| |
| # Delete the summary from the default category (that does not have it) |
| self.runCmd("type summary delete Rectangle", check=False) |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Width = ', |
| 'r2 = Width = ', |
| 'r3 = Width = ']) |
| |
| # Now add another summary to another category and switch back and forth |
| self.runCmd("type category delete Category1 Category2") |
| |
| self.runCmd( |
| "type summary add Rectangle -w Category1 --summary-string \"Category1\"") |
| self.runCmd( |
| "type summary add Rectangle -w Category2 --summary-string \"Category2\"") |
| |
| self.runCmd("type category enable Category2") |
| self.runCmd("type category enable Category1") |
| |
| self.runCmd("type summary list -w Category1") |
| self.expect("type summary list -w NoSuchCategoryHere", |
| substrs=['no matching results found']) |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Category1', |
| 'r2 = Category1', |
| 'r3 = Category1']) |
| |
| self.runCmd("type category disable Category1") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Category2', |
| 'r2 = Category2', |
| 'r3 = Category2']) |
| |
| # Check that re-enabling an enabled category works |
| self.runCmd("type category enable Category1") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Category1', |
| 'r2 = Category1', |
| 'r3 = Category1']) |
| |
| self.runCmd("type category delete Category1") |
| self.runCmd("type category delete Category2") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = {', |
| 'r2 = {', |
| 'r3 = {']) |
| |
| # Check that multiple summaries can go into one category |
| self.runCmd( |
| "type summary add -w Category1 --summary-string \"Width = ${var.w}, Height = ${var.h}\" Rectangle") |
| self.runCmd( |
| "type summary add -w Category1 --summary-string \"Radius = ${var.r}\" Circle") |
| |
| self.runCmd("type category enable Category1") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Width = ', |
| 'r2 = Width = ', |
| 'r3 = Width = ']) |
| |
| self.expect("frame variable c1 c2 c3", |
| substrs=['c1 = Radius = ', |
| 'c2 = Radius = ', |
| 'c3 = Radius = ']) |
| |
| self.runCmd("type summary delete Circle -w Category1") |
| |
| self.expect("frame variable c1 c2 c3", |
| substrs=['c1 = {', |
| 'c2 = {', |
| 'c3 = {']) |
| |
| # Add a regex based summary to a category |
| self.runCmd( |
| "type summary add -w Category1 --summary-string \"Radius = ${var.r}\" -x Circle") |
| |
| self.expect("frame variable r1 r2 r3", |
| substrs=['r1 = Width = ', |
| 'r2 = Width = ', |
| 'r3 = Width = ']) |
| |
| self.expect("frame variable c1 c2 c3", |
| substrs=['c1 = Radius = ', |
| 'c2 = Radius = ', |
| 'c3 = Radius = ']) |
| |
| # Delete it |
| self.runCmd("type summary delete Circle -w Category1") |
| |
| self.expect("frame variable c1 c2 c3", |
| substrs=['c1 = {', |
| 'c2 = {', |
| 'c3 = {']) |
| |
| # Change a summary inside a category and check that the change is |
| # reflected |
| self.runCmd( |
| "type summary add Circle -w Category1 --summary-string \"summary1\"") |
| |
| self.expect("frame variable c1 c2 c3", |
| substrs=['c1 = summary1', |
| 'c2 = summary1', |
| 'c3 = summary1']) |
| |
| self.runCmd( |
| "type summary add Circle -w Category1 --summary-string \"summary2\"") |
| |
| self.expect("frame variable c1 c2 c3", |
| substrs=['c1 = summary2', |
| 'c2 = summary2', |
| 'c3 = summary2']) |
| |
| # Check that our order of priority works. Start by clearing categories |
| self.runCmd("type category delete Category1") |
| |
| self.runCmd( |
| "type summary add Shape -w BaseCategory --summary-string \"AShape\"") |
| self.runCmd("type category enable BaseCategory") |
| |
| self.expect("print (Shape*)&c1", |
| substrs=['AShape']) |
| self.expect("print (Shape*)&r1", |
| substrs=['AShape']) |
| self.expect("print (Shape*)c_ptr", |
| substrs=['AShape']) |
| self.expect("print (Shape*)r_ptr", |
| substrs=['AShape']) |
| |
| self.runCmd( |
| "type summary add Circle -w CircleCategory --summary-string \"ACircle\"") |
| self.runCmd( |
| "type summary add Rectangle -w RectangleCategory --summary-string \"ARectangle\"") |
| self.runCmd("type category enable CircleCategory") |
| |
| self.expect("frame variable c1", |
| substrs=['ACircle']) |
| self.expect("frame variable c_ptr", |
| substrs=['ACircle']) |
| |
| self.runCmd( |
| "type summary add \"Rectangle *\" -w RectangleStarCategory --summary-string \"ARectangleStar\"") |
| self.runCmd("type category enable RectangleStarCategory") |
| |
| self.expect("frame variable c1 r1 c_ptr r_ptr", |
| substrs=['ACircle', |
| 'ARectangleStar']) |
| |
| self.runCmd("type category enable RectangleCategory") |
| |
| self.expect("frame variable c1 r1 c_ptr r_ptr", |
| substrs=['ACircle', |
| 'ACircle', |
| 'ARectangle']) |
| |
| # Check that abruptly deleting an enabled category does not crash us |
| self.runCmd("type category delete RectangleCategory") |
| |
| self.expect("frame variable c1 r1 c_ptr r_ptr", |
| substrs=['ACircle', |
| '(Rectangle) r1 = ', 'w = 5', 'h = 6', |
| 'ACircle', |
| 'ARectangleStar']) |
| |
| # check that list commands work |
| self.expect("type category list", |
| substrs=['RectangleStarCategory (enabled)']) |
| |
| self.expect("type summary list", |
| substrs=['ARectangleStar']) |
| |
| # Disable a category and check that it fallsback |
| self.runCmd("type category disable CircleCategory") |
| |
| # check that list commands work |
| self.expect("type category list", |
| substrs=['CircleCategory (disabled']) |
| |
| self.expect("frame variable c1 r_ptr", |
| substrs=['AShape', |
| 'ARectangleStar']) |
| |
| # check that filters work into categories |
| self.runCmd( |
| "type filter add Rectangle --child w --category RectangleCategory") |
| self.runCmd("type category enable RectangleCategory") |
| self.runCmd( |
| "type summary add Rectangle --category RectangleCategory --summary-string \" \" -e") |
| self.expect('frame variable r2', |
| substrs=['w = 9']) |
| self.runCmd("type summary add Rectangle --summary-string \" \" -e") |
| self.expect('frame variable r2', matching=False, |
| substrs=['h = 16']) |
| |
| # Now delete all categories |
| self.runCmd( |
| "type category delete CircleCategory RectangleStarCategory BaseCategory RectangleCategory") |
| |
| # check that a deleted category with filter does not blow us up |
| self.expect('frame variable r2', |
| substrs=['w = 9', |
| 'h = 16']) |
| |
| # and also validate that one can print formatters for a language |
| self.expect( |
| 'type summary list -l c++', |
| substrs=[ |
| 'vector', |
| 'map', |
| 'list', |
| 'string']) |