xref: /llvm-project/llvm/unittests/TextAPI/TextStubV4Tests.cpp (revision d9a9872ec4760762fdc467ef283cea302a3742e5)
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/InterfaceFile.h"
11 #include "llvm/TextAPI/TextAPIReader.h"
12 #include "llvm/TextAPI/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 
TEST(TBDv4,ReadFile)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: [weakReexport]\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: [weakReference]\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(getPlatformFromName("macos"));
86   Platforms.insert(getPlatformFromName("ios"));
87   auto Archs = AK_i386 | AK_x86_64;
88   TargetList Targets = {
89       Target(AK_i386, PLATFORM_MACOS),
90       Target(AK_x86_64, PLATFORM_MACOS),
91       Target(AK_x86_64, PLATFORM_IOS),
92   };
93   EXPECT_EQ(Archs, File->getArchitectures());
94   EXPECT_EQ(Platforms.size(), File->getPlatforms().size());
95   for (auto Platform : File->getPlatforms())
96     EXPECT_EQ(Platforms.count(Platform), 1U);
97   EXPECT_EQ(std::string("Umbrella.framework/Umbrella"), File->getInstallName());
98   EXPECT_EQ(PackedVersion(1, 2, 3), File->getCurrentVersion());
99   EXPECT_EQ(PackedVersion(1, 2, 0), File->getCompatibilityVersion());
100   EXPECT_EQ(5U, File->getSwiftABIVersion());
101   EXPECT_FALSE(File->isTwoLevelNamespace());
102   EXPECT_TRUE(File->isApplicationExtensionSafe());
103   EXPECT_FALSE(File->isOSLibNotForSharedCache());
104   InterfaceFileRef client("ClientA", Targets);
105   InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A",
106                             {Targets[0]});
107   EXPECT_EQ(1U, File->allowableClients().size());
108   EXPECT_EQ(client, File->allowableClients().front());
109   EXPECT_EQ(1U, File->reexportedLibraries().size());
110   EXPECT_EQ(reexport, File->reexportedLibraries().front());
111 
112   ExportedSymbolSeq Exports, Reexports, Undefineds;
113   for (const auto *Sym : File->symbols()) {
114     ExportedSymbol Temp =
115         ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
116                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
117                        Sym->isThreadLocalValue()};
118     if (Sym->isUndefined()) {
119       EXPECT_FALSE(Sym->isWeakDefined());
120       Undefineds.emplace_back(std::move(Temp));
121     }
122     // Check that defined symbols cannot be set as weak referenced.
123     else if (Sym->isReexported()) {
124       EXPECT_FALSE(Sym->isWeakReferenced());
125       Reexports.emplace_back(std::move(Temp));
126     } else {
127       EXPECT_FALSE(Sym->isWeakReferenced());
128       Exports.emplace_back(std::move(Temp));
129     }
130   }
131   llvm::sort(Exports);
132   llvm::sort(Reexports);
133   llvm::sort(Undefineds);
134 
135   static ExportedSymbol ExpectedExportedSymbols[] = {
136       {EncodeKind::GlobalSymbol, "_symA", false, false},
137       {EncodeKind::GlobalSymbol, "_symAB", false, false},
138       {EncodeKind::GlobalSymbol, "_symB", false, false},
139   };
140 
141   static ExportedSymbol ExpectedReexportedSymbols[] = {
142       {EncodeKind::GlobalSymbol, "_symC", false, false},
143       {EncodeKind::GlobalSymbol, "weakReexport", true, false},
144   };
145 
146   static ExportedSymbol ExpectedUndefinedSymbols[] = {
147       {EncodeKind::GlobalSymbol, "_symD", false, false},
148       {EncodeKind::GlobalSymbol, "weakReference", true, false},
149   };
150 
151   EXPECT_EQ(std::size(ExpectedExportedSymbols), Exports.size());
152   EXPECT_EQ(std::size(ExpectedReexportedSymbols), Reexports.size());
153   EXPECT_EQ(std::size(ExpectedUndefinedSymbols), Undefineds.size());
154   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
155                          std::begin(ExpectedExportedSymbols)));
156   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
157                          std::begin(ExpectedReexportedSymbols)));
158   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
159                          std::begin(ExpectedUndefinedSymbols)));
160 }
161 
TEST(TBDv4,ReadMultipleDocuments)162 TEST(TBDv4, ReadMultipleDocuments) {
163   static const char TBDv4Inlines[] =
164       "--- !tapi-tbd\n"
165       "tbd-version: 4\n"
166       "targets: [ i386-macos, i386-maccatalyst, x86_64-macos, "
167       "x86_64-maccatalyst ]\n"
168       "install-name: /System/Library/Frameworks/Umbrella.framework/Umbrella\n"
169       "parent-umbrella:\n"
170       "  - targets: [ i386-macos, x86_64-macos ]\n"
171       "    umbrella: System\n"
172       "reexported-libraries:\n"
173       "  - targets: [ i386-macos, x86_64-macos ]\n"
174       "    libraries: [ /System/Library/Frameworks/A.framework/A ]\n"
175       "--- !tapi-tbd\n"
176       "tbd-version: 4\n"
177       "targets:  [ i386-macos, x86_64-macos ]\n"
178       "uuids:\n"
179       "  - target: i386-macos\n"
180       "    value: 20000000-0000-0000-0000-000000000000\n"
181       "  - target: x86_64-macos\n"
182       "    value: 21111111-1111-1111-1111-111111111111\n"
183       "flags: [ flat_namespace ]\n"
184       "install-name: /System/Library/Frameworks/A.framework/A\n"
185       "current-version: 1.2.3\n"
186       "compatibility-version: 1.2\n"
187       "swift-abi-version: 5\n"
188       "exports:\n"
189       "  - targets: [ i386-macos ]\n"
190       "    symbols: [ _symA ]\n"
191       "    objc-classes: []\n"
192       "    objc-eh-types: []\n"
193       "    objc-ivars: []\n"
194       "    weak-symbols: []\n"
195       "    thread-local-symbols: []\n"
196       "  - targets: [ x86_64-macos ]\n"
197       "    symbols: [_symAB]\n"
198       "reexports:\n"
199       "  - targets: [ i386-macos ]\n"
200       "    symbols: [_symC]\n"
201       "    objc-classes: []\n"
202       "    objc-eh-types: []\n"
203       "    objc-ivars: []\n"
204       "    weak-symbols: []\n"
205       "    thread-local-symbols: []\n"
206       "undefineds:\n"
207       "  - targets: [ i386-macos ]\n"
208       "    symbols: [ _symD ]\n"
209       "    objc-classes: []\n"
210       "    objc-eh-types: []\n"
211       "    objc-ivars: []\n"
212       "    weak-symbols: []\n"
213       "    thread-local-symbols: []\n"
214       "...\n";
215 
216   PlatformSet Platforms;
217   Platforms.insert(PLATFORM_MACOS);
218   Platforms.insert(PLATFORM_MACCATALYST);
219   ArchitectureSet Archs = AK_i386 | AK_x86_64;
220   TargetList Targets;
221   for (auto &&Arch : Archs)
222     for (auto &&Platform : Platforms)
223       Targets.emplace_back(Target(Arch, Platform));
224   TargetToAttr Uuids = {
225       {Targets[0], "00000000-0000-0000-0000-000000000000"},
226       {Targets[1], "00000000-0000-0000-0000-000000000002"},
227       {Targets[2], "11111111-1111-1111-1111-111111111111"},
228       {Targets[3], "11111111-1111-1111-1111-111111111112"},
229   };
230 
231   Expected<TBDFile> Result =
232       TextAPIReader::get(MemoryBufferRef(TBDv4Inlines, "Test.tbd"));
233   EXPECT_TRUE(!!Result);
234   TBDFile File = std::move(Result.get());
235   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
236   EXPECT_EQ(Archs, File->getArchitectures());
237   EXPECT_EQ(Platforms, File->getPlatforms());
238   EXPECT_EQ(
239       std::string("/System/Library/Frameworks/Umbrella.framework/Umbrella"),
240       File->getInstallName());
241   EXPECT_TRUE(File->isTwoLevelNamespace());
242   EXPECT_TRUE(File->isApplicationExtensionSafe());
243   EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion());
244   EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
245   InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A",
246                             {Targets[0], Targets[2]});
247   EXPECT_EQ(1U, File->reexportedLibraries().size());
248   EXPECT_EQ(reexport, File->reexportedLibraries().front());
249   EXPECT_TRUE(File->symbols().empty());
250 
251   // Check Inlined Document
252   Targets.clear();
253   Uuids.clear();
254   PlatformType Platform = PLATFORM_MACOS;
255   for (auto &&Arch : Archs)
256     Targets.emplace_back(Target(Arch, Platform));
257   Uuids = {
258       {Targets[0], "20000000-0000-0000-0000-000000000000"},
259       {Targets[1], "21111111-1111-1111-1111-111111111111"},
260   };
261 
262   TBDReexportFile Document = File->documents().front();
263   EXPECT_EQ(FileType::TBD_V4, Document->getFileType());
264   EXPECT_EQ(Archs, Document->getArchitectures());
265   EXPECT_EQ(1U, Document->getPlatforms().size());
266   EXPECT_EQ(Platform, *(Document->getPlatforms().begin()));
267   EXPECT_EQ(std::string("/System/Library/Frameworks/A.framework/A"),
268             Document->getInstallName());
269   EXPECT_EQ(PackedVersion(1, 2, 3), Document->getCurrentVersion());
270   EXPECT_EQ(PackedVersion(1, 2, 0), Document->getCompatibilityVersion());
271   EXPECT_EQ(5U, Document->getSwiftABIVersion());
272   EXPECT_FALSE(Document->isTwoLevelNamespace());
273   EXPECT_TRUE(Document->isApplicationExtensionSafe());
274 
275   ExportedSymbolSeq Exports;
276   ExportedSymbolSeq Reexports, Undefineds;
277   for (const auto *Sym : Document->symbols()) {
278     ExportedSymbol Temp =
279         ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
280                        Sym->isWeakDefined(), Sym->isThreadLocalValue()};
281     EXPECT_FALSE(Sym->isWeakReferenced());
282     if (Sym->isUndefined())
283       Undefineds.emplace_back(std::move(Temp));
284     else
285       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
286                           : Exports.emplace_back(std::move(Temp));
287   }
288   llvm::sort(Exports);
289   llvm::sort(Reexports);
290   llvm::sort(Undefineds);
291 
292   static ExportedSymbol ExpectedExportedSymbols[] = {
293       {EncodeKind::GlobalSymbol, "_symA", false, false},
294       {EncodeKind::GlobalSymbol, "_symAB", false, false},
295   };
296 
297   static ExportedSymbol ExpectedReexportedSymbols[] = {
298       {EncodeKind::GlobalSymbol, "_symC", false, false},
299   };
300 
301   static ExportedSymbol ExpectedUndefinedSymbols[] = {
302       {EncodeKind::GlobalSymbol, "_symD", false, false},
303   };
304 
305   EXPECT_EQ(std::size(ExpectedExportedSymbols), Exports.size());
306   EXPECT_EQ(std::size(ExpectedReexportedSymbols), Reexports.size());
307   EXPECT_EQ(std::size(ExpectedUndefinedSymbols), Undefineds.size());
308   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
309                          std::begin(ExpectedExportedSymbols)));
310   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
311                          std::begin(ExpectedReexportedSymbols)));
312   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
313                          std::begin(ExpectedUndefinedSymbols)));
314 }
315 
TEST(TBDv4,WriteFile)316 TEST(TBDv4, WriteFile) {
317   static const char TBDv4File[] =
318       "--- !tapi-tbd\n"
319       "tbd-version:     4\n"
320       "targets:         [ i386-macos, x86_64-ios-simulator ]\n"
321       "install-name:    'Umbrella.framework/Umbrella'\n"
322       "current-version: 1.2.3\n"
323       "compatibility-version: 0\n"
324       "swift-abi-version: 5\n"
325       "parent-umbrella:\n"
326       "  - targets:         [ i386-macos, x86_64-ios-simulator ]\n"
327       "    umbrella:        System\n"
328       "allowable-clients:\n"
329       "  - targets:         [ i386-macos ]\n"
330       "    clients:         [ ClientA ]\n"
331       "exports:\n"
332       "  - targets:         [ i386-macos ]\n"
333       "    symbols:         [ _symA ]\n"
334       "    objc-classes:    [ Class1 ]\n"
335       "    weak-symbols:    [ _symC ]\n"
336       "  - targets:         [ x86_64-ios-simulator ]\n"
337       "    symbols:         [ _symB ]\n"
338       "...\n";
339 
340   InterfaceFile File;
341   TargetList Targets = {
342       Target(AK_i386, PLATFORM_MACOS),
343       Target(AK_x86_64, PLATFORM_IOSSIMULATOR),
344   };
345   File.setInstallName("Umbrella.framework/Umbrella");
346   File.setFileType(FileType::TBD_V4);
347   File.addTargets(Targets);
348   File.setCurrentVersion(PackedVersion(1, 2, 3));
349   File.setTwoLevelNamespace();
350   File.setApplicationExtensionSafe(true);
351   File.setSwiftABIVersion(5);
352   File.addAllowableClient("ClientA", Targets[0]);
353   File.addParentUmbrella(Targets[0], "System");
354   File.addParentUmbrella(Targets[1], "System");
355   File.addSymbol(EncodeKind::GlobalSymbol, "_symA", {Targets[0]});
356   File.addSymbol(EncodeKind::GlobalSymbol, "_symB", {Targets[1]});
357   File.addSymbol(EncodeKind::GlobalSymbol, "_symC", {Targets[0]},
358                  SymbolFlags::WeakDefined);
359   File.addSymbol(EncodeKind::ObjectiveCClass, "Class1", {Targets[0]});
360 
361   SmallString<4096> Buffer;
362   raw_svector_ostream OS(Buffer);
363   Error Result = TextAPIWriter::writeToStream(OS, File);
364   EXPECT_FALSE(Result);
365   EXPECT_STREQ(TBDv4File, Buffer.c_str());
366 }
367 
TEST(TBDv4,WriteMultipleDocuments)368 TEST(TBDv4, WriteMultipleDocuments) {
369   static const char TBDv4Inlines[] =
370       "--- !tapi-tbd\n"
371       "tbd-version:     4\n"
372       "targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n"
373       "install-name:    "
374       "'/System/Library/Frameworks/Umbrella.framework/Umbrella'\n"
375       "reexported-libraries:\n"
376       "  - targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n"
377       "    libraries:       [ '/System/Library/Frameworks/A.framework/A' ]\n"
378       "--- !tapi-tbd\n"
379       "tbd-version:     4\n"
380       "targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n"
381       "install-name:    '/System/Library/Frameworks/A.framework/A'\n"
382       "exports:\n"
383       "  - targets:         [ i386-maccatalyst ]\n"
384       "    weak-symbols:    [ _symC ]\n"
385       "  - targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n"
386       "    symbols:         [ _symA ]\n"
387       "    objc-classes:    [ Class1 ]\n"
388       "  - targets:         [ x86_64-maccatalyst ]\n"
389       "    symbols:         [ _symAB ]\n"
390       "...\n";
391 
392   InterfaceFile File;
393   PlatformType Platform = PLATFORM_MACCATALYST;
394   TargetList Targets = {
395       Target(AK_i386, Platform),
396       Target(AK_x86_64, Platform),
397   };
398   TargetToAttr Uuids = {{Targets[0], "00000000-0000-0000-0000-000000000002"},
399                         {Targets[1], "11111111-1111-1111-1111-111111111112"}};
400   File.setInstallName("/System/Library/Frameworks/Umbrella.framework/Umbrella");
401   File.setFileType(FileType::TBD_V4);
402   File.addTargets(Targets);
403   File.setCompatibilityVersion(PackedVersion(1, 0, 0));
404   File.setCurrentVersion(PackedVersion(1, 0, 0));
405   File.setTwoLevelNamespace();
406   File.setApplicationExtensionSafe(true);
407   File.addReexportedLibrary("/System/Library/Frameworks/A.framework/A",
408                             Targets[0]);
409   File.addReexportedLibrary("/System/Library/Frameworks/A.framework/A",
410                             Targets[1]);
411 
412   // Write Second Document
413   Uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"},
414            {Targets[1], "11111111-1111-1111-1111-111111111111"}};
415   InterfaceFile Document;
416   Document.setInstallName("/System/Library/Frameworks/A.framework/A");
417   Document.setFileType(FileType::TBD_V4);
418   Document.addTargets(Targets);
419   Document.setCompatibilityVersion(PackedVersion(1, 0, 0));
420   Document.setCurrentVersion(PackedVersion(1, 0, 0));
421   Document.setTwoLevelNamespace();
422   Document.setApplicationExtensionSafe(true);
423   Document.addSymbol(EncodeKind::GlobalSymbol, "_symA", Targets);
424   Document.addSymbol(EncodeKind::GlobalSymbol, "_symAB", {Targets[1]});
425   Document.addSymbol(EncodeKind::GlobalSymbol, "_symC", {Targets[0]},
426                      SymbolFlags::WeakDefined);
427   Document.addSymbol(EncodeKind::ObjectiveCClass, "Class1", Targets);
428   File.addDocument(std::make_shared<InterfaceFile>(std::move(Document)));
429 
430   SmallString<4096> Buffer;
431   raw_svector_ostream OS(Buffer);
432   Error Result = TextAPIWriter::writeToStream(OS, File);
433   EXPECT_FALSE(Result);
434   EXPECT_STREQ(TBDv4Inlines, Buffer.c_str());
435 }
436 
TEST(TBDv4,MultipleTargets)437 TEST(TBDv4, MultipleTargets) {
438   static const char TBDv4MultipleTargets[] =
439       "--- !tapi-tbd\n"
440       "tbd-version: 4\n"
441       "targets: [ i386-maccatalyst, x86_64-tvos, arm64-ios ]\n"
442       "install-name: Test.dylib\n"
443       "...\n";
444 
445   Expected<TBDFile> Result =
446       TextAPIReader::get(MemoryBufferRef(TBDv4MultipleTargets, "Test.tbd"));
447   EXPECT_TRUE(!!Result);
448   PlatformSet Platforms;
449   Platforms.insert(PLATFORM_MACCATALYST);
450   Platforms.insert(PLATFORM_TVOS);
451   Platforms.insert(PLATFORM_IOS);
452   TBDFile File = std::move(Result.get());
453   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
454   EXPECT_EQ(AK_x86_64 | AK_arm64 | AK_i386, File->getArchitectures());
455   EXPECT_EQ(Platforms.size(), File->getPlatforms().size());
456   for (auto Platform : File->getPlatforms())
457     EXPECT_EQ(Platforms.count(Platform), 1U);
458 
459   SmallString<4096> Buffer;
460   raw_svector_ostream OS(Buffer);
461   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
462   EXPECT_TRUE(!WriteResult);
463   EXPECT_EQ(stripWhitespace(TBDv4MultipleTargets),
464             stripWhitespace(Buffer.c_str()));
465 }
466 
TEST(TBDv4,MultipleTargetsSameArch)467 TEST(TBDv4, MultipleTargetsSameArch) {
468   static const char TBDv4TargetsSameArch[] =
469       "--- !tapi-tbd\n"
470       "tbd-version: 4\n"
471       "targets: [ x86_64-tvos , x86_64-maccatalyst ]\n"
472       "install-name: Test.dylib\n"
473       "...\n";
474 
475   Expected<TBDFile> Result =
476       TextAPIReader::get(MemoryBufferRef(TBDv4TargetsSameArch, "Test.tbd"));
477   EXPECT_TRUE(!!Result);
478   PlatformSet Platforms;
479   Platforms.insert(PLATFORM_TVOS);
480   Platforms.insert(PLATFORM_MACCATALYST);
481   TBDFile File = std::move(Result.get());
482   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
483   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
484   EXPECT_EQ(Platforms.size(), File->getPlatforms().size());
485   for (auto Platform : File->getPlatforms())
486     EXPECT_EQ(Platforms.count(Platform), 1U);
487 
488   SmallString<4096> Buffer;
489   raw_svector_ostream OS(Buffer);
490   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
491   EXPECT_TRUE(!WriteResult);
492   EXPECT_EQ(stripWhitespace(TBDv4TargetsSameArch),
493             stripWhitespace(Buffer.c_str()));
494 }
495 
TEST(TBDv4,MultipleTargetsSamePlatform)496 TEST(TBDv4, MultipleTargetsSamePlatform) {
497   static const char TBDv4MultipleTargetsSamePlatform[] =
498       "--- !tapi-tbd\n"
499       "tbd-version: 4\n"
500       "targets: [ armv7k-ios , arm64-ios]\n"
501       "install-name: Test.dylib\n"
502       "...\n";
503 
504   Expected<TBDFile> Result = TextAPIReader::get(
505       MemoryBufferRef(TBDv4MultipleTargetsSamePlatform, "Test.tbd"));
506   EXPECT_TRUE(!!Result);
507   TBDFile File = std::move(Result.get());
508   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
509   EXPECT_EQ(AK_arm64 | AK_armv7k, File->getArchitectures());
510   EXPECT_EQ(File->getPlatforms().size(), 1U);
511   EXPECT_EQ(PLATFORM_IOS, *File->getPlatforms().begin());
512 
513   SmallString<4096> Buffer;
514   raw_svector_ostream OS(Buffer);
515   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
516   EXPECT_TRUE(!WriteResult);
517   EXPECT_EQ(stripWhitespace(TBDv4MultipleTargetsSamePlatform),
518             stripWhitespace(Buffer.c_str()));
519 }
520 
TEST(TBDv4,Target_maccatalyst)521 TEST(TBDv4, Target_maccatalyst) {
522   static const char TBDv4TargetMacCatalyst[] =
523       "--- !tapi-tbd\n"
524       "tbd-version: 4\n"
525       "targets: [  x86_64-maccatalyst ]\n"
526       "install-name: Test.dylib\n"
527       "...\n";
528 
529   Expected<TBDFile> Result =
530       TextAPIReader::get(MemoryBufferRef(TBDv4TargetMacCatalyst, "Test.tbd"));
531   EXPECT_TRUE(!!Result);
532   TBDFile File = std::move(Result.get());
533   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
534   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
535   EXPECT_EQ(File->getPlatforms().size(), 1U);
536   EXPECT_EQ(PLATFORM_MACCATALYST, *File->getPlatforms().begin());
537 
538   SmallString<4096> Buffer;
539   raw_svector_ostream OS(Buffer);
540   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
541   EXPECT_TRUE(!WriteResult);
542   EXPECT_EQ(stripWhitespace(TBDv4TargetMacCatalyst),
543             stripWhitespace(Buffer.c_str()));
544 }
545 
TEST(TBDv4,Target_maccatalyst2)546 TEST(TBDv4, Target_maccatalyst2) {
547   static const char TBDv4TargetMacCatalyst[] =
548       "--- !tapi-tbd\n"
549       "tbd-version: 4\n"
550       "targets: [  x86_64-maccatalyst ]\n"
551       "install-name: Test.dylib\n"
552       "...\n";
553 
554   Expected<TBDFile> Result =
555       TextAPIReader::get(MemoryBufferRef(TBDv4TargetMacCatalyst, "Test.tbd"));
556   EXPECT_TRUE(!!Result);
557   TBDFile File = std::move(Result.get());
558   EXPECT_EQ(File->getPlatforms().size(), 1U);
559   EXPECT_EQ(getPlatformFromName("ios-macabi"), *File->getPlatforms().begin());
560 }
561 
TEST(TBDv4,Target_x86_ios)562 TEST(TBDv4, Target_x86_ios) {
563   static const char TBDv4Targetx86iOS[] = "--- !tapi-tbd\n"
564                                           "tbd-version: 4\n"
565                                           "targets: [  x86_64-ios ]\n"
566                                           "install-name: Test.dylib\n"
567                                           "...\n";
568 
569   Expected<TBDFile> Result =
570       TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86iOS, "Test.tbd"));
571   EXPECT_TRUE(!!Result);
572   TBDFile File = std::move(Result.get());
573   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
574   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
575   EXPECT_EQ(File->getPlatforms().size(), 1U);
576   EXPECT_EQ(PLATFORM_IOS, *File->getPlatforms().begin());
577 
578   SmallString<4096> Buffer;
579   raw_svector_ostream OS(Buffer);
580   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
581   EXPECT_TRUE(!WriteResult);
582   EXPECT_EQ(stripWhitespace(TBDv4Targetx86iOS),
583             stripWhitespace(Buffer.c_str()));
584 }
585 
TEST(TBDv4,Target_arm_bridgeOS)586 TEST(TBDv4, Target_arm_bridgeOS) {
587   static const char TBDv4PlatformBridgeOS[] = "--- !tapi-tbd\n"
588                                               "tbd-version: 4\n"
589                                               "targets: [  armv7k-bridgeos ]\n"
590                                               "install-name: Test.dylib\n"
591                                               "...\n";
592 
593   Expected<TBDFile> Result =
594       TextAPIReader::get(MemoryBufferRef(TBDv4PlatformBridgeOS, "Test.tbd"));
595   EXPECT_TRUE(!!Result);
596   TBDFile File = std::move(Result.get());
597   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
598   EXPECT_EQ(File->getPlatforms().size(), 1U);
599   EXPECT_EQ(PLATFORM_BRIDGEOS, *File->getPlatforms().begin());
600   EXPECT_EQ(ArchitectureSet(AK_armv7k), File->getArchitectures());
601 
602   SmallString<4096> Buffer;
603   raw_svector_ostream OS(Buffer);
604   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
605   EXPECT_TRUE(!WriteResult);
606   EXPECT_EQ(stripWhitespace(TBDv4PlatformBridgeOS),
607             stripWhitespace(Buffer.c_str()));
608 }
609 
TEST(TBDv4,Target_arm_iOS)610 TEST(TBDv4, Target_arm_iOS) {
611   static const char TBDv4ArchArm64e[] = "--- !tapi-tbd\n"
612                                         "tbd-version: 4\n"
613                                         "targets: [  arm64e-ios ]\n"
614                                         "install-name: Test.dylib\n"
615                                         "...\n";
616 
617   Expected<TBDFile> Result =
618       TextAPIReader::get(MemoryBufferRef(TBDv4ArchArm64e, "Test.tbd"));
619   EXPECT_TRUE(!!Result);
620   TBDFile File = std::move(Result.get());
621   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
622   EXPECT_EQ(File->getPlatforms().size(), 1U);
623   EXPECT_EQ(PLATFORM_IOS, *File->getPlatforms().begin());
624   EXPECT_EQ(ArchitectureSet(AK_arm64e), File->getArchitectures());
625 
626   SmallString<4096> Buffer;
627   raw_svector_ostream OS(Buffer);
628   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
629   EXPECT_TRUE(!WriteResult);
630   EXPECT_EQ(stripWhitespace(TBDv4ArchArm64e), stripWhitespace(Buffer.c_str()));
631 }
632 
TEST(TBDv4,Target_x86_macos)633 TEST(TBDv4, Target_x86_macos) {
634   static const char TBDv4Targetx86MacOS[] = "--- !tapi-tbd\n"
635                                             "tbd-version: 4\n"
636                                             "targets: [  x86_64-macos ]\n"
637                                             "install-name: Test.dylib\n"
638                                             "...\n";
639 
640   Expected<TBDFile> Result =
641       TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86MacOS, "Test.tbd"));
642   EXPECT_TRUE(!!Result);
643   TBDFile File = std::move(Result.get());
644   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
645   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
646   EXPECT_EQ(File->getPlatforms().size(), 1U);
647   EXPECT_EQ(PLATFORM_MACOS, *File->getPlatforms().begin());
648 
649   SmallString<4096> Buffer;
650   raw_svector_ostream OS(Buffer);
651   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
652   EXPECT_TRUE(!WriteResult);
653   EXPECT_EQ(stripWhitespace(TBDv4Targetx86MacOS),
654             stripWhitespace(Buffer.c_str()));
655 }
656 
TEST(TBDv4,Target_x86_ios_simulator)657 TEST(TBDv4, Target_x86_ios_simulator) {
658   static const char TBDv4Targetx86iOSSim[] =
659       "--- !tapi-tbd\n"
660       "tbd-version: 4\n"
661       "targets: [  x86_64-ios-simulator  ]\n"
662       "install-name: Test.dylib\n"
663       "...\n";
664 
665   Expected<TBDFile> Result =
666       TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86iOSSim, "Test.tbd"));
667   EXPECT_TRUE(!!Result);
668   TBDFile File = std::move(Result.get());
669   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
670   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
671   EXPECT_EQ(File->getPlatforms().size(), 1U);
672   EXPECT_EQ(PLATFORM_IOSSIMULATOR, *File->getPlatforms().begin());
673 
674   SmallString<4096> Buffer;
675   raw_svector_ostream OS(Buffer);
676   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
677   EXPECT_TRUE(!WriteResult);
678   EXPECT_EQ(stripWhitespace(TBDv4Targetx86iOSSim),
679             stripWhitespace(Buffer.c_str()));
680 }
681 
TEST(TBDv4,Target_x86_tvos_simulator)682 TEST(TBDv4, Target_x86_tvos_simulator) {
683   static const char TBDv4x86tvOSSim[] = "--- !tapi-tbd\n"
684                                         "tbd-version: 4\n"
685                                         "targets: [  x86_64-tvos-simulator  ]\n"
686                                         "install-name: Test.dylib\n"
687                                         "...\n";
688 
689   Expected<TBDFile> Result =
690       TextAPIReader::get(MemoryBufferRef(TBDv4x86tvOSSim, "Test.tbd"));
691   EXPECT_TRUE(!!Result);
692   TBDFile File = std::move(Result.get());
693   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
694   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
695   EXPECT_EQ(File->getPlatforms().size(), 1U);
696   EXPECT_EQ(PLATFORM_TVOSSIMULATOR, *File->getPlatforms().begin());
697 
698   SmallString<4096> Buffer;
699   raw_svector_ostream OS(Buffer);
700   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
701   EXPECT_TRUE(!WriteResult);
702   EXPECT_EQ(stripWhitespace(TBDv4x86tvOSSim), stripWhitespace(Buffer.c_str()));
703 }
704 
TEST(TBDv4,Target_i386_watchos_simulator)705 TEST(TBDv4, Target_i386_watchos_simulator) {
706   static const char TBDv4i386watchOSSim[] =
707       "--- !tapi-tbd\n"
708       "tbd-version: 4\n"
709       "targets: [  i386-watchos-simulator  ]\n"
710       "install-name: Test.dylib\n"
711       "...\n";
712 
713   Expected<TBDFile> Result =
714       TextAPIReader::get(MemoryBufferRef(TBDv4i386watchOSSim, "Test.tbd"));
715   EXPECT_TRUE(!!Result);
716   TBDFile File = std::move(Result.get());
717   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
718   EXPECT_EQ(ArchitectureSet(AK_i386), File->getArchitectures());
719   EXPECT_EQ(File->getPlatforms().size(), 1U);
720   EXPECT_EQ(PLATFORM_WATCHOSSIMULATOR, *File->getPlatforms().begin());
721 
722   SmallString<4096> Buffer;
723   raw_svector_ostream OS(Buffer);
724   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
725   EXPECT_TRUE(!WriteResult);
726   EXPECT_EQ(stripWhitespace(TBDv4i386watchOSSim),
727             stripWhitespace(Buffer.c_str()));
728 }
729 
TEST(TBDv4,Target_i386_driverkit)730 TEST(TBDv4, Target_i386_driverkit) {
731   static const char TBDv4i386DriverKit[] = "--- !tapi-tbd\n"
732                                            "tbd-version: 4\n"
733                                            "targets: [  i386-driverkit  ]\n"
734                                            "install-name: Test.dylib\n"
735                                            "...\n";
736 
737   Expected<TBDFile> Result =
738       TextAPIReader::get(MemoryBufferRef(TBDv4i386DriverKit, "Test.tbd"));
739   EXPECT_TRUE(!!Result);
740   TBDFile File = std::move(Result.get());
741   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
742   EXPECT_EQ(ArchitectureSet(AK_i386), File->getArchitectures());
743   EXPECT_EQ(File->getPlatforms().size(), 1U);
744   EXPECT_EQ(PLATFORM_DRIVERKIT, *File->getPlatforms().begin());
745 
746   SmallString<4096> Buffer;
747   raw_svector_ostream OS(Buffer);
748   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
749   EXPECT_TRUE(!WriteResult);
750   EXPECT_EQ(stripWhitespace(TBDv4i386DriverKit),
751             stripWhitespace(Buffer.c_str()));
752 }
753 
TEST(TBDv4,Target_arm64_xros)754 TEST(TBDv4, Target_arm64_xros) {
755   static const char TBDv4ArchArm64e[] =
756       "--- !tapi-tbd\n"
757       "tbd-version: 4\n"
758       "targets: [ arm64e-xros, arm64e-xros-simulator ]\n"
759       "install-name: Test.dylib\n"
760       "...\n";
761 
762   auto Result =
763       TextAPIReader::get(MemoryBufferRef(TBDv4ArchArm64e, "Test.tbd"));
764   EXPECT_TRUE(!!Result);
765   auto File = std::move(Result.get());
766   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
767   PlatformSet ExpectedSet;
768   ExpectedSet.insert(PLATFORM_XROS);
769   ExpectedSet.insert(PLATFORM_XROS_SIMULATOR);
770   EXPECT_EQ(File->getPlatforms().size(), 2U);
771   for (auto Platform : File->getPlatforms())
772     EXPECT_EQ(ExpectedSet.count(Platform), 1U);
773 
774   EXPECT_EQ(ArchitectureSet(AK_arm64e), File->getArchitectures());
775 
776   SmallString<4096> Buffer;
777   raw_svector_ostream OS(Buffer);
778   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
779   EXPECT_TRUE(!WriteResult);
780   EXPECT_EQ(stripWhitespace(TBDv4ArchArm64e), stripWhitespace(Buffer.c_str()));
781 }
782 
TEST(TBDv4,Swift_1)783 TEST(TBDv4, Swift_1) {
784   static const char TBDv4SwiftVersion1[] = "--- !tapi-tbd\n"
785                                            "tbd-version: 4\n"
786                                            "targets: [  x86_64-macos ]\n"
787                                            "install-name: Test.dylib\n"
788                                            "swift-abi-version: 1\n"
789                                            "...\n";
790 
791   Expected<TBDFile> Result =
792       TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion1, "Test.tbd"));
793   EXPECT_TRUE(!!Result);
794   TBDFile File = std::move(Result.get());
795   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
796   EXPECT_EQ(1U, File->getSwiftABIVersion());
797 
798   // No writer test because we emit "swift-abi-version:1.0".
799 }
800 
TEST(TBDv4,Swift_2)801 TEST(TBDv4, Swift_2) {
802   static const char TBDv4Swift2[] = "--- !tapi-tbd\n"
803                                     "tbd-version: 4\n"
804                                     "targets: [  x86_64-macos ]\n"
805                                     "install-name: Test.dylib\n"
806                                     "swift-abi-version: 2\n"
807                                     "...\n";
808 
809   Expected<TBDFile> Result =
810       TextAPIReader::get(MemoryBufferRef(TBDv4Swift2, "Test.tbd"));
811   EXPECT_TRUE(!!Result);
812   TBDFile File = std::move(Result.get());
813   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
814   EXPECT_EQ(2U, File->getSwiftABIVersion());
815 
816   // No writer test because we emit "swift-abi-version:2.0".
817 }
818 
TEST(TBDv4,Swift_5)819 TEST(TBDv4, Swift_5) {
820   static const char TBDv4SwiftVersion5[] = "--- !tapi-tbd\n"
821                                            "tbd-version: 4\n"
822                                            "targets: [  x86_64-macos ]\n"
823                                            "install-name: Test.dylib\n"
824                                            "swift-abi-version: 5\n"
825                                            "...\n";
826 
827   Expected<TBDFile> Result =
828       TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion5, "Test.tbd"));
829   EXPECT_TRUE(!!Result);
830   TBDFile File = std::move(Result.get());
831   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
832   EXPECT_EQ(5U, File->getSwiftABIVersion());
833 
834   SmallString<4096> Buffer;
835   raw_svector_ostream OS(Buffer);
836   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
837   EXPECT_TRUE(!WriteResult);
838   EXPECT_EQ(stripWhitespace(TBDv4SwiftVersion5),
839             stripWhitespace(Buffer.c_str()));
840 }
841 
TEST(TBDv4,Swift_99)842 TEST(TBDv4, Swift_99) {
843   static const char TBDv4SwiftVersion99[] = "--- !tapi-tbd\n"
844                                             "tbd-version: 4\n"
845                                             "targets: [  x86_64-macos ]\n"
846                                             "install-name: Test.dylib\n"
847                                             "swift-abi-version: 99\n"
848                                             "...\n";
849 
850   Expected<TBDFile> Result =
851       TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion99, "Test.tbd"));
852   EXPECT_TRUE(!!Result);
853   TBDFile File = std::move(Result.get());
854   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
855   EXPECT_EQ(99U, File->getSwiftABIVersion());
856 
857   SmallString<4096> Buffer;
858   raw_svector_ostream OS(Buffer);
859   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
860   EXPECT_TRUE(!WriteResult);
861   EXPECT_EQ(stripWhitespace(TBDv4SwiftVersion99),
862             stripWhitespace(Buffer.c_str()));
863 }
864 
TEST(TBDv4,NotForSharedCache)865 TEST(TBDv4, NotForSharedCache) {
866 
867   static const char TBDv4NotForSharedCache[] =
868       "--- !tapi-tbd\n"
869       "tbd-version: 4\n"
870       "targets: [  arm64-macos ]\n"
871       "flags: [ not_for_dyld_shared_cache ]\n"
872       "install-name: /S/L/F/Foo.framework/Foo\n"
873       "...\n";
874 
875   Expected<TBDFile> Result =
876       TextAPIReader::get(MemoryBufferRef(TBDv4NotForSharedCache, "Test.tbd"));
877   EXPECT_TRUE(!!Result);
878   Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS);
879   TBDFile ReadFile = std::move(Result.get());
880   EXPECT_EQ(FileType::TBD_V4, ReadFile->getFileType());
881   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
882             ReadFile->getInstallName());
883   EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end());
884   EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget);
885   EXPECT_TRUE(ReadFile->isOSLibNotForSharedCache());
886 }
887 
TEST(TBDv4,InvalidArchitecture)888 TEST(TBDv4, InvalidArchitecture) {
889   static const char TBDv4UnknownArch[] = "--- !tapi-tbd\n"
890                                          "tbd-version: 4\n"
891                                          "targets: [ foo-macos ]\n"
892                                          "install-name: Test.dylib\n"
893                                          "...\n";
894 
895   Expected<TBDFile> Result =
896       TextAPIReader::get(MemoryBufferRef(TBDv4UnknownArch, "Test.tbd"));
897   EXPECT_FALSE(!!Result);
898   std::string ErrorMessage = toString(Result.takeError());
899   EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown "
900             "architecture\ntargets: [ foo-macos ]\n"
901             "           ^~~~~~~~~~\n",
902             ErrorMessage);
903 }
904 
TEST(TBDv4,InvalidPlatform)905 TEST(TBDv4, InvalidPlatform) {
906   static const char TBDv4FInvalidPlatform[] = "--- !tapi-tbd\n"
907                                               "tbd-version: 4\n"
908                                               "targets: [ x86_64-maos ]\n"
909                                               "install-name: Test.dylib\n"
910                                               "...\n";
911 
912   Expected<TBDFile> Result =
913       TextAPIReader::get(MemoryBufferRef(TBDv4FInvalidPlatform, "Test.tbd"));
914   EXPECT_FALSE(!!Result);
915   std::string ErrorMessage = toString(Result.takeError());
916   EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown platform\ntargets: "
917             "[ x86_64-maos ]\n"
918             "           ^~~~~~~~~~~~\n",
919             ErrorMessage);
920 }
921 
TEST(TBDv4,MalformedFile1)922 TEST(TBDv4, MalformedFile1) {
923   static const char TBDv4MalformedFile1[] = "--- !tapi-tbd\n"
924                                             "tbd-version: 4\n"
925                                             "...\n";
926 
927   Expected<TBDFile> Result =
928       TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile1, "Test.tbd"));
929   EXPECT_FALSE(!!Result);
930   std::string ErrorMessage = toString(Result.takeError());
931   ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key "
932             "'targets'\ntbd-version: 4\n^\n",
933             ErrorMessage);
934 }
935 
TEST(TBDv4,MalformedFile2)936 TEST(TBDv4, MalformedFile2) {
937   static const char TBDv4MalformedFile2[] = "--- !tapi-tbd\n"
938                                             "tbd-version: 4\n"
939                                             "targets: [ x86_64-macos ]\n"
940                                             "install-name: Test.dylib\n"
941                                             "foobar: \"unsupported key\"\n"
942                                             "...\n";
943 
944   Expected<TBDFile> Result =
945       TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile2, "Test.tbd"));
946   EXPECT_FALSE(!!Result);
947   std::string ErrorMessage = toString(Result.takeError());
948   ASSERT_EQ(
949       "malformed file\nTest.tbd:5:1: error: unknown key 'foobar'\nfoobar: "
950       "\"unsupported key\"\n^~~~~~\n",
951       ErrorMessage);
952 }
953 
TEST(TBDv4,MalformedFile3)954 TEST(TBDv4, MalformedFile3) {
955   static const char TBDv4MalformedSwift[] = "--- !tapi-tbd\n"
956                                             "tbd-version: 4\n"
957                                             "targets: [  x86_64-macos ]\n"
958                                             "install-name: Test.dylib\n"
959                                             "swift-abi-version: 1.1\n"
960                                             "...\n";
961 
962   Expected<TBDFile> Result =
963       TextAPIReader::get(MemoryBufferRef(TBDv4MalformedSwift, "Test.tbd"));
964   EXPECT_FALSE(!!Result);
965   std::string ErrorMessage = toString(Result.takeError());
966   EXPECT_EQ("malformed file\nTest.tbd:5:20: error: invalid Swift ABI "
967             "version.\nswift-abi-version: 1.1\n                   ^~~\n",
968             ErrorMessage);
969 }
970 
TEST(TBDv4,InterfaceEquality)971 TEST(TBDv4, InterfaceEquality) {
972   static const char TBDv4File[] =
973       "--- !tapi-tbd\n"
974       "tbd-version: 4\n"
975       "targets:  [ i386-macos, x86_64-macos, x86_64-ios, i386-maccatalyst, "
976       "x86_64-maccatalyst ]\n"
977       "install-name: Umbrella.framework/Umbrella\n"
978       "current-version: 1.2.3\n"
979       "compatibility-version: 1.2\n"
980       "swift-abi-version: 5\n"
981       "parent-umbrella:\n"
982       "  - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n"
983       "    umbrella: System\n"
984       "allowable-clients:\n"
985       "  - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n"
986       "    clients: [ ClientA ]\n"
987       "reexported-libraries:\n"
988       "  - targets: [ i386-macos ]\n"
989       "    libraries: [ /System/Library/Frameworks/A.framework/A ]\n"
990       "exports:\n"
991       "  - targets: [ i386-macos ]\n"
992       "    symbols: [ _symA ]\n"
993       "    objc-classes: []\n"
994       "    objc-eh-types: []\n"
995       "    objc-ivars: []\n"
996       "    weak-symbols: []\n"
997       "    thread-local-symbols: []\n"
998       "  - targets: [ x86_64-ios ]\n"
999       "    symbols: [_symB]\n"
1000       "  - targets: [ x86_64-macos, x86_64-ios ]\n"
1001       "    symbols: [_symAB]\n"
1002       "  - targets: [ i386-maccatalyst ]\n"
1003       "    weak-symbols: [ _symC ]\n"
1004       "  - targets: [ i386-maccatalyst, x86_64-maccatalyst ]\n"
1005       "    symbols: [ _symA ]\n"
1006       "    objc-classes: [ Class1 ]\n"
1007       "  - targets: [ x86_64-maccatalyst ]\n"
1008       "    symbols: [ _symAB ]\n"
1009       "reexports:\n"
1010       "  - targets: [ i386-macos ]\n"
1011       "    symbols: [_symC]\n"
1012       "    objc-classes: []\n"
1013       "    objc-eh-types: []\n"
1014       "    objc-ivars: []\n"
1015       "    weak-symbols: []\n"
1016       "    thread-local-symbols: []\n"
1017       "undefineds:\n"
1018       "  - targets: [ i386-macos ]\n"
1019       "    symbols: [ _symD ]\n"
1020       "    objc-classes: []\n"
1021       "    objc-eh-types: []\n"
1022       "    objc-ivars: []\n"
1023       "    weak-symbols: []\n"
1024       "    thread-local-symbols: []\n"
1025       "...\n";
1026 
1027   Expected<TBDFile> ResultA =
1028       TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd"));
1029   EXPECT_TRUE(!!ResultA);
1030   InterfaceFile FileA = std::move(*ResultA.get());
1031   Expected<TBDFile> ResultB =
1032       TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd"));
1033   EXPECT_TRUE(!!ResultB);
1034   InterfaceFile FileB = std::move(*ResultB.get());
1035   EXPECT_TRUE(FileA == FileB);
1036 }
1037 
TEST(TBDv4,InterfaceDiffVersionsEquality)1038 TEST(TBDv4, InterfaceDiffVersionsEquality) {
1039   static const char TBDv4File[] =
1040       "--- !tapi-tbd\n"
1041       "tbd-version: 4\n"
1042       "targets:  [ i386-macos, x86_64-macos ]\n"
1043       "install-name: Umbrella.framework/Umbrella\n"
1044       "current-version: 1.2.3\n"
1045       "compatibility-version: 1.0\n"
1046       "swift-abi-version: 5\n"
1047       "parent-umbrella:\n"
1048       "  - targets: [ i386-macos, x86_64-macos ]\n"
1049       "    umbrella: System\n"
1050       "allowable-clients:\n"
1051       "  - targets: [ i386-macos, x86_64-macos ]\n"
1052       "    clients: [ ClientA ]\n"
1053       "reexported-libraries:\n"
1054       "  - targets: [ i386-macos ]\n"
1055       "    libraries: [ /System/Library/Frameworks/A.framework/A ]\n"
1056       "exports:\n"
1057       "  - targets: [ i386-macos ]\n"
1058       "    symbols: [ _sym5 ]\n"
1059       "    objc-classes: [ class3]\n"
1060       "    objc-eh-types: []\n"
1061       "    objc-ivars: [ class1._ivar3 ]\n"
1062       "    weak-symbols: [ _weak3 ]\n"
1063       "  - targets: [ x86_64-macos ]\n"
1064       "    symbols: [_symAB]\n"
1065       "  - targets: [ i386-macos, x86_64-macos ]\n"
1066       "    symbols: [_symA]\n"
1067       "    objc-classes: [ class1, class2 ]\n"
1068       "    objc-eh-types: [ class1 ]\n"
1069       "    objc-ivars: [ class1._ivar1, class1._ivar2 ]\n"
1070       "    weak-symbols: [ _weak1, _weak2 ]\n"
1071       "    thread-local-symbols: [ _tlv1, _tlv3 ]\n"
1072       "undefineds:\n"
1073       "  - targets: [ i386-macos ]\n"
1074       "    symbols: [ _symC ]\n"
1075       "    objc-classes: []\n"
1076       "    objc-eh-types: []\n"
1077       "    objc-ivars: []\n"
1078       "    weak-symbols: []\n"
1079       "    thread-local-symbols: []\n"
1080       "...\n";
1081 
1082   static const char TBDv3File[] =
1083       "--- !tapi-tbd-v3\n"
1084       "archs: [ i386, x86_64 ]\n"
1085       "platform: macosx\n"
1086       "install-name: Umbrella.framework/Umbrella\n"
1087       "current-version: 1.2.3\n"
1088       "compatibility-version: 1.0\n"
1089       "swift-abi-version: 5\n"
1090       "parent-umbrella: System\n"
1091       "exports:\n"
1092       "  - archs: [ i386, x86_64 ]\n"
1093       "    allowable-clients: [ ClientA ]\n"
1094       "    symbols: [ _symA ]\n"
1095       "    objc-classes: [ class1, class2 ]\n"
1096       "    objc-eh-types: [ class1 ]\n"
1097       "    objc-ivars: [ class1._ivar1, class1._ivar2 ]\n"
1098       "    weak-def-symbols: [ _weak1, _weak2 ]\n"
1099       "    thread-local-symbols: [ _tlv1, _tlv3 ]\n"
1100       "  - archs: [ i386 ]\n"
1101       "    re-exports: [ /System/Library/Frameworks/A.framework/A ]\n"
1102       "    symbols: [ _sym5 ]\n"
1103       "    objc-classes: [ class3 ]\n"
1104       "    objc-ivars: [ class1._ivar3 ]\n"
1105       "    weak-def-symbols: [ _weak3 ]\n"
1106       "  - archs: [ x86_64 ]\n"
1107       "    symbols: [ _symAB ]\n"
1108       "undefineds:\n"
1109       "  - archs: [ i386 ]\n"
1110       "    symbols: [ _symC ]\n"
1111       "...\n";
1112 
1113   Expected<TBDFile> ResultA =
1114       TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd"));
1115   EXPECT_TRUE(!!ResultA);
1116   InterfaceFile FileA = std::move(*ResultA.get());
1117   Expected<TBDFile> ResultB =
1118       TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd"));
1119   EXPECT_TRUE(!!ResultB);
1120   InterfaceFile FileB = std::move(*ResultB.get());
1121   EXPECT_TRUE(FileA == FileB);
1122 }
1123 
TEST(TBDv4,InterfaceInequality)1124 TEST(TBDv4, InterfaceInequality) {
1125   static const char TBDv4File[] = "--- !tapi-tbd\n"
1126                                   "tbd-version: 4\n"
1127                                   "targets:  [ i386-macos, x86_64-macos ]\n"
1128                                   "install-name: Umbrella.framework/Umbrella\n"
1129                                   "...\n";
1130 
1131   Expected<TBDFile> ResultA =
1132       TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd"));
1133   EXPECT_TRUE(!!ResultA);
1134   InterfaceFile FileA = std::move(*ResultA.get());
1135   Expected<TBDFile> ResultB =
1136       TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd"));
1137   EXPECT_TRUE(!!ResultB);
1138   InterfaceFile FileB = std::move(*ResultB.get());
1139 
1140   EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) {
1141     File->addTarget(Target(AK_x86_64, PLATFORM_IOS));
1142   }));
1143   EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) {
1144     File->setCurrentVersion(PackedVersion(1, 2, 3));
1145     File->setCompatibilityVersion(PackedVersion(1, 0, 0));
1146   }));
1147   EXPECT_TRUE(checkEqualityOnTransform(
1148       FileA, FileB, [](InterfaceFile *File) { File->setSwiftABIVersion(5); }));
1149   EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) {
1150     File->setTwoLevelNamespace(false);
1151   }));
1152   EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) {
1153     File->setApplicationExtensionSafe(false);
1154   }));
1155   EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) {
1156     File->addParentUmbrella(Target(AK_x86_64, PLATFORM_MACOS), "System.dylib");
1157   }));
1158   EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) {
1159     File->addAllowableClient("ClientA", Target(AK_i386, PLATFORM_MACOS));
1160   }));
1161   EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) {
1162     File->addReexportedLibrary("/System/Library/Frameworks/A.framework/A",
1163                                Target(AK_i386, PLATFORM_MACOS));
1164   }));
1165   EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) {
1166     File->addSymbol(EncodeKind::GlobalSymbol, "_symA",
1167                     {Target(AK_x86_64, PLATFORM_MACOS)});
1168   }));
1169   EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) {
1170     InterfaceFile Document;
1171     Document.setFileType(FileType::TBD_V4);
1172     Document.addTargets(TargetList{Target(AK_i386, PLATFORM_MACOS),
1173                                    Target(AK_x86_64, PLATFORM_MACOS)});
1174     Document.setInstallName("/System/Library/Frameworks/A.framework/A");
1175     File->addDocument(std::make_shared<InterfaceFile>(std::move(Document)));
1176   }));
1177 }
1178 
1179 } // end namespace TBDv4
1180