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.assertEqual( 37 "targets" in debug_stats, 38 True, 39 'Make sure the "targets" key in in target.GetStatistics()', 40 ) 41 self.assertEqual( 42 "modules" in debug_stats, 43 True, 44 'Make sure the "modules" key in in target.GetStatistics()', 45 ) 46 stats_json = debug_stats["targets"][0] 47 self.assertEqual( 48 "expressionEvaluation" in stats_json, 49 True, 50 'Make sure the "expressionEvaluation" key in in target.GetStatistics()["targets"][0]', 51 ) 52 self.assertEqual( 53 "frameVariable" in stats_json, 54 True, 55 'Make sure the "frameVariable" key in in target.GetStatistics()["targets"][0]', 56 ) 57 expressionEvaluation = stats_json["expressionEvaluation"] 58 self.assertEqual( 59 "successes" in expressionEvaluation, 60 True, 61 'Make sure the "successes" key in in "expressionEvaluation" dictionary"', 62 ) 63 self.assertEqual( 64 "failures" in expressionEvaluation, 65 True, 66 'Make sure the "failures" key in in "expressionEvaluation" dictionary"', 67 ) 68 frameVariable = stats_json["frameVariable"] 69 self.assertEqual( 70 "successes" in frameVariable, 71 True, 72 'Make sure the "successes" key in in "frameVariable" dictionary"', 73 ) 74 self.assertEqual( 75 "failures" in frameVariable, 76 True, 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("memory", debug_stats_summary) 89 self.assertNotIn("commands", debug_stats_summary) 90 91 # Summary values should be the same as in full statistics. 92 # Except the parse time on Mac OS X is not deterministic. 93 for key, value in debug_stats_summary.items(): 94 self.assertIn(key, debug_stats) 95 if key != "targets" and not key.endswith("Time"): 96 self.assertEqual(debug_stats[key], value) 97 98 def test_command_stats_api(self): 99 """ 100 Test GetCommandInterpreter::GetStatistics() API. 101 """ 102 self.build() 103 exe = self.getBuildArtifact("a.out") 104 lldbutil.run_to_name_breakpoint(self, "main") 105 106 interp = self.dbg.GetCommandInterpreter() 107 result = lldb.SBCommandReturnObject() 108 interp.HandleCommand("bt", result) 109 110 stream = lldb.SBStream() 111 res = interp.GetStatistics().GetAsJSON(stream) 112 command_stats = json.loads(stream.GetData()) 113 114 # Verify bt command is correctly parsed into final form. 115 self.assertEqual(command_stats["thread backtrace"], 1) 116 # Verify original raw command is not duplicatedly captured. 117 self.assertNotIn("bt", command_stats) 118 # Verify bt's regex command is not duplicatedly captured. 119 self.assertNotIn("_regexp-bt", command_stats) 120 121 @add_test_categories(["dwo"]) 122 def test_command_stats_force(self): 123 """ 124 Test reporting all pssible debug info stats by force loading all debug 125 info. For example, dwo files 126 """ 127 src_dir = self.getSourceDir() 128 dwo_yaml_path = os.path.join(src_dir, "main-main.dwo.yaml") 129 exe_yaml_path = os.path.join(src_dir, "main.yaml") 130 dwo_path = self.getBuildArtifact("main-main.dwo") 131 exe_path = self.getBuildArtifact("main") 132 self.yaml2obj(dwo_yaml_path, dwo_path) 133 self.yaml2obj(exe_yaml_path, exe_path) 134 135 # Turn on symbols on-demand loading 136 self.runCmd("settings set symbols.load-on-demand true") 137 138 # We need the current working directory to be set to the build directory 139 os.chdir(self.getBuildDir()) 140 # Create a target with the object file we just created from YAML 141 target = self.dbg.CreateTarget(exe_path) 142 self.assertTrue(target, VALID_TARGET) 143 144 # Get statistics 145 stats_options = lldb.SBStatisticsOptions() 146 stats = target.GetStatistics(stats_options) 147 stream = lldb.SBStream() 148 stats.GetAsJSON(stream) 149 debug_stats = json.loads(stream.GetData()) 150 self.assertEqual(debug_stats["totalDebugInfoByteSize"], 193) 151 152 # Get statistics with force loading 153 stats_options.SetReportAllAvailableDebugInfo(True) 154 stats_force = target.GetStatistics(stats_options) 155 stream_force = lldb.SBStream() 156 stats_force.GetAsJSON(stream_force) 157 debug_stats_force = json.loads(stream_force.GetData()) 158 self.assertEqual(debug_stats_force["totalDebugInfoByteSize"], 445) 159