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