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 =
158       SymbolFile::CompileUnits | SymbolFile::LineTables;
159   EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());
160 }
161 
162 TEST_F(SymbolFilePDBTests, TestResolveSymbolContextBasename) {
163   // Test that attempting to call ResolveSymbolContext with only a basename
164   // finds all full paths
165   // with the same basename
166   FileSpec fspec(m_pdb_test_exe.c_str(), false);
167   ArchSpec aspec("i686-pc-windows");
168   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
169 
170   SymbolVendor *plugin = module->GetSymbolVendor();
171   EXPECT_NE(nullptr, plugin);
172   SymbolFile *symfile = plugin->GetSymbolFile();
173 
174   FileSpec header_spec("test-pdb.cpp", false);
175   SymbolContextList sc_list;
176   uint32_t result_count = symfile->ResolveSymbolContext(
177       header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
178   EXPECT_EQ(1u, result_count);
179   EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec));
180 }
181 
182 TEST_F(SymbolFilePDBTests, TestResolveSymbolContextFullPath) {
183   // Test that attempting to call ResolveSymbolContext with a full path only
184   // finds the one source
185   // file that matches the full path.
186   FileSpec fspec(m_pdb_test_exe.c_str(), false);
187   ArchSpec aspec("i686-pc-windows");
188   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
189 
190   SymbolVendor *plugin = module->GetSymbolVendor();
191   EXPECT_NE(nullptr, plugin);
192   SymbolFile *symfile = plugin->GetSymbolFile();
193 
194   FileSpec header_spec(
195       R"spec(D:\src\llvm\tools\lldb\unittests\SymbolFile\PDB\Inputs\test-pdb.cpp)spec",
196       false);
197   SymbolContextList sc_list;
198   uint32_t result_count = symfile->ResolveSymbolContext(
199       header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
200   EXPECT_GE(1u, result_count);
201   EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec));
202 }
203 
204 TEST_F(SymbolFilePDBTests,
205        TestLookupOfHeaderFileWithInlines) {
206   // Test that when looking up a header file via ResolveSymbolContext (i.e. a
207   // file that was not by itself
208   // compiled, but only contributes to the combined code of other source files),
209   // a SymbolContext is returned
210   // for each compiland which has line contributions from the requested header.
211   FileSpec fspec(m_pdb_test_exe.c_str(), false);
212   ArchSpec aspec("i686-pc-windows");
213   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
214 
215   SymbolVendor *plugin = module->GetSymbolVendor();
216   EXPECT_NE(nullptr, plugin);
217   SymbolFile *symfile = plugin->GetSymbolFile();
218 
219   FileSpec header_specs[] = {FileSpec("test-pdb.h", false),
220                              FileSpec("test-pdb-nested.h", false)};
221   FileSpec main_cpp_spec("test-pdb.cpp", false);
222   FileSpec alt_cpp_spec("test-pdb-alt.cpp", false);
223   for (const auto &hspec : header_specs) {
224     SymbolContextList sc_list;
225     uint32_t result_count = symfile->ResolveSymbolContext(
226         hspec, 0, true, lldb::eSymbolContextCompUnit, sc_list);
227     EXPECT_EQ(2u, result_count);
228     EXPECT_TRUE(ContainsCompileUnit(sc_list, main_cpp_spec));
229     EXPECT_TRUE(ContainsCompileUnit(sc_list, alt_cpp_spec));
230   }
231 }
232 
233 TEST_F(SymbolFilePDBTests, TestLookupOfHeaderFileWithNoInlines) {
234   // Test that when looking up a header file via ResolveSymbolContext (i.e. a
235   // file that was not by itself
236   // compiled, but only contributes to the combined code of other source files),
237   // that if check_inlines
238   // is false, no SymbolContexts are returned.
239   FileSpec fspec(m_pdb_test_exe.c_str(), false);
240   ArchSpec aspec("i686-pc-windows");
241   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
242 
243   SymbolVendor *plugin = module->GetSymbolVendor();
244   EXPECT_NE(nullptr, plugin);
245   SymbolFile *symfile = plugin->GetSymbolFile();
246 
247   FileSpec header_specs[] = {FileSpec("test-pdb.h", false),
248                              FileSpec("test-pdb-nested.h", false)};
249   for (const auto &hspec : header_specs) {
250     SymbolContextList sc_list;
251     uint32_t result_count = symfile->ResolveSymbolContext(
252         hspec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
253     EXPECT_EQ(0u, result_count);
254   }
255 }
256 
257 TEST_F(SymbolFilePDBTests, TestLineTablesMatchAll) {
258   // Test that when calling ResolveSymbolContext with a line number of 0, all
259   // line entries from
260   // the specified files are returned.
261   FileSpec fspec(m_pdb_test_exe.c_str(), false);
262   ArchSpec aspec("i686-pc-windows");
263   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
264 
265   SymbolVendor *plugin = module->GetSymbolVendor();
266   SymbolFile *symfile = plugin->GetSymbolFile();
267 
268   FileSpec source_file("test-pdb.cpp", false);
269   FileSpec header1("test-pdb.h", false);
270   FileSpec header2("test-pdb-nested.h", false);
271   uint32_t cus = symfile->GetNumCompileUnits();
272   EXPECT_EQ(2u, cus);
273 
274   SymbolContextList sc_list;
275   uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
276 
277   uint32_t count =
278       symfile->ResolveSymbolContext(source_file, 0, true, scope, sc_list);
279   EXPECT_EQ(1u, count);
280   SymbolContext sc;
281   EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
282 
283   LineTable *lt = sc.comp_unit->GetLineTable();
284   EXPECT_NE(nullptr, lt);
285   count = lt->GetSize();
286   // We expect one extra entry for termination (per function)
287   EXPECT_EQ(16u, count);
288 
289   VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040);
290   VerifyLineEntry(module, sc, source_file, *lt, 8, 0x401043);
291   VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045);
292 
293   VerifyLineEntry(module, sc, source_file, *lt, 13, 0x401050);
294   VerifyLineEntry(module, sc, source_file, *lt, 14, 0x401054);
295   VerifyLineEntry(module, sc, source_file, *lt, 15, 0x401070);
296 
297   VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);
298   VerifyLineEntry(module, sc, header1, *lt, 10, 0x401093);
299   VerifyLineEntry(module, sc, header1, *lt, 11, 0x4010a2);
300 
301   VerifyLineEntry(module, sc, header2, *lt, 5, 0x401080);
302   VerifyLineEntry(module, sc, header2, *lt, 6, 0x401083);
303   VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089);
304 }
305 
306 TEST_F(SymbolFilePDBTests, TestLineTablesMatchSpecific) {
307   // Test that when calling ResolveSymbolContext with a specific line number,
308   // only line entries
309   // which match the requested line are returned.
310   FileSpec fspec(m_pdb_test_exe.c_str(), false);
311   ArchSpec aspec("i686-pc-windows");
312   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
313 
314   SymbolVendor *plugin = module->GetSymbolVendor();
315   SymbolFile *symfile = plugin->GetSymbolFile();
316 
317   FileSpec source_file("test-pdb.cpp", false);
318   FileSpec header1("test-pdb.h", false);
319   FileSpec header2("test-pdb-nested.h", false);
320   uint32_t cus = symfile->GetNumCompileUnits();
321   EXPECT_EQ(2u, cus);
322 
323   SymbolContextList sc_list;
324   uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
325 
326   // First test with line 7, and verify that only line 7 entries are added.
327   uint32_t count =
328       symfile->ResolveSymbolContext(source_file, 7, true, scope, sc_list);
329   EXPECT_EQ(1u, count);
330   SymbolContext sc;
331   EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
332 
333   LineTable *lt = sc.comp_unit->GetLineTable();
334   EXPECT_NE(nullptr, lt);
335   count = lt->GetSize();
336   // We expect one extra entry for termination
337   EXPECT_EQ(3u, count);
338 
339   VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040);
340   VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089);
341 
342   sc_list.Clear();
343   // Then test with line 9, and verify that only line 9 entries are added.
344   count = symfile->ResolveSymbolContext(source_file, 9, true, scope, sc_list);
345   EXPECT_EQ(1u, count);
346   EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
347 
348   lt = sc.comp_unit->GetLineTable();
349   EXPECT_NE(nullptr, lt);
350   count = lt->GetSize();
351   // We expect one extra entry for termination
352   EXPECT_EQ(3u, count);
353 
354   VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045);
355   VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);
356 }
357 
358 TEST_F(SymbolFilePDBTests, TestSimpleClassTypes) {
359   FileSpec fspec(m_types_test_exe.c_str(), false);
360   ArchSpec aspec("i686-pc-windows");
361   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
362 
363   SymbolVendor *plugin = module->GetSymbolVendor();
364   SymbolFilePDB *symfile =
365       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
366   llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
367   SymbolContext sc;
368   llvm::DenseSet<SymbolFile *> searched_files;
369   TypeMap results;
370   EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("Class"), nullptr, false, 0,
371                                    searched_files, results));
372   EXPECT_EQ(1u, results.GetSize());
373   lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
374   EXPECT_EQ(ConstString("Class"), udt_type->GetName());
375   CompilerType compiler_type = udt_type->GetForwardCompilerType();
376   EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
377   EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_Class"),
378             udt_type->GetByteSize());
379 }
380 
381 TEST_F(SymbolFilePDBTests, TestNestedClassTypes) {
382   FileSpec fspec(m_types_test_exe.c_str(), false);
383   ArchSpec aspec("i686-pc-windows");
384   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
385 
386   SymbolVendor *plugin = module->GetSymbolVendor();
387   SymbolFilePDB *symfile =
388       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
389   llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
390   SymbolContext sc;
391   llvm::DenseSet<SymbolFile *> searched_files;
392   TypeMap results;
393   EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("Class::NestedClass"),
394                                    nullptr, false, 0, searched_files, results));
395   EXPECT_EQ(1u, results.GetSize());
396   lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
397   EXPECT_EQ(ConstString("Class::NestedClass"), udt_type->GetName());
398   CompilerType compiler_type = udt_type->GetForwardCompilerType();
399   EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
400   EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NestedClass"),
401             udt_type->GetByteSize());
402 }
403 
404 TEST_F(SymbolFilePDBTests, TestClassInNamespace) {
405   FileSpec fspec(m_types_test_exe.c_str(), false);
406   ArchSpec aspec("i686-pc-windows");
407   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
408 
409   SymbolVendor *plugin = module->GetSymbolVendor();
410   SymbolFilePDB *symfile =
411       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
412   llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
413   SymbolContext sc;
414   llvm::DenseSet<SymbolFile *> searched_files;
415   TypeMap results;
416   EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("NS::NSClass"), nullptr,
417                                    false, 0, searched_files, results));
418   EXPECT_EQ(1u, results.GetSize());
419   lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
420   EXPECT_EQ(ConstString("NS::NSClass"), udt_type->GetName());
421   CompilerType compiler_type = udt_type->GetForwardCompilerType();
422   EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
423   EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NSClass"),
424             udt_type->GetByteSize());
425 }
426 
427 TEST_F(SymbolFilePDBTests, TestEnumTypes) {
428   FileSpec fspec(m_types_test_exe.c_str(), false);
429   ArchSpec aspec("i686-pc-windows");
430   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
431 
432   SymbolVendor *plugin = module->GetSymbolVendor();
433   SymbolFilePDB *symfile =
434       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
435   llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
436   SymbolContext sc;
437   llvm::DenseSet<SymbolFile *> searched_files;
438   const char *EnumsToCheck[] = {"Enum", "ShortEnum"};
439   for (auto Enum : EnumsToCheck) {
440     TypeMap results;
441     EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString(Enum), nullptr, false, 0,
442                                      searched_files, results));
443     EXPECT_EQ(1u, results.GetSize());
444     lldb::TypeSP enum_type = results.GetTypeAtIndex(0);
445     EXPECT_EQ(ConstString(Enum), enum_type->GetName());
446     CompilerType compiler_type = enum_type->GetFullCompilerType();
447     EXPECT_TRUE(ClangASTContext::IsEnumType(compiler_type.GetOpaqueQualType()));
448     clang::EnumDecl *enum_decl = ClangASTContext::GetAsEnumDecl(compiler_type);
449     EXPECT_NE(nullptr, enum_decl);
450     EXPECT_EQ(2, std::distance(enum_decl->enumerator_begin(),
451                                enum_decl->enumerator_end()));
452 
453     std::string sizeof_var = "sizeof_";
454     sizeof_var.append(Enum);
455     EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var),
456               enum_type->GetByteSize());
457   }
458 }
459 
460 TEST_F(SymbolFilePDBTests, TestArrayTypes) {
461   // In order to get this test working, we need to support lookup by symbol
462   // name.  Because array
463   // types themselves do not have names, only the symbols have names (i.e. the
464   // name of the array).
465 }
466 
467 TEST_F(SymbolFilePDBTests, TestFunctionTypes) {
468   // In order to get this test working, we need to support lookup by symbol
469   // name.  Because array
470   // types themselves do not have names, only the symbols have names (i.e. the
471   // name of the array).
472 }
473 
474 TEST_F(SymbolFilePDBTests, TestTypedefs) {
475   FileSpec fspec(m_types_test_exe.c_str(), false);
476   ArchSpec aspec("i686-pc-windows");
477   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
478 
479   SymbolVendor *plugin = module->GetSymbolVendor();
480   SymbolFilePDB *symfile =
481       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
482   llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
483   SymbolContext sc;
484   llvm::DenseSet<SymbolFile *> searched_files;
485   TypeMap results;
486 
487   const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef"};
488   for (auto Typedef : TypedefsToCheck) {
489     TypeMap results;
490     EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString(Typedef), nullptr, false,
491                                      0, searched_files, results));
492     EXPECT_EQ(1u, results.GetSize());
493     lldb::TypeSP typedef_type = results.GetTypeAtIndex(0);
494     EXPECT_EQ(ConstString(Typedef), typedef_type->GetName());
495     CompilerType compiler_type = typedef_type->GetFullCompilerType();
496     ClangASTContext *clang_type_system =
497         llvm::dyn_cast_or_null<ClangASTContext>(compiler_type.GetTypeSystem());
498     EXPECT_TRUE(
499         clang_type_system->IsTypedefType(compiler_type.GetOpaqueQualType()));
500 
501     std::string sizeof_var = "sizeof_";
502     sizeof_var.append(Typedef);
503     EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var),
504               typedef_type->GetByteSize());
505   }
506 }
507 
508 TEST_F(SymbolFilePDBTests, TestRegexNameMatch) {
509   FileSpec fspec(m_types_test_exe.c_str(), false);
510   ArchSpec aspec("i686-pc-windows");
511   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
512 
513   SymbolVendor *plugin = module->GetSymbolVendor();
514   SymbolFilePDB *symfile =
515       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
516   SymbolContext sc;
517   llvm::DenseSet<SymbolFile *> searched_files;
518   TypeMap results;
519   uint32_t num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr,
520                                             false, 0, searched_files, results);
521   EXPECT_GT(num_results, 1u);
522   EXPECT_EQ(num_results, results.GetSize());
523 }
524 
525 TEST_F(SymbolFilePDBTests, TestMaxMatches) {
526   FileSpec fspec(m_types_test_exe.c_str(), false);
527   ArchSpec aspec("i686-pc-windows");
528   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
529 
530   SymbolVendor *plugin = module->GetSymbolVendor();
531   SymbolFilePDB *symfile =
532       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
533   SymbolContext sc;
534   llvm::DenseSet<SymbolFile *> searched_files;
535   TypeMap results;
536   uint32_t num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr,
537                                             false, 0, searched_files, results);
538   // Try to limit ourselves from 1 to 10 results, otherwise we could be doing
539   // this thousands of times.
540   // The idea is just to make sure that for a variety of values, the number of
541   // limited results always
542   // comes out to the number we are expecting.
543   uint32_t iterations = std::min(num_results, 10u);
544   for (uint32_t i = 1; i <= iterations; ++i) {
545     uint32_t num_limited_results = symfile->FindTypes(
546         sc, ConstString(".*"), nullptr, false, i, searched_files, results);
547     EXPECT_EQ(i, num_limited_results);
548     EXPECT_EQ(num_limited_results, results.GetSize());
549   }
550 }
551 
552 TEST_F(SymbolFilePDBTests, TestNullName) {
553   FileSpec fspec(m_types_test_exe.c_str(), false);
554   ArchSpec aspec("i686-pc-windows");
555   lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
556 
557   SymbolVendor *plugin = module->GetSymbolVendor();
558   SymbolFilePDB *symfile =
559       static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
560   SymbolContext sc;
561   llvm::DenseSet<SymbolFile *> searched_files;
562   TypeMap results;
563   uint32_t num_results = symfile->FindTypes(sc, ConstString(), nullptr, false,
564                                             0, searched_files, results);
565   EXPECT_EQ(0u, num_results);
566   EXPECT_EQ(0u, results.GetSize());
567 }
568