llvm-project

Форк
0
/
TextStubV5Tests.cpp 
2452 строки · 65.5 Кб
1
//===-- TextStubV5Tests.cpp - TBD V5 File Test ----------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===-----------------------------------------------------------------------===/
8

9
#include "TextStubHelpers.h"
10
#include "llvm/TextAPI/InterfaceFile.h"
11
#include "llvm/TextAPI/TextAPIReader.h"
12
#include "llvm/TextAPI/TextAPIWriter.h"
13
#include "gtest/gtest.h"
14
#include <string>
15
#include <vector>
16

17
using namespace llvm;
18
using namespace llvm::MachO;
19

20
namespace TBDv5 {
21

22
TEST(TBDv5, ReadFile) {
23
  static const char TBDv5File[] = R"({
24
"tapi_tbd_version": 5,
25
"main_library": {
26
  "target_info": [
27
    {
28
      "target": "x86_64-macos",
29
      "min_deployment": "10.14"
30
    },
31
    {
32
      "target": "arm64-macos",
33
      "min_deployment": "10.14"
34
    },
35
    {
36
      "target": "arm64-maccatalyst",
37
      "min_deployment": "12.1"
38
    }
39
  ],
40
  "flags": [
41
    {
42
      "targets": [
43
            "x86_64-macos"
44
        ],
45
      "attributes": [
46
            "flat_namespace"
47
        ]
48
    }
49
  ],
50
  "install_names": [
51
    {
52
        "name": "/S/L/F/Foo.framework/Foo"
53
    }
54
  ],
55
  "current_versions": [
56
    {
57
        "version": "1.2"
58
    }
59
  ],
60
  "compatibility_versions": [
61
    { "version": "1.1" }
62
  ],
63
  "rpaths": [
64
    {
65
      "targets": [
66
          "x86_64-macos"
67
      ],
68
      "paths": [
69
          "@executable_path/.../Frameworks"
70
      ]
71
    }
72
  ],
73
  "parent_umbrellas": [
74
    {
75
      "umbrella": "System"
76
    }
77
  ],
78
  "allowable_clients": [
79
    {
80
        "clients": [
81
            "ClientA",
82
            "ClientB"
83
        ]
84
    }
85
  ],
86
  "reexported_libraries": [
87
    {
88
        "names": [
89
            "/u/l/l/libfoo.dylib",
90
            "/u/l/l/libbar.dylib"
91
        ]
92
    }
93
  ],
94
  "exported_symbols": [
95
    {
96
        "targets": [
97
            "x86_64-macos",
98
            "arm64-macos"
99
        ],
100
        "data": {
101
            "global": [
102
                "_global"
103
            ],
104
            "objc_class": [
105
                "ClassA"
106
            ],
107
            "weak": [],
108
            "thread_local": []
109
        },
110
        "text": {
111
            "global": [
112
                "_func"
113
            ],
114
            "weak": [],
115
            "thread_local": []
116
        }
117
    },
118
    {
119
      "targets": [
120
          "x86_64-macos"
121
      ],
122
      "data": {
123
          "global": [
124
              "_globalVar"
125
          ],
126
          "objc_class": [
127
              "ClassA",
128
              "ClassB",
129
              "ClassData"
130
          ],
131
          "objc_eh_type": [
132
              "ClassA",
133
              "ClassB"
134
          ],
135
          "objc_ivar": [
136
              "ClassA.ivar1",
137
              "ClassA.ivar2",
138
              "ClassC.ivar1"
139
          ]
140
      },
141
      "text": {
142
          "global": [
143
              "_funcFoo"
144
          ]
145
      }
146
    }
147
  ],
148
  "reexported_symbols": [
149
    {
150
        "targets": [
151
            "x86_64-macos",
152
            "arm64-macos"
153
        ],
154
        "data": {
155
            "global": [
156
                "_globalRe"
157
            ],
158
            "objc_class": [
159
                "ClassRexport"
160
            ]
161
        },
162
        "text": {
163
            "global": [
164
                "_funcA"
165
            ]
166
        }
167
    }
168
  ],
169
  "undefined_symbols": [
170
    {
171
        "targets": [
172
            "x86_64-macos"
173
        ],
174
        "data": {
175
            "global": [
176
                "_globalBind"
177
            ],
178
            "weak": [
179
                "referenced_sym"
180
            ]
181
        }
182
    }
183
  ]
184
},
185
"libraries": []
186
})";
187

188
  MemoryBufferRef InputBuf = MemoryBufferRef(TBDv5File, "Test.tbd");
189
  Expected<FileType> ExpectedFT = TextAPIReader::canRead(InputBuf);
190
  EXPECT_TRUE(!!ExpectedFT);
191

192
  Expected<TBDFile> Result = TextAPIReader::get(InputBuf);
193
  EXPECT_TRUE(!!Result);
194
  TBDFile File = std::move(Result.get());
195
  EXPECT_EQ(FileType::TBD_V5, File->getFileType());
196
  EXPECT_EQ(*ExpectedFT, File->getFileType());
197
  EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName());
198

199
  TargetList AllTargets = {
200
      Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
201
      Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
202
      Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
203
  };
204
  std::set<Target> FileTargets{File->targets().begin(), File->targets().end()};
205
  EXPECT_EQ(mapToPlatformSet(AllTargets), File->getPlatforms());
206
  EXPECT_EQ(mapToArchitectureSet(AllTargets), File->getArchitectures());
207
  EXPECT_EQ(FileTargets.size(), AllTargets.size());
208
  for (const auto &Targ : AllTargets) {
209
    auto FileTarg = FileTargets.find(Targ);
210
    EXPECT_FALSE(FileTarg == FileTargets.end());
211
    EXPECT_EQ(*FileTarg, Targ);
212
    PackedVersion MD = Targ.MinDeployment;
213
    PackedVersion FileMD = FileTarg->MinDeployment;
214
    EXPECT_EQ(MD, FileMD);
215
  }
216

217
  EXPECT_EQ(PackedVersion(1, 2, 0), File->getCurrentVersion());
218
  EXPECT_EQ(PackedVersion(1, 1, 0), File->getCompatibilityVersion());
219
  EXPECT_TRUE(File->isApplicationExtensionSafe());
220
  EXPECT_FALSE(File->isTwoLevelNamespace());
221
  EXPECT_FALSE(File->isOSLibNotForSharedCache());
222
  EXPECT_EQ(0U, File->documents().size());
223

224
  InterfaceFileRef ClientA("ClientA", AllTargets);
225
  InterfaceFileRef ClientB("ClientB", AllTargets);
226
  EXPECT_EQ(2U, File->allowableClients().size());
227
  EXPECT_EQ(ClientA, File->allowableClients().at(0));
228
  EXPECT_EQ(ClientB, File->allowableClients().at(1));
229

230
  InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
231
  InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
232
  EXPECT_EQ(2U, File->reexportedLibraries().size());
233
  EXPECT_EQ(ReexportA, File->reexportedLibraries().at(0));
234
  EXPECT_EQ(ReexportB, File->reexportedLibraries().at(1));
235

236
  TargetToAttr RPaths = {
237
      {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"},
238
  };
239
  EXPECT_EQ(RPaths, File->rpaths());
240

241
  TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"},
242
                            {Target(AK_arm64, PLATFORM_MACOS), "System"},
243
                            {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
244
  EXPECT_EQ(Umbrellas, File->umbrellas());
245

246
  ExportedSymbolSeq Exports, Reexports, Undefineds;
247
  for (const auto *Sym : File->symbols()) {
248
    TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
249
    ExportedSymbol Temp =
250
        ExportedSymbol{Sym->getKind(),
251
                       std::string(Sym->getName()),
252
                       Sym->isWeakDefined() || Sym->isWeakReferenced(),
253
                       Sym->isThreadLocalValue(),
254
                       Sym->isData(),
255
                       SymTargets};
256
    if (Sym->isUndefined())
257
      Undefineds.emplace_back(std::move(Temp));
258
    else
259
      Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
260
                          : Exports.emplace_back(std::move(Temp));
261
  }
262
  llvm::sort(Exports);
263
  llvm::sort(Reexports);
264
  llvm::sort(Undefineds);
265

266
  TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS),
267
                             Target(AK_arm64, PLATFORM_MACOS)};
268

