| import glob | |
| import json | |
| import lldb | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test import lldbutil | |
| import os | |
| import time | |
| class DebugIndexCacheTestcase(TestBase): | |
| SHARED_BUILD_TESTCASE = False | |
| def setUp(self): | |
| # Call super's setUp(). | |
| TestBase.setUp(self) | |
| # Set the lldb module cache directory to a directory inside the build | |
| # artifacts directory so no other tests are interfered with. | |
| self.cache_dir = os.path.join(self.getBuildDir(), "lldb-module-cache") | |
| def get_module_cache_files(self, basename): | |
| module_cache_glob = os.path.join( | |
| self.cache_dir, "llvmcache-*%s*dwarf-index*" % (basename) | |
| ) | |
| return glob.glob(module_cache_glob) | |
| def get_stats(self, log_path=None): | |
| """ | |
| Get the output of the "statistics dump" and return the JSON as a | |
| python dictionary. | |
| """ | |
| # If log_path is set, open the path and emit the output of the command | |
| # for debugging purposes. | |
| if log_path is not None: | |
| f = open(log_path, "w") | |
| else: | |
| f = None | |
| return_obj = lldb.SBCommandReturnObject() | |
| command = "statistics dump " | |
| if f: | |
| f.write("(lldb) %s\n" % (command)) | |
| self.ci.HandleCommand(command, return_obj, False) | |
| metrics_json = return_obj.GetOutput() | |
| if f: | |
| f.write(metrics_json) | |
| return json.loads(metrics_json) | |
| def enable_lldb_index_cache(self): | |
| self.runCmd( | |
| 'settings set symbols.lldb-index-cache-path "%s"' % (self.cache_dir) | |
| ) | |
| self.runCmd("settings set symbols.enable-lldb-index-cache true") | |
| @no_debug_info_test | |
| def test_with_caching_enabled(self): | |
| """ | |
| Test module cache functionality for debug info index caching. | |
| We test that a debug info index file is created for the debug | |
| information when caching is enabled with a file that contains | |
| at least one of each kind of DIE in ManualDWARFIndex::IndexSet. | |
| The input file has DWARF that will fill in every member of the | |
| ManualDWARFIndex::IndexSet class to ensure we can encode all of the | |
| required information. | |
| With caching enabled, we also verify that the appropriate statistics | |
| specify that the cache file was saved to the cache. | |
| """ | |
| self.enable_lldb_index_cache() | |
| src_dir = self.getSourceDir() | |
| yaml_path = os.path.join(src_dir, "exe.yaml") | |
| yaml_base, ext = os.path.splitext(yaml_path) | |
| obj_path = self.getBuildArtifact("main.o") | |
| self.yaml2obj(yaml_path, obj_path) | |
| # Create a target with the object file we just created from YAML | |
| target = self.dbg.CreateTarget(obj_path) | |
| self.assertTrue(target, VALID_TARGET) | |
| debug_index_cache_files = self.get_module_cache_files("main.o") | |
| self.assertEqual( | |
| len(debug_index_cache_files), | |
| 1, | |
| "make sure there is one file in the module cache directory (%s) for main.o that is a debug info cache" | |
| % (self.cache_dir), | |
| ) | |
| # Verify that the module statistics have the information that specifies | |
| # if we loaded or saved the debug index and symtab to the cache | |
| stats = self.get_stats() | |
| module_stats = stats["modules"][0] | |
| self.assertFalse(module_stats["debugInfoIndexLoadedFromCache"]) | |
| self.assertTrue(module_stats["debugInfoIndexSavedToCache"]) | |
| self.assertFalse(module_stats["symbolTableLoadedFromCache"]) | |
| self.assertTrue(module_stats["symbolTableSavedToCache"]) | |
| # Verify the top level stats track how many things were loaded or saved | |
| # to the cache. | |
| self.assertEqual(stats["totalDebugInfoIndexLoadedFromCache"], 0) | |
| self.assertEqual(stats["totalDebugInfoIndexSavedToCache"], 1) | |
| self.assertEqual(stats["totalSymbolTablesLoadedFromCache"], 0) | |
| self.assertEqual(stats["totalSymbolTablesSavedToCache"], 1) | |
| @no_debug_info_test | |
| def test_with_caching_disabled(self): | |
| """ | |
| Test module cache functionality for debug info index caching. | |
| We test that a debug info index file is not created for the debug | |
| information when caching is disabled with a file that contains | |
| at least one of each kind of DIE in ManualDWARFIndex::IndexSet. | |
| The input file has DWARF that will fill in every member of the | |
| ManualDWARFIndex::IndexSet class to ensure we can encode all of the | |
| required information. | |
| With caching disabled, we also verify that the appropriate | |
| statistics specify that the cache file was not saved to the cache. | |
| """ | |
| src_dir = self.getSourceDir() | |
| yaml_path = os.path.join(src_dir, "exe.yaml") | |
| yaml_base, ext = os.path.splitext(yaml_path) | |
| obj_path = self.getBuildArtifact("main.o") | |
| self.yaml2obj(yaml_path, obj_path) | |
| # Create a target with the object file we just created from YAML | |
| target = self.dbg.CreateTarget(obj_path) | |
| self.assertTrue(target, VALID_TARGET) | |
| debug_index_cache_files = self.get_module_cache_files("main.o") | |
| self.assertEqual( | |
| len(debug_index_cache_files), | |
| 0, | |
| "make sure there is no file in the module cache directory (%s) for main.o that is a debug info cache" | |
| % (self.cache_dir), | |
| ) | |
| # Verify that the module statistics have the information that specifies | |
| # if we loaded or saved the debug index and symtab to the cache | |
| stats = self.get_stats() | |
| module_stats = stats["modules"][0] | |
| self.assertFalse(module_stats["debugInfoIndexLoadedFromCache"]) | |
| self.assertFalse(module_stats["debugInfoIndexSavedToCache"]) | |
| self.assertFalse(module_stats["symbolTableLoadedFromCache"]) | |
| self.assertFalse(module_stats["symbolTableSavedToCache"]) | |
| # Verify the top level stats track how many things were loaded or saved | |
| # to the cache. | |
| self.assertEqual(stats["totalDebugInfoIndexLoadedFromCache"], 0) | |
| self.assertEqual(stats["totalDebugInfoIndexSavedToCache"], 0) | |
| self.assertEqual(stats["totalSymbolTablesLoadedFromCache"], 0) | |
| self.assertEqual(stats["totalSymbolTablesSavedToCache"], 0) |