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