269
  std::vector<ExportedSymbol> ExpectedExportedSymbols = {
270
      {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
271
      {EncodeKind::GlobalSymbol,
272
       "_funcFoo",
273
       false,
274
       false,
275
       false,
276
       {Target(AK_x86_64, PLATFORM_MACOS)}},
277
      {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
278
      {EncodeKind::GlobalSymbol,
279
       "_globalVar",
280
       false,
281
       false,
282
       true,
283
       {Target(AK_x86_64, PLATFORM_MACOS)}},
284
      {EncodeKind::ObjectiveCClass,
285
       "ClassA",
286
       false,
287
       false,
288
       true,
289
       {Target(AK_x86_64, PLATFORM_MACOS)}},
290
      {EncodeKind::ObjectiveCClass,
291
       "ClassB",
292
       false,
293
       false,
294
       true,
295
       {Target(AK_x86_64, PLATFORM_MACOS)}},
296
      {EncodeKind::ObjectiveCClass,
297
       "ClassData",
298
       false,
299
       false,
300
       true,
301
       {Target(AK_x86_64, PLATFORM_MACOS)}},
302
      {EncodeKind::ObjectiveCClassEHType,
303
       "ClassA",
304
       false,
305
       false,
306
       true,
307
       {Target(AK_x86_64, PLATFORM_MACOS)}},
308
      {EncodeKind::ObjectiveCClassEHType,
309
       "ClassB",
310
       false,
311
       false,
312
       true,
313
       {Target(AK_x86_64, PLATFORM_MACOS)}},
314
      {EncodeKind::ObjectiveCInstanceVariable,
315
       "ClassA.ivar1",
316
       false,
317
       false,
318
       true,
319
       {Target(AK_x86_64, PLATFORM_MACOS)}},
320
      {EncodeKind::ObjectiveCInstanceVariable,
321
       "ClassA.ivar2",
322
       false,
323
       false,
324
       true,
325
       {Target(AK_x86_64, PLATFORM_MACOS)}},
326
      {EncodeKind::ObjectiveCInstanceVariable,
327
       "ClassC.ivar1",
328
       false,
329
       false,
330
       true,
331
       {Target(AK_x86_64, PLATFORM_MACOS)}},
332
  };
333
  std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
334
      {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
335
      {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
336
      {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true,
337
       MacOSTargets},
338
  };
339

340
  std::vector<ExportedSymbol> ExpectedUndefinedSymbols = {
341
      {EncodeKind::GlobalSymbol,
342
       "_globalBind",
343
       false,
344
       false,
345
       true,
346
       {Target(AK_x86_64, PLATFORM_MACOS)}},
347
      {EncodeKind::GlobalSymbol,
348
       "referenced_sym",
349
       true,
350
       false,
351
       true,
352
       {Target(AK_x86_64, PLATFORM_MACOS)}},
353
  };
354

355
  EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
356
  EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
357
  EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size());
358
  EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
359
                         std::begin(ExpectedExportedSymbols)));
360
  EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
361
                         std::begin(ExpectedReexportedSymbols)));
362
  EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
363
                         std::begin(ExpectedUndefinedSymbols)));
364

365
  EXPECT_TRUE(
366
      File->getSymbol(EncodeKind::GlobalSymbol, "_globalBind").has_value());
367
}
368

369
TEST(TBDv5, ReadMultipleTargets) {
370
  static const char TBDv5File[] = R"({ 
371
"tapi_tbd_version": 5,
372
"main_library":  {
373
  "target_info": [
374
      {
375
          "target": "x86_64-macos",
376
          "min_deployment": "10.14" 
377
      },
378
      {
379
          "target": "arm64-macos",
380
          "min_deployment": "10.14"
381
      },
382
      {
383
          "target": "arm64-maccatalyst",
384
          "min_deployment": "12.1"
385
      }
386
  ],
387
  "install_names":[
388
      { "name":"/usr/lib/libFoo.dylib" }
389
  ],
390
  "swift_abi":[ { "abi":8 } ],
391
  "reexported_libraries": [
392
      {
393
          "targets": [ "x86_64-maccatalyst" ],
394
          "names": [
395
              "/u/l/l/libfoo.dylib",
396
              "/u/l/l/libbar.dylib"
397
          ]
398
      },
399
      {
400
          "targets": [ "arm64-maccatalyst" ],
401
          "names": [ "/u/l/l/libArmOnly.dylib" ]
402
      }
403
  ]
404
}
405
})";
406

407
  Expected<TBDFile> Result =
408
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
409
  EXPECT_TRUE(!!Result);
410
  TBDFile File = std::move(Result.get());
411
  EXPECT_EQ(FileType::TBD_V5, File->getFileType());
412
  EXPECT_EQ(std::string("/usr/lib/libFoo.dylib"), File->getInstallName());
413
  EXPECT_TRUE(File->isApplicationExtensionSafe());
414
  EXPECT_TRUE(File->isTwoLevelNamespace());
415
  EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion());
416
  EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
417
  EXPECT_EQ(8U, File->getSwiftABIVersion());
418

419
  TargetList AllTargets = {
420
      Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
421
      Target(AK_arm64, PLATFORM_MACOS, VersionTuple(10, 14)),
422
      Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(12, 1)),
423
  };
424
  EXPECT_EQ(mapToPlatformSet(AllTargets), File->getPlatforms());
425
  EXPECT_EQ(mapToArchitectureSet(AllTargets), File->getArchitectures());
426

427
  InterfaceFileRef ReexportA("/u/l/l/libArmOnly.dylib",
428
                             {Target(AK_arm64, PLATFORM_MACCATALYST)});
429
  InterfaceFileRef ReexportB("/u/l/l/libbar.dylib",
430
                             {Target(AK_x86_64, PLATFORM_MACCATALYST)});
431
  InterfaceFileRef ReexportC("/u/l/l/libfoo.dylib",
432
                             {Target(AK_x86_64, PLATFORM_MACCATALYST)});
433
  EXPECT_EQ(3U, File->reexportedLibraries().size());
434
  EXPECT_EQ(ReexportA, File->reexportedLibraries().at(0));
435
  EXPECT_EQ(ReexportB, File->reexportedLibraries().at(1));
436
  EXPECT_EQ(ReexportC, File->reexportedLibraries().at(2));
437
}
438

439
TEST(TBDv5, ReadMultipleDocuments) {
440
  static const char TBDv5File[] = R"({ 
441
"tapi_tbd_version": 5,
442
"main_library": {
443
  "target_info": [
444
    {
445
      "target": "armv7-ios",
446
      "min_deployment": "11.0" 
447
    }
448
  ],
449
  "install_names":[
450
    { "name":"/S/L/F/Foo.framework/Foo" }
451
  ],
452
  "reexported_libraries": [
453
    { "names": ["/u/l/l/libfoo.dylib"] }
454
  ]
455
},
456
"libraries": [
457
  {
458
    "target_info": [
459
      {
460
        "target": "armv7-ios",
461
        "min_deployment": "11.0" 
462
      }
463
    ],
464
    "install_names":[
465
      { "name":"/u/l/l/libfoo.dylib" }
466
    ],
467
    "flags":[ 
468
      { "attributes": ["not_app_extension_safe"] }
469
    ], 
470
    "exported_symbols": [
471
      {
472
        "data": {
473
          "thread_local": [ "_globalVar" ],
474
          "objc_class": [ "ClassData", "ClassA", "ClassB"], 
475
          "objc_eh_type": [ "ClassA", "ClassB" ]
476
        },
477
        "text": {
478
          "global": [ "_funcFoo" ]
479
        }
480
      }
481
    ]
482
  }
483
]})";
484

485
  Expected<TBDFile> Result =
486
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
487
  EXPECT_TRUE(!!Result);
488
  TBDFile File = std::move(Result.get());
489
  EXPECT_EQ(FileType::TBD_V5, File->getFileType());
490
  EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName());
491
  EXPECT_TRUE(File->isTwoLevelNamespace());
492
  EXPECT_TRUE(File->isApplicationExtensionSafe());
493

494
  TargetList Targets(File->targets().begin(), File->targets().end());
495
  Target iOSTarget(AK_armv7, PLATFORM_IOS, VersionTuple(11, 0));
496
  EXPECT_EQ(TargetList{iOSTarget}, Targets);
497
  std::vector<const Symbol *> Symbols(File->symbols().begin(),
498
                                      File->symbols().end());
499
  EXPECT_EQ(0U, Symbols.size());
500

501
  InterfaceFileRef Reexport("/u/l/l/libfoo.dylib", {iOSTarget});
502
  EXPECT_EQ(1U, File->reexportedLibraries().size());
503
  EXPECT_EQ(Reexport, File->reexportedLibraries().at(0));
504

505
  // Check inlined library.
506
  EXPECT_EQ(1U, File->documents().size());
507
  TBDReexportFile Document = File->documents().front();
508
  Targets = {Document->targets().begin(), Document->targets().end()};
509
  EXPECT_EQ(TargetList{iOSTarget}, Targets);
510
  EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document->getInstallName());
511
  EXPECT_EQ(0U, Document->getSwiftABIVersion());
512
  EXPECT_TRUE(Document->isTwoLevelNamespace());
513
  EXPECT_FALSE(Document->isApplicationExtensionSafe());
514

515
  ExportedSymbolSeq Exports;
516
  for (const auto *Sym : Document->symbols())
517
    Exports.emplace_back(
518
        ExportedSymbol{Sym->getKind(),
519
                       std::string(Sym->getName()),
520
                       Sym->isWeakDefined() || Sym->isWeakReferenced(),
521
                       Sym->isThreadLocalValue(),
522
                       Sym->isData(),
523
                       {iOSTarget}});
