1 /**
2  * Copyright (C) 2018 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 #include <stdlib.h>
18 #include <string.h>
19 
20 #include <android-base/logging.h>
21 #include <gtest/gtest.h>
22 
23 #include "installd_constants.h"
24 #include "otapreopt_parameters.h"
25 
26 namespace android {
27 namespace installd {
28 
ParseBool(const char * in)29 static bool ParseBool(const char* in) {
30     if (strcmp(in, "true") == 0) {
31         return true;
32     }
33     return false;
34 }
35 
ParseNull(const char * arg)36 static const char* ParseNull(const char* arg) {
37     return (strcmp(arg, "!") == 0) ? nullptr : arg;
38 }
39 
40 class OTAPreoptTest : public testing::Test {
41 protected:
SetUp()42     virtual void SetUp() {
43         setenv("ANDROID_LOG_TAGS", "*:f", 1);
44         android::base::InitLogging(nullptr, android::base::StderrLogger);
45     }
46 
verifyPackageParameters(const OTAPreoptParameters & params,uint32_t version,bool versioned,const char ** args)47     void verifyPackageParameters(const OTAPreoptParameters& params,
48                                  uint32_t version,
49                                  bool versioned,
50                                  const char** args) {
51         //  otapreopt target-slot [version] dexopt {DEXOPT_PARAMETERS}
52         int i = 0;
53         if (version > 2 || (version == 2 && versioned)) {
54             i += 4;
55         } else {
56             i += 3;
57         }
58         ASSERT_STREQ(params.target_slot.c_str(), args[1]);
59         ASSERT_STREQ(params.apk_path, args[i++]);
60         ASSERT_EQ(params.uid, static_cast<uid_t>(atoi(args[i++])));
61         ASSERT_STREQ(params.pkgName, args[i++]);
62         ASSERT_STREQ(params.instruction_set, args[i++]);
63         ASSERT_EQ(params.dexopt_needed, atoi(args[i++]));
64         ASSERT_STREQ(params.oat_dir, args[i++]);
65         const int dexopt_flags = atoi(args[i++]);
66         ASSERT_STREQ(params.compiler_filter, args[i++]);
67         ASSERT_STREQ(params.volume_uuid, ParseNull(args[i++]));
68         ASSERT_STREQ(params.shared_libraries, ParseNull(args[i++]));
69         if (version > 1) {
70             ASSERT_STREQ(params.se_info, ParseNull(args[i++]));
71         } else {
72             ASSERT_EQ(params.se_info, nullptr);
73         }
74         if (version > 2) {
75             ASSERT_EQ(params.downgrade, ParseBool(args[i++]));
76         } else {
77             ASSERT_FALSE(params.downgrade);
78         }
79         if (version > 3) {
80             ASSERT_EQ(params.target_sdk_version, atoi(args[i++]));
81         } else {
82             ASSERT_EQ(params.target_sdk_version, 0);
83         }
84         if (version > 4) {
85             ASSERT_STREQ(params.profile_name, ParseNull(args[i++]));
86         } else {
87             ASSERT_STREQ(params.profile_name, "primary.prof");
88         }
89         if (version > 5) {
90             ASSERT_STREQ(params.dex_metadata_path, ParseNull(args[i++]));
91         } else {
92             ASSERT_EQ(params.dex_metadata_path, nullptr);
93         }
94         if (version > 6) {
95             ASSERT_STREQ(params.compilation_reason, ParseNull(args[i++]));
96         } else {
97             ASSERT_STREQ(params.compilation_reason, "ab-ota");
98         }
99         if (version > 7) {
100             ASSERT_EQ(params.dexopt_flags, dexopt_flags);
101         } else {
102             ASSERT_EQ(params.dexopt_flags, dexopt_flags | DEXOPT_GENERATE_COMPACT_DEX);
103         }
104     }
105 
getVersionCStr(uint32_t version)106     const char* getVersionCStr(uint32_t version) {
107         switch (version) {
108             case 1: return "1";
109             case 2: return "2";
110             case 3: return "3";
111             case 4: return "4";
112             case 5: return "5";
113             case 6: return "6";
114             case 7: return "7";
115             case 8: return "8";
116             case 9: return "9";
117             case 10: return "10";
118         }
119         return nullptr;
120     }
121 
getArgs(uint32_t version,bool versioned,const char * shared_libs="shared.lib")122     std::vector<const char*> getArgs(uint32_t version,
123                                      bool versioned,
124                                      const char* shared_libs = "shared.lib") {
125         std::vector<const char*> args;
126         args.push_back("otapreopt");  // "otapreopt"
127         args.push_back("a");  // slot
128         if (versioned) {
129             args.push_back(getVersionCStr(version));
130         }
131         args.push_back("dexopt");  // "dexopt"
132         args.push_back("foo.apk");  // apk_path
133         args.push_back("123");  // uid
134         args.push_back("pkgname");  // pkg
135         args.push_back("arm");  // isa
136         args.push_back("1");  // dexopt_needed (DEX2OAT_FROM_SCRATCH)
137         args.push_back("oat_dir");  // oat_dir
138         args.push_back("0");  // dexopt_flags
139         args.push_back("speed");  // filter
140         args.push_back("!");  // volume
141         args.push_back(shared_libs);  // libs
142 
143         if (version > 1) {
144             args.push_back("!");  // seinfo
145         }
146         if (version > 2) {
147             args.push_back("true");  // downgrade
148         }
149         if (version > 3) {
150             args.push_back("28");  // sdk_version
151         }
152         if (version > 4) {
153             args.push_back("split_a.prof");  // profile_name
154         }
155         if (version > 5) {
156             args.push_back("dex_metadata.dm");  // dex_metadata_path
157         }
158         if (version > 6) {
159             args.push_back("ab-ota-test");  // compilation_reason
160         }
161         args.push_back(nullptr);  // we have to end with null.
162         return args;
163     }
164 
VerifyReadArguments(uint32_t version,bool versioned,const char * shared_libs="shared.lib")165     void VerifyReadArguments(uint32_t version,
166                              bool versioned,
167                              const char* shared_libs = "shared.lib") {
168         OTAPreoptParameters params;
169         std::vector<const char*> args = getArgs(version, versioned, shared_libs);
170         ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data()));
171         verifyPackageParameters(params, version, versioned, args.data());
172     }
173 };
174 
TEST_F(OTAPreoptTest,ReadArgumentsV1)175 TEST_F(OTAPreoptTest, ReadArgumentsV1) {
176     VerifyReadArguments(1, false);
177 }
178 
TEST_F(OTAPreoptTest,ReadArgumentsV2Unversioned)179 TEST_F(OTAPreoptTest, ReadArgumentsV2Unversioned) {
180     VerifyReadArguments(2, false);
181 }
182 
TEST_F(OTAPreoptTest,ReadArgumentsV2)183 TEST_F(OTAPreoptTest, ReadArgumentsV2) {
184     VerifyReadArguments(2, true);
185 }
186 
TEST_F(OTAPreoptTest,ReadArgumentsV3)187 TEST_F(OTAPreoptTest, ReadArgumentsV3) {
188     VerifyReadArguments(3, true);
189 }
190 
TEST_F(OTAPreoptTest,ReadArgumentsV4)191 TEST_F(OTAPreoptTest, ReadArgumentsV4) {
192     VerifyReadArguments(4, true);
193 }
194 
TEST_F(OTAPreoptTest,ReadArgumentsV5)195 TEST_F(OTAPreoptTest, ReadArgumentsV5) {
196     VerifyReadArguments(5, true);
197 }
198 
TEST_F(OTAPreoptTest,ReadArgumentsV6)199 TEST_F(OTAPreoptTest, ReadArgumentsV6) {
200     VerifyReadArguments(6, true);
201 }
202 
TEST_F(OTAPreoptTest,ReadArgumentsV7)203 TEST_F(OTAPreoptTest, ReadArgumentsV7) {
204     VerifyReadArguments(7, true);
205 }
206 
TEST_F(OTAPreoptTest,ReadArgumentsV9SharedLibsAmpersand)207 TEST_F(OTAPreoptTest, ReadArgumentsV9SharedLibsAmpersand) {
208     OTAPreoptParameters params;
209     std::vector<const char*> args = getArgs(9, true, "&");
210     ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
211 }
212 
TEST_F(OTAPreoptTest,ReadArgumentsV10SharedLibsAmpersand)213 TEST_F(OTAPreoptTest, ReadArgumentsV10SharedLibsAmpersand) {
214     OTAPreoptParameters params;
215     std::vector<const char*> args = getArgs(10, true, "&");
216     ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data()));
217 }
218 
TEST_F(OTAPreoptTest,ReadArgumentsFailToManyArgs)219 TEST_F(OTAPreoptTest, ReadArgumentsFailToManyArgs) {
220     OTAPreoptParameters params;
221     std::vector<const char*> args = getArgs(5, true);
222     args[2] = "3";  // pretend it's version 3. It should fail since there are too many args.
223     ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
224 }
225 
TEST_F(OTAPreoptTest,ReadArgumentsFailInsufficientArgs)226 TEST_F(OTAPreoptTest, ReadArgumentsFailInsufficientArgs) {
227     OTAPreoptParameters params;
228     std::vector<const char*> args = getArgs(4, true);
229     args[2] = "5";  // pretend it's version 5. It should fail since there are insufficient args.
230     ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
231 }
232 
TEST_F(OTAPreoptTest,ReadArgumentsFailInvalidDexopt)233 TEST_F(OTAPreoptTest, ReadArgumentsFailInvalidDexopt) {
234     OTAPreoptParameters params;
235     std::vector<const char*> args = getArgs(4, true);
236     args[3] = "dexopt-invalid";
237     ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
238 }
239 
TEST_F(OTAPreoptTest,ReadArgumentsFailInvalidSlot)240 TEST_F(OTAPreoptTest, ReadArgumentsFailInvalidSlot) {
241     OTAPreoptParameters params;
242     std::vector<const char*> args = getArgs(3, true);
243     args[1] = "invalid-slot???";
244     ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
245 }
246 
247 }  // namespace installd
248 }  // namespace android
249