16bbdecc5SRaphael Isemannimport lldb 2d7b33853SGreg Claytonimport json 3*3db7cc1bSGreg Claytonimport os 46bbdecc5SRaphael Isemannfrom lldbsuite.test.decorators import * 56bbdecc5SRaphael Isemannfrom lldbsuite.test.lldbtest import * 66bbdecc5SRaphael Isemannfrom lldbsuite.test import lldbutil 799451b44SJordan Rupprecht 86bbdecc5SRaphael Isemannclass TestCase(TestBase): 96bbdecc5SRaphael Isemann 10d7b33853SGreg Clayton NO_DEBUG_INFO_TESTCASE = True 11d7b33853SGreg Clayton 12d7b33853SGreg Clayton def test_enable_disable(self): 13d7b33853SGreg Clayton """ 14d7b33853SGreg Clayton Test "statistics disable" and "statistics enable". These don't do 15d7b33853SGreg Clayton anything anymore for cheap to gather statistics. In the future if 16d7b33853SGreg Clayton statistics are expensive to gather, we can enable the feature inside 17d7b33853SGreg Clayton of LLDB and test that enabling and disabling stops expesive information 18d7b33853SGreg Clayton from being gathered. 19d7b33853SGreg Clayton """ 20*3db7cc1bSGreg Clayton self.build() 21d7b33853SGreg Clayton target = self.createTestTarget() 226bbdecc5SRaphael Isemann 236bbdecc5SRaphael Isemann self.expect("statistics disable", substrs=['need to enable statistics before disabling'], error=True) 246bbdecc5SRaphael Isemann self.expect("statistics enable") 256bbdecc5SRaphael Isemann self.expect("statistics enable", substrs=['already enabled'], error=True) 266bbdecc5SRaphael Isemann self.expect("statistics disable") 27d7b33853SGreg Clayton self.expect("statistics disable", substrs=['need to enable statistics before disabling'], error=True) 286bbdecc5SRaphael Isemann 29d7b33853SGreg Clayton def verify_key_in_dict(self, key, d, description): 30d7b33853SGreg Clayton self.assertEqual(key in d, True, 31d7b33853SGreg Clayton 'make sure key "%s" is in dictionary %s' % (key, description)) 32d7b33853SGreg Clayton 33d7b33853SGreg Clayton def verify_key_not_in_dict(self, key, d, description): 34d7b33853SGreg Clayton self.assertEqual(key in d, False, 35d7b33853SGreg Clayton 'make sure key "%s" is in dictionary %s' % (key, description)) 36d7b33853SGreg Clayton 37d7b33853SGreg Clayton def verify_keys(self, dict, description, keys_exist, keys_missing=None): 38d7b33853SGreg Clayton """ 39d7b33853SGreg Clayton Verify that all keys in "keys_exist" list are top level items in 40d7b33853SGreg Clayton "dict", and that all keys in "keys_missing" do not exist as top 41d7b33853SGreg Clayton level items in "dict". 42d7b33853SGreg Clayton """ 43d7b33853SGreg Clayton if keys_exist: 44d7b33853SGreg Clayton for key in keys_exist: 45d7b33853SGreg Clayton self.verify_key_in_dict(key, dict, description) 46d7b33853SGreg Clayton if keys_missing: 47d7b33853SGreg Clayton for key in keys_missing: 48d7b33853SGreg Clayton self.verify_key_not_in_dict(key, dict, description) 49d7b33853SGreg Clayton 50d7b33853SGreg Clayton def verify_success_fail_count(self, stats, key, num_successes, num_fails): 51d7b33853SGreg Clayton self.verify_key_in_dict(key, stats, 'stats["%s"]' % (key)) 52d7b33853SGreg Clayton success_fail_dict = stats[key] 53d7b33853SGreg Clayton self.assertEqual(success_fail_dict['successes'], num_successes, 54d7b33853SGreg Clayton 'make sure success count') 55d7b33853SGreg Clayton self.assertEqual(success_fail_dict['failures'], num_fails, 56d7b33853SGreg Clayton 'make sure success count') 57d7b33853SGreg Clayton 58d7b33853SGreg Clayton def get_stats(self, options=None, log_path=None): 59d7b33853SGreg Clayton """ 60d7b33853SGreg Clayton Get the output of the "statistics dump" with optional extra options 61d7b33853SGreg Clayton and return the JSON as a python dictionary. 62d7b33853SGreg Clayton """ 63d7b33853SGreg Clayton # If log_path is set, open the path and emit the output of the command 64d7b33853SGreg Clayton # for debugging purposes. 65d7b33853SGreg Clayton if log_path is not None: 66d7b33853SGreg Clayton f = open(log_path, 'w') 67d7b33853SGreg Clayton else: 68d7b33853SGreg Clayton f = None 69d7b33853SGreg Clayton return_obj = lldb.SBCommandReturnObject() 70d7b33853SGreg Clayton command = "statistics dump " 71d7b33853SGreg Clayton if options is not None: 72d7b33853SGreg Clayton command += options 73d7b33853SGreg Clayton if f: 74d7b33853SGreg Clayton f.write('(lldb) %s\n' % (command)) 75d7b33853SGreg Clayton self.ci.HandleCommand(command, return_obj, False) 76d7b33853SGreg Clayton metrics_json = return_obj.GetOutput() 77d7b33853SGreg Clayton if f: 78d7b33853SGreg Clayton f.write(metrics_json) 79d7b33853SGreg Clayton return json.loads(metrics_json) 80d7b33853SGreg Clayton 81c571988eSGreg Clayton 82c571988eSGreg Clayton def get_target_stats(self, debug_stats): 83c571988eSGreg Clayton if "targets" in debug_stats: 84c571988eSGreg Clayton return debug_stats["targets"][0] 85c571988eSGreg Clayton return None 86c571988eSGreg Clayton 87d7b33853SGreg Clayton def test_expressions_frame_var_counts(self): 88*3db7cc1bSGreg Clayton self.build() 89d7b33853SGreg Clayton lldbutil.run_to_source_breakpoint(self, "// break here", 90d7b33853SGreg Clayton lldb.SBFileSpec("main.c")) 91d7b33853SGreg Clayton 92d7b33853SGreg Clayton self.expect("expr patatino", substrs=['27']) 93c571988eSGreg Clayton stats = self.get_target_stats(self.get_stats()) 94d7b33853SGreg Clayton self.verify_success_fail_count(stats, 'expressionEvaluation', 1, 0) 956a4905aeSRaphael Isemann self.expect("expr doesnt_exist", error=True, 966a4905aeSRaphael Isemann substrs=["undeclared identifier 'doesnt_exist'"]) 976a4905aeSRaphael Isemann # Doesn't successfully execute. 986a4905aeSRaphael Isemann self.expect("expr int *i = nullptr; *i", error=True) 99910838f0SGreg Clayton # Interpret an integer as an array with 3 elements is a failure for 100910838f0SGreg Clayton # the "expr" command, but the expression evaluation will succeed and 101910838f0SGreg Clayton # be counted as a success even though the "expr" options will for the 102910838f0SGreg Clayton # command to fail. It is more important to track expression evaluation 103910838f0SGreg Clayton # from all sources instead of just through the command, so this was 104910838f0SGreg Clayton # changed. If we want to track command success and fails, we can do 105910838f0SGreg Clayton # so using another metric. 1066a4905aeSRaphael Isemann self.expect("expr -Z 3 -- 1", error=True, 1076a4905aeSRaphael Isemann substrs=["expression cannot be used with --element-count"]) 1086a4905aeSRaphael Isemann # We should have gotten 3 new failures and the previous success. 109c571988eSGreg Clayton stats = self.get_target_stats(self.get_stats()) 110910838f0SGreg Clayton self.verify_success_fail_count(stats, 'expressionEvaluation', 2, 2) 1116bbdecc5SRaphael Isemann 1126bbdecc5SRaphael Isemann self.expect("statistics enable") 1136bbdecc5SRaphael Isemann # 'frame var' with enabled statistics will change stats. 1146bbdecc5SRaphael Isemann self.expect("frame var", substrs=['27']) 115c571988eSGreg Clayton stats = self.get_target_stats(self.get_stats()) 116d7b33853SGreg Clayton self.verify_success_fail_count(stats, 'frameVariable', 1, 0) 117d7b33853SGreg Clayton 118dbd36e1eSGreg Clayton # Test that "stopCount" is available when the process has run 119dbd36e1eSGreg Clayton self.assertEqual('stopCount' in stats, True, 120dbd36e1eSGreg Clayton 'ensure "stopCount" is in target JSON') 121dbd36e1eSGreg Clayton self.assertGreater(stats['stopCount'], 0, 122dbd36e1eSGreg Clayton 'make sure "stopCount" is greater than zero') 123dbd36e1eSGreg Clayton 124d7b33853SGreg Clayton def test_default_no_run(self): 125d7b33853SGreg Clayton """Test "statistics dump" without running the target. 126d7b33853SGreg Clayton 127d7b33853SGreg Clayton When we don't run the target, we expect to not see any 'firstStopTime' 128d7b33853SGreg Clayton or 'launchOrAttachTime' top level keys that measure the launch or 129d7b33853SGreg Clayton attach of the target. 130d7b33853SGreg Clayton 131d7b33853SGreg Clayton Output expected to be something like: 132d7b33853SGreg Clayton 133d7b33853SGreg Clayton (lldb) statistics dump 134d7b33853SGreg Clayton { 135cd8122b2SJonas Devlieghere "memory" : {...}, 136c571988eSGreg Clayton "modules" : [...], 137c571988eSGreg Clayton "targets" : [ 138c571988eSGreg Clayton { 139d7b33853SGreg Clayton "targetCreateTime": 0.26566899599999999, 140d7b33853SGreg Clayton "expressionEvaluation": { 141d7b33853SGreg Clayton "failures": 0, 142d7b33853SGreg Clayton "successes": 0 143d7b33853SGreg Clayton }, 144d7b33853SGreg Clayton "frameVariable": { 145d7b33853SGreg Clayton "failures": 0, 146d7b33853SGreg Clayton "successes": 0 147d7b33853SGreg Clayton }, 148c571988eSGreg Clayton "moduleIdentifiers": [...], 149c571988eSGreg Clayton } 150c571988eSGreg Clayton ], 1512887d9fdSGreg Clayton "totalDebugInfoByteSize": 182522234, 1522887d9fdSGreg Clayton "totalDebugInfoIndexTime": 2.33343, 1532887d9fdSGreg Clayton "totalDebugInfoParseTime": 8.2121400240000071, 154c571988eSGreg Clayton "totalSymbolTableParseTime": 0.123, 155c571988eSGreg Clayton "totalSymbolTableIndexTime": 0.234, 156d7b33853SGreg Clayton } 157d7b33853SGreg Clayton """ 158*3db7cc1bSGreg Clayton self.build() 159d7b33853SGreg Clayton target = self.createTestTarget() 160c571988eSGreg Clayton debug_stats = self.get_stats() 161c571988eSGreg Clayton debug_stat_keys = [ 162cd8122b2SJonas Devlieghere 'memory', 163c571988eSGreg Clayton 'modules', 164c571988eSGreg Clayton 'targets', 165c571988eSGreg Clayton 'totalSymbolTableParseTime', 166c571988eSGreg Clayton 'totalSymbolTableIndexTime', 167a2154b19SGreg Clayton 'totalSymbolTablesLoadedFromCache', 168a2154b19SGreg Clayton 'totalSymbolTablesSavedToCache', 1692887d9fdSGreg Clayton 'totalDebugInfoByteSize', 1702887d9fdSGreg Clayton 'totalDebugInfoIndexTime', 171a2154b19SGreg Clayton 'totalDebugInfoIndexLoadedFromCache', 172a2154b19SGreg Clayton 'totalDebugInfoIndexSavedToCache', 1732887d9fdSGreg Clayton 'totalDebugInfoParseTime', 174c571988eSGreg Clayton ] 175c571988eSGreg Clayton self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) 176c571988eSGreg Clayton stats = debug_stats['targets'][0] 177d7b33853SGreg Clayton keys_exist = [ 178d7b33853SGreg Clayton 'expressionEvaluation', 179d7b33853SGreg Clayton 'frameVariable', 180c571988eSGreg Clayton 'moduleIdentifiers', 181d7b33853SGreg Clayton 'targetCreateTime', 182d7b33853SGreg Clayton ] 183d7b33853SGreg Clayton keys_missing = [ 184d7b33853SGreg Clayton 'firstStopTime', 185d7b33853SGreg Clayton 'launchOrAttachTime' 186d7b33853SGreg Clayton ] 187d7b33853SGreg Clayton self.verify_keys(stats, '"stats"', keys_exist, keys_missing) 188d7b33853SGreg Clayton self.assertGreater(stats['targetCreateTime'], 0.0) 189d7b33853SGreg Clayton 190d7b33853SGreg Clayton def test_default_with_run(self): 191d7b33853SGreg Clayton """Test "statistics dump" when running the target to a breakpoint. 192d7b33853SGreg Clayton 193d7b33853SGreg Clayton When we run the target, we expect to see 'launchOrAttachTime' and 194d7b33853SGreg Clayton 'firstStopTime' top level keys. 195d7b33853SGreg Clayton 196d7b33853SGreg Clayton Output expected to be something like: 197d7b33853SGreg Clayton 198d7b33853SGreg Clayton (lldb) statistics dump 199d7b33853SGreg Clayton { 200cd8122b2SJonas Devlieghere "memory" : {...}, 201c571988eSGreg Clayton "modules" : [...], 202c571988eSGreg Clayton "targets" : [ 203c571988eSGreg Clayton { 204d7b33853SGreg Clayton "firstStopTime": 0.34164492800000001, 205d7b33853SGreg Clayton "launchOrAttachTime": 0.31969605400000001, 206c571988eSGreg Clayton "moduleIdentifiers": [...], 207d7b33853SGreg Clayton "targetCreateTime": 0.0040863039999999998 208d7b33853SGreg Clayton "expressionEvaluation": { 209d7b33853SGreg Clayton "failures": 0, 210d7b33853SGreg Clayton "successes": 0 211d7b33853SGreg Clayton }, 212d7b33853SGreg Clayton "frameVariable": { 213d7b33853SGreg Clayton "failures": 0, 214d7b33853SGreg Clayton "successes": 0 215d7b33853SGreg Clayton }, 216d7b33853SGreg Clayton } 217c571988eSGreg Clayton ], 2182887d9fdSGreg Clayton "totalDebugInfoByteSize": 182522234, 2192887d9fdSGreg Clayton "totalDebugInfoIndexTime": 2.33343, 2202887d9fdSGreg Clayton "totalDebugInfoParseTime": 8.2121400240000071, 221c571988eSGreg Clayton "totalSymbolTableParseTime": 0.123, 222c571988eSGreg Clayton "totalSymbolTableIndexTime": 0.234, 223c571988eSGreg Clayton } 224d7b33853SGreg Clayton 225d7b33853SGreg Clayton """ 226*3db7cc1bSGreg Clayton self.build() 227d7b33853SGreg Clayton target = self.createTestTarget() 228d7b33853SGreg Clayton lldbutil.run_to_source_breakpoint(self, "// break here", 229d7b33853SGreg Clayton lldb.SBFileSpec("main.c")) 230c571988eSGreg Clayton debug_stats = self.get_stats() 231c571988eSGreg Clayton debug_stat_keys = [ 232cd8122b2SJonas Devlieghere 'memory', 233c571988eSGreg Clayton 'modules', 234c571988eSGreg Clayton 'targets', 235c571988eSGreg Clayton 'totalSymbolTableParseTime', 236c571988eSGreg Clayton 'totalSymbolTableIndexTime', 237a2154b19SGreg Clayton 'totalSymbolTablesLoadedFromCache', 238a2154b19SGreg Clayton 'totalSymbolTablesSavedToCache', 2392887d9fdSGreg Clayton 'totalDebugInfoByteSize', 2402887d9fdSGreg Clayton 'totalDebugInfoIndexTime', 241a2154b19SGreg Clayton 'totalDebugInfoIndexLoadedFromCache', 242a2154b19SGreg Clayton 'totalDebugInfoIndexSavedToCache', 2432887d9fdSGreg Clayton 'totalDebugInfoParseTime', 244c571988eSGreg Clayton ] 245c571988eSGreg Clayton self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) 246c571988eSGreg Clayton stats = debug_stats['targets'][0] 247d7b33853SGreg Clayton keys_exist = [ 248d7b33853SGreg Clayton 'expressionEvaluation', 249d7b33853SGreg Clayton 'firstStopTime', 250d7b33853SGreg Clayton 'frameVariable', 251d7b33853SGreg Clayton 'launchOrAttachTime', 252c571988eSGreg Clayton 'moduleIdentifiers', 253d7b33853SGreg Clayton 'targetCreateTime', 254d7b33853SGreg Clayton ] 255d7b33853SGreg Clayton self.verify_keys(stats, '"stats"', keys_exist, None) 256d7b33853SGreg Clayton self.assertGreater(stats['firstStopTime'], 0.0) 257d7b33853SGreg Clayton self.assertGreater(stats['launchOrAttachTime'], 0.0) 258d7b33853SGreg Clayton self.assertGreater(stats['targetCreateTime'], 0.0) 259c571988eSGreg Clayton 260cd8122b2SJonas Devlieghere def test_memory(self): 261cd8122b2SJonas Devlieghere """ 262cd8122b2SJonas Devlieghere Test "statistics dump" and the memory information. 263cd8122b2SJonas Devlieghere """ 264*3db7cc1bSGreg Clayton self.build() 265cd8122b2SJonas Devlieghere exe = self.getBuildArtifact("a.out") 266cd8122b2SJonas Devlieghere target = self.createTestTarget(file_path=exe) 267cd8122b2SJonas Devlieghere debug_stats = self.get_stats() 268cd8122b2SJonas Devlieghere debug_stat_keys = [ 269cd8122b2SJonas Devlieghere 'memory', 270cd8122b2SJonas Devlieghere 'modules', 271cd8122b2SJonas Devlieghere 'targets', 272cd8122b2SJonas Devlieghere 'totalSymbolTableParseTime', 273cd8122b2SJonas Devlieghere 'totalSymbolTableIndexTime', 274cd8122b2SJonas Devlieghere 'totalSymbolTablesLoadedFromCache', 275cd8122b2SJonas Devlieghere 'totalSymbolTablesSavedToCache', 276cd8122b2SJonas Devlieghere 'totalDebugInfoParseTime', 277cd8122b2SJonas Devlieghere 'totalDebugInfoIndexTime', 278cd8122b2SJonas Devlieghere 'totalDebugInfoIndexLoadedFromCache', 279cd8122b2SJonas Devlieghere 'totalDebugInfoIndexSavedToCache', 280cd8122b2SJonas Devlieghere 'totalDebugInfoByteSize' 281cd8122b2SJonas Devlieghere ] 282cd8122b2SJonas Devlieghere self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) 283cd8122b2SJonas Devlieghere 284cd8122b2SJonas Devlieghere memory = debug_stats['memory'] 285cd8122b2SJonas Devlieghere memory_keys= [ 286cd8122b2SJonas Devlieghere 'strings', 287cd8122b2SJonas Devlieghere ] 288cd8122b2SJonas Devlieghere self.verify_keys(memory, '"memory"', memory_keys, None) 289cd8122b2SJonas Devlieghere 290cd8122b2SJonas Devlieghere strings = memory['strings'] 291cd8122b2SJonas Devlieghere strings_keys= [ 292cd8122b2SJonas Devlieghere 'bytesTotal', 293cd8122b2SJonas Devlieghere 'bytesUsed', 294cd8122b2SJonas Devlieghere 'bytesUnused', 295cd8122b2SJonas Devlieghere ] 296cd8122b2SJonas Devlieghere self.verify_keys(strings, '"strings"', strings_keys, None) 297cd8122b2SJonas Devlieghere 298cd8122b2SJonas Devlieghere 299c571988eSGreg Clayton def find_module_in_metrics(self, path, stats): 300c571988eSGreg Clayton modules = stats['modules'] 301c571988eSGreg Clayton for module in modules: 302c571988eSGreg Clayton if module['path'] == path: 303c571988eSGreg Clayton return module 304c571988eSGreg Clayton return None 305c571988eSGreg Clayton 306*3db7cc1bSGreg Clayton def find_module_by_id_in_metrics(self, id, stats): 307*3db7cc1bSGreg Clayton modules = stats['modules'] 308*3db7cc1bSGreg Clayton for module in modules: 309*3db7cc1bSGreg Clayton if module['identifier'] == id: 310*3db7cc1bSGreg Clayton return module 311*3db7cc1bSGreg Clayton return None 312*3db7cc1bSGreg Clayton 313c571988eSGreg Clayton def test_modules(self): 314c571988eSGreg Clayton """ 315c571988eSGreg Clayton Test "statistics dump" and the module information. 316c571988eSGreg Clayton """ 317*3db7cc1bSGreg Clayton self.build() 318c571988eSGreg Clayton exe = self.getBuildArtifact("a.out") 319c571988eSGreg Clayton target = self.createTestTarget(file_path=exe) 320c571988eSGreg Clayton debug_stats = self.get_stats() 321c571988eSGreg Clayton debug_stat_keys = [ 322cd8122b2SJonas Devlieghere 'memory', 323c571988eSGreg Clayton 'modules', 324c571988eSGreg Clayton 'targets', 325c571988eSGreg Clayton 'totalSymbolTableParseTime', 326c571988eSGreg Clayton 'totalSymbolTableIndexTime', 327a2154b19SGreg Clayton 'totalSymbolTablesLoadedFromCache', 328a2154b19SGreg Clayton 'totalSymbolTablesSavedToCache', 3292887d9fdSGreg Clayton 'totalDebugInfoParseTime', 3302887d9fdSGreg Clayton 'totalDebugInfoIndexTime', 331a2154b19SGreg Clayton 'totalDebugInfoIndexLoadedFromCache', 332a2154b19SGreg Clayton 'totalDebugInfoIndexSavedToCache', 3332887d9fdSGreg Clayton 'totalDebugInfoByteSize' 334c571988eSGreg Clayton ] 335c571988eSGreg Clayton self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) 336c571988eSGreg Clayton stats = debug_stats['targets'][0] 337c571988eSGreg Clayton keys_exist = [ 338c571988eSGreg Clayton 'moduleIdentifiers', 339c571988eSGreg Clayton ] 340c571988eSGreg Clayton self.verify_keys(stats, '"stats"', keys_exist, None) 341c571988eSGreg Clayton exe_module = self.find_module_in_metrics(exe, debug_stats) 342c571988eSGreg Clayton module_keys = [ 3432887d9fdSGreg Clayton 'debugInfoByteSize', 344a2154b19SGreg Clayton 'debugInfoIndexLoadedFromCache', 3452887d9fdSGreg Clayton 'debugInfoIndexTime', 346a2154b19SGreg Clayton 'debugInfoIndexSavedToCache', 3472887d9fdSGreg Clayton 'debugInfoParseTime', 348c571988eSGreg Clayton 'identifier', 349c571988eSGreg Clayton 'path', 350c571988eSGreg Clayton 'symbolTableIndexTime', 351a2154b19SGreg Clayton 'symbolTableLoadedFromCache', 352c571988eSGreg Clayton 'symbolTableParseTime', 353a2154b19SGreg Clayton 'symbolTableSavedToCache', 354c571988eSGreg Clayton 'triple', 355c571988eSGreg Clayton 'uuid', 356c571988eSGreg Clayton ] 357c571988eSGreg Clayton self.assertNotEqual(exe_module, None) 358c571988eSGreg Clayton self.verify_keys(exe_module, 'module dict for "%s"' % (exe), module_keys) 359fb254968SGreg Clayton 360fb254968SGreg Clayton def test_breakpoints(self): 361fb254968SGreg Clayton """Test "statistics dump" 362fb254968SGreg Clayton 363fb254968SGreg Clayton Output expected to be something like: 364fb254968SGreg Clayton 365fb254968SGreg Clayton { 366cd8122b2SJonas Devlieghere "memory" : {...}, 367fb254968SGreg Clayton "modules" : [...], 368fb254968SGreg Clayton "targets" : [ 369fb254968SGreg Clayton { 370fb254968SGreg Clayton "firstStopTime": 0.34164492800000001, 371fb254968SGreg Clayton "launchOrAttachTime": 0.31969605400000001, 372fb254968SGreg Clayton "moduleIdentifiers": [...], 373fb254968SGreg Clayton "targetCreateTime": 0.0040863039999999998 374fb254968SGreg Clayton "expressionEvaluation": { 375fb254968SGreg Clayton "failures": 0, 376fb254968SGreg Clayton "successes": 0 377fb254968SGreg Clayton }, 378fb254968SGreg Clayton "frameVariable": { 379fb254968SGreg Clayton "failures": 0, 380fb254968SGreg Clayton "successes": 0 381fb254968SGreg Clayton }, 382fb254968SGreg Clayton "breakpoints": [ 383fb254968SGreg Clayton { 384fb254968SGreg Clayton "details": {...}, 385fb254968SGreg Clayton "id": 1, 386fb254968SGreg Clayton "resolveTime": 2.65438675 387fb254968SGreg Clayton }, 388fb254968SGreg Clayton { 389fb254968SGreg Clayton "details": {...}, 390fb254968SGreg Clayton "id": 2, 391fb254968SGreg Clayton "resolveTime": 4.3632581669999997 392fb254968SGreg Clayton } 393fb254968SGreg Clayton ] 394fb254968SGreg Clayton } 395fb254968SGreg Clayton ], 396fb254968SGreg Clayton "totalDebugInfoByteSize": 182522234, 397fb254968SGreg Clayton "totalDebugInfoIndexTime": 2.33343, 398fb254968SGreg Clayton "totalDebugInfoParseTime": 8.2121400240000071, 399fb254968SGreg Clayton "totalSymbolTableParseTime": 0.123, 400fb254968SGreg Clayton "totalSymbolTableIndexTime": 0.234, 401fb254968SGreg Clayton "totalBreakpointResolveTime": 7.0176449170000001 402fb254968SGreg Clayton } 403fb254968SGreg Clayton 404fb254968SGreg Clayton """ 405*3db7cc1bSGreg Clayton self.build() 406fb254968SGreg Clayton target = self.createTestTarget() 407fb254968SGreg Clayton self.runCmd("b main.cpp:7") 408fb254968SGreg Clayton self.runCmd("b a_function") 409fb254968SGreg Clayton debug_stats = self.get_stats() 410fb254968SGreg Clayton debug_stat_keys = [ 411cd8122b2SJonas Devlieghere 'memory', 412fb254968SGreg Clayton 'modules', 413fb254968SGreg Clayton 'targets', 414fb254968SGreg Clayton 'totalSymbolTableParseTime', 415fb254968SGreg Clayton 'totalSymbolTableIndexTime', 416a2154b19SGreg Clayton 'totalSymbolTablesLoadedFromCache', 417a2154b19SGreg Clayton 'totalSymbolTablesSavedToCache', 418fb254968SGreg Clayton 'totalDebugInfoParseTime', 419fb254968SGreg Clayton 'totalDebugInfoIndexTime', 420a2154b19SGreg Clayton 'totalDebugInfoIndexLoadedFromCache', 421a2154b19SGreg Clayton 'totalDebugInfoIndexSavedToCache', 422fb254968SGreg Clayton 'totalDebugInfoByteSize', 423fb254968SGreg Clayton ] 424fb254968SGreg Clayton self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) 425fb254968SGreg Clayton target_stats = debug_stats['targets'][0] 426fb254968SGreg Clayton keys_exist = [ 427fb254968SGreg Clayton 'breakpoints', 428fb254968SGreg Clayton 'expressionEvaluation', 429fb254968SGreg Clayton 'frameVariable', 430fb254968SGreg Clayton 'targetCreateTime', 431fb254968SGreg Clayton 'moduleIdentifiers', 432fb254968SGreg Clayton 'totalBreakpointResolveTime', 433fb254968SGreg Clayton ] 434fb254968SGreg Clayton self.verify_keys(target_stats, '"stats"', keys_exist, None) 435fb254968SGreg Clayton self.assertGreater(target_stats['totalBreakpointResolveTime'], 0.0) 436fb254968SGreg Clayton breakpoints = target_stats['breakpoints'] 437fb254968SGreg Clayton bp_keys_exist = [ 438fb254968SGreg Clayton 'details', 439fb254968SGreg Clayton 'id', 440fb254968SGreg Clayton 'internal', 441fb254968SGreg Clayton 'numLocations', 442fb254968SGreg Clayton 'numResolvedLocations', 443fb254968SGreg Clayton 'resolveTime' 444fb254968SGreg Clayton ] 445fb254968SGreg Clayton for breakpoint in breakpoints: 446fb254968SGreg Clayton self.verify_keys(breakpoint, 'target_stats["breakpoints"]', 447fb254968SGreg Clayton bp_keys_exist, None) 448*3db7cc1bSGreg Clayton 449*3db7cc1bSGreg Clayton 450*3db7cc1bSGreg Clayton @skipUnlessDarwin 451*3db7cc1bSGreg Clayton @no_debug_info_test 452*3db7cc1bSGreg Clayton def test_dsym_binary_has_symfile_in_stats(self): 453*3db7cc1bSGreg Clayton """ 454*3db7cc1bSGreg Clayton Test that if our executable has a stand alone dSYM file containing 455*3db7cc1bSGreg Clayton debug information, that the dSYM file path is listed as a key/value 456*3db7cc1bSGreg Clayton pair in the "a.out" binaries module stats. Also verify the the main 457*3db7cc1bSGreg Clayton executable's module statistics has a debug info size that is greater 458*3db7cc1bSGreg Clayton than zero as the dSYM contains debug info. 459*3db7cc1bSGreg Clayton """ 460*3db7cc1bSGreg Clayton self.build(debug_info="dsym") 461*3db7cc1bSGreg Clayton exe_name = 'a.out' 462*3db7cc1bSGreg Clayton exe = self.getBuildArtifact(exe_name) 463*3db7cc1bSGreg Clayton dsym = self.getBuildArtifact(exe_name + ".dSYM") 464*3db7cc1bSGreg Clayton # Make sure the executable file exists after building. 465*3db7cc1bSGreg Clayton self.assertEqual(os.path.exists(exe), True) 466*3db7cc1bSGreg Clayton # Make sure the dSYM file exists after building. 467*3db7cc1bSGreg Clayton self.assertEqual(os.path.isdir(dsym), True) 468*3db7cc1bSGreg Clayton 469*3db7cc1bSGreg Clayton # Create the target 470*3db7cc1bSGreg Clayton target = self.createTestTarget(file_path=exe) 471*3db7cc1bSGreg Clayton 472*3db7cc1bSGreg Clayton debug_stats = self.get_stats() 473*3db7cc1bSGreg Clayton 474*3db7cc1bSGreg Clayton exe_stats = self.find_module_in_metrics(exe, debug_stats) 475*3db7cc1bSGreg Clayton # If we have a dSYM file, there should be a key/value pair in the module 476*3db7cc1bSGreg Clayton # statistics and the path should match the dSYM file path in the build 477*3db7cc1bSGreg Clayton # artifacts. 478*3db7cc1bSGreg Clayton self.assertIn('symbolFilePath', exe_stats) 479*3db7cc1bSGreg Clayton stats_dsym = exe_stats['symbolFilePath'] 480*3db7cc1bSGreg Clayton 481*3db7cc1bSGreg Clayton # Make sure main executable's module info has debug info size that is 482*3db7cc1bSGreg Clayton # greater than zero as the dSYM file and main executable work together 483*3db7cc1bSGreg Clayton # in the lldb.SBModule class to provide the data. 484*3db7cc1bSGreg Clayton self.assertGreater(exe_stats['debugInfoByteSize'], 0) 485*3db7cc1bSGreg Clayton 486*3db7cc1bSGreg Clayton # The "dsym" variable contains the bundle directory for the dSYM, while 487*3db7cc1bSGreg Clayton # the "stats_dsym" will have the 488*3db7cc1bSGreg Clayton self.assertIn(dsym, stats_dsym) 489*3db7cc1bSGreg Clayton # Since we have a dSYM file, we should not be loading DWARF from the .o 490*3db7cc1bSGreg Clayton # files and the .o file module identifiers should NOT be in the module 491*3db7cc1bSGreg Clayton # statistics. 492*3db7cc1bSGreg Clayton self.assertNotIn('symbolFileModuleIdentifiers', exe_stats) 493*3db7cc1bSGreg Clayton 494*3db7cc1bSGreg Clayton @skipUnlessDarwin 495*3db7cc1bSGreg Clayton @no_debug_info_test 496*3db7cc1bSGreg Clayton def test_no_dsym_binary_has_symfile_identifiers_in_stats(self): 497*3db7cc1bSGreg Clayton """ 498*3db7cc1bSGreg Clayton Test that if our executable loads debug info from the .o files, 499*3db7cc1bSGreg Clayton that the module statistics contains a 'symbolFileModuleIdentifiers' 500*3db7cc1bSGreg Clayton key which is a list of module identifiers, and verify that the 501*3db7cc1bSGreg Clayton module identifier can be used to find the .o file's module stats. 502*3db7cc1bSGreg Clayton Also verify the the main executable's module statistics has a debug 503*3db7cc1bSGreg Clayton info size that is zero, as the main executable itself has no debug 504*3db7cc1bSGreg Clayton info, but verify that the .o files have debug info size that is 505*3db7cc1bSGreg Clayton greater than zero. This test ensures that we don't double count 506*3db7cc1bSGreg Clayton debug info. 507*3db7cc1bSGreg Clayton """ 508*3db7cc1bSGreg Clayton self.build(debug_info="dwarf") 509*3db7cc1bSGreg Clayton exe_name = 'a.out' 510*3db7cc1bSGreg Clayton exe = self.getBuildArtifact(exe_name) 511*3db7cc1bSGreg Clayton dsym = self.getBuildArtifact(exe_name + ".dSYM") 512*3db7cc1bSGreg Clayton print("carp: dsym = '%s'" % (dsym)) 513*3db7cc1bSGreg Clayton # Make sure the executable file exists after building. 514*3db7cc1bSGreg Clayton self.assertEqual(os.path.exists(exe), True) 515*3db7cc1bSGreg Clayton # Make sure the dSYM file doesn't exist after building. 516*3db7cc1bSGreg Clayton self.assertEqual(os.path.isdir(dsym), False) 517*3db7cc1bSGreg Clayton 518*3db7cc1bSGreg Clayton # Create the target 519*3db7cc1bSGreg Clayton target = self.createTestTarget(file_path=exe) 520*3db7cc1bSGreg Clayton 521*3db7cc1bSGreg Clayton # Force the 'main.o' .o file's DWARF to be loaded so it will show up 522*3db7cc1bSGreg Clayton # in the stats. 523*3db7cc1bSGreg Clayton self.runCmd("b main.cpp:7") 524*3db7cc1bSGreg Clayton 525*3db7cc1bSGreg Clayton debug_stats = self.get_stats() 526*3db7cc1bSGreg Clayton 527*3db7cc1bSGreg Clayton exe_stats = self.find_module_in_metrics(exe, debug_stats) 528*3db7cc1bSGreg Clayton # If we don't have a dSYM file, there should not be a key/value pair in 529*3db7cc1bSGreg Clayton # the module statistics. 530*3db7cc1bSGreg Clayton self.assertNotIn('symbolFilePath', exe_stats) 531*3db7cc1bSGreg Clayton 532*3db7cc1bSGreg Clayton # Make sure main executable's module info has debug info size that is 533*3db7cc1bSGreg Clayton # zero as there is no debug info in the main executable, only in the 534*3db7cc1bSGreg Clayton # .o files. The .o files will also only be loaded if something causes 535*3db7cc1bSGreg Clayton # them to be loaded, so we set a breakpoint to force the .o file debug 536*3db7cc1bSGreg Clayton # info to be loaded. 537*3db7cc1bSGreg Clayton self.assertEqual(exe_stats['debugInfoByteSize'], 0) 538*3db7cc1bSGreg Clayton 539*3db7cc1bSGreg Clayton # When we don't have a dSYM file, the SymbolFileDWARFDebugMap class 540*3db7cc1bSGreg Clayton # should create modules for each .o file that contains DWARF that the 541*3db7cc1bSGreg Clayton # symbol file creates, so we need to verify that we have a valid module 542*3db7cc1bSGreg Clayton # identifier for main.o that is we should not be loading DWARF from the .o 543*3db7cc1bSGreg Clayton # files and the .o file module identifiers should NOT be in the module 544*3db7cc1bSGreg Clayton # statistics. 545*3db7cc1bSGreg Clayton self.assertIn('symbolFileModuleIdentifiers', exe_stats) 546*3db7cc1bSGreg Clayton 547*3db7cc1bSGreg Clayton symfileIDs = exe_stats['symbolFileModuleIdentifiers'] 548*3db7cc1bSGreg Clayton for symfileID in symfileIDs: 549*3db7cc1bSGreg Clayton o_module = self.find_module_by_id_in_metrics(symfileID, debug_stats) 550*3db7cc1bSGreg Clayton self.assertNotEqual(o_module, None) 551*3db7cc1bSGreg Clayton # Make sure each .o file has some debug info bytes. 552*3db7cc1bSGreg Clayton self.assertGreater(o_module['debugInfoByteSize'], 0) 553