524

525
  llvm::sort(Exports);
526
  ExportedSymbolSeq ExpectedExports = {
527
      {EncodeKind::GlobalSymbol, "_funcFoo", false, false, false, {iOSTarget}},
528
      {EncodeKind::GlobalSymbol, "_globalVar", false, true, true, {iOSTarget}},
529
      {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, {iOSTarget}},
530
      {EncodeKind::ObjectiveCClass, "ClassB", false, false, true, {iOSTarget}},
531
      {EncodeKind::ObjectiveCClass,
532
       "ClassData",
533
       false,
534
       false,
535
       true,
536
       {iOSTarget}},
537
      {EncodeKind::ObjectiveCClassEHType,
538
       "ClassA",
539
       false,
540
       false,
541
       true,
542
       {iOSTarget}},
543
      {EncodeKind::ObjectiveCClassEHType,
544
       "ClassB",
545
       false,
546
       false,
547
       true,
548
       {iOSTarget}},
549
  };
550

551
  EXPECT_EQ(ExpectedExports.size(), Exports.size());
552
  EXPECT_TRUE(
553
      std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports)));
554
}
555

556
TEST(TBDv5, WriteFile) {
557
  static const char TBDv5File[] = R"({
558
"tapi_tbd_version": 5,
559
"main_library": {
560
  "target_info": [
561
    {
562
      "target": "x86_64-macos",
563
      "min_deployment": "10.14"
564
    },
565
    {
566
      "target": "arm64-macos",
567
      "min_deployment": "10.14"
568
    },
569
    {
570
      "target": "arm64-maccatalyst",
571
      "min_deployment": "12.1"
572
    }
573
  ],
574
  "install_names": [
575
    {
576
        "name": "@rpath/S/L/F/Foo.framework/Foo"
577
    }
578
  ],
579
  "current_versions": [
580
    {
581
        "version": "1.2"
582
    }
583
  ],
584
  "compatibility_versions": [
585
    { "version": "1.1" }
586
  ],
587
  "flags": [
588
    {
589
      "attributes": [
590
            "flat_namespace"
591
        ]
592
    }
593
  ],
594
  "rpaths": [
595
    {
596
      "targets": [
597
          "x86_64-macos"
598
      ],
599
      "paths": [
600
          "@executable_path/.../Frameworks"
601
      ]
602
    }
603
  ],
604
  "parent_umbrellas": [
605
    {
606
      "umbrella": "System"
607
    }
608
  ],
609
  "allowable_clients": [
610
    {
611
        "clients": [
612
            "ClientA",
613
            "ClientB"
614
        ]
615
    }
616
  ],
617
  "reexported_libraries": [
618
    {
619
        "names": [
620
            "/u/l/l/libfoo.dylib",
621
            "/u/l/l/libbar.dylib"
622
        ]
623
    }
624
  ],
625
  "exported_symbols": [
626
    {
627
        "targets": [
628
            "x86_64-macos",
629
            "arm64-macos"
630
        ],
631
        "data": {
632
            "global": [
633
                "_global"
634
            ],
635
            "objc_class": [
636
                "ClassA"
637
            ],
638
            "weak": [],
639
            "thread_local": []
640
        },
641
        "text": {
642
            "global": [
643
                "_func"
644
            ],
645
            "weak": [],
646
            "thread_local": []
647
        }
648
    },
649
    {
650
      "targets": [
651
          "x86_64-macos"
652
      ],
653
      "data": {
654
          "global": [
655
              "_globalVar"
656
          ],
657
          "objc_class": [
658
              "ClassA",
659
              "ClassB",
660
              "ClassData"
661
          ],
662
          "objc_eh_type": [
663
              "ClassA",
664
              "ClassB"
665
          ],
666
          "objc_ivar": [
667
              "ClassA.ivar1",
668
              "ClassA.ivar2",
669
              "ClassC.ivar1"
670
          ]
671
      },
672
      "text": {
673
          "global": [
674
              "_funcFoo"
675
          ]
676
      }
677
    }
678
  ],
679
  "reexported_symbols": [
680
    {
681
        "data": {
682
            "global": [
683
                "_globalRe"
684
            ],
685
            "objc_class": [
686
                "ClassRexport"
687
            ]
688
        },
689
        "text": {
690
            "global": [
691
                "_funcA"
692
            ]
693
        }
694
    }
695
  ],
696
  "undefined_symbols": [
697
    {
698
        "targets": [
699
            "x86_64-macos"
700
        ],
701
        "data": {
702
            "global": [
703
                "_globalBind"
704
            ],
705
            "weak": [
706
                "referenced_sym"
707
            ]
708
        }
709
    }
710
  ]
711
}})";
712

713
  InterfaceFile File;
714
  File.setFileType(FileType::TBD_V5);
715

716
  TargetList AllTargets = {
717
      Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
718
      Target(AK_arm64, PLATFORM_MACOS, VersionTuple(10, 14)),
719
      Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(12, 1)),
720
  };
721
  File.addTargets(AllTargets);
722
  File.setInstallName("@rpath/S/L/F/Foo.framework/Foo");
723
  File.setCurrentVersion(PackedVersion(1, 2, 0));
724
  File.setCompatibilityVersion(PackedVersion(1, 1, 0));
725
  File.addRPath("@executable_path/.../Frameworks", AllTargets[0]);
726

727
  for (const auto &Targ : AllTargets) {
728
    File.addParentUmbrella(Targ, "System");
729
    File.addAllowableClient("ClientA", Targ);
730
    File.addAllowableClient("ClientB", Targ);
731
    File.addReexportedLibrary("/u/l/l/libfoo.dylib", Targ);
732
    File.addReexportedLibrary("/u/l/l/libbar.dylib", Targ);
733
  }
734

735
  SymbolFlags Flags = SymbolFlags::None;
736
  // Exports.
