# Test the SBAPI for GetStatistics() import json import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class TestStatsAPI(TestBase): NO_DEBUG_INFO_TESTCASE = True def test_stats_api(self): """ Test SBTarget::GetStatistics() API. """ self.build() exe = self.getBuildArtifact("a.out") # Launch a process and break (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, "break here", lldb.SBFileSpec("main.c") ) # Test enabling/disabling stats self.assertFalse(target.GetCollectingStats()) target.SetCollectingStats(True) self.assertTrue(target.GetCollectingStats()) target.SetCollectingStats(False) self.assertFalse(target.GetCollectingStats()) # Test the function to get the statistics in JSON'ish. stats = target.GetStatistics() stream = lldb.SBStream() res = stats.GetAsJSON(stream) debug_stats = json.loads(stream.GetData()) self.assertIn( "targets", debug_stats, 'Make sure the "targets" key in in target.GetStatistics()', ) self.assertIn( "modules", debug_stats, 'Make sure the "modules" key in in target.GetStatistics()', ) stats_json = debug_stats["targets"][0] self.assertIn( "expressionEvaluation", stats_json, 'Make sure the "expressionEvaluation" key in in target.GetStatistics()["targets"][0]', ) self.assertIn( "frameVariable", stats_json, 'Make sure the "frameVariable" key in in target.GetStatistics()["targets"][0]', ) expressionEvaluation = stats_json["expressionEvaluation"] self.assertIn( "successes", expressionEvaluation, 'Make sure the "successes" key in in "expressionEvaluation" dictionary"', ) self.assertIn( "failures", expressionEvaluation, 'Make sure the "failures" key in in "expressionEvaluation" dictionary"', ) frameVariable = stats_json["frameVariable"] self.assertIn( "successes", frameVariable, 'Make sure the "successes" key in in "frameVariable" dictionary"', ) self.assertIn( "failures", frameVariable, 'Make sure the "failures" key in in "frameVariable" dictionary"', ) # Test statistics summary. stats_options = lldb.SBStatisticsOptions() stats_options.SetSummaryOnly(True) stats_summary = target.GetStatistics(stats_options) stream_summary = lldb.SBStream() stats_summary.GetAsJSON(stream_summary) debug_stats_summary = json.loads(stream_summary.GetData()) self.assertNotIn("modules", debug_stats_summary) self.assertNotIn("commands", debug_stats_summary) # Summary values should be the same as in full statistics. # The exceptions to this are: # - The parse time on Mac OS X is not deterministic. # - Memory usage may grow over time due to the use of ConstString. for key, value in debug_stats_summary.items(): self.assertIn(key, debug_stats) if key != "memory" and key != "targets" and not key.endswith("Time"): self.assertEqual(debug_stats[key], value) def test_command_stats_api(self): """ Test GetCommandInterpreter::GetStatistics() API. """ self.build() exe = self.getBuildArtifact("a.out") lldbutil.run_to_name_breakpoint(self, "main") interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() interp.HandleCommand("bt", result) stream = lldb.SBStream() res = interp.GetStatistics().GetAsJSON(stream) command_stats = json.loads(stream.GetData()) # Verify bt command is correctly parsed into final form. self.assertEqual(command_stats["thread backtrace"], 1) # Verify original raw command is not duplicatedly captured. self.assertNotIn("bt", command_stats) # Verify bt's regex command is not duplicatedly captured. self.assertNotIn("_regexp-bt", command_stats) @add_test_categories(["dwo"]) def test_command_stats_force(self): """ Test reporting all pssible debug info stats by force loading all debug info. For example, dwo files """ src_dir = self.getSourceDir() dwo_yaml_path = os.path.join(src_dir, "main-main.dwo.yaml") exe_yaml_path = os.path.join(src_dir, "main.yaml") dwo_path = self.getBuildArtifact("main-main.dwo") exe_path = self.getBuildArtifact("main") self.yaml2obj(dwo_yaml_path, dwo_path) self.yaml2obj(exe_yaml_path, exe_path) # Turn on symbols on-demand loading self.runCmd("settings set symbols.load-on-demand true") # We need the current working directory to be set to the build directory os.chdir(self.getBuildDir()) # Create a target with the object file we just created from YAML target = self.dbg.CreateTarget(exe_path) self.assertTrue(target, VALID_TARGET) # Get statistics stats_options = lldb.SBStatisticsOptions() stats = target.GetStatistics(stats_options) stream = lldb.SBStream() stats.GetAsJSON(stream) debug_stats = json.loads(stream.GetData()) self.assertEqual(debug_stats["totalDebugInfoByteSize"], 193) # Get statistics with force loading stats_options.SetReportAllAvailableDebugInfo(True) stats_force = target.GetStatistics(stats_options) stream_force = lldb.SBStream() stats_force.GetAsJSON(stream_force) debug_stats_force = json.loads(stream_force.GetData()) self.assertEqual(debug_stats_force["totalDebugInfoByteSize"], 445)