xref: /llvm-project/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py (revision ba7f52ccf42fd481a1b309fe76863729fdd18c1c)
1# Test the SBAPI for GetStatistics()
2
3import json
4import lldb
5from lldbsuite.test.decorators import *
6from lldbsuite.test.lldbtest import *
7from lldbsuite.test import lldbutil
8
9
10class TestStatsAPI(TestBase):
11    NO_DEBUG_INFO_TESTCASE = True
12
13    def test_stats_api(self):
14        """
15        Test SBTarget::GetStatistics() API.
16        """
17        self.build()
18        exe = self.getBuildArtifact("a.out")
19        # Launch a process and break
20        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
21            self, "break here", lldb.SBFileSpec("main.c")
22        )
23
24        # Test enabling/disabling stats
25        self.assertFalse(target.GetCollectingStats())
26        target.SetCollectingStats(True)
27        self.assertTrue(target.GetCollectingStats())
28        target.SetCollectingStats(False)
29        self.assertFalse(target.GetCollectingStats())
30
31        # Test the function to get the statistics in JSON'ish.
32        stats = target.GetStatistics()
33        stream = lldb.SBStream()
34        res = stats.GetAsJSON(stream)
35        debug_stats = json.loads(stream.GetData())
36        self.assertIn(
37            "targets",
38            debug_stats,
39            'Make sure the "targets" key in in target.GetStatistics()',
40        )
41        self.assertIn(
42            "modules",
43            debug_stats,
44            'Make sure the "modules" key in in target.GetStatistics()',
45        )
46        stats_json = debug_stats["targets"][0]
47        self.assertIn(
48            "expressionEvaluation",
49            stats_json,
50            'Make sure the "expressionEvaluation" key in in target.GetStatistics()["targets"][0]',
51        )
52        self.assertIn(
53            "frameVariable",
54            stats_json,
55            'Make sure the "frameVariable" key in in target.GetStatistics()["targets"][0]',
56        )
57        expressionEvaluation = stats_json["expressionEvaluation"]
58        self.assertIn(
59            "successes",
60            expressionEvaluation,
61            'Make sure the "successes" key in in "expressionEvaluation" dictionary"',
62        )
63        self.assertIn(
64            "failures",
65            expressionEvaluation,
66            'Make sure the "failures" key in in "expressionEvaluation" dictionary"',
67        )
68        frameVariable = stats_json["frameVariable"]
69        self.assertIn(
70            "successes",
71            frameVariable,
72            'Make sure the "successes" key in in "frameVariable" dictionary"',
73        )
74        self.assertIn(
75            "failures",
76            frameVariable,
77            'Make sure the "failures" key in in "frameVariable" dictionary"',
78        )
79
80        # Test statistics summary.
81        stats_options = lldb.SBStatisticsOptions()
82        stats_options.SetSummaryOnly(True)
83        stats_summary = target.GetStatistics(stats_options)
84        stream_summary = lldb.SBStream()
85        stats_summary.GetAsJSON(stream_summary)
86        debug_stats_summary = json.loads(stream_summary.GetData())
87        self.assertNotIn("modules", debug_stats_summary)
88        self.assertNotIn("commands", debug_stats_summary)
89
90        # Summary values should be the same as in full statistics.
91        # The exceptions to this are:
92        # - The parse time on Mac OS X is not deterministic.
93        # - Memory usage may grow over time due to the use of ConstString.
94        for key, value in debug_stats_summary.items():
95            self.assertIn(key, debug_stats)
96            if key != "memory" and key != "targets" and not key.endswith("Time"):
97                self.assertEqual(debug_stats[key], value)
98
99    def test_command_stats_api(self):
100        """
101        Test GetCommandInterpreter::GetStatistics() API.
102        """
103        self.build()
104        exe = self.getBuildArtifact("a.out")
105        lldbutil.run_to_name_breakpoint(self, "main")
106
107        interp = self.dbg.GetCommandInterpreter()
108        result = lldb.SBCommandReturnObject()
109        interp.HandleCommand("bt", result)
110
111        stream = lldb.SBStream()
112        res = interp.GetStatistics().GetAsJSON(stream)
113        command_stats = json.loads(stream.GetData())
114
115        # Verify bt command is correctly parsed into final form.
116        self.assertEqual(command_stats["thread backtrace"], 1)
117        # Verify original raw command is not duplicatedly captured.
118        self.assertNotIn("bt", command_stats)
119        # Verify bt's regex command is not duplicatedly captured.
120        self.assertNotIn("_regexp-bt", command_stats)
121
122    @add_test_categories(["dwo"])
123    def test_command_stats_force(self):
124        """
125        Test reporting all pssible debug info stats by force loading all debug
126        info. For example, dwo files
127        """
128        src_dir = self.getSourceDir()
129        dwo_yaml_path = os.path.join(src_dir, "main-main.dwo.yaml")
130        exe_yaml_path = os.path.join(src_dir, "main.yaml")
131        dwo_path = self.getBuildArtifact("main-main.dwo")
132        exe_path = self.getBuildArtifact("main")
133        self.yaml2obj(dwo_yaml_path, dwo_path)
134        self.yaml2obj(exe_yaml_path, exe_path)
135
136        # Turn on symbols on-demand loading
137        self.runCmd("settings set symbols.load-on-demand true")
138
139        # We need the current working directory to be set to the build directory
140        os.chdir(self.getBuildDir())
141        # Create a target with the object file we just created from YAML
142        target = self.dbg.CreateTarget(exe_path)
143        self.assertTrue(target, VALID_TARGET)
144
145        # Get statistics
146        stats_options = lldb.SBStatisticsOptions()
147        stats = target.GetStatistics(stats_options)
148        stream = lldb.SBStream()
149        stats.GetAsJSON(stream)
150        debug_stats = json.loads(stream.GetData())
151        self.assertEqual(debug_stats["totalDebugInfoByteSize"], 193)
152
153        # Get statistics with force loading
154        stats_options.SetReportAllAvailableDebugInfo(True)
155        stats_force = target.GetStatistics(stats_options)
156        stream_force = lldb.SBStream()
157        stats_force.GetAsJSON(stream_force)
158        debug_stats_force = json.loads(stream_force.GetData())
159        self.assertEqual(debug_stats_force["totalDebugInfoByteSize"], 445)
160