737
  File.addSymbol(EncodeKind::GlobalSymbol, "_global",
738
                 {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data);
739
  File.addSymbol(EncodeKind::GlobalSymbol, "_func",
740
                 {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Text);
741
  File.addSymbol(EncodeKind::ObjectiveCClass, "ClassA",
742
                 {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data);
743
  File.addSymbol(EncodeKind::GlobalSymbol, "_funcFoo", {AllTargets[0]},
744
                 Flags | SymbolFlags::Text);
745
  File.addSymbol(EncodeKind::GlobalSymbol, "_globalVar", {AllTargets[0]},
746
                 Flags | SymbolFlags::Data);
747
  File.addSymbol(EncodeKind::ObjectiveCClass, "ClassData", {AllTargets[0]},
748
                 Flags | SymbolFlags::Data);
749
  File.addSymbol(EncodeKind::ObjectiveCClassEHType, "ClassA", {AllTargets[0]},
750
                 Flags | SymbolFlags::Data);
751
  File.addSymbol(EncodeKind::ObjectiveCClassEHType, "ClassB", {AllTargets[0]},
752
                 Flags | SymbolFlags::Data);
753
  File.addSymbol(EncodeKind::ObjectiveCInstanceVariable, "ClassA.ivar1",
754
                 {AllTargets[0]}, Flags | SymbolFlags::Data);
755
  File.addSymbol(EncodeKind::ObjectiveCInstanceVariable, "ClassA.ivar2",
756
                 {AllTargets[0]}, Flags | SymbolFlags::Data);
757
  File.addSymbol(EncodeKind::ObjectiveCInstanceVariable, "ClassC.ivar1",
758
                 {AllTargets[0]}, Flags | SymbolFlags::Data);
759

760
  // Reexports.
761
  Flags = SymbolFlags::Rexported;
762
  File.addSymbol(EncodeKind::GlobalSymbol, "_globalRe", AllTargets,
763
                 Flags | SymbolFlags::Data);
764
  File.addSymbol(EncodeKind::GlobalSymbol, "_funcA", AllTargets,
765
                 Flags | SymbolFlags::Text);
766
  File.addSymbol(EncodeKind::ObjectiveCClass, "ClassRexport", AllTargets,
767
                 Flags | SymbolFlags::Data);
768

769
  // Undefineds.
770
  Flags = SymbolFlags::Undefined;
771
  File.addSymbol(EncodeKind::GlobalSymbol, "_globalBind", {AllTargets[0]},
772
                 Flags | SymbolFlags::Data);
773
  File.addSymbol(EncodeKind::GlobalSymbol, "referenced_sym", {AllTargets[0]},
774
                 Flags | SymbolFlags::Data | SymbolFlags::WeakReferenced);
775

776
  File.setTwoLevelNamespace(false);
777
  File.setApplicationExtensionSafe(true);
778

779
  // Write out file then process it back into IF and compare equality
780
  // against TBDv5File.
781
  SmallString<4096> Buffer;
782
  raw_svector_ostream OS(Buffer);
783
  Error Result = TextAPIWriter::writeToStream(OS, File);
784
  EXPECT_FALSE(Result);
785

786
  Expected<TBDFile> Input =
787
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Input.tbd"));
788
  EXPECT_TRUE(!!Input);
789
  TBDFile InputFile = std::move(Input.get());
790

791
  Expected<TBDFile> Output =
792
      TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
793
  EXPECT_TRUE(!!Output);
794
  TBDFile OutputFile = std::move(Output.get());
795
  EXPECT_EQ(*InputFile, *OutputFile);
796
}
797

798
TEST(TBDv5, WriteMultipleDocuments) {
799
  static const char TBDv5File[] = R"({ 
800
"tapi_tbd_version": 5,
801
"main_library": {
802
  "target_info": [
803
    {
804
      "target": "armv7-ios",
805
      "min_deployment": "11.0" 
806
    }
807
  ],
808
  "install_names":[
809
    { "name":"/S/L/F/Foo.framework/Foo" }
810
  ],
811
  "reexported_libraries": [
812
    { "names": ["/u/l/l/libfoo.dylib"] 
813
    }
814
  ]
815
},
816
"libraries": [
817
  {
818
    "target_info": [
819
      {
820
        "target": "armv7-ios",
821
        "min_deployment": "11.0" 
822
      },
823
      {
824
        "target": "armv7s-ios",
825
        "min_deployment": "11.0" 
826
      }
827
    ],
828
    "install_names":[
829
      { "name":"/u/l/l/libfoo.dylib" }
830
    ],
831
    "current_versions": [
832
      {
833
          "version": "2.1.1"
834
      }
835
    ],
836
    "rpaths": [
837
      {
838
        "targets": [
839
            "armv7-ios"
840
        ],
841
        "paths": [
842
            "@executable_path/.../Frameworks"
843
        ]
844
      }],
845
    "reexported_libraries": [ { "names": ["@rpath/libfoo.dylib"] } ],
846
    "flags":[ 
847
      { "attributes": ["not_app_extension_safe"] }
848
    ], 
849
    "exported_symbols": [
850
      {
851
        "text": {
852
          "global": [ "_funcFoo" ]
853
        }
854
      }
855
    ]
856
  },
857
  {
858
    "target_info": [
859
      {
860
        "target": "armv7-ios",
861
        "min_deployment": "11.0" 
862
      }
863
    ],
864
    "install_names":[
865
      { "name":"@rpath/libfoo.dylib" }
866
    ],
867
    "exported_symbols": [
868
      {
869
        "data": {
870
          "global": [ "_varFooBaz" ]
871
        }
872
      }
873
    ]
874
  }
875
]})";
876

877
  InterfaceFile File;
878
  File.setFileType(FileType::TBD_V5);
879

880
  TargetList AllTargets = {
881
      Target(AK_armv7, PLATFORM_IOS, VersionTuple(11, 0)),
882
      Target(AK_armv7s, PLATFORM_IOS, VersionTuple(11, 0)),
883
  };
884
  File.setInstallName("/S/L/F/Foo.framework/Foo");
885
  File.addTarget(AllTargets[0]);
886
  File.setCurrentVersion(PackedVersion(1, 0, 0));
887
  File.setCompatibilityVersion(PackedVersion(1, 0, 0));
888
  File.addReexportedLibrary("/u/l/l/libfoo.dylib", AllTargets[0]);
889
  File.setTwoLevelNamespace();
890
  File.setApplicationExtensionSafe(true);
891

892
  InterfaceFile NestedFile;
893
  NestedFile.setFileType(FileType::TBD_V5);
894
  NestedFile.setInstallName("/u/l/l/libfoo.dylib");
895
  NestedFile.addTargets(AllTargets);
896
  NestedFile.setCompatibilityVersion(PackedVersion(1, 0, 0));
897
  NestedFile.setTwoLevelNamespace();
898
  NestedFile.setApplicationExtensionSafe(false);
899
  NestedFile.setCurrentVersion(PackedVersion(2, 1, 1));
900
  NestedFile.addRPath("@executable_path/.../Frameworks", AllTargets[0]);
901
  for (const auto &Targ : AllTargets)
902
    NestedFile.addReexportedLibrary("@rpath/libfoo.dylib", Targ);
903
  NestedFile.addSymbol(EncodeKind::GlobalSymbol, "_funcFoo", AllTargets,
904
                       SymbolFlags::Text);
905
  File.addDocument(std::make_shared<InterfaceFile>(std::move(NestedFile)));
906

907
  InterfaceFile NestedFileB;
908
  NestedFileB.setFileType(FileType::TBD_V5);
909
  NestedFileB.setInstallName("@rpath/libfoo.dylib");
910
  NestedFileB.addTarget(AllTargets[0]);
911
  NestedFileB.setCompatibilityVersion(PackedVersion(1, 0, 0));
912
  NestedFileB.setCurrentVersion(PackedVersion(1, 0, 0));
913
  NestedFileB.setTwoLevelNamespace();
914
  NestedFileB.setApplicationExtensionSafe(true);
915
  NestedFileB.addSymbol(EncodeKind::GlobalSymbol, "_varFooBaz", {AllTargets[0]},
916
                        SymbolFlags::Data);
917
  File.addDocument(std::make_shared<InterfaceFile>(std::move(NestedFileB)));
918

919
  // Write out file then process it back into IF and compare equality
920
  // against TBDv5File.
921
  SmallString<4096> Buffer;
922
  raw_svector_ostream OS(Buffer);
923
  Error Result = TextAPIWriter::writeToStream(OS, File, FileType::Invalid,
924
                                              /*Compact=*/true);
925
  EXPECT_FALSE(Result);
926

927
  Expected<TBDFile> Input =
928
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Input.tbd"));
929
  EXPECT_TRUE(!!Input);
930
  TBDFile InputFile = std::move(Input.get());
931

932
  Expected<TBDFile> Output =
933
      TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
934
  EXPECT_TRUE(!!Output);
935
  TBDFile OutputFile = std::move(Output.get());
936
  EXPECT_EQ(*InputFile, *OutputFile);
937
}
938

939
TEST(TBDv5, Target_Simulator) {
940
  static const char TBDv5File[] = R"({ 
941
"tapi_tbd_version": 5,
942
"main_library": {
943
  "target_info": [
944
    {
945
      "target": "arm64-ios-simulator",
946
      "min_deployment": "11.0"
947
    },
948
    {
949
      "target": "x86_64-ios-simulator",
950
      "min_deployment": "11.3" 
951
    }
952
  ],
953
  "install_names":[
954
    { "name":"/S/L/F/Foo.framework/Foo" }
955
  ]
956
}})";
957

958
  Expected<TBDFile> Result =
959
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
960
  EXPECT_TRUE(!!Result);
961
  TBDFile File = std::move(Result.get());
962
  EXPECT_EQ(FileType::TBD_V5, File->getFileType());
963
  TargetList ExpectedTargets = {
964
      Target(AK_x86_64, PLATFORM_IOSSIMULATOR, VersionTuple(11, 3)),
965
      Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(14, 0)),
966
  };
967
  TargetList Targets{File->targets().begin(), File->targets().end()};
968
  llvm::sort(Targets);
969
  EXPECT_EQ(Targets, ExpectedTargets);
970

971
  SmallString<4096> Buffer;
972
  raw_svector_ostream OS(Buffer);
973
  Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
974
  EXPECT_TRUE(!WriteResult);
975

976
  Expected<TBDFile> Output =
977
      TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
978
  EXPECT_TRUE(!!Output);
979
  TBDFile WriteResultFile = std::move(Output.get());
980
  EXPECT_EQ(*File, *WriteResultFile);
981
}
982

983
TEST(TBDv5, Target_UnsupportedMinOS) {
984
  static const char TBDv5File[] = R"({ 
985
"tapi_tbd_version": 5,
986
"main_library": {
987
  "target_info": [
988
    {
989
      "target": "arm64-macos",
990
      "min_deployment": "10.14"
991
    },
992
    {
993
      "target": "x86_64-macos",
994
      "min_deployment": "10.14" 
995
    }
996
  ],
997
  "install_names":[
998
    { "name":"/S/L/F/Foo.framework/Foo" }
999
  ]
1000
}})";
1001

1002
  Expected<TBDFile> Result =
1003
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1004
  EXPECT_TRUE(!!Result);
1005
  TBDFile File = std::move(Result.get());
1006
  EXPECT_EQ(FileType::TBD_V5, File->getFileType());
1007
  TargetList ExpectedTargets = {
1008
      Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
1009
      Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0)),
1010
  };
1011
  TargetList Targets{File->targets().begin(), File->targets().end()};
1012
  llvm::sort(Targets);
1013
  EXPECT_EQ(Targets, ExpectedTargets);
1014

1015
  SmallString<4096> Buffer;
1016
  raw_svector_ostream OS(Buffer);
1017
  Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
1018
  EXPECT_TRUE(!WriteResult);
1019

1020
  Expected<TBDFile> Output =
1021
      TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
1022
  EXPECT_TRUE(!!Output);
1023
  TBDFile WriteResultFile = std::move(Output.get());
