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 #include <map>
18 #include <memory>
19 #include <string>
20 
21 #include <android-base/logging.h>
22 
23 #include <gtest/gtest.h>
24 
25 #include "execv_helper.h"
26 #include "run_dex2oat.h"
27 #include "unique_file.h"
28 
29 namespace android {
30 namespace installd {
31 
32 class RunDex2OatTest : public testing::Test {
33   public:
34     static constexpr const char* INPUT_PATH = "/dir/input/basename.apk";
35     static constexpr const char* OUTPUT_PATH = "/dir/output/basename.oat";
36     static constexpr const char* FLAG_UNUSED = "{{FLAG_UNUSED}}";
37 
38     // UniqueFile closes FD. Avoid using standard I/O since the test is expected to print gtest
39     // results. Alternatively, mock out UniqueFile to avoid the side effect of close(2).
40     static constexpr int ZIP_FD = 3;
41     static constexpr int OAT_FD = 4;
42     static constexpr int INPUT_VDEX_FD = 5;
43     static constexpr int OUTPUT_VDEX_FD = 6;
44     static constexpr int IMAGE_FD = 7;
45     static constexpr int PROFILE_FD = 8;
46     static constexpr int DEX_METADATA_FD = 9;
47     static constexpr int SWAP_FD = 10;
48 
49     using FakeSystemProperties = std::map<std::string, std::string>;
50 
51     // A fake RunDex2Oat that allows to override (fake) system properties and starts with none.
52     class FakeRunDex2Oat : public RunDex2Oat {
53       private:
54         static constexpr const char* TRUE_STR = "true";
55         static constexpr const char* FALSE_STR = "false";
56 
57       public:
FakeRunDex2Oat(ExecVHelper * execv_helper,FakeSystemProperties * properties)58         FakeRunDex2Oat(ExecVHelper* execv_helper, FakeSystemProperties* properties)
59           : RunDex2Oat("/dir/bin/dex2oat", execv_helper), properties_(properties) { }
60 
~FakeRunDex2Oat()61         virtual ~FakeRunDex2Oat() {}
62 
GetProperty(const std::string & key,const std::string & default_value)63         virtual std::string GetProperty(const std::string& key,
64                                         const std::string& default_value) override {
65             if (!properties_) {
66                 return default_value;
67             }
68             auto iter = properties_->find(key);
69             if (iter == properties_->end()) {
70                 return default_value;
71             }
72             return iter->second;
73         }
74 
GetBoolProperty(const std::string & key,bool default_value)75         virtual bool GetBoolProperty(const std::string& key, bool default_value) override {
76             std::string value = GetProperty(key, "");
77             if (value == "") {
78                 return default_value;
79             }
80             return value == TRUE_STR;
81         }
82 
83       private:
84         FakeSystemProperties* properties_;
85     };
86 
87     struct RunDex2OatArgs {
MakeDefaultTestArgsandroid::installd::RunDex2OatTest::RunDex2OatArgs88         static std::unique_ptr<RunDex2OatArgs> MakeDefaultTestArgs() {
89             auto args = std::make_unique<RunDex2OatArgs>();
90             args->input_dex.reset(ZIP_FD, INPUT_PATH);
91             args->output_oat.reset(OAT_FD, OUTPUT_PATH);
92             args->input_vdex.reset(INPUT_VDEX_FD, "UNUSED_PATH");
93             args->output_vdex.reset(OUTPUT_VDEX_FD, "UNUSED_PATH");
94             args->instruction_set = "arm64";
95             args->compilation_reason = "rundex2oattest";
96             return args;
97         }
98 
99         UniqueFile output_oat;
100         UniqueFile output_vdex;
101         UniqueFile output_image;
102         UniqueFile input_dex;
103         UniqueFile input_vdex;
104         UniqueFile dex_metadata;
105         UniqueFile profile;
106         int swap_fd = -1;
107         const char* instruction_set = nullptr;
108         const char* compiler_filter = "extract";
109         bool debuggable = false;
110         bool post_bootcomplete = false;
111         bool for_restore = false;
112         const char* class_loader_context = nullptr;
113         std::string class_loader_context_fds;
114         int target_sdk_version = 0;
115         bool enable_hidden_api_checks = false;
116         bool generate_compact_dex = true;
117         bool use_jitzygote = false;
118         bool background_job_compile = false;
119         const char* compilation_reason = nullptr;
120     };
121 
122     class FakeExecVHelper : public ExecVHelper {
123       public:
HasArg(const std::string & arg) const124         bool HasArg(const std::string& arg) const {
125             auto end = argv_.end() - 1;  // To exclude the terminating nullptr
126             return find(argv_.begin(), end, arg) != end;
127         }
128 
FlagNotUsed(const std::string & flag) const129         bool FlagNotUsed(const std::string& flag) const {
130             auto has_prefix = [flag](const char* arg) {
131                 return strncmp(arg, flag.c_str(), flag.size()) == 0;
132             };
133             auto end = argv_.end() - 1;  // To exclude the terminating nullptr
134             return find_if(argv_.begin(), end, has_prefix) == end;
135         }
136 
Exec(int exit_code)137         virtual void Exec(int exit_code) override {
138             std::string cmd;
139             for (auto arg : argv_) {
140                 if (arg == nullptr) {
141                   continue;
142                 }
143                 cmd += arg;
144                 cmd += " ";
145             }
146             LOG(DEBUG) << "FakeExecVHelper exit_code: " << exit_code << " cmd: " << cmd << "\n";
147         }
148     };
149 
SetUp()150     virtual void SetUp() override {
151         execv_helper_.reset(new FakeExecVHelper());
152         system_properties_.clear();
153         initializeDefaultExpectedFlags();
154     }
155 
156     // Initializes the default flags expected to a run.  It currently matches to the expected flags
157     // with RunDex2OatArgs::MakeDefaultTestArgs.
158     //
159     // default_expected_flags_ defines a mapping of <flag_name, expected_value>, where flag_name is
160     // something like "--flag-name", and expected_value can be "=value" or ":value" (depending on
161     // its delimiter), "" (if no value is needed), or a special value of FLAG_UNUSED to indicates
162     // that it should not be used.
initializeDefaultExpectedFlags()163     void initializeDefaultExpectedFlags() {
164         default_expected_flags_.clear();
165 
166         // Files
167         default_expected_flags_["--zip-fd"] = "=" + std::to_string(ZIP_FD);
168         default_expected_flags_["--zip-location"] = "=basename.apk";
169         default_expected_flags_["--oat-fd"] = "=" + std::to_string(OAT_FD);
170         default_expected_flags_["--oat-location"] = "=" + std::string(OUTPUT_PATH);
171         default_expected_flags_["--input-vdex-fd"] = "=" + std::to_string(INPUT_VDEX_FD);
172         default_expected_flags_["--output-vdex-fd"] = "=" + std::to_string(OUTPUT_VDEX_FD);
173         default_expected_flags_["--classpath-dir"] = "=/dir/input";
174         default_expected_flags_["--app-image-fd"] = FLAG_UNUSED;
175         default_expected_flags_["--profile-file-fd"] = FLAG_UNUSED;
176         default_expected_flags_["--swap-fd"] = FLAG_UNUSED;
177         default_expected_flags_["--class-loader-context"] = FLAG_UNUSED;
178         default_expected_flags_["--class-loader-context-fds"] = FLAG_UNUSED;
179         default_expected_flags_["--boot-image"] = FLAG_UNUSED;
180 
181         // Arch
182         default_expected_flags_["--instruction-set"] = "=arm64";
183         default_expected_flags_["--instruction-set-features"] = FLAG_UNUSED;
184         default_expected_flags_["--instruction-set-variant"] = FLAG_UNUSED;
185         default_expected_flags_["--cpu-set"] = FLAG_UNUSED;
186 
187         // Misc
188         default_expected_flags_["--compiler-filter"] = "=extract";
189         default_expected_flags_["--compilation-reason"] = "=rundex2oattest";
190         default_expected_flags_["--compact-dex-level"] = FLAG_UNUSED;
191         default_expected_flags_["-j"] = FLAG_UNUSED;
192         default_expected_flags_["--max-image-block-size"] = FLAG_UNUSED;
193         default_expected_flags_["--very-large-app-threshold"] = FLAG_UNUSED;
194         default_expected_flags_["--resolve-startup-const-strings"] = FLAG_UNUSED;
195         default_expected_flags_["--force-jit-zygote"] = FLAG_UNUSED;
196 
197         // Debug
198         default_expected_flags_["--debuggable"] = FLAG_UNUSED;
199         default_expected_flags_["--generate-debug-info"] = FLAG_UNUSED;
200         default_expected_flags_["--generate-mini-debug-info"] = FLAG_UNUSED;
201 
202         // Runtime
203         // TODO(victorhsieh): Check if the previous flag is actually --runtime-arg.
204         default_expected_flags_["-Xms"] = FLAG_UNUSED;
205         default_expected_flags_["-Xmx"] = FLAG_UNUSED;
206         default_expected_flags_["-Xbootclasspath"] = FLAG_UNUSED;
207         default_expected_flags_["-Xtarget-sdk-version"] = FLAG_UNUSED;
208         default_expected_flags_["-Xhidden-api-policy"] = FLAG_UNUSED;
209         default_expected_flags_["-Xnorelocate"] = FLAG_UNUSED;
210 
211         // Test only
212         default_expected_flags_["--foo"] = FLAG_UNUSED;
213         default_expected_flags_["--bar"] = FLAG_UNUSED;
214         default_expected_flags_["--baz"] = FLAG_UNUSED;
215     }
216 
SetExpectedFlagUsed(const std::string & flag,const std::string & value)217     void SetExpectedFlagUsed(const std::string& flag, const std::string& value) {
218         auto iter = default_expected_flags_.find(flag);
219         ASSERT_NE(iter, default_expected_flags_.end()) << "Must define the default value";
220         iter->second = value;
221     }
222 
VerifyExpectedFlags()223     void VerifyExpectedFlags() {
224         for (auto const& [flag, value] : default_expected_flags_) {
225             if (value == FLAG_UNUSED) {
226                 EXPECT_TRUE(execv_helper_->FlagNotUsed(flag))
227                     << "Flag " << flag << " should be unused, but got the value " << value;
228             } else if (value == "") {
229                 EXPECT_TRUE(execv_helper_->HasArg(flag))
230                     << "Flag " << flag << " should be specified without value, but got " << value;
231             } else {
232                 EXPECT_TRUE(execv_helper_->HasArg(flag + value))
233                     << "Flag " << flag << value << " is not specificed";
234             }
235         }
236     }
237 
setSystemProperty(const std::string & key,const std::string & value)238     void setSystemProperty(const std::string& key, const std::string& value) {
239         system_properties_[key] = value;
240     }
241 
CallRunDex2Oat(std::unique_ptr<RunDex2OatArgs> args)242     void CallRunDex2Oat(std::unique_ptr<RunDex2OatArgs> args) {
243         FakeRunDex2Oat runner(execv_helper_.get(), &system_properties_);
244         runner.Initialize(args->output_oat,
245                           args->output_vdex,
246                           args->output_image,
247                           args->input_dex,
248                           args->input_vdex,
249                           args->dex_metadata,
250                           args->profile,
251                           args->class_loader_context,
252                           args->class_loader_context_fds,
253                           args->swap_fd,
254                           args->instruction_set,
255                           args->compiler_filter,
256                           args->debuggable,
257                           args->post_bootcomplete,
258                           args->for_restore,
259                           args->target_sdk_version,
260                           args->enable_hidden_api_checks,
261                           args->generate_compact_dex,
262                           args->use_jitzygote,
263                           args->background_job_compile,
264                           args->compilation_reason);
265         runner.Exec(/*exit_code=*/ 0);
266     }
267 
268   private:
269     std::unique_ptr<FakeExecVHelper> execv_helper_;
270     std::map<std::string, std::string> default_expected_flags_;
271     FakeSystemProperties system_properties_;
272 };
273 
TEST_F(RunDex2OatTest,BasicInputOutput)274 TEST_F(RunDex2OatTest, BasicInputOutput) {
275     auto execv_helper = std::make_unique<FakeExecVHelper>();
276     CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
277 
278     VerifyExpectedFlags();
279 }
280 
TEST_F(RunDex2OatTest,WithAllOtherInputFds)281 TEST_F(RunDex2OatTest, WithAllOtherInputFds) {
282     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
283     args->output_image.reset(IMAGE_FD, "UNUSED_PATH");
284     args->profile.reset(PROFILE_FD, "UNUSED_PATH");
285     args->swap_fd = SWAP_FD;
286     CallRunDex2Oat(std::move(args));
287 
288     SetExpectedFlagUsed("--app-image-fd", "=" + std::to_string(IMAGE_FD));
289     SetExpectedFlagUsed("--profile-file-fd", "=" + std::to_string(PROFILE_FD));
290     SetExpectedFlagUsed("--swap-fd", "=" + std::to_string(SWAP_FD));
291     VerifyExpectedFlags();
292 }
293 
TEST_F(RunDex2OatTest,WithClassLoaderContext)294 TEST_F(RunDex2OatTest, WithClassLoaderContext) {
295     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
296     args->class_loader_context = "CLASS_LOADER_CONTEXT";
297     CallRunDex2Oat(std::move(args));
298 
299     SetExpectedFlagUsed("--class-loader-context", "=CLASS_LOADER_CONTEXT");
300     SetExpectedFlagUsed("--class-loader-context-fds", FLAG_UNUSED);
301     VerifyExpectedFlags();
302 }
303 
TEST_F(RunDex2OatTest,WithClassLoaderContextAndFds)304 TEST_F(RunDex2OatTest, WithClassLoaderContextAndFds) {
305     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
306     args->class_loader_context = "CLASS_LOADER_CONTEXT";
307     args->class_loader_context_fds = "CLASS_LOADER_CONTEXT_FDS";
308     CallRunDex2Oat(std::move(args));
309 
310     SetExpectedFlagUsed("--class-loader-context", "=CLASS_LOADER_CONTEXT");
311     SetExpectedFlagUsed("--class-loader-context-fds", "=CLASS_LOADER_CONTEXT_FDS");
312     VerifyExpectedFlags();
313 }
314 
TEST_F(RunDex2OatTest,WithOnlyClassLoaderContextFds)315 TEST_F(RunDex2OatTest, WithOnlyClassLoaderContextFds) {
316     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
317     args->class_loader_context_fds = "CLASS_LOADER_CONTEXT_FDS";
318     CallRunDex2Oat(std::move(args));
319 
320     SetExpectedFlagUsed("--class-loader-context", FLAG_UNUSED);
321     SetExpectedFlagUsed("--class-loader-context-fds", FLAG_UNUSED);
322     VerifyExpectedFlags();
323 }
324 
TEST_F(RunDex2OatTest,DoNotGenerateCompactDex)325 TEST_F(RunDex2OatTest, DoNotGenerateCompactDex) {
326     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
327     args->generate_compact_dex = false;
328     CallRunDex2Oat(std::move(args));
329 
330     SetExpectedFlagUsed("--compact-dex-level", "=none");
331     VerifyExpectedFlags();
332 }
333 
TEST_F(RunDex2OatTest,DoNotGenerateCompactDexWithVdexInPlaceUpdate)334 TEST_F(RunDex2OatTest, DoNotGenerateCompactDexWithVdexInPlaceUpdate) {
335     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
336     args->generate_compact_dex = true;
337     args->input_vdex.reset(INPUT_VDEX_FD, "UNUSED_PATH");
338     args->output_vdex.reset(INPUT_VDEX_FD, "UNUSED_PATH");
339     CallRunDex2Oat(std::move(args));
340 
341     SetExpectedFlagUsed("--compact-dex-level", "=none");
342     SetExpectedFlagUsed("--output-vdex-fd", "=" + std::to_string(INPUT_VDEX_FD));
343     VerifyExpectedFlags();
344 }
345 
TEST_F(RunDex2OatTest,ISA)346 TEST_F(RunDex2OatTest, ISA) {
347     setSystemProperty("dalvik.vm.isa.x86.features", "a-x86-feature");
348     setSystemProperty("dalvik.vm.isa.x86.variant", "a-x86-variant");
349     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
350     args->instruction_set = "x86";
351     CallRunDex2Oat(std::move(args));
352 
353     SetExpectedFlagUsed("--instruction-set", "=x86");
354     SetExpectedFlagUsed("--instruction-set-features", "=a-x86-feature");
355     SetExpectedFlagUsed("--instruction-set-variant", "=a-x86-variant");
356     VerifyExpectedFlags();
357 }
358 
TEST_F(RunDex2OatTest,CpuSetPreBootComplete)359 TEST_F(RunDex2OatTest, CpuSetPreBootComplete) {
360     setSystemProperty("dalvik.vm.boot-dex2oat-cpu-set", "1,2");
361     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
362     args->post_bootcomplete = false;
363     CallRunDex2Oat(std::move(args));
364 
365     SetExpectedFlagUsed("--cpu-set", "=1,2");
366     VerifyExpectedFlags();
367 }
368 
TEST_F(RunDex2OatTest,CpuSetPostBootCompleteNotForRestore)369 TEST_F(RunDex2OatTest, CpuSetPostBootCompleteNotForRestore) {
370     setSystemProperty("dalvik.vm.dex2oat-cpu-set", "1,2");
371     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
372     args->post_bootcomplete = true;
373     args->for_restore = false;
374     CallRunDex2Oat(std::move(args));
375 
376     SetExpectedFlagUsed("--cpu-set", "=1,2");
377     VerifyExpectedFlags();
378 }
379 
TEST_F(RunDex2OatTest,CpuSetPostBootCompleteBackground)380 TEST_F(RunDex2OatTest, CpuSetPostBootCompleteBackground) {
381     setSystemProperty("dalvik.vm.background-dex2oat-cpu-set", "1,3");
382     setSystemProperty("dalvik.vm.dex2oat-cpu-set", "1,2");
383     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
384     args->post_bootcomplete = true;
385     args->background_job_compile = true;
386     CallRunDex2Oat(std::move(args));
387 
388     SetExpectedFlagUsed("--cpu-set", "=1,3");
389     VerifyExpectedFlags();
390 }
391 
TEST_F(RunDex2OatTest,CpuSetPostBootCompleteBackground_Backup)392 TEST_F(RunDex2OatTest, CpuSetPostBootCompleteBackground_Backup) {
393     setSystemProperty("dalvik.vm.background-dex2oat-cpu-set", "");
394     setSystemProperty("dalvik.vm.dex2oat-cpu-set", "1,2");
395     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
396     args->post_bootcomplete = true;
397     args->background_job_compile = true;
398     CallRunDex2Oat(std::move(args));
399 
400     SetExpectedFlagUsed("--cpu-set", "=1,2");
401     VerifyExpectedFlags();
402 }
403 
TEST_F(RunDex2OatTest,CpuSetPostBootCompleteForRestore)404 TEST_F(RunDex2OatTest, CpuSetPostBootCompleteForRestore) {
405     setSystemProperty("dalvik.vm.restore-dex2oat-cpu-set", "1,2");
406     setSystemProperty("dalvik.vm.dex2oat-cpu-set", "2,3");
407     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
408     args->post_bootcomplete = true;
409     args->for_restore = true;
410     CallRunDex2Oat(std::move(args));
411 
412     SetExpectedFlagUsed("--cpu-set", "=1,2");
413     VerifyExpectedFlags();
414 }
415 
TEST_F(RunDex2OatTest,CpuSetPostBootCompleteForRestore_Backup)416 TEST_F(RunDex2OatTest, CpuSetPostBootCompleteForRestore_Backup) {
417     setSystemProperty("dalvik.vm.restore-dex2oat-cpu-set", "");
418     setSystemProperty("dalvik.vm.dex2oat-cpu-set", "1,2");
419     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
420     args->post_bootcomplete = true;
421     args->for_restore = true;
422     CallRunDex2Oat(std::move(args));
423 
424     SetExpectedFlagUsed("--cpu-set", "=1,2");
425     VerifyExpectedFlags();
426 }
427 
TEST_F(RunDex2OatTest,Runtime)428 TEST_F(RunDex2OatTest, Runtime) {
429     setSystemProperty("dalvik.vm.dex2oat-Xms", "1234m");
430     setSystemProperty("dalvik.vm.dex2oat-Xmx", "5678m");
431     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
432     args->target_sdk_version = 30;
433     args->enable_hidden_api_checks = true;
434     CallRunDex2Oat(std::move(args));
435 
436     SetExpectedFlagUsed("-Xms", "1234m");
437     SetExpectedFlagUsed("-Xmx", "5678m");
438     SetExpectedFlagUsed("-Xtarget-sdk-version", ":30");
439     SetExpectedFlagUsed("-Xhidden-api-policy", ":enabled");
440     SetExpectedFlagUsed("-Xnorelocate", FLAG_UNUSED);
441     VerifyExpectedFlags();
442 }
443 
TEST_F(RunDex2OatTest,DalvikVmDex2oatFilter)444 TEST_F(RunDex2OatTest, DalvikVmDex2oatFilter) {
445     setSystemProperty("dalvik.vm.dex2oat-filter", "speed");
446     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
447     args->compiler_filter = nullptr;
448     CallRunDex2Oat(std::move(args));
449 
450     SetExpectedFlagUsed("--compiler-filter", "=speed");
451     VerifyExpectedFlags();
452 }
453 
TEST_F(RunDex2OatTest,ResolveStartupStartings)454 TEST_F(RunDex2OatTest, ResolveStartupStartings) {
455     setSystemProperty("dalvik.vm.dex2oat-resolve-startup-strings", "false");
456     CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
457 
458     SetExpectedFlagUsed("--resolve-startup-const-strings", "=false");
459     VerifyExpectedFlags();
460 }
461 
TEST_F(RunDex2OatTest,ResolveStartupStartingsOverride)462 TEST_F(RunDex2OatTest, ResolveStartupStartingsOverride) {
463     setSystemProperty("dalvik.vm.dex2oat-resolve-startup-strings", "false");
464     setSystemProperty("persist.device_config.runtime.dex2oat_resolve_startup_strings", "true");
465     CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
466 
467     SetExpectedFlagUsed("--resolve-startup-const-strings", "=true");
468     VerifyExpectedFlags();
469 }
470 
TEST_F(RunDex2OatTest,ThreadsPreBootComplete)471 TEST_F(RunDex2OatTest, ThreadsPreBootComplete) {
472     setSystemProperty("dalvik.vm.boot-dex2oat-threads", "2");
473     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
474     args->post_bootcomplete = false;
475     CallRunDex2Oat(std::move(args));
476 
477     SetExpectedFlagUsed("-j", "2");
478     VerifyExpectedFlags();
479 }
480 
TEST_F(RunDex2OatTest,ThreadsPostBootCompleteNotForRestore)481 TEST_F(RunDex2OatTest, ThreadsPostBootCompleteNotForRestore) {
482     setSystemProperty("dalvik.vm.dex2oat-threads", "3");
483     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
484     args->post_bootcomplete = true;
485     args->for_restore = false;
486     CallRunDex2Oat(std::move(args));
487 
488     SetExpectedFlagUsed("-j", "3");
489     VerifyExpectedFlags();
490 }
491 
TEST_F(RunDex2OatTest,ThreadsPostBootCompleteBackground)492 TEST_F(RunDex2OatTest, ThreadsPostBootCompleteBackground) {
493     setSystemProperty("dalvik.vm.background-dex2oat-threads", "2");
494     setSystemProperty("dalvik.vm.dex2oat-threads", "3");
495     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
496     args->post_bootcomplete = true;
497     args->background_job_compile = true;
498     CallRunDex2Oat(std::move(args));
499 
500     SetExpectedFlagUsed("-j", "2");
501     VerifyExpectedFlags();
502 }
503 
TEST_F(RunDex2OatTest,ThreadsPostBootCompleteBackground_Backup)504 TEST_F(RunDex2OatTest, ThreadsPostBootCompleteBackground_Backup) {
505     setSystemProperty("dalvik.vm.background-dex2oat-threads", "");
506     setSystemProperty("dalvik.vm.dex2oat-threads", "3");
507     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
508     args->post_bootcomplete = true;
509     args->background_job_compile = true;
510     CallRunDex2Oat(std::move(args));
511 
512     SetExpectedFlagUsed("-j", "3");
513     VerifyExpectedFlags();
514 }
515 
TEST_F(RunDex2OatTest,ThreadsPostBootCompleteForRestore)516 TEST_F(RunDex2OatTest, ThreadsPostBootCompleteForRestore) {
517     setSystemProperty("dalvik.vm.restore-dex2oat-threads", "4");
518     setSystemProperty("dalvik.vm.dex2oat-threads", "5");
519     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
520     args->post_bootcomplete = true;
521     args->for_restore = true;
522     CallRunDex2Oat(std::move(args));
523 
524     SetExpectedFlagUsed("-j", "4");
525     VerifyExpectedFlags();
526 }
527 
TEST_F(RunDex2OatTest,ThreadsPostBootCompleteForRestore_Backup)528 TEST_F(RunDex2OatTest, ThreadsPostBootCompleteForRestore_Backup) {
529     setSystemProperty("dalvik.vm.restore-dex2oat-threads", "");
530     setSystemProperty("dalvik.vm.dex2oat-threads", "5");
531     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
532     args->post_bootcomplete = true;
533     args->for_restore = true;
534     CallRunDex2Oat(std::move(args));
535 
536     SetExpectedFlagUsed("-j", "5");
537     VerifyExpectedFlags();
538 }
539 
TEST_F(RunDex2OatTest,Debuggable)540 TEST_F(RunDex2OatTest, Debuggable) {
541     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
542     args->debuggable = true;
543     CallRunDex2Oat(std::move(args));
544 
545     SetExpectedFlagUsed("--debuggable", "");
546     VerifyExpectedFlags();
547 }
548 
TEST_F(RunDex2OatTest,AlwaysDebuggable)549 TEST_F(RunDex2OatTest, AlwaysDebuggable) {
550     setSystemProperty("dalvik.vm.always_debuggable", "1");
551     CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
552 
553     SetExpectedFlagUsed("--debuggable", "");
554     VerifyExpectedFlags();
555 }
556 
TEST_F(RunDex2OatTest,GenerateDebugInfo)557 TEST_F(RunDex2OatTest, GenerateDebugInfo) {
558     setSystemProperty("debug.generate-debug-info", "true");
559     CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
560 
561     SetExpectedFlagUsed("--generate-debug-info", "");
562     VerifyExpectedFlags();
563 }
564 
TEST_F(RunDex2OatTest,HiddenApiCheck)565 TEST_F(RunDex2OatTest, HiddenApiCheck) {
566     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
567     args->enable_hidden_api_checks = true;
568     CallRunDex2Oat(std::move(args));
569 
570     SetExpectedFlagUsed("-Xhidden-api-policy", ":enabled");
571     VerifyExpectedFlags();
572 }
573 
TEST_F(RunDex2OatTest,Misc)574 TEST_F(RunDex2OatTest, Misc) {
575     setSystemProperty("dalvik.vm.dex2oat-max-image-block-size", "524288");
576     setSystemProperty("dalvik.vm.dex2oat-very-large", "100000");
577     CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
578 
579     SetExpectedFlagUsed("--max-image-block-size", "=524288");
580     SetExpectedFlagUsed("--very-large-app-threshold", "=100000");
581     VerifyExpectedFlags();
582 }
583 
TEST_F(RunDex2OatTest,ExtraFlags)584 TEST_F(RunDex2OatTest, ExtraFlags) {
585     setSystemProperty("dalvik.vm.dex2oat-flags", "--foo=123 --bar:456 --baz");
586     CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
587 
588     SetExpectedFlagUsed("--foo", "=123");
589     SetExpectedFlagUsed("--bar", ":456");
590     SetExpectedFlagUsed("--baz", "");
591     VerifyExpectedFlags();
592 }
593 
TEST_F(RunDex2OatTest,UseJitZygoteImage)594 TEST_F(RunDex2OatTest, UseJitZygoteImage) {
595     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
596     args->use_jitzygote = true;
597     CallRunDex2Oat(std::move(args));
598 
599     SetExpectedFlagUsed("--force-jit-zygote", "");
600     VerifyExpectedFlags();
601 }
602 
TEST_F(RunDex2OatTest,BootImage)603 TEST_F(RunDex2OatTest, BootImage) {
604     setSystemProperty("dalvik.vm.boot-image", "foo.art:bar.art");
605     CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
606 
607     SetExpectedFlagUsed("--boot-image", "=foo.art:bar.art");
608     VerifyExpectedFlags();
609 }
610 
611 }  // namespace installd
612 }  // namespace android
613