| """Test the LLDB module cache funcionality.""" | |
| import glob | |
| import lldb | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test import lldbutil | |
| import os | |
| import time | |
| @requireNotWasm("modules carry no build ID to cache on") | |
| class ModuleCacheTestcaseSimple(TestBase): | |
| SHARED_BUILD_TESTCASE = False | |
| def setUp(self): | |
| # Call super's setUp(). | |
| TestBase.setUp(self) | |
| # Find the line number in a(int) to break at. | |
| self.cache_dir = os.path.join(self.getBuildDir(), "lldb-module-cache") | |
| # Set the lldb module cache directory to a directory inside the build | |
| # artifacts directory so no other tests are interfered with. | |
| self.runCmd( | |
| 'settings set symbols.lldb-index-cache-path "%s"' % (self.cache_dir) | |
| ) | |
| self.runCmd("settings set symbols.enable-lldb-index-cache true") | |
| self.build() | |
| def get_module_cache_files(self, basename): | |
| module_file_glob = os.path.join( | |
| self.cache_dir, "llvmcache-*%s*-symtab-*" % (basename) | |
| ) | |
| return glob.glob(module_file_glob) | |
| # Doesn't depend on any specific debug information. | |
| @no_debug_info_test | |
| @skipIfWindows | |
| def test(self): | |
| """ | |
| Test module cache functionality for a simple object file. | |
| This will test that if we enable the module cache, we have a | |
| corresponding index cache entry for the symbol table for the | |
| executable. It also removes the executable, rebuilds so that the | |
| modification time of the binary gets updated, and then creates a new | |
| target and should cause the cache to get updated so the cache file | |
| should get an updated modification time. | |
| """ | |
| exe = self.getBuildArtifact("a.out") | |
| # Create a module with no dependencies. | |
| target = self.createTestTarget(load_dependent_modules=False) | |
| # Get the executable module and get the number of symbols to make | |
| # sure the symbol table gets parsed and cached. The module cache is | |
| # enabled in the setUp() function. | |
| main_module = target.GetModuleAtIndex(0) | |
| self.assertTrue(main_module.IsValid()) | |
| # Make sure the symbol table gets loaded and cached | |
| main_module.GetNumSymbols() | |
| cache_files = self.get_module_cache_files("a.out") | |
| self.assertEqual( | |
| len(cache_files), 1, "make sure there is only one cache file for 'a.out'" | |
| ) | |
| symtab_cache_path = cache_files[0] | |
| exe_mtime_1 = os.path.getmtime(exe) | |
| symtab_mtime_1 = os.path.getmtime(symtab_cache_path) | |
| # Now remove the executable and sleep for a few seconds to make sure we | |
| # get a different creation and modification time for the file since some | |
| # OSs store the modification time in seconds since Jan 1, 1970. | |
| os.remove(exe) | |
| self.assertFalse( | |
| os.path.exists(exe), "make sure we were able to remove the executable" | |
| ) | |
| time.sleep(2) | |
| # Now rebuild the binary so it has a different content which should | |
| # update the UUID to make the cache miss when it tries to load the | |
| # symbol table from the binary at the same path. | |
| self.build(dictionary={"CFLAGS_EXTRAS": "-DEXTRA_FUNCTION"}) | |
| self.assertTrue( | |
| os.path.exists(exe), "make sure executable exists after rebuild" | |
| ) | |
| # Make sure the modification time has changed or this test will fail. | |
| exe_mtime_2 = os.path.getmtime(exe) | |
| self.assertNotEqual( | |
| exe_mtime_1, | |
| exe_mtime_2, | |
| "make sure the modification time of the executable has changed", | |
| ) | |
| # Make sure the module cache still has an out of date cache with the | |
| # same old modification time. | |
| self.assertEqual( | |
| symtab_mtime_1, | |
| os.path.getmtime(symtab_cache_path), | |
| "check that the 'symtab' cache file modification time doesn't match the executable modification time after rebuild", | |
| ) | |
| # Create a new target and get the symbols again, and make sure the cache | |
| # gets updated for the symbol table cache | |
| target = self.createTestTarget(load_dependent_modules=False) | |
| main_module = target.GetModuleAtIndex(0) | |
| self.assertTrue(main_module.IsValid()) | |
| main_module.GetNumSymbols() | |
| self.assertTrue( | |
| os.path.exists(symtab_cache_path), | |
| 'make sure "symtab" cache files exists after cache is updated', | |
| ) | |
| symtab_mtime_2 = os.path.getmtime(symtab_cache_path) | |
| self.assertNotEqual( | |
| symtab_mtime_1, | |
| symtab_mtime_2, | |
| 'make sure modification time of "symtab-..." changed', | |
| ) |