1"""
2Test lldb data formatter subsystem for bitset for libcxx and libstdcpp.
3"""
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11USE_LIBSTDCPP = "USE_LIBSTDCPP"
12USE_LIBCPP = "USE_LIBCPP"
13VALUE = "VALUE"
14REFERENCE = "REFERENCE"
15POINTER = "POINTER"
16
17
18class GenericBitsetDataFormatterTestCase(TestBase):
19    def setUp(self):
20        TestBase.setUp(self)
21        primes = [1] * 1000
22        primes[0] = primes[1] = 0
23        for i in range(2, len(primes)):
24            for j in range(2 * i, len(primes), i):
25                primes[j] = 0
26        self.primes = primes
27
28    def getBitsetVariant(self, size, variant):
29        if variant == VALUE:
30            return "std::bitset<" + str(size) + ">"
31        elif variant == REFERENCE:
32            return "std::bitset<" + str(size) + "> &"
33        elif variant == POINTER:
34            return "std::bitset<" + str(size) + "> *"
35        return ""
36
37    def check(self, name, size, variant):
38        var = self.frame().FindVariable(name)
39        self.assertTrue(var.IsValid())
40        self.assertEqual(var.GetNumChildren(), size)
41        children = []
42        for i in range(size):
43            child = var.GetChildAtIndex(i)
44            children.append(
45                ValueCheck(value=str(bool(child.GetValueAsUnsigned())).lower())
46            )
47            self.assertEqual(
48                child.GetValueAsUnsigned(),
49                self.primes[i],
50                "variable: %s, index: %d" % (name, size),
51            )
52        self.expect_var_path(
53            name, type=self.getBitsetVariant(size, variant), children=children
54        )
55
56    def do_test_value(self, stdlib_type):
57        """Test that std::bitset is displayed correctly"""
58        self.build(dictionary={stdlib_type: "1"})
59
60        lldbutil.run_to_source_breakpoint(
61            self, "// break here", lldb.SBFileSpec("main.cpp", False)
62        )
63
64        self.check("empty", 0, VALUE)
65        self.check("small", 13, VALUE)
66        self.check("medium", 70, VALUE)
67        self.check("large", 1000, VALUE)
68
69    @add_test_categories(["libstdcxx"])
70    def test_value_libstdcpp(self):
71        self.do_test_value(USE_LIBSTDCPP)
72
73    @add_test_categories(["libc++"])
74    def test_value_libcpp(self):
75        self.do_test_value(USE_LIBCPP)
76
77    def do_test_ptr_and_ref(self, stdlib_type):
78        """Test that ref and ptr to std::bitset is displayed correctly"""
79        self.build(dictionary={stdlib_type: "1"})
80
81        (_, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
82            self, "Check ref and ptr", lldb.SBFileSpec("main.cpp", False)
83        )
84
85        self.check("ref", 13, REFERENCE)
86        self.check("ptr", 13, POINTER)
87
88        lldbutil.continue_to_breakpoint(process, bkpt)
89
90        self.check("ref", 70, REFERENCE)
91        self.check("ptr", 70, POINTER)
92
93        lldbutil.continue_to_breakpoint(process, bkpt)
94
95        self.check("ref", 1000, REFERENCE)
96        self.check("ptr", 1000, POINTER)
97
98    @add_test_categories(["libstdcxx"])
99    def test_ptr_and_ref_libstdcpp(self):
100        self.do_test_ptr_and_ref(USE_LIBSTDCPP)
101
102    @add_test_categories(["libc++"])
103    def test_ptr_and_ref_libcpp(self):
104        self.do_test_ptr_and_ref(USE_LIBCPP)
105