e8addf1ae7a32aea116ba036165a7209381143ce
[lldb.git] / llvm / unittests / TextAPI / TextStubV4Tests.cpp
1 //===-- TextStubV4Tests.cpp - TBD V4 File Test ----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===-----------------------------------------------------------------------===/
8
9 #include "TextStubHelpers.h"
10 #include "llvm/TextAPI/MachO/InterfaceFile.h"
11 #include "llvm/TextAPI/MachO/TextAPIReader.h"
12 #include "llvm/TextAPI/MachO/TextAPIWriter.h"
13 #include "gtest/gtest.h"
14 #include <string>
15 #include <vector>
16
17 using namespace llvm;
18 using namespace llvm::MachO;
19
20
21 namespace TBDv4 {
22
23 TEST(TBDv4, ReadFile) {
24   static const char TBDv4File[] =
25       "--- !tapi-tbd\n"
26       "tbd-version: 4\n"
27       "targets:  [ i386-macos, x86_64-macos, x86_64-ios ]\n"
28       "uuids:\n"
29       "  - target: i386-macos\n"
30       "    value: 00000000-0000-0000-0000-000000000000\n"
31       "  - target: x86_64-macos\n"
32       "    value: 11111111-1111-1111-1111-111111111111\n"
33       "  - target: x86_64-ios\n"
34       "    value: 11111111-1111-1111-1111-111111111111\n"
35       "flags: [ flat_namespace, installapi ]\n"
36       "install-name: Umbrella.framework/Umbrella\n"
37       "current-version: 1.2.3\n"
38       "compatibility-version: 1.2\n"
39       "swift-abi-version: 5\n"
40       "parent-umbrella:\n"
41       "  - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n"
42       "    umbrella: System\n"
43       "allowable-clients:\n"
44       "  - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n"
45       "    clients: [ ClientA ]\n"
46       "reexported-libraries:\n"
47       "  - targets: [ i386-macos ]\n"
48       "    libraries: [ /System/Library/Frameworks/A.framework/A ]\n"
49       "exports:\n"
50       "  - targets: [ i386-macos ]\n"
51       "    symbols: [ _symA ]\n"
52       "    objc-classes: []\n"
53       "    objc-eh-types: []\n"
54       "    objc-ivars: []\n"
55       "    weak-symbols: []\n"
56       "    thread-local-symbols: []\n"
57       "  - targets: [ x86_64-ios ]\n"
58       "    symbols: [_symB]\n"
59       "  - targets: [ x86_64-macos, x86_64-ios ]\n"
60       "    symbols: [_symAB]\n"
61       "reexports:\n"
62       "  - targets: [ i386-macos ]\n"
63       "    symbols: [_symC]\n"
64       "    objc-classes: []\n"
65       "    objc-eh-types: []\n"
66       "    objc-ivars: []\n"
67       "    weak-symbols: []\n"
68       "    thread-local-symbols: []\n"
69       "undefineds:\n"
70       "  - targets: [ i386-macos ]\n"
71       "    symbols: [ _symD ]\n"
72       "    objc-classes: []\n"
73       "    objc-eh-types: []\n"
74       "    objc-ivars: []\n"
75       "    weak-symbols: []\n"
76       "    thread-local-symbols: []\n"
77       "...\n";
78
79   Expected<TBDFile> Result =
80       TextAPIReader::get(MemoryBufferRef(TBDv4File, "Test.tbd"));
81   EXPECT_TRUE(!!Result);
82   TBDFile File = std::move(Result.get());
83   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
84   PlatformSet Platforms;
85   Platforms.insert(PlatformKind::macOS);
86   Platforms.insert(PlatformKind::iOS);
87   auto Archs = AK_i386 | AK_x86_64;
88   TargetList Targets = {
89       Target(AK_i386, PlatformKind::macOS),
90       Target(AK_x86_64, PlatformKind::macOS),
91       Target(AK_x86_64, PlatformKind::iOS),
92   };
93   UUIDs uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"},
94                  {Targets[1], "11111111-1111-1111-1111-111111111111"},
95                  {Targets[2], "11111111-1111-1111-1111-111111111111"}};
96   EXPECT_EQ(Archs, File->getArchitectures());
97   EXPECT_EQ(uuids, File->uuids());
98   EXPECT_EQ(Platforms.size(), File->getPlatforms().size());
99   for (auto Platform : File->getPlatforms())
100     EXPECT_EQ(Platforms.count(Platform), 1U);
101   EXPECT_EQ(std::string("Umbrella.framework/Umbrella"), File->getInstallName());
102   EXPECT_EQ(PackedVersion(1, 2, 3), File->getCurrentVersion());
103   EXPECT_EQ(PackedVersion(1, 2, 0), File->getCompatibilityVersion());
104   EXPECT_EQ(5U, File->getSwiftABIVersion());
105   EXPECT_FALSE(File->isTwoLevelNamespace());
106   EXPECT_TRUE(File->isApplicationExtensionSafe());
107   EXPECT_TRUE(File->isInstallAPI());
108   InterfaceFileRef client("ClientA", Targets);
109   InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A",
110                             {Targets[0]});
111   EXPECT_EQ(1U, File->allowableClients().size());
112   EXPECT_EQ(client, File->allowableClients().front());
113   EXPECT_EQ(1U, File->reexportedLibraries().size());
114   EXPECT_EQ(reexport, File->reexportedLibraries().front());
115
116   ExportedSymbolSeq Exports, Reexports, Undefineds;
117   ExportedSymbol temp;
118   for (const auto *Sym : File->symbols()) {
119     temp = ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
120                           Sym->isWeakDefined(), Sym->isThreadLocalValue()};
121     EXPECT_FALSE(Sym->isWeakReferenced());
122     if (Sym->isUndefined())
123       Undefineds.emplace_back(std::move(temp));
124     else
125       Sym->isReexported() ? Reexports.emplace_back(std::move(temp))
126                           : Exports.emplace_back(std::move(temp));
127   }
128   llvm::sort(Exports.begin(), Exports.end());
129   llvm::sort(Reexports.begin(), Reexports.end());
130   llvm::sort(Undefineds.begin(), Undefineds.end());
131
132   static ExportedSymbol ExpectedExportedSymbols[] = {
133       {SymbolKind::GlobalSymbol, "_symA", false, false},
134       {SymbolKind::GlobalSymbol, "_symAB", false, false},
135       {SymbolKind::GlobalSymbol, "_symB", false, false},
136   };
137
138   static ExportedSymbol ExpectedReexportedSymbols[] = {
139       {SymbolKind::GlobalSymbol, "_symC", false, false},
140   };
141
142   static ExportedSymbol ExpectedUndefinedSymbols[] = {
143       {SymbolKind::GlobalSymbol, "_symD", false, false},
144   };
145
146   EXPECT_EQ(sizeof(ExpectedExportedSymbols) / sizeof(ExportedSymbol),
147             Exports.size());
148   EXPECT_EQ(sizeof(ExpectedReexportedSymbols) / sizeof(ExportedSymbol),
149             Reexports.size());
150   EXPECT_EQ(sizeof(ExpectedUndefinedSymbols) / sizeof(ExportedSymbol),
151             Undefineds.size());
152   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
153                          std::begin(ExpectedExportedSymbols)));
154   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
155                          std::begin(ExpectedReexportedSymbols)));
156   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
157                          std::begin(ExpectedUndefinedSymbols)));
158 }
159
160 TEST(TBDv4, ReadMultipleDocuments) {
161   static const char TBDv4Inlines[] =
162       "--- !tapi-tbd\n"
163       "tbd-version: 4\n"
164       "targets: [ i386-macos, i386-maccatalyst, x86_64-macos, "
165       "x86_64-maccatalyst ]\n"
166       "uuids:\n"
167       "  - target: i386-macos\n"
168       "    value: 00000000-0000-0000-0000-000000000000\n"
169       "  - target: i386-maccatalyst\n"
170       "    value: 00000000-0000-0000-0000-000000000002\n"
171       "  - target: x86_64-macos\n"
172       "    value: 11111111-1111-1111-1111-111111111111\n"
173       "  - target: x86_64-maccatalyst\n"
174       "    value: 11111111-1111-1111-1111-111111111112\n"
175       "install-name: /System/Library/Frameworks/Umbrella.framework/Umbrella\n"
176       "parent-umbrella:\n"
177       "  - targets: [ i386-macos, x86_64-macos ]\n"
178       "    umbrella: System\n"
179       "reexported-libraries:\n"
180       "  - targets: [ i386-macos, x86_64-macos ]\n"
181       "    libraries: [ /System/Library/Frameworks/A.framework/A ]\n"
182       "--- !tapi-tbd\n"
183       "tbd-version: 4\n"
184       "targets:  [ i386-macos, x86_64-macos ]\n"
185       "uuids:\n"
186       "  - target: i386-macos\n"
187       "    value: 20000000-0000-0000-0000-000000000000\n"
188       "  - target: x86_64-macos\n"
189       "    value: 21111111-1111-1111-1111-111111111111\n"
190       "flags: [ flat_namespace ]\n"
191       "install-name: /System/Library/Frameworks/A.framework/A\n"
192       "current-version: 1.2.3\n"
193       "compatibility-version: 1.2\n"
194       "swift-abi-version: 5\n"
195       "exports:\n"
196       "  - targets: [ i386-macos ]\n"
197       "    symbols: [ _symA ]\n"
198       "    objc-classes: []\n"
199       "    objc-eh-types: []\n"
200       "    objc-ivars: []\n"
201       "    weak-symbols: []\n"
202       "    thread-local-symbols: []\n"
203       "  - targets: [ x86_64-macos ]\n"
204       "    symbols: [_symAB]\n"
205       "reexports:\n"
206       "  - targets: [ i386-macos ]\n"
207       "    symbols: [_symC]\n"
208       "    objc-classes: []\n"
209       "    objc-eh-types: []\n"
210       "    objc-ivars: []\n"
211       "    weak-symbols: []\n"
212       "    thread-local-symbols: []\n"
213       "undefineds:\n"
214       "  - targets: [ i386-macos ]\n"
215       "    symbols: [ _symD ]\n"
216       "    objc-classes: []\n"
217       "    objc-eh-types: []\n"
218       "    objc-ivars: []\n"
219       "    weak-symbols: []\n"
220       "    thread-local-symbols: []\n"
221       "...\n";
222
223   PlatformSet Platforms;
224   Platforms.insert(PlatformKind::macOS);
225   Platforms.insert(PlatformKind::macCatalyst);
226   ArchitectureSet Archs = AK_i386 | AK_x86_64;
227   TargetList Targets;
228   for (auto &&Arch : Archs)
229     for (auto &&Platform : Platforms)
230       Targets.emplace_back(Target(Arch, Platform));
231   UUIDs Uuids = {
232       {Targets[0], "00000000-0000-0000-0000-000000000000"},
233       {Targets[1], "00000000-0000-0000-0000-000000000002"},
234       {Targets[2], "11111111-1111-1111-1111-111111111111"},
235       {Targets[3], "11111111-1111-1111-1111-111111111112"},
236   };
237
238   Expected<TBDFile> Result =
239       TextAPIReader::get(MemoryBufferRef(TBDv4Inlines, "Test.tbd"));
240   EXPECT_TRUE(!!Result);
241   TBDFile File = std::move(Result.get());
242   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
243   EXPECT_EQ(Archs, File->getArchitectures());
244   EXPECT_EQ(Uuids, File->uuids());
245   EXPECT_EQ(Platforms, File->getPlatforms());
246   EXPECT_EQ(
247       std::string("/System/Library/Frameworks/Umbrella.framework/Umbrella"),
248       File->getInstallName());
249   EXPECT_TRUE(File->isTwoLevelNamespace());
250   EXPECT_TRUE(File->isApplicationExtensionSafe());
251   EXPECT_FALSE(File->isInstallAPI());
252   EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion());
253   EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
254   InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A",
255                             {Targets[0], Targets[2]});
256   EXPECT_EQ(1U, File->reexportedLibraries().size());
257   EXPECT_EQ(reexport, File->reexportedLibraries().front());
258   ExportedSymbolSeq Exports;
259   for (const auto *Sym : File->symbols()) {
260     EXPECT_FALSE(Sym->isWeakReferenced());
261     EXPECT_FALSE(Sym->isUndefined());
262     Exports.emplace_back(ExportedSymbol{Sym->getKind(), Sym->getName().str(),
263                                         Sym->isWeakDefined(),
264                                         Sym->isThreadLocalValue()});
265   }
266   EXPECT_EQ(0U, Exports.size());
267
268   // Check Inlined Document
269   Exports.clear();
270   Targets.clear();
271   Uuids.clear();
272   PlatformKind Platform = PlatformKind::macOS;
273   for (auto &&Arch : Archs)
274     Targets.emplace_back(Target(Arch, Platform));
275   Uuids = {
276       {Targets[0], "20000000-0000-0000-0000-000000000000"},
277       {Targets[1], "21111111-1111-1111-1111-111111111111"},
278   };
279
280   auto Document = File->documents().front();
281   EXPECT_EQ(FileType::TBD_V4, Document->getFileType());
282   EXPECT_EQ(Archs, Document->getArchitectures());
283   EXPECT_EQ(Uuids, Document->uuids());
284   EXPECT_EQ(1U, Document->getPlatforms().size());
285   EXPECT_EQ(Platform, *(Document->getPlatforms().begin()));
286   EXPECT_EQ(std::string("/System/Library/Frameworks/A.framework/A"),
287             Document->getInstallName());
288   EXPECT_EQ(PackedVersion(1, 2, 3), Document->getCurrentVersion());
289   EXPECT_EQ(PackedVersion(1, 2, 0), Document->getCompatibilityVersion());
290   EXPECT_EQ(5U, Document->getSwiftABIVersion());
291   EXPECT_FALSE(Document->isTwoLevelNamespace());
292   EXPECT_TRUE(Document->isApplicationExtensionSafe());
293   EXPECT_FALSE(Document->isInstallAPI());
294
295   ExportedSymbolSeq Reexports, Undefineds;
296   for (const auto *Sym : Document->symbols()) {
297     ExportedSymbol Temp =
298         ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
299                        Sym->isWeakDefined(), Sym->isThreadLocalValue()};
300     EXPECT_FALSE(Sym->isWeakReferenced());
301     if (Sym->isUndefined())
302       Undefineds.emplace_back(std::move(Temp));
303     else
304       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
305                           : Exports.emplace_back(std::move(Temp));
306   }
307   llvm::sort(Exports.begin(), Exports.end());
308   llvm::sort(Reexports.begin(), Reexports.end());
309   llvm::sort(Undefineds.begin(), Undefineds.end());
310
311   static ExportedSymbol ExpectedExportedSymbols[] = {
312       {SymbolKind::GlobalSymbol, "_symA", false, false},
313       {SymbolKind::GlobalSymbol, "_symAB", false, false},
314   };
315
316   static ExportedSymbol ExpectedReexportedSymbols[] = {
317       {SymbolKind::GlobalSymbol, "_symC", false, false},
318   };
319
320   static ExportedSymbol ExpectedUndefinedSymbols[] = {
321       {SymbolKind::GlobalSymbol, "_symD", false, false},
322   };
323
324   EXPECT_EQ(sizeof(ExpectedExportedSymbols) / sizeof(ExportedSymbol),
325             Exports.size());
326   EXPECT_EQ(sizeof(ExpectedReexportedSymbols) / sizeof(ExportedSymbol),
327             Reexports.size());
328   EXPECT_EQ(sizeof(ExpectedUndefinedSymbols) / sizeof(ExportedSymbol),
329             Undefineds.size());
330   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
331                          std::begin(ExpectedExportedSymbols)));
332   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
333                          std::begin(ExpectedReexportedSymbols)));
334   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
335                          std::begin(ExpectedUndefinedSymbols)));
336 }
337
338 TEST(TBDv4, WriteFile) {
339   static const char TBDv4File[] =
340       "--- !tapi-tbd\n"
341       "tbd-version:     4\n"
342       "targets:         [ i386-macos, x86_64-ios-simulator ]\n"
343       "uuids:\n"
344       "  - target:          i386-macos\n"
345       "    value:           00000000-0000-0000-0000-000000000000\n"
346       "  - target:          x86_64-ios-simulator\n"
347       "    value:           11111111-1111-1111-1111-111111111111\n"
348       "flags:           [ installapi ]\n"
349       "install-name:    'Umbrella.framework/Umbrella'\n"
350       "current-version: 1.2.3\n"
351       "compatibility-version: 0\n"
352       "swift-abi-version: 5\n"
353       "parent-umbrella:\n"
354       "  - targets:         [ i386-macos, x86_64-ios-simulator ]\n"
355       "    umbrella:        System\n"
356       "allowable-clients:\n"
357       "  - targets:         [ i386-macos ]\n"
358       "    clients:         [ ClientA ]\n"
359       "exports:\n"
360       "  - targets:         [ i386-macos ]\n"
361       "    symbols:         [ _symA ]\n"
362       "    objc-classes:    [ Class1 ]\n"
363       "    weak-symbols:    [ _symC ]\n"
364       "  - targets:         [ x86_64-ios-simulator ]\n"
365       "    symbols:         [ _symB ]\n"
366       "...\n";
367
368   InterfaceFile File;
369   TargetList Targets = {
370       Target(AK_i386, PlatformKind::macOS),
371       Target(AK_x86_64, PlatformKind::iOSSimulator),
372   };
373   UUIDs uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"},
374                  {Targets[1], "11111111-1111-1111-1111-111111111111"}};
375   File.setInstallName("Umbrella.framework/Umbrella");
376   File.setFileType(FileType::TBD_V4);
377   File.addTargets(Targets);
378   File.addUUID(uuids[0].first, uuids[0].second);
379   File.addUUID(uuids[1].first, uuids[1].second);
380   File.setCurrentVersion(PackedVersion(1, 2, 3));
381   File.setTwoLevelNamespace();
382   File.setInstallAPI(true);
383   File.setApplicationExtensionSafe(true);
384   File.setSwiftABIVersion(5);
385   File.addAllowableClient("ClientA", Targets[0]);
386   File.addParentUmbrella(Targets[0], "System");
387   File.addParentUmbrella(Targets[1], "System");
388   File.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[0]});
389   File.addSymbol(SymbolKind::GlobalSymbol, "_symB", {Targets[1]});
390   File.addSymbol(SymbolKind::GlobalSymbol, "_symC", {Targets[0]},
391                  SymbolFlags::WeakDefined);
392   File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[0]});
393
394   SmallString<4096> Buffer;
395   raw_svector_ostream OS(Buffer);
396   Error Result = TextAPIWriter::writeToStream(OS, File);
397   EXPECT_FALSE(Result);
398   EXPECT_STREQ(TBDv4File, Buffer.c_str());
399 }
400
401 TEST(TBDv4, WriteMultipleDocuments) {
402   static const char TBDv4Inlines[] =
403       "--- !tapi-tbd\n"
404       "tbd-version:     4\n"
405       "targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n"
406       "uuids:\n"
407       "  - target:          i386-maccatalyst\n"
408       "    value:           00000000-0000-0000-0000-000000000002\n"
409       "  - target:          x86_64-maccatalyst\n"
410       "    value:           11111111-1111-1111-1111-111111111112\n"
411       "install-name:    "
412       "'/System/Library/Frameworks/Umbrella.framework/Umbrella'\n"
413       "reexported-libraries:\n"
414       "  - targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n"
415       "    libraries:       [ '/System/Library/Frameworks/A.framework/A' ]\n"
416       "--- !tapi-tbd\n"
417       "tbd-version:     4\n"
418       "targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n"
419       "uuids:\n"
420       "  - target:          i386-maccatalyst\n"
421       "    value:           00000000-0000-0000-0000-000000000000\n"
422       "  - target:          x86_64-maccatalyst\n"
423       "    value:           11111111-1111-1111-1111-111111111111\n"
424       "install-name:    '/System/Library/Frameworks/A.framework/A'\n"
425       "exports:\n"
426       "  - targets:         [ i386-maccatalyst ]\n"
427       "    weak-symbols:    [ _symC ]\n"
428       "  - targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n"
429       "    symbols:         [ _symA ]\n"
430       "    objc-classes:    [ Class1 ]\n"
431       "  - targets:         [ x86_64-maccatalyst ]\n"
432       "    symbols:         [ _symAB ]\n"
433       "...\n";
434
435   InterfaceFile File;
436   PlatformKind Platform = PlatformKind::macCatalyst;
437   TargetList Targets = {
438       Target(AK_i386, Platform),
439       Target(AK_x86_64, Platform),
440   };
441   UUIDs Uuids = {{Targets[0], "00000000-0000-0000-0000-000000000002"},
442                  {Targets[1], "11111111-1111-1111-1111-111111111112"}};
443   File.setInstallName("/System/Library/Frameworks/Umbrella.framework/Umbrella");
444   File.setFileType(FileType::TBD_V4);
445   File.addTargets(Targets);
446   File.addUUID(Uuids[0].first, Uuids[0].second);
447   File.addUUID(Uuids[1].first, Uuids[1].second);
448   File.setCompatibilityVersion(PackedVersion(1, 0, 0));
449   File.setCurrentVersion(PackedVersion(1, 0, 0));
450   File.setTwoLevelNamespace();
451   File.setApplicationExtensionSafe(true);
452   File.addReexportedLibrary("/System/Library/Frameworks/A.framework/A",
453                             Targets[0]);
454   File.addReexportedLibrary("/System/Library/Frameworks/A.framework/A",
455                             Targets[1]);
456
457   // Write Second Document
458   Uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"},
459            {Targets[1], "11111111-1111-1111-1111-111111111111"}};
460   InterfaceFile Document;
461   Document.setInstallName("/System/Library/Frameworks/A.framework/A");
462   Document.setFileType(FileType::TBD_V4);
463   Document.addTargets(Targets);
464   Document.addUUID(Uuids[0].first, Uuids[0].second);
465   Document.addUUID(Uuids[1].first, Uuids[1].second);
466   Document.setCompatibilityVersion(PackedVersion(1, 0, 0));
467   Document.setCurrentVersion(PackedVersion(1, 0, 0));
468   Document.setTwoLevelNamespace();
469   Document.setApplicationExtensionSafe(true);
470   Document.addSymbol(SymbolKind::GlobalSymbol, "_symA", Targets);
471   Document.addSymbol(SymbolKind::GlobalSymbol, "_symAB", {Targets[1]});
472   Document.addSymbol(SymbolKind::GlobalSymbol, "_symC", {Targets[0]},
473                      SymbolFlags::WeakDefined);
474   Document.addSymbol(SymbolKind::ObjectiveCClass, "Class1", Targets);
475   File.addDocument(std::make_shared<InterfaceFile>(std::move(Document)));
476
477   SmallString<4096> Buffer;
478   raw_svector_ostream OS(Buffer);
479   Error Result = TextAPIWriter::writeToStream(OS, File);
480   EXPECT_FALSE(Result);
481   EXPECT_STREQ(TBDv4Inlines, Buffer.c_str());
482 }
483
484 TEST(TBDv4, MultipleTargets) {
485   static const char TBDv4MultipleTargets[] =
486       "--- !tapi-tbd\n"
487       "tbd-version: 4\n"
488       "targets: [ i386-maccatalyst, x86_64-tvos, arm64-ios ]\n"
489       "install-name: Test.dylib\n"
490       "...\n";
491
492   Expected<TBDFile> Result =
493       TextAPIReader::get(MemoryBufferRef(TBDv4MultipleTargets, "Test.tbd"));
494   EXPECT_TRUE(!!Result);
495   PlatformSet Platforms;
496   Platforms.insert(PlatformKind::macCatalyst);
497   Platforms.insert(PlatformKind::tvOS);
498   Platforms.insert(PlatformKind::iOS);
499   TBDFile File = std::move(Result.get());
500   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
501   EXPECT_EQ(AK_x86_64 | AK_arm64 | AK_i386, File->getArchitectures());
502   EXPECT_EQ(Platforms.size(), File->getPlatforms().size());
503   for (auto Platform : File->getPlatforms())
504     EXPECT_EQ(Platforms.count(Platform), 1U);
505
506   SmallString<4096> Buffer;
507   raw_svector_ostream OS(Buffer);
508   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
509   EXPECT_TRUE(!WriteResult);
510   EXPECT_EQ(stripWhitespace(TBDv4MultipleTargets),
511             stripWhitespace(Buffer.c_str()));
512 }
513
514 TEST(TBDv4, MultipleTargetsSameArch) {
515   static const char TBDv4TargetsSameArch[] =
516       "--- !tapi-tbd\n"
517       "tbd-version: 4\n"
518       "targets: [ x86_64-tvos , x86_64-maccatalyst ]\n"
519       "install-name: Test.dylib\n"
520       "...\n";
521
522   Expected<TBDFile> Result =
523       TextAPIReader::get(MemoryBufferRef(TBDv4TargetsSameArch, "Test.tbd"));
524   EXPECT_TRUE(!!Result);
525   PlatformSet Platforms;
526   Platforms.insert(PlatformKind::tvOS);
527   Platforms.insert(PlatformKind::macCatalyst);
528   TBDFile File = std::move(Result.get());
529   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
530   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
531   EXPECT_EQ(Platforms.size(), File->getPlatforms().size());
532   for (auto Platform : File->getPlatforms())
533     EXPECT_EQ(Platforms.count(Platform), 1U);
534
535   SmallString<4096> Buffer;
536   raw_svector_ostream OS(Buffer);
537   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
538   EXPECT_TRUE(!WriteResult);
539   EXPECT_EQ(stripWhitespace(TBDv4TargetsSameArch),
540             stripWhitespace(Buffer.c_str()));
541 }
542
543 TEST(TBDv4, MultipleTargetsSamePlatform) {
544   static const char TBDv4MultipleTargetsSamePlatform[] =
545       "--- !tapi-tbd\n"
546       "tbd-version: 4\n"
547       "targets: [ armv7k-ios , arm64-ios]\n"
548       "install-name: Test.dylib\n"
549       "...\n";
550
551   Expected<TBDFile> Result = TextAPIReader::get(
552       MemoryBufferRef(TBDv4MultipleTargetsSamePlatform, "Test.tbd"));
553   EXPECT_TRUE(!!Result);
554   TBDFile File = std::move(Result.get());
555   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
556   EXPECT_EQ(AK_arm64 | AK_armv7k, File->getArchitectures());
557   EXPECT_EQ(File->getPlatforms().size(), 1U);
558   EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin());
559
560   SmallString<4096> Buffer;
561   raw_svector_ostream OS(Buffer);
562   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
563   EXPECT_TRUE(!WriteResult);
564   EXPECT_EQ(stripWhitespace(TBDv4MultipleTargetsSamePlatform),
565             stripWhitespace(Buffer.c_str()));
566 }
567
568 TEST(TBDv4, Target_maccatalyst) {
569   static const char TBDv4TargetMacCatalyst[] =
570       "--- !tapi-tbd\n"
571       "tbd-version: 4\n"
572       "targets: [  x86_64-maccatalyst ]\n"
573       "install-name: Test.dylib\n"
574       "...\n";
575
576   Expected<TBDFile> Result =
577       TextAPIReader::get(MemoryBufferRef(TBDv4TargetMacCatalyst, "Test.tbd"));
578   EXPECT_TRUE(!!Result);
579   TBDFile File = std::move(Result.get());
580   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
581   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
582   EXPECT_EQ(File->getPlatforms().size(), 1U);
583   EXPECT_EQ(PlatformKind::macCatalyst, *File->getPlatforms().begin());
584
585   SmallString<4096> Buffer;
586   raw_svector_ostream OS(Buffer);
587   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
588   EXPECT_TRUE(!WriteResult);
589   EXPECT_EQ(stripWhitespace(TBDv4TargetMacCatalyst),
590             stripWhitespace(Buffer.c_str()));
591 }
592
593 TEST(TBDv4, Target_x86_ios) {
594   static const char TBDv4Targetx86iOS[] = "--- !tapi-tbd\n"
595                                           "tbd-version: 4\n"
596                                           "targets: [  x86_64-ios ]\n"
597                                           "install-name: Test.dylib\n"
598                                           "...\n";
599
600   Expected<TBDFile> Result =
601       TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86iOS, "Test.tbd"));
602   EXPECT_TRUE(!!Result);
603   TBDFile File = std::move(Result.get());
604   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
605   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
606   EXPECT_EQ(File->getPlatforms().size(), 1U);
607   EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin());
608
609   SmallString<4096> Buffer;
610   raw_svector_ostream OS(Buffer);
611   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
612   EXPECT_TRUE(!WriteResult);
613   EXPECT_EQ(stripWhitespace(TBDv4Targetx86iOS),
614             stripWhitespace(Buffer.c_str()));
615 }
616
617 TEST(TBDv4, Target_arm_bridgeOS) {
618   static const char TBDv4PlatformBridgeOS[] = "--- !tapi-tbd\n"
619                                               "tbd-version: 4\n"
620                                               "targets: [  armv7k-bridgeos ]\n"
621                                               "install-name: Test.dylib\n"
622                                               "...\n";
623
624   Expected<TBDFile> Result =
625       TextAPIReader::get(MemoryBufferRef(TBDv4PlatformBridgeOS, "Test.tbd"));
626   EXPECT_TRUE(!!Result);
627   TBDFile File = std::move(Result.get());
628   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
629   EXPECT_EQ(File->getPlatforms().size(), 1U);
630   EXPECT_EQ(PlatformKind::bridgeOS, *File->getPlatforms().begin());
631   EXPECT_EQ(ArchitectureSet(AK_armv7k), File->getArchitectures());
632
633   SmallString<4096> Buffer;
634   raw_svector_ostream OS(Buffer);
635   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
636   EXPECT_TRUE(!WriteResult);
637   EXPECT_EQ(stripWhitespace(TBDv4PlatformBridgeOS),
638             stripWhitespace(Buffer.c_str()));
639 }
640
641 TEST(TBDv4, Target_arm_iOS) {
642   static const char TBDv4ArchArm64e[] = "--- !tapi-tbd\n"
643                                         "tbd-version: 4\n"
644                                         "targets: [  arm64e-ios ]\n"
645                                         "install-name: Test.dylib\n"
646                                         "...\n";
647
648   Expected<TBDFile> Result =
649       TextAPIReader::get(MemoryBufferRef(TBDv4ArchArm64e, "Test.tbd"));
650   EXPECT_TRUE(!!Result);
651   TBDFile File = std::move(Result.get());
652   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
653   EXPECT_EQ(File->getPlatforms().size(), 1U);
654   EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin());
655   EXPECT_EQ(ArchitectureSet(AK_arm64e), File->getArchitectures());
656
657   SmallString<4096> Buffer;
658   raw_svector_ostream OS(Buffer);
659   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
660   EXPECT_TRUE(!WriteResult);
661   EXPECT_EQ(stripWhitespace(TBDv4ArchArm64e), stripWhitespace(Buffer.c_str()));
662 }
663
664 TEST(TBDv4, Target_x86_macos) {
665   static const char TBDv4Targetx86MacOS[] = "--- !tapi-tbd\n"
666                                             "tbd-version: 4\n"
667                                             "targets: [  x86_64-macos ]\n"
668                                             "install-name: Test.dylib\n"
669                                             "...\n";
670
671   Expected<TBDFile> Result =
672       TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86MacOS, "Test.tbd"));
673   EXPECT_TRUE(!!Result);
674   TBDFile File = std::move(Result.get());
675   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
676   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
677   EXPECT_EQ(File->getPlatforms().size(), 1U);
678   EXPECT_EQ(PlatformKind::macOS, *File->getPlatforms().begin());
679
680   SmallString<4096> Buffer;
681   raw_svector_ostream OS(Buffer);
682   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
683   EXPECT_TRUE(!WriteResult);
684   EXPECT_EQ(stripWhitespace(TBDv4Targetx86MacOS),
685             stripWhitespace(Buffer.c_str()));
686 }
687
688 TEST(TBDv4, Target_x86_ios_simulator) {
689   static const char TBDv4Targetx86iOSSim[] =
690       "--- !tapi-tbd\n"
691       "tbd-version: 4\n"
692       "targets: [  x86_64-ios-simulator  ]\n"
693       "install-name: Test.dylib\n"
694       "...\n";
695
696   Expected<TBDFile> Result =
697       TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86iOSSim, "Test.tbd"));
698   EXPECT_TRUE(!!Result);
699   TBDFile File = std::move(Result.get());
700   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
701   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
702   EXPECT_EQ(File->getPlatforms().size(), 1U);
703   EXPECT_EQ(PlatformKind::iOSSimulator, *File->getPlatforms().begin());
704
705   SmallString<4096> Buffer;
706   raw_svector_ostream OS(Buffer);
707   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
708   EXPECT_TRUE(!WriteResult);
709   EXPECT_EQ(stripWhitespace(TBDv4Targetx86iOSSim),
710             stripWhitespace(Buffer.c_str()));
711 }
712
713 TEST(TBDv4, Target_x86_tvos_simulator) {
714   static const char TBDv4x86tvOSSim[] = "--- !tapi-tbd\n"
715                                         "tbd-version: 4\n"
716                                         "targets: [  x86_64-tvos-simulator  ]\n"
717                                         "install-name: Test.dylib\n"
718                                         "...\n";
719
720   Expected<TBDFile> Result =
721       TextAPIReader::get(MemoryBufferRef(TBDv4x86tvOSSim, "Test.tbd"));
722   EXPECT_TRUE(!!Result);
723   TBDFile File = std::move(Result.get());
724   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
725   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
726   EXPECT_EQ(File->getPlatforms().size(), 1U);
727   EXPECT_EQ(PlatformKind::tvOSSimulator, *File->getPlatforms().begin());
728
729   SmallString<4096> Buffer;
730   raw_svector_ostream OS(Buffer);
731   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
732   EXPECT_TRUE(!WriteResult);
733   EXPECT_EQ(stripWhitespace(TBDv4x86tvOSSim), stripWhitespace(Buffer.c_str()));
734 }
735
736 TEST(TBDv4, Target_i386_watchos_simulator) {
737   static const char TBDv4i386watchOSSim[] =
738       "--- !tapi-tbd\n"
739       "tbd-version: 4\n"
740       "targets: [  i386-watchos-simulator  ]\n"
741       "install-name: Test.dylib\n"
742       "...\n";
743
744   Expected<TBDFile> Result =
745       TextAPIReader::get(MemoryBufferRef(TBDv4i386watchOSSim, "Test.tbd"));
746   EXPECT_TRUE(!!Result);
747   TBDFile File = std::move(Result.get());
748   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
749   EXPECT_EQ(ArchitectureSet(AK_i386), File->getArchitectures());
750   EXPECT_EQ(File->getPlatforms().size(), 1U);
751   EXPECT_EQ(PlatformKind::watchOSSimulator, *File->getPlatforms().begin());
752
753   SmallString<4096> Buffer;
754   raw_svector_ostream OS(Buffer);
755   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
756   EXPECT_TRUE(!WriteResult);
757   EXPECT_EQ(stripWhitespace(TBDv4i386watchOSSim),
758             stripWhitespace(Buffer.c_str()));
759 }
760
761 TEST(TBDv4, Swift_1) {
762   static const char TBDv4SwiftVersion1[] = "--- !tapi-tbd\n"
763                                            "tbd-version: 4\n"
764                                            "targets: [  x86_64-macos ]\n"
765                                            "install-name: Test.dylib\n"
766                                            "swift-abi-version: 1\n"
767                                            "...\n";
768
769   Expected<TBDFile> Result =
770       TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion1, "Test.tbd"));
771   EXPECT_TRUE(!!Result);
772   TBDFile File = std::move(Result.get());
773   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
774   EXPECT_EQ(1U, File->getSwiftABIVersion());
775
776   // No writer test because we emit "swift-abi-version:1.0".
777 }
778
779 TEST(TBDv4, Swift_2) {
780   static const char TBDv4Swift2[] = "--- !tapi-tbd\n"
781                                     "tbd-version: 4\n"
782                                     "targets: [  x86_64-macos ]\n"
783                                     "install-name: Test.dylib\n"
784                                     "swift-abi-version: 2\n"
785                                     "...\n";
786
787   Expected<TBDFile> Result =
788       TextAPIReader::get(MemoryBufferRef(TBDv4Swift2, "Test.tbd"));
789   EXPECT_TRUE(!!Result);
790   TBDFile File = std::move(Result.get());
791   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
792   EXPECT_EQ(2U, File->getSwiftABIVersion());
793
794   // No writer test because we emit "swift-abi-version:2.0".
795 }
796
797 TEST(TBDv4, Swift_5) {
798   static const char TBDv4SwiftVersion5[] = "--- !tapi-tbd\n"
799                                            "tbd-version: 4\n"
800                                            "targets: [  x86_64-macos ]\n"
801                                            "install-name: Test.dylib\n"
802                                            "swift-abi-version: 5\n"
803                                            "...\n";
804
805   Expected<TBDFile> Result =
806       TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion5, "Test.tbd"));
807   EXPECT_TRUE(!!Result);
808   TBDFile File = std::move(Result.get());
809   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
810   EXPECT_EQ(5U, File->getSwiftABIVersion());
811
812   SmallString<4096> Buffer;
813   raw_svector_ostream OS(Buffer);
814   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
815   EXPECT_TRUE(!WriteResult);
816   EXPECT_EQ(stripWhitespace(TBDv4SwiftVersion5),
817             stripWhitespace(Buffer.c_str()));
818 }
819
820 TEST(TBDv4, Swift_99) {
821   static const char TBDv4SwiftVersion99[] = "--- !tapi-tbd\n"
822                                             "tbd-version: 4\n"
823                                             "targets: [  x86_64-macos ]\n"
824                                             "install-name: Test.dylib\n"
825                                             "swift-abi-version: 99\n"
826                                             "...\n";
827
828   Expected<TBDFile> Result =
829       TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion99, "Test.tbd"));
830   EXPECT_TRUE(!!Result);
831   TBDFile File = std::move(Result.get());
832   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
833   EXPECT_EQ(99U, File->getSwiftABIVersion());
834
835   SmallString<4096> Buffer;
836   raw_svector_ostream OS(Buffer);
837   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
838   EXPECT_TRUE(!WriteResult);
839   EXPECT_EQ(stripWhitespace(TBDv4SwiftVersion99),
840             stripWhitespace(Buffer.c_str()));
841 }
842
843 TEST(TBDv4, InvalidArchitecture) {
844   static const char TBDv4UnknownArch[] = "--- !tapi-tbd\n"
845                                          "tbd-version: 4\n"
846                                          "targets: [ foo-macos ]\n"
847                                          "install-name: Test.dylib\n"
848                                          "...\n";
849
850   Expected<TBDFile> Result =
851       TextAPIReader::get(MemoryBufferRef(TBDv4UnknownArch, "Test.tbd"));
852   EXPECT_FALSE(!!Result);
853   std::string ErrorMessage = toString(Result.takeError());
854   EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown "
855             "architecture\ntargets: [ foo-macos ]\n"
856             "           ^~~~~~~~~~\n",
857             ErrorMessage);
858 }
859
860 TEST(TBDv4, InvalidPlatform) {
861   static const char TBDv4FInvalidPlatform[] = "--- !tapi-tbd\n"
862                                               "tbd-version: 4\n"
863                                               "targets: [ x86_64-maos ]\n"
864                                               "install-name: Test.dylib\n"
865                                               "...\n";
866
867   Expected<TBDFile> Result =
868       TextAPIReader::get(MemoryBufferRef(TBDv4FInvalidPlatform, "Test.tbd"));
869   EXPECT_FALSE(!!Result);
870   std::string ErrorMessage = toString(Result.takeError());
871   EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown platform\ntargets: "
872             "[ x86_64-maos ]\n"
873             "           ^~~~~~~~~~~~\n",
874             ErrorMessage);
875 }
876
877 TEST(TBDv4, MalformedFile1) {
878   static const char TBDv4MalformedFile1[] = "--- !tapi-tbd\n"
879                                             "tbd-version: 4\n"
880                                             "...\n";
881
882   Expected<TBDFile> Result =
883       TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile1, "Test.tbd"));
884   EXPECT_FALSE(!!Result);
885   std::string ErrorMessage = toString(Result.takeError());
886   ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key "
887             "'targets'\ntbd-version: 4\n^\n",
888             ErrorMessage);
889 }
890
891 TEST(TBDv4, MalformedFile2) {
892   static const char TBDv4MalformedFile2[] = "--- !tapi-tbd\n"
893                                             "tbd-version: 4\n"
894                                             "targets: [ x86_64-macos ]\n"
895                                             "install-name: Test.dylib\n"
896                                             "foobar: \"unsupported key\"\n";
897
898   Expected<TBDFile> Result =
899       TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile2, "Test.tbd"));
900   EXPECT_FALSE(!!Result);
901   std::string ErrorMessage = toString(Result.takeError());
902   ASSERT_EQ(
903       "malformed file\nTest.tbd:5:9: error: unknown key 'foobar'\nfoobar: "
904       "\"unsupported key\"\n        ^~~~~~~~~~~~~~~~~\n",
905       ErrorMessage);
906 }
907
908 TEST(TBDv4, MalformedFile3) {
909   static const char TBDv4MalformedSwift[] = "--- !tapi-tbd\n"
910                                             "tbd-version: 4\n"
911                                             "targets: [  x86_64-macos ]\n"
912                                             "install-name: Test.dylib\n"
913                                             "swift-abi-version: 1.1\n"
914                                             "...\n";
915
916   Expected<TBDFile> Result =
917       TextAPIReader::get(MemoryBufferRef(TBDv4MalformedSwift, "Test.tbd"));
918   EXPECT_FALSE(!!Result);
919   std::string ErrorMessage = toString(Result.takeError());
920   EXPECT_EQ("malformed file\nTest.tbd:5:20: error: invalid Swift ABI "
921             "version.\nswift-abi-version: 1.1\n                   ^~~\n",
922             ErrorMessage);
923 }
924
925 } // end namespace TBDv4