1*a2154b19SGreg Claytonimport glob
2*a2154b19SGreg Claytonimport json
3*a2154b19SGreg Claytonimport lldb
4*a2154b19SGreg Claytonfrom lldbsuite.test.decorators import *
5*a2154b19SGreg Claytonfrom lldbsuite.test.lldbtest import *
6*a2154b19SGreg Claytonfrom lldbsuite.test import lldbutil
7*a2154b19SGreg Claytonimport os
8*a2154b19SGreg Claytonimport time
9*a2154b19SGreg Clayton
10*a2154b19SGreg Clayton
11*a2154b19SGreg Claytonclass DebugIndexCacheTestcase(TestBase):
12*a2154b19SGreg Clayton
13*a2154b19SGreg Clayton    def setUp(self):
14*a2154b19SGreg Clayton        # Call super's setUp().
15*a2154b19SGreg Clayton        TestBase.setUp(self)
16*a2154b19SGreg Clayton        # Set the lldb module cache directory to a directory inside the build
17*a2154b19SGreg Clayton        # artifacts directory so no other tests are interfered with.
18*a2154b19SGreg Clayton        self.cache_dir = os.path.join(self.getBuildDir(), 'lldb-module-cache')
19*a2154b19SGreg Clayton
20*a2154b19SGreg Clayton    def get_module_cache_files(self, basename):
21*a2154b19SGreg Clayton        module_cache_glob = os.path.join(self.cache_dir,
22*a2154b19SGreg Clayton                                         "llvmcache-*%s*dwarf-index*" % (basename))
23*a2154b19SGreg Clayton        return glob.glob(module_cache_glob)
24*a2154b19SGreg Clayton
25*a2154b19SGreg Clayton    def get_stats(self, log_path=None):
26*a2154b19SGreg Clayton        """
27*a2154b19SGreg Clayton            Get the output of the "statistics dump" and return the JSON as a
28*a2154b19SGreg Clayton            python dictionary.
29*a2154b19SGreg Clayton        """
30*a2154b19SGreg Clayton        # If log_path is set, open the path and emit the output of the command
31*a2154b19SGreg Clayton        # for debugging purposes.
32*a2154b19SGreg Clayton        if log_path is not None:
33*a2154b19SGreg Clayton            f = open(log_path, 'w')
34*a2154b19SGreg Clayton        else:
35*a2154b19SGreg Clayton            f = None
36*a2154b19SGreg Clayton        return_obj = lldb.SBCommandReturnObject()
37*a2154b19SGreg Clayton        command = "statistics dump "
38*a2154b19SGreg Clayton        if f:
39*a2154b19SGreg Clayton            f.write('(lldb) %s\n' % (command))
40*a2154b19SGreg Clayton        self.ci.HandleCommand(command, return_obj, False)
41*a2154b19SGreg Clayton        metrics_json = return_obj.GetOutput()
42*a2154b19SGreg Clayton        if f:
43*a2154b19SGreg Clayton            f.write(metrics_json)
44*a2154b19SGreg Clayton        return json.loads(metrics_json)
45*a2154b19SGreg Clayton
46*a2154b19SGreg Clayton    def enable_lldb_index_cache(self):
47*a2154b19SGreg Clayton        self.runCmd('settings set symbols.lldb-index-cache-path "%s"' % (self.cache_dir))
48*a2154b19SGreg Clayton        self.runCmd('settings set symbols.enable-lldb-index-cache true')
49*a2154b19SGreg Clayton
50*a2154b19SGreg Clayton    @no_debug_info_test
51*a2154b19SGreg Clayton    def test_with_caching_enabled(self):
52*a2154b19SGreg Clayton        """
53*a2154b19SGreg Clayton            Test module cache functionality for debug info index caching.
54*a2154b19SGreg Clayton
55*a2154b19SGreg Clayton            We test that a debug info index file is created for the debug
56*a2154b19SGreg Clayton            information when caching is enabled with a file that contains
57*a2154b19SGreg Clayton            at least one of each kind of DIE in ManualDWARFIndex::IndexSet.
58*a2154b19SGreg Clayton
59*a2154b19SGreg Clayton            The input file has DWARF that will fill in every member of the
60*a2154b19SGreg Clayton            ManualDWARFIndex::IndexSet class to ensure we can encode all of the
61*a2154b19SGreg Clayton            required information.
62*a2154b19SGreg Clayton
63*a2154b19SGreg Clayton            With caching enabled, we also verify that the appropriate statistics
64*a2154b19SGreg Clayton            specify that the cache file was saved to the cache.
65*a2154b19SGreg Clayton        """
66*a2154b19SGreg Clayton        self.enable_lldb_index_cache()
67*a2154b19SGreg Clayton        src_dir = self.getSourceDir()
68*a2154b19SGreg Clayton        yaml_path = os.path.join(src_dir, "exe.yaml")
69*a2154b19SGreg Clayton        yaml_base, ext = os.path.splitext(yaml_path)
70*a2154b19SGreg Clayton        obj_path = self.getBuildArtifact("main.o")
71*a2154b19SGreg Clayton        self.yaml2obj(yaml_path, obj_path)
72*a2154b19SGreg Clayton
73*a2154b19SGreg Clayton        # Create a target with the object file we just created from YAML
74*a2154b19SGreg Clayton        target = self.dbg.CreateTarget(obj_path)
75*a2154b19SGreg Clayton        self.assertTrue(target, VALID_TARGET)
76*a2154b19SGreg Clayton
77*a2154b19SGreg Clayton        debug_index_cache_files = self.get_module_cache_files('main.o')
78*a2154b19SGreg Clayton        self.assertEqual(len(debug_index_cache_files), 1,
79*a2154b19SGreg Clayton                "make sure there is one file in the module cache directory (%s) for main.o that is a debug info cache" % (self.cache_dir))
80*a2154b19SGreg Clayton
81*a2154b19SGreg Clayton        # Verify that the module statistics have the information that specifies
82*a2154b19SGreg Clayton        # if we loaded or saved the debug index and symtab to the cache
83*a2154b19SGreg Clayton        stats = self.get_stats()
84*a2154b19SGreg Clayton        module_stats = stats['modules'][0]
85*a2154b19SGreg Clayton        self.assertFalse(module_stats['debugInfoIndexLoadedFromCache'])
86*a2154b19SGreg Clayton        self.assertTrue(module_stats['debugInfoIndexSavedToCache'])
87*a2154b19SGreg Clayton        self.assertFalse(module_stats['symbolTableLoadedFromCache'])
88*a2154b19SGreg Clayton        self.assertTrue(module_stats['symbolTableSavedToCache'])
89*a2154b19SGreg Clayton        # Verify the top level stats track how many things were loaded or saved
90*a2154b19SGreg Clayton        # to the cache.
91*a2154b19SGreg Clayton        self.assertEqual(stats["totalDebugInfoIndexLoadedFromCache"], 0)
92*a2154b19SGreg Clayton        self.assertEqual(stats["totalDebugInfoIndexSavedToCache"], 1)
93*a2154b19SGreg Clayton        self.assertEqual(stats["totalSymbolTablesLoadedFromCache"], 0)
94*a2154b19SGreg Clayton        self.assertEqual(stats["totalSymbolTablesSavedToCache"], 1)
95*a2154b19SGreg Clayton
96*a2154b19SGreg Clayton    @no_debug_info_test
97*a2154b19SGreg Clayton    def test_with_caching_disabled(self):
98*a2154b19SGreg Clayton        """
99*a2154b19SGreg Clayton            Test module cache functionality for debug info index caching.
100*a2154b19SGreg Clayton
101*a2154b19SGreg Clayton            We test that a debug info index file is not created for the debug
102*a2154b19SGreg Clayton            information when caching is disabled with a file that contains
103*a2154b19SGreg Clayton            at least one of each kind of DIE in ManualDWARFIndex::IndexSet.
104*a2154b19SGreg Clayton
105*a2154b19SGreg Clayton            The input file has DWARF that will fill in every member of the
106*a2154b19SGreg Clayton            ManualDWARFIndex::IndexSet class to ensure we can encode all of the
107*a2154b19SGreg Clayton            required information.
108*a2154b19SGreg Clayton
109*a2154b19SGreg Clayton            With caching disabled, we also verify that the appropriate
110*a2154b19SGreg Clayton            statistics specify that the cache file was not saved to the cache.
111*a2154b19SGreg Clayton        """
112*a2154b19SGreg Clayton        src_dir = self.getSourceDir()
113*a2154b19SGreg Clayton        yaml_path = os.path.join(src_dir, "exe.yaml")
114*a2154b19SGreg Clayton        yaml_base, ext = os.path.splitext(yaml_path)
115*a2154b19SGreg Clayton        obj_path = self.getBuildArtifact("main.o")
116*a2154b19SGreg Clayton        self.yaml2obj(yaml_path, obj_path)
117*a2154b19SGreg Clayton
118*a2154b19SGreg Clayton        # Create a target with the object file we just created from YAML
119*a2154b19SGreg Clayton        target = self.dbg.CreateTarget(obj_path)
120*a2154b19SGreg Clayton        self.assertTrue(target, VALID_TARGET)
121*a2154b19SGreg Clayton
122*a2154b19SGreg Clayton        debug_index_cache_files = self.get_module_cache_files('main.o')
123*a2154b19SGreg Clayton        self.assertEqual(len(debug_index_cache_files), 0,
124*a2154b19SGreg Clayton                "make sure there is no file in the module cache directory (%s) for main.o that is a debug info cache" % (self.cache_dir))
125*a2154b19SGreg Clayton
126*a2154b19SGreg Clayton        # Verify that the module statistics have the information that specifies
127*a2154b19SGreg Clayton        # if we loaded or saved the debug index and symtab to the cache
128*a2154b19SGreg Clayton        stats = self.get_stats()
129*a2154b19SGreg Clayton        module_stats = stats['modules'][0]
130*a2154b19SGreg Clayton        self.assertFalse(module_stats['debugInfoIndexLoadedFromCache'])
131*a2154b19SGreg Clayton        self.assertFalse(module_stats['debugInfoIndexSavedToCache'])
132*a2154b19SGreg Clayton        self.assertFalse(module_stats['symbolTableLoadedFromCache'])
133*a2154b19SGreg Clayton        self.assertFalse(module_stats['symbolTableSavedToCache'])
134*a2154b19SGreg Clayton        # Verify the top level stats track how many things were loaded or saved
135*a2154b19SGreg Clayton        # to the cache.
136*a2154b19SGreg Clayton        self.assertEqual(stats["totalDebugInfoIndexLoadedFromCache"], 0)
137*a2154b19SGreg Clayton        self.assertEqual(stats["totalDebugInfoIndexSavedToCache"], 0)
138*a2154b19SGreg Clayton        self.assertEqual(stats["totalSymbolTablesLoadedFromCache"], 0)
139*a2154b19SGreg Clayton        self.assertEqual(stats["totalSymbolTablesSavedToCache"], 0)
140