1"""
2Test lldb data formatter for LibStdC++ std::variant.
3"""
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class LibStdcxxVariantDataFormatterTestCase(TestBase):
13    @add_test_categories(["libstdcxx"])
14    def test_with_run_command(self):
15        """Test LibStdC++ std::variant data formatter works correctly."""
16        self.build()
17
18        (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(
19            self, "// break here", lldb.SBFileSpec("main.cpp", False)
20        )
21
22        lldbutil.continue_to_breakpoint(self.process, bkpt)
23
24        for name in ["v1", "v1_typedef"]:
25            self.expect(
26                "frame variable " + name,
27                substrs=[name + " =  Active Type = int  {", "Value = 12", "}"],
28            )
29
30        for name in ["v1_ref", "v1_typedef_ref"]:
31            self.expect(
32                "frame variable " + name,
33                substrs=[name + " =  Active Type = int : {", "Value = 12", "}"],
34            )
35
36        self.expect(
37            "frame variable v_v1",
38            substrs=[
39                "v_v1 =  Active Type = std::variant<int, double, char>  {",
40                "Value =  Active Type = int  {",
41                "Value = 12",
42                "}",
43                "}",
44            ],
45        )
46
47        lldbutil.continue_to_breakpoint(self.process, bkpt)
48
49        self.expect(
50            "frame variable v1",
51            substrs=["v1 =  Active Type = double  {", "Value = 2", "}"],
52        )
53
54        lldbutil.continue_to_breakpoint(self.process, bkpt)
55
56        self.expect(
57            "frame variable v2",
58            substrs=["v2 =  Active Type = double  {", "Value = 2", "}"],
59        )
60
61        self.expect(
62            "frame variable v3",
63            substrs=["v3 =  Active Type = char  {", "Value = 'A'", "}"],
64        )
65        """
66        TODO: temporarily disable No Value tests as they seem to fail on ubuntu/debian
67        bots. Pending reproduce and investigation.
68
69        self.expect("frame variable v_no_value", substrs=["v_no_value =  No Value"])
70
71        self.expect(
72            "frame variable v_many_types_no_value",
73            substrs=["v_many_types_no_value =  No Value"],
74        )
75        """
76
77    @add_test_categories(["libstdcxx"])
78    def test_invalid_variant_index(self):
79        """Test LibStdC++ data formatter for std::variant with invalid index."""
80        self.build()
81
82        (self.target, self.process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
83            self, "// break here", lldb.SBFileSpec("main.cpp", False)
84        )
85
86        lldbutil.continue_to_breakpoint(self.process, bkpt)
87
88        self.expect(
89            "frame variable v1",
90            substrs=["v1 =  Active Type = int  {", "Value = 12", "}"],
91        )
92
93        var_v1 = thread.frames[0].FindVariable("v1")
94        var_v1_raw_obj = var_v1.GetNonSyntheticValue()
95        index_obj = var_v1_raw_obj.GetChildMemberWithName("_M_index")
96        self.assertTrue(index_obj and index_obj.IsValid())
97
98        INVALID_INDEX = "100"
99        index_obj.SetValueFromCString(INVALID_INDEX)
100
101        self.expect("frame variable v1", substrs=["v1 =  <Invalid>"])
102