1024
  EXPECT_EQ(*File, *WriteResultFile);
1025
}
1026

1027
TEST(TBDv5, MisspelledKey) {
1028
  static const char TBDv5File[] = R"({ 
1029
"tapi_tbd_version": 5,
1030
"main_library": {
1031
  "target_info": [
1032
    {
1033
      "target": "arm64-ios-simulator",
1034
      "min_deployment": "11.0"
1035
    }
1036
  ],
1037
  "intall_names":[
1038
    { "name":"/S/L/F/Foo.framework/Foo" }
1039
  ]
1040
}})";
1041

1042
  Expected<TBDFile> Result =
1043
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1044
  EXPECT_FALSE(!!Result);
1045
  std::string ErrorMessage = toString(Result.takeError());
1046
  EXPECT_EQ("invalid install_names section\n", ErrorMessage);
1047
}
1048

1049
TEST(TBDv5, InvalidVersion) {
1050
  static const char TBDv5File[] = R"({ 
1051
"tapi_tbd_version": 11,
1052
"main_library": {
1053
  "target_info": [
1054
    {
1055
      "target": "arm64-ios-simulator",
1056
      "min_deployment": "11.0"
1057
    }
1058
  ],
1059
  "install_names":[
1060
    { "name":"/S/L/F/Foo.framework/Foo" }
1061
  ]
1062
}})";
1063

1064
  Expected<TBDFile> Result =
1065
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1066
  EXPECT_FALSE(!!Result);
1067
  std::string ErrorMessage = toString(Result.takeError());
1068
  EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage);
1069
}
1070

1071
TEST(TBDv5, MissingRequiredKey) {
1072
  static const char TBDv5File[] = R"({ 
1073
"main_library": {
1074
  "target_info": [
1075
    {
1076
      "target": "arm64-ios-simulator",
1077
      "min_deployment": "11.0"
1078
    }
1079
  ],
1080
  "install_names":[
1081
    { "name":"/S/L/F/Foo.framework/Foo" }
1082
  ]
1083
}})";
1084

1085
  Expected<TBDFile> Result =
1086
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1087
  EXPECT_FALSE(!!Result);
1088
  std::string ErrorMessage = toString(Result.takeError());
1089
  EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage);
1090
}
1091

1092
TEST(TBDv5, InvalidSymbols) {
1093
  static const char TBDv5File[] = R"({ 
1094
"tapi_tbd_version": 5,
1095
"main_library": {
1096
  "target_info": [
1097
    {
1098
      "target": "arm64-driverkit",
1099
      "min_deployment": "11.0"
1100
    }
1101
  ],
1102
  "install_names":[
1103
    { "name":"/S/L/F/Foo.framework/Foo" }
1104
  ],
1105
  "exported_symbols": [
1106
    {
1107
      "daa": {
1108
        "global": {
1109
            "weak": []
1110
          }
1111
      }
1112
    }
1113
  ]
1114
}})";
1115

1116
  Expected<TBDFile> Result =
1117
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1118
  EXPECT_FALSE(!!Result);
1119
  std::string ErrorMessage = toString(Result.takeError());
1120
  EXPECT_EQ("invalid exported_symbols section\n", ErrorMessage);
1121
}
1122

1123
TEST(TBDv5, DefaultMinOS) {
1124
  static const char TBDv5File[] = R"({ 
1125
"tapi_tbd_version": 5,
1126
"main_library": {
1127
  "target_info": [
1128
    {
1129
      "target": "arm64-ios-simulator"
1130
    }
1131
  ],
1132
  "install_names":[
1133
    { "name":"/S/L/F/Foo.framework/Foo" }
1134
  ]
1135
}})";
1136

1137
  Expected<TBDFile> Result =
1138
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1139
  EXPECT_TRUE(!!Result);
1140
  TBDFile File = std::move(Result.get());
1141
  EXPECT_EQ(FileType::TBD_V5, File->getFileType());
1142
  EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName());
1143
  EXPECT_TRUE(File->targets().begin() != File->targets().end());
1144
  EXPECT_EQ(*File->targets().begin(),
1145
            Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(0, 0)));
1146
}
1147

1148
TEST(TBDv5, InvalidMinOS) {
1149
  static const char TBDv5File[] = R"({ 
1150
"tapi_tbd_version": 5,
1151
"main_library": {
1152
  "target_info": [
1153
    {
1154
      "target": "arm64-ios-simulator",
1155
      "min_deployment": "swift-abi"
1156
    }
1157
  ],
1158
  "install_names":[
1159
    { "name":"/S/L/F/Foo.framework/Foo" }
1160
  ]
1161
}})";
1162

1163
  Expected<TBDFile> Result =
1164
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1165
  EXPECT_FALSE(!!Result);
1166
  std::string ErrorMessage = toString(Result.takeError());
1167
  EXPECT_EQ("invalid min_deployment section\n", ErrorMessage);
1168
}
1169

1170
TEST(TBDv5, SimSupport) {
1171
  static const char TBDv5File[] = R"({ 
1172
"tapi_tbd_version": 5,
1173
"main_library": {
1174
  "target_info": [
1175
    {
1176
      "target": "arm64-macos",
1177
      "min_deployment": "11.1" 
1178
    }
1179
  ],
1180
  "install_names":[
1181
    { "name":"/S/L/F/Foo.framework/Foo" }
1182
  ],
1183
  "flags":[ 
1184
    { "attributes": ["sim_support"] }
1185
  ] 
1186
}})";
1187

1188
  Expected<TBDFile> Result =
1189
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1190
  EXPECT_TRUE(!!Result);
1191
  Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 1));
1192
  TBDFile ReadFile = std::move(Result.get());
1193
  EXPECT_EQ(FileType::TBD_V5, ReadFile->getFileType());
1194
  EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1195
            ReadFile->getInstallName());
1196
  EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end());
1197
  EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget);
1198
  EXPECT_TRUE(ReadFile->hasSimulatorSupport());
1199
}
1200

1201
TEST(TBDv5, NotForSharedCache) {
1202
  static const char TBDv5File[] = R"({ 
1203
"tapi_tbd_version": 5,
1204
"main_library": {
1205
  "target_info": [
1206
    {
1207
      "target": "arm64-macos",
1208
      "min_deployment": "11.1" 
1209
    }
1210
  ],
1211
  "install_names":[
1212
    { "name":"/S/L/F/Foo.framework/Foo" }
1213
  ],
1214
  "flags":[ 
1215
    { "attributes": ["not_for_dyld_shared_cache"] }
1216
  ] 
1217
}})";
1218

1219
  Expected<TBDFile> Result =
1220
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1221
  EXPECT_TRUE(!!Result);
1222
  Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 1));
1223
  TBDFile ReadFile = std::move(Result.get());
1224
  EXPECT_EQ(FileType::TBD_V5, ReadFile->getFileType());
1225
  EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1226
            ReadFile->getInstallName());
1227
  EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end());
1228
  EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget);
1229
  EXPECT_FALSE(ReadFile->hasSimulatorSupport());
1230
  EXPECT_TRUE(ReadFile->isOSLibNotForSharedCache());
1231
}
1232

1233
TEST(TBDv5, ObjCInterfaces) {
1234
  static const char TBDv5File[] = R"({ 
1235
"tapi_tbd_version": 5,
1236
"main_library": {
1237
  "target_info": [
1238
    {
1239
      "target": "arm64-ios-simulator",
1240
      "min_deployment": "14.0"
1241
    }
1242
  ],
1243
  "install_names":[
1244
    { "name":"/S/L/F/Foo.framework/Foo" }
1245
  ],
1246
  "exported_symbols": [
1247
    {
1248
      "data": {
1249
         "global": [
1250
              "_global",
1251
              "_OBJC_METACLASS_$_Standalone",
1252
              "_OBJC_CLASS_$_Standalone2"
1253
          ],
1254
          "weak": ["_OBJC_EHTYPE_$_NSObject"],
1255
          "objc_class": [
1256
              "ClassA",
1257
              "ClassB"
1258
          ],
1259
          "objc_eh_type": ["ClassA"]
1260
      }
1261
    }]
1262
}})";
1263

1264
  Expected<TBDFile> Result =
1265
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1266
  EXPECT_TRUE(!!Result);
1267
  TBDFile File = std::move(Result.get());
1268
  EXPECT_EQ(FileType::TBD_V5, File->getFileType());
1269
  Target ExpectedTarget =
1270
      Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(14, 0));
1271
  EXPECT_EQ(*File->targets().begin(), ExpectedTarget);
1272

1273
  // Check Symbols.
1274
  ExportedSymbolSeq Exports;
1275
  for (const auto *Sym : File->symbols()) {
1276
    ExportedSymbol Temp =
1277
        ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
1278
                       Sym->isWeakDefined() || Sym->isWeakReferenced(),
1279
                       Sym->isThreadLocalValue(), Sym->isData()};
1280
    Exports.emplace_back(std::move(Temp));
1281
  }
1282
  llvm::sort(Exports);
