xref: /llvm-project/llvm/unittests/TextAPI/TextStubV4Tests.cpp (revision d26e0bcfba6ca4f9946ec712b8815d386dfec9c5)
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 static ExportedSymbol TBDv4ExportedSymbols[] = {
21     {SymbolKind::GlobalSymbol, "_symA", false, false},
22     {SymbolKind::GlobalSymbol, "_symAB", false, false},
23     {SymbolKind::GlobalSymbol, "_symB", false, false},
24 };
25 
26 static ExportedSymbol TBDv4ReexportedSymbols[] = {
27     {SymbolKind::GlobalSymbol, "_symC", false, false},
28 };
29 
30 static ExportedSymbol TBDv4UndefinedSymbols[] = {
31     {SymbolKind::GlobalSymbol, "_symD", false, false},
32 };
33 
34 namespace TBDv4 {
35 
36 TEST(TBDv4, ReadFile) {
37   static const char TBDv4File[] =
38       "--- !tapi-tbd\n"
39       "tbd-version: 4\n"
40       "targets:  [ i386-macos, x86_64-macos, x86_64-ios ]\n"
41       "uuids:\n"
42       "  - target: i386-macos\n"
43       "    value: 00000000-0000-0000-0000-000000000000\n"
44       "  - target: x86_64-macos\n"
45       "    value: 11111111-1111-1111-1111-111111111111\n"
46       "  - target: x86_64-ios\n"
47       "    value: 11111111-1111-1111-1111-111111111111\n"
48       "flags: [ flat_namespace, installapi ]\n"
49       "install-name: Umbrella.framework/Umbrella\n"
50       "current-version: 1.2.3\n"
51       "compatibility-version: 1.2\n"
52       "swift-abi-version: 5\n"
53       "parent-umbrella:\n"
54       "  - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n"
55       "    umbrella: System\n"
56       "allowable-clients:\n"
57       "  - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n"
58       "    clients: [ ClientA ]\n"
59       "reexported-libraries:\n"
60       "  - targets: [ i386-macos ]\n"
61       "    libraries: [ /System/Library/Frameworks/A.framework/A ]\n"
62       "exports:\n"
63       "  - targets: [ i386-macos ]\n"
64       "    symbols: [ _symA ]\n"
65       "    objc-classes: []\n"
66       "    objc-eh-types: []\n"
67       "    objc-ivars: []\n"
68       "    weak-symbols: []\n"
69       "    thread-local-symbols: []\n"
70       "  - targets: [ x86_64-ios ]\n"
71       "    symbols: [_symB]\n"
72       "  - targets: [ x86_64-macos, x86_64-ios ]\n"
73       "    symbols: [_symAB]\n"
74       "reexports:\n"
75       "  - targets: [ i386-macos ]\n"
76       "    symbols: [_symC]\n"
77       "    objc-classes: []\n"
78       "    objc-eh-types: []\n"
79       "    objc-ivars: []\n"
80       "    weak-symbols: []\n"
81       "    thread-local-symbols: []\n"
82       "undefineds:\n"
83       "  - targets: [ i386-macos ]\n"
84       "    symbols: [ _symD ]\n"
85       "    objc-classes: []\n"
86       "    objc-eh-types: []\n"
87       "    objc-ivars: []\n"
88       "    weak-symbols: []\n"
89       "    thread-local-symbols: []\n"
90       "...\n";
91 
92   auto Result = TextAPIReader::get(MemoryBufferRef(TBDv4File, "Test.tbd"));
93   EXPECT_TRUE(!!Result);
94   auto File = std::move(Result.get());
95   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
96   PlatformSet Platforms;
97   Platforms.insert(PlatformKind::macOS);
98   Platforms.insert(PlatformKind::iOS);
99   auto Archs = AK_i386 | AK_x86_64;
100   TargetList Targets = {
101       Target(AK_i386, PlatformKind::macOS),
102       Target(AK_x86_64, PlatformKind::macOS),
103       Target(AK_x86_64, PlatformKind::iOS),
104   };
105   UUIDs uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"},
106                  {Targets[1], "11111111-1111-1111-1111-111111111111"},
107                  {Targets[2], "11111111-1111-1111-1111-111111111111"}};
108   EXPECT_EQ(Archs, File->getArchitectures());
109   EXPECT_EQ(uuids, File->uuids());
110   EXPECT_EQ(Platforms.size(), File->getPlatforms().size());
111   for (auto Platform : File->getPlatforms())
112     EXPECT_EQ(Platforms.count(Platform), 1U);
113   EXPECT_EQ(std::string("Umbrella.framework/Umbrella"), File->getInstallName());
114   EXPECT_EQ(PackedVersion(1, 2, 3), File->getCurrentVersion());
115   EXPECT_EQ(PackedVersion(1, 2, 0), File->getCompatibilityVersion());
116   EXPECT_EQ(5U, File->getSwiftABIVersion());
117   EXPECT_FALSE(File->isTwoLevelNamespace());
118   EXPECT_TRUE(File->isApplicationExtensionSafe());
119   EXPECT_TRUE(File->isInstallAPI());
120   InterfaceFileRef client("ClientA", Targets);
121   InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A",
122                             {Targets[0]});
123   EXPECT_EQ(1U, File->allowableClients().size());
124   EXPECT_EQ(client, File->allowableClients().front());
125   EXPECT_EQ(1U, File->reexportedLibraries().size());
126   EXPECT_EQ(reexport, File->reexportedLibraries().front());
127 
128   ExportedSymbolSeq Exports, Reexports, Undefineds;
129   ExportedSymbol temp;
130   for (const auto *Sym : File->symbols()) {
131     temp = ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
132                           Sym->isWeakDefined(), Sym->isThreadLocalValue()};
133     EXPECT_FALSE(Sym->isWeakReferenced());
134     if (Sym->isUndefined())
135       Undefineds.emplace_back(std::move(temp));
136     else
137       Sym->isReexported() ? Reexports.emplace_back(std::move(temp))
138                           : Exports.emplace_back(std::move(temp));
139   }
140   llvm::sort(Exports.begin(), Exports.end());
141   llvm::sort(Reexports.begin(), Reexports.end());
142   llvm::sort(Undefineds.begin(), Undefineds.end());
143 
144   EXPECT_EQ(sizeof(TBDv4ExportedSymbols) / sizeof(ExportedSymbol),
145             Exports.size());
146   EXPECT_EQ(sizeof(TBDv4ReexportedSymbols) / sizeof(ExportedSymbol),
147             Reexports.size());
148   EXPECT_EQ(sizeof(TBDv4UndefinedSymbols) / sizeof(ExportedSymbol),
149             Undefineds.size());
150   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
151                          std::begin(TBDv4ExportedSymbols)));
152   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
153                          std::begin(TBDv4ReexportedSymbols)));
154   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
155                          std::begin(TBDv4UndefinedSymbols)));
156 }
157 
158 TEST(TBDv4, WriteFile) {
159   static const char TBDv4File[] =
160       "--- !tapi-tbd\n"
161       "tbd-version:     4\n"
162       "targets:         [ i386-macos, x86_64-ios-simulator ]\n"
163       "uuids:\n"
164       "  - target:          i386-macos\n"
165       "    value:           00000000-0000-0000-0000-000000000000\n"
166       "  - target:          x86_64-ios-simulator\n"
167       "    value:           11111111-1111-1111-1111-111111111111\n"
168       "flags:           [ installapi ]\n"
169       "install-name:    'Umbrella.framework/Umbrella'\n"
170       "current-version: 1.2.3\n"
171       "compatibility-version: 0\n"
172       "swift-abi-version: 5\n"
173       "parent-umbrella:\n"
174       "  - targets:         [ i386-macos, x86_64-ios-simulator ]\n"
175       "    umbrella:        System\n"
176       "allowable-clients:\n"
177       "  - targets:         [ i386-macos ]\n"
178       "    clients:         [ ClientA ]\n"
179       "exports:\n"
180       "  - targets:         [ i386-macos ]\n"
181       "    symbols:         [ _symA ]\n"
182       "    objc-classes:    [ Class1 ]\n"
183       "    weak-symbols:    [ _symC ]\n"
184       "  - targets:         [ x86_64-ios-simulator ]\n"
185       "    symbols:         [ _symB ]\n"
186       "...\n";
187 
188   InterfaceFile File;
189   TargetList Targets = {
190       Target(AK_i386, PlatformKind::macOS),
191       Target(AK_x86_64, PlatformKind::iOSSimulator),
192   };
193   UUIDs uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"},
194                  {Targets[1], "11111111-1111-1111-1111-111111111111"}};
195   File.setInstallName("Umbrella.framework/Umbrella");
196   File.setFileType(FileType::TBD_V4);
197   File.addTargets(Targets);
198   File.addUUID(uuids[0].first, uuids[0].second);
199   File.addUUID(uuids[1].first, uuids[1].second);
200   File.setCurrentVersion(PackedVersion(1, 2, 3));
201   File.setTwoLevelNamespace();
202   File.setInstallAPI(true);
203   File.setApplicationExtensionSafe(true);
204   File.setSwiftABIVersion(5);
205   File.addAllowableClient("ClientA", Targets[0]);
206   File.addParentUmbrella(Targets[0], "System");
207   File.addParentUmbrella(Targets[1], "System");
208   File.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[0]});
209   File.addSymbol(SymbolKind::GlobalSymbol, "_symB", {Targets[1]});
210   File.addSymbol(SymbolKind::GlobalSymbol, "_symC", {Targets[0]},
211                  SymbolFlags::WeakDefined);
212   File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[0]});
213 
214   SmallString<4096> Buffer;
215   raw_svector_ostream OS(Buffer);
216   auto Result = TextAPIWriter::writeToStream(OS, File);
217   EXPECT_FALSE(Result);
218   EXPECT_STREQ(TBDv4File, Buffer.c_str());
219 }
220 
221 TEST(TBDv4, MultipleTargets) {
222   static const char TBDv4MultipleTargets[] =
223       "--- !tapi-tbd\n"
224       "tbd-version: 4\n"
225       "targets: [ i386-maccatalyst, x86_64-tvos, arm64-ios ]\n"
226       "install-name: Test.dylib\n"
227       "...\n";
228 
229   auto Result =
230       TextAPIReader::get(MemoryBufferRef(TBDv4MultipleTargets, "Test.tbd"));
231   EXPECT_TRUE(!!Result);
232   PlatformSet Platforms;
233   Platforms.insert(PlatformKind::macCatalyst);
234   Platforms.insert(PlatformKind::tvOS);
235   Platforms.insert(PlatformKind::iOS);
236   auto File = std::move(Result.get());
237   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
238   EXPECT_EQ(AK_x86_64 | AK_arm64 | AK_i386, File->getArchitectures());
239   EXPECT_EQ(Platforms.size(), File->getPlatforms().size());
240   for (auto Platform : File->getPlatforms())
241     EXPECT_EQ(Platforms.count(Platform), 1U);
242 
243   SmallString<4096> Buffer;
244   raw_svector_ostream OS(Buffer);
245   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
246   EXPECT_TRUE(!WriteResult);
247   EXPECT_EQ(stripWhitespace(TBDv4MultipleTargets),
248             stripWhitespace(Buffer.c_str()));
249 }
250 
251 TEST(TBDv4, MultipleTargetsSameArch) {
252   static const char TBDv4TargetsSameArch[] =
253       "--- !tapi-tbd\n"
254       "tbd-version: 4\n"
255       "targets: [ x86_64-tvos , x86_64-maccatalyst ]\n"
256       "install-name: Test.dylib\n"
257       "...\n";
258 
259   auto Result =
260       TextAPIReader::get(MemoryBufferRef(TBDv4TargetsSameArch, "Test.tbd"));
261   EXPECT_TRUE(!!Result);
262   PlatformSet Platforms;
263   Platforms.insert(PlatformKind::tvOS);
264   Platforms.insert(PlatformKind::macCatalyst);
265   auto File = std::move(Result.get());
266   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
267   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
268   EXPECT_EQ(Platforms.size(), File->getPlatforms().size());
269   for (auto Platform : File->getPlatforms())
270     EXPECT_EQ(Platforms.count(Platform), 1U);
271 
272   SmallString<4096> Buffer;
273   raw_svector_ostream OS(Buffer);
274   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
275   EXPECT_TRUE(!WriteResult);
276   EXPECT_EQ(stripWhitespace(TBDv4TargetsSameArch),
277             stripWhitespace(Buffer.c_str()));
278 }
279 
280 TEST(TBDv4, MultipleTargetsSamePlatform) {
281   static const char TBDv4MultipleTargetsSamePlatform[] =
282       "--- !tapi-tbd\n"
283       "tbd-version: 4\n"
284       "targets: [ armv7k-ios , arm64-ios]\n"
285       "install-name: Test.dylib\n"
286       "...\n";
287 
288   auto Result = TextAPIReader::get(
289       MemoryBufferRef(TBDv4MultipleTargetsSamePlatform, "Test.tbd"));
290   EXPECT_TRUE(!!Result);
291   auto File = std::move(Result.get());
292   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
293   EXPECT_EQ(AK_arm64 | AK_armv7k, File->getArchitectures());
294   EXPECT_EQ(File->getPlatforms().size(), 1U);
295   EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin());
296 
297   SmallString<4096> Buffer;
298   raw_svector_ostream OS(Buffer);
299   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
300   EXPECT_TRUE(!WriteResult);
301   EXPECT_EQ(stripWhitespace(TBDv4MultipleTargetsSamePlatform),
302             stripWhitespace(Buffer.c_str()));
303 }
304 
305 TEST(TBDv4, Target_maccatalyst) {
306   static const char TBDv4TargetMacCatalyst[] =
307       "--- !tapi-tbd\n"
308       "tbd-version: 4\n"
309       "targets: [  x86_64-maccatalyst ]\n"
310       "install-name: Test.dylib\n"
311       "...\n";
312 
313   auto Result =
314       TextAPIReader::get(MemoryBufferRef(TBDv4TargetMacCatalyst, "Test.tbd"));
315   EXPECT_TRUE(!!Result);
316   auto File = std::move(Result.get());
317   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
318   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
319   EXPECT_EQ(File->getPlatforms().size(), 1U);
320   EXPECT_EQ(PlatformKind::macCatalyst, *File->getPlatforms().begin());
321 
322   SmallString<4096> Buffer;
323   raw_svector_ostream OS(Buffer);
324   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
325   EXPECT_TRUE(!WriteResult);
326   EXPECT_EQ(stripWhitespace(TBDv4TargetMacCatalyst),
327             stripWhitespace(Buffer.c_str()));
328 }
329 
330 TEST(TBDv4, Target_x86_ios) {
331   static const char TBDv4Targetx86iOS[] = "--- !tapi-tbd\n"
332                                           "tbd-version: 4\n"
333                                           "targets: [  x86_64-ios ]\n"
334                                           "install-name: Test.dylib\n"
335                                           "...\n";
336 
337   auto Result =
338       TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86iOS, "Test.tbd"));
339   EXPECT_TRUE(!!Result);
340   auto File = std::move(Result.get());
341   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
342   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
343   EXPECT_EQ(File->getPlatforms().size(), 1U);
344   EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin());
345 
346   SmallString<4096> Buffer;
347   raw_svector_ostream OS(Buffer);
348   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
349   EXPECT_TRUE(!WriteResult);
350   EXPECT_EQ(stripWhitespace(TBDv4Targetx86iOS),
351             stripWhitespace(Buffer.c_str()));
352 }
353 
354 TEST(TBDv4, Target_arm_bridgeOS) {
355   static const char TBDv4PlatformBridgeOS[] = "--- !tapi-tbd\n"
356                                               "tbd-version: 4\n"
357                                               "targets: [  armv7k-bridgeos ]\n"
358                                               "install-name: Test.dylib\n"
359                                               "...\n";
360 
361   auto Result =
362       TextAPIReader::get(MemoryBufferRef(TBDv4PlatformBridgeOS, "Test.tbd"));
363   EXPECT_TRUE(!!Result);
364   auto File = std::move(Result.get());
365   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
366   EXPECT_EQ(File->getPlatforms().size(), 1U);
367   EXPECT_EQ(PlatformKind::bridgeOS, *File->getPlatforms().begin());
368   EXPECT_EQ(ArchitectureSet(AK_armv7k), File->getArchitectures());
369 
370   SmallString<4096> Buffer;
371   raw_svector_ostream OS(Buffer);
372   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
373   EXPECT_TRUE(!WriteResult);
374   EXPECT_EQ(stripWhitespace(TBDv4PlatformBridgeOS),
375             stripWhitespace(Buffer.c_str()));
376 }
377 
378 TEST(TBDv4, Target_arm_iOS) {
379   static const char TBDv4ArchArm64e[] = "--- !tapi-tbd\n"
380                                         "tbd-version: 4\n"
381                                         "targets: [  arm64e-ios ]\n"
382                                         "install-name: Test.dylib\n"
383                                         "...\n";
384 
385   auto Result =
386       TextAPIReader::get(MemoryBufferRef(TBDv4ArchArm64e, "Test.tbd"));
387   EXPECT_TRUE(!!Result);
388   auto File = std::move(Result.get());
389   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
390   EXPECT_EQ(File->getPlatforms().size(), 1U);
391   EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin());
392   EXPECT_EQ(ArchitectureSet(AK_arm64e), File->getArchitectures());
393 
394   SmallString<4096> Buffer;
395   raw_svector_ostream OS(Buffer);
396   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
397   EXPECT_TRUE(!WriteResult);
398   EXPECT_EQ(stripWhitespace(TBDv4ArchArm64e), stripWhitespace(Buffer.c_str()));
399 }
400 
401 TEST(TBDv4, Target_x86_macos) {
402   static const char TBDv4Targetx86MacOS[] = "--- !tapi-tbd\n"
403                                             "tbd-version: 4\n"
404                                             "targets: [  x86_64-macos ]\n"
405                                             "install-name: Test.dylib\n"
406                                             "...\n";
407 
408   auto Result =
409       TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86MacOS, "Test.tbd"));
410   EXPECT_TRUE(!!Result);
411   auto File = std::move(Result.get());
412   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
413   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
414   EXPECT_EQ(File->getPlatforms().size(), 1U);
415   EXPECT_EQ(PlatformKind::macOS, *File->getPlatforms().begin());
416 
417   SmallString<4096> Buffer;
418   raw_svector_ostream OS(Buffer);
419   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
420   EXPECT_TRUE(!WriteResult);
421   EXPECT_EQ(stripWhitespace(TBDv4Targetx86MacOS),
422             stripWhitespace(Buffer.c_str()));
423 }
424 
425 TEST(TBDv4, Target_x86_ios_simulator) {
426   static const char TBDv4Targetx86iOSSim[] =
427       "--- !tapi-tbd\n"
428       "tbd-version: 4\n"
429       "targets: [  x86_64-ios-simulator  ]\n"
430       "install-name: Test.dylib\n"
431       "...\n";
432 
433   auto Result =
434       TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86iOSSim, "Test.tbd"));
435   EXPECT_TRUE(!!Result);
436   auto File = std::move(Result.get());
437   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
438   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
439   EXPECT_EQ(File->getPlatforms().size(), 1U);
440   EXPECT_EQ(PlatformKind::iOSSimulator, *File->getPlatforms().begin());
441 
442   SmallString<4096> Buffer;
443   raw_svector_ostream OS(Buffer);
444   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
445   EXPECT_TRUE(!WriteResult);
446   EXPECT_EQ(stripWhitespace(TBDv4Targetx86iOSSim),
447             stripWhitespace(Buffer.c_str()));
448 }
449 
450 TEST(TBDv4, Target_x86_tvos_simulator) {
451   static const char TBDv4x86tvOSSim[] = "--- !tapi-tbd\n"
452                                         "tbd-version: 4\n"
453                                         "targets: [  x86_64-tvos-simulator  ]\n"
454                                         "install-name: Test.dylib\n"
455                                         "...\n";
456 
457   auto Result =
458       TextAPIReader::get(MemoryBufferRef(TBDv4x86tvOSSim, "Test.tbd"));
459   EXPECT_TRUE(!!Result);
460   auto File = std::move(Result.get());
461   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
462   EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures());
463   EXPECT_EQ(File->getPlatforms().size(), 1U);
464   EXPECT_EQ(PlatformKind::tvOSSimulator, *File->getPlatforms().begin());
465 
466   SmallString<4096> Buffer;
467   raw_svector_ostream OS(Buffer);
468   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
469   EXPECT_TRUE(!WriteResult);
470   EXPECT_EQ(stripWhitespace(TBDv4x86tvOSSim), stripWhitespace(Buffer.c_str()));
471 }
472 
473 TEST(TBDv4, Target_i386_watchos_simulator) {
474   static const char TBDv4i386watchOSSim[] =
475       "--- !tapi-tbd\n"
476       "tbd-version: 4\n"
477       "targets: [  i386-watchos-simulator  ]\n"
478       "install-name: Test.dylib\n"
479       "...\n";
480 
481   auto Result =
482       TextAPIReader::get(MemoryBufferRef(TBDv4i386watchOSSim, "Test.tbd"));
483   EXPECT_TRUE(!!Result);
484   auto File = std::move(Result.get());
485   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
486   EXPECT_EQ(ArchitectureSet(AK_i386), File->getArchitectures());
487   EXPECT_EQ(File->getPlatforms().size(), 1U);
488   EXPECT_EQ(PlatformKind::watchOSSimulator, *File->getPlatforms().begin());
489 
490   SmallString<4096> Buffer;
491   raw_svector_ostream OS(Buffer);
492   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
493   EXPECT_TRUE(!WriteResult);
494   EXPECT_EQ(stripWhitespace(TBDv4i386watchOSSim),
495             stripWhitespace(Buffer.c_str()));
496 }
497 
498 TEST(TBDv4, Swift_1) {
499   static const char TBDv4SwiftVersion1[] = "--- !tapi-tbd\n"
500                                            "tbd-version: 4\n"
501                                            "targets: [  x86_64-macos ]\n"
502                                            "install-name: Test.dylib\n"
503                                            "swift-abi-version: 1\n"
504                                            "...\n";
505 
506   auto Result =
507       TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion1, "Test.tbd"));
508   EXPECT_TRUE(!!Result);
509   auto File = std::move(Result.get());
510   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
511   EXPECT_EQ(1U, File->getSwiftABIVersion());
512 
513   // No writer test because we emit "swift-abi-version:1.0".
514 }
515 
516 TEST(TBDv4, Swift_2) {
517   static const char TBDv4Swift2[] = "--- !tapi-tbd\n"
518                                     "tbd-version: 4\n"
519                                     "targets: [  x86_64-macos ]\n"
520                                     "install-name: Test.dylib\n"
521                                     "swift-abi-version: 2\n"
522                                     "...\n";
523 
524   auto Result = TextAPIReader::get(MemoryBufferRef(TBDv4Swift2, "Test.tbd"));
525   EXPECT_TRUE(!!Result);
526   auto File = std::move(Result.get());
527   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
528   EXPECT_EQ(2U, File->getSwiftABIVersion());
529 
530   // No writer test because we emit "swift-abi-version:2.0".
531 }
532 
533 TEST(TBDv4, Swift_5) {
534   static const char TBDv4SwiftVersion5[] = "--- !tapi-tbd\n"
535                                            "tbd-version: 4\n"
536                                            "targets: [  x86_64-macos ]\n"
537                                            "install-name: Test.dylib\n"
538                                            "swift-abi-version: 5\n"
539                                            "...\n";
540 
541   auto Result =
542       TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion5, "Test.tbd"));
543   EXPECT_TRUE(!!Result);
544   auto File = std::move(Result.get());
545   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
546   EXPECT_EQ(5U, File->getSwiftABIVersion());
547 
548   SmallString<4096> Buffer;
549   raw_svector_ostream OS(Buffer);
550   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
551   EXPECT_TRUE(!WriteResult);
552   EXPECT_EQ(stripWhitespace(TBDv4SwiftVersion5),
553             stripWhitespace(Buffer.c_str()));
554 }
555 
556 TEST(TBDv4, Swift_99) {
557   static const char TBDv4SwiftVersion99[] = "--- !tapi-tbd\n"
558                                             "tbd-version: 4\n"
559                                             "targets: [  x86_64-macos ]\n"
560                                             "install-name: Test.dylib\n"
561                                             "swift-abi-version: 99\n"
562                                             "...\n";
563 
564   auto Result =
565       TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion99, "Test.tbd"));
566   EXPECT_TRUE(!!Result);
567   auto File = std::move(Result.get());
568   EXPECT_EQ(FileType::TBD_V4, File->getFileType());
569   EXPECT_EQ(99U, File->getSwiftABIVersion());
570 
571   SmallString<4096> Buffer;
572   raw_svector_ostream OS(Buffer);
573   auto WriteResult = TextAPIWriter::writeToStream(OS, *File);
574   EXPECT_TRUE(!WriteResult);
575   EXPECT_EQ(stripWhitespace(TBDv4SwiftVersion99),
576             stripWhitespace(Buffer.c_str()));
577 }
578 
579 TEST(TBDv4, InvalidArchitecture) {
580   static const char TBDv4UnknownArch[] = "--- !tapi-tbd\n"
581                                          "tbd-version: 4\n"
582                                          "targets: [ foo-macos ]\n"
583                                          "install-name: Test.dylib\n"
584                                          "...\n";
585 
586   auto Result =
587       TextAPIReader::get(MemoryBufferRef(TBDv4UnknownArch, "Test.tbd"));
588   EXPECT_FALSE(!!Result);
589   auto errorMessage = toString(Result.takeError());
590   EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown "
591             "architecture\ntargets: [ foo-macos ]\n"
592             "           ^~~~~~~~~~\n",
593             errorMessage);
594 }
595 
596 TEST(TBDv4, InvalidPlatform) {
597   static const char TBDv4FInvalidPlatform[] = "--- !tapi-tbd\n"
598                                               "tbd-version: 4\n"
599                                               "targets: [ x86_64-maos ]\n"
600                                               "install-name: Test.dylib\n"
601                                               "...\n";
602 
603   auto Result =
604       TextAPIReader::get(MemoryBufferRef(TBDv4FInvalidPlatform, "Test.tbd"));
605   EXPECT_FALSE(!!Result);
606   auto errorMessage = toString(Result.takeError());
607   EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown platform\ntargets: "
608             "[ x86_64-maos ]\n"
609             "           ^~~~~~~~~~~~\n",
610             errorMessage);
611 }
612 
613 TEST(TBDv4, MalformedFile1) {
614   static const char TBDv4MalformedFile1[] = "--- !tapi-tbd\n"
615                                             "tbd-version: 4\n"
616                                             "...\n";
617 
618   auto Result =
619       TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile1, "Test.tbd"));
620   EXPECT_FALSE(!!Result);
621   auto errorMessage = toString(Result.takeError());
622   ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key "
623             "'targets'\ntbd-version: 4\n^\n",
624             errorMessage);
625 }
626 
627 TEST(TBDv4, MalformedFile2) {
628   static const char TBDv4MalformedFile2[] = "--- !tapi-tbd\n"
629                                             "tbd-version: 4\n"
630                                             "targets: [ x86_64-macos ]\n"
631                                             "install-name: Test.dylib\n"
632                                             "foobar: \"unsupported key\"\n";
633 
634   auto Result =
635       TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile2, "Test.tbd"));
636   EXPECT_FALSE(!!Result);
637   auto errorMessage = toString(Result.takeError());
638   ASSERT_EQ(
639       "malformed file\nTest.tbd:5:9: error: unknown key 'foobar'\nfoobar: "
640       "\"unsupported key\"\n        ^~~~~~~~~~~~~~~~~\n",
641       errorMessage);
642 }
643 
644 TEST(TBDv4, MalformedFile3) {
645   static const char TBDv4MalformedSwift[] = "--- !tapi-tbd\n"
646                                             "tbd-version: 4\n"
647                                             "targets: [  x86_64-macos ]\n"
648                                             "install-name: Test.dylib\n"
649                                             "swift-abi-version: 1.1\n"
650                                             "...\n";
651 
652   auto Result =
653       TextAPIReader::get(MemoryBufferRef(TBDv4MalformedSwift, "Test.tbd"));
654   EXPECT_FALSE(!!Result);
655   auto errorMessage = toString(Result.takeError());
656   EXPECT_EQ("malformed file\nTest.tbd:5:20: error: invalid Swift ABI "
657             "version.\nswift-abi-version: 1.1\n                   ^~~\n",
658             errorMessage);
659 }
660 
661 } // end namespace TBDv4
662