1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "derive_sdk_test"
18
19 #include "derive_sdk.h"
20
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <android-base/properties.h>
24 #include <android-modules-utils/sdk_level.h>
25 #include <gtest/gtest.h>
26 #include <stdlib.h>
27 #include <sys/stat.h>
28
29 #include <cstdlib>
30 #include <string>
31 #include <unordered_map>
32
33 #include "packages/modules/common/proto/sdk.pb.h"
34
35 #define EXPECT_ALL(n) \
36 { \
37 EXPECT_R(n); \
38 EXPECT_S(n); \
39 EXPECT_T(n); \
40 EXPECT_U(n); \
41 }
42
43 #define EXPECT_R(n) EXPECT_EQ(GetR(), (n))
44
45 // Only expect the S extension level to be set on S+ devices.
46 #define EXPECT_S(n) EXPECT_EQ(GetS(), android::modules::sdklevel::IsAtLeastS() ? (n) : -1)
47
48 // Only expect the T extension level to be set on T+ devices.
49 #define EXPECT_T(n) EXPECT_EQ(GetT(), android::modules::sdklevel::IsAtLeastT() ? (n) : -1)
50
51 // Only expect the U extension level to be set on U+ devices.
52 #define EXPECT_U(n) EXPECT_EQ(GetU(), android::modules::sdklevel::IsAtLeastU() ? (n) : -1)
53
54 // Only expect the V extension level to be set on V+ devices.
55 #define EXPECT_V(n) EXPECT_EQ(GetV(), android::modules::sdklevel::IsAtLeastV() ? (n) : -1)
56
57 class DeriveSdkTest : public ::testing::Test {
58 protected:
TearDown()59 void TearDown() override { android::derivesdk::SetSdkLevels("/apex"); }
60
dir()61 const std::string dir() { return std::string(dir_.path); }
62
EtcDir(const std::string & apex)63 const std::string EtcDir(const std::string& apex) {
64 return dir() + "/" + apex + "/etc";
65 }
66
AddVersionToDb(const int version,const std::unordered_map<SdkModule,int> & requirements)67 void AddVersionToDb(const int version, const std::unordered_map<SdkModule, int>& requirements) {
68 ExtensionVersion* sdk = db_.add_versions();
69 sdk->set_version(version);
70 for (auto pair : requirements) {
71 ExtensionVersion_ModuleRequirement* req = sdk->add_requirements();
72 req->set_module(pair.first);
73 req->mutable_version()->set_version(pair.second);
74 }
75 WriteProto(db_, EtcDir("com.android.sdkext") + "/extensions_db.pb");
76 }
77
AddExtensionVersion(const int version,const std::unordered_map<SdkModule,int> & requirements)78 void AddExtensionVersion(const int version,
79 const std::unordered_map<SdkModule, int>& requirements) {
80 AddVersionToDb(version, requirements);
81 ASSERT_TRUE(android::derivesdk::SetSdkLevels(dir()));
82 }
83
SetApexVersion(const std::string apex,int version)84 void SetApexVersion(const std::string apex, int version) {
85 SdkVersion sdk_version;
86 sdk_version.set_version(version);
87 WriteProto(sdk_version, EtcDir(apex) + "/sdkinfo.pb");
88
89 ASSERT_TRUE(android::derivesdk::SetSdkLevels(dir()));
90 }
91
WriteProto(const google::protobuf::MessageLite & proto,const std::string & path)92 void WriteProto(const google::protobuf::MessageLite& proto,
93 const std::string& path) {
94 std::string buf;
95 proto.SerializeToString(&buf);
96 std::string cmd("mkdir -p " + path.substr(0, path.find_last_of('/')));
97 ASSERT_EQ(0, system(cmd.c_str()));
98 ASSERT_TRUE(android::base::WriteStringToFile(buf, path, true));
99 }
100
GetR()101 int GetR() { return android::base::GetIntProperty("build.version.extensions.r", -1); }
102
GetS()103 int GetS() { return android::base::GetIntProperty("build.version.extensions.s", -1); }
104
GetT()105 int GetT() { return android::base::GetIntProperty("build.version.extensions.t", -1); }
106
GetU()107 int GetU() { return android::base::GetIntProperty("build.version.extensions.u", -1); }
108
GetV()109 int GetV() { return android::base::GetIntProperty("build.version.extensions.v", -1); }
110
EXPECT_ADSERVICES(int n)111 void EXPECT_ADSERVICES(int n) {
112 int actual = android::base::GetIntProperty("build.version.extensions.ad_services", -1);
113 // Only expect the AdServices extension level to be set on T+ devices.
114 EXPECT_EQ(actual, android::modules::sdklevel::IsAtLeastT() ? n : -1);
115 }
116
117 ExtensionDatabase db_;
118 TemporaryDir dir_;
119 };
120
TEST_F(DeriveSdkTest,OneDessert_OneVersion_OneApex)121 TEST_F(DeriveSdkTest, OneDessert_OneVersion_OneApex) {
122 AddExtensionVersion(3, {{SdkModule::SDK_EXTENSIONS, 2}});
123 EXPECT_ALL(0);
124
125 SetApexVersion("com.android.sdkext", 3);
126 EXPECT_ALL(3);
127 }
128
TEST_F(DeriveSdkTest,OneDessert_OneVersion_TwoApexes)129 TEST_F(DeriveSdkTest, OneDessert_OneVersion_TwoApexes) {
130 AddExtensionVersion(5, {
131 {SdkModule::MEDIA, 5},
132 {SdkModule::SDK_EXTENSIONS, 2},
133 });
134 EXPECT_ALL(0);
135
136 // Only sdkext
137 SetApexVersion("com.android.sdkext", 2);
138 EXPECT_ALL(0);
139
140 // Only media
141 SetApexVersion("com.android.sdkext", 0);
142 SetApexVersion("com.android.media", 5);
143 EXPECT_ALL(0);
144
145 // Both
146 SetApexVersion("com.android.sdkext", 2);
147 EXPECT_ALL(5);
148 }
149
TEST_F(DeriveSdkTest,OneDessert_ManyVersions)150 TEST_F(DeriveSdkTest, OneDessert_ManyVersions) {
151 AddExtensionVersion(1, {
152 {SdkModule::MEDIA, 1},
153 });
154 EXPECT_ALL(0);
155 SetApexVersion("com.android.media", 1);
156 EXPECT_ALL(1);
157
158 AddExtensionVersion(2, {
159 {SdkModule::MEDIA, 1},
160 {SdkModule::MEDIA_PROVIDER, 2},
161 {SdkModule::SDK_EXTENSIONS, 2},
162 });
163 EXPECT_ALL(1);
164 SetApexVersion("com.android.mediaprovider", 2);
165 EXPECT_ALL(1);
166 SetApexVersion("com.android.sdkext", 2);
167 EXPECT_ALL(2);
168
169 AddExtensionVersion(3, {
170 {SdkModule::MEDIA, 3},
171 {SdkModule::MEDIA_PROVIDER, 2},
172 {SdkModule::SDK_EXTENSIONS, 3},
173 });
174 EXPECT_ALL(2);
175 SetApexVersion("com.android.media", 3);
176 EXPECT_ALL(2);
177 SetApexVersion("com.android.sdkext", 3);
178 EXPECT_ALL(3);
179 }
180
TEST_F(DeriveSdkTest,TwoDesserts_ManyVersions)181 TEST_F(DeriveSdkTest, TwoDesserts_ManyVersions) {
182 AddExtensionVersion(1, {
183 {SdkModule::TETHERING, 1},
184 });
185 EXPECT_ALL(0);
186
187 // Only tethering v1
188 SetApexVersion("com.android.tethering", 1);
189 EXPECT_ALL(1);
190
191 // V2 defined
192 AddExtensionVersion(2, {
193 {SdkModule::ART, 2},
194 {SdkModule::TETHERING, 1},
195 });
196 EXPECT_R(2);
197 EXPECT_S(1);
198
199 // Only art v2
200 SetApexVersion("com.android.tethering", 0);
201 SetApexVersion("com.android.art", 2);
202 EXPECT_ALL(0);
203
204 // Both
205 SetApexVersion("com.android.tethering", 1);
206 EXPECT_ALL(2);
207
208 // V3 defined
209 AddExtensionVersion(3, {
210 {SdkModule::ART, 3},
211 {SdkModule::MEDIA, 3},
212 {SdkModule::TETHERING, 1},
213 });
214 EXPECT_ALL(2);
215
216 // Only media v3
217 SetApexVersion("com.android.media", 3);
218 EXPECT_R(3);
219 EXPECT_S(2);
220
221 // Only art v3
222 SetApexVersion("com.android.media", 0);
223 SetApexVersion("com.android.art", 3);
224 EXPECT_ALL(2);
225
226 // Both
227 SetApexVersion("com.android.media", 3);
228 EXPECT_ALL(3);
229 }
230
TEST_F(DeriveSdkTest,UnmappedModule)231 TEST_F(DeriveSdkTest, UnmappedModule) {
232 AddVersionToDb(5, {
233 {static_cast<SdkModule>(77), 5}, // Doesn't exist.
234 {SdkModule::SDK_EXTENSIONS, 2},
235 });
236
237 ASSERT_FALSE(android::derivesdk::SetSdkLevels(dir()));
238 }
239
TEST_F(DeriveSdkTest,AdServicesPreV7)240 TEST_F(DeriveSdkTest, AdServicesPreV7) {
241 AddExtensionVersion(1, {
242 {SdkModule::TETHERING, 1},
243 });
244 EXPECT_ALL(0);
245 EXPECT_ADSERVICES(1);
246
247 SetApexVersion("com.android.tethering", 1);
248 EXPECT_ALL(1);
249
250 // V2 defined
251 AddExtensionVersion(2, {
252 {SdkModule::AD_SERVICES, 2},
253 {SdkModule::TETHERING, 2},
254 });
255 EXPECT_ALL(1);
256 EXPECT_ADSERVICES(1);
257
258 // Only adservices v2
259 SetApexVersion("com.android.adservices", 2);
260 EXPECT_ALL(1);
261 EXPECT_ADSERVICES(2);
262
263 // Both v2
264 SetApexVersion("com.android.tethering", 2);
265 EXPECT_ALL(2);
266 EXPECT_ADSERVICES(2);
267
268 // Only tethering v2. R and S extension are bumped, but T requires adserices.
269 SetApexVersion("com.android.adservices", 0);
270 SetApexVersion("com.android.tethering", 2);
271 EXPECT_R(2);
272 EXPECT_S(2);
273 EXPECT_T(1);
274 EXPECT_ADSERVICES(1);
275 }
276
TEST_F(DeriveSdkTest,AdServicesPostV7)277 TEST_F(DeriveSdkTest, AdServicesPostV7) {
278 // Need to add a base version with an R module to prevent the
279 // dessert extension versions from getting bumped.
280 AddExtensionVersion(1, {
281 {SdkModule::TETHERING, 1},
282 });
283
284 // Only adservices v2
285 SetApexVersion("com.android.adservices", 2);
286 EXPECT_ALL(0);
287 EXPECT_ADSERVICES(1);
288
289 // From v7 and onwards, we only care about the adservices version
290 SetApexVersion("com.android.adservices", 7);
291 EXPECT_ALL(0);
292 EXPECT_ADSERVICES(7);
293
294 SetApexVersion("com.android.adservices", 10);
295 EXPECT_ALL(0);
296 EXPECT_ADSERVICES(10);
297 }
298
TEST_F(DeriveSdkTest,Tiramisu)299 TEST_F(DeriveSdkTest, Tiramisu) {
300 AddExtensionVersion(1, {
301 {SdkModule::AD_SERVICES, 1},
302 {SdkModule::APPSEARCH, 2},
303 {SdkModule::ON_DEVICE_PERSONALIZATION, 3},
304 });
305 EXPECT_T(0);
306
307 SetApexVersion("com.android.adservices", 1);
308 EXPECT_T(0);
309
310 SetApexVersion("com.android.appsearch", 2);
311 EXPECT_T(0);
312
313 SetApexVersion("com.android.ondevicepersonalization", 3);
314 EXPECT_T(1);
315 }
316
TEST_F(DeriveSdkTest,UpsideDownCake)317 TEST_F(DeriveSdkTest, UpsideDownCake) {
318 AddExtensionVersion(1, {
319 {SdkModule::CONFIG_INFRASTRUCTURE, 1},
320 {SdkModule::HEALTH_FITNESS, 2},
321 });
322 EXPECT_U(0);
323
324 SetApexVersion("com.android.configinfrastructure", 1);
325 EXPECT_U(0);
326
327 SetApexVersion("com.android.healthfitness", 2);
328 EXPECT_U(1);
329 }
330
TEST_F(DeriveSdkTest,VanillaIceCream)331 TEST_F(DeriveSdkTest, VanillaIceCream) {
332 // Nothing to do: no new modules were added in V
333 }
334
main(int argc,char ** argv)335 int main(int argc, char** argv) {
336 ::testing::InitGoogleTest(&argc, argv);
337 return RUN_ALL_TESTS();
338 }
339