1283

1284
  std::vector<ExportedSymbol> ExpectedExports = {
1285
      {EncodeKind::GlobalSymbol, "_OBJC_CLASS_$_Standalone2", false, false,
1286
       true},
1287
      {EncodeKind::GlobalSymbol, "_OBJC_EHTYPE_$_NSObject", true, false, true},
1288
      {EncodeKind::GlobalSymbol, "_OBJC_METACLASS_$_Standalone", false, false,
1289
       true},
1290
      {EncodeKind::GlobalSymbol, "_global", false, false, true},
1291
      {EncodeKind::ObjectiveCClass, "ClassA", false, false, true},
1292
      {EncodeKind::ObjectiveCClass, "ClassB", false, false, true},
1293
      {EncodeKind::ObjectiveCClassEHType, "ClassA", false, false, true}};
1294

1295
  EXPECT_EQ(ExpectedExports.size(), Exports.size());
1296
  EXPECT_TRUE(
1297
      std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports)));
1298

1299
  SmallString<4096> Buffer;
1300
  raw_svector_ostream OS(Buffer);
1301
  Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
1302
  EXPECT_TRUE(!WriteResult);
1303

1304
  Expected<TBDFile> Output =
1305
      TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
1306
  EXPECT_TRUE(!!Output);
1307
  TBDFile WriteResultFile = std::move(Output.get());
1308
  EXPECT_EQ(*File, *WriteResultFile);
1309
}
1310

1311
TEST(TBDv5, MergeIF) {
1312
  static const char TBDv5FileA[] = R"({
1313
"tapi_tbd_version": 5,
1314
"main_library": {
1315
  "target_info": [
1316
    {
1317
      "target": "x86_64-macos",
1318
      "min_deployment": "10.14"
1319
    },
1320
    {
1321
      "target": "arm64-macos",
1322
      "min_deployment": "10.14"
1323
    },
1324
    {
1325
      "target": "arm64-maccatalyst",
1326
      "min_deployment": "12.1"
1327
    }
1328
  ],
1329
  "flags": [
1330
    {
1331
      "targets": [
1332
            "x86_64-macos"
1333
        ],
1334
      "attributes": [
1335
            "flat_namespace"
1336
        ]
1337
    }
1338
  ],
1339
  "install_names": [
1340
    {
1341
        "name": "/S/L/F/Foo.framework/Foo"
1342
    }
1343
  ],
1344
  "current_versions": [
1345
    {
1346
        "version": "1.2"
1347
    }
1348
  ],
1349
  "compatibility_versions": [
1350
    { "version": "1.1" }
1351
  ],
1352
  "rpaths": [
1353
    {
1354
      "targets": [
1355
          "x86_64-macos"
1356
      ],
1357
      "paths": [
1358
          "@executable_path/.../Frameworks"
1359
      ]
1360
    }
1361
  ],
1362
  "parent_umbrellas": [
1363
    {
1364
      "umbrella": "System"
1365
    }
1366
  ],
1367
  "allowable_clients": [
1368
    {
1369
        "clients": [
1370
            "ClientA",
1371
            "ClientB"
1372
        ]
1373
    }
1374
  ],
1375
  "reexported_libraries": [
1376
    {
1377
        "names": [
1378
            "/u/l/l/libfoo.dylib",
1379
            "/u/l/l/libbar.dylib"
1380
        ]
1381
    }
1382
  ],
1383
  "exported_symbols": [
1384
    {
1385
        "targets": [
1386
            "x86_64-macos",
1387
            "arm64-macos"
1388
        ],
1389
        "data": {
1390
            "global": [
1391
                "_global"
1392
            ],
1393
            "objc_class": [
1394
                "ClassA"
1395
            ],
1396
            "weak": [],
1397
            "thread_local": []
1398
        },
1399
        "text": {
1400
            "global": [
1401
                "_func"
1402
            ],
1403
            "weak": [],
1404
            "thread_local": []
1405
        }
1406
    },
1407
    {
1408
      "targets": [
1409
          "x86_64-macos"
1410
      ],
1411
      "data": {
1412
          "global": [
1413
              "_globalVar"
1414
          ],
1415
          "objc_class": [
1416
              "ClassA",
1417
              "ClassB",
1418
              "ClassData"
1419
          ],
1420
          "objc_eh_type": [
1421
              "ClassA",
1422
              "ClassB"
1423
          ],
1424
          "objc_ivar": [
1425
              "ClassA.ivar1",
1426
              "ClassA.ivar2",
1427
              "ClassC.ivar1"
1428
          ]
1429
      },
1430
      "text": {
1431
          "global": [
1432
              "_funcFoo"
1433
          ]
1434
      }
1435
    }
1436
  ],
1437
  "reexported_symbols": [
1438
    {
1439
        "targets": [
1440
            "x86_64-macos",
1441
            "arm64-macos"
1442
        ],
1443
        "data": {
1444
            "global": [
1445
                "_globalRe"
1446
            ],
1447
            "objc_class": [
1448
                "ClassRexport"
1449
            ]
1450
        },
1451
        "text": {
1452
            "global": [
1453
                "_funcA"
1454
            ]
1455
        }
1456
    }
1457
  ],
1458
  "undefined_symbols": [
1459
    {
1460
        "targets": [
1461
            "x86_64-macos"
1462
        ],
1463
        "data": {
1464
            "global": [
1465
                "_globalBind"
1466
            ],
1467
            "weak": [
1468
                "referenced_sym"
1469
            ]
1470
        }
1471
    }
1472
  ]
1473
},
1474
"libraries": []
1475
})";
1476

1477
  static const char TBDv5FileB[] = R"({
1478
"tapi_tbd_version": 5,
1479
"main_library": {
1480
  "target_info": [
1481
    {
1482
      "target": "x86_64-macos",
1483
      "min_deployment": "10.14"
1484
    },
1485
    {
1486
      "target": "arm64-macos",
1487
      "min_deployment": "10.14"
1488
    },
1489
    {
1490
      "target": "arm64-maccatalyst",
1491
      "min_deployment": "12.1"
1492
    }
1493
  ],
1494
  "flags": [
1495
    {
1496
      "targets": [
1497
            "x86_64-macos"
1498
        ],
1499
      "attributes": [
1500
            "flat_namespace"
1501
        ]
1502
    }
1503
  ],
1504
  "install_names": [
1505
    {
1506
        "name": "/S/L/F/Foo.framework/Foo"
1507
    }
1508
  ],
1509
  "current_versions": [
1510
    {
1511
        "version": "1.2"
1512
    }
1513
  ],
1514
  "compatibility_versions": [
1515
    { "version": "1.1" }
1516
  ],
1517
  "exported_symbols": [
1518
    {
1519
        "targets": [
1520
            "x86_64-macos",
1521
            "arm64-macos"
1522
        ],
1523
        "data": {
1524
            "global": [
1525
                "_globalZ"
1526
            ],
1527
            "objc_class": [
1528
                "ClassZ"
1529
            ],
1530
            "weak": [],
1531
            "thread_local": []
1532
        },
1533
        "text": {
1534
            "global": [
1535
                "_funcZ"
1536
            ],
1537
            "weak": [],
1538
            "thread_local": []
1539
        }
1540
    },
1541
    {
1542
      "targets": [
1543
          "x86_64-macos"
1544
      ],
1545
      "data": {
1546
          "global": [
1547
              "_globalVarZ"
1548
          ],
1549
          "objc_class": [
1550
              "ClassZ",
1551
              "ClassF"
1552
          ],
1553
          "objc_eh_type": [
1554
              "ClassZ",
1555
              "ClassF"
1556
          ],
1557
          "objc_ivar": [
1558
              "ClassZ.ivar1",
1559
              "ClassZ.ivar2",
1560
              "ClassF.ivar1"
1561
          ]
1562
      },
1563
      "text": {
1564
          "global": [
1565
              "_funcFooZ"
1566
          ]
1567
      }
1568
    }
1569
  ]
1570
},
1571
"libraries": []
1572
})";
1573

1574
  Expected<TBDFile> ResultA =
1575
      TextAPIReader::get(MemoryBufferRef(TBDv5FileA, "Test.tbd"));
1576
  EXPECT_TRUE(!!ResultA);
1577
  TBDFile FileA = std::move(ResultA.get());
1578

1579
  Expected<TBDFile> ResultB =
1580
      TextAPIReader::get(MemoryBufferRef(TBDv5FileB, "Test.tbd"));
1581
  EXPECT_TRUE(!!ResultB);
1582
  TBDFile FileB = std::move(ResultB.get());
1583

1584
  Expected<TBDFile> MergedResult = FileA->merge(FileB.get());
1585
  EXPECT_TRUE(!!MergedResult);
1586
  TBDFile MergedFile = std::move(MergedResult.get());
1587

1588
  EXPECT_EQ(FileType::TBD_V5, MergedFile->getFileType());
1589
  EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1590
            MergedFile->getInstallName());
