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_FALSE(File
->isOSLibNotForSharedCache());
222 EXPECT_EQ(0U, File
->documents().size());
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));
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));
236 TargetToAttr RPaths
= {
237 {Target(AK_x86_64
, PLATFORM_MACOS
), "@executable_path/.../Frameworks"},
239 EXPECT_EQ(RPaths
, File
->rpaths());
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());
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(),
256 if (Sym
->isUndefined())
257 Undefineds
.emplace_back(std::move(Temp
));
259 Sym
->isReexported() ? Reexports
.emplace_back(std::move(Temp
))
260 : Exports
.emplace_back(std::move(Temp
));
263 llvm::sort(Reexports
);
264 llvm::sort(Undefineds
);
266 TargetList MacOSTargets
= {Target(AK_x86_64
, PLATFORM_MACOS
),
267 Target(AK_arm64
, PLATFORM_MACOS
)};
269 std::vector
<ExportedSymbol
> ExpectedExportedSymbols
= {
270 {EncodeKind::GlobalSymbol
, "_func", false, false, false, MacOSTargets
},
271 {EncodeKind::GlobalSymbol
,
276 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
277 {EncodeKind::GlobalSymbol
, "_global", false, false, true, MacOSTargets
},
278 {EncodeKind::GlobalSymbol
,
283 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
284 {EncodeKind::ObjectiveCClass
,
289 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
290 {EncodeKind::ObjectiveCClass
,
295 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
296 {EncodeKind::ObjectiveCClass
,
301 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
302 {EncodeKind::ObjectiveCClassEHType
,
307 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
308 {EncodeKind::ObjectiveCClassEHType
,
313 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
314 {EncodeKind::ObjectiveCInstanceVariable
,
319 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
320 {EncodeKind::ObjectiveCInstanceVariable
,
325 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
326 {EncodeKind::ObjectiveCInstanceVariable
,
331 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
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,
340 std::vector
<ExportedSymbol
> ExpectedUndefinedSymbols
= {
341 {EncodeKind::GlobalSymbol
,
346 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
347 {EncodeKind::GlobalSymbol
,
352 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
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
)));
366 File
->getSymbol(EncodeKind::GlobalSymbol
, "_globalBind").has_value());
369 TEST(TBDv5
, ReadMultipleTargets
) {
370 static const char TBDv5File
[] = R
"({
371 "tapi_tbd_version
": 5,
375 "target
": "x86_64
-macos
",
376 "min_deployment
": "10.14"
379 "target
": "arm64
-macos
",
380 "min_deployment
": "10.14"
383 "target
": "arm64
-maccatalyst
",
384 "min_deployment
": "12.1"
388 { "name
":"/usr
/lib
/libFoo
.dylib
" }
390 "swift_abi
":[ { "abi
":8 } ],
391 "reexported_libraries
": [
393 "targets
": [ "x86_64
-maccatalyst
" ],
395 "/u
/l
/l
/libfoo
.dylib
",
396 "/u
/l
/l
/libbar
.dylib
"
400 "targets
": [ "arm64
-maccatalyst
" ],
401 "names
": [ "/u
/l
/l
/libArmOnly
.dylib
" ]
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());
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)),
424 EXPECT_EQ(mapToPlatformSet(AllTargets
), File
->getPlatforms());
425 EXPECT_EQ(mapToArchitectureSet(AllTargets
), File
->getArchitectures());
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));
439 TEST(TBDv5
, ReadMultipleDocuments
) {
440 static const char TBDv5File
[] = R
"({
441 "tapi_tbd_version
": 5,
445 "target
": "armv7
-ios
",
446 "min_deployment
": "11.0"
450 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
452 "reexported_libraries
": [
453 { "names
": ["/u
/l
/l
/libfoo
.dylib
"] }
460 "target
": "armv7
-ios
",
461 "min_deployment
": "11.0"
465 { "name
":"/u
/l
/l
/libfoo
.dylib
" }
468 { "attributes
": ["not_app_extension_safe
"] }
470 "exported_symbols
": [
473 "thread_local
": [ "_globalVar
" ],
474 "objc_class
": [ "ClassData
", "ClassA
", "ClassB
"],
475 "objc_eh_type
": [ "ClassA
", "ClassB
" ]
478 "global
": [ "_funcFoo
" ]
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());
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());
501 InterfaceFileRef
Reexport("/u/l/l/libfoo.dylib", {iOSTarget
});
502 EXPECT_EQ(1U, File
->reexportedLibraries().size());
503 EXPECT_EQ(Reexport
, File
->reexportedLibraries().at(0));
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());
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(),
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
,
537 {EncodeKind::ObjectiveCClassEHType
,
543 {EncodeKind::ObjectiveCClassEHType
,
551 EXPECT_EQ(ExpectedExports
.size(), Exports
.size());
553 std::equal(Exports
.begin(), Exports
.end(), std::begin(ExpectedExports
)));
556 TEST(TBDv5
, WriteFile
) {
557 static const char TBDv5File
[] = R
"({
558 "tapi_tbd_version
": 5,
562 "target
": "x86_64
-macos
",
563 "min_deployment
": "10.14"
566 "target
": "arm64
-macos
",
567 "min_deployment
": "10.14"
570 "target
": "arm64
-maccatalyst
",
571 "min_deployment
": "12.1"
576 "name
": "@rpath
/S
/L
/F
/Foo
.framework
/Foo
"
579 "current_versions
": [
584 "compatibility_versions
": [
600 "@executable_path
/.../Frameworks
"
604 "parent_umbrellas
": [
609 "allowable_clients
": [
617 "reexported_libraries
": [
620 "/u
/l
/l
/libfoo
.dylib
",
621 "/u
/l
/l
/libbar
.dylib
"
625 "exported_symbols
": [
679 "reexported_symbols
": [
696 "undefined_symbols
": [
714 File
.setFileType(FileType::TBD_V5
);
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)),
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]);
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
);
735 SymbolFlags Flags
= SymbolFlags::None
;
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
);
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
);
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
);
776 File
.setTwoLevelNamespace(false);
777 File
.setApplicationExtensionSafe(true);
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
);
786 Expected
<TBDFile
> Input
=
787 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Input.tbd"));
788 EXPECT_TRUE(!!Input
);
789 TBDFile InputFile
= std::move(Input
.get());
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
);
798 TEST(TBDv5
, WriteMultipleDocuments
) {
799 static const char TBDv5File
[] = R
"({
800 "tapi_tbd_version
": 5,
804 "target
": "armv7
-ios
",
805 "min_deployment
": "11.0"
809 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
811 "reexported_libraries
": [
812 { "names
": ["/u
/l
/l
/libfoo
.dylib
"]
820 "target
": "armv7
-ios
",
821 "min_deployment
": "11.0"
824 "target
": "armv7s
-ios
",
825 "min_deployment
": "11.0"
829 { "name
":"/u
/l
/l
/libfoo
.dylib
" }
831 "current_versions
": [
842 "@executable_path
/.../Frameworks
"
845 "reexported_libraries
": [ { "names
": ["@rpath
/libfoo
.dylib
"] } ],
847 { "attributes
": ["not_app_extension_safe
"] }
849 "exported_symbols
": [
852 "global
": [ "_funcFoo
" ]
860 "target
": "armv7
-ios
",
861 "min_deployment
": "11.0"
865 { "name
":"@rpath
/libfoo
.dylib
" }
867 "exported_symbols
": [
870 "global
": [ "_varFooBaz
" ]
878 File
.setFileType(FileType::TBD_V5
);
880 TargetList AllTargets
= {
881 Target(AK_armv7
, PLATFORM_IOS
, VersionTuple(11, 0)),
882 Target(AK_armv7s
, PLATFORM_IOS
, VersionTuple(11, 0)),
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);
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
,
905 File
.addDocument(std::make_shared
<InterfaceFile
>(std::move(NestedFile
)));
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]},
917 File
.addDocument(std::make_shared
<InterfaceFile
>(std::move(NestedFileB
)));
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
,
925 EXPECT_FALSE(Result
);
927 Expected
<TBDFile
> Input
=
928 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Input.tbd"));
929 EXPECT_TRUE(!!Input
);
930 TBDFile InputFile
= std::move(Input
.get());
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
);
939 TEST(TBDv5
, Target_Simulator
) {
940 static const char TBDv5File
[] = R
"({
941 "tapi_tbd_version
": 5,
945 "target
": "arm64
-ios
-simulator
",
946 "min_deployment
": "11.0"
949 "target
": "x86_64
-ios
-simulator
",
950 "min_deployment
": "11.3"
954 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
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)),
967 TargetList Targets
{File
->targets().begin(), File
->targets().end()};
969 EXPECT_EQ(Targets
, ExpectedTargets
);
971 SmallString
<4096> Buffer
;
972 raw_svector_ostream
OS(Buffer
);
973 Error WriteResult
= TextAPIWriter::writeToStream(OS
, *File
);
974 EXPECT_TRUE(!WriteResult
);
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
);
983 TEST(TBDv5
, Target_UnsupportedMinOS
) {
984 static const char TBDv5File
[] = R
"({
985 "tapi_tbd_version
": 5,
989 "target
": "arm64
-macos
",
990 "min_deployment
": "10.14"
993 "target
": "x86_64
-macos
",
994 "min_deployment
": "10.14"
998 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
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)),
1011 TargetList Targets
{File
->targets().begin(), File
->targets().end()};
1012 llvm::sort(Targets
);
1013 EXPECT_EQ(Targets
, ExpectedTargets
);
1015 SmallString
<4096> Buffer
;
1016 raw_svector_ostream
OS(Buffer
);
1017 Error WriteResult
= TextAPIWriter::writeToStream(OS
, *File
);
1018 EXPECT_TRUE(!WriteResult
);
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
);
1027 TEST(TBDv5
, MisspelledKey
) {
1028 static const char TBDv5File
[] = R
"({
1029 "tapi_tbd_version
": 5,
1033 "target
": "arm64
-ios
-simulator
",
1034 "min_deployment
": "11.0"
1038 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
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
);
1049 TEST(TBDv5
, InvalidVersion
) {
1050 static const char TBDv5File
[] = R
"({
1051 "tapi_tbd_version
": 11,
1055 "target
": "arm64
-ios
-simulator
",
1056 "min_deployment
": "11.0"
1060 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
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
);
1071 TEST(TBDv5
, MissingRequiredKey
) {
1072 static const char TBDv5File
[] = R
"({
1076 "target
": "arm64
-ios
-simulator
",
1077 "min_deployment
": "11.0"
1081 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
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
);
1092 TEST(TBDv5
, InvalidSymbols
) {
1093 static const char TBDv5File
[] = R
"({
1094 "tapi_tbd_version
": 5,
1098 "target
": "arm64
-driverkit
",
1099 "min_deployment
": "11.0"
1103 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1105 "exported_symbols
": [
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
);
1123 TEST(TBDv5
, DefaultMinOS
) {
1124 static const char TBDv5File
[] = R
"({
1125 "tapi_tbd_version
": 5,
1129 "target
": "arm64
-ios
-simulator
"
1133 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
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)));
1148 TEST(TBDv5
, InvalidMinOS
) {
1149 static const char TBDv5File
[] = R
"({
1150 "tapi_tbd_version
": 5,
1154 "target
": "arm64
-ios
-simulator
",
1155 "min_deployment
": "swift
-abi
"
1159 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
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
);
1170 TEST(TBDv5
, SimSupport
) {
1171 static const char TBDv5File
[] = R
"({
1172 "tapi_tbd_version
": 5,
1176 "target
": "arm64
-macos
",
1177 "min_deployment
": "11.1"
1181 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1184 { "attributes
": ["sim_support
"] }
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());
1201 TEST(TBDv5
, NotForSharedCache
) {
1202 static const char TBDv5File
[] = R
"({
1203 "tapi_tbd_version
": 5,
1207 "target
": "arm64
-macos
",
1208 "min_deployment
": "11.1"
1212 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1215 { "attributes
": ["not_for_dyld_shared_cache
"] }
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());
1233 TEST(TBDv5
, ObjCInterfaces
) {
1234 static const char TBDv5File
[] = R
"({
1235 "tapi_tbd_version
": 5,
1239 "target
": "arm64
-ios
-simulator
",
1240 "min_deployment
": "14.0"
1244 { "name
":"/S
/L
/F
/Foo
.framework
/Foo
" }
1246 "exported_symbols
": [
1251 "_OBJC_METACLASS_$_Standalone
",
1252 "_OBJC_CLASS_$_Standalone2
"
1254 "weak
": ["_OBJC_EHTYPE_$_NSObject
"],
1259 "objc_eh_type
": ["ClassA
"]
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
);
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
));
1282 llvm::sort(Exports
);
1284 std::vector
<ExportedSymbol
> ExpectedExports
= {
1285 {EncodeKind::GlobalSymbol
, "_OBJC_CLASS_$_Standalone2", false, false,
1287 {EncodeKind::GlobalSymbol
, "_OBJC_EHTYPE_$_NSObject", true, false, true},
1288 {EncodeKind::GlobalSymbol
, "_OBJC_METACLASS_$_Standalone", false, false,
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}};
1295 EXPECT_EQ(ExpectedExports
.size(), Exports
.size());
1297 std::equal(Exports
.begin(), Exports
.end(), std::begin(ExpectedExports
)));
1299 SmallString
<4096> Buffer
;
1300 raw_svector_ostream
OS(Buffer
);
1301 Error WriteResult
= TextAPIWriter::writeToStream(OS
, *File
);
1302 EXPECT_TRUE(!WriteResult
);
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
);
1311 TEST(TBDv5
, MergeIF
) {
1312 static const char TBDv5FileA
[] = R
"({
1313 "tapi_tbd_version
": 5,
1317 "target
": "x86_64
-macos
",
1318 "min_deployment
": "10.14"
1321 "target
": "arm64
-macos
",
1322 "min_deployment
": "10.14"
1325 "target
": "arm64
-maccatalyst
",
1326 "min_deployment
": "12.1"
1341 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
1344 "current_versions
": [
1349 "compatibility_versions
": [
1350 { "version
": "1.1" }
1358 "@executable_path
/.../Frameworks
"
1362 "parent_umbrellas
": [
1364 "umbrella
": "System
"
1367 "allowable_clients
": [
1375 "reexported_libraries
": [
1378 "/u
/l
/l
/libfoo
.dylib
",
1379 "/u
/l
/l
/libbar
.dylib
"
1383 "exported_symbols
": [
1437 "reexported_symbols
": [
1458 "undefined_symbols
": [
1477 static const char TBDv5FileB
[] = R
"({
1478 "tapi_tbd_version
": 5,
1482 "target
": "x86_64
-macos
",
1483 "min_deployment
": "10.14"
1486 "target
": "arm64
-macos
",
1487 "min_deployment
": "10.14"
1490 "target
": "arm64
-maccatalyst
",
1491 "min_deployment
": "12.1"
1506 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
1509 "current_versions
": [
1514 "compatibility_versions
": [
1515 { "version
": "1.1" }
1517 "exported_symbols
": [
1574 Expected
<TBDFile
> ResultA
=
1575 TextAPIReader::get(MemoryBufferRef(TBDv5FileA
, "Test.tbd"));
1576 EXPECT_TRUE(!!ResultA
);
1577 TBDFile FileA
= std::move(ResultA
.get());
1579 Expected
<TBDFile
> ResultB
=
1580 TextAPIReader::get(MemoryBufferRef(TBDv5FileB
, "Test.tbd"));
1581 EXPECT_TRUE(!!ResultB
);
1582 TBDFile FileB
= std::move(ResultB
.get());
1584 Expected
<TBDFile
> MergedResult
= FileA
->merge(FileB
.get());
1585 EXPECT_TRUE(!!MergedResult
);
1586 TBDFile MergedFile
= std::move(MergedResult
.get());
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)),
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));
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));
1615 TargetToAttr RPaths
= {
1616 {Target(AK_x86_64
, PLATFORM_MACOS
), "@executable_path/.../Frameworks"},
1618 EXPECT_EQ(RPaths
, MergedFile
->rpaths());
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());
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(),
1635 if (Sym
->isUndefined())
1636 Undefineds
.emplace_back(std::move(Temp
));
1638 Sym
->isReexported() ? Reexports
.emplace_back(std::move(Temp
))
1639 : Exports
.emplace_back(std::move(Temp
));
1641 llvm::sort(Exports
);
1642 llvm::sort(Reexports
);
1643 llvm::sort(Undefineds
);
1645 TargetList MacOSTargets
= {Target(AK_x86_64
, PLATFORM_MACOS
),
1646 Target(AK_arm64
, PLATFORM_MACOS
)};
1648 std::vector
<ExportedSymbol
> ExpectedExportedSymbols
= {
1649 {EncodeKind::GlobalSymbol
, "_func", false, false, false, MacOSTargets
},
1650 {EncodeKind::GlobalSymbol
,
1655 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1656 {EncodeKind::GlobalSymbol
,
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
,
1669 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1670 {EncodeKind::GlobalSymbol
,
1675 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1676 {EncodeKind::GlobalSymbol
, "_globalZ", false, false, true, MacOSTargets
},
1677 {EncodeKind::ObjectiveCClass
,
1682 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1683 {EncodeKind::ObjectiveCClass
,
1688 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1689 {EncodeKind::ObjectiveCClass
,
1694 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1695 {EncodeKind::ObjectiveCClass
,
1700 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1701 {EncodeKind::ObjectiveCClass
,
1706 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1707 {EncodeKind::ObjectiveCClassEHType
,
1712 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1713 {EncodeKind::ObjectiveCClassEHType
,
1718 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1719 {EncodeKind::ObjectiveCClassEHType
,
1724 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1725 {EncodeKind::ObjectiveCClassEHType
,
1730 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1731 {EncodeKind::ObjectiveCInstanceVariable
,
1736 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1737 {EncodeKind::ObjectiveCInstanceVariable
,
1742 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1743 {EncodeKind::ObjectiveCInstanceVariable
,
1748 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1749 {EncodeKind::ObjectiveCInstanceVariable
,
1754 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1755 {EncodeKind::ObjectiveCInstanceVariable
,
1760 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1761 {EncodeKind::ObjectiveCInstanceVariable
,
1766 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
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,
1776 std::vector
<ExportedSymbol
> ExpectedUndefinedSymbols
= {
1777 {EncodeKind::GlobalSymbol
,
1782 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
1783 {EncodeKind::GlobalSymbol
,
1788 {Target(AK_x86_64
, PLATFORM_MACOS
)}},
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
)));
1802 TEST(TBDv5
, ExtractIF
) {
1803 static const char TBDv5File
[] = R
"({
1804 "tapi_tbd_version
": 5,
1808 "target
": "x86_64
-macos
",
1809 "min_deployment
": "10.14"
1812 "target
": "arm64
-macos
",
1813 "min_deployment
": "10.14"
1816 "target
": "arm64
-maccatalyst
",
1817 "min_deployment
": "12.1"
1832 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
1835 "current_versions
": [
1840 "compatibility_versions
": [
1841 { "version
": "1.1" }
1849 "@executable_path
/.../Frameworks
"
1853 "parent_umbrellas
": [
1855 "umbrella
": "System
"
1858 "allowable_clients
": [
1866 "reexported_libraries
": [
1869 "/u
/l
/l
/libfoo
.dylib
",
1870 "/u
/l
/l
/libbar
.dylib
"
1874 "exported_symbols
": [
1928 "reexported_symbols
": [
1949 "undefined_symbols
": [
1968 Expected
<TBDFile
> Result
=
1969 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
1970 EXPECT_TRUE(!!Result
);
1971 TBDFile File
= std::move(Result
.get());
1973 Expected
<TBDFile
> ExtractedResult
= File
->extract(AK_arm64
);
1974 EXPECT_TRUE(!!ExtractedResult
);
1975 TBDFile ExtractedFile
= std::move(ExtractedResult
.get());
1977 EXPECT_EQ(FileType::TBD_V5
, ExtractedFile
->getFileType());
1978 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1979 ExtractedFile
->getInstallName());
1981 TargetList AllTargets
= {
1982 Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(11, 0, 0)),
1983 Target(AK_arm64
, PLATFORM_MACCATALYST
, VersionTuple(14, 0)),
1985 EXPECT_EQ(mapToPlatformSet(AllTargets
), ExtractedFile
->getPlatforms());
1986 EXPECT_EQ(mapToArchitectureSet(AllTargets
),
1987 ExtractedFile
->getArchitectures());
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());
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));
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));
2007 EXPECT_EQ(0u, ExtractedFile
->rpaths().size());
2009 TargetToAttr Umbrellas
= {{Target(AK_arm64
, PLATFORM_MACOS
), "System"},
2010 {Target(AK_arm64
, PLATFORM_MACCATALYST
), "System"}};
2011 EXPECT_EQ(Umbrellas
, ExtractedFile
->umbrellas());
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(),
2023 if (Sym
->isUndefined())
2024 Undefineds
.emplace_back(std::move(Temp
));
2026 Sym
->isReexported() ? Reexports
.emplace_back(std::move(Temp
))
2027 : Exports
.emplace_back(std::move(Temp
));
2029 llvm::sort(Exports
);
2030 llvm::sort(Reexports
);
2031 llvm::sort(Undefineds
);
2033 TargetList MacOSTargets
= {Target(AK_arm64
, PLATFORM_MACOS
)};
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
},
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,
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
)));
2056 TEST(TBDv5
, RemoveIF
) {
2057 static const char TBDv5File
[] = R
"({
2058 "tapi_tbd_version
": 5,
2062 "target
": "x86_64
-macos
",
2063 "min_deployment
": "10.14"
2066 "target
": "arm64
-macos
",
2067 "min_deployment
": "10.14"
2070 "target
": "arm64
-maccatalyst
",
2071 "min_deployment
": "12.1"
2081 "not_for_dyld_shared_cache
"
2087 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
2090 "current_versions
": [
2095 "compatibility_versions
": [
2096 { "version
": "1.1" }
2104 "@executable_path
/.../Frameworks
"
2108 "parent_umbrellas
": [
2110 "umbrella
": "System
"
2113 "allowable_clients
": [
2121 "reexported_libraries
": [
2124 "/u
/l
/l
/libfoo
.dylib
",
2125 "/u
/l
/l
/libbar
.dylib
"
2129 "exported_symbols
": [
2183 "reexported_symbols
": [
2204 "undefined_symbols
": [
2223 Expected
<TBDFile
> Result
=
2224 TextAPIReader::get(MemoryBufferRef(TBDv5File
, "Test.tbd"));
2225 EXPECT_TRUE(!!Result
);
2226 TBDFile File
= std::move(Result
.get());
2228 Expected
<TBDFile
> RemovedResult
= File
->remove(AK_x86_64
);
2229 EXPECT_TRUE(!!RemovedResult
);
2230 TBDFile RemovedFile
= std::move(RemovedResult
.get());
2232 EXPECT_EQ(FileType::TBD_V5
, RemovedFile
->getFileType());
2233 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2234 RemovedFile
->getInstallName());
2236 TargetList AllTargets
= {
2237 Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(11, 0, 0)),
2238 Target(AK_arm64
, PLATFORM_MACCATALYST
, VersionTuple(14, 0)),
2240 EXPECT_EQ(mapToPlatformSet(AllTargets
), RemovedFile
->getPlatforms());
2241 EXPECT_EQ(mapToArchitectureSet(AllTargets
), RemovedFile
->getArchitectures());
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());
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));
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));
2262 EXPECT_EQ(0u, RemovedFile
->rpaths().size());
2264 TargetToAttr Umbrellas
= {{Target(AK_arm64
, PLATFORM_MACOS
), "System"},
2265 {Target(AK_arm64
, PLATFORM_MACCATALYST
), "System"}};
2266 EXPECT_EQ(Umbrellas
, RemovedFile
->umbrellas());
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(),
2278 if (Sym
->isUndefined())
2279 Undefineds
.emplace_back(std::move(Temp
));
2281 Sym
->isReexported() ? Reexports
.emplace_back(std::move(Temp
))
2282 : Exports
.emplace_back(std::move(Temp
));
2284 llvm::sort(Exports
);
2285 llvm::sort(Reexports
);
2286 llvm::sort(Undefineds
);
2288 TargetList MacOSTargets
= {Target(AK_arm64
, PLATFORM_MACOS
)};
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
},
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,
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
)));
2311 TEST(TBDv5
, InlineIF
) {
2312 static const char UmbrellaFile
[] = R
"({
2313 "tapi_tbd_version
": 5,
2317 "target
": "x86_64
-macos
",
2318 "min_deployment
": "10.14"
2321 "target
": "arm64
-macos
",
2322 "min_deployment
": "10.14"
2327 "name
": "/S
/L
/F
/Foo
.framework
/Foo
"
2330 "current_versions
": [
2335 "reexported_libraries
": [
2338 "/u
/l
/l
/libfoo
.dylib
",
2339 "/u
/l
/l
/libbar
.dylib
"
2345 static const char ReexportFile
[] = R
"({
2346 "tapi_tbd_version
": 5,
2350 "target
": "x86_64
-macos
",
2351 "min_deployment
": "10.14"
2354 "target
": "arm64
-macos
",
2355 "min_deployment
": "10.14"
2360 "name
" : "/u
/l
/l
/libfoo
.dylib
"
2363 "current_versions
": [
2374 "@executable_path
/.../Frameworks
"
2378 "exported_symbols
": [
2397 Expected
<TBDFile
> UmbrellaResult
=
2398 TextAPIReader::get(MemoryBufferRef(UmbrellaFile
, "Test.tbd"));
2399 EXPECT_TRUE(!!UmbrellaResult
);
2400 TBDFile Umbrella
= std::move(UmbrellaResult
.get());
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
);
2408 EXPECT_EQ(FileType::TBD_V5
, Umbrella
->getFileType());
2409 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2410 Umbrella
->getInstallName());
2412 TargetList AllTargets
= {
2413 Target(AK_x86_64
, PLATFORM_MACOS
, VersionTuple(10, 14)),
2414 Target(AK_arm64
, PLATFORM_MACOS
, VersionTuple(11, 0, 0)),
2416 EXPECT_EQ(mapToPlatformSet(AllTargets
), Umbrella
->getPlatforms());
2417 EXPECT_EQ(mapToArchitectureSet(AllTargets
), Umbrella
->getArchitectures());
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());
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());
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
});
2444 llvm::sort(Exports
);
2446 ExportedSymbolSeq ExpectedExports
= {
2447 {EncodeKind::GlobalSymbol
, "_global", false, false, true, AllTargets
},
2448 {EncodeKind::ObjectiveCClass
, "ClassA", false, false, true, AllTargets
},
2450 EXPECT_EQ(ExpectedExports
.size(), Exports
.size());
2452 std::equal(Exports
.begin(), Exports
.end(), std::begin(ExpectedExports
)));
2454 } // end namespace TBDv5