xref: /llvm-project/llvm/unittests/TextAPI/TextStubV5Tests.cpp (revision 03506bc0a99fd53d0f4e3d0bd77eb2f7bad96102)
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       {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
271       {EncodeKind::GlobalSymbol,
272        "_funcFoo",
273        false,
274        false,
275        false,
276        {Target(AK_x86_64, PLATFORM_MACOS)}},
277       {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
278       {EncodeKind::GlobalSymbol,
279        "_globalVar",
280        false,
281        false,
282        true,
283        {Target(AK_x86_64, PLATFORM_MACOS)}},
284       {EncodeKind::ObjectiveCClass,
285        "ClassA",
286        false,
287        false,
288        true,
289        {Target(AK_x86_64, PLATFORM_MACOS)}},
290       {EncodeKind::ObjectiveCClass,
291        "ClassB",
292        false,
293        false,
294        true,
295        {Target(AK_x86_64, PLATFORM_MACOS)}},
296       {EncodeKind::ObjectiveCClass,
297        "ClassData",
298        false,
299        false,
300        true,
301        {Target(AK_x86_64, PLATFORM_MACOS)}},
302       {EncodeKind::ObjectiveCClassEHType,
303        "ClassA",
304        false,
305        false,
306        true,
307        {Target(AK_x86_64, PLATFORM_MACOS)}},
308       {EncodeKind::ObjectiveCClassEHType,
309        "ClassB",
310        false,
311        false,
312        true,
313        {Target(AK_x86_64, PLATFORM_MACOS)}},
314       {EncodeKind::ObjectiveCInstanceVariable,
315        "ClassA.ivar1",
316        false,
317        false,
318        true,
319        {Target(AK_x86_64, PLATFORM_MACOS)}},
320       {EncodeKind::ObjectiveCInstanceVariable,
321        "ClassA.ivar2",
322        false,
323        false,
324        true,
325        {Target(AK_x86_64, PLATFORM_MACOS)}},
326       {EncodeKind::ObjectiveCInstanceVariable,
327        "ClassC.ivar1",
328        false,
329        false,
330        true,
331        {Target(AK_x86_64, PLATFORM_MACOS)}},
332   };
333   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
334       {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
335       {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
336       {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true,
337        MacOSTargets},
338   };
339 
340   std::vector<ExportedSymbol> ExpectedUndefinedSymbols = {
341       {EncodeKind::GlobalSymbol,
342        "_globalBind",
343        false,
344        false,
345        true,
346        {Target(AK_x86_64, PLATFORM_MACOS)}},
347       {EncodeKind::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(EncodeKind::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       {EncodeKind::GlobalSymbol, "_funcFoo", false, false, false, {iOSTarget}},
528       {EncodeKind::GlobalSymbol, "_globalVar", false, true, true, {iOSTarget}},
529       {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, {iOSTarget}},
530       {EncodeKind::ObjectiveCClass, "ClassB", false, false, true, {iOSTarget}},
531       {EncodeKind::ObjectiveCClass,
532        "ClassData",
533        false,
534        false,
535        true,
536        {iOSTarget}},
537       {EncodeKind::ObjectiveCClassEHType,
538        "ClassA",
539        false,
540        false,
541        true,
542        {iOSTarget}},
543       {EncodeKind::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("@executable_path/.../Frameworks", AllTargets[0]);
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(EncodeKind::GlobalSymbol, "_global",
738                  {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data);
739   File.addSymbol(EncodeKind::GlobalSymbol, "_func",
740                  {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Text);
741   File.addSymbol(EncodeKind::ObjectiveCClass, "ClassA",
742                  {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data);
743   File.addSymbol(EncodeKind::GlobalSymbol, "_funcFoo", {AllTargets[0]},
744                  Flags | SymbolFlags::Text);
745   File.addSymbol(EncodeKind::GlobalSymbol, "_globalVar", {AllTargets[0]},
746                  Flags | SymbolFlags::Data);
747   File.addSymbol(EncodeKind::ObjectiveCClass, "ClassData", {AllTargets[0]},
748                  Flags | SymbolFlags::Data);
749   File.addSymbol(EncodeKind::ObjectiveCClassEHType, "ClassA", {AllTargets[0]},
750                  Flags | SymbolFlags::Data);
751   File.addSymbol(EncodeKind::ObjectiveCClassEHType, "ClassB", {AllTargets[0]},
752                  Flags | SymbolFlags::Data);
753   File.addSymbol(EncodeKind::ObjectiveCInstanceVariable, "ClassA.ivar1",
754                  {AllTargets[0]}, Flags | SymbolFlags::Data);
755   File.addSymbol(EncodeKind::ObjectiveCInstanceVariable, "ClassA.ivar2",
756                  {AllTargets[0]}, Flags | SymbolFlags::Data);
757   File.addSymbol(EncodeKind::ObjectiveCInstanceVariable, "ClassC.ivar1",
758                  {AllTargets[0]}, Flags | SymbolFlags::Data);
759 
760   // Reexports.
761   Flags = SymbolFlags::Rexported;
762   File.addSymbol(EncodeKind::GlobalSymbol, "_globalRe", AllTargets,
763                  Flags | SymbolFlags::Data);
764   File.addSymbol(EncodeKind::GlobalSymbol, "_funcA", AllTargets,
765                  Flags | SymbolFlags::Text);
766   File.addSymbol(EncodeKind::ObjectiveCClass, "ClassRexport", AllTargets,
767                  Flags | SymbolFlags::Data);
768 
769   // Undefineds.
770   Flags = SymbolFlags::Undefined;
771   File.addSymbol(EncodeKind::GlobalSymbol, "_globalBind", {AllTargets[0]},
772                  Flags | SymbolFlags::Data);
773   File.addSymbol(EncodeKind::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("@executable_path/.../Frameworks", AllTargets[0]);
901   for (const auto &Targ : AllTargets)
902     NestedFile.addReexportedLibrary("@rpath/libfoo.dylib", Targ);
903   NestedFile.addSymbol(EncodeKind::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(EncodeKind::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, ObjCInterfaces) {
1234   static const char TBDv5File[] = R"({
1235 "tapi_tbd_version": 5,
1236 "main_library": {
1237   "target_info": [
1238     {
1239       "target": "arm64-ios-simulator",
1240       "min_deployment": "14.0"
1241     }
1242   ],
1243   "install_names":[
1244     { "name":"/S/L/F/Foo.framework/Foo" }
1245   ],
1246   "exported_symbols": [
1247     {
1248       "data": {
1249          "global": [
1250               "_global",
1251               "_OBJC_METACLASS_$_Standalone",
1252               "_OBJC_CLASS_$_Standalone2"
1253           ],
1254           "weak": ["_OBJC_EHTYPE_$_NSObject"],
1255           "objc_class": [
1256               "ClassA",
1257               "ClassB"
1258           ],
1259           "objc_eh_type": ["ClassA"]
1260       }
1261     }]
1262 }})";
1263 
1264   Expected<TBDFile> Result =
1265       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1266   EXPECT_TRUE(!!Result);
1267   TBDFile File = std::move(Result.get());
1268   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
1269   Target ExpectedTarget =
1270       Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(14, 0));
1271   EXPECT_EQ(*File->targets().begin(), ExpectedTarget);
1272 
1273   // Check Symbols.
1274   ExportedSymbolSeq Exports;
1275   for (const auto *Sym : File->symbols()) {
1276     ExportedSymbol Temp =
1277         ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
1278                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
1279                        Sym->isThreadLocalValue(), Sym->isData()};
1280     Exports.emplace_back(std::move(Temp));
1281   }
1282   llvm::sort(Exports);
1283 
1284   std::vector<ExportedSymbol> ExpectedExports = {
1285       {EncodeKind::GlobalSymbol, "_OBJC_CLASS_$_Standalone2", false, false,
1286        true},
1287       {EncodeKind::GlobalSymbol, "_OBJC_EHTYPE_$_NSObject", true, false, true},
1288       {EncodeKind::GlobalSymbol, "_OBJC_METACLASS_$_Standalone", false, false,
1289        true},
1290       {EncodeKind::GlobalSymbol, "_global", false, false, true},
1291       {EncodeKind::ObjectiveCClass, "ClassA", false, false, true},
1292       {EncodeKind::ObjectiveCClass, "ClassB", false, false, true},
1293       {EncodeKind::ObjectiveCClassEHType, "ClassA", false, false, true}};
1294 
1295   EXPECT_EQ(ExpectedExports.size(), Exports.size());
1296   EXPECT_TRUE(
1297       std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports)));
1298 
1299   SmallString<4096> Buffer;
1300   raw_svector_ostream OS(Buffer);
1301   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
1302   EXPECT_TRUE(!WriteResult);
1303 
1304   Expected<TBDFile> Output =
1305       TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
1306   EXPECT_TRUE(!!Output);
1307   TBDFile WriteResultFile = std::move(Output.get());
1308   EXPECT_EQ(*File, *WriteResultFile);
1309 }
1310 
1311 TEST(TBDv5, MergeIF) {
1312   static const char TBDv5FileA[] = R"({
1313 "tapi_tbd_version": 5,
1314 "main_library": {
1315   "target_info": [
1316     {
1317       "target": "x86_64-macos",
1318       "min_deployment": "10.14"
1319     },
1320     {
1321       "target": "arm64-macos",
1322       "min_deployment": "10.14"
1323     },
1324     {
1325       "target": "arm64-maccatalyst",
1326       "min_deployment": "12.1"
1327     }
1328   ],
1329   "flags": [
1330     {
1331       "targets": [
1332             "x86_64-macos"
1333         ],
1334       "attributes": [
1335             "flat_namespace"
1336         ]
1337     }
1338   ],
1339   "install_names": [
1340     {
1341         "name": "/S/L/F/Foo.framework/Foo"
1342     }
1343   ],
1344   "current_versions": [
1345     {
1346         "version": "1.2"
1347     }
1348   ],
1349   "compatibility_versions": [
1350     { "version": "1.1" }
1351   ],
1352   "rpaths": [
1353     {
1354       "targets": [
1355           "x86_64-macos"
1356       ],
1357       "paths": [
1358           "@executable_path/.../Frameworks"
1359       ]
1360     }
1361   ],
1362   "parent_umbrellas": [
1363     {
1364       "umbrella": "System"
1365     }
1366   ],
1367   "allowable_clients": [
1368     {
1369         "clients": [
1370             "ClientA",
1371             "ClientB"
1372         ]
1373     }
1374   ],
1375   "reexported_libraries": [
1376     {
1377         "names": [
1378             "/u/l/l/libfoo.dylib",
1379             "/u/l/l/libbar.dylib"
1380         ]
1381     }
1382   ],
1383   "exported_symbols": [
1384     {
1385         "targets": [
1386             "x86_64-macos",
1387             "arm64-macos"
1388         ],
1389         "data": {
1390             "global": [
1391                 "_global"
1392             ],
1393             "objc_class": [
1394                 "ClassA"
1395             ],
1396             "weak": [],
1397             "thread_local": []
1398         },
1399         "text": {
1400             "global": [
1401                 "_func"
1402             ],
1403             "weak": [],
1404             "thread_local": []
1405         }
1406     },
1407     {
1408       "targets": [
1409           "x86_64-macos"
1410       ],
1411       "data": {
1412           "global": [
1413               "_globalVar"
1414           ],
1415           "objc_class": [
1416               "ClassA",
1417               "ClassB",
1418               "ClassData"
1419           ],
1420           "objc_eh_type": [
1421               "ClassA",
1422               "ClassB"
1423           ],
1424           "objc_ivar": [
1425               "ClassA.ivar1",
1426               "ClassA.ivar2",
1427               "ClassC.ivar1"
1428           ]
1429       },
1430       "text": {
1431           "global": [
1432               "_funcFoo"
1433           ]
1434       }
1435     }
1436   ],
1437   "reexported_symbols": [
1438     {
1439         "targets": [
1440             "x86_64-macos",
1441             "arm64-macos"
1442         ],
1443         "data": {
1444             "global": [
1445                 "_globalRe"
1446             ],
1447             "objc_class": [
1448                 "ClassRexport"
1449             ]
1450         },
1451         "text": {
1452             "global": [
1453                 "_funcA"
1454             ]
1455         }
1456     }
1457   ],
1458   "undefined_symbols": [
1459     {
1460         "targets": [
1461             "x86_64-macos"
1462         ],
1463         "data": {
1464             "global": [
1465                 "_globalBind"
1466             ],
1467             "weak": [
1468                 "referenced_sym"
1469             ]
1470         }
1471     }
1472   ]
1473 },
1474 "libraries": []
1475 })";
1476 
1477   static const char TBDv5FileB[] = R"({
1478 "tapi_tbd_version": 5,
1479 "main_library": {
1480   "target_info": [
1481     {
1482       "target": "x86_64-macos",
1483       "min_deployment": "10.14"
1484     },
1485     {
1486       "target": "arm64-macos",
1487       "min_deployment": "10.14"
1488     },
1489     {
1490       "target": "arm64-maccatalyst",
1491       "min_deployment": "12.1"
1492     }
1493   ],
1494   "flags": [
1495     {
1496       "targets": [
1497             "x86_64-macos"
1498         ],
1499       "attributes": [
1500             "flat_namespace"
1501         ]
1502     }
1503   ],
1504   "install_names": [
1505     {
1506         "name": "/S/L/F/Foo.framework/Foo"
1507     }
1508   ],
1509   "current_versions": [
1510     {
1511         "version": "1.2"
1512     }
1513   ],
1514   "compatibility_versions": [
1515     { "version": "1.1" }
1516   ],
1517   "exported_symbols": [
1518     {
1519         "targets": [
1520             "x86_64-macos",
1521             "arm64-macos"
1522         ],
1523         "data": {
1524             "global": [
1525                 "_globalZ"
1526             ],
1527             "objc_class": [
1528                 "ClassZ"
1529             ],
1530             "weak": [],
1531             "thread_local": []
1532         },
1533         "text": {
1534             "global": [
1535                 "_funcZ"
1536             ],
1537             "weak": [],
1538             "thread_local": []
1539         }
1540     },
1541     {
1542       "targets": [
1543           "x86_64-macos"
1544       ],
1545       "data": {
1546           "global": [
1547               "_globalVarZ"
1548           ],
1549           "objc_class": [
1550               "ClassZ",
1551               "ClassF"
1552           ],
1553           "objc_eh_type": [
1554               "ClassZ",
1555               "ClassF"
1556           ],
1557           "objc_ivar": [
1558               "ClassZ.ivar1",
1559               "ClassZ.ivar2",
1560               "ClassF.ivar1"
1561           ]
1562       },
1563       "text": {
1564           "global": [
1565               "_funcFooZ"
1566           ]
1567       }
1568     }
1569   ]
1570 },
1571 "libraries": []
1572 })";
1573 
1574   Expected<TBDFile> ResultA =
1575       TextAPIReader::get(MemoryBufferRef(TBDv5FileA, "Test.tbd"));
1576   EXPECT_TRUE(!!ResultA);
1577   TBDFile FileA = std::move(ResultA.get());
1578 
1579   Expected<TBDFile> ResultB =
1580       TextAPIReader::get(MemoryBufferRef(TBDv5FileB, "Test.tbd"));
1581   EXPECT_TRUE(!!ResultB);
1582   TBDFile FileB = std::move(ResultB.get());
1583 
1584   Expected<TBDFile> MergedResult = FileA->merge(FileB.get());
1585   EXPECT_TRUE(!!MergedResult);
1586   TBDFile MergedFile = std::move(MergedResult.get());
1587 
1588   EXPECT_EQ(FileType::TBD_V5, MergedFile->getFileType());
1589   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1590             MergedFile->getInstallName());
1591   TargetList AllTargets = {
1592       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
1593       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
1594       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
1595   };
1596   EXPECT_EQ(mapToPlatformSet(AllTargets), MergedFile->getPlatforms());
1597   EXPECT_EQ(mapToArchitectureSet(AllTargets), MergedFile->getArchitectures());
1598   EXPECT_EQ(PackedVersion(1, 2, 0), MergedFile->getCurrentVersion());
1599   EXPECT_EQ(PackedVersion(1, 1, 0), MergedFile->getCompatibilityVersion());
1600   EXPECT_TRUE(MergedFile->isApplicationExtensionSafe());
1601   EXPECT_FALSE(MergedFile->isTwoLevelNamespace());
1602   EXPECT_EQ(0U, MergedFile->documents().size());
1603   InterfaceFileRef ClientA("ClientA", AllTargets);
1604   InterfaceFileRef ClientB("ClientB", AllTargets);
1605   EXPECT_EQ(2U, MergedFile->allowableClients().size());
1606   EXPECT_EQ(ClientA, MergedFile->allowableClients().at(0));
1607   EXPECT_EQ(ClientB, MergedFile->allowableClients().at(1));
1608 
1609   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
1610   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
1611   EXPECT_EQ(2U, MergedFile->reexportedLibraries().size());
1612   EXPECT_EQ(ReexportA, MergedFile->reexportedLibraries().at(0));
1613   EXPECT_EQ(ReexportB, MergedFile->reexportedLibraries().at(1));
1614 
1615   TargetToAttr RPaths = {
1616       {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"},
1617   };
1618   EXPECT_EQ(RPaths, MergedFile->rpaths());
1619 
1620   TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"},
1621                             {Target(AK_arm64, PLATFORM_MACOS), "System"},
1622                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
1623   EXPECT_EQ(Umbrellas, MergedFile->umbrellas());
1624 
1625   ExportedSymbolSeq Exports, Reexports, Undefineds;
1626   for (const auto *Sym : MergedFile->symbols()) {
1627     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
1628     ExportedSymbol Temp =
1629         ExportedSymbol{Sym->getKind(),
1630                        std::string(Sym->getName()),
1631                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
1632                        Sym->isThreadLocalValue(),
1633                        Sym->isData(),
1634                        SymTargets};
1635     if (Sym->isUndefined())
1636       Undefineds.emplace_back(std::move(Temp));
1637     else
1638       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
1639                           : Exports.emplace_back(std::move(Temp));
1640   }
1641   llvm::sort(Exports);
1642   llvm::sort(Reexports);
1643   llvm::sort(Undefineds);
1644 
1645   TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS),
1646                              Target(AK_arm64, PLATFORM_MACOS)};
1647 
1648   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
1649       {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
1650       {EncodeKind::GlobalSymbol,
1651        "_funcFoo",
1652        false,
1653        false,
1654        false,
1655        {Target(AK_x86_64, PLATFORM_MACOS)}},
1656       {EncodeKind::GlobalSymbol,
1657        "_funcFooZ",
1658        false,
1659        false,
1660        false,
1661        {Target(AK_x86_64, PLATFORM_MACOS)}},
1662       {EncodeKind::GlobalSymbol, "_funcZ", false, false, false, MacOSTargets},
1663       {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
1664       {EncodeKind::GlobalSymbol,
1665        "_globalVar",
1666        false,
1667        false,
1668        true,
1669        {Target(AK_x86_64, PLATFORM_MACOS)}},
1670       {EncodeKind::GlobalSymbol,
1671        "_globalVarZ",
1672        false,
1673        false,
1674        true,
1675        {Target(AK_x86_64, PLATFORM_MACOS)}},
1676       {EncodeKind::GlobalSymbol, "_globalZ", false, false, true, MacOSTargets},
1677       {EncodeKind::ObjectiveCClass,
1678        "ClassA",
1679        false,
1680        false,
1681        true,
1682        {Target(AK_x86_64, PLATFORM_MACOS)}},
1683       {EncodeKind::ObjectiveCClass,
1684        "ClassB",
1685        false,
1686        false,
1687        true,
1688        {Target(AK_x86_64, PLATFORM_MACOS)}},
1689       {EncodeKind::ObjectiveCClass,
1690        "ClassData",
1691        false,
1692        false,
1693        true,
1694        {Target(AK_x86_64, PLATFORM_MACOS)}},
1695       {EncodeKind::ObjectiveCClass,
1696        "ClassF",
1697        false,
1698        false,
1699        true,
1700        {Target(AK_x86_64, PLATFORM_MACOS)}},
1701       {EncodeKind::ObjectiveCClass,
1702        "ClassZ",
1703        false,
1704        false,
1705        true,
1706        {Target(AK_x86_64, PLATFORM_MACOS)}},
1707       {EncodeKind::ObjectiveCClassEHType,
1708        "ClassA",
1709        false,
1710        false,
1711        true,
1712        {Target(AK_x86_64, PLATFORM_MACOS)}},
1713       {EncodeKind::ObjectiveCClassEHType,
1714        "ClassB",
1715        false,
1716        false,
1717        true,
1718        {Target(AK_x86_64, PLATFORM_MACOS)}},
1719       {EncodeKind::ObjectiveCClassEHType,
1720        "ClassF",
1721        false,
1722        false,
1723        true,
1724        {Target(AK_x86_64, PLATFORM_MACOS)}},
1725       {EncodeKind::ObjectiveCClassEHType,
1726        "ClassZ",
1727        false,
1728        false,
1729        true,
1730        {Target(AK_x86_64, PLATFORM_MACOS)}},
1731       {EncodeKind::ObjectiveCInstanceVariable,
1732        "ClassA.ivar1",
1733        false,
1734        false,
1735        true,
1736        {Target(AK_x86_64, PLATFORM_MACOS)}},
1737       {EncodeKind::ObjectiveCInstanceVariable,
1738        "ClassA.ivar2",
1739        false,
1740        false,
1741        true,
1742        {Target(AK_x86_64, PLATFORM_MACOS)}},
1743       {EncodeKind::ObjectiveCInstanceVariable,
1744        "ClassC.ivar1",
1745        false,
1746        false,
1747        true,
1748        {Target(AK_x86_64, PLATFORM_MACOS)}},
1749       {EncodeKind::ObjectiveCInstanceVariable,
1750        "ClassF.ivar1",
1751        false,
1752        false,
1753        true,
1754        {Target(AK_x86_64, PLATFORM_MACOS)}},
1755       {EncodeKind::ObjectiveCInstanceVariable,
1756        "ClassZ.ivar1",
1757        false,
1758        false,
1759        true,
1760        {Target(AK_x86_64, PLATFORM_MACOS)}},
1761       {EncodeKind::ObjectiveCInstanceVariable,
1762        "ClassZ.ivar2",
1763        false,
1764        false,
1765        true,
1766        {Target(AK_x86_64, PLATFORM_MACOS)}},
1767   };
1768 
1769   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
1770       {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
1771       {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
1772       {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true,
1773        MacOSTargets},
1774   };
1775 
1776   std::vector<ExportedSymbol> ExpectedUndefinedSymbols = {
1777       {EncodeKind::GlobalSymbol,
1778        "_globalBind",
1779        false,
1780        false,
1781        true,
1782        {Target(AK_x86_64, PLATFORM_MACOS)}},
1783       {EncodeKind::GlobalSymbol,
1784        "referenced_sym",
1785        true,
1786        false,
1787        true,
1788        {Target(AK_x86_64, PLATFORM_MACOS)}},
1789   };
1790 
1791   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
1792   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
1793   EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size());
1794   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
1795                          std::begin(ExpectedExportedSymbols)));
1796   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
1797                          std::begin(ExpectedReexportedSymbols)));
1798   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
1799                          std::begin(ExpectedUndefinedSymbols)));
1800 }
1801 
1802 TEST(TBDv5, ExtractIF) {
1803   static const char TBDv5File[] = R"({
1804 "tapi_tbd_version": 5,
1805 "main_library": {
1806   "target_info": [
1807     {
1808       "target": "x86_64-macos",
1809       "min_deployment": "10.14"
1810     },
1811     {
1812       "target": "arm64-macos",
1813       "min_deployment": "10.14"
1814     },
1815     {
1816       "target": "arm64-maccatalyst",
1817       "min_deployment": "12.1"
1818     }
1819   ],
1820   "flags": [
1821     {
1822       "targets": [
1823             "x86_64-macos"
1824         ],
1825       "attributes": [
1826             "flat_namespace"
1827         ]
1828     }
1829   ],
1830   "install_names": [
1831     {
1832         "name": "/S/L/F/Foo.framework/Foo"
1833     }
1834   ],
1835   "current_versions": [
1836     {
1837         "version": "1.2"
1838     }
1839   ],
1840   "compatibility_versions": [
1841     { "version": "1.1" }
1842   ],
1843   "rpaths": [
1844     {
1845       "targets": [
1846           "x86_64-macos"
1847       ],
1848       "paths": [
1849           "@executable_path/.../Frameworks"
1850       ]
1851     }
1852   ],
1853   "parent_umbrellas": [
1854     {
1855       "umbrella": "System"
1856     }
1857   ],
1858   "allowable_clients": [
1859     {
1860         "clients": [
1861             "ClientA",
1862             "ClientB"
1863         ]
1864     }
1865   ],
1866   "reexported_libraries": [
1867     {
1868         "names": [
1869             "/u/l/l/libfoo.dylib",
1870             "/u/l/l/libbar.dylib"
1871         ]
1872     }
1873   ],
1874   "exported_symbols": [
1875     {
1876         "targets": [
1877             "x86_64-macos",
1878             "arm64-macos"
1879         ],
1880         "data": {
1881             "global": [
1882                 "_global"
1883             ],
1884             "objc_class": [
1885                 "ClassA"
1886             ],
1887             "weak": [],
1888             "thread_local": []
1889         },
1890         "text": {
1891             "global": [
1892                 "_func"
1893             ],
1894             "weak": [],
1895             "thread_local": []
1896         }
1897     },
1898     {
1899       "targets": [
1900           "x86_64-macos"
1901       ],
1902       "data": {
1903           "global": [
1904               "_globalVar"
1905           ],
1906           "objc_class": [
1907               "ClassA",
1908               "ClassB",
1909               "ClassData"
1910           ],
1911           "objc_eh_type": [
1912               "ClassA",
1913               "ClassB"
1914           ],
1915           "objc_ivar": [
1916               "ClassA.ivar1",
1917               "ClassA.ivar2",
1918               "ClassC.ivar1"
1919           ]
1920       },
1921       "text": {
1922           "global": [
1923               "_funcFoo"
1924           ]
1925       }
1926     }
1927   ],
1928   "reexported_symbols": [
1929     {
1930         "targets": [
1931             "x86_64-macos",
1932             "arm64-macos"
1933         ],
1934         "data": {
1935             "global": [
1936                 "_globalRe"
1937             ],
1938             "objc_class": [
1939                 "ClassRexport"
1940             ]
1941         },
1942         "text": {
1943             "global": [
1944                 "_funcA"
1945             ]
1946         }
1947     }
1948   ],
1949   "undefined_symbols": [
1950     {
1951         "targets": [
1952             "x86_64-macos"
1953         ],
1954         "data": {
1955             "global": [
1956                 "_globalBind"
1957             ],
1958             "weak": [
1959                 "referenced_sym"
1960             ]
1961         }
1962     }
1963   ]
1964 },
1965 "libraries": []
1966 })";
1967 
1968   Expected<TBDFile> Result =
1969       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1970   EXPECT_TRUE(!!Result);
1971   TBDFile File = std::move(Result.get());
1972 
1973   Expected<TBDFile> ExtractedResult = File->extract(AK_arm64);
1974   EXPECT_TRUE(!!ExtractedResult);
1975   TBDFile ExtractedFile = std::move(ExtractedResult.get());
1976 
1977   EXPECT_EQ(FileType::TBD_V5, ExtractedFile->getFileType());
1978   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1979             ExtractedFile->getInstallName());
1980 
1981   TargetList AllTargets = {
1982       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
1983       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
1984   };
1985   EXPECT_EQ(mapToPlatformSet(AllTargets), ExtractedFile->getPlatforms());
1986   EXPECT_EQ(mapToArchitectureSet(AllTargets),
1987             ExtractedFile->getArchitectures());
1988 
1989   EXPECT_EQ(PackedVersion(1, 2, 0), ExtractedFile->getCurrentVersion());
1990   EXPECT_EQ(PackedVersion(1, 1, 0), ExtractedFile->getCompatibilityVersion());
1991   EXPECT_TRUE(ExtractedFile->isApplicationExtensionSafe());
1992   EXPECT_FALSE(ExtractedFile->isTwoLevelNamespace());
1993   EXPECT_EQ(0U, ExtractedFile->documents().size());
1994 
1995   InterfaceFileRef ClientA("ClientA", AllTargets);
1996   InterfaceFileRef ClientB("ClientB", AllTargets);
1997   EXPECT_EQ(2U, ExtractedFile->allowableClients().size());
1998   EXPECT_EQ(ClientA, ExtractedFile->allowableClients().at(0));
1999   EXPECT_EQ(ClientB, ExtractedFile->allowableClients().at(1));
2000 
2001   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
2002   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
2003   EXPECT_EQ(2U, ExtractedFile->reexportedLibraries().size());
2004   EXPECT_EQ(ReexportA, ExtractedFile->reexportedLibraries().at(0));
2005   EXPECT_EQ(ReexportB, ExtractedFile->reexportedLibraries().at(1));
2006 
2007   EXPECT_EQ(0u, ExtractedFile->rpaths().size());
2008 
2009   TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"},
2010                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
2011   EXPECT_EQ(Umbrellas, ExtractedFile->umbrellas());
2012 
2013   ExportedSymbolSeq Exports, Reexports, Undefineds;
2014   for (const auto *Sym : ExtractedFile->symbols()) {
2015     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
2016     ExportedSymbol Temp =
2017         ExportedSymbol{Sym->getKind(),
2018                        std::string(Sym->getName()),
2019                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
2020                        Sym->isThreadLocalValue(),
2021                        Sym->isData(),
2022                        SymTargets};
2023     if (Sym->isUndefined())
2024       Undefineds.emplace_back(std::move(Temp));
2025     else
2026       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
2027                           : Exports.emplace_back(std::move(Temp));
2028   }
2029   llvm::sort(Exports);
2030   llvm::sort(Reexports);
2031   llvm::sort(Undefineds);
2032 
2033   TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)};
2034 
2035   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
2036       {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
2037       {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
2038       {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
2039   };
2040   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
2041       {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
2042       {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
2043       {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true,
2044        MacOSTargets},
2045   };
2046 
2047   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
2048   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
2049   EXPECT_EQ(0U, Undefineds.size());
2050   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
2051                          std::begin(ExpectedExportedSymbols)));
2052   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
2053                          std::begin(ExpectedReexportedSymbols)));
2054 }
2055 
2056 TEST(TBDv5, RemoveIF) {
2057   static const char TBDv5File[] = R"({
2058 "tapi_tbd_version": 5,
2059 "main_library": {
2060   "target_info": [
2061     {
2062       "target": "x86_64-macos",
2063       "min_deployment": "10.14"
2064     },
2065     {
2066       "target": "arm64-macos",
2067       "min_deployment": "10.14"
2068     },
2069     {
2070       "target": "arm64-maccatalyst",
2071       "min_deployment": "12.1"
2072     }
2073   ],
2074   "flags": [
2075     {
2076       "targets": [
2077             "x86_64-macos"
2078         ],
2079       "attributes": [
2080             "flat_namespace",
2081             "not_for_dyld_shared_cache"
2082         ]
2083     }
2084   ],
2085   "install_names": [
2086     {
2087         "name": "/S/L/F/Foo.framework/Foo"
2088     }
2089   ],
2090   "current_versions": [
2091     {
2092         "version": "1.2"
2093     }
2094   ],
2095   "compatibility_versions": [
2096     { "version": "1.1" }
2097   ],
2098   "rpaths": [
2099     {
2100       "targets": [
2101           "x86_64-macos"
2102       ],
2103       "paths": [
2104           "@executable_path/.../Frameworks"
2105       ]
2106     }
2107   ],
2108   "parent_umbrellas": [
2109     {
2110       "umbrella": "System"
2111     }
2112   ],
2113   "allowable_clients": [
2114     {
2115         "clients": [
2116             "ClientA",
2117             "ClientB"
2118         ]
2119     }
2120   ],
2121   "reexported_libraries": [
2122     {
2123         "names": [
2124             "/u/l/l/libfoo.dylib",
2125             "/u/l/l/libbar.dylib"
2126         ]
2127     }
2128   ],
2129   "exported_symbols": [
2130     {
2131         "targets": [
2132             "x86_64-macos",
2133             "arm64-macos"
2134         ],
2135         "data": {
2136             "global": [
2137                 "_global"
2138             ],
2139             "objc_class": [
2140                 "ClassA"
2141             ],
2142             "weak": [],
2143             "thread_local": []
2144         },
2145         "text": {
2146             "global": [
2147                 "_func"
2148             ],
2149             "weak": [],
2150             "thread_local": []
2151         }
2152     },
2153     {
2154       "targets": [
2155           "x86_64-macos"
2156       ],
2157       "data": {
2158           "global": [
2159               "_globalVar"
2160           ],
2161           "objc_class": [
2162               "ClassA",
2163               "ClassB",
2164               "ClassData"
2165           ],
2166           "objc_eh_type": [
2167               "ClassA",
2168               "ClassB"
2169           ],
2170           "objc_ivar": [
2171               "ClassA.ivar1",
2172               "ClassA.ivar2",
2173               "ClassC.ivar1"
2174           ]
2175       },
2176       "text": {
2177           "global": [
2178               "_funcFoo"
2179           ]
2180       }
2181     }
2182   ],
2183   "reexported_symbols": [
2184     {
2185         "targets": [
2186             "x86_64-macos",
2187             "arm64-macos"
2188         ],
2189         "data": {
2190             "global": [
2191                 "_globalRe"
2192             ],
2193             "objc_class": [
2194                 "ClassRexport"
2195             ]
2196         },
2197         "text": {
2198             "global": [
2199                 "_funcA"
2200             ]
2201         }
2202     }
2203   ],
2204   "undefined_symbols": [
2205     {
2206         "targets": [
2207             "x86_64-macos"
2208         ],
2209         "data": {
2210             "global": [
2211                 "_globalBind"
2212             ],
2213             "weak": [
2214                 "referenced_sym"
2215             ]
2216         }
2217     }
2218   ]
2219 },
2220 "libraries": []
2221 })";
2222 
2223   Expected<TBDFile> Result =
2224       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
2225   EXPECT_TRUE(!!Result);
2226   TBDFile File = std::move(Result.get());
2227 
2228   Expected<TBDFile> RemovedResult = File->remove(AK_x86_64);
2229   EXPECT_TRUE(!!RemovedResult);
2230   TBDFile RemovedFile = std::move(RemovedResult.get());
2231 
2232   EXPECT_EQ(FileType::TBD_V5, RemovedFile->getFileType());
2233   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2234             RemovedFile->getInstallName());
2235 
2236   TargetList AllTargets = {
2237       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
2238       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
2239   };
2240   EXPECT_EQ(mapToPlatformSet(AllTargets), RemovedFile->getPlatforms());
2241   EXPECT_EQ(mapToArchitectureSet(AllTargets), RemovedFile->getArchitectures());
2242 
2243   EXPECT_EQ(PackedVersion(1, 2, 0), RemovedFile->getCurrentVersion());
2244   EXPECT_EQ(PackedVersion(1, 1, 0), RemovedFile->getCompatibilityVersion());
2245   EXPECT_TRUE(RemovedFile->isApplicationExtensionSafe());
2246   EXPECT_TRUE(RemovedFile->isOSLibNotForSharedCache());
2247   EXPECT_FALSE(RemovedFile->isTwoLevelNamespace());
2248   EXPECT_EQ(0U, RemovedFile->documents().size());
2249 
2250   InterfaceFileRef ClientA("ClientA", AllTargets);
2251   InterfaceFileRef ClientB("ClientB", AllTargets);
2252   EXPECT_EQ(2U, RemovedFile->allowableClients().size());
2253   EXPECT_EQ(ClientA, RemovedFile->allowableClients().at(0));
2254   EXPECT_EQ(ClientB, RemovedFile->allowableClients().at(1));
2255 
2256   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
2257   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
2258   EXPECT_EQ(2U, RemovedFile->reexportedLibraries().size());
2259   EXPECT_EQ(ReexportA, RemovedFile->reexportedLibraries().at(0));
2260   EXPECT_EQ(ReexportB, RemovedFile->reexportedLibraries().at(1));
2261 
2262   EXPECT_EQ(0u, RemovedFile->rpaths().size());
2263 
2264   TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"},
2265                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
2266   EXPECT_EQ(Umbrellas, RemovedFile->umbrellas());
2267 
2268   ExportedSymbolSeq Exports, Reexports, Undefineds;
2269   for (const auto *Sym : RemovedFile->symbols()) {
2270     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
2271     ExportedSymbol Temp =
2272         ExportedSymbol{Sym->getKind(),
2273                        std::string(Sym->getName()),
2274                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
2275                        Sym->isThreadLocalValue(),
2276                        Sym->isData(),
2277                        SymTargets};
2278     if (Sym->isUndefined())
2279       Undefineds.emplace_back(std::move(Temp));
2280     else
2281       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
2282                           : Exports.emplace_back(std::move(Temp));
2283   }
2284   llvm::sort(Exports);
2285   llvm::sort(Reexports);
2286   llvm::sort(Undefineds);
2287 
2288   TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)};
2289 
2290   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
2291       {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
2292       {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
2293       {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
2294   };
2295   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
2296       {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
2297       {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
2298       {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true,
2299        MacOSTargets},
2300   };
2301 
2302   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
2303   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
2304   EXPECT_EQ(0U, Undefineds.size());
2305   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
2306                          std::begin(ExpectedExportedSymbols)));
2307   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
2308                          std::begin(ExpectedReexportedSymbols)));
2309 }
2310 
2311 TEST(TBDv5, InlineIF) {
2312   static const char UmbrellaFile[] = R"({
2313 "tapi_tbd_version": 5,
2314 "main_library": {
2315   "target_info": [
2316     {
2317       "target": "x86_64-macos",
2318       "min_deployment": "10.14"
2319     },
2320     {
2321       "target": "arm64-macos",
2322       "min_deployment": "10.14"
2323     }
2324   ],
2325   "install_names": [
2326     {
2327         "name": "/S/L/F/Foo.framework/Foo"
2328     }
2329   ],
2330   "current_versions": [
2331     {
2332         "version": "1.2"
2333     }
2334   ],
2335   "reexported_libraries": [
2336     {
2337         "names": [
2338             "/u/l/l/libfoo.dylib",
2339             "/u/l/l/libbar.dylib"
2340         ]
2341     }
2342   ]
2343 }})";
2344 
2345   static const char ReexportFile[] = R"({
2346 "tapi_tbd_version": 5,
2347 "main_library": {
2348   "target_info": [
2349     {
2350       "target": "x86_64-macos",
2351       "min_deployment": "10.14"
2352     },
2353     {
2354       "target": "arm64-macos",
2355       "min_deployment": "10.14"
2356     }
2357   ],
2358   "install_names": [
2359     {
2360         "name" : "/u/l/l/libfoo.dylib"
2361     }
2362   ],
2363   "current_versions": [
2364     {
2365         "version": "1"
2366     }
2367   ],
2368   "rpaths": [
2369     {
2370       "targets": [
2371           "x86_64-macos"
2372       ],
2373       "paths": [
2374           "@executable_path/.../Frameworks"
2375       ]
2376     }
2377   ],
2378   "exported_symbols": [
2379     {
2380         "targets": [
2381             "x86_64-macos",
2382             "arm64-macos"
2383         ],
2384         "data": {
2385             "global": [
2386                 "_global"
2387             ],
2388             "objc_class": [
2389                 "ClassA"
2390             ],
2391             "weak": [],
2392             "thread_local": []
2393         }
2394     }
2395   ]}})";
2396 
2397   Expected<TBDFile> UmbrellaResult =
2398       TextAPIReader::get(MemoryBufferRef(UmbrellaFile, "Test.tbd"));
2399   EXPECT_TRUE(!!UmbrellaResult);
2400   TBDFile Umbrella = std::move(UmbrellaResult.get());
2401 
2402   Expected<TBDFile> ReexportResult =
2403       TextAPIReader::get(MemoryBufferRef(ReexportFile, "Test.tbd"));
2404   EXPECT_TRUE(!!ReexportResult);
2405   TBDReexportFile Reexport = std::move(ReexportResult.get());
2406   Umbrella->inlineLibrary(Reexport);
2407 
2408   EXPECT_EQ(FileType::TBD_V5, Umbrella->getFileType());
2409   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2410             Umbrella->getInstallName());
2411 
2412   TargetList AllTargets = {
2413       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
2414       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
2415   };
2416   EXPECT_EQ(mapToPlatformSet(AllTargets), Umbrella->getPlatforms());
2417   EXPECT_EQ(mapToArchitectureSet(AllTargets), Umbrella->getArchitectures());
2418 
2419   EXPECT_EQ(PackedVersion(1, 2, 0), Umbrella->getCurrentVersion());
2420   EXPECT_EQ(PackedVersion(1, 0, 0), Umbrella->getCompatibilityVersion());
2421   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
2422   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
2423   EXPECT_EQ(2U, Umbrella->reexportedLibraries().size());
2424   EXPECT_EQ(ReexportA, Umbrella->reexportedLibraries().at(0));
2425   EXPECT_EQ(ReexportB, Umbrella->reexportedLibraries().at(1));
2426   EXPECT_EQ(1U, Umbrella->documents().size());
2427 
2428   TBDReexportFile Document = Umbrella->documents().front();
2429   EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document->getInstallName());
2430   EXPECT_EQ(0U, Document->getSwiftABIVersion());
2431   EXPECT_TRUE(Document->isTwoLevelNamespace());
2432   EXPECT_TRUE(Document->isApplicationExtensionSafe());
2433   EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCurrentVersion());
2434   EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCompatibilityVersion());
2435 
2436   ExportedSymbolSeq Exports;
2437   for (const auto *Sym : Document->symbols()) {
2438     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
2439     Exports.emplace_back(
2440         ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
2441                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
2442                        Sym->isThreadLocalValue(), Sym->isData(), SymTargets});
2443   }
2444   llvm::sort(Exports);
2445 
2446   ExportedSymbolSeq ExpectedExports = {
2447       {EncodeKind::GlobalSymbol, "_global", false, false, true, AllTargets},
2448       {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, AllTargets},
2449   };
2450   EXPECT_EQ(ExpectedExports.size(), Exports.size());
2451   EXPECT_TRUE(
2452       std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports)));
2453 }
2454 } // end namespace TBDv5
2455