1 //===-- PythonDataObjectsTests.cpp ------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "gtest/gtest.h"
11 
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/Config/config.h"
14 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/Path.h"
18 
19 #include "lldb/Core/Address.h"
20 #include "lldb/Core/ArchSpec.h"
21 #include "lldb/Core/Module.h"
22 #include "lldb/Core/ModuleSpec.h"
23 #include "lldb/Host/FileSpec.h"
24 #include "lldb/Host/HostInfo.h"
25 #include "lldb/Symbol/ClangASTContext.h"
26 #include "lldb/Symbol/CompileUnit.h"
27 #include "lldb/Symbol/LineTable.h"
28 #include "lldb/Symbol/SymbolVendor.h"
29 
30 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
31 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
32 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
33 
34 #if defined(_MSC_VER)
35 #include "lldb/Host/windows/windows.h"
36 #include <objbase.h>
37 #endif
38 
39 #include <algorithm>
40 
41 extern const char *TestMainArgv0;
42 
43 using namespace lldb_private;
44 
45 class SymbolFilePDBTests : public testing::Test {
46 public:
47   void SetUp() override {
48 // Initialize and TearDown the plugin every time, so we get a brand new
49 // AST every time so that modifications to the AST from each test don't
50 // leak into the next test.
51 #if defined(_MSC_VER)
52     ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
53 #endif
54 
55     HostInfo::Initialize();
56     ObjectFilePECOFF::Initialize();
57     SymbolFileDWARF::Initialize();
58     ClangASTContext::Initialize();
59     SymbolFilePDB::Initialize();
60 
61     llvm::StringRef exe_folder = llvm::sys::path::parent_path(TestMainArgv0);
62     llvm::SmallString<128> inputs_folder = exe_folder;
63     llvm::sys::path::append(inputs_folder, "Inputs");
64 
65     m_pdb_test_exe = inputs_folder;
66     m_dwarf_test_exe = inputs_folder;
67     m_types_test_exe = inputs_folder;
68     llvm::sys::path::append(m_pdb_test_exe, "test-pdb.exe");
69     llvm::sys::path::append(m_dwarf_test_exe, "test-dwarf.exe");
70     llvm::sys::path::append(m_types_test_exe, "test-pdb-types.exe");
71   }
72 
73   void TearDown() override {
74     SymbolFilePDB::Terminate();
75     ClangASTContext::Initialize();
76     SymbolFileDWARF::Terminate();
77     ObjectFilePECOFF::Terminate();
78     HostInfo::Terminate();
79 
80 #if defined(_MSC_VER)
81     ::CoUninitialize();
82 #endif
83   }
84 
85 protected:
86   llvm::SmallString<128> m_pdb_test_exe;
87   llvm::SmallString<128> m_dwarf_test_exe;
88   llvm::SmallString<128> m_types_test_exe;
89 
90   bool FileSpecMatchesAsBaseOrFull(const FileSpec &left,
91                                    const FileSpec &right) const {
92     // If the filenames don't match, the paths can't be equal
93     if (!left.FileEquals(right))
94       return false;
95     // If BOTH have a directory, also compare the directories.
96     if (left.GetDirectory() && right.GetDirectory())
97       return left.DirectoryEquals(right);
98 
99     // If one has a directory but not the other, they match.
100     return true;
101   }
102 
103   void VerifyLineEntry(lldb::ModuleSP module, const SymbolContext &sc,
104                        const FileSpec &spec, LineTable &lt, uint32_t line,
105                        lldb::addr_t addr) {
106     LineEntry entry;
107     Address address;
108     EXPECT_TRUE(module->ResolveFileAddress(addr, address));
109 
110     EXPECT_TRUE(lt.FindLineEntryByAddress(address, entry));
111     EXPECT_EQ(line, entry.line);
112     EXPECT_EQ(address, entry.range.GetBaseAddress());
113 
114     EXPECT_TRUE(FileSpecMatchesAsBaseOrFull(spec, entry.file));
115   }
116 
117   bool ContainsCompileUnit(const SymbolContextList &sc_list,
118                            const FileSpec &spec) const {
119     for (size_t i = 0; i < sc_list.GetSize(); ++i) {
120       const SymbolContext &sc = sc_list[i];
121       if (FileSpecMatchesAsBaseOrFull(*sc.comp_unit, spec))
122         return true;
123     }
124     return false;
125   }
126 
127   int GetGlobalConstantInteger(const llvm::pdb::IPDBSession &session,
128                                llvm::StringRef var) const {
129     auto global = session.getGlobalScope();
130     auto results =
131         global->findChildren(llvm::pdb::PDB_SymType::Data, var,
132                              llvm::pdb::PDB_NameSearchFlags::NS_Default);
133     uint32_t count = results->getChildCount();
134     if (count == 0)
135       return -1;
136 
137     auto item = results->getChildAtIndex(0);
138     auto symbol = llvm::dyn_cast<llvm::pdb::PDBSymbolData>(item.get());
139     if (!symbol)
140       return -1;
141     llvm::pdb::Variant value = symbol->getValue();
142     switch (value.Type) {
143     case llvm::pdb::PDB_VariantType::Int16:
144       return value.Value.Int16;
145     case llvm::pdb::PDB_VariantType::Int32:
146       return value.Value.Int32;
147     case llvm::pdb::PDB_VariantType::UInt16:
148       return value.Value.UInt16;
149     case llvm::pdb::PDB_VariantType::UInt32:
150       return value.Value.UInt32;
151     default:
152       return 0;
153     }
154   }
155 };
156 
157 #if HAVE_DIA_SDK
158 #define REQUIRES_DIA_SDK(TestName) TestName
159 #else
160 #define REQUIRES_DIA_SDK(TestName) DISABLED_##TestName
161 #endif
162 
163 TEST_F(SymbolFilePDBTests, TestAbilitiesForDWARF) {
164   // Test that when we have Dwarf debug info, SymbolFileDWARF is used.
165   FileSpec fspec(m_dwarf_test_exe.c_str(), false);
166   ArchSpec aspec("i686-pc-windows");
167   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
168 
169   SymbolVendor *plugin = module->GetSymbolVendor();
170   EXPECT_NE(nullptr, plugin);
171   SymbolFile *symfile = plugin->GetSymbolFile();
172   EXPECT_NE(nullptr, symfile);
173   EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic());
174 
175   uint32_t expected_abilities = SymbolFile::kAllAbilities;
176   EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());
177 }
178 
179 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestAbilitiesForPDB)) {
180   // Test that when we have PDB debug info, SymbolFilePDB is used.
181   FileSpec fspec(m_pdb_test_exe.c_str(), false);
182   ArchSpec aspec("i686-pc-windows");
183   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
184 
185   SymbolVendor *plugin = module->GetSymbolVendor();
186   EXPECT_NE(nullptr, plugin);
187   SymbolFile *symfile = plugin->GetSymbolFile();
188   EXPECT_NE(nullptr, symfile);
189   EXPECT_EQ(symfile->GetPluginName(), SymbolFilePDB::GetPluginNameStatic());
190 
191   uint32_t expected_abilities =
192       SymbolFile::CompileUnits | SymbolFile::LineTables;
193   EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());
194 }
195 
196 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestResolveSymbolContextBasename)) {
197   // Test that attempting to call ResolveSymbolContext with only a basename
198   // finds all full paths
199   // with the same basename
200   FileSpec fspec(m_pdb_test_exe.c_str(), false);
201   ArchSpec aspec("i686-pc-windows");
202   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
203 
204   SymbolVendor *plugin = module->GetSymbolVendor();
205   EXPECT_NE(nullptr, plugin);
206   SymbolFile *symfile = plugin->GetSymbolFile();
207 
208   FileSpec header_spec("test-pdb.cpp", false);
209   SymbolContextList sc_list;
210   uint32_t result_count = symfile->ResolveSymbolContext(
211       header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
212   EXPECT_EQ(1u, result_count);
213   EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec));
214 }
215 
216 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestResolveSymbolContextFullPath)) {
217   // Test that attempting to call ResolveSymbolContext with a full path only
218   // finds the one source
219   // file that matches the full path.
220   FileSpec fspec(m_pdb_test_exe.c_str(), false);
221   ArchSpec aspec("i686-pc-windows");
222   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
223 
224   SymbolVendor *plugin = module->GetSymbolVendor();
225   EXPECT_NE(nullptr, plugin);
226   SymbolFile *symfile = plugin->GetSymbolFile();
227 
228   FileSpec header_spec(
229       R"spec(D:\src\llvm\tools\lldb\unittests\SymbolFile\PDB\Inputs\test-pdb.cpp)spec",
230       false);
231   SymbolContextList sc_list;
232   uint32_t result_count = symfile->ResolveSymbolContext(
233       header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
234   EXPECT_GE(1u, result_count);
235   EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec));
236 }
237 
238 TEST_F(SymbolFilePDBTests,
239        REQUIRES_DIA_SDK(TestLookupOfHeaderFileWithInlines)) {
240   // Test that when looking up a header file via ResolveSymbolContext (i.e. a
241   // file that was not by itself
242   // compiled, but only contributes to the combined code of other source files),
243   // a SymbolContext is returned
244   // for each compiland which has line contributions from the requested header.
245   FileSpec fspec(m_pdb_test_exe.c_str(), false);
246   ArchSpec aspec("i686-pc-windows");
247   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
248 
249   SymbolVendor *plugin = module->GetSymbolVendor();
250   EXPECT_NE(nullptr, plugin);
251   SymbolFile *symfile = plugin->GetSymbolFile();
252 
253   FileSpec header_specs[] = {FileSpec("test-pdb.h", false),
254                              FileSpec("test-pdb-nested.h", false)};
255   FileSpec main_cpp_spec("test-pdb.cpp", false);
256   FileSpec alt_cpp_spec("test-pdb-alt.cpp", false);
257   for (const auto &hspec : header_specs) {
258     SymbolContextList sc_list;
259     uint32_t result_count = symfile->ResolveSymbolContext(
260         hspec, 0, true, lldb::eSymbolContextCompUnit, sc_list);
261     EXPECT_EQ(2u, result_count);
262     EXPECT_TRUE(ContainsCompileUnit(sc_list, main_cpp_spec));
263     EXPECT_TRUE(ContainsCompileUnit(sc_list, alt_cpp_spec));
264   }
265 }
266 
267 TEST_F(SymbolFilePDBTests,
268        REQUIRES_DIA_SDK(TestLookupOfHeaderFileWithNoInlines)) {
269   // Test that when looking up a header file via ResolveSymbolContext (i.e. a
270   // file that was not by itself
271   // compiled, but only contributes to the combined code of other source files),
272   // that if check_inlines
273   // is false, no SymbolContexts are returned.
274   FileSpec fspec(m_pdb_test_exe.c_str(), false);
275   ArchSpec aspec("i686-pc-windows");
276   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
277 
278   SymbolVendor *plugin = module->GetSymbolVendor();
279   EXPECT_NE(nullptr, plugin);
280   SymbolFile *symfile = plugin->GetSymbolFile();
281 
282   FileSpec header_specs[] = {FileSpec("test-pdb.h", false),
283                              FileSpec("test-pdb-nested.h", false)};
284   for (const auto &hspec : header_specs) {
285     SymbolContextList sc_list;
286     uint32_t result_count = symfile->ResolveSymbolContext(
287         hspec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
288     EXPECT_EQ(0u, result_count);
289   }
290 }
291 
292 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchAll)) {
293   // Test that when calling ResolveSymbolContext with a line number of 0, all
294   // line entries from
295   // the specified files are returned.
296   FileSpec fspec(m_pdb_test_exe.c_str(), false);
297   ArchSpec aspec("i686-pc-windows");
298   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
299 
300   SymbolVendor *plugin = module->GetSymbolVendor();
301   SymbolFile *symfile = plugin->GetSymbolFile();
302 
303   FileSpec source_file("test-pdb.cpp", false);
304   FileSpec header1("test-pdb.h", false);
305   FileSpec header2("test-pdb-nested.h", false);
306   uint32_t cus = symfile->GetNumCompileUnits();
307   EXPECT_EQ(2u, cus);
308 
309   SymbolContextList sc_list;
310   uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
311 
312   uint32_t count =
313       symfile->ResolveSymbolContext(source_file, 0, true, scope, sc_list);
314   EXPECT_EQ(1u, count);
315   SymbolContext sc;
316   EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
317 
318   LineTable *lt = sc.comp_unit->GetLineTable();
319   EXPECT_NE(nullptr, lt);
320   count = lt->GetSize();
321   // We expect one extra entry for termination (per function)
322   EXPECT_EQ(16u, count);
323 
324   VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040);
325   VerifyLineEntry(module, sc, source_file, *lt, 8, 0x401043);
326   VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045);
327 
328   VerifyLineEntry(module, sc, source_file, *lt, 13, 0x401050);
329   VerifyLineEntry(module, sc, source_file, *lt, 14, 0x401054);
330   VerifyLineEntry(module, sc, source_file, *lt, 15, 0x401070);
331 
332   VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);
333   VerifyLineEntry(module, sc, header1, *lt, 10, 0x401093);
334   VerifyLineEntry(module, sc, header1, *lt, 11, 0x4010a2);
335 
336   VerifyLineEntry(module, sc, header2, *lt, 5, 0x401080);
337   VerifyLineEntry(module, sc, header2, *lt, 6, 0x401083);
338   VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089);
339 }
340 
341 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchSpecific)) {
342   // Test that when calling ResolveSymbolContext with a specific line number,
343   // only line entries
344   // which match the requested line are returned.
345   FileSpec fspec(m_pdb_test_exe.c_str(), false);
346   ArchSpec aspec("i686-pc-windows");
347   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
348 
349   SymbolVendor *plugin = module->GetSymbolVendor();
350   SymbolFile *symfile = plugin->GetSymbolFile();
351 
352   FileSpec source_file("test-pdb.cpp", false);
353   FileSpec header1("test-pdb.h", false);
354   FileSpec header2("test-pdb-nested.h", false);
355   uint32_t cus = symfile->GetNumCompileUnits();
356   EXPECT_EQ(2u, cus);
357 
358   SymbolContextList sc_list;
359   uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
360 
361   // First test with line 7, and verify that only line 7 entries are added.
362   uint32_t count =
363       symfile->ResolveSymbolContext(source_file, 7, true, scope, sc_list);
364   EXPECT_EQ(1u, count);
365   SymbolContext sc;
366   EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
367 
368   LineTable *lt = sc.comp_unit->GetLineTable();
369   EXPECT_NE(nullptr, lt);
370   count = lt->GetSize();
371   // We expect one extra entry for termination
372   EXPECT_EQ(3u, count);
373 
374   VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040);
375   VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089);
376 
377   sc_list.Clear();
378   // Then test with line 9, and verify that only line 9 entries are added.
379   count = symfile->ResolveSymbolContext(source_file, 9, true, scope, sc_list);
380   EXPECT_EQ(1u, count);
381   EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
382 
383   lt = sc.comp_unit->GetLineTable();
384   EXPECT_NE(nullptr, lt);
385   count = lt->GetSize();
386   // We expect one extra entry for termination
387   EXPECT_EQ(3u, count);
388 
389   VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045);
390   VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);
391 }
392 
393 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestSimpleClassTypes)) {
394   FileSpec fspec(m_types_test_exe.c_str(), false);
395   ArchSpec aspec("i686-pc-windows");
396   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
397 
398   SymbolVendor *plugin = module->GetSymbolVendor();
399   SymbolFilePDB *symfile =
400       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
401   const llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
402   SymbolContext sc;
403   llvm::DenseSet<SymbolFile *> searched_files;
404   TypeMap results;
405   EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("Class"), nullptr, false, 0,
406                                    searched_files, results));
407   EXPECT_EQ(1u, results.GetSize());
408   lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
409   EXPECT_EQ(ConstString("Class"), udt_type->GetName());
410   CompilerType compiler_type = udt_type->GetForwardCompilerType();
411   EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
412   EXPECT_EQ(uint64_t(GetGlobalConstantInteger(session, "sizeof_Class")),
413             udt_type->GetByteSize());
414 }
415 
416 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNestedClassTypes)) {
417   FileSpec fspec(m_types_test_exe.c_str(), false);
418   ArchSpec aspec("i686-pc-windows");
419   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
420 
421   SymbolVendor *plugin = module->GetSymbolVendor();
422   SymbolFilePDB *symfile =
423       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
424   const llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
425   SymbolContext sc;
426   llvm::DenseSet<SymbolFile *> searched_files;
427   TypeMap results;
428   EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("Class::NestedClass"),
429                                    nullptr, false, 0, searched_files, results));
430   EXPECT_EQ(1u, results.GetSize());
431   lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
432   EXPECT_EQ(ConstString("Class::NestedClass"), udt_type->GetName());
433   CompilerType compiler_type = udt_type->GetForwardCompilerType();
434   EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
435   EXPECT_EQ(uint64_t(GetGlobalConstantInteger(session, "sizeof_NestedClass")),
436             udt_type->GetByteSize());
437 }
438 
439 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestClassInNamespace)) {
440   FileSpec fspec(m_types_test_exe.c_str(), false);
441   ArchSpec aspec("i686-pc-windows");
442   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
443 
444   SymbolVendor *plugin = module->GetSymbolVendor();
445   SymbolFilePDB *symfile =
446       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
447   const llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
448   SymbolContext sc;
449   llvm::DenseSet<SymbolFile *> searched_files;
450   TypeMap results;
451   EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("NS::NSClass"), nullptr,
452                                    false, 0, searched_files, results));
453   EXPECT_EQ(1u, results.GetSize());
454   lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
455   EXPECT_EQ(ConstString("NS::NSClass"), udt_type->GetName());
456   CompilerType compiler_type = udt_type->GetForwardCompilerType();
457   EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
458   EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NSClass"),
459             udt_type->GetByteSize());
460 }
461 
462 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestEnumTypes)) {
463   FileSpec fspec(m_types_test_exe.c_str(), false);
464   ArchSpec aspec("i686-pc-windows");
465   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
466 
467   SymbolVendor *plugin = module->GetSymbolVendor();
468   SymbolFilePDB *symfile =
469       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
470   const llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
471   SymbolContext sc;
472   llvm::DenseSet<SymbolFile *> searched_files;
473   const char *EnumsToCheck[] = {"Enum", "ShortEnum"};
474   for (auto Enum : EnumsToCheck) {
475     TypeMap results;
476     EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString(Enum), nullptr, false, 0,
477                                      searched_files, results));
478     EXPECT_EQ(1u, results.GetSize());
479     lldb::TypeSP enum_type = results.GetTypeAtIndex(0);
480     EXPECT_EQ(ConstString(Enum), enum_type->GetName());
481     CompilerType compiler_type = enum_type->GetFullCompilerType();
482     EXPECT_TRUE(ClangASTContext::IsEnumType(compiler_type.GetOpaqueQualType()));
483     clang::EnumDecl *enum_decl = ClangASTContext::GetAsEnumDecl(compiler_type);
484     EXPECT_NE(nullptr, enum_decl);
485     EXPECT_EQ(2, std::distance(enum_decl->enumerator_begin(),
486                                enum_decl->enumerator_end()));
487 
488     std::string sizeof_var = "sizeof_";
489     sizeof_var.append(Enum);
490     EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()),
491               enum_type->GetByteSize());
492   }
493 }
494 
495 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestArrayTypes)) {
496   // In order to get this test working, we need to support lookup by symbol
497   // name.  Because array
498   // types themselves do not have names, only the symbols have names (i.e. the
499   // name of the array).
500 }
501 
502 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestFunctionTypes)) {
503   // In order to get this test working, we need to support lookup by symbol
504   // name.  Because array
505   // types themselves do not have names, only the symbols have names (i.e. the
506   // name of the array).
507 }
508 
509 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestTypedefs)) {
510   FileSpec fspec(m_types_test_exe.c_str(), false);
511   ArchSpec aspec("i686-pc-windows");
512   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
513 
514   SymbolVendor *plugin = module->GetSymbolVendor();
515   SymbolFilePDB *symfile =
516       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
517   const llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
518   SymbolContext sc;
519   llvm::DenseSet<SymbolFile *> searched_files;
520   TypeMap results;
521 
522   const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef"};
523   for (auto Typedef : TypedefsToCheck) {
524     TypeMap results;
525     EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString(Typedef), nullptr, false,
526                                      0, searched_files, results));
527     EXPECT_EQ(1u, results.GetSize());
528     lldb::TypeSP typedef_type = results.GetTypeAtIndex(0);
529     EXPECT_EQ(ConstString(Typedef), typedef_type->GetName());
530     CompilerType compiler_type = typedef_type->GetFullCompilerType();
531     ClangASTContext *clang_type_system =
532         llvm::dyn_cast_or_null<ClangASTContext>(compiler_type.GetTypeSystem());
533     EXPECT_TRUE(
534         clang_type_system->IsTypedefType(compiler_type.GetOpaqueQualType()));
535 
536     std::string sizeof_var = "sizeof_";
537     sizeof_var.append(Typedef);
538     EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()),
539               typedef_type->GetByteSize());
540   }
541 }
542 
543 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestRegexNameMatch)) {
544   FileSpec fspec(m_types_test_exe.c_str(), false);
545   ArchSpec aspec("i686-pc-windows");
546   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
547 
548   SymbolVendor *plugin = module->GetSymbolVendor();
549   SymbolFilePDB *symfile =
550       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
551   SymbolContext sc;
552   llvm::DenseSet<SymbolFile *> searched_files;
553   TypeMap results;
554   uint32_t num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr,
555                                             false, 0, searched_files, results);
556   EXPECT_GT(num_results, 1u);
557   EXPECT_EQ(num_results, results.GetSize());
558 }
559 
560 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestMaxMatches)) {
561   FileSpec fspec(m_types_test_exe.c_str(), false);
562   ArchSpec aspec("i686-pc-windows");
563   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
564 
565   SymbolVendor *plugin = module->GetSymbolVendor();
566   SymbolFilePDB *symfile =
567       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
568   SymbolContext sc;
569   llvm::DenseSet<SymbolFile *> searched_files;
570   TypeMap results;
571   uint32_t num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr,
572                                             false, 0, searched_files, results);
573   // Try to limit ourselves from 1 to 10 results, otherwise we could be doing
574   // this thousands of times.
575   // The idea is just to make sure that for a variety of values, the number of
576   // limited results always
577   // comes out to the number we are expecting.
578   uint32_t iterations = std::min(num_results, 10u);
579   for (uint32_t i = 1; i <= iterations; ++i) {
580     uint32_t num_limited_results = symfile->FindTypes(
581         sc, ConstString(".*"), nullptr, false, i, searched_files, results);
582     EXPECT_EQ(i, num_limited_results);
583     EXPECT_EQ(num_limited_results, results.GetSize());
584   }
585 }
586 
587 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNullName)) {
588   FileSpec fspec(m_types_test_exe.c_str(), false);
589   ArchSpec aspec("i686-pc-windows");
590   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
591 
592   SymbolVendor *plugin = module->GetSymbolVendor();
593   SymbolFilePDB *symfile =
594       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
595   SymbolContext sc;
596   llvm::DenseSet<SymbolFile *> searched_files;
597   TypeMap results;
598   uint32_t num_results = symfile->FindTypes(sc, ConstString(), nullptr, false,
599                                             0, searched_files, results);
600   EXPECT_EQ(0u, num_results);
601   EXPECT_EQ(0u, results.GetSize());
602 }
603