1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
"""
Test lldb data formatter subsystem.
"""
import lldb
from lldbsuite.test.lldbtest import *
import lldbsuite.test.lldbutil as lldbutil
class SynthDataFormatterTestCase(TestBase):
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.
def cleanup():
self.runCmd("type format clear", check=False)
self.runCmd("type summary clear", check=False)
self.runCmd("type filter clear", check=False)
# Execute the cleanup function during test case tear down.
self.addTearDownHook(cleanup)
# Pick some values and check that the basics work
self.runCmd("type filter add BagOfInts --child x --child z")
self.expect("frame variable int_bag", substrs=["x = 6", "z = 8"])
# Check we can still access the missing child by summary
self.runCmd('type summary add BagOfInts --summary-string "y=${var.y}"')
self.expect("frame variable int_bag", substrs=["y=7"])
# Even if we have synth children, the summary prevails
self.expect(
"frame variable int_bag", matching=False, substrs=["x = 6", "z = 8"]
)
# if we skip synth and summary show y
self.expect(
"frame variable int_bag --synthetic-type false --no-summary-depth=1",
substrs=["x = 6", "y = 7", "z = 8"],
)
# if we ask for raw output same happens
self.expect(
"frame variable int_bag --raw-output", substrs=["x = 6", "y = 7", "z = 8"]
)
# Summary+Synth must work together
self.runCmd('type summary add BagOfInts --summary-string "x=${var.x}" -e')
self.expect("frame variable int_bag", substrs=["x=6", "x = 6", "z = 8"])
# Same output, but using Python
self.runCmd(
"type summary add BagOfInts --python-script \"return 'x=%s' % valobj.GetChildMemberWithName('x').GetValue()\" -e"
)
self.expect("frame variable int_bag", substrs=["x=6", "x = 6", "z = 8"])
# If I skip summaries, still give me the artificial children
self.expect(
"frame variable int_bag --no-summary-depth=1", substrs=["x = 6", "z = 8"]
)
# Delete synth and check that the view reflects it immediately
self.runCmd("type filter delete BagOfInts")
self.expect("frame variable int_bag", substrs=["x = 6", "y = 7", "z = 8"])
# Add the synth again and check that it's honored deeper in the
# hierarchy
self.runCmd("type filter add BagOfInts --child x --child z")
self.expect(
"frame variable bag_bag",
substrs=[
"x = x=69 {",
"x = 69",
"z = 71",
"y = x=66 {",
"x = 66",
"z = 68",
],
)
self.expect(
"frame variable bag_bag", matching=False, substrs=["y = 70", "y = 67"]
)
# Check that a synth can expand nested stuff
self.runCmd("type filter add BagOfBags --child x.y --child y.z")
self.expect("frame variable bag_bag", substrs=["x.y = 70", "y.z = 68"])
# ...even if we get -> and . wrong
self.runCmd('type filter add BagOfBags --child x.y --child "y->z"')
self.expect("frame variable bag_bag", substrs=["x.y = 70", "y->z = 68"])
# ...even bitfields
self.runCmd('type filter add BagOfBags --child x.y --child "y->z[1-2]"')
self.expect(
"frame variable bag_bag --show-types",
substrs=["x.y = 70", "(int:2) y->z[1-2] = 2"],
)
# ...even if we format the bitfields
self.runCmd('type filter add BagOfBags --child x.y --child "y->y[0-0]"')
self.runCmd('type format add "int:1" -f bool')
self.expect(
"frame variable bag_bag --show-types",
substrs=["x.y = 70", "(int:1) y->y[0-0] = true"],
)
# ...even if we use one-liner summaries
self.runCmd("type summary add -c BagOfBags")
self.expect(
"frame variable bag_bag",
substrs=["(BagOfBags) bag_bag = (x.y = 70, y->y[0-0] = true)"],
)
self.runCmd("type summary delete BagOfBags")
# now check we are dynamic (and arrays work)
self.runCmd(
"type filter add Plenty --child bitfield --child array[0] --child array[2]"
)
self.expect(
"frame variable plenty_of_stuff",
substrs=["bitfield = 1", "array[0] = 5", "array[2] = 3"],
)
self.runCmd("n")
self.expect(
"frame variable plenty_of_stuff",
substrs=["bitfield = 17", "array[0] = 5", "array[2] = 3"],
)
# skip synthetic children
self.expect(
"frame variable plenty_of_stuff --synthetic-type no",
substrs=["some_values = 0x", "array = 0x", "array_size = 5"],
)
# check flat printing with synthetic children
self.expect(
"frame variable plenty_of_stuff --flat",
substrs=[
"plenty_of_stuff.bitfield = 17",
"*(plenty_of_stuff.array) = 5",
"*(plenty_of_stuff.array) = 3",
],
)
# check that we do not lose location information for our children
self.expect(
"frame variable plenty_of_stuff --location",
substrs=["0x", ": bitfield = 17"],
)
# check we work across pointer boundaries
self.expect(
"frame variable plenty_of_stuff.some_values --ptr-depth=1",
substrs=["(BagOfInts *) plenty_of_stuff.some_values", "x = 5", "z = 7"],
)
# but not if we don't want to
self.runCmd("type filter add BagOfInts --child x --child z -p")
self.expect(
"frame variable plenty_of_stuff.some_values --ptr-depth=1",
substrs=[
"(BagOfInts *) plenty_of_stuff.some_values",
"x = 5",
"y = 6",
"z = 7",
],
)
# check we're dynamic even if nested
self.runCmd("type filter add BagOfBags --child x.z")
self.expect("frame variable bag_bag", substrs=["x.z = 71"])
self.runCmd("n")
self.expect("frame variable bag_bag", substrs=["x.z = 12"])
self.runCmd('type summary add -e -s "I am always empty but have" EmptyStruct')
self.expect("frame variable es", substrs=["I am always empty but have {}"])
self.runCmd('type summary add -e -h -s "I am really empty" EmptyStruct')
self.expect("frame variable es", substrs=["I am really empty"])
self.expect(
"frame variable es", substrs=["I am really empty {}"], matching=False
)
|