1591
  TargetList AllTargets = {
1592
      Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
1593
      Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
1594
      Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
1595
  };
1596
  EXPECT_EQ(mapToPlatformSet(AllTargets), MergedFile->getPlatforms());
1597
  EXPECT_EQ(mapToArchitectureSet(AllTargets), MergedFile->getArchitectures());
1598
  EXPECT_EQ(PackedVersion(1, 2, 0), MergedFile->getCurrentVersion());
1599
  EXPECT_EQ(PackedVersion(1, 1, 0), MergedFile->getCompatibilityVersion());
1600
  EXPECT_TRUE(MergedFile->isApplicationExtensionSafe());
1601
  EXPECT_FALSE(MergedFile->isTwoLevelNamespace());
1602
  EXPECT_EQ(0U, MergedFile->documents().size());
1603
  InterfaceFileRef ClientA("ClientA", AllTargets);
1604
  InterfaceFileRef ClientB("ClientB", AllTargets);
1605
  EXPECT_EQ(2U, MergedFile->allowableClients().size());
1606
  EXPECT_EQ(ClientA, MergedFile->allowableClients().at(0));
1607
  EXPECT_EQ(ClientB, MergedFile->allowableClients().at(1));
1608

1609
  InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
1610
  InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
1611
  EXPECT_EQ(2U, MergedFile->reexportedLibraries().size());
1612
  EXPECT_EQ(ReexportA, MergedFile->reexportedLibraries().at(0));
1613
  EXPECT_EQ(ReexportB, MergedFile->reexportedLibraries().at(1));
1614

1615
  TargetToAttr RPaths = {
1616
      {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"},
1617
  };
1618
  EXPECT_EQ(RPaths, MergedFile->rpaths());
1619

1620
  TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"},
1621
                            {Target(AK_arm64, PLATFORM_MACOS), "System"},
1622
                            {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
1623
  EXPECT_EQ(Umbrellas, MergedFile->umbrellas());
1624

1625
  ExportedSymbolSeq Exports, Reexports, Undefineds;
1626
  for (const auto *Sym : MergedFile->symbols()) {
1627
    TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
1628
    ExportedSymbol Temp =
1629
        ExportedSymbol{Sym->getKind(),
1630
                       std::string(Sym->getName()),
1631
                       Sym->isWeakDefined() || Sym->isWeakReferenced(),
1632
                       Sym->isThreadLocalValue(),
1633
                       Sym->isData(),
1634
                       SymTargets};
1635
    if (Sym->isUndefined())
1636
      Undefineds.emplace_back(std::move(Temp));
1637
    else
1638
      Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
1639
                          : Exports.emplace_back(std::move(Temp));
1640
  }
1641
  llvm::sort(Exports);
1642
  llvm::sort(Reexports);
1643
  llvm::sort(Undefineds);
1644

1645
  TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS),
1646
                             Target(AK_arm64, PLATFORM_MACOS)};
1647

