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