1 //===-- TextStubV5Tests.cpp - TBD V5 File Test ----------------------------===//
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
7 //===-----------------------------------------------------------------------===/
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"
18 using namespace llvm::MachO
;
22 TEST(TBDv5
, ReadFile
) {
23 static const char TBDv5File
[] = R
"({
24 "tapi_tbd_version
": 5,
28 "target
": "x86_64
-macos
",
29 "min_deployment
": "10.14"
32 "target
": "arm64
-macos
",
33 "min_deployment
": "10.14"
36 "target
": "arm64
-maccatalyst
",
37 "min_deployment
": "12.1"
52 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
60 "compatibility_versions
": [
69 "@executable_path
/.../Frameworks
"
78 "allowable_clients
": [
86 "reexported_libraries
": [
89 "/u
/l
/l
/libfoo
.dylib
",
148 "reexported_symbols
": [
169 "undefined_symbols
": [
188 MemoryBufferRef InputBuf
= MemoryBufferRef(TBDv5File
, "Test.tbd");
189 Expected
<FileType
> ExpectedFT
= TextAPIReader::canRead(InputBuf
);
190 EXPECT_TRUE(!!ExpectedFT
);
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());
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)),
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
);
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_EQ(0U, File
->documents().size());
223 InterfaceFileRef
ClientA("ClientA", AllTargets
);
224 InterfaceFileRef
ClientB("ClientB", AllTargets
);
225 EXPECT_EQ(2U, File
->allowableClients().size());
226 EXPECT_EQ(ClientA
, File
->allowableClients().at(0));
227 EXPECT_EQ(ClientB
, File
->allowableClients().at(1));
229 InterfaceFileRef
ReexportA("/u/l/l/libbar.dylib", AllTargets
);
230 InterfaceFileRef
ReexportB("/u/l/l/libfoo.dylib", AllTargets
);
231 EXPECT_EQ(2U, File
->reexportedLibraries().size());
232 EXPECT_EQ(ReexportA
, File
->reexportedLibraries().at(0));
233 EXPECT_EQ(ReexportB
, File
->reexportedLibraries().at(1));
235 TargetToAttr RPaths
= {
236 {Target(AK_x86_64
, PLATFORM_MACOS
), "@executable_path/.../Frameworks"},
238 EXPECT_EQ(RPaths
, File
->rpaths());
240 TargetToAttr Umbrellas
= {{Target(AK_x86_64
, PLATFORM_MACOS
), "System"},
241 {Target(AK_arm64
, PLATFORM_MACOS
), "System"},
242 {Target(AK_arm64
, PLATFORM_MACCATALYST
), "System"}};
243 EXPECT_EQ(Umbrellas
, File
->umbrellas());
245 ExportedSymbolSeq Exports
, Reexports
, Undefineds
;
246 for (const auto *Sym
: File
->symbols()) {
247 TargetList SymTargets
{Sym
->targets().begin(), Sym
->targets().end()};
248 ExportedSymbol Temp
=
249 ExportedSymbol
{Sym
->getKind(),
250 std::string(Sym
->getName()),
251 Sym
->isWeakDefined() || Sym
->isWeakReferenced(),
252 Sym
->isThreadLocalValue(),
255 if (Sym
->isUndefined())
256 Undefineds
.emplace_back(std::move(Temp
));
258 Sym
->isReexported() ? Reexports
.emplace_back(std::move(Temp
))
259 : Exports
.emplace_back(std::move(Temp
));
262 llvm::sort(Reexports
);
263 llvm::sort(Undefineds
);
265 TargetList MacOSTargets
= {Target(AK_x86_64
, PLATFORM_MACOS
),
266 Target(AK_arm64
, PLATFORM_MACOS
)};
268 std::vector
<ExportedSymbol
> ExpectedExportedSymbols
= {
269 {SymbolKind::GlobalSymbol
, "_func", false, false, false, MacOSTargets
},
270 {SymbolKind::GlobalSymbol
,
275 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
276 {SymbolKind::GlobalSymbol
, "_global", false, false, true, MacOSTargets
},
277 {SymbolKind::GlobalSymbol
,
282 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
283 {SymbolKind::ObjectiveCClass
,
288 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
289 {SymbolKind::ObjectiveCClass
,
294 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
295 {SymbolKind::ObjectiveCClass
,
300 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
301 {SymbolKind::ObjectiveCClassEHType
,
306 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
307 {SymbolKind::ObjectiveCClassEHType
,
312 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
313 {SymbolKind::ObjectiveCInstanceVariable
,
318 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
319 {SymbolKind::ObjectiveCInstanceVariable
,
324 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
325 {SymbolKind::ObjectiveCInstanceVariable
,
330 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
332 std::vector
<ExportedSymbol
> ExpectedReexportedSymbols
= {
333 {SymbolKind::GlobalSymbol
, "_funcA", false, false, false, MacOSTargets
},
334 {SymbolKind::GlobalSymbol
, "_globalRe", false, false, true, MacOSTargets
},
335 {SymbolKind::ObjectiveCClass
, "ClassRexport", false, false, true,
339 std::vector
<ExportedSymbol
> ExpectedUndefinedSymbols
= {
340 {SymbolKind::GlobalSymbol
,
345 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
346 {SymbolKind::GlobalSymbol
,
351 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
354 EXPECT_EQ(ExpectedExportedSymbols
.size(), Exports
.size());
355 EXPECT_EQ(ExpectedReexportedSymbols
.size(), Reexports
.size());
356 EXPECT_EQ(ExpectedUndefinedSymbols
.size(), Undefineds
.size());
357 EXPECT_TRUE(std::equal(Exports
.begin(), Exports
.end(),
358 std::begin(ExpectedExportedSymbols
)));
359 EXPECT_TRUE(std::equal(Reexports
.begin(), Reexports
.end(),
360 std::begin(ExpectedReexportedSymbols
)));
361 EXPECT_TRUE(std::equal(Undefineds
.begin(), Undefineds
.end(),
362 std::begin(ExpectedUndefinedSymbols
)));
365 File
->getSymbol(SymbolKind::GlobalSymbol
, "_globalBind").has_value());
368 TEST(TBDv5
, ReadMultipleTargets
) {
369 static const char TBDv5File
[] = R
"({
370 "tapi_tbd_version
": 5,
374 "target
": "x86_64
-macos
",
375 "min_deployment
": "10.14"
378 "target
": "arm64
-macos
",
379 "min_deployment
": "10.14"
382 "target
": "arm64
-maccatalyst
",
383 "min_deployment
": "12.1"
387 { "name
":"/usr
/lib
/libFoo
.dylib
" }
389 "swift_abi
":[ { "abi
":8 } ],
390 "reexported_libraries
": [
392 "targets
": [ "x86_64
-maccatalyst
" ],
394 "/u
/l
/l
/libfoo
.dylib
",
395 "/u
/l
/l
/libbar
.dylib
"
399 "targets
": [ "arm64
-maccatalyst
" ],
400 "names
": [ "/u
/l
/l
/libArmOnly
.dylib
" ]
406 Expected
<TBDFile
> Result
=
407 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
408 EXPECT_TRUE(!!Result
);
409 TBDFile File
= std::move(Result
.get());
410 EXPECT_EQ(FileType::TBD_V5
, File
->getFileType());
411 EXPECT_EQ(std::string("/usr/lib/libFoo.dylib"), File
->getInstallName());
412 EXPECT_TRUE(File
->isApplicationExtensionSafe());
413 EXPECT_TRUE(File
->isTwoLevelNamespace());
414 EXPECT_EQ(PackedVersion(1, 0, 0), File
->getCurrentVersion());
415 EXPECT_EQ(PackedVersion(1, 0, 0), File
->getCompatibilityVersion());
416 EXPECT_EQ(8U, File
->getSwiftABIVersion());
418 TargetList AllTargets
= {
419 Target(AK_x86_64
, PLATFORM_MACOS
, VersionTuple(10, 14)),
420 Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(10, 14)),
421 Target(AK_arm64
, PLATFORM_MACCATALYST
, VersionTuple(12, 1)),
423 EXPECT_EQ(mapToPlatformSet(AllTargets
), File
->getPlatforms());
424 EXPECT_EQ(mapToArchitectureSet(AllTargets
), File
->getArchitectures());
426 InterfaceFileRef
ReexportA("/u/l/l/libArmOnly.dylib",
427 {Target(AK_arm64
, PLATFORM_MACCATALYST
)});
428 InterfaceFileRef
ReexportB("/u/l/l/libbar.dylib",
429 {Target(AK_x86_64
, PLATFORM_MACCATALYST
)});
430 InterfaceFileRef
ReexportC("/u/l/l/libfoo.dylib",
431 {Target(AK_x86_64
, PLATFORM_MACCATALYST
)});
432 EXPECT_EQ(3U, File
->reexportedLibraries().size());
433 EXPECT_EQ(ReexportA
, File
->reexportedLibraries().at(0));
434 EXPECT_EQ(ReexportB
, File
->reexportedLibraries().at(1));
435 EXPECT_EQ(ReexportC
, File
->reexportedLibraries().at(2));
438 TEST(TBDv5
, ReadMultipleDocuments
) {
439 static const char TBDv5File
[] = R
"({
440 "tapi_tbd_version
": 5,
444 "target
": "armv7
-ios
",
445 "min_deployment
": "11.0"
449 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
451 "reexported_libraries
": [
452 { "names
": ["/u
/l
/l
/libfoo
.dylib
"] }
459 "target
": "armv7
-ios
",
460 "min_deployment
": "11.0"
464 { "name
":"/u
/l
/l
/libfoo
.dylib
" }
467 { "attributes
": ["not_app_extension_safe
"] }
469 "exported_symbols
": [
472 "thread_local
": [ "_globalVar
" ],
473 "objc_class
": [ "ClassData
", "ClassA
", "ClassB
"],
474 "objc_eh_type
": [ "ClassA
", "ClassB
" ]
477 "global
": [ "_funcFoo
" ]
484 Expected
<TBDFile
> Result
=
485 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
486 EXPECT_TRUE(!!Result
);
487 TBDFile File
= std::move(Result
.get());
488 EXPECT_EQ(FileType::TBD_V5
, File
->getFileType());
489 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File
->getInstallName());
490 EXPECT_TRUE(File
->isTwoLevelNamespace());
491 EXPECT_TRUE(File
->isApplicationExtensionSafe());
493 TargetList
Targets(File
->targets().begin(), File
->targets().end());
494 Target
iOSTarget(AK_armv7
, PLATFORM_IOS
, VersionTuple(11, 0));
495 EXPECT_EQ(TargetList
{iOSTarget
}, Targets
);
496 std::vector
<const Symbol
*> Symbols(File
->symbols().begin(),
497 File
->symbols().end());
498 EXPECT_EQ(0U, Symbols
.size());
500 InterfaceFileRef
Reexport("/u/l/l/libfoo.dylib", {iOSTarget
});
501 EXPECT_EQ(1U, File
->reexportedLibraries().size());
502 EXPECT_EQ(Reexport
, File
->reexportedLibraries().at(0));
504 // Check inlined library.
505 EXPECT_EQ(1U, File
->documents().size());
506 TBDReexportFile Document
= File
->documents().front();
507 Targets
= {Document
->targets().begin(), Document
->targets().end()};
508 EXPECT_EQ(TargetList
{iOSTarget
}, Targets
);
509 EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document
->getInstallName());
510 EXPECT_EQ(0U, Document
->getSwiftABIVersion());
511 EXPECT_TRUE(Document
->isTwoLevelNamespace());
512 EXPECT_FALSE(Document
->isApplicationExtensionSafe());
514 ExportedSymbolSeq Exports
;
515 for (const auto *Sym
: Document
->symbols())
516 Exports
.emplace_back(
517 ExportedSymbol
{Sym
->getKind(),
518 std::string(Sym
->getName()),
519 Sym
->isWeakDefined() || Sym
->isWeakReferenced(),
520 Sym
->isThreadLocalValue(),
525 ExportedSymbolSeq ExpectedExports
= {
526 {SymbolKind::GlobalSymbol
, "_funcFoo", false, false, false, {iOSTarget
}},
527 {SymbolKind::GlobalSymbol
, "_globalVar", false, true, true, {iOSTarget
}},
528 {SymbolKind::ObjectiveCClass
, "ClassA", false, false, true, {iOSTarget
}},
529 {SymbolKind::ObjectiveCClass
, "ClassB", false, false, true, {iOSTarget
}},
530 {SymbolKind::ObjectiveCClass
,
536 {SymbolKind::ObjectiveCClassEHType
,
542 {SymbolKind::ObjectiveCClassEHType
,
550 EXPECT_EQ(ExpectedExports
.size(), Exports
.size());
552 std::equal(Exports
.begin(), Exports
.end(), std::begin(ExpectedExports
)));
555 TEST(TBDv5
, WriteFile
) {
556 static const char TBDv5File
[] = R
"({
557 "tapi_tbd_version
": 5,
561 "target
": "x86_64
-macos
",
562 "min_deployment
": "10.14"
565 "target
": "arm64
-macos
",
566 "min_deployment
": "10.14"
569 "target
": "arm64
-maccatalyst
",
570 "min_deployment
": "12.1"
575 "name
": "@rpath
/S
/L
/F
/Foo
.framework
/Foo
"
578 "current_versions
": [
583 "compatibility_versions
": [
599 "@executable_path
/.../Frameworks
"
603 "parent_umbrellas
": [
608 "allowable_clients
": [
616 "reexported_libraries
": [
619 "/u
/l
/l
/libfoo
.dylib
",
620 "/u
/l
/l
/libbar
.dylib
"
624 "exported_symbols
": [
678 "reexported_symbols
": [
695 "undefined_symbols
": [
713 File
.setFileType(FileType::TBD_V5
);
715 TargetList AllTargets
= {
716 Target(AK_x86_64
, PLATFORM_MACOS
, VersionTuple(10, 14)),
717 Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(10, 14)),
718 Target(AK_arm64
, PLATFORM_MACCATALYST
, VersionTuple(12, 1)),
720 File
.addTargets(AllTargets
);
721 File
.setInstallName("@rpath/S/L/F/Foo.framework/Foo");
722 File
.setCurrentVersion(PackedVersion(1, 2, 0));
723 File
.setCompatibilityVersion(PackedVersion(1, 1, 0));
724 File
.addRPath(AllTargets
[0], "@executable_path/.../Frameworks");
726 for (const auto &Targ
: AllTargets
) {
727 File
.addParentUmbrella(Targ
, "System");
728 File
.addAllowableClient("ClientA", Targ
);
729 File
.addAllowableClient("ClientB", Targ
);
730 File
.addReexportedLibrary("/u/l/l/libfoo.dylib", Targ
);
731 File
.addReexportedLibrary("/u/l/l/libbar.dylib", Targ
);
734 SymbolFlags Flags
= SymbolFlags::None
;
736 File
.addSymbol(SymbolKind::GlobalSymbol
, "_global",
737 {AllTargets
[0], AllTargets
[1]}, Flags
| SymbolFlags::Data
);
738 File
.addSymbol(SymbolKind::GlobalSymbol
, "_func",
739 {AllTargets
[0], AllTargets
[1]}, Flags
| SymbolFlags::Text
);
740 File
.addSymbol(SymbolKind::ObjectiveCClass
, "ClassA",
741 {AllTargets
[0], AllTargets
[1]}, Flags
| SymbolFlags::Data
);
742 File
.addSymbol(SymbolKind::GlobalSymbol
, "_funcFoo", {AllTargets
[0]},
743 Flags
| SymbolFlags::Text
);
744 File
.addSymbol(SymbolKind::GlobalSymbol
, "_globalVar", {AllTargets
[0]},
745 Flags
| SymbolFlags::Data
);
746 File
.addSymbol(SymbolKind::ObjectiveCClass
, "ClassData", {AllTargets
[0]},
747 Flags
| SymbolFlags::Data
);
748 File
.addSymbol(SymbolKind::ObjectiveCClassEHType
, "ClassA", {AllTargets
[0]},
749 Flags
| SymbolFlags::Data
);
750 File
.addSymbol(SymbolKind::ObjectiveCClassEHType
, "ClassB", {AllTargets
[0]},
751 Flags
| SymbolFlags::Data
);
752 File
.addSymbol(SymbolKind::ObjectiveCInstanceVariable
, "ClassA.ivar1",
753 {AllTargets
[0]}, Flags
| SymbolFlags::Data
);
754 File
.addSymbol(SymbolKind::ObjectiveCInstanceVariable
, "ClassA.ivar2",
755 {AllTargets
[0]}, Flags
| SymbolFlags::Data
);
756 File
.addSymbol(SymbolKind::ObjectiveCInstanceVariable
, "ClassC.ivar1",
757 {AllTargets
[0]}, Flags
| SymbolFlags::Data
);
760 Flags
= SymbolFlags::Rexported
;
761 File
.addSymbol(SymbolKind::GlobalSymbol
, "_globalRe", AllTargets
,
762 Flags
| SymbolFlags::Data
);
763 File
.addSymbol(SymbolKind::GlobalSymbol
, "_funcA", AllTargets
,
764 Flags
| SymbolFlags::Text
);
765 File
.addSymbol(SymbolKind::ObjectiveCClass
, "ClassRexport", AllTargets
,
766 Flags
| SymbolFlags::Data
);
769 Flags
= SymbolFlags::Undefined
;
770 File
.addSymbol(SymbolKind::GlobalSymbol
, "_globalBind", {AllTargets
[0]},
771 Flags
| SymbolFlags::Data
);
772 File
.addSymbol(SymbolKind::GlobalSymbol
, "referenced_sym", {AllTargets
[0]},
773 Flags
| SymbolFlags::Data
| SymbolFlags::WeakReferenced
);
775 File
.setTwoLevelNamespace(false);
776 File
.setApplicationExtensionSafe(true);
778 // Write out file then process it back into IF and compare equality
779 // against TBDv5File.
780 SmallString
<4096> Buffer
;
781 raw_svector_ostream
OS(Buffer
);
782 Error Result
= TextAPIWriter::writeToStream(OS
, File
);
783 EXPECT_FALSE(Result
);
785 Expected
<TBDFile
> Input
=
786 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Input.tbd"));
787 EXPECT_TRUE(!!Input
);
788 TBDFile InputFile
= std::move(Input
.get());
790 Expected
<TBDFile
> Output
=
791 TextAPIReader::get(MemoryBufferRef(Buffer
, "Output.tbd"));
792 EXPECT_TRUE(!!Output
);
793 TBDFile OutputFile
= std::move(Output
.get());
794 EXPECT_EQ(*InputFile
, *OutputFile
);
797 TEST(TBDv5
, WriteMultipleDocuments
) {
798 static const char TBDv5File
[] = R
"({
799 "tapi_tbd_version
": 5,
803 "target
": "armv7
-ios
",
804 "min_deployment
": "11.0"
808 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
810 "reexported_libraries
": [
811 { "names
": ["/u
/l
/l
/libfoo
.dylib
"]
819 "target
": "armv7
-ios
",
820 "min_deployment
": "11.0"
823 "target
": "armv7s
-ios
",
824 "min_deployment
": "11.0"
828 { "name
":"/u
/l
/l
/libfoo
.dylib
" }
830 "current_versions
": [
841 "@executable_path
/.../Frameworks
"
844 "reexported_libraries
": [ { "names
": ["@rpath
/libfoo
.dylib
"] } ],
846 { "attributes
": ["not_app_extension_safe
"] }
848 "exported_symbols
": [
851 "global
": [ "_funcFoo
" ]
859 "target
": "armv7
-ios
",
860 "min_deployment
": "11.0"
864 { "name
":"@rpath
/libfoo
.dylib
" }
866 "exported_symbols
": [
869 "global
": [ "_varFooBaz
" ]
877 File
.setFileType(FileType::TBD_V5
);
879 TargetList AllTargets
= {
880 Target(AK_armv7
, PLATFORM_IOS
, VersionTuple(11, 0)),
881 Target(AK_armv7s
, PLATFORM_IOS
, VersionTuple(11, 0)),
883 File
.setInstallName("/S/L/F/Foo.framework/Foo");
884 File
.addTarget(AllTargets
[0]);
885 File
.setCurrentVersion(PackedVersion(1, 0, 0));
886 File
.setCompatibilityVersion(PackedVersion(1, 0, 0));
887 File
.addReexportedLibrary("/u/l/l/libfoo.dylib", AllTargets
[0]);
888 File
.setTwoLevelNamespace();
889 File
.setApplicationExtensionSafe(true);
891 InterfaceFile NestedFile
;
892 NestedFile
.setFileType(FileType::TBD_V5
);
893 NestedFile
.setInstallName("/u/l/l/libfoo.dylib");
894 NestedFile
.addTargets(AllTargets
);
895 NestedFile
.setCompatibilityVersion(PackedVersion(1, 0, 0));
896 NestedFile
.setTwoLevelNamespace();
897 NestedFile
.setApplicationExtensionSafe(false);
898 NestedFile
.setCurrentVersion(PackedVersion(2, 1, 1));
899 NestedFile
.addRPath(AllTargets
[0], "@executable_path/.../Frameworks");
900 for (const auto &Targ
: AllTargets
)
901 NestedFile
.addReexportedLibrary("@rpath/libfoo.dylib", Targ
);
902 NestedFile
.addSymbol(SymbolKind::GlobalSymbol
, "_funcFoo", AllTargets
,
904 File
.addDocument(std::make_shared
<InterfaceFile
>(std::move(NestedFile
)));
906 InterfaceFile NestedFileB
;
907 NestedFileB
.setFileType(FileType::TBD_V5
);
908 NestedFileB
.setInstallName("@rpath/libfoo.dylib");
909 NestedFileB
.addTarget(AllTargets
[0]);
910 NestedFileB
.setCompatibilityVersion(PackedVersion(1, 0, 0));
911 NestedFileB
.setCurrentVersion(PackedVersion(1, 0, 0));
912 NestedFileB
.setTwoLevelNamespace();
913 NestedFileB
.setApplicationExtensionSafe(true);
914 NestedFileB
.addSymbol(SymbolKind::GlobalSymbol
, "_varFooBaz", {AllTargets
[0]},
916 File
.addDocument(std::make_shared
<InterfaceFile
>(std::move(NestedFileB
)));
918 // Write out file then process it back into IF and compare equality
919 // against TBDv5File.
920 SmallString
<4096> Buffer
;
921 raw_svector_ostream
OS(Buffer
);
922 Error Result
= TextAPIWriter::writeToStream(OS
, File
, FileType::Invalid
,
924 EXPECT_FALSE(Result
);
926 Expected
<TBDFile
> Input
=
927 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Input.tbd"));
928 EXPECT_TRUE(!!Input
);
929 TBDFile InputFile
= std::move(Input
.get());
931 Expected
<TBDFile
> Output
=
932 TextAPIReader::get(MemoryBufferRef(Buffer
, "Output.tbd"));
933 EXPECT_TRUE(!!Output
);
934 TBDFile OutputFile
= std::move(Output
.get());
935 EXPECT_EQ(*InputFile
, *OutputFile
);
938 TEST(TBDv5
, Target_Simulator
) {
939 static const char TBDv5File
[] = R
"({
940 "tapi_tbd_version
": 5,
944 "target
": "arm64
-ios
-simulator
",
945 "min_deployment
": "11.0"
948 "target
": "x86_64
-ios
-simulator
",
949 "min_deployment
": "11.3"
953 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
957 Expected
<TBDFile
> Result
=
958 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
959 EXPECT_TRUE(!!Result
);
960 TBDFile File
= std::move(Result
.get());
961 EXPECT_EQ(FileType::TBD_V5
, File
->getFileType());
962 TargetList ExpectedTargets
= {
963 Target(AK_x86_64
, PLATFORM_IOSSIMULATOR
, VersionTuple(11, 3)),
964 Target(AK_arm64
, PLATFORM_IOSSIMULATOR
, VersionTuple(14, 0)),
966 TargetList Targets
{File
->targets().begin(), File
->targets().end()};
968 EXPECT_EQ(Targets
, ExpectedTargets
);
970 SmallString
<4096> Buffer
;
971 raw_svector_ostream
OS(Buffer
);
972 Error WriteResult
= TextAPIWriter::writeToStream(OS
, *File
);
973 EXPECT_TRUE(!WriteResult
);
975 Expected
<TBDFile
> Output
=
976 TextAPIReader::get(MemoryBufferRef(Buffer
, "Output.tbd"));
977 EXPECT_TRUE(!!Output
);
978 TBDFile WriteResultFile
= std::move(Output
.get());
979 EXPECT_EQ(*File
, *WriteResultFile
);
982 TEST(TBDv5
, Target_UnsupportedMinOS
) {
983 static const char TBDv5File
[] = R
"({
984 "tapi_tbd_version
": 5,
988 "target
": "arm64
-macos
",
989 "min_deployment
": "10.14"
992 "target
": "x86_64
-macos
",
993 "min_deployment
": "10.14"
997 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1001 Expected
<TBDFile
> Result
=
1002 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
1003 EXPECT_TRUE(!!Result
);
1004 TBDFile File
= std::move(Result
.get());
1005 EXPECT_EQ(FileType::TBD_V5
, File
->getFileType());
1006 TargetList ExpectedTargets
= {
1007 Target(AK_x86_64
, PLATFORM_MACOS
, VersionTuple(10, 14)),
1008 Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(11, 0)),
1010 TargetList Targets
{File
->targets().begin(), File
->targets().end()};
1011 llvm::sort(Targets
);
1012 EXPECT_EQ(Targets
, ExpectedTargets
);
1014 SmallString
<4096> Buffer
;
1015 raw_svector_ostream
OS(Buffer
);
1016 Error WriteResult
= TextAPIWriter::writeToStream(OS
, *File
);
1017 EXPECT_TRUE(!WriteResult
);
1019 Expected
<TBDFile
> Output
=
1020 TextAPIReader::get(MemoryBufferRef(Buffer
, "Output.tbd"));
1021 EXPECT_TRUE(!!Output
);
1022 TBDFile WriteResultFile
= std::move(Output
.get());
1023 EXPECT_EQ(*File
, *WriteResultFile
);
1026 TEST(TBDv5
, MisspelledKey
) {
1027 static const char TBDv5File
[] = R
"({
1028 "tapi_tbd_version
": 5,
1032 "target
": "arm64
-ios
-simulator
",
1033 "min_deployment
": "11.0"
1037 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1041 Expected
<TBDFile
> Result
=
1042 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
1043 EXPECT_FALSE(!!Result
);
1044 std::string ErrorMessage
= toString(Result
.takeError());
1045 EXPECT_EQ("invalid install_names section\n", ErrorMessage
);
1048 TEST(TBDv5
, InvalidVersion
) {
1049 static const char TBDv5File
[] = R
"({
1050 "tapi_tbd_version
": 11,
1054 "target
": "arm64
-ios
-simulator
",
1055 "min_deployment
": "11.0"
1059 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1063 Expected
<TBDFile
> Result
=
1064 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
1065 EXPECT_FALSE(!!Result
);
1066 std::string ErrorMessage
= toString(Result
.takeError());
1067 EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage
);
1070 TEST(TBDv5
, MissingRequiredKey
) {
1071 static const char TBDv5File
[] = R
"({
1075 "target
": "arm64
-ios
-simulator
",
1076 "min_deployment
": "11.0"
1080 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1084 Expected
<TBDFile
> Result
=
1085 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
1086 EXPECT_FALSE(!!Result
);
1087 std::string ErrorMessage
= toString(Result
.takeError());
1088 EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage
);
1091 TEST(TBDv5
, InvalidSymbols
) {
1092 static const char TBDv5File
[] = R
"({
1093 "tapi_tbd_version
": 5,
1097 "target
": "arm64
-driverkit
",
1098 "min_deployment
": "11.0"
1102 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1104 "exported_symbols
": [
1115 Expected
<TBDFile
> Result
=
1116 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
1117 EXPECT_FALSE(!!Result
);
1118 std::string ErrorMessage
= toString(Result
.takeError());
1119 EXPECT_EQ("invalid exported_symbols section\n", ErrorMessage
);
1122 TEST(TBDv5
, DefaultMinOS
) {
1123 static const char TBDv5File
[] = R
"({
1124 "tapi_tbd_version
": 5,
1128 "target
": "arm64
-ios
-simulator
"
1132 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1136 Expected
<TBDFile
> Result
=
1137 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
1138 EXPECT_TRUE(!!Result
);
1139 TBDFile File
= std::move(Result
.get());
1140 EXPECT_EQ(FileType::TBD_V5
, File
->getFileType());
1141 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File
->getInstallName());
1142 EXPECT_TRUE(File
->targets().begin() != File
->targets().end());
1143 EXPECT_EQ(*File
->targets().begin(),
1144 Target(AK_arm64
, PLATFORM_IOSSIMULATOR
, VersionTuple(0, 0)));
1147 TEST(TBDv5
, InvalidMinOS
) {
1148 static const char TBDv5File
[] = R
"({
1149 "tapi_tbd_version
": 5,
1153 "target
": "arm64
-ios
-simulator
",
1154 "min_deployment
": "swift
-abi
"
1158 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1162 Expected
<TBDFile
> Result
=
1163 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
1164 EXPECT_FALSE(!!Result
);
1165 std::string ErrorMessage
= toString(Result
.takeError());
1166 EXPECT_EQ("invalid min_deployment section\n", ErrorMessage
);
1169 TEST(TBDv5
, SimSupport
) {
1170 static const char TBDv5File
[] = R
"({
1171 "tapi_tbd_version
": 5,
1175 "target
": "arm64
-macos
",
1176 "min_deployment
": "11.1"
1180 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1183 { "attributes
": ["sim_support
"] }
1187 Expected
<TBDFile
> Result
=
1188 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
1189 EXPECT_TRUE(!!Result
);
1190 Target ExpectedTarget
= Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(11, 1));
1191 TBDFile ReadFile
= std::move(Result
.get());
1192 EXPECT_EQ(FileType::TBD_V5
, ReadFile
->getFileType());
1193 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1194 ReadFile
->getInstallName());
1195 EXPECT_TRUE(ReadFile
->targets().begin() != ReadFile
->targets().end());
1196 EXPECT_EQ(*ReadFile
->targets().begin(), ExpectedTarget
);
1197 EXPECT_TRUE(ReadFile
->hasSimulatorSupport());
1200 TEST(TBDv5
, MergeIF
) {
1201 static const char TBDv5FileA
[] = R
"({
1202 "tapi_tbd_version
": 5,
1206 "target
": "x86_64
-macos
",
1207 "min_deployment
": "10.14"
1210 "target
": "arm64
-macos
",
1211 "min_deployment
": "10.14"
1214 "target
": "arm64
-maccatalyst
",
1215 "min_deployment
": "12.1"
1230 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
1233 "current_versions
": [
1238 "compatibility_versions
": [
1239 { "version
": "1.1" }
1247 "@executable_path
/.../Frameworks
"
1251 "parent_umbrellas
": [
1253 "umbrella
": "System
"
1256 "allowable_clients
": [
1264 "reexported_libraries
": [
1267 "/u
/l
/l
/libfoo
.dylib
",
1268 "/u
/l
/l
/libbar
.dylib
"
1272 "exported_symbols
": [
1326 "reexported_symbols
": [
1347 "undefined_symbols
": [
1366 static const char TBDv5FileB
[] = R
"({
1367 "tapi_tbd_version
": 5,
1371 "target
": "x86_64
-macos
",
1372 "min_deployment
": "10.14"
1375 "target
": "arm64
-macos
",
1376 "min_deployment
": "10.14"
1379 "target
": "arm64
-maccatalyst
",
1380 "min_deployment
": "12.1"
1395 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
1398 "current_versions
": [
1403 "compatibility_versions
": [
1404 { "version
": "1.1" }
1406 "exported_symbols
": [
1463 Expected
<TBDFile
> ResultA
=
1464 TextAPIReader::get(MemoryBufferRef(TBDv5FileA
, "Test.tbd"));
1465 EXPECT_TRUE(!!ResultA
);
1466 TBDFile FileA
= std::move(ResultA
.get());
1468 Expected
<TBDFile
> ResultB
=
1469 TextAPIReader::get(MemoryBufferRef(TBDv5FileB
, "Test.tbd"));
1470 EXPECT_TRUE(!!ResultB
);
1471 TBDFile FileB
= std::move(ResultB
.get());
1473 Expected
<TBDFile
> MergedResult
= FileA
->merge(FileB
.get());
1474 EXPECT_TRUE(!!MergedResult
);
1475 TBDFile MergedFile
= std::move(MergedResult
.get());
1477 EXPECT_EQ(FileType::TBD_V5
, MergedFile
->getFileType());
1478 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1479 MergedFile
->getInstallName());
1480 TargetList AllTargets
= {
1481 Target(AK_x86_64
, PLATFORM_MACOS
, VersionTuple(10, 14)),
1482 Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(11, 0, 0)),
1483 Target(AK_arm64
, PLATFORM_MACCATALYST
, VersionTuple(14, 0)),
1485 EXPECT_EQ(mapToPlatformSet(AllTargets
), MergedFile
->getPlatforms());
1486 EXPECT_EQ(mapToArchitectureSet(AllTargets
), MergedFile
->getArchitectures());
1487 EXPECT_EQ(PackedVersion(1, 2, 0), MergedFile
->getCurrentVersion());
1488 EXPECT_EQ(PackedVersion(1, 1, 0), MergedFile
->getCompatibilityVersion());
1489 EXPECT_TRUE(MergedFile
->isApplicationExtensionSafe());
1490 EXPECT_FALSE(MergedFile
->isTwoLevelNamespace());
1491 EXPECT_EQ(0U, MergedFile
->documents().size());
1492 InterfaceFileRef
ClientA("ClientA", AllTargets
);
1493 InterfaceFileRef
ClientB("ClientB", AllTargets
);
1494 EXPECT_EQ(2U, MergedFile
->allowableClients().size());
1495 EXPECT_EQ(ClientA
, MergedFile
->allowableClients().at(0));
1496 EXPECT_EQ(ClientB
, MergedFile
->allowableClients().at(1));
1498 InterfaceFileRef
ReexportA("/u/l/l/libbar.dylib", AllTargets
);
1499 InterfaceFileRef
ReexportB("/u/l/l/libfoo.dylib", AllTargets
);
1500 EXPECT_EQ(2U, MergedFile
->reexportedLibraries().size());
1501 EXPECT_EQ(ReexportA
, MergedFile
->reexportedLibraries().at(0));
1502 EXPECT_EQ(ReexportB
, MergedFile
->reexportedLibraries().at(1));
1504 TargetToAttr RPaths
= {
1505 {Target(AK_x86_64
, PLATFORM_MACOS
), "@executable_path/.../Frameworks"},
1507 EXPECT_EQ(RPaths
, MergedFile
->rpaths());
1509 TargetToAttr Umbrellas
= {{Target(AK_x86_64
, PLATFORM_MACOS
), "System"},
1510 {Target(AK_arm64
, PLATFORM_MACOS
), "System"},
1511 {Target(AK_arm64
, PLATFORM_MACCATALYST
), "System"}};
1512 EXPECT_EQ(Umbrellas
, MergedFile
->umbrellas());
1514 ExportedSymbolSeq Exports
, Reexports
, Undefineds
;
1515 for (const auto *Sym
: MergedFile
->symbols()) {
1516 TargetList SymTargets
{Sym
->targets().begin(), Sym
->targets().end()};
1517 ExportedSymbol Temp
=
1518 ExportedSymbol
{Sym
->getKind(),
1519 std::string(Sym
->getName()),
1520 Sym
->isWeakDefined() || Sym
->isWeakReferenced(),
1521 Sym
->isThreadLocalValue(),
1524 if (Sym
->isUndefined())
1525 Undefineds
.emplace_back(std::move(Temp
));
1527 Sym
->isReexported() ? Reexports
.emplace_back(std::move(Temp
))
1528 : Exports
.emplace_back(std::move(Temp
));
1530 llvm::sort(Exports
);
1531 llvm::sort(Reexports
);
1532 llvm::sort(Undefineds
);
1534 TargetList MacOSTargets
= {Target(AK_x86_64
, PLATFORM_MACOS
),
1535 Target(AK_arm64
, PLATFORM_MACOS
)};
1537 std::vector
<ExportedSymbol
> ExpectedExportedSymbols
= {
1538 {SymbolKind::GlobalSymbol
, "_func", false, false, false, MacOSTargets
},
1539 {SymbolKind::GlobalSymbol
,
1544 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1545 {SymbolKind::GlobalSymbol
,
1550 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1551 {SymbolKind::GlobalSymbol
, "_funcZ", false, false, false, MacOSTargets
},
1552 {SymbolKind::GlobalSymbol
, "_global", false, false, true, MacOSTargets
},
1553 {SymbolKind::GlobalSymbol
,
1558 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1559 {SymbolKind::GlobalSymbol
,
1564 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1565 {SymbolKind::GlobalSymbol
, "_globalZ", false, false, true, MacOSTargets
},
1566 {SymbolKind::ObjectiveCClass
,
1571 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1572 {SymbolKind::ObjectiveCClass
,
1577 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1578 {SymbolKind::ObjectiveCClass
,
1583 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1584 {SymbolKind::ObjectiveCClass
,
1589 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1590 {SymbolKind::ObjectiveCClass
,
1595 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1596 {SymbolKind::ObjectiveCClassEHType
,
1601 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1602 {SymbolKind::ObjectiveCClassEHType
,
1607 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1608 {SymbolKind::ObjectiveCClassEHType
,
1613 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1614 {SymbolKind::ObjectiveCClassEHType
,
1619 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1620 {SymbolKind::ObjectiveCInstanceVariable
,
1625 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1626 {SymbolKind::ObjectiveCInstanceVariable
,
1631 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1632 {SymbolKind::ObjectiveCInstanceVariable
,
1637 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1638 {SymbolKind::ObjectiveCInstanceVariable
,
1643 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1644 {SymbolKind::ObjectiveCInstanceVariable
,
1649 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1650 {SymbolKind::ObjectiveCInstanceVariable
,
1655 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1658 std::vector
<ExportedSymbol
> ExpectedReexportedSymbols
= {
1659 {SymbolKind::GlobalSymbol
, "_funcA", false, false, false, MacOSTargets
},
1660 {SymbolKind::GlobalSymbol
, "_globalRe", false, false, true, MacOSTargets
},
1661 {SymbolKind::ObjectiveCClass
, "ClassRexport", false, false, true,
1665 std::vector
<ExportedSymbol
> ExpectedUndefinedSymbols
= {
1666 {SymbolKind::GlobalSymbol
,
1671 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1672 {SymbolKind::GlobalSymbol
,
1677 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1680 EXPECT_EQ(ExpectedExportedSymbols
.size(), Exports
.size());
1681 EXPECT_EQ(ExpectedReexportedSymbols
.size(), Reexports
.size());
1682 EXPECT_EQ(ExpectedUndefinedSymbols
.size(), Undefineds
.size());
1683 EXPECT_TRUE(std::equal(Exports
.begin(), Exports
.end(),
1684 std::begin(ExpectedExportedSymbols
)));
1685 EXPECT_TRUE(std::equal(Reexports
.begin(), Reexports
.end(),
1686 std::begin(ExpectedReexportedSymbols
)));
1687 EXPECT_TRUE(std::equal(Undefineds
.begin(), Undefineds
.end(),
1688 std::begin(ExpectedUndefinedSymbols
)));
1691 TEST(TBDv5
, ExtractIF
) {
1692 static const char TBDv5File
[] = R
"({
1693 "tapi_tbd_version
": 5,
1697 "target
": "x86_64
-macos
",
1698 "min_deployment
": "10.14"
1701 "target
": "arm64
-macos
",
1702 "min_deployment
": "10.14"
1705 "target
": "arm64
-maccatalyst
",
1706 "min_deployment
": "12.1"
1721 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
1724 "current_versions
": [
1729 "compatibility_versions
": [
1730 { "version
": "1.1" }
1738 "@executable_path
/.../Frameworks
"
1742 "parent_umbrellas
": [
1744 "umbrella
": "System
"
1747 "allowable_clients
": [
1755 "reexported_libraries
": [
1758 "/u
/l
/l
/libfoo
.dylib
",
1759 "/u
/l
/l
/libbar
.dylib
"
1763 "exported_symbols
": [
1817 "reexported_symbols
": [
1838 "undefined_symbols
": [
1857 Expected
<TBDFile
> Result
=
1858 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
1859 EXPECT_TRUE(!!Result
);
1860 TBDFile File
= std::move(Result
.get());
1862 Expected
<TBDFile
> ExtractedResult
= File
->extract(AK_arm64
);
1863 EXPECT_TRUE(!!ExtractedResult
);
1864 TBDFile ExtractedFile
= std::move(ExtractedResult
.get());
1866 EXPECT_EQ(FileType::TBD_V5
, ExtractedFile
->getFileType());
1867 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1868 ExtractedFile
->getInstallName());
1870 TargetList AllTargets
= {
1871 Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(11, 0, 0)),
1872 Target(AK_arm64
, PLATFORM_MACCATALYST
, VersionTuple(14, 0)),
1874 EXPECT_EQ(mapToPlatformSet(AllTargets
), ExtractedFile
->getPlatforms());
1875 EXPECT_EQ(mapToArchitectureSet(AllTargets
),
1876 ExtractedFile
->getArchitectures());
1878 EXPECT_EQ(PackedVersion(1, 2, 0), ExtractedFile
->getCurrentVersion());
1879 EXPECT_EQ(PackedVersion(1, 1, 0), ExtractedFile
->getCompatibilityVersion());
1880 EXPECT_TRUE(ExtractedFile
->isApplicationExtensionSafe());
1881 EXPECT_FALSE(ExtractedFile
->isTwoLevelNamespace());
1882 EXPECT_EQ(0U, ExtractedFile
->documents().size());
1884 InterfaceFileRef
ClientA("ClientA", AllTargets
);
1885 InterfaceFileRef
ClientB("ClientB", AllTargets
);
1886 EXPECT_EQ(2U, ExtractedFile
->allowableClients().size());
1887 EXPECT_EQ(ClientA
, ExtractedFile
->allowableClients().at(0));
1888 EXPECT_EQ(ClientB
, ExtractedFile
->allowableClients().at(1));
1890 InterfaceFileRef
ReexportA("/u/l/l/libbar.dylib", AllTargets
);
1891 InterfaceFileRef
ReexportB("/u/l/l/libfoo.dylib", AllTargets
);
1892 EXPECT_EQ(2U, ExtractedFile
->reexportedLibraries().size());
1893 EXPECT_EQ(ReexportA
, ExtractedFile
->reexportedLibraries().at(0));
1894 EXPECT_EQ(ReexportB
, ExtractedFile
->reexportedLibraries().at(1));
1896 EXPECT_EQ(0u, ExtractedFile
->rpaths().size());
1898 TargetToAttr Umbrellas
= {{Target(AK_arm64
, PLATFORM_MACOS
), "System"},
1899 {Target(AK_arm64
, PLATFORM_MACCATALYST
), "System"}};
1900 EXPECT_EQ(Umbrellas
, ExtractedFile
->umbrellas());
1902 ExportedSymbolSeq Exports
, Reexports
, Undefineds
;
1903 for (const auto *Sym
: ExtractedFile
->symbols()) {
1904 TargetList SymTargets
{Sym
->targets().begin(), Sym
->targets().end()};
1905 ExportedSymbol Temp
=
1906 ExportedSymbol
{Sym
->getKind(),
1907 std::string(Sym
->getName()),
1908 Sym
->isWeakDefined() || Sym
->isWeakReferenced(),
1909 Sym
->isThreadLocalValue(),
1912 if (Sym
->isUndefined())
1913 Undefineds
.emplace_back(std::move(Temp
));
1915 Sym
->isReexported() ? Reexports
.emplace_back(std::move(Temp
))
1916 : Exports
.emplace_back(std::move(Temp
));
1918 llvm::sort(Exports
);
1919 llvm::sort(Reexports
);
1920 llvm::sort(Undefineds
);
1922 TargetList MacOSTargets
= {Target(AK_arm64
, PLATFORM_MACOS
)};
1924 std::vector
<ExportedSymbol
> ExpectedExportedSymbols
= {
1925 {SymbolKind::GlobalSymbol
, "_func", false, false, false, MacOSTargets
},
1926 {SymbolKind::GlobalSymbol
, "_global", false, false, true, MacOSTargets
},
1927 {SymbolKind::ObjectiveCClass
, "ClassA", false, false, true, MacOSTargets
},
1929 std::vector
<ExportedSymbol
> ExpectedReexportedSymbols
= {
1930 {SymbolKind::GlobalSymbol
, "_funcA", false, false, false, MacOSTargets
},
1931 {SymbolKind::GlobalSymbol
, "_globalRe", false, false, true, MacOSTargets
},
1932 {SymbolKind::ObjectiveCClass
, "ClassRexport", false, false, true,
1936 EXPECT_EQ(ExpectedExportedSymbols
.size(), Exports
.size());
1937 EXPECT_EQ(ExpectedReexportedSymbols
.size(), Reexports
.size());
1938 EXPECT_EQ(0U, Undefineds
.size());
1939 EXPECT_TRUE(std::equal(Exports
.begin(), Exports
.end(),
1940 std::begin(ExpectedExportedSymbols
)));
1941 EXPECT_TRUE(std::equal(Reexports
.begin(), Reexports
.end(),
1942 std::begin(ExpectedReexportedSymbols
)));
1945 TEST(TBDv5
, RemoveIF
) {
1946 static const char TBDv5File
[] = R
"({
1947 "tapi_tbd_version
": 5,
1951 "target
": "x86_64
-macos
",
1952 "min_deployment
": "10.14"
1955 "target
": "arm64
-macos
",
1956 "min_deployment
": "10.14"
1959 "target
": "arm64
-maccatalyst
",
1960 "min_deployment
": "12.1"
1975 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
1978 "current_versions
": [
1983 "compatibility_versions
": [
1984 { "version
": "1.1" }
1992 "@executable_path
/.../Frameworks
"
1996 "parent_umbrellas
": [
1998 "umbrella
": "System
"
2001 "allowable_clients
": [
2009 "reexported_libraries
": [
2012 "/u
/l
/l
/libfoo
.dylib
",
2013 "/u
/l
/l
/libbar
.dylib
"
2017 "exported_symbols
": [
2071 "reexported_symbols
": [
2092 "undefined_symbols
": [
2111 Expected
<TBDFile
> Result
=
2112 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
2113 EXPECT_TRUE(!!Result
);
2114 TBDFile File
= std::move(Result
.get());
2116 Expected
<TBDFile
> RemovedResult
= File
->remove(AK_x86_64
);
2117 EXPECT_TRUE(!!RemovedResult
);
2118 TBDFile RemovedFile
= std::move(RemovedResult
.get());
2120 EXPECT_EQ(FileType::TBD_V5
, RemovedFile
->getFileType());
2121 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2122 RemovedFile
->getInstallName());
2124 TargetList AllTargets
= {
2125 Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(11, 0, 0)),
2126 Target(AK_arm64
, PLATFORM_MACCATALYST
, VersionTuple(14, 0)),
2128 EXPECT_EQ(mapToPlatformSet(AllTargets
), RemovedFile
->getPlatforms());
2129 EXPECT_EQ(mapToArchitectureSet(AllTargets
), RemovedFile
->getArchitectures());
2131 EXPECT_EQ(PackedVersion(1, 2, 0), RemovedFile
->getCurrentVersion());
2132 EXPECT_EQ(PackedVersion(1, 1, 0), RemovedFile
->getCompatibilityVersion());
2133 EXPECT_TRUE(RemovedFile
->isApplicationExtensionSafe());
2134 EXPECT_FALSE(RemovedFile
->isTwoLevelNamespace());
2135 EXPECT_EQ(0U, RemovedFile
->documents().size());
2137 InterfaceFileRef
ClientA("ClientA", AllTargets
);
2138 InterfaceFileRef
ClientB("ClientB", AllTargets
);
2139 EXPECT_EQ(2U, RemovedFile
->allowableClients().size());
2140 EXPECT_EQ(ClientA
, RemovedFile
->allowableClients().at(0));
2141 EXPECT_EQ(ClientB
, RemovedFile
->allowableClients().at(1));
2143 InterfaceFileRef
ReexportA("/u/l/l/libbar.dylib", AllTargets
);
2144 InterfaceFileRef
ReexportB("/u/l/l/libfoo.dylib", AllTargets
);
2145 EXPECT_EQ(2U, RemovedFile
->reexportedLibraries().size());
2146 EXPECT_EQ(ReexportA
, RemovedFile
->reexportedLibraries().at(0));
2147 EXPECT_EQ(ReexportB
, RemovedFile
->reexportedLibraries().at(1));
2149 EXPECT_EQ(0u, RemovedFile
->rpaths().size());
2151 TargetToAttr Umbrellas
= {{Target(AK_arm64
, PLATFORM_MACOS
), "System"},
2152 {Target(AK_arm64
, PLATFORM_MACCATALYST
), "System"}};
2153 EXPECT_EQ(Umbrellas
, RemovedFile
->umbrellas());
2155 ExportedSymbolSeq Exports
, Reexports
, Undefineds
;
2156 for (const auto *Sym
: RemovedFile
->symbols()) {
2157 TargetList SymTargets
{Sym
->targets().begin(), Sym
->targets().end()};
2158 ExportedSymbol Temp
=
2159 ExportedSymbol
{Sym
->getKind(),
2160 std::string(Sym
->getName()),
2161 Sym
->isWeakDefined() || Sym
->isWeakReferenced(),
2162 Sym
->isThreadLocalValue(),
2165 if (Sym
->isUndefined())
2166 Undefineds
.emplace_back(std::move(Temp
));
2168 Sym
->isReexported() ? Reexports
.emplace_back(std::move(Temp
))
2169 : Exports
.emplace_back(std::move(Temp
));
2171 llvm::sort(Exports
);
2172 llvm::sort(Reexports
);
2173 llvm::sort(Undefineds
);
2175 TargetList MacOSTargets
= {Target(AK_arm64
, PLATFORM_MACOS
)};
2177 std::vector
<ExportedSymbol
> ExpectedExportedSymbols
= {
2178 {SymbolKind::GlobalSymbol
, "_func", false, false, false, MacOSTargets
},
2179 {SymbolKind::GlobalSymbol
, "_global", false, false, true, MacOSTargets
},
2180 {SymbolKind::ObjectiveCClass
, "ClassA", false, false, true, MacOSTargets
},
2182 std::vector
<ExportedSymbol
> ExpectedReexportedSymbols
= {
2183 {SymbolKind::GlobalSymbol
, "_funcA", false, false, false, MacOSTargets
},
2184 {SymbolKind::GlobalSymbol
, "_globalRe", false, false, true, MacOSTargets
},
2185 {SymbolKind::ObjectiveCClass
, "ClassRexport", false, false, true,
2189 EXPECT_EQ(ExpectedExportedSymbols
.size(), Exports
.size());
2190 EXPECT_EQ(ExpectedReexportedSymbols
.size(), Reexports
.size());
2191 EXPECT_EQ(0U, Undefineds
.size());
2192 EXPECT_TRUE(std::equal(Exports
.begin(), Exports
.end(),
2193 std::begin(ExpectedExportedSymbols
)));
2194 EXPECT_TRUE(std::equal(Reexports
.begin(), Reexports
.end(),
2195 std::begin(ExpectedReexportedSymbols
)));
2198 TEST(TBDv5
, InlineIF
) {
2199 static const char UmbrellaFile
[] = R
"({
2200 "tapi_tbd_version
": 5,
2204 "target
": "x86_64
-macos
",
2205 "min_deployment
": "10.14"
2208 "target
": "arm64
-macos
",
2209 "min_deployment
": "10.14"
2214 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
2217 "current_versions
": [
2222 "reexported_libraries
": [
2225 "/u
/l
/l
/libfoo
.dylib
",
2226 "/u
/l
/l
/libbar
.dylib
"
2232 static const char ReexportFile
[] = R
"({
2233 "tapi_tbd_version
": 5,
2237 "target
": "x86_64
-macos
",
2238 "min_deployment
": "10.14"
2241 "target
": "arm64
-macos
",
2242 "min_deployment
": "10.14"
2247 "name
" : "/u
/l
/l
/libfoo
.dylib
"
2250 "current_versions
": [
2261 "@executable_path
/.../Frameworks
"
2265 "exported_symbols
": [
2284 Expected
<TBDFile
> UmbrellaResult
=
2285 TextAPIReader::get(MemoryBufferRef(UmbrellaFile
, "Test.tbd"));
2286 EXPECT_TRUE(!!UmbrellaResult
);
2287 TBDFile Umbrella
= std::move(UmbrellaResult
.get());
2289 Expected
<TBDFile
> ReexportResult
=
2290 TextAPIReader::get(MemoryBufferRef(ReexportFile
, "Test.tbd"));
2291 EXPECT_TRUE(!!ReexportResult
);
2292 TBDReexportFile Reexport
= std::move(ReexportResult
.get());
2293 Umbrella
->inlineLibrary(Reexport
);
2295 EXPECT_EQ(FileType::TBD_V5
, Umbrella
->getFileType());
2296 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2297 Umbrella
->getInstallName());
2299 TargetList AllTargets
= {
2300 Target(AK_x86_64
, PLATFORM_MACOS
, VersionTuple(10, 14)),
2301 Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(11, 0, 0)),
2303 EXPECT_EQ(mapToPlatformSet(AllTargets
), Umbrella
->getPlatforms());
2304 EXPECT_EQ(mapToArchitectureSet(AllTargets
), Umbrella
->getArchitectures());
2306 EXPECT_EQ(PackedVersion(1, 2, 0), Umbrella
->getCurrentVersion());
2307 EXPECT_EQ(PackedVersion(1, 0, 0), Umbrella
->getCompatibilityVersion());
2308 InterfaceFileRef
ReexportA("/u/l/l/libbar.dylib", AllTargets
);
2309 InterfaceFileRef
ReexportB("/u/l/l/libfoo.dylib", AllTargets
);
2310 EXPECT_EQ(2U, Umbrella
->reexportedLibraries().size());
2311 EXPECT_EQ(ReexportA
, Umbrella
->reexportedLibraries().at(0));
2312 EXPECT_EQ(ReexportB
, Umbrella
->reexportedLibraries().at(1));
2313 EXPECT_EQ(1U, Umbrella
->documents().size());
2315 TBDReexportFile Document
= Umbrella
->documents().front();
2316 EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document
->getInstallName());
2317 EXPECT_EQ(0U, Document
->getSwiftABIVersion());
2318 EXPECT_TRUE(Document
->isTwoLevelNamespace());
2319 EXPECT_TRUE(Document
->isApplicationExtensionSafe());
2320 EXPECT_EQ(PackedVersion(1, 0, 0), Document
->getCurrentVersion());
2321 EXPECT_EQ(PackedVersion(1, 0, 0), Document
->getCompatibilityVersion());
2323 ExportedSymbolSeq Exports
;
2324 for (const auto *Sym
: Document
->symbols()) {
2325 TargetList SymTargets
{Sym
->targets().begin(), Sym
->targets().end()};
2326 Exports
.emplace_back(
2327 ExportedSymbol
{Sym
->getKind(), std::string(Sym
->getName()),
2328 Sym
->isWeakDefined() || Sym
->isWeakReferenced(),
2329 Sym
->isThreadLocalValue(), Sym
->isData(), SymTargets
});
2331 llvm::sort(Exports
);
2333 ExportedSymbolSeq ExpectedExports
= {
2334 {SymbolKind::GlobalSymbol
, "_global", false, false, true, AllTargets
},
2335 {SymbolKind::ObjectiveCClass
, "ClassA", false, false, true, AllTargets
},
2337 EXPECT_EQ(ExpectedExports
.size(), Exports
.size());
2339 std::equal(Exports
.begin(), Exports
.end(), std::begin(ExpectedExports
)));
2341 } // end namespace TBDv5