1da816ca0SGreg Clayton"""Test the LLDB module cache funcionality."""
2da816ca0SGreg Clayton
3da816ca0SGreg Claytonimport glob
4da816ca0SGreg Claytonimport lldb
5da816ca0SGreg Claytonfrom lldbsuite.test.decorators import *
6da816ca0SGreg Claytonfrom lldbsuite.test.lldbtest import *
7da816ca0SGreg Claytonfrom lldbsuite.test import lldbutil
8da816ca0SGreg Claytonimport os
9da816ca0SGreg Claytonimport time
10da816ca0SGreg Clayton
11da816ca0SGreg Clayton
12da816ca0SGreg Claytonclass ModuleCacheTestcaseSimple(TestBase):
13da816ca0SGreg Clayton
14da816ca0SGreg Clayton    def setUp(self):
15da816ca0SGreg Clayton        # Call super's setUp().
16da816ca0SGreg Clayton        TestBase.setUp(self)
17da816ca0SGreg Clayton        # Find the line number in a(int) to break at.
18da816ca0SGreg Clayton        self.cache_dir = os.path.join(self.getBuildDir(), 'lldb-module-cache')
19da816ca0SGreg Clayton        # Set the lldb module cache directory to a directory inside the build
20da816ca0SGreg Clayton        # artifacts directory so no other tests are interfered with.
21da816ca0SGreg Clayton        self.runCmd('settings set symbols.lldb-index-cache-path "%s"' % (self.cache_dir))
22da816ca0SGreg Clayton        self.runCmd('settings set symbols.enable-lldb-index-cache true')
23da816ca0SGreg Clayton        self.build()
24da816ca0SGreg Clayton
25da816ca0SGreg Clayton
26da816ca0SGreg Clayton    def get_module_cache_files(self, basename):
27*daed4797SPavel Labath        module_file_glob = os.path.join(self.cache_dir,
28*daed4797SPavel Labath                "llvmcache-*%s*-symtab-*" % (basename))
29da816ca0SGreg Clayton        return glob.glob(module_file_glob)
30da816ca0SGreg Clayton
31da816ca0SGreg Clayton    # Doesn't depend on any specific debug information.
32da816ca0SGreg Clayton    @no_debug_info_test
33a2154b19SGreg Clayton    @skipIfWindows
34da816ca0SGreg Clayton    def test(self):
35da816ca0SGreg Clayton        """
36da816ca0SGreg Clayton            Test module cache functionality for a simple object file.
37da816ca0SGreg Clayton
38da816ca0SGreg Clayton            This will test that if we enable the module cache, we have a
39da816ca0SGreg Clayton            corresponding index cache entry for the symbol table for the
40da816ca0SGreg Clayton            executable. It also removes the executable, rebuilds so that the
41da816ca0SGreg Clayton            modification time of the binary gets updated, and then creates a new
42da816ca0SGreg Clayton            target and should cause the cache to get updated so the cache file
43da816ca0SGreg Clayton            should get an updated modification time.
44da816ca0SGreg Clayton        """
45da816ca0SGreg Clayton        exe = self.getBuildArtifact("a.out")
46da816ca0SGreg Clayton
47da816ca0SGreg Clayton        # Create a module with no depedencies.
48da816ca0SGreg Clayton        target = self.createTestTarget(load_dependent_modules=False)
49da816ca0SGreg Clayton
50da816ca0SGreg Clayton        # Get the executable module and get the number of symbols to make
51da816ca0SGreg Clayton        # sure the symbol table gets parsed and cached. The module cache is
52da816ca0SGreg Clayton        # enabled in the setUp() function.
53da816ca0SGreg Clayton        main_module = target.GetModuleAtIndex(0)
54da816ca0SGreg Clayton        self.assertTrue(main_module.IsValid())
55da816ca0SGreg Clayton        # Make sure the symbol table gets loaded and cached
56da816ca0SGreg Clayton        main_module.GetNumSymbols()
57da816ca0SGreg Clayton        cache_files = self.get_module_cache_files("a.out")
58da816ca0SGreg Clayton        self.assertEqual(len(cache_files), 1,
59da816ca0SGreg Clayton                         "make sure there is only one cache file for 'a.out'")
60da816ca0SGreg Clayton        symtab_cache_path = cache_files[0]
61da816ca0SGreg Clayton        exe_mtime_1 = os.path.getmtime(exe)
62da816ca0SGreg Clayton        symtab_mtime_1 = os.path.getmtime(symtab_cache_path)
63da816ca0SGreg Clayton        # Now remove the executable and sleep for a few seconds to make sure we
64da816ca0SGreg Clayton        # get a different creation and modification time for the file since some
65da816ca0SGreg Clayton        # OSs store the modification time in seconds since Jan 1, 1970.
66da816ca0SGreg Clayton        os.remove(exe)
67da816ca0SGreg Clayton        self.assertEqual(os.path.exists(exe), False,
68da816ca0SGreg Clayton                         'make sure we were able to remove the executable')
69da816ca0SGreg Clayton        time.sleep(2)
70da816ca0SGreg Clayton        # Now rebuild the binary so it has a different content which should
71da816ca0SGreg Clayton        # update the UUID to make the cache miss when it tries to load the
72da816ca0SGreg Clayton        # symbol table from the binary at the same path.
73da816ca0SGreg Clayton        self.build(dictionary={'CFLAGS_EXTRAS': '-DEXTRA_FUNCTION'})
74da816ca0SGreg Clayton        self.assertEqual(os.path.exists(exe), True,
75da816ca0SGreg Clayton                         'make sure executable exists after rebuild')
76da816ca0SGreg Clayton        # Make sure the modification time has changed or this test will fail.
77da816ca0SGreg Clayton        exe_mtime_2 = os.path.getmtime(exe)
78da816ca0SGreg Clayton        self.assertNotEqual(
79da816ca0SGreg Clayton                exe_mtime_1,
80da816ca0SGreg Clayton                exe_mtime_2,
81da816ca0SGreg Clayton                "make sure the modification time of the executable has changed")
82da816ca0SGreg Clayton        # Make sure the module cache still has an out of date cache with the
83da816ca0SGreg Clayton        # same old modification time.
84da816ca0SGreg Clayton        self.assertEqual(symtab_mtime_1,
85da816ca0SGreg Clayton                         os.path.getmtime(symtab_cache_path),
86da816ca0SGreg Clayton                         "check that the 'symtab' cache file modification time doesn't match the executable modification time after rebuild")
87da816ca0SGreg Clayton        # Create a new target and get the symbols again, and make sure the cache
88da816ca0SGreg Clayton        # gets updated for the symbol table cache
89da816ca0SGreg Clayton        target = self.createTestTarget(load_dependent_modules=False)
90da816ca0SGreg Clayton        main_module = target.GetModuleAtIndex(0)
91da816ca0SGreg Clayton        self.assertTrue(main_module.IsValid())
92da816ca0SGreg Clayton        main_module.GetNumSymbols()
93da816ca0SGreg Clayton        self.assertEqual(os.path.exists(symtab_cache_path), True,
94da816ca0SGreg Clayton                         'make sure "symtab" cache files exists after cache is updated')
95da816ca0SGreg Clayton        symtab_mtime_2 = os.path.getmtime(symtab_cache_path)
96da816ca0SGreg Clayton        self.assertNotEqual(
97da816ca0SGreg Clayton                symtab_mtime_1,
98da816ca0SGreg Clayton                symtab_mtime_2,
99da816ca0SGreg Clayton                'make sure modification time of "symtab-..." changed')
100