xref: /llvm-project/llvm/unittests/TextAPI/TextStubV5Tests.cpp (revision e17efa60b197c07ea21c2cba44670acf0dd75e60)
1 //===-- TextStubV5Tests.cpp - TBD V5 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 namespace TBDv5 {
21 
22 TEST(TBDv5, ReadFile) {
23   static const char TBDv5File[] = R"({
24 "tapi_tbd_version": 5,
25 "main_library": {
26   "target_info": [
27     {
28       "target": "x86_64-macos",
29       "min_deployment": "10.14"
30     },
31     {
32       "target": "arm64-macos",
33       "min_deployment": "10.14"
34     },
35     {
36       "target": "arm64-maccatalyst",
37       "min_deployment": "12.1"
38     }
39   ],
40   "flags": [
41     {
42       "targets": [
43             "x86_64-macos"
44         ],
45       "attributes": [
46             "flat_namespace"
47         ]
48     }
49   ],
50   "install_names": [
51     {
52         "name": "/S/L/F/Foo.framework/Foo"
53     }
54   ],
55   "current_versions": [
56     {
57         "version": "1.2"
58     }
59   ],
60   "compatibility_versions": [
61     { "version": "1.1" }
62   ],
63   "rpaths": [
64     {
65       "targets": [
66           "x86_64-macos"
67       ],
68       "paths": [
69           "@executable_path/.../Frameworks"
70       ]
71     }
72   ],
73   "parent_umbrellas": [
74     {
75       "umbrella": "System"
76     }
77   ],
78   "allowable_clients": [
79     {
80         "clients": [
81             "ClientA",
82             "ClientB"
83         ]
84     }
85   ],
86   "reexported_libraries": [
87     {
88         "names": [
89             "/u/l/l/libfoo.dylib",
90             "/u/l/l/libbar.dylib"
91         ]
92     }
93   ],
94   "exported_symbols": [
95     {
96         "targets": [
97             "x86_64-macos",
98             "arm64-macos"
99         ],
100         "data": {
101             "global": [
102                 "_global"
103             ],
104             "objc_class": [
105                 "ClassA"
106             ],
107             "weak": [],
108             "thread_local": []
109         },
110         "text": {
111             "global": [
112                 "_func"
113             ],
114             "weak": [],
115             "thread_local": []
116         }
117     },
118     {
119       "targets": [
120           "x86_64-macos"
121       ],
122       "data": {
123           "global": [
124               "_globalVar"
125           ],
126           "objc_class": [
127               "ClassA",
128               "ClassB",
129               "ClassData"
130           ],
131           "objc_eh_type": [
132               "ClassA",
133               "ClassB"
134           ],
135           "objc_ivar": [
136               "ClassA.ivar1",
137               "ClassA.ivar2",
138               "ClassC.ivar1"
139           ]
140       },
141       "text": {
142           "global": [
143               "_funcFoo"
144           ]
145       }
146     }
147   ],
148   "reexported_symbols": [
149     {
150         "targets": [
151             "x86_64-macos",
152             "arm64-macos"
153         ],
154         "data": {
155             "global": [
156                 "_globalRe"
157             ],
158             "objc_class": [
159                 "ClassRexport"
160             ]
161         },
162         "text": {
163             "global": [
164                 "_funcA"
165             ]
166         }
167     }
168   ],
169   "undefined_symbols": [
170     {
171         "targets": [
172             "x86_64-macos"
173         ],
174         "data": {
175             "global": [
176                 "_globalBind"
177             ],
178             "weak": [
179                 "referenced_sym"
180             ]
181         }
182     }
183   ]
184 },
185 "libraries": []
186 })";
187 
188   MemoryBufferRef InputBuf = MemoryBufferRef(TBDv5File, "Test.tbd");
189   Expected<FileType> ExpectedFT = TextAPIReader::canRead(InputBuf);
190   EXPECT_TRUE(!!ExpectedFT);
191 
192   Expected<TBDFile> Result = TextAPIReader::get(InputBuf);
193   EXPECT_TRUE(!!Result);
194   TBDFile File = std::move(Result.get());
195   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
196   EXPECT_EQ(*ExpectedFT, File->getFileType());
197   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName());
198 
199   TargetList AllTargets = {
200       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
201       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
202       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
203   };
204   std::set<Target> FileTargets{File->targets().begin(), File->targets().end()};
205   EXPECT_EQ(mapToPlatformSet(AllTargets), File->getPlatforms());
206   EXPECT_EQ(mapToArchitectureSet(AllTargets), File->getArchitectures());
207   EXPECT_EQ(FileTargets.size(), AllTargets.size());
208   for (const auto &Targ : AllTargets) {
209     auto FileTarg = FileTargets.find(Targ);
210     EXPECT_FALSE(FileTarg == FileTargets.end());
211     EXPECT_EQ(*FileTarg, Targ);
212     PackedVersion MD = Targ.MinDeployment;
213     PackedVersion FileMD = FileTarg->MinDeployment;
214     EXPECT_EQ(MD, FileMD);
215   }
216 
217   EXPECT_EQ(PackedVersion(1, 2, 0), File->getCurrentVersion());
218   EXPECT_EQ(PackedVersion(1, 1, 0), File->getCompatibilityVersion());
219   EXPECT_TRUE(File->isApplicationExtensionSafe());
220   EXPECT_FALSE(File->isTwoLevelNamespace());
221   EXPECT_FALSE(File->isOSLibNotForSharedCache());
222   EXPECT_EQ(0U, File->documents().size());
223 
224   InterfaceFileRef ClientA("ClientA", AllTargets);
225   InterfaceFileRef ClientB("ClientB", AllTargets);
226   EXPECT_EQ(2U, File->allowableClients().size());
227   EXPECT_EQ(ClientA, File->allowableClients().at(0));
228   EXPECT_EQ(ClientB, File->allowableClients().at(1));
229 
230   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
231   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
232   EXPECT_EQ(2U, File->reexportedLibraries().size());
233   EXPECT_EQ(ReexportA, File->reexportedLibraries().at(0));
234   EXPECT_EQ(ReexportB, File->reexportedLibraries().at(1));
235 
236   TargetToAttr RPaths = {
237       {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"},
238   };
239   EXPECT_EQ(RPaths, File->rpaths());
240 
241   TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"},
242                             {Target(AK_arm64, PLATFORM_MACOS), "System"},
243                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
244   EXPECT_EQ(Umbrellas, File->umbrellas());
245 
246   ExportedSymbolSeq Exports, Reexports, Undefineds;
247   for (const auto *Sym : File->symbols()) {
248     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
249     ExportedSymbol Temp =
250         ExportedSymbol{Sym->getKind(),
251                        std::string(Sym->getName()),
252                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
253                        Sym->isThreadLocalValue(),
254                        Sym->isData(),
255                        SymTargets};
256     if (Sym->isUndefined())
257       Undefineds.emplace_back(std::move(Temp));
258     else
259       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
260                           : Exports.emplace_back(std::move(Temp));
261   }
262   llvm::sort(Exports);
263   llvm::sort(Reexports);
264   llvm::sort(Undefineds);
265 
266   TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS),
267                              Target(AK_arm64, PLATFORM_MACOS)};
268 
269   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
270       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
271       {SymbolKind::GlobalSymbol,
272        "_funcFoo",
273        false,
274        false,
275        false,
276        {Target(AK_x86_64, PLATFORM_MACOS)}},
277       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
278       {SymbolKind::GlobalSymbol,
279        "_globalVar",
280        false,
281        false,
282        true,
283        {Target(AK_x86_64, PLATFORM_MACOS)}},
284       {SymbolKind::ObjectiveCClass,
285        "ClassA",
286        false,
287        false,
288        true,
289        {Target(AK_x86_64, PLATFORM_MACOS)}},
290       {SymbolKind::ObjectiveCClass,
291        "ClassB",
292        false,
293        false,
294        true,
295        {Target(AK_x86_64, PLATFORM_MACOS)}},
296       {SymbolKind::ObjectiveCClass,
297        "ClassData",
298        false,
299        false,
300        true,
301        {Target(AK_x86_64, PLATFORM_MACOS)}},
302       {SymbolKind::ObjectiveCClassEHType,
303        "ClassA",
304        false,
305        false,
306        true,
307        {Target(AK_x86_64, PLATFORM_MACOS)}},
308       {SymbolKind::ObjectiveCClassEHType,
309        "ClassB",
310        false,
311        false,
312        true,
313        {Target(AK_x86_64, PLATFORM_MACOS)}},
314       {SymbolKind::ObjectiveCInstanceVariable,
315        "ClassA.ivar1",
316        false,
317        false,
318        true,
319        {Target(AK_x86_64, PLATFORM_MACOS)}},
320       {SymbolKind::ObjectiveCInstanceVariable,
321        "ClassA.ivar2",
322        false,
323        false,
324        true,
325        {Target(AK_x86_64, PLATFORM_MACOS)}},
326       {SymbolKind::ObjectiveCInstanceVariable,
327        "ClassC.ivar1",
328        false,
329        false,
330        true,
331        {Target(AK_x86_64, PLATFORM_MACOS)}},
332   };
333   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
334       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
335       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
336       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
337        MacOSTargets},
338   };
339 
340   std::vector<ExportedSymbol> ExpectedUndefinedSymbols = {
341       {SymbolKind::GlobalSymbol,
342        "_globalBind",
343        false,
344        false,
345        true,
346        {Target(AK_x86_64, PLATFORM_MACOS)}},
347       {SymbolKind::GlobalSymbol,
348        "referenced_sym",
349        true,
350        false,
351        true,
352        {Target(AK_x86_64, PLATFORM_MACOS)}},
353   };
354 
355   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
356   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
357   EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size());
358   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
359                          std::begin(ExpectedExportedSymbols)));
360   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
361                          std::begin(ExpectedReexportedSymbols)));
362   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
363                          std::begin(ExpectedUndefinedSymbols)));
364 
365   EXPECT_TRUE(
366       File->getSymbol(SymbolKind::GlobalSymbol, "_globalBind").has_value());
367 }
368 
369 TEST(TBDv5, ReadMultipleTargets) {
370   static const char TBDv5File[] = R"({
371 "tapi_tbd_version": 5,
372 "main_library":  {
373   "target_info": [
374       {
375           "target": "x86_64-macos",
376           "min_deployment": "10.14"
377       },
378       {
379           "target": "arm64-macos",
380           "min_deployment": "10.14"
381       },
382       {
383           "target": "arm64-maccatalyst",
384           "min_deployment": "12.1"
385       }
386   ],
387   "install_names":[
388       { "name":"/usr/lib/libFoo.dylib" }
389   ],
390   "swift_abi":[ { "abi":8 } ],
391   "reexported_libraries": [
392       {
393           "targets": [ "x86_64-maccatalyst" ],
394           "names": [
395               "/u/l/l/libfoo.dylib",
396               "/u/l/l/libbar.dylib"
397           ]
398       },
399       {
400           "targets": [ "arm64-maccatalyst" ],
401           "names": [ "/u/l/l/libArmOnly.dylib" ]
402       }
403   ]
404 }
405 })";
406 
407   Expected<TBDFile> Result =
408       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
409   EXPECT_TRUE(!!Result);
410   TBDFile File = std::move(Result.get());
411   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
412   EXPECT_EQ(std::string("/usr/lib/libFoo.dylib"), File->getInstallName());
413   EXPECT_TRUE(File->isApplicationExtensionSafe());
414   EXPECT_TRUE(File->isTwoLevelNamespace());
415   EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion());
416   EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
417   EXPECT_EQ(8U, File->getSwiftABIVersion());
418 
419   TargetList AllTargets = {
420       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
421       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(10, 14)),
422       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(12, 1)),
423   };
424   EXPECT_EQ(mapToPlatformSet(AllTargets), File->getPlatforms());
425   EXPECT_EQ(mapToArchitectureSet(AllTargets), File->getArchitectures());
426 
427   InterfaceFileRef ReexportA("/u/l/l/libArmOnly.dylib",
428                              {Target(AK_arm64, PLATFORM_MACCATALYST)});
429   InterfaceFileRef ReexportB("/u/l/l/libbar.dylib",
430                              {Target(AK_x86_64, PLATFORM_MACCATALYST)});
431   InterfaceFileRef ReexportC("/u/l/l/libfoo.dylib",
432                              {Target(AK_x86_64, PLATFORM_MACCATALYST)});
433   EXPECT_EQ(3U, File->reexportedLibraries().size());
434   EXPECT_EQ(ReexportA, File->reexportedLibraries().at(0));
435   EXPECT_EQ(ReexportB, File->reexportedLibraries().at(1));
436   EXPECT_EQ(ReexportC, File->reexportedLibraries().at(2));
437 }
438 
439 TEST(TBDv5, ReadMultipleDocuments) {
440   static const char TBDv5File[] = R"({
441 "tapi_tbd_version": 5,
442 "main_library": {
443   "target_info": [
444     {
445       "target": "armv7-ios",
446       "min_deployment": "11.0"
447     }
448   ],
449   "install_names":[
450     { "name":"/S/L/F/Foo.framework/Foo" }
451   ],
452   "reexported_libraries": [
453     { "names": ["/u/l/l/libfoo.dylib"] }
454   ]
455 },
456 "libraries": [
457   {
458     "target_info": [
459       {
460         "target": "armv7-ios",
461         "min_deployment": "11.0"
462       }
463     ],
464     "install_names":[
465       { "name":"/u/l/l/libfoo.dylib" }
466     ],
467     "flags":[
468       { "attributes": ["not_app_extension_safe"] }
469     ],
470     "exported_symbols": [
471       {
472         "data": {
473           "thread_local": [ "_globalVar" ],
474           "objc_class": [ "ClassData", "ClassA", "ClassB"],
475           "objc_eh_type": [ "ClassA", "ClassB" ]
476         },
477         "text": {
478           "global": [ "_funcFoo" ]
479         }
480       }
481     ]
482   }
483 ]})";
484 
485   Expected<TBDFile> Result =
486       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
487   EXPECT_TRUE(!!Result);
488   TBDFile File = std::move(Result.get());
489   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
490   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName());
491   EXPECT_TRUE(File->isTwoLevelNamespace());
492   EXPECT_TRUE(File->isApplicationExtensionSafe());
493 
494   TargetList Targets(File->targets().begin(), File->targets().end());
495   Target iOSTarget(AK_armv7, PLATFORM_IOS, VersionTuple(11, 0));
496   EXPECT_EQ(TargetList{iOSTarget}, Targets);
497   std::vector<const Symbol *> Symbols(File->symbols().begin(),
498                                       File->symbols().end());
499   EXPECT_EQ(0U, Symbols.size());
500 
501   InterfaceFileRef Reexport("/u/l/l/libfoo.dylib", {iOSTarget});
502   EXPECT_EQ(1U, File->reexportedLibraries().size());
503   EXPECT_EQ(Reexport, File->reexportedLibraries().at(0));
504 
505   // Check inlined library.
506   EXPECT_EQ(1U, File->documents().size());
507   TBDReexportFile Document = File->documents().front();
508   Targets = {Document->targets().begin(), Document->targets().end()};
509   EXPECT_EQ(TargetList{iOSTarget}, Targets);
510   EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document->getInstallName());
511   EXPECT_EQ(0U, Document->getSwiftABIVersion());
512   EXPECT_TRUE(Document->isTwoLevelNamespace());
513   EXPECT_FALSE(Document->isApplicationExtensionSafe());
514 
515   ExportedSymbolSeq Exports;
516   for (const auto *Sym : Document->symbols())
517     Exports.emplace_back(
518         ExportedSymbol{Sym->getKind(),
519                        std::string(Sym->getName()),
520                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
521                        Sym->isThreadLocalValue(),
522                        Sym->isData(),
523                        {iOSTarget}});
524 
525   llvm::sort(Exports);
526   ExportedSymbolSeq ExpectedExports = {
527       {SymbolKind::GlobalSymbol, "_funcFoo", false, false, false, {iOSTarget}},
528       {SymbolKind::GlobalSymbol, "_globalVar", false, true, true, {iOSTarget}},
529       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, {iOSTarget}},
530       {SymbolKind::ObjectiveCClass, "ClassB", false, false, true, {iOSTarget}},
531       {SymbolKind::ObjectiveCClass,
532        "ClassData",
533        false,
534        false,
535        true,
536        {iOSTarget}},
537       {SymbolKind::ObjectiveCClassEHType,
538        "ClassA",
539        false,
540        false,
541        true,
542        {iOSTarget}},
543       {SymbolKind::ObjectiveCClassEHType,
544        "ClassB",
545        false,
546        false,
547        true,
548        {iOSTarget}},
549   };
550 
551   EXPECT_EQ(ExpectedExports.size(), Exports.size());
552   EXPECT_TRUE(
553       std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports)));
554 }
555 
556 TEST(TBDv5, WriteFile) {
557   static const char TBDv5File[] = R"({
558 "tapi_tbd_version": 5,
559 "main_library": {
560   "target_info": [
561     {
562       "target": "x86_64-macos",
563       "min_deployment": "10.14"
564     },
565     {
566       "target": "arm64-macos",
567       "min_deployment": "10.14"
568     },
569     {
570       "target": "arm64-maccatalyst",
571       "min_deployment": "12.1"
572     }
573   ],
574   "install_names": [
575     {
576         "name": "@rpath/S/L/F/Foo.framework/Foo"
577     }
578   ],
579   "current_versions": [
580     {
581         "version": "1.2"
582     }
583   ],
584   "compatibility_versions": [
585     { "version": "1.1" }
586   ],
587   "flags": [
588     {
589       "attributes": [
590             "flat_namespace"
591         ]
592     }
593   ],
594   "rpaths": [
595     {
596       "targets": [
597           "x86_64-macos"
598       ],
599       "paths": [
600           "@executable_path/.../Frameworks"
601       ]
602     }
603   ],
604   "parent_umbrellas": [
605     {
606       "umbrella": "System"
607     }
608   ],
609   "allowable_clients": [
610     {
611         "clients": [
612             "ClientA",
613             "ClientB"
614         ]
615     }
616   ],
617   "reexported_libraries": [
618     {
619         "names": [
620             "/u/l/l/libfoo.dylib",
621             "/u/l/l/libbar.dylib"
622         ]
623     }
624   ],
625   "exported_symbols": [
626     {
627         "targets": [
628             "x86_64-macos",
629             "arm64-macos"
630         ],
631         "data": {
632             "global": [
633                 "_global"
634             ],
635             "objc_class": [
636                 "ClassA"
637             ],
638             "weak": [],
639             "thread_local": []
640         },
641         "text": {
642             "global": [
643                 "_func"
644             ],
645             "weak": [],
646             "thread_local": []
647         }
648     },
649     {
650       "targets": [
651           "x86_64-macos"
652       ],
653       "data": {
654           "global": [
655               "_globalVar"
656           ],
657           "objc_class": [
658               "ClassA",
659               "ClassB",
660               "ClassData"
661           ],
662           "objc_eh_type": [
663               "ClassA",
664               "ClassB"
665           ],
666           "objc_ivar": [
667               "ClassA.ivar1",
668               "ClassA.ivar2",
669               "ClassC.ivar1"
670           ]
671       },
672       "text": {
673           "global": [
674               "_funcFoo"
675           ]
676       }
677     }
678   ],
679   "reexported_symbols": [
680     {
681         "data": {
682             "global": [
683                 "_globalRe"
684             ],
685             "objc_class": [
686                 "ClassRexport"
687             ]
688         },
689         "text": {
690             "global": [
691                 "_funcA"
692             ]
693         }
694     }
695   ],
696   "undefined_symbols": [
697     {
698         "targets": [
699             "x86_64-macos"
700         ],
701         "data": {
702             "global": [
703                 "_globalBind"
704             ],
705             "weak": [
706                 "referenced_sym"
707             ]
708         }
709     }
710   ]
711 }})";
712 
713   InterfaceFile File;
714   File.setFileType(FileType::TBD_V5);
715 
716   TargetList AllTargets = {
717       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
718       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(10, 14)),
719       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(12, 1)),
720   };
721   File.addTargets(AllTargets);
722   File.setInstallName("@rpath/S/L/F/Foo.framework/Foo");
723   File.setCurrentVersion(PackedVersion(1, 2, 0));
724   File.setCompatibilityVersion(PackedVersion(1, 1, 0));
725   File.addRPath(AllTargets[0], "@executable_path/.../Frameworks");
726 
727   for (const auto &Targ : AllTargets) {
728     File.addParentUmbrella(Targ, "System");
729     File.addAllowableClient("ClientA", Targ);
730     File.addAllowableClient("ClientB", Targ);
731     File.addReexportedLibrary("/u/l/l/libfoo.dylib", Targ);
732     File.addReexportedLibrary("/u/l/l/libbar.dylib", Targ);
733   }
734 
735   SymbolFlags Flags = SymbolFlags::None;
736   // Exports.
737   File.addSymbol(SymbolKind::GlobalSymbol, "_global",
738                  {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data);
739   File.addSymbol(SymbolKind::GlobalSymbol, "_func",
740                  {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Text);
741   File.addSymbol(SymbolKind::ObjectiveCClass, "ClassA",
742                  {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data);
743   File.addSymbol(SymbolKind::GlobalSymbol, "_funcFoo", {AllTargets[0]},
744                  Flags | SymbolFlags::Text);
745   File.addSymbol(SymbolKind::GlobalSymbol, "_globalVar", {AllTargets[0]},
746                  Flags | SymbolFlags::Data);
747   File.addSymbol(SymbolKind::ObjectiveCClass, "ClassData", {AllTargets[0]},
748                  Flags | SymbolFlags::Data);
749   File.addSymbol(SymbolKind::ObjectiveCClassEHType, "ClassA", {AllTargets[0]},
750                  Flags | SymbolFlags::Data);
751   File.addSymbol(SymbolKind::ObjectiveCClassEHType, "ClassB", {AllTargets[0]},
752                  Flags | SymbolFlags::Data);
753   File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassA.ivar1",
754                  {AllTargets[0]}, Flags | SymbolFlags::Data);
755   File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassA.ivar2",
756                  {AllTargets[0]}, Flags | SymbolFlags::Data);
757   File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassC.ivar1",
758                  {AllTargets[0]}, Flags | SymbolFlags::Data);
759 
760   // Reexports.
761   Flags = SymbolFlags::Rexported;
762   File.addSymbol(SymbolKind::GlobalSymbol, "_globalRe", AllTargets,
763                  Flags | SymbolFlags::Data);
764   File.addSymbol(SymbolKind::GlobalSymbol, "_funcA", AllTargets,
765                  Flags | SymbolFlags::Text);
766   File.addSymbol(SymbolKind::ObjectiveCClass, "ClassRexport", AllTargets,
767                  Flags | SymbolFlags::Data);
768 
769   // Undefineds.
770   Flags = SymbolFlags::Undefined;
771   File.addSymbol(SymbolKind::GlobalSymbol, "_globalBind", {AllTargets[0]},
772                  Flags | SymbolFlags::Data);
773   File.addSymbol(SymbolKind::GlobalSymbol, "referenced_sym", {AllTargets[0]},
774                  Flags | SymbolFlags::Data | SymbolFlags::WeakReferenced);
775 
776   File.setTwoLevelNamespace(false);
777   File.setApplicationExtensionSafe(true);
778 
779   // Write out file then process it back into IF and compare equality
780   // against TBDv5File.
781   SmallString<4096> Buffer;
782   raw_svector_ostream OS(Buffer);
783   Error Result = TextAPIWriter::writeToStream(OS, File);
784   EXPECT_FALSE(Result);
785 
786   Expected<TBDFile> Input =
787       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Input.tbd"));
788   EXPECT_TRUE(!!Input);
789   TBDFile InputFile = std::move(Input.get());
790 
791   Expected<TBDFile> Output =
792       TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
793   EXPECT_TRUE(!!Output);
794   TBDFile OutputFile = std::move(Output.get());
795   EXPECT_EQ(*InputFile, *OutputFile);
796 }
797 
798 TEST(TBDv5, WriteMultipleDocuments) {
799   static const char TBDv5File[] = R"({
800 "tapi_tbd_version": 5,
801 "main_library": {
802   "target_info": [
803     {
804       "target": "armv7-ios",
805       "min_deployment": "11.0"
806     }
807   ],
808   "install_names":[
809     { "name":"/S/L/F/Foo.framework/Foo" }
810   ],
811   "reexported_libraries": [
812     { "names": ["/u/l/l/libfoo.dylib"]
813     }
814   ]
815 },
816 "libraries": [
817   {
818     "target_info": [
819       {
820         "target": "armv7-ios",
821         "min_deployment": "11.0"
822       },
823       {
824         "target": "armv7s-ios",
825         "min_deployment": "11.0"
826       }
827     ],
828     "install_names":[
829       { "name":"/u/l/l/libfoo.dylib" }
830     ],
831     "current_versions": [
832       {
833           "version": "2.1.1"
834       }
835     ],
836     "rpaths": [
837       {
838         "targets": [
839             "armv7-ios"
840         ],
841         "paths": [
842             "@executable_path/.../Frameworks"
843         ]
844       }],
845     "reexported_libraries": [ { "names": ["@rpath/libfoo.dylib"] } ],
846     "flags":[
847       { "attributes": ["not_app_extension_safe"] }
848     ],
849     "exported_symbols": [
850       {
851         "text": {
852           "global": [ "_funcFoo" ]
853         }
854       }
855     ]
856   },
857   {
858     "target_info": [
859       {
860         "target": "armv7-ios",
861         "min_deployment": "11.0"
862       }
863     ],
864     "install_names":[
865       { "name":"@rpath/libfoo.dylib" }
866     ],
867     "exported_symbols": [
868       {
869         "data": {
870           "global": [ "_varFooBaz" ]
871         }
872       }
873     ]
874   }
875 ]})";
876 
877   InterfaceFile File;
878   File.setFileType(FileType::TBD_V5);
879 
880   TargetList AllTargets = {
881       Target(AK_armv7, PLATFORM_IOS, VersionTuple(11, 0)),
882       Target(AK_armv7s, PLATFORM_IOS, VersionTuple(11, 0)),
883   };
884   File.setInstallName("/S/L/F/Foo.framework/Foo");
885   File.addTarget(AllTargets[0]);
886   File.setCurrentVersion(PackedVersion(1, 0, 0));
887   File.setCompatibilityVersion(PackedVersion(1, 0, 0));
888   File.addReexportedLibrary("/u/l/l/libfoo.dylib", AllTargets[0]);
889   File.setTwoLevelNamespace();
890   File.setApplicationExtensionSafe(true);
891 
892   InterfaceFile NestedFile;
893   NestedFile.setFileType(FileType::TBD_V5);
894   NestedFile.setInstallName("/u/l/l/libfoo.dylib");
895   NestedFile.addTargets(AllTargets);
896   NestedFile.setCompatibilityVersion(PackedVersion(1, 0, 0));
897   NestedFile.setTwoLevelNamespace();
898   NestedFile.setApplicationExtensionSafe(false);
899   NestedFile.setCurrentVersion(PackedVersion(2, 1, 1));
900   NestedFile.addRPath(AllTargets[0], "@executable_path/.../Frameworks");
901   for (const auto &Targ : AllTargets)
902     NestedFile.addReexportedLibrary("@rpath/libfoo.dylib", Targ);
903   NestedFile.addSymbol(SymbolKind::GlobalSymbol, "_funcFoo", AllTargets,
904                        SymbolFlags::Text);
905   File.addDocument(std::make_shared<InterfaceFile>(std::move(NestedFile)));
906 
907   InterfaceFile NestedFileB;
908   NestedFileB.setFileType(FileType::TBD_V5);
909   NestedFileB.setInstallName("@rpath/libfoo.dylib");
910   NestedFileB.addTarget(AllTargets[0]);
911   NestedFileB.setCompatibilityVersion(PackedVersion(1, 0, 0));
912   NestedFileB.setCurrentVersion(PackedVersion(1, 0, 0));
913   NestedFileB.setTwoLevelNamespace();
914   NestedFileB.setApplicationExtensionSafe(true);
915   NestedFileB.addSymbol(SymbolKind::GlobalSymbol, "_varFooBaz", {AllTargets[0]},
916                         SymbolFlags::Data);
917   File.addDocument(std::make_shared<InterfaceFile>(std::move(NestedFileB)));
918 
919   // Write out file then process it back into IF and compare equality
920   // against TBDv5File.
921   SmallString<4096> Buffer;
922   raw_svector_ostream OS(Buffer);
923   Error Result = TextAPIWriter::writeToStream(OS, File, FileType::Invalid,
924                                               /*Compact=*/true);
925   EXPECT_FALSE(Result);
926 
927   Expected<TBDFile> Input =
928       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Input.tbd"));
929   EXPECT_TRUE(!!Input);
930   TBDFile InputFile = std::move(Input.get());
931 
932   Expected<TBDFile> Output =
933       TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
934   EXPECT_TRUE(!!Output);
935   TBDFile OutputFile = std::move(Output.get());
936   EXPECT_EQ(*InputFile, *OutputFile);
937 }
938 
939 TEST(TBDv5, Target_Simulator) {
940   static const char TBDv5File[] = R"({
941 "tapi_tbd_version": 5,
942 "main_library": {
943   "target_info": [
944     {
945       "target": "arm64-ios-simulator",
946       "min_deployment": "11.0"
947     },
948     {
949       "target": "x86_64-ios-simulator",
950       "min_deployment": "11.3"
951     }
952   ],
953   "install_names":[
954     { "name":"/S/L/F/Foo.framework/Foo" }
955   ]
956 }})";
957 
958   Expected<TBDFile> Result =
959       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
960   EXPECT_TRUE(!!Result);
961   TBDFile File = std::move(Result.get());
962   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
963   TargetList ExpectedTargets = {
964       Target(AK_x86_64, PLATFORM_IOSSIMULATOR, VersionTuple(11, 3)),
965       Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(14, 0)),
966   };
967   TargetList Targets{File->targets().begin(), File->targets().end()};
968   llvm::sort(Targets);
969   EXPECT_EQ(Targets, ExpectedTargets);
970 
971   SmallString<4096> Buffer;
972   raw_svector_ostream OS(Buffer);
973   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
974   EXPECT_TRUE(!WriteResult);
975 
976   Expected<TBDFile> Output =
977       TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
978   EXPECT_TRUE(!!Output);
979   TBDFile WriteResultFile = std::move(Output.get());
980   EXPECT_EQ(*File, *WriteResultFile);
981 }
982 
983 TEST(TBDv5, Target_UnsupportedMinOS) {
984   static const char TBDv5File[] = R"({
985 "tapi_tbd_version": 5,
986 "main_library": {
987   "target_info": [
988     {
989       "target": "arm64-macos",
990       "min_deployment": "10.14"
991     },
992     {
993       "target": "x86_64-macos",
994       "min_deployment": "10.14"
995     }
996   ],
997   "install_names":[
998     { "name":"/S/L/F/Foo.framework/Foo" }
999   ]
1000 }})";
1001 
1002   Expected<TBDFile> Result =
1003       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1004   EXPECT_TRUE(!!Result);
1005   TBDFile File = std::move(Result.get());
1006   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
1007   TargetList ExpectedTargets = {
1008       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
1009       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0)),
1010   };
1011   TargetList Targets{File->targets().begin(), File->targets().end()};
1012   llvm::sort(Targets);
1013   EXPECT_EQ(Targets, ExpectedTargets);
1014 
1015   SmallString<4096> Buffer;
1016   raw_svector_ostream OS(Buffer);
1017   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
1018   EXPECT_TRUE(!WriteResult);
1019 
1020   Expected<TBDFile> Output =
1021       TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
1022   EXPECT_TRUE(!!Output);
1023   TBDFile WriteResultFile = std::move(Output.get());
1024   EXPECT_EQ(*File, *WriteResultFile);
1025 }
1026 
1027 TEST(TBDv5, MisspelledKey) {
1028   static const char TBDv5File[] = R"({
1029 "tapi_tbd_version": 5,
1030 "main_library": {
1031   "target_info": [
1032     {
1033       "target": "arm64-ios-simulator",
1034       "min_deployment": "11.0"
1035     }
1036   ],
1037   "intall_names":[
1038     { "name":"/S/L/F/Foo.framework/Foo" }
1039   ]
1040 }})";
1041 
1042   Expected<TBDFile> Result =
1043       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1044   EXPECT_FALSE(!!Result);
1045   std::string ErrorMessage = toString(Result.takeError());
1046   EXPECT_EQ("invalid install_names section\n", ErrorMessage);
1047 }
1048 
1049 TEST(TBDv5, InvalidVersion) {
1050   static const char TBDv5File[] = R"({
1051 "tapi_tbd_version": 11,
1052 "main_library": {
1053   "target_info": [
1054     {
1055       "target": "arm64-ios-simulator",
1056       "min_deployment": "11.0"
1057     }
1058   ],
1059   "install_names":[
1060     { "name":"/S/L/F/Foo.framework/Foo" }
1061   ]
1062 }})";
1063 
1064   Expected<TBDFile> Result =
1065       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1066   EXPECT_FALSE(!!Result);
1067   std::string ErrorMessage = toString(Result.takeError());
1068   EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage);
1069 }
1070 
1071 TEST(TBDv5, MissingRequiredKey) {
1072   static const char TBDv5File[] = R"({
1073 "main_library": {
1074   "target_info": [
1075     {
1076       "target": "arm64-ios-simulator",
1077       "min_deployment": "11.0"
1078     }
1079   ],
1080   "install_names":[
1081     { "name":"/S/L/F/Foo.framework/Foo" }
1082   ]
1083 }})";
1084 
1085   Expected<TBDFile> Result =
1086       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1087   EXPECT_FALSE(!!Result);
1088   std::string ErrorMessage = toString(Result.takeError());
1089   EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage);
1090 }
1091 
1092 TEST(TBDv5, InvalidSymbols) {
1093   static const char TBDv5File[] = R"({
1094 "tapi_tbd_version": 5,
1095 "main_library": {
1096   "target_info": [
1097     {
1098       "target": "arm64-driverkit",
1099       "min_deployment": "11.0"
1100     }
1101   ],
1102   "install_names":[
1103     { "name":"/S/L/F/Foo.framework/Foo" }
1104   ],
1105   "exported_symbols": [
1106     {
1107       "daa": {
1108         "global": {
1109             "weak": []
1110           }
1111       }
1112     }
1113   ]
1114 }})";
1115 
1116   Expected<TBDFile> Result =
1117       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1118   EXPECT_FALSE(!!Result);
1119   std::string ErrorMessage = toString(Result.takeError());
1120   EXPECT_EQ("invalid exported_symbols section\n", ErrorMessage);
1121 }
1122 
1123 TEST(TBDv5, DefaultMinOS) {
1124   static const char TBDv5File[] = R"({
1125 "tapi_tbd_version": 5,
1126 "main_library": {
1127   "target_info": [
1128     {
1129       "target": "arm64-ios-simulator"
1130     }
1131   ],
1132   "install_names":[
1133     { "name":"/S/L/F/Foo.framework/Foo" }
1134   ]
1135 }})";
1136 
1137   Expected<TBDFile> Result =
1138       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1139   EXPECT_TRUE(!!Result);
1140   TBDFile File = std::move(Result.get());
1141   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
1142   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName());
1143   EXPECT_TRUE(File->targets().begin() != File->targets().end());
1144   EXPECT_EQ(*File->targets().begin(),
1145             Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(0, 0)));
1146 }
1147 
1148 TEST(TBDv5, InvalidMinOS) {
1149   static const char TBDv5File[] = R"({
1150 "tapi_tbd_version": 5,
1151 "main_library": {
1152   "target_info": [
1153     {
1154       "target": "arm64-ios-simulator",
1155       "min_deployment": "swift-abi"
1156     }
1157   ],
1158   "install_names":[
1159     { "name":"/S/L/F/Foo.framework/Foo" }
1160   ]
1161 }})";
1162 
1163   Expected<TBDFile> Result =
1164       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1165   EXPECT_FALSE(!!Result);
1166   std::string ErrorMessage = toString(Result.takeError());
1167   EXPECT_EQ("invalid min_deployment section\n", ErrorMessage);
1168 }
1169 
1170 TEST(TBDv5, SimSupport) {
1171   static const char TBDv5File[] = R"({
1172 "tapi_tbd_version": 5,
1173 "main_library": {
1174   "target_info": [
1175     {
1176       "target": "arm64-macos",
1177       "min_deployment": "11.1"
1178     }
1179   ],
1180   "install_names":[
1181     { "name":"/S/L/F/Foo.framework/Foo" }
1182   ],
1183   "flags":[
1184     { "attributes": ["sim_support"] }
1185   ]
1186 }})";
1187 
1188   Expected<TBDFile> Result =
1189       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1190   EXPECT_TRUE(!!Result);
1191   Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 1));
1192   TBDFile ReadFile = std::move(Result.get());
1193   EXPECT_EQ(FileType::TBD_V5, ReadFile->getFileType());
1194   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1195             ReadFile->getInstallName());
1196   EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end());
1197   EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget);
1198   EXPECT_TRUE(ReadFile->hasSimulatorSupport());
1199 }
1200 
1201 TEST(TBDv5, NotForSharedCache) {
1202   static const char TBDv5File[] = R"({
1203 "tapi_tbd_version": 5,
1204 "main_library": {
1205   "target_info": [
1206     {
1207       "target": "arm64-macos",
1208       "min_deployment": "11.1"
1209     }
1210   ],
1211   "install_names":[
1212     { "name":"/S/L/F/Foo.framework/Foo" }
1213   ],
1214   "flags":[
1215     { "attributes": ["not_for_dyld_shared_cache"] }
1216   ]
1217 }})";
1218 
1219   Expected<TBDFile> Result =
1220       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1221   EXPECT_TRUE(!!Result);
1222   Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 1));
1223   TBDFile ReadFile = std::move(Result.get());
1224   EXPECT_EQ(FileType::TBD_V5, ReadFile->getFileType());
1225   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1226             ReadFile->getInstallName());
1227   EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end());
1228   EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget);
1229   EXPECT_FALSE(ReadFile->hasSimulatorSupport());
1230   EXPECT_TRUE(ReadFile->isOSLibNotForSharedCache());
1231 }
1232 
1233 TEST(TBDv5, MergeIF) {
1234   static const char TBDv5FileA[] = R"({
1235 "tapi_tbd_version": 5,
1236 "main_library": {
1237   "target_info": [
1238     {
1239       "target": "x86_64-macos",
1240       "min_deployment": "10.14"
1241     },
1242     {
1243       "target": "arm64-macos",
1244       "min_deployment": "10.14"
1245     },
1246     {
1247       "target": "arm64-maccatalyst",
1248       "min_deployment": "12.1"
1249     }
1250   ],
1251   "flags": [
1252     {
1253       "targets": [
1254             "x86_64-macos"
1255         ],
1256       "attributes": [
1257             "flat_namespace"
1258         ]
1259     }
1260   ],
1261   "install_names": [
1262     {
1263         "name": "/S/L/F/Foo.framework/Foo"
1264     }
1265   ],
1266   "current_versions": [
1267     {
1268         "version": "1.2"
1269     }
1270   ],
1271   "compatibility_versions": [
1272     { "version": "1.1" }
1273   ],
1274   "rpaths": [
1275     {
1276       "targets": [
1277           "x86_64-macos"
1278       ],
1279       "paths": [
1280           "@executable_path/.../Frameworks"
1281       ]
1282     }
1283   ],
1284   "parent_umbrellas": [
1285     {
1286       "umbrella": "System"
1287     }
1288   ],
1289   "allowable_clients": [
1290     {
1291         "clients": [
1292             "ClientA",
1293             "ClientB"
1294         ]
1295     }
1296   ],
1297   "reexported_libraries": [
1298     {
1299         "names": [
1300             "/u/l/l/libfoo.dylib",
1301             "/u/l/l/libbar.dylib"
1302         ]
1303     }
1304   ],
1305   "exported_symbols": [
1306     {
1307         "targets": [
1308             "x86_64-macos",
1309             "arm64-macos"
1310         ],
1311         "data": {
1312             "global": [
1313                 "_global"
1314             ],
1315             "objc_class": [
1316                 "ClassA"
1317             ],
1318             "weak": [],
1319             "thread_local": []
1320         },
1321         "text": {
1322             "global": [
1323                 "_func"
1324             ],
1325             "weak": [],
1326             "thread_local": []
1327         }
1328     },
1329     {
1330       "targets": [
1331           "x86_64-macos"
1332       ],
1333       "data": {
1334           "global": [
1335               "_globalVar"
1336           ],
1337           "objc_class": [
1338               "ClassA",
1339               "ClassB",
1340               "ClassData"
1341           ],
1342           "objc_eh_type": [
1343               "ClassA",
1344               "ClassB"
1345           ],
1346           "objc_ivar": [
1347               "ClassA.ivar1",
1348               "ClassA.ivar2",
1349               "ClassC.ivar1"
1350           ]
1351       },
1352       "text": {
1353           "global": [
1354               "_funcFoo"
1355           ]
1356       }
1357     }
1358   ],
1359   "reexported_symbols": [
1360     {
1361         "targets": [
1362             "x86_64-macos",
1363             "arm64-macos"
1364         ],
1365         "data": {
1366             "global": [
1367                 "_globalRe"
1368             ],
1369             "objc_class": [
1370                 "ClassRexport"
1371             ]
1372         },
1373         "text": {
1374             "global": [
1375                 "_funcA"
1376             ]
1377         }
1378     }
1379   ],
1380   "undefined_symbols": [
1381     {
1382         "targets": [
1383             "x86_64-macos"
1384         ],
1385         "data": {
1386             "global": [
1387                 "_globalBind"
1388             ],
1389             "weak": [
1390                 "referenced_sym"
1391             ]
1392         }
1393     }
1394   ]
1395 },
1396 "libraries": []
1397 })";
1398 
1399   static const char TBDv5FileB[] = R"({
1400 "tapi_tbd_version": 5,
1401 "main_library": {
1402   "target_info": [
1403     {
1404       "target": "x86_64-macos",
1405       "min_deployment": "10.14"
1406     },
1407     {
1408       "target": "arm64-macos",
1409       "min_deployment": "10.14"
1410     },
1411     {
1412       "target": "arm64-maccatalyst",
1413       "min_deployment": "12.1"
1414     }
1415   ],
1416   "flags": [
1417     {
1418       "targets": [
1419             "x86_64-macos"
1420         ],
1421       "attributes": [
1422             "flat_namespace"
1423         ]
1424     }
1425   ],
1426   "install_names": [
1427     {
1428         "name": "/S/L/F/Foo.framework/Foo"
1429     }
1430   ],
1431   "current_versions": [
1432     {
1433         "version": "1.2"
1434     }
1435   ],
1436   "compatibility_versions": [
1437     { "version": "1.1" }
1438   ],
1439   "exported_symbols": [
1440     {
1441         "targets": [
1442             "x86_64-macos",
1443             "arm64-macos"
1444         ],
1445         "data": {
1446             "global": [
1447                 "_globalZ"
1448             ],
1449             "objc_class": [
1450                 "ClassZ"
1451             ],
1452             "weak": [],
1453             "thread_local": []
1454         },
1455         "text": {
1456             "global": [
1457                 "_funcZ"
1458             ],
1459             "weak": [],
1460             "thread_local": []
1461         }
1462     },
1463     {
1464       "targets": [
1465           "x86_64-macos"
1466       ],
1467       "data": {
1468           "global": [
1469               "_globalVarZ"
1470           ],
1471           "objc_class": [
1472               "ClassZ",
1473               "ClassF"
1474           ],
1475           "objc_eh_type": [
1476               "ClassZ",
1477               "ClassF"
1478           ],
1479           "objc_ivar": [
1480               "ClassZ.ivar1",
1481               "ClassZ.ivar2",
1482               "ClassF.ivar1"
1483           ]
1484       },
1485       "text": {
1486           "global": [
1487               "_funcFooZ"
1488           ]
1489       }
1490     }
1491   ]
1492 },
1493 "libraries": []
1494 })";
1495 
1496   Expected<TBDFile> ResultA =
1497       TextAPIReader::get(MemoryBufferRef(TBDv5FileA, "Test.tbd"));
1498   EXPECT_TRUE(!!ResultA);
1499   TBDFile FileA = std::move(ResultA.get());
1500 
1501   Expected<TBDFile> ResultB =
1502       TextAPIReader::get(MemoryBufferRef(TBDv5FileB, "Test.tbd"));
1503   EXPECT_TRUE(!!ResultB);
1504   TBDFile FileB = std::move(ResultB.get());
1505 
1506   Expected<TBDFile> MergedResult = FileA->merge(FileB.get());
1507   EXPECT_TRUE(!!MergedResult);
1508   TBDFile MergedFile = std::move(MergedResult.get());
1509 
1510   EXPECT_EQ(FileType::TBD_V5, MergedFile->getFileType());
1511   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1512             MergedFile->getInstallName());
1513   TargetList AllTargets = {
1514       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
1515       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
1516       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
1517   };
1518   EXPECT_EQ(mapToPlatformSet(AllTargets), MergedFile->getPlatforms());
1519   EXPECT_EQ(mapToArchitectureSet(AllTargets), MergedFile->getArchitectures());
1520   EXPECT_EQ(PackedVersion(1, 2, 0), MergedFile->getCurrentVersion());
1521   EXPECT_EQ(PackedVersion(1, 1, 0), MergedFile->getCompatibilityVersion());
1522   EXPECT_TRUE(MergedFile->isApplicationExtensionSafe());
1523   EXPECT_FALSE(MergedFile->isTwoLevelNamespace());
1524   EXPECT_EQ(0U, MergedFile->documents().size());
1525   InterfaceFileRef ClientA("ClientA", AllTargets);
1526   InterfaceFileRef ClientB("ClientB", AllTargets);
1527   EXPECT_EQ(2U, MergedFile->allowableClients().size());
1528   EXPECT_EQ(ClientA, MergedFile->allowableClients().at(0));
1529   EXPECT_EQ(ClientB, MergedFile->allowableClients().at(1));
1530 
1531   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
1532   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
1533   EXPECT_EQ(2U, MergedFile->reexportedLibraries().size());
1534   EXPECT_EQ(ReexportA, MergedFile->reexportedLibraries().at(0));
1535   EXPECT_EQ(ReexportB, MergedFile->reexportedLibraries().at(1));
1536 
1537   TargetToAttr RPaths = {
1538       {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"},
1539   };
1540   EXPECT_EQ(RPaths, MergedFile->rpaths());
1541 
1542   TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"},
1543                             {Target(AK_arm64, PLATFORM_MACOS), "System"},
1544                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
1545   EXPECT_EQ(Umbrellas, MergedFile->umbrellas());
1546 
1547   ExportedSymbolSeq Exports, Reexports, Undefineds;
1548   for (const auto *Sym : MergedFile->symbols()) {
1549     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
1550     ExportedSymbol Temp =
1551         ExportedSymbol{Sym->getKind(),
1552                        std::string(Sym->getName()),
1553                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
1554                        Sym->isThreadLocalValue(),
1555                        Sym->isData(),
1556                        SymTargets};
1557     if (Sym->isUndefined())
1558       Undefineds.emplace_back(std::move(Temp));
1559     else
1560       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
1561                           : Exports.emplace_back(std::move(Temp));
1562   }
1563   llvm::sort(Exports);
1564   llvm::sort(Reexports);
1565   llvm::sort(Undefineds);
1566 
1567   TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS),
1568                              Target(AK_arm64, PLATFORM_MACOS)};
1569 
1570   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
1571       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
1572       {SymbolKind::GlobalSymbol,
1573        "_funcFoo",
1574        false,
1575        false,
1576        false,
1577        {Target(AK_x86_64, PLATFORM_MACOS)}},
1578       {SymbolKind::GlobalSymbol,
1579        "_funcFooZ",
1580        false,
1581        false,
1582        false,
1583        {Target(AK_x86_64, PLATFORM_MACOS)}},
1584       {SymbolKind::GlobalSymbol, "_funcZ", false, false, false, MacOSTargets},
1585       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
1586       {SymbolKind::GlobalSymbol,
1587        "_globalVar",
1588        false,
1589        false,
1590        true,
1591        {Target(AK_x86_64, PLATFORM_MACOS)}},
1592       {SymbolKind::GlobalSymbol,
1593        "_globalVarZ",
1594        false,
1595        false,
1596        true,
1597        {Target(AK_x86_64, PLATFORM_MACOS)}},
1598       {SymbolKind::GlobalSymbol, "_globalZ", false, false, true, MacOSTargets},
1599       {SymbolKind::ObjectiveCClass,
1600        "ClassA",
1601        false,
1602        false,
1603        true,
1604        {Target(AK_x86_64, PLATFORM_MACOS)}},
1605       {SymbolKind::ObjectiveCClass,
1606        "ClassB",
1607        false,
1608        false,
1609        true,
1610        {Target(AK_x86_64, PLATFORM_MACOS)}},
1611       {SymbolKind::ObjectiveCClass,
1612        "ClassData",
1613        false,
1614        false,
1615        true,
1616        {Target(AK_x86_64, PLATFORM_MACOS)}},
1617       {SymbolKind::ObjectiveCClass,
1618        "ClassF",
1619        false,
1620        false,
1621        true,
1622        {Target(AK_x86_64, PLATFORM_MACOS)}},
1623       {SymbolKind::ObjectiveCClass,
1624        "ClassZ",
1625        false,
1626        false,
1627        true,
1628        {Target(AK_x86_64, PLATFORM_MACOS)}},
1629       {SymbolKind::ObjectiveCClassEHType,
1630        "ClassA",
1631        false,
1632        false,
1633        true,
1634        {Target(AK_x86_64, PLATFORM_MACOS)}},
1635       {SymbolKind::ObjectiveCClassEHType,
1636        "ClassB",
1637        false,
1638        false,
1639        true,
1640        {Target(AK_x86_64, PLATFORM_MACOS)}},
1641       {SymbolKind::ObjectiveCClassEHType,
1642        "ClassF",
1643        false,
1644        false,
1645        true,
1646        {Target(AK_x86_64, PLATFORM_MACOS)}},
1647       {SymbolKind::ObjectiveCClassEHType,
1648        "ClassZ",
1649        false,
1650        false,
1651        true,
1652        {Target(AK_x86_64, PLATFORM_MACOS)}},
1653       {SymbolKind::ObjectiveCInstanceVariable,
1654        "ClassA.ivar1",
1655        false,
1656        false,
1657        true,
1658        {Target(AK_x86_64, PLATFORM_MACOS)}},
1659       {SymbolKind::ObjectiveCInstanceVariable,
1660        "ClassA.ivar2",
1661        false,
1662        false,
1663        true,
1664        {Target(AK_x86_64, PLATFORM_MACOS)}},
1665       {SymbolKind::ObjectiveCInstanceVariable,
1666        "ClassC.ivar1",
1667        false,
1668        false,
1669        true,
1670        {Target(AK_x86_64, PLATFORM_MACOS)}},
1671       {SymbolKind::ObjectiveCInstanceVariable,
1672        "ClassF.ivar1",
1673        false,
1674        false,
1675        true,
1676        {Target(AK_x86_64, PLATFORM_MACOS)}},
1677       {SymbolKind::ObjectiveCInstanceVariable,
1678        "ClassZ.ivar1",
1679        false,
1680        false,
1681        true,
1682        {Target(AK_x86_64, PLATFORM_MACOS)}},
1683       {SymbolKind::ObjectiveCInstanceVariable,
1684        "ClassZ.ivar2",
1685        false,
1686        false,
1687        true,
1688        {Target(AK_x86_64, PLATFORM_MACOS)}},
1689   };
1690 
1691   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
1692       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
1693       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
1694       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
1695        MacOSTargets},
1696   };
1697 
1698   std::vector<ExportedSymbol> ExpectedUndefinedSymbols = {
1699       {SymbolKind::GlobalSymbol,
1700        "_globalBind",
1701        false,
1702        false,
1703        true,
1704        {Target(AK_x86_64, PLATFORM_MACOS)}},
1705       {SymbolKind::GlobalSymbol,
1706        "referenced_sym",
1707        true,
1708        false,
1709        true,
1710        {Target(AK_x86_64, PLATFORM_MACOS)}},
1711   };
1712 
1713   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
1714   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
1715   EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size());
1716   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
1717                          std::begin(ExpectedExportedSymbols)));
1718   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
1719                          std::begin(ExpectedReexportedSymbols)));
1720   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
1721                          std::begin(ExpectedUndefinedSymbols)));
1722 }
1723 
1724 TEST(TBDv5, ExtractIF) {
1725   static const char TBDv5File[] = R"({
1726 "tapi_tbd_version": 5,
1727 "main_library": {
1728   "target_info": [
1729     {
1730       "target": "x86_64-macos",
1731       "min_deployment": "10.14"
1732     },
1733     {
1734       "target": "arm64-macos",
1735       "min_deployment": "10.14"
1736     },
1737     {
1738       "target": "arm64-maccatalyst",
1739       "min_deployment": "12.1"
1740     }
1741   ],
1742   "flags": [
1743     {
1744       "targets": [
1745             "x86_64-macos"
1746         ],
1747       "attributes": [
1748             "flat_namespace"
1749         ]
1750     }
1751   ],
1752   "install_names": [
1753     {
1754         "name": "/S/L/F/Foo.framework/Foo"
1755     }
1756   ],
1757   "current_versions": [
1758     {
1759         "version": "1.2"
1760     }
1761   ],
1762   "compatibility_versions": [
1763     { "version": "1.1" }
1764   ],
1765   "rpaths": [
1766     {
1767       "targets": [
1768           "x86_64-macos"
1769       ],
1770       "paths": [
1771           "@executable_path/.../Frameworks"
1772       ]
1773     }
1774   ],
1775   "parent_umbrellas": [
1776     {
1777       "umbrella": "System"
1778     }
1779   ],
1780   "allowable_clients": [
1781     {
1782         "clients": [
1783             "ClientA",
1784             "ClientB"
1785         ]
1786     }
1787   ],
1788   "reexported_libraries": [
1789     {
1790         "names": [
1791             "/u/l/l/libfoo.dylib",
1792             "/u/l/l/libbar.dylib"
1793         ]
1794     }
1795   ],
1796   "exported_symbols": [
1797     {
1798         "targets": [
1799             "x86_64-macos",
1800             "arm64-macos"
1801         ],
1802         "data": {
1803             "global": [
1804                 "_global"
1805             ],
1806             "objc_class": [
1807                 "ClassA"
1808             ],
1809             "weak": [],
1810             "thread_local": []
1811         },
1812         "text": {
1813             "global": [
1814                 "_func"
1815             ],
1816             "weak": [],
1817             "thread_local": []
1818         }
1819     },
1820     {
1821       "targets": [
1822           "x86_64-macos"
1823       ],
1824       "data": {
1825           "global": [
1826               "_globalVar"
1827           ],
1828           "objc_class": [
1829               "ClassA",
1830               "ClassB",
1831               "ClassData"
1832           ],
1833           "objc_eh_type": [
1834               "ClassA",
1835               "ClassB"
1836           ],
1837           "objc_ivar": [
1838               "ClassA.ivar1",
1839               "ClassA.ivar2",
1840               "ClassC.ivar1"
1841           ]
1842       },
1843       "text": {
1844           "global": [
1845               "_funcFoo"
1846           ]
1847       }
1848     }
1849   ],
1850   "reexported_symbols": [
1851     {
1852         "targets": [
1853             "x86_64-macos",
1854             "arm64-macos"
1855         ],
1856         "data": {
1857             "global": [
1858                 "_globalRe"
1859             ],
1860             "objc_class": [
1861                 "ClassRexport"
1862             ]
1863         },
1864         "text": {
1865             "global": [
1866                 "_funcA"
1867             ]
1868         }
1869     }
1870   ],
1871   "undefined_symbols": [
1872     {
1873         "targets": [
1874             "x86_64-macos"
1875         ],
1876         "data": {
1877             "global": [
1878                 "_globalBind"
1879             ],
1880             "weak": [
1881                 "referenced_sym"
1882             ]
1883         }
1884     }
1885   ]
1886 },
1887 "libraries": []
1888 })";
1889 
1890   Expected<TBDFile> Result =
1891       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1892   EXPECT_TRUE(!!Result);
1893   TBDFile File = std::move(Result.get());
1894 
1895   Expected<TBDFile> ExtractedResult = File->extract(AK_arm64);
1896   EXPECT_TRUE(!!ExtractedResult);
1897   TBDFile ExtractedFile = std::move(ExtractedResult.get());
1898 
1899   EXPECT_EQ(FileType::TBD_V5, ExtractedFile->getFileType());
1900   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1901             ExtractedFile->getInstallName());
1902 
1903   TargetList AllTargets = {
1904       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
1905       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
1906   };
1907   EXPECT_EQ(mapToPlatformSet(AllTargets), ExtractedFile->getPlatforms());
1908   EXPECT_EQ(mapToArchitectureSet(AllTargets),
1909             ExtractedFile->getArchitectures());
1910 
1911   EXPECT_EQ(PackedVersion(1, 2, 0), ExtractedFile->getCurrentVersion());
1912   EXPECT_EQ(PackedVersion(1, 1, 0), ExtractedFile->getCompatibilityVersion());
1913   EXPECT_TRUE(ExtractedFile->isApplicationExtensionSafe());
1914   EXPECT_FALSE(ExtractedFile->isTwoLevelNamespace());
1915   EXPECT_EQ(0U, ExtractedFile->documents().size());
1916 
1917   InterfaceFileRef ClientA("ClientA", AllTargets);
1918   InterfaceFileRef ClientB("ClientB", AllTargets);
1919   EXPECT_EQ(2U, ExtractedFile->allowableClients().size());
1920   EXPECT_EQ(ClientA, ExtractedFile->allowableClients().at(0));
1921   EXPECT_EQ(ClientB, ExtractedFile->allowableClients().at(1));
1922 
1923   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
1924   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
1925   EXPECT_EQ(2U, ExtractedFile->reexportedLibraries().size());
1926   EXPECT_EQ(ReexportA, ExtractedFile->reexportedLibraries().at(0));
1927   EXPECT_EQ(ReexportB, ExtractedFile->reexportedLibraries().at(1));
1928 
1929   EXPECT_EQ(0u, ExtractedFile->rpaths().size());
1930 
1931   TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"},
1932                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
1933   EXPECT_EQ(Umbrellas, ExtractedFile->umbrellas());
1934 
1935   ExportedSymbolSeq Exports, Reexports, Undefineds;
1936   for (const auto *Sym : ExtractedFile->symbols()) {
1937     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
1938     ExportedSymbol Temp =
1939         ExportedSymbol{Sym->getKind(),
1940                        std::string(Sym->getName()),
1941                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
1942                        Sym->isThreadLocalValue(),
1943                        Sym->isData(),
1944                        SymTargets};
1945     if (Sym->isUndefined())
1946       Undefineds.emplace_back(std::move(Temp));
1947     else
1948       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
1949                           : Exports.emplace_back(std::move(Temp));
1950   }
1951   llvm::sort(Exports);
1952   llvm::sort(Reexports);
1953   llvm::sort(Undefineds);
1954 
1955   TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)};
1956 
1957   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
1958       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
1959       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
1960       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
1961   };
1962   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
1963       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
1964       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
1965       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
1966        MacOSTargets},
1967   };
1968 
1969   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
1970   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
1971   EXPECT_EQ(0U, Undefineds.size());
1972   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
1973                          std::begin(ExpectedExportedSymbols)));
1974   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
1975                          std::begin(ExpectedReexportedSymbols)));
1976 }
1977 
1978 TEST(TBDv5, RemoveIF) {
1979   static const char TBDv5File[] = R"({
1980 "tapi_tbd_version": 5,
1981 "main_library": {
1982   "target_info": [
1983     {
1984       "target": "x86_64-macos",
1985       "min_deployment": "10.14"
1986     },
1987     {
1988       "target": "arm64-macos",
1989       "min_deployment": "10.14"
1990     },
1991     {
1992       "target": "arm64-maccatalyst",
1993       "min_deployment": "12.1"
1994     }
1995   ],
1996   "flags": [
1997     {
1998       "targets": [
1999             "x86_64-macos"
2000         ],
2001       "attributes": [
2002             "flat_namespace"
2003         ]
2004     }
2005   ],
2006   "install_names": [
2007     {
2008         "name": "/S/L/F/Foo.framework/Foo"
2009     }
2010   ],
2011   "current_versions": [
2012     {
2013         "version": "1.2"
2014     }
2015   ],
2016   "compatibility_versions": [
2017     { "version": "1.1" }
2018   ],
2019   "rpaths": [
2020     {
2021       "targets": [
2022           "x86_64-macos"
2023       ],
2024       "paths": [
2025           "@executable_path/.../Frameworks"
2026       ]
2027     }
2028   ],
2029   "parent_umbrellas": [
2030     {
2031       "umbrella": "System"
2032     }
2033   ],
2034   "allowable_clients": [
2035     {
2036         "clients": [
2037             "ClientA",
2038             "ClientB"
2039         ]
2040     }
2041   ],
2042   "reexported_libraries": [
2043     {
2044         "names": [
2045             "/u/l/l/libfoo.dylib",
2046             "/u/l/l/libbar.dylib"
2047         ]
2048     }
2049   ],
2050   "exported_symbols": [
2051     {
2052         "targets": [
2053             "x86_64-macos",
2054             "arm64-macos"
2055         ],
2056         "data": {
2057             "global": [
2058                 "_global"
2059             ],
2060             "objc_class": [
2061                 "ClassA"
2062             ],
2063             "weak": [],
2064             "thread_local": []
2065         },
2066         "text": {
2067             "global": [
2068                 "_func"
2069             ],
2070             "weak": [],
2071             "thread_local": []
2072         }
2073     },
2074     {
2075       "targets": [
2076           "x86_64-macos"
2077       ],
2078       "data": {
2079           "global": [
2080               "_globalVar"
2081           ],
2082           "objc_class": [
2083               "ClassA",
2084               "ClassB",
2085               "ClassData"
2086           ],
2087           "objc_eh_type": [
2088               "ClassA",
2089               "ClassB"
2090           ],
2091           "objc_ivar": [
2092               "ClassA.ivar1",
2093               "ClassA.ivar2",
2094               "ClassC.ivar1"
2095           ]
2096       },
2097       "text": {
2098           "global": [
2099               "_funcFoo"
2100           ]
2101       }
2102     }
2103   ],
2104   "reexported_symbols": [
2105     {
2106         "targets": [
2107             "x86_64-macos",
2108             "arm64-macos"
2109         ],
2110         "data": {
2111             "global": [
2112                 "_globalRe"
2113             ],
2114             "objc_class": [
2115                 "ClassRexport"
2116             ]
2117         },
2118         "text": {
2119             "global": [
2120                 "_funcA"
2121             ]
2122         }
2123     }
2124   ],
2125   "undefined_symbols": [
2126     {
2127         "targets": [
2128             "x86_64-macos"
2129         ],
2130         "data": {
2131             "global": [
2132                 "_globalBind"
2133             ],
2134             "weak": [
2135                 "referenced_sym"
2136             ]
2137         }
2138     }
2139   ]
2140 },
2141 "libraries": []
2142 })";
2143 
2144   Expected<TBDFile> Result =
2145       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
2146   EXPECT_TRUE(!!Result);
2147   TBDFile File = std::move(Result.get());
2148 
2149   Expected<TBDFile> RemovedResult = File->remove(AK_x86_64);
2150   EXPECT_TRUE(!!RemovedResult);
2151   TBDFile RemovedFile = std::move(RemovedResult.get());
2152 
2153   EXPECT_EQ(FileType::TBD_V5, RemovedFile->getFileType());
2154   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2155             RemovedFile->getInstallName());
2156 
2157   TargetList AllTargets = {
2158       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
2159       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
2160   };
2161   EXPECT_EQ(mapToPlatformSet(AllTargets), RemovedFile->getPlatforms());
2162   EXPECT_EQ(mapToArchitectureSet(AllTargets), RemovedFile->getArchitectures());
2163 
2164   EXPECT_EQ(PackedVersion(1, 2, 0), RemovedFile->getCurrentVersion());
2165   EXPECT_EQ(PackedVersion(1, 1, 0), RemovedFile->getCompatibilityVersion());
2166   EXPECT_TRUE(RemovedFile->isApplicationExtensionSafe());
2167   EXPECT_FALSE(RemovedFile->isTwoLevelNamespace());
2168   EXPECT_EQ(0U, RemovedFile->documents().size());
2169 
2170   InterfaceFileRef ClientA("ClientA", AllTargets);
2171   InterfaceFileRef ClientB("ClientB", AllTargets);
2172   EXPECT_EQ(2U, RemovedFile->allowableClients().size());
2173   EXPECT_EQ(ClientA, RemovedFile->allowableClients().at(0));
2174   EXPECT_EQ(ClientB, RemovedFile->allowableClients().at(1));
2175 
2176   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
2177   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
2178   EXPECT_EQ(2U, RemovedFile->reexportedLibraries().size());
2179   EXPECT_EQ(ReexportA, RemovedFile->reexportedLibraries().at(0));
2180   EXPECT_EQ(ReexportB, RemovedFile->reexportedLibraries().at(1));
2181 
2182   EXPECT_EQ(0u, RemovedFile->rpaths().size());
2183 
2184   TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"},
2185                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
2186   EXPECT_EQ(Umbrellas, RemovedFile->umbrellas());
2187 
2188   ExportedSymbolSeq Exports, Reexports, Undefineds;
2189   for (const auto *Sym : RemovedFile->symbols()) {
2190     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
2191     ExportedSymbol Temp =
2192         ExportedSymbol{Sym->getKind(),
2193                        std::string(Sym->getName()),
2194                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
2195                        Sym->isThreadLocalValue(),
2196                        Sym->isData(),
2197                        SymTargets};
2198     if (Sym->isUndefined())
2199       Undefineds.emplace_back(std::move(Temp));
2200     else
2201       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
2202                           : Exports.emplace_back(std::move(Temp));
2203   }
2204   llvm::sort(Exports);
2205   llvm::sort(Reexports);
2206   llvm::sort(Undefineds);
2207 
2208   TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)};
2209 
2210   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
2211       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
2212       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
2213       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
2214   };
2215   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
2216       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
2217       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
2218       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
2219        MacOSTargets},
2220   };
2221 
2222   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
2223   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
2224   EXPECT_EQ(0U, Undefineds.size());
2225   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
2226                          std::begin(ExpectedExportedSymbols)));
2227   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
2228                          std::begin(ExpectedReexportedSymbols)));
2229 }
2230 
2231 TEST(TBDv5, InlineIF) {
2232   static const char UmbrellaFile[] = R"({
2233 "tapi_tbd_version": 5,
2234 "main_library": {
2235   "target_info": [
2236     {
2237       "target": "x86_64-macos",
2238       "min_deployment": "10.14"
2239     },
2240     {
2241       "target": "arm64-macos",
2242       "min_deployment": "10.14"
2243     }
2244   ],
2245   "install_names": [
2246     {
2247         "name": "/S/L/F/Foo.framework/Foo"
2248     }
2249   ],
2250   "current_versions": [
2251     {
2252         "version": "1.2"
2253     }
2254   ],
2255   "reexported_libraries": [
2256     {
2257         "names": [
2258             "/u/l/l/libfoo.dylib",
2259             "/u/l/l/libbar.dylib"
2260         ]
2261     }
2262   ]
2263 }})";
2264 
2265   static const char ReexportFile[] = R"({
2266 "tapi_tbd_version": 5,
2267 "main_library": {
2268   "target_info": [
2269     {
2270       "target": "x86_64-macos",
2271       "min_deployment": "10.14"
2272     },
2273     {
2274       "target": "arm64-macos",
2275       "min_deployment": "10.14"
2276     }
2277   ],
2278   "install_names": [
2279     {
2280         "name" : "/u/l/l/libfoo.dylib"
2281     }
2282   ],
2283   "current_versions": [
2284     {
2285         "version": "1"
2286     }
2287   ],
2288   "rpaths": [
2289     {
2290       "targets": [
2291           "x86_64-macos"
2292       ],
2293       "paths": [
2294           "@executable_path/.../Frameworks"
2295       ]
2296     }
2297   ],
2298   "exported_symbols": [
2299     {
2300         "targets": [
2301             "x86_64-macos",
2302             "arm64-macos"
2303         ],
2304         "data": {
2305             "global": [
2306                 "_global"
2307             ],
2308             "objc_class": [
2309                 "ClassA"
2310             ],
2311             "weak": [],
2312             "thread_local": []
2313         }
2314     }
2315   ]}})";
2316 
2317   Expected<TBDFile> UmbrellaResult =
2318       TextAPIReader::get(MemoryBufferRef(UmbrellaFile, "Test.tbd"));
2319   EXPECT_TRUE(!!UmbrellaResult);
2320   TBDFile Umbrella = std::move(UmbrellaResult.get());
2321 
2322   Expected<TBDFile> ReexportResult =
2323       TextAPIReader::get(MemoryBufferRef(ReexportFile, "Test.tbd"));
2324   EXPECT_TRUE(!!ReexportResult);
2325   TBDReexportFile Reexport = std::move(ReexportResult.get());
2326   Umbrella->inlineLibrary(Reexport);
2327 
2328   EXPECT_EQ(FileType::TBD_V5, Umbrella->getFileType());
2329   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2330             Umbrella->getInstallName());
2331 
2332   TargetList AllTargets = {
2333       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
2334       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
2335   };
2336   EXPECT_EQ(mapToPlatformSet(AllTargets), Umbrella->getPlatforms());
2337   EXPECT_EQ(mapToArchitectureSet(AllTargets), Umbrella->getArchitectures());
2338 
2339   EXPECT_EQ(PackedVersion(1, 2, 0), Umbrella->getCurrentVersion());
2340   EXPECT_EQ(PackedVersion(1, 0, 0), Umbrella->getCompatibilityVersion());
2341   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
2342   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
2343   EXPECT_EQ(2U, Umbrella->reexportedLibraries().size());
2344   EXPECT_EQ(ReexportA, Umbrella->reexportedLibraries().at(0));
2345   EXPECT_EQ(ReexportB, Umbrella->reexportedLibraries().at(1));
2346   EXPECT_EQ(1U, Umbrella->documents().size());
2347 
2348   TBDReexportFile Document = Umbrella->documents().front();
2349   EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document->getInstallName());
2350   EXPECT_EQ(0U, Document->getSwiftABIVersion());
2351   EXPECT_TRUE(Document->isTwoLevelNamespace());
2352   EXPECT_TRUE(Document->isApplicationExtensionSafe());
2353   EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCurrentVersion());
2354   EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCompatibilityVersion());
2355 
2356   ExportedSymbolSeq Exports;
2357   for (const auto *Sym : Document->symbols()) {
2358     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
2359     Exports.emplace_back(
2360         ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
2361                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
2362                        Sym->isThreadLocalValue(), Sym->isData(), SymTargets});
2363   }
2364   llvm::sort(Exports);
2365 
2366   ExportedSymbolSeq ExpectedExports = {
2367       {SymbolKind::GlobalSymbol, "_global", false, false, true, AllTargets},
2368       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, AllTargets},
2369   };
2370   EXPECT_EQ(ExpectedExports.size(), Exports.size());
2371   EXPECT_TRUE(
2372       std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports)));
2373 }
2374 } // end namespace TBDv5
2375