"""
Test lldb data formatter for libc++ std::unique_ptr.
"""
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestCase(TestBase):
def make_expected_type(self, pointee_type: str, qualifiers: str = "") -> str:
if qualifiers:
qualifiers = " " + qualifiers
if self.expectedCompiler(["clang"]) and self.expectedCompilerVersion(
[">", "16.0"]
):
return f"std::unique_ptr<{pointee_type}>{qualifiers}"
else:
return f"std::unique_ptr<{pointee_type}, std::default_delete<{pointee_type}> >{qualifiers}"
def make_expected_basic_string_ptr(self) -> str:
if self.expectedCompiler(["clang"]) and self.expectedCompilerVersion(
[">", "16.0"]
):
return f"std::unique_ptr<std::string>"
else:
return (
"std::unique_ptr<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, "
"std::default_delete<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >"
)
@add_test_categories(["libc++"])
def test_unique_ptr_variables(self):
"""Test `frame variable` output for `std::unique_ptr` types."""
self.build()
lldbutil.run_to_source_breakpoint(
self, "// break here", lldb.SBFileSpec("main.cpp")
)
valobj = self.expect_var_path(
"up_empty",
type=self.make_expected_type("int"),
summary="nullptr",
children=[ValueCheck(name="pointer")],
)
self.assertEqual(
valobj.child[0].GetValueAsUnsigned(lldb.LLDB_INVALID_ADDRESS), 0
)
self.expect(
"frame variable *up_empty", substrs=["(int) *up_empty = <parent is NULL>"]
)
valobj = self.expect_var_path(
"up_int",
type=self.make_expected_type("int"),
summary="10",
children=[ValueCheck(name="pointer")],
)
self.assertNotEqual(valobj.child[0].unsigned, 0)
valobj = self.expect_var_path(
"up_int_ref",
type=self.make_expected_type("int", qualifiers="&"),
summary="10",
children=[ValueCheck(name="pointer")],
)
self.assertNotEqual(valobj.child[0].unsigned, 0)
valobj = self.expect_var_path(
"up_int_ref_ref",
type=self.make_expected_type("int", qualifiers="&&"),
summary="10",
children=[ValueCheck(name="pointer")],
)
self.assertNotEqual(valobj.child[0].unsigned, 0)
valobj = self.expect_var_path(
"up_str",
type=self.make_expected_basic_string_ptr(),
summary='"hello"',
children=[ValueCheck(name="pointer", summary='"hello"')],
)
valobj = self.expect_var_path("up_user", type=self.make_expected_type("User"))
self.assertRegex(valobj.summary, "^User @ 0x0*[1-9a-f][0-9a-f]+$")
self.assertNotEqual(valobj.child[0].unsigned, 0)
valobj = self.expect_var_path(
"*up_user",
type="User",
children=[
ValueCheck(name="id", value="30"),
ValueCheck(name="name", summary='"steph"'),
],
)
self.assertEqual(str(valobj), '(User) *pointer = (id = 30, name = "steph")')
valobj = self.expect_var_path(
"up_non_empty_deleter",
type="std::unique_ptr<int, NonEmptyIntDeleter>",
summary="1234",
children=[
ValueCheck(name="pointer"),
ValueCheck(
name="deleter", children=[ValueCheck(name="dummy_", value="9999")]
),
],
)
self.assertNotEqual(valobj.child[0].unsigned, 0)
self.expect_var_path("up_user->id", type="int", value="30")
self.expect_var_path("up_user->name", type="std::string", summary='"steph"')