1//===- unittests/Basic/DarwinSDKInfoTest.cpp -- SDKSettings.json 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 "clang/Basic/DarwinSDKInfo.h"
10#include "llvm/Support/JSON.h"
11#include "gtest/gtest.h"
12#include <optional>
13
14using namespace llvm;
15using namespace clang;
16
17// Check the version mapping logic in DarwinSDKInfo.
18TEST(DarwinSDKInfo, VersionMapping) {
19 llvm::json::Object Obj({{.K: "3.0", .V: "1.0"}, {.K: "3.1", .V: "1.2"}});
20 std::optional<DarwinSDKInfo::RelatedTargetVersionMapping> Mapping =
21 DarwinSDKInfo::RelatedTargetVersionMapping::parseJSON(Obj,
22 MaximumDeploymentTarget: VersionTuple());
23 EXPECT_TRUE(Mapping);
24 EXPECT_EQ(Mapping->getMinimumValue(), VersionTuple(1));
25
26 // Exact mapping.
27 EXPECT_EQ(Mapping->map(VersionTuple(3), VersionTuple(0, 1), std::nullopt),
28 VersionTuple(1));
29 EXPECT_EQ(Mapping->map(VersionTuple(3, 0), VersionTuple(0, 1), std::nullopt),
30 VersionTuple(1));
31 EXPECT_EQ(
32 Mapping->map(VersionTuple(3, 0, 0), VersionTuple(0, 1), std::nullopt),
33 VersionTuple(1));
34 EXPECT_EQ(Mapping->map(VersionTuple(3, 1), VersionTuple(0, 1), std::nullopt),
35 VersionTuple(1, 2));
36 EXPECT_EQ(
37 Mapping->map(VersionTuple(3, 1, 0), VersionTuple(0, 1), std::nullopt),
38 VersionTuple(1, 2));
39
40 // Missing mapping - fallback to major.
41 EXPECT_EQ(
42 Mapping->map(VersionTuple(3, 0, 1), VersionTuple(0, 1), std::nullopt),
43 VersionTuple(1));
44
45 // Minimum
46 EXPECT_EQ(Mapping->map(VersionTuple(2), VersionTuple(0, 1), std::nullopt),
47 VersionTuple(0, 1));
48
49 // Maximum
50 EXPECT_EQ(
51 Mapping->map(VersionTuple(4), VersionTuple(0, 1), VersionTuple(100)),
52 VersionTuple(100));
53}
54
55// Check the version mapping logic in DarwinSDKInfo.
56TEST(DarwinSDKInfo, VersionMappingMissingKey) {
57 llvm::json::Object Obj({{.K: "3.0", .V: "1.0"}, {.K: "5.0", .V: "1.2"}});
58 std::optional<DarwinSDKInfo::RelatedTargetVersionMapping> Mapping =
59 DarwinSDKInfo::RelatedTargetVersionMapping::parseJSON(Obj,
60 MaximumDeploymentTarget: VersionTuple());
61 EXPECT_TRUE(Mapping);
62 EXPECT_EQ(
63 Mapping->map(VersionTuple(4), VersionTuple(0, 1), VersionTuple(100)),
64 std::nullopt);
65}
66
67TEST(DarwinSDKInfo, VersionMappingParseEmpty) {
68 llvm::json::Object Obj({});
69 EXPECT_FALSE(
70 DarwinSDKInfo::RelatedTargetVersionMapping::parseJSON(Obj, VersionTuple())
71 .has_value());
72}
73
74TEST(DarwinSDKInfo, VersionMappingParseError) {
75 llvm::json::Object Obj({{.K: "test", .V: "1.2"}});
76 EXPECT_FALSE(
77 DarwinSDKInfo::RelatedTargetVersionMapping::parseJSON(Obj, VersionTuple())
78 .has_value());
79}
80
81TEST(DarwinSDKInfoTest, ParseAndTestMappingMacCatalyst) {
82 llvm::json::Object Obj;
83 Obj["Version"] = "11.0";
84 Obj["MaximumDeploymentTarget"] = "11.99";
85 llvm::json::Object VersionMap;
86 VersionMap["10.15"] = "13.1";
87 VersionMap["11.0"] = "14.0";
88 VersionMap["11.2"] = "14.2";
89 llvm::json::Object MacOS2iOSMac;
90 MacOS2iOSMac["macOS_iOSMac"] = std::move(VersionMap);
91 Obj["VersionMap"] = std::move(MacOS2iOSMac);
92
93 auto SDKInfo = DarwinSDKInfo::parseDarwinSDKSettingsJSON(Obj: &Obj);
94 ASSERT_TRUE(SDKInfo);
95 EXPECT_EQ(SDKInfo->getVersion(), VersionTuple(11, 0));
96
97 auto Mapping = SDKInfo->getVersionMapping(
98 Kind: DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair());
99 ASSERT_TRUE(Mapping);
100 // Verify that the macOS versions that are present in the map are translated
101 // directly to their corresponding Mac Catalyst versions.
102 EXPECT_EQ(*Mapping->map(VersionTuple(10, 15), VersionTuple(), std::nullopt),
103 VersionTuple(13, 1));
104 EXPECT_EQ(*Mapping->map(VersionTuple(11, 0), VersionTuple(), std::nullopt),
105 VersionTuple(14, 0));
106 EXPECT_EQ(*Mapping->map(VersionTuple(11, 2), VersionTuple(), std::nullopt),
107 VersionTuple(14, 2));
108
109 // Verify that a macOS version that's not present in the map is translated
110 // like the nearest major OS version.
111 EXPECT_EQ(*Mapping->map(VersionTuple(11, 1), VersionTuple(), std::nullopt),
112 VersionTuple(14, 0));
113
114 // Verify that the macOS versions that are outside of the mapped version
115 // range map to the min/max values passed to the `map` call.
116 EXPECT_EQ(
117 *Mapping->map(VersionTuple(10, 14), VersionTuple(99, 99), std::nullopt),
118 VersionTuple(99, 99));
119 EXPECT_EQ(
120 *Mapping->map(VersionTuple(11, 5), VersionTuple(), VersionTuple(99, 99)),
121 VersionTuple(99, 99));
122 EXPECT_EQ(*Mapping->map(VersionTuple(11, 5), VersionTuple(99, 98),
123 VersionTuple(99, 99)),
124 VersionTuple(99, 99));
125}
126
127TEST(DarwinSDKInfoTest, ParseAndTestMappingIOSDerived) {
128 llvm::json::Object Obj;
129 Obj["Version"] = "15.0";
130 Obj["MaximumDeploymentTarget"] = "15.0.99";
131 llvm::json::Object VersionMap;
132 VersionMap["10.0"] = "10.0";
133 VersionMap["10.3.1"] = "10.2";
134 VersionMap["11.0"] = "11.0";
135 llvm::json::Object IOSToTvOS;
136 IOSToTvOS["iOS_tvOS"] = std::move(VersionMap);
137 Obj["VersionMap"] = std::move(IOSToTvOS);
138
139 auto SDKInfo = DarwinSDKInfo::parseDarwinSDKSettingsJSON(Obj: &Obj);
140 ASSERT_TRUE(SDKInfo);
141 EXPECT_EQ(SDKInfo->getVersion(), VersionTuple(15, 0));
142
143 // Verify that mapping is present for platforms that derive from iOS.
144 const auto *Mapping = SDKInfo->getVersionMapping(Kind: DarwinSDKInfo::OSEnvPair(
145 llvm::Triple::IOS, llvm::Triple::UnknownEnvironment, llvm::Triple::TvOS,
146 llvm::Triple::UnknownEnvironment));
147 ASSERT_TRUE(Mapping);
148
149 // Verify that the iOS versions that are present in the map are translated
150 // directly to their corresponding tvOS versions.
151 EXPECT_EQ(*Mapping->map(VersionTuple(10, 0), VersionTuple(), std::nullopt),
152 VersionTuple(10, 0));
153 EXPECT_EQ(*Mapping->map(VersionTuple(10, 3, 1), VersionTuple(), std::nullopt),
154 VersionTuple(10, 2));
155 EXPECT_EQ(*Mapping->map(VersionTuple(11, 0), VersionTuple(), std::nullopt),
156 VersionTuple(11, 0));
157
158 // Verify that an iOS version that's not present in the map is translated
159 // like the nearest major OS version.
160 EXPECT_EQ(*Mapping->map(VersionTuple(10, 1), VersionTuple(), std::nullopt),
161 VersionTuple(10, 0));
162
163 // Verify that the iOS versions that are outside of the mapped version
164 // range map to the min/max values passed to the `map` call.
165 EXPECT_EQ(
166 *Mapping->map(VersionTuple(9, 0), VersionTuple(99, 99), std::nullopt),
167 VersionTuple(99, 99));
168 EXPECT_EQ(
169 *Mapping->map(VersionTuple(13, 0), VersionTuple(), VersionTuple(99, 99)),
170 VersionTuple(99, 99));
171
172 // Verify introduced, deprecated, and obsoleted mappings.
173 EXPECT_EQ(Mapping->mapIntroducedAvailabilityVersion(VersionTuple(10, 1)),
174 VersionTuple(10.0));
175 EXPECT_EQ(Mapping->mapDeprecatedObsoletedAvailabilityVersion(
176 VersionTuple(100000, 0)),
177 VersionTuple(100000));
178 EXPECT_EQ(
179 Mapping->mapDeprecatedObsoletedAvailabilityVersion(VersionTuple(13.0)),
180 VersionTuple(15, 0, 99));
181}
182
183TEST(DarwinSDKInfoTest, MissingKeys) {
184 llvm::json::Object Obj;
185 ASSERT_FALSE(DarwinSDKInfo::parseDarwinSDKSettingsJSON(&Obj));
186 Obj["Version"] = "11.0";
187 ASSERT_FALSE(DarwinSDKInfo::parseDarwinSDKSettingsJSON(&Obj));
188}
189

source code of clang/unittests/Basic/DarwinSDKInfoTest.cpp