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