1648
  std::vector<ExportedSymbol> ExpectedExportedSymbols = {
1649
      {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
1650
      {EncodeKind::GlobalSymbol,
1651
       "_funcFoo",
1652
       false,
1653
       false,
1654
       false,
1655
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1656
      {EncodeKind::GlobalSymbol,
1657
       "_funcFooZ",
1658
       false,
1659
       false,
1660
       false,
1661
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1662
      {EncodeKind::GlobalSymbol, "_funcZ", false, false, false, MacOSTargets},
1663
      {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
1664
      {EncodeKind::GlobalSymbol,
1665
       "_globalVar",
1666
       false,
1667
       false,
1668
       true,
1669
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1670
      {EncodeKind::GlobalSymbol,
1671
       "_globalVarZ",
1672
       false,
1673
       false,
1674
       true,
1675
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1676
      {EncodeKind::GlobalSymbol, "_globalZ", false, false, true, MacOSTargets},
1677
      {EncodeKind::ObjectiveCClass,
1678
       "ClassA",
1679
       false,
1680
       false,
1681
       true,
1682
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1683
      {EncodeKind::ObjectiveCClass,
1684
       "ClassB",
1685
       false,
1686
       false,
1687
       true,
1688
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1689
      {EncodeKind::ObjectiveCClass,
1690
       "ClassData",
1691
       false,
1692
       false,
1693
       true,
1694
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1695
      {EncodeKind::ObjectiveCClass,
1696
       "ClassF",
1697
       false,
1698
       false,
1699
       true,
1700
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1701
      {EncodeKind::ObjectiveCClass,
1702
       "ClassZ",
1703
       false,
1704
       false,
1705
       true,
1706
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1707
      {EncodeKind::ObjectiveCClassEHType,
1708
       "ClassA",
1709
       false,
1710
       false,
1711
       true,
1712
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1713
      {EncodeKind::ObjectiveCClassEHType,
1714
       "ClassB",
1715
       false,
1716
       false,
1717
       true,
1718
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1719
      {EncodeKind::ObjectiveCClassEHType,
1720
       "ClassF",
1721
       false,
1722
       false,
1723
       true,
1724
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1725
      {EncodeKind::ObjectiveCClassEHType,
1726
       "ClassZ",
1727
       false,
1728
       false,
1729
       true,
1730
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1731
      {EncodeKind::ObjectiveCInstanceVariable,
1732
       "ClassA.ivar1",
1733
       false,
1734
       false,
1735
       true,
1736
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1737
      {EncodeKind::ObjectiveCInstanceVariable,
1738
       "ClassA.ivar2",
1739
       false,
1740
       false,
1741
       true,
1742
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1743
      {EncodeKind::ObjectiveCInstanceVariable,
1744
       "ClassC.ivar1",
1745
       false,
1746
       false,
1747
       true,
1748
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1749
      {EncodeKind::ObjectiveCInstanceVariable,
1750
       "ClassF.ivar1",
1751
       false,
1752
       false,
1753
       true,
1754
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1755
      {EncodeKind::ObjectiveCInstanceVariable,
1756
       "ClassZ.ivar1",
1757
       false,
1758
       false,
1759
       true,
1760
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1761
      {EncodeKind::ObjectiveCInstanceVariable,
1762
       "ClassZ.ivar2",
1763
       false,
1764
       false,
1765
       true,
1766
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1767
  };
1768

1769
  std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
1770
      {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
1771
      {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
1772
      {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true,
1773
       MacOSTargets},
1774
  };
1775

1776
  std::vector<ExportedSymbol> ExpectedUndefinedSymbols = {
1777
      {EncodeKind::GlobalSymbol,
1778
       "_globalBind",
1779
       false,
1780
       false,
1781
       true,
1782
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1783
      {EncodeKind::GlobalSymbol,
1784
       "referenced_sym",
1785
       true,
1786
       false,
1787
       true,
1788
       {Target(AK_x86_64, PLATFORM_MACOS)}},
1789
  };
1790

1791
  EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
1792
  EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
1793
  EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size());
1794
  EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
1795
                         std::begin(ExpectedExportedSymbols)));
1796
  EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
1797
                         std::begin(ExpectedReexportedSymbols)));
1798
  EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
1799
                         std::begin(ExpectedUndefinedSymbols)));
1800
}
1801

1802
TEST(TBDv5, ExtractIF) {
1803
  static const char TBDv5File[] = R"({
1804
"tapi_tbd_version": 5,
1805
"main_library": {
1806
  "target_info": [
1807
    {
1808
      "target": "x86_64-macos",
1809
      "min_deployment": "10.14"
1810
    },
1811
    {
1812
      "target": "arm64-macos",
1813
      "min_deployment": "10.14"
1814
    },
1815
    {
1816
      "target": "arm64-maccatalyst",
1817
      "min_deployment": "12.1"
1818
    }
1819
  ],
1820
  "flags": [
1821
    {
1822
      "targets": [
1823
            "x86_64-macos"
1824
        ],
1825
      "attributes": [
1826
            "flat_namespace"
1827
        ]
1828
    }
1829
  ],
1830
  "install_names": [
1831
    {
1832
        "name": "/S/L/F/Foo.framework/Foo"
1833
    }
1834
  ],
1835
  "current_versions": [
1836
    {
1837
        "version": "1.2"
1838
    }
1839
  ],
1840
  "compatibility_versions": [
1841
    { "version": "1.1" }
1842
  ],
1843
  "rpaths": [
1844
    {
1845
      "targets": [
1846
          "x86_64-macos"
1847
      ],
1848
      "paths": [
1849
          "@executable_path/.../Frameworks"
1850
      ]
1851
    }
1852
  ],
1853
  "parent_umbrellas": [
1854
    {
1855
      "umbrella": "System"
1856
    }
1857
  ],
1858
  "allowable_clients": [
1859
    {
1860
        "clients": [
1861
            "ClientA",
1862
            "ClientB"
1863
        ]
1864
    }
1865
  ],
1866
  "reexported_libraries": [
1867
    {
1868
        "names": [
1869
            "/u/l/l/libfoo.dylib",
1870
            "/u/l/l/libbar.dylib"
1871
        ]
1872
    }
1873
  ],
1874
  "exported_symbols": [
1875
    {
1876
        "targets": [
1877
            "x86_64-macos",
1878
            "arm64-macos"
1879
        ],
1880
        "data": {
1881
            "global": [
1882
                "_global"
1883
            ],
1884
            "objc_class": [
1885
                "ClassA"
1886
            ],
1887
            "weak": [],
1888
            "thread_local": []
1889
        },
1890
        "text": {
1891
            "global": [
1892
                "_func"
1893
            ],
1894
            "weak": [],
1895
            "thread_local": []
1896
        }
1897
    },
1898
    {
1899
      "targets": [
1900
          "x86_64-macos"
1901
      ],
1902
      "data": {
1903
          "global": [
1904
              "_globalVar"
1905
          ],
1906
          "objc_class": [
1907
              "ClassA",
1908
              "ClassB",
1909
              "ClassData"
1910
          ],
1911
          "objc_eh_type": [
1912
              "ClassA",
1913
              "ClassB"
1914
          ],
1915
          "objc_ivar": [
1916
              "ClassA.ivar1",
1917
              "ClassA.ivar2",
1918
              "ClassC.ivar1"
1919
          ]
1920
      },
1921
      "text": {
1922
          "global": [
1923
              "_funcFoo"
1924
          ]
1925
      }
1926
    }
1927
  ],
1928
  "reexported_symbols": [
1929
    {
1930
        "targets": [
1931
            "x86_64-macos",
1932
            "arm64-macos"
1933
        ],
1934
        "data": {
1935
            "global": [
1936
                "_globalRe"
1937
            ],
1938
            "objc_class": [
1939
                "ClassRexport"
1940
            ]
1941
        },
1942
        "text": {
1943
            "global": [
1944
                "_funcA"
1945
            ]
1946
        }
1947
    }
1948
  ],
1949
  "undefined_symbols": [
1950
    {
1951
        "targets": [
1952
            "x86_64-macos"
1953
        ],
1954
        "data": {
1955
            "global": [
1956
                "_globalBind"
1957
            ],
1958
            "weak": [
1959
                "referenced_sym"
1960
            ]
1961
        }
1962
    }
1963
  ]
1964
},
1965
"libraries": []
1966
})";
1967

1968
  Expected<TBDFile> Result =
1969
      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1970
  EXPECT_TRUE(!!Result);
1971
  TBDFile File = std::move(Result.get());
1972

1973
  Expected<TBDFile> ExtractedResult = File->extract(AK_arm64);
1974
  EXPECT_TRUE(!!ExtractedResult);
1975
  TBDFile ExtractedFile = std::move(ExtractedResult.get());
1976

1977
  EXPECT_EQ(FileType::TBD_V5, ExtractedFile->getFileType());
1978
  EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1979
            ExtractedFile->getInstallName());
1980

1981
  TargetList AllTargets = {
1982
      Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
1983
      Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
1984
  };
1985
  EXPECT_EQ(mapToPlatformSet(AllTargets), ExtractedFile->getPlatforms());
1986
  EXPECT_EQ(mapToArchitectureSet(AllTargets),
1987
            ExtractedFile->getArchitectures());
1988

1989
  EXPECT_EQ(PackedVersion(1, 2, 0), ExtractedFile->getCurrentVersion());
1990
  EXPECT_EQ(PackedVersion(1, 1, 0), ExtractedFile->getCompatibilityVersion());
1991
  EXPECT_TRUE(ExtractedFile->isApplicationExtensionSafe());
1992
  EXPECT_FALSE(ExtractedFile->isTwoLevelNamespace());
1993
  EXPECT_EQ(0U, ExtractedFile->documents().size());
1994

1995
  InterfaceFileRef ClientA("ClientA", AllTargets);
1996
  InterfaceFileRef ClientB("ClientB", AllTargets);
1997
  EXPECT_EQ(2U, ExtractedFile->allowableClients().size());
1998
  EXPECT_EQ(ClientA, ExtractedFile->allowableClients().at(0));
1999
  EXPECT_EQ(ClientB, ExtractedFile->allowableClients().at(1));
2000

2001
  InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
2002
  InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
2003
  EXPECT_EQ(2U, ExtractedFile->reexportedLibraries().size());
2004
  EXPECT_EQ(ReexportA, ExtractedFile->reexportedLibraries().at(0));
2005
  EXPECT_EQ(ReexportB, ExtractedFile->reexportedLibraries().at(1));
2006

2007
  EXPECT_EQ(0u, ExtractedFile->rpaths().size());
2008

2009
  TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"},
2010
                            {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
2011
  EXPECT_EQ(Umbrellas, ExtractedFile->umbrellas());
2012

2013
  ExportedSymbolSeq Exports, Reexports, Undefineds;
2014
  for (const auto *Sym : ExtractedFile->symbols()) {
2015
    TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
2016
    ExportedSymbol Temp =
2017
        ExportedSymbol{Sym->getKind(),
2018
                       std::string(Sym->getName()),
2019
                       Sym->isWeakDefined() || Sym->isWeakReferenced(),
2020
                       Sym->isThreadLocalValue(),
2021
                       Sym->isData(),
2022
                       SymTargets};
2023
    if (Sym->isUndefined())
2024
      Undefineds.emplace_back(std::move(Temp));
2025
    else
2026
      Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
2027
                          : Exports.emplace_back(std::move(Temp));
2028
  }
2029
  llvm::sort(Exports);
2030
  llvm::sort(Reexports);
2031
  llvm::sort(Undefineds);
2032

2033
  TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)};
2034

2035
  std::vector<ExportedSymbol> ExpectedExportedSymbols = {
2036
      {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
2037
      {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
2038
      {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
2039
  };
2040
  std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
2041
      {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
2042
      {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
2043
      {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true,
2044
       MacOSTargets},
2045
  };
2046

2047
  EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
2048
  EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
2049
  EXPECT_EQ(0U, Undefineds.size());
2050
  EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
2051
                         std::begin(ExpectedExportedSymbols)));
2052
  EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
2053
                         std::begin(ExpectedReexportedSymbols)));
2054
}
2055

2056
TEST(TBDv5, RemoveIF) {
2057
  static const char TBDv5File[] = R"({
2058
"tapi_tbd_version": 5,
2059
"main_library": {
2060
  "target_info": [
2061
    {
2062
      "target": "x86_64-macos",
2063
      "min_deployment": "10.14"
2064
    },
2065
    {
2066
      "target": "arm64-macos",
2067
      "min_deployment": "10.14"
2068
    },
2069
    {
2070
      "target": "arm64-maccatalyst",
2071
      "min_deployment": "12.1"
2072
    }
2073
  ],
2074
  "flags": [
2075
    {
2076
      "targets": [
2077
            "x86_64-macos"
2078
        ],
2079
      "attributes": [
2080
            "flat_namespace"
2081
        ]
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(MemoryBufferRef(TBDv5File, "Test.tbd"));
2224
  EXPECT_TRUE(!!Result);
2225
  TBDFile File = std::move(Result.get());
2226

2227
  Expected<TBDFile> RemovedResult = File->remove(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{Sym->getKind(),
2271
                       std::string(Sym->getName()),
2272
                       Sym->isWeakDefined() || Sym->isWeakReferenced(),
2273
                       Sym->isThreadLocalValue(),
2274
                       Sym->isData(),
2275
                       SymTargets};
2276
    if (Sym->isUndefined())
2277
      Undefineds.emplace_back(std::move(Temp));
2278
    else
2279
      Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
2280
                          : Exports.emplace_back(std::move(Temp));
2281
  }
2282
  llvm::sort(Exports);
2283
  llvm::sort(Reexports);
2284
  llvm::sort(Undefineds);
2285

2286
  TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)};
2287

2288
  std::vector<ExportedSymbol> ExpectedExportedSymbols = {
2289
      {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
2290
      {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
2291
      {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
2292
  };
2293
  std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
2294
      {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
2295
      {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
2296
      {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true,
2297
       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(MemoryBufferRef(UmbrellaFile, "Test.tbd"));
2397
  EXPECT_TRUE(!!UmbrellaResult);
2398
  TBDFile Umbrella = std::move(UmbrellaResult.get());
2399

2400
  Expected<TBDFile> ReexportResult =
2401
      TextAPIReader::get(MemoryBufferRef(ReexportFile, "Test.tbd"));
2402
  EXPECT_TRUE(!!ReexportResult);
2403
  TBDReexportFile Reexport = std::move(ReexportResult.get());
2404
  Umbrella->inlineLibrary(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
        ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
2439
                       Sym->isWeakDefined() || Sym->isWeakReferenced(),
2440
                       Sym->isThreadLocalValue(), Sym->isData(), SymTargets});
2441
  }
2442
  llvm::sort(Exports);
2443

2444
  ExportedSymbolSeq ExpectedExports = {
2445
      {EncodeKind::GlobalSymbol, "_global", false, false, true, AllTargets},
2446
      {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, 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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.