1*da816ca0SGreg Clayton"""Test the LLDB module cache funcionality."""
2*da816ca0SGreg Clayton
3*da816ca0SGreg Claytonimport glob
4*da816ca0SGreg Claytonimport lldb
5*da816ca0SGreg Claytonfrom lldbsuite.test.decorators import *
6*da816ca0SGreg Claytonfrom lldbsuite.test.lldbtest import *
7*da816ca0SGreg Claytonfrom lldbsuite.test import lldbutil
8*da816ca0SGreg Claytonimport os
9*da816ca0SGreg Claytonimport time
10*da816ca0SGreg Clayton
11*da816ca0SGreg Clayton
12*da816ca0SGreg Claytonclass ModuleCacheTestcaseBSD(TestBase):
13*da816ca0SGreg Clayton
14*da816ca0SGreg Clayton    mydir = TestBase.compute_mydir(__file__)
15*da816ca0SGreg Clayton
16*da816ca0SGreg Clayton    def setUp(self):
17*da816ca0SGreg Clayton        # Call super's setUp().
18*da816ca0SGreg Clayton        TestBase.setUp(self)
19*da816ca0SGreg Clayton        # Find the line number in a(int) to break at.
20*da816ca0SGreg Clayton        self.line_a = line_number(
21*da816ca0SGreg Clayton            'a.c', '// Set file and line breakpoint inside a().')
22*da816ca0SGreg Clayton        self.line_b = line_number(
23*da816ca0SGreg Clayton            'b.c', '// Set file and line breakpoint inside b().')
24*da816ca0SGreg Clayton        self.line_c = line_number(
25*da816ca0SGreg Clayton            'c.c', '// Set file and line breakpoint inside c().')
26*da816ca0SGreg Clayton        self.cache_dir = os.path.join(self.getBuildDir(), 'lldb-module-cache')
27*da816ca0SGreg Clayton        # Set the lldb module cache directory to a directory inside the build
28*da816ca0SGreg Clayton        # artifacts directory so no other tests are interfered with.
29*da816ca0SGreg Clayton        self.runCmd('settings set symbols.lldb-index-cache-path "%s"' % (self.cache_dir))
30*da816ca0SGreg Clayton        self.runCmd('settings set symbols.enable-lldb-index-cache true')
31*da816ca0SGreg Clayton        self.build()
32*da816ca0SGreg Clayton
33*da816ca0SGreg Clayton
34*da816ca0SGreg Clayton    def get_module_cache_files(self, basename):
35*da816ca0SGreg Clayton        module_cache_glob = os.path.join(self.cache_dir, "llvmcache-*%s*symtab*" % (basename))
36*da816ca0SGreg Clayton        return glob.glob(module_cache_glob)
37*da816ca0SGreg Clayton
38*da816ca0SGreg Clayton
39*da816ca0SGreg Clayton    # Requires no dSYM, so we let the Makefile make the right stuff for us
40*da816ca0SGreg Clayton    @no_debug_info_test
41*da816ca0SGreg Clayton    @skipUnlessDarwin
42*da816ca0SGreg Clayton    def test(self):
43*da816ca0SGreg Clayton        """
44*da816ca0SGreg Clayton            Test module cache functionality for bsd archive object files.
45*da816ca0SGreg Clayton
46*da816ca0SGreg Clayton            This will test that if we enable the module cache, we have a
47*da816ca0SGreg Clayton            corresponding cache entry for the .o files in libfoo.a.
48*da816ca0SGreg Clayton
49*da816ca0SGreg Clayton            The static library has two entries for "a.o":
50*da816ca0SGreg Clayton            - one from a.c
51*da816ca0SGreg Clayton            - one from c.c which had c.o renamed to a.o and then put into the
52*da816ca0SGreg Clayton              libfoo.a as an extra .o file with different contents from the
53*da816ca0SGreg Clayton              original a.o
54*da816ca0SGreg Clayton
55*da816ca0SGreg Clayton            We do this to test that we can correctly cache duplicate .o files
56*da816ca0SGreg Clayton            that appear in .a files.
57*da816ca0SGreg Clayton
58*da816ca0SGreg Clayton            This test only works on darwin because of the way DWARF is stored
59*da816ca0SGreg Clayton            where the debug map will refer to .o files inside of .a files.
60*da816ca0SGreg Clayton        """
61*da816ca0SGreg Clayton        exe = self.getBuildArtifact("a.out")
62*da816ca0SGreg Clayton
63*da816ca0SGreg Clayton        # Create a module with no depedencies.
64*da816ca0SGreg Clayton        target = self.createTestTarget(load_dependent_modules=False)
65*da816ca0SGreg Clayton
66*da816ca0SGreg Clayton        self.runCmd('breakpoint set -f a.c -l %d' % (self.line_a))
67*da816ca0SGreg Clayton        self.runCmd('breakpoint set -f b.c -l %d' % (self.line_b))
68*da816ca0SGreg Clayton        self.runCmd('breakpoint set -f c.c -l %d' % (self.line_c))
69*da816ca0SGreg Clayton
70*da816ca0SGreg Clayton        # Get the executable module and get the number of symbols to make
71*da816ca0SGreg Clayton        # sure the symbol table gets parsed and cached. The module cache is
72*da816ca0SGreg Clayton        # enabled in the setUp() function.
73*da816ca0SGreg Clayton        main_module = target.GetModuleAtIndex(0)
74*da816ca0SGreg Clayton        self.assertTrue(main_module.IsValid())
75*da816ca0SGreg Clayton        # Make sure the symbol table gets loaded and cached
76*da816ca0SGreg Clayton        main_module.GetNumSymbols()
77*da816ca0SGreg Clayton        a_o_cache_files = self.get_module_cache_files("libfoo.a(a.o)")
78*da816ca0SGreg Clayton        b_o_cache_files = self.get_module_cache_files("libfoo.a(b.o)")
79*da816ca0SGreg Clayton        # We expect the directory for a.o to have two cache directories:
80*da816ca0SGreg Clayton        # - 1 for the a.o with a earlier mod time
81*da816ca0SGreg Clayton        # - 1 for the a.o that was renamed from c.o that should be 2 seconds older
82*da816ca0SGreg Clayton        self.assertEqual(len(a_o_cache_files), 2,
83*da816ca0SGreg Clayton                "make sure there are two files in the module cache directory (%s) for libfoo.a(a.o)" % (self.cache_dir))
84*da816ca0SGreg Clayton        self.assertEqual(len(b_o_cache_files), 1,
85*da816ca0SGreg Clayton                "make sure there are two files in the module cache directory (%s) for libfoo.a(b.o)" % (self.cache_dir))
86