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