blob: 5fc3da42e817c6325dcbba6ff2290749c61a1920 [file] [log] [blame]
Andreas Gampee1459ae2016-06-29 09:36:30 -07001/*
2 * Copyright (C) 2016 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
Igor Murashkin5573c372017-11-16 13:34:30 -080017#include <regex>
Andreas Gampe7adeda82016-07-25 08:27:35 -070018#include <sstream>
Andreas Gampee1459ae2016-06-29 09:36:30 -070019#include <string>
20#include <vector>
Andreas Gampee1459ae2016-06-29 09:36:30 -070021
Andreas Gampe46ee31b2016-12-14 10:11:49 -080022#include <sys/wait.h>
23#include <unistd.h>
24
Andreas Gampe57943812017-12-06 21:39:13 -080025#include <android-base/logging.h>
26#include <android-base/stringprintf.h>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080027
Andreas Gampee1459ae2016-06-29 09:36:30 -070028#include "common_runtime_test.h"
29
Andreas Gampee1459ae2016-06-29 09:36:30 -070030#include "base/macros.h"
Andreas Gampeb486a982017-06-01 13:45:54 -070031#include "base/mutex-inl.h"
David Sehrc431b9d2018-03-02 12:01:51 -080032#include "base/utils.h"
David Sehr013fd802018-01-11 22:55:24 -080033#include "dex/art_dex_file_loader.h"
Mathieu Chartier05f90d12018-02-07 13:47:17 -080034#include "dex/base64_test_util.h"
David Sehr312f3b22018-03-19 08:39:26 -070035#include "dex/bytecode_utils.h"
Mathieu Chartier2242ef12018-07-23 18:14:13 -070036#include "dex/class_accessor-inl.h"
David Sehr9e734c72018-01-04 17:56:19 -080037#include "dex/code_item_accessors-inl.h"
38#include "dex/dex_file-inl.h"
39#include "dex/dex_file_loader.h"
Andreas Gampee1459ae2016-06-29 09:36:30 -070040#include "dex2oat_environment_test.h"
Andreas Gampef7882972017-03-20 16:35:24 -070041#include "dex2oat_return_codes.h"
Andreas Gampe67f02822016-06-24 21:05:23 -070042#include "oat.h"
43#include "oat_file.h"
David Sehr82d046e2018-04-23 08:14:19 -070044#include "profile/profile_compilation_info.h"
Mathieu Chartier792111c2018-02-15 13:02:15 -080045#include "vdex_file.h"
46#include "ziparchive/zip_writer.h"
Andreas Gampee1459ae2016-06-29 09:36:30 -070047
Andreas Gampee1459ae2016-06-29 09:36:30 -070048namespace art {
49
Mathieu Chartierea650f32017-05-24 12:04:13 -070050static constexpr size_t kMaxMethodIds = 65535;
Mathieu Chartier9e050df2017-08-09 10:05:47 -070051static constexpr bool kDebugArgs = false;
Mathieu Chartier02129102017-12-22 11:04:01 -080052static const char* kDisableCompactDex = "--compact-dex-level=none";
Mathieu Chartierea650f32017-05-24 12:04:13 -070053
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080054using android::base::StringPrintf;
55
Andreas Gampee1459ae2016-06-29 09:36:30 -070056class Dex2oatTest : public Dex2oatEnvironmentTest {
57 public:
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010058 virtual void TearDown() override {
Andreas Gampee1459ae2016-06-29 09:36:30 -070059 Dex2oatEnvironmentTest::TearDown();
60
61 output_ = "";
62 error_msg_ = "";
63 success_ = false;
64 }
65
66 protected:
Mathieu Chartier9e050df2017-08-09 10:05:47 -070067 int GenerateOdexForTestWithStatus(const std::vector<std::string>& dex_locations,
Andreas Gampef7882972017-03-20 16:35:24 -070068 const std::string& odex_location,
69 CompilerFilter::Filter filter,
70 std::string* error_msg,
71 const std::vector<std::string>& extra_args = {},
72 bool use_fd = false) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080073 std::unique_ptr<File> oat_file;
Andreas Gampee1459ae2016-06-29 09:36:30 -070074 std::vector<std::string> args;
Mathieu Chartier9e050df2017-08-09 10:05:47 -070075 // Add dex file args.
76 for (const std::string& dex_location : dex_locations) {
77 args.push_back("--dex-file=" + dex_location);
78 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080079 if (use_fd) {
80 oat_file.reset(OS::CreateEmptyFile(odex_location.c_str()));
81 CHECK(oat_file != nullptr) << odex_location;
82 args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
Mathieu Chartier046854b2017-03-01 17:16:22 -080083 args.push_back("--oat-location=" + odex_location);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080084 } else {
85 args.push_back("--oat-file=" + odex_location);
86 }
Andreas Gampee1459ae2016-06-29 09:36:30 -070087 args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
88 args.push_back("--runtime-arg");
89 args.push_back("-Xnorelocate");
90
91 args.insert(args.end(), extra_args.begin(), extra_args.end());
92
Andreas Gampef7882972017-03-20 16:35:24 -070093 int status = Dex2Oat(args, error_msg);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080094 if (oat_file != nullptr) {
Andreas Gampef7882972017-03-20 16:35:24 -070095 CHECK_EQ(oat_file->FlushClose(), 0) << "Could not flush and close oat file";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080096 }
Andreas Gampef7882972017-03-20 16:35:24 -070097 return status;
98 }
Andreas Gampee1459ae2016-06-29 09:36:30 -070099
Andreas Gampe641a4732017-08-24 13:21:35 -0700100 void GenerateOdexForTest(
101 const std::string& dex_location,
102 const std::string& odex_location,
103 CompilerFilter::Filter filter,
104 const std::vector<std::string>& extra_args = {},
105 bool expect_success = true,
106 bool use_fd = false) {
107 GenerateOdexForTest(dex_location,
108 odex_location,
109 filter,
110 extra_args,
111 expect_success,
112 use_fd,
113 [](const OatFile&) {});
114 }
115
Andreas Gampe80ddf272018-01-11 09:41:00 -0800116 bool test_accepts_odex_file_on_failure = false;
117
Andreas Gampe641a4732017-08-24 13:21:35 -0700118 template <typename T>
119 void GenerateOdexForTest(
120 const std::string& dex_location,
121 const std::string& odex_location,
122 CompilerFilter::Filter filter,
123 const std::vector<std::string>& extra_args,
124 bool expect_success,
125 bool use_fd,
126 T check_oat) {
Andreas Gampef7882972017-03-20 16:35:24 -0700127 std::string error_msg;
Mathieu Chartier9e050df2017-08-09 10:05:47 -0700128 int status = GenerateOdexForTestWithStatus({dex_location},
Andreas Gampef7882972017-03-20 16:35:24 -0700129 odex_location,
130 filter,
131 &error_msg,
132 extra_args,
133 use_fd);
Andreas Gampe80ddf272018-01-11 09:41:00 -0800134 bool success = (WIFEXITED(status) && WEXITSTATUS(status) == 0);
Andreas Gampee1459ae2016-06-29 09:36:30 -0700135 if (expect_success) {
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800136 ASSERT_TRUE(success) << error_msg << std::endl << output_;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700137
138 // Verify the odex file was generated as expected.
Nicolas Geoffray30025092018-04-19 14:43:29 +0100139 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
140 odex_location.c_str(),
Andreas Gampee1459ae2016-06-29 09:36:30 -0700141 odex_location.c_str(),
142 nullptr,
143 nullptr,
144 false,
145 /*low_4gb*/false,
146 dex_location.c_str(),
147 &error_msg));
148 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
149
150 CheckFilter(filter, odex_file->GetCompilerFilter());
Calin Juravle1ce70852017-06-28 10:59:03 -0700151 check_oat(*(odex_file.get()));
Andreas Gampee1459ae2016-06-29 09:36:30 -0700152 } else {
153 ASSERT_FALSE(success) << output_;
154
155 error_msg_ = error_msg;
156
Andreas Gampe80ddf272018-01-11 09:41:00 -0800157 if (!test_accepts_odex_file_on_failure) {
158 // Verify there's no loadable odex file.
Nicolas Geoffray30025092018-04-19 14:43:29 +0100159 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
160 odex_location.c_str(),
Andreas Gampe80ddf272018-01-11 09:41:00 -0800161 odex_location.c_str(),
162 nullptr,
163 nullptr,
164 false,
165 /*low_4gb*/false,
166 dex_location.c_str(),
167 &error_msg));
168 ASSERT_TRUE(odex_file.get() == nullptr);
169 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700170 }
171 }
172
Calin Juravle1ccf6132017-08-02 17:46:53 -0700173 // Check the input compiler filter against the generated oat file's filter. May be overridden
Andreas Gampee1459ae2016-06-29 09:36:30 -0700174 // in subclasses when equality is not expected.
175 virtual void CheckFilter(CompilerFilter::Filter expected, CompilerFilter::Filter actual) {
176 EXPECT_EQ(expected, actual);
177 }
178
Andreas Gampef7882972017-03-20 16:35:24 -0700179 int Dex2Oat(const std::vector<std::string>& dex2oat_args, std::string* error_msg) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700180 Runtime* runtime = Runtime::Current();
181
182 const std::vector<gc::space::ImageSpace*>& image_spaces =
183 runtime->GetHeap()->GetBootImageSpaces();
184 if (image_spaces.empty()) {
185 *error_msg = "No image location found for Dex2Oat.";
186 return false;
187 }
188 std::string image_location = image_spaces[0]->GetImageLocation();
189
190 std::vector<std::string> argv;
191 argv.push_back(runtime->GetCompilerExecutable());
Calin Juravle1ccf6132017-08-02 17:46:53 -0700192
Nicolas Geoffray433b79a2017-01-30 20:54:45 +0000193 if (runtime->IsJavaDebuggable()) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700194 argv.push_back("--debuggable");
195 }
196 runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
197
198 if (!runtime->IsVerificationEnabled()) {
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100199 argv.push_back("--compiler-filter=assume-verified");
Andreas Gampee1459ae2016-06-29 09:36:30 -0700200 }
201
202 if (runtime->MustRelocateIfPossible()) {
203 argv.push_back("--runtime-arg");
204 argv.push_back("-Xrelocate");
205 } else {
206 argv.push_back("--runtime-arg");
207 argv.push_back("-Xnorelocate");
208 }
209
210 if (!kIsTargetBuild) {
211 argv.push_back("--host");
212 }
213
214 argv.push_back("--boot-image=" + image_location);
215
216 std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
217 argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
218
219 argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
220
221 // We must set --android-root.
222 const char* android_root = getenv("ANDROID_ROOT");
223 CHECK(android_root != nullptr);
224 argv.push_back("--android-root=" + std::string(android_root));
225
Mathieu Chartier9e050df2017-08-09 10:05:47 -0700226 if (kDebugArgs) {
227 std::string all_args;
228 for (const std::string& arg : argv) {
229 all_args += arg + " ";
230 }
231 LOG(ERROR) << all_args;
232 }
233
Andreas Gampe38aa0b52018-07-10 23:26:55 -0700234 // We need dex2oat to actually log things.
235 auto post_fork_fn = []() { return setenv("ANDROID_LOG_TAGS", "*:d", 1) == 0; };
236 ForkAndExecResult res = ForkAndExec(argv, post_fork_fn, &output_);
237 if (res.stage != ForkAndExecResult::kFinished) {
238 *error_msg = strerror(errno);
239 return -1;
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100240 }
Andreas Gampe38aa0b52018-07-10 23:26:55 -0700241 success_ = res.StandardSuccess();
242 return res.status_code;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700243 }
244
245 std::string output_ = "";
246 std::string error_msg_ = "";
247 bool success_ = false;
248};
249
250class Dex2oatSwapTest : public Dex2oatTest {
251 protected:
252 void RunTest(bool use_fd, bool expect_use, const std::vector<std::string>& extra_args = {}) {
253 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
254 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
255
Andreas Gampe7adeda82016-07-25 08:27:35 -0700256 Copy(GetTestDexFileName(), dex_location);
Andreas Gampee1459ae2016-06-29 09:36:30 -0700257
258 std::vector<std::string> copy(extra_args);
259
260 std::unique_ptr<ScratchFile> sf;
261 if (use_fd) {
262 sf.reset(new ScratchFile());
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800263 copy.push_back(android::base::StringPrintf("--swap-fd=%d", sf->GetFd()));
Andreas Gampee1459ae2016-06-29 09:36:30 -0700264 } else {
265 std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
266 copy.push_back("--swap-file=" + swap_location);
267 }
268 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, copy);
269
270 CheckValidity();
271 ASSERT_TRUE(success_);
272 CheckResult(expect_use);
273 }
274
Andreas Gampe7adeda82016-07-25 08:27:35 -0700275 virtual std::string GetTestDexFileName() {
Vladimir Marko15357702017-02-09 10:37:31 +0000276 return Dex2oatEnvironmentTest::GetTestDexFileName("VerifierDeps");
Andreas Gampe7adeda82016-07-25 08:27:35 -0700277 }
278
279 virtual void CheckResult(bool expect_use) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700280 if (kIsTargetBuild) {
281 CheckTargetResult(expect_use);
282 } else {
283 CheckHostResult(expect_use);
284 }
285 }
286
Andreas Gampe7adeda82016-07-25 08:27:35 -0700287 virtual void CheckTargetResult(bool expect_use ATTRIBUTE_UNUSED) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700288 // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
289 // something for variants with file descriptor where we can control the lifetime of
290 // the swap file and thus take a look at it.
291 }
292
Andreas Gampe7adeda82016-07-25 08:27:35 -0700293 virtual void CheckHostResult(bool expect_use) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700294 if (!kIsTargetBuild) {
295 if (expect_use) {
296 EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
297 << output_;
298 } else {
299 EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
300 << output_;
301 }
302 }
303 }
304
305 // Check whether the dex2oat run was really successful.
Andreas Gampe7adeda82016-07-25 08:27:35 -0700306 virtual void CheckValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700307 if (kIsTargetBuild) {
308 CheckTargetValidity();
309 } else {
310 CheckHostValidity();
311 }
312 }
313
Andreas Gampe7adeda82016-07-25 08:27:35 -0700314 virtual void CheckTargetValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700315 // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
316 // something for variants with file descriptor where we can control the lifetime of
317 // the swap file and thus take a look at it.
318 }
319
320 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
Andreas Gampe7adeda82016-07-25 08:27:35 -0700321 virtual void CheckHostValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700322 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
323 }
324};
325
326TEST_F(Dex2oatSwapTest, DoNotUseSwapDefaultSingleSmall) {
327 RunTest(false /* use_fd */, false /* expect_use */);
328 RunTest(true /* use_fd */, false /* expect_use */);
329}
330
331TEST_F(Dex2oatSwapTest, DoNotUseSwapSingle) {
332 RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
333 RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
334}
335
336TEST_F(Dex2oatSwapTest, DoNotUseSwapSmall) {
337 RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
338 RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
339}
340
341TEST_F(Dex2oatSwapTest, DoUseSwapSingleSmall) {
342 RunTest(false /* use_fd */,
343 true /* expect_use */,
344 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
345 RunTest(true /* use_fd */,
346 true /* expect_use */,
347 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
348}
349
Andreas Gampe7adeda82016-07-25 08:27:35 -0700350class Dex2oatSwapUseTest : public Dex2oatSwapTest {
351 protected:
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100352 void CheckHostResult(bool expect_use) override {
Andreas Gampe7adeda82016-07-25 08:27:35 -0700353 if (!kIsTargetBuild) {
354 if (expect_use) {
355 EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
356 << output_;
357 } else {
358 EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
359 << output_;
360 }
361 }
362 }
363
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100364 std::string GetTestDexFileName() override {
Andreas Gampe7adeda82016-07-25 08:27:35 -0700365 // Use Statics as it has a handful of functions.
366 return CommonRuntimeTest::GetTestDexFileName("Statics");
367 }
368
369 void GrabResult1() {
370 if (!kIsTargetBuild) {
371 native_alloc_1_ = ParseNativeAlloc();
372 swap_1_ = ParseSwap(false /* expected */);
373 } else {
374 native_alloc_1_ = std::numeric_limits<size_t>::max();
375 swap_1_ = 0;
376 }
377 }
378
379 void GrabResult2() {
380 if (!kIsTargetBuild) {
381 native_alloc_2_ = ParseNativeAlloc();
382 swap_2_ = ParseSwap(true /* expected */);
383 } else {
384 native_alloc_2_ = 0;
385 swap_2_ = std::numeric_limits<size_t>::max();
386 }
387 }
388
389 private:
390 size_t ParseNativeAlloc() {
391 std::regex native_alloc_regex("dex2oat took.*native alloc=[^ ]+ \\(([0-9]+)B\\)");
392 std::smatch native_alloc_match;
393 bool found = std::regex_search(output_, native_alloc_match, native_alloc_regex);
394 if (!found) {
395 EXPECT_TRUE(found);
396 return 0;
397 }
398 if (native_alloc_match.size() != 2U) {
399 EXPECT_EQ(native_alloc_match.size(), 2U);
400 return 0;
401 }
402
403 std::istringstream stream(native_alloc_match[1].str());
404 size_t value;
405 stream >> value;
406
407 return value;
408 }
409
410 size_t ParseSwap(bool expected) {
411 std::regex swap_regex("dex2oat took[^\\n]+swap=[^ ]+ \\(([0-9]+)B\\)");
412 std::smatch swap_match;
413 bool found = std::regex_search(output_, swap_match, swap_regex);
414 if (found != expected) {
415 EXPECT_EQ(expected, found);
416 return 0;
417 }
418
419 if (!found) {
420 return 0;
421 }
422
423 if (swap_match.size() != 2U) {
424 EXPECT_EQ(swap_match.size(), 2U);
425 return 0;
426 }
427
428 std::istringstream stream(swap_match[1].str());
429 size_t value;
430 stream >> value;
431
432 return value;
433 }
434
435 protected:
436 size_t native_alloc_1_;
437 size_t native_alloc_2_;
438
439 size_t swap_1_;
440 size_t swap_2_;
441};
442
443TEST_F(Dex2oatSwapUseTest, CheckSwapUsage) {
Roland Levillain05e34f42018-05-24 13:19:05 +0000444 // Native memory usage isn't correctly tracked when running under ASan.
445 TEST_DISABLED_FOR_MEMORY_TOOL();
Andreas Gampef4a67fd2017-05-04 09:55:36 -0700446
Vladimir Marko57070da2017-02-14 16:16:30 +0000447 // The `native_alloc_2_ >= native_alloc_1_` assertion below may not
Roland Levillain19772bf2017-02-16 11:28:10 +0000448 // hold true on some x86 systems; disable this test while we
449 // investigate (b/29259363).
450 TEST_DISABLED_FOR_X86();
Vladimir Marko57070da2017-02-14 16:16:30 +0000451
Andreas Gampe7adeda82016-07-25 08:27:35 -0700452 RunTest(false /* use_fd */,
453 false /* expect_use */);
454 GrabResult1();
455 std::string output_1 = output_;
456
457 output_ = "";
458
459 RunTest(false /* use_fd */,
460 true /* expect_use */,
461 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
462 GrabResult2();
463 std::string output_2 = output_;
464
465 if (native_alloc_2_ >= native_alloc_1_ || swap_1_ >= swap_2_) {
466 EXPECT_LT(native_alloc_2_, native_alloc_1_);
467 EXPECT_LT(swap_1_, swap_2_);
468
469 LOG(ERROR) << output_1;
470 LOG(ERROR) << output_2;
471 }
472}
473
Andreas Gampe67f02822016-06-24 21:05:23 -0700474class Dex2oatVeryLargeTest : public Dex2oatTest {
475 protected:
476 void CheckFilter(CompilerFilter::Filter input ATTRIBUTE_UNUSED,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100477 CompilerFilter::Filter result ATTRIBUTE_UNUSED) override {
Andreas Gampe67f02822016-06-24 21:05:23 -0700478 // Ignore, we'll do our own checks.
479 }
480
481 void RunTest(CompilerFilter::Filter filter,
482 bool expect_large,
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700483 bool expect_downgrade,
Andreas Gampe67f02822016-06-24 21:05:23 -0700484 const std::vector<std::string>& extra_args = {}) {
485 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
486 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700487 std::string app_image_file = GetScratchDir() + "/Test.art";
Andreas Gampe67f02822016-06-24 21:05:23 -0700488
489 Copy(GetDexSrc1(), dex_location);
490
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700491 std::vector<std::string> new_args(extra_args);
492 new_args.push_back("--app-image-file=" + app_image_file);
493 GenerateOdexForTest(dex_location, odex_location, filter, new_args);
Andreas Gampe67f02822016-06-24 21:05:23 -0700494
495 CheckValidity();
496 ASSERT_TRUE(success_);
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700497 CheckResult(dex_location,
498 odex_location,
499 app_image_file,
500 filter,
501 expect_large,
502 expect_downgrade);
Andreas Gampe67f02822016-06-24 21:05:23 -0700503 }
504
505 void CheckResult(const std::string& dex_location,
506 const std::string& odex_location,
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700507 const std::string& app_image_file,
Andreas Gampe67f02822016-06-24 21:05:23 -0700508 CompilerFilter::Filter filter,
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700509 bool expect_large,
510 bool expect_downgrade) {
511 if (expect_downgrade) {
512 EXPECT_TRUE(expect_large);
513 }
Andreas Gampe67f02822016-06-24 21:05:23 -0700514 // Host/target independent checks.
515 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +0100516 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
517 odex_location.c_str(),
Andreas Gampe67f02822016-06-24 21:05:23 -0700518 odex_location.c_str(),
519 nullptr,
520 nullptr,
521 false,
522 /*low_4gb*/false,
523 dex_location.c_str(),
524 &error_msg));
525 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700526 EXPECT_GT(app_image_file.length(), 0u);
527 std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file.c_str()));
Andreas Gampe67f02822016-06-24 21:05:23 -0700528 if (expect_large) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700529 // Note: we cannot check the following
530 // EXPECT_FALSE(CompilerFilter::IsAotCompilationEnabled(odex_file->GetCompilerFilter()));
Andreas Gampe67f02822016-06-24 21:05:23 -0700531 // The reason is that the filter override currently happens when the dex files are
532 // loaded in dex2oat, which is after the oat file has been started. Thus, the header
533 // store cannot be changed, and the original filter is set in stone.
534
535 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
536 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
537 ASSERT_TRUE(dex_file != nullptr);
538 uint32_t class_def_count = dex_file->NumClassDefs();
539 ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
540 for (uint16_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
541 OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
542 EXPECT_EQ(oat_class.GetType(), OatClassType::kOatClassNoneCompiled);
543 }
544 }
545
546 // If the input filter was "below," it should have been used.
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100547 if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kExtract, filter)) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700548 EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
549 }
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700550
551 // If expect large, make sure the app image isn't generated or is empty.
552 if (file != nullptr) {
553 EXPECT_EQ(file->GetLength(), 0u);
554 }
Andreas Gampe67f02822016-06-24 21:05:23 -0700555 } else {
556 EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700557 ASSERT_TRUE(file != nullptr) << app_image_file;
558 EXPECT_GT(file->GetLength(), 0u);
Andreas Gampe67f02822016-06-24 21:05:23 -0700559 }
560
561 // Host/target dependent checks.
562 if (kIsTargetBuild) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700563 CheckTargetResult(expect_downgrade);
Andreas Gampe67f02822016-06-24 21:05:23 -0700564 } else {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700565 CheckHostResult(expect_downgrade);
Andreas Gampe67f02822016-06-24 21:05:23 -0700566 }
567 }
568
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700569 void CheckTargetResult(bool expect_downgrade ATTRIBUTE_UNUSED) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700570 // TODO: Ignore for now. May do something for fd things.
571 }
572
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700573 void CheckHostResult(bool expect_downgrade) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700574 if (!kIsTargetBuild) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700575 if (expect_downgrade) {
576 EXPECT_NE(output_.find("Very large app, downgrading to"), std::string::npos) << output_;
Andreas Gampe67f02822016-06-24 21:05:23 -0700577 } else {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700578 EXPECT_EQ(output_.find("Very large app, downgrading to"), std::string::npos) << output_;
Andreas Gampe67f02822016-06-24 21:05:23 -0700579 }
580 }
581 }
582
583 // Check whether the dex2oat run was really successful.
584 void CheckValidity() {
585 if (kIsTargetBuild) {
586 CheckTargetValidity();
587 } else {
588 CheckHostValidity();
589 }
590 }
591
592 void CheckTargetValidity() {
593 // TODO: Ignore for now.
594 }
595
596 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
597 void CheckHostValidity() {
598 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
599 }
600};
601
602TEST_F(Dex2oatVeryLargeTest, DontUseVeryLarge) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700603 RunTest(CompilerFilter::kAssumeVerified, false, false);
604 RunTest(CompilerFilter::kExtract, false, false);
605 RunTest(CompilerFilter::kQuicken, false, false);
606 RunTest(CompilerFilter::kSpeed, false, false);
Andreas Gampe67f02822016-06-24 21:05:23 -0700607
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700608 RunTest(CompilerFilter::kAssumeVerified, false, false, { "--very-large-app-threshold=10000000" });
609 RunTest(CompilerFilter::kExtract, false, false, { "--very-large-app-threshold=10000000" });
610 RunTest(CompilerFilter::kQuicken, false, false, { "--very-large-app-threshold=10000000" });
611 RunTest(CompilerFilter::kSpeed, false, false, { "--very-large-app-threshold=10000000" });
Andreas Gampe67f02822016-06-24 21:05:23 -0700612}
613
614TEST_F(Dex2oatVeryLargeTest, UseVeryLarge) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700615 RunTest(CompilerFilter::kAssumeVerified, true, false, { "--very-large-app-threshold=100" });
616 RunTest(CompilerFilter::kExtract, true, false, { "--very-large-app-threshold=100" });
617 RunTest(CompilerFilter::kQuicken, true, true, { "--very-large-app-threshold=100" });
618 RunTest(CompilerFilter::kSpeed, true, true, { "--very-large-app-threshold=100" });
Andreas Gampe67f02822016-06-24 21:05:23 -0700619}
620
Mathieu Chartier97ab5e32017-02-22 13:35:44 -0800621// Regressin test for b/35665292.
622TEST_F(Dex2oatVeryLargeTest, SpeedProfileNoProfile) {
623 // Test that dex2oat doesn't crash with speed-profile but no input profile.
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700624 RunTest(CompilerFilter::kSpeedProfile, false, false);
Mathieu Chartier97ab5e32017-02-22 13:35:44 -0800625}
626
Jeff Hao608f2ce2016-10-19 11:17:11 -0700627class Dex2oatLayoutTest : public Dex2oatTest {
628 protected:
629 void CheckFilter(CompilerFilter::Filter input ATTRIBUTE_UNUSED,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100630 CompilerFilter::Filter result ATTRIBUTE_UNUSED) override {
Jeff Hao608f2ce2016-10-19 11:17:11 -0700631 // Ignore, we'll do our own checks.
632 }
633
Jeff Hao41fba6a2016-11-28 11:53:33 -0800634 // Emits a profile with a single dex file with the given location and a single class index of 1.
635 void GenerateProfile(const std::string& test_profile,
636 const std::string& dex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800637 size_t num_classes,
Jeff Hao41fba6a2016-11-28 11:53:33 -0800638 uint32_t checksum) {
639 int profile_test_fd = open(test_profile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
640 CHECK_GE(profile_test_fd, 0);
641
642 ProfileCompilationInfo info;
643 std::string profile_key = ProfileCompilationInfo::GetProfileDexFileKey(dex_location);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800644 for (size_t i = 0; i < num_classes; ++i) {
Mathieu Chartierea650f32017-05-24 12:04:13 -0700645 info.AddClassIndex(profile_key, checksum, dex::TypeIndex(1 + i), kMaxMethodIds);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800646 }
Jeff Hao41fba6a2016-11-28 11:53:33 -0800647 bool result = info.Save(profile_test_fd);
648 close(profile_test_fd);
649 ASSERT_TRUE(result);
650 }
651
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800652 void CompileProfileOdex(const std::string& dex_location,
653 const std::string& odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800654 const std::string& app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800655 bool use_fd,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800656 size_t num_profile_classes,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000657 const std::vector<std::string>& extra_args = {},
658 bool expect_success = true) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800659 const std::string profile_location = GetScratchDir() + "/primary.prof";
Jeff Hao41fba6a2016-11-28 11:53:33 -0800660 const char* location = dex_location.c_str();
661 std::string error_msg;
662 std::vector<std::unique_ptr<const DexFile>> dex_files;
David Sehr013fd802018-01-11 22:55:24 -0800663 const ArtDexFileLoader dex_file_loader;
664 ASSERT_TRUE(dex_file_loader.Open(
Nicolas Geoffray095c6c92017-10-19 13:59:55 +0100665 location, location, /* verify */ true, /* verify_checksum */ true, &error_msg, &dex_files));
Jeff Hao41fba6a2016-11-28 11:53:33 -0800666 EXPECT_EQ(dex_files.size(), 1U);
667 std::unique_ptr<const DexFile>& dex_file = dex_files[0];
Mathieu Chartier046854b2017-03-01 17:16:22 -0800668 GenerateProfile(profile_location,
669 dex_location,
670 num_profile_classes,
671 dex_file->GetLocationChecksum());
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800672 std::vector<std::string> copy(extra_args);
673 copy.push_back("--profile-file=" + profile_location);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800674 std::unique_ptr<File> app_image_file;
675 if (!app_image_file_name.empty()) {
676 if (use_fd) {
677 app_image_file.reset(OS::CreateEmptyFile(app_image_file_name.c_str()));
678 copy.push_back("--app-image-fd=" + std::to_string(app_image_file->Fd()));
679 } else {
680 copy.push_back("--app-image-file=" + app_image_file_name);
681 }
682 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800683 GenerateOdexForTest(dex_location,
684 odex_location,
685 CompilerFilter::kSpeedProfile,
686 copy,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000687 expect_success,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800688 use_fd);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800689 if (app_image_file != nullptr) {
690 ASSERT_EQ(app_image_file->FlushCloseOrErase(), 0) << "Could not flush and close art file";
691 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800692 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700693
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100694 uint64_t GetImageObjectSectionSize(const std::string& image_file_name) {
Mathieu Chartier046854b2017-03-01 17:16:22 -0800695 EXPECT_FALSE(image_file_name.empty());
696 std::unique_ptr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
697 CHECK(file != nullptr);
698 ImageHeader image_header;
699 const bool success = file->ReadFully(&image_header, sizeof(image_header));
700 CHECK(success);
701 CHECK(image_header.IsValid());
702 ReaderMutexLock mu(Thread::Current(), *Locks::mutator_lock_);
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100703 return image_header.GetObjectsSection().Size();
Mathieu Chartier046854b2017-03-01 17:16:22 -0800704 }
705
706 void RunTest(bool app_image) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800707 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
708 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Mathieu Chartier046854b2017-03-01 17:16:22 -0800709 std::string app_image_file = app_image ? (GetOdexDir() + "/DexOdexNoOat.art"): "";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800710 Copy(GetDexSrc2(), dex_location);
711
Mathieu Chartier046854b2017-03-01 17:16:22 -0800712 uint64_t image_file_empty_profile = 0;
713 if (app_image) {
714 CompileProfileOdex(dex_location,
715 odex_location,
716 app_image_file,
717 /* use_fd */ false,
718 /* num_profile_classes */ 0);
719 CheckValidity();
720 ASSERT_TRUE(success_);
721 // Don't check the result since CheckResult relies on the class being in the profile.
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100722 image_file_empty_profile = GetImageObjectSectionSize(app_image_file);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800723 EXPECT_GT(image_file_empty_profile, 0u);
724 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700725
Mathieu Chartier046854b2017-03-01 17:16:22 -0800726 // Small profile.
727 CompileProfileOdex(dex_location,
728 odex_location,
729 app_image_file,
730 /* use_fd */ false,
731 /* num_profile_classes */ 1);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700732 CheckValidity();
733 ASSERT_TRUE(success_);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800734 CheckResult(dex_location, odex_location, app_image_file);
735
736 if (app_image) {
737 // Test that the profile made a difference by adding more classes.
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100738 const uint64_t image_file_small_profile = GetImageObjectSectionSize(app_image_file);
739 ASSERT_LT(image_file_empty_profile, image_file_small_profile);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800740 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700741 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800742
743 void RunTestVDex() {
744 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
745 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
746 std::string vdex_location = GetOdexDir() + "/DexOdexNoOat.vdex";
Mathieu Chartier046854b2017-03-01 17:16:22 -0800747 std::string app_image_file_name = GetOdexDir() + "/DexOdexNoOat.art";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800748 Copy(GetDexSrc2(), dex_location);
749
750 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
751 CHECK(vdex_file1 != nullptr) << vdex_location;
752 ScratchFile vdex_file2;
753 {
754 std::string input_vdex = "--input-vdex-fd=-1";
755 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
756 CompileProfileOdex(dex_location,
757 odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800758 app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800759 /* use_fd */ true,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800760 /* num_profile_classes */ 1,
Mathieu Chartierf1609832018-01-31 03:09:56 -0800761 { input_vdex, output_vdex });
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800762 EXPECT_GT(vdex_file1->GetLength(), 0u);
763 }
764 {
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000765 // Test that vdex and dexlayout fail gracefully.
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800766 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
767 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2.GetFd());
768 CompileProfileOdex(dex_location,
769 odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800770 app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800771 /* use_fd */ true,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800772 /* num_profile_classes */ 1,
Mathieu Chartierd27923c2018-02-08 21:00:03 -0800773 { input_vdex, output_vdex },
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100774 /* expect_success */ true);
775 EXPECT_GT(vdex_file2.GetFile()->GetLength(), 0u);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800776 }
777 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
778 CheckValidity();
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100779 ASSERT_TRUE(success_);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800780 }
781
Mathieu Chartier046854b2017-03-01 17:16:22 -0800782 void CheckResult(const std::string& dex_location,
783 const std::string& odex_location,
784 const std::string& app_image_file_name) {
Jeff Hao608f2ce2016-10-19 11:17:11 -0700785 // Host/target independent checks.
786 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +0100787 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
788 odex_location.c_str(),
Jeff Hao608f2ce2016-10-19 11:17:11 -0700789 odex_location.c_str(),
790 nullptr,
791 nullptr,
792 false,
793 /*low_4gb*/false,
794 dex_location.c_str(),
795 &error_msg));
796 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
797
Jeff Hao042e8982016-10-19 11:17:11 -0700798 const char* location = dex_location.c_str();
799 std::vector<std::unique_ptr<const DexFile>> dex_files;
David Sehr013fd802018-01-11 22:55:24 -0800800 const ArtDexFileLoader dex_file_loader;
801 ASSERT_TRUE(dex_file_loader.Open(
Nicolas Geoffray095c6c92017-10-19 13:59:55 +0100802 location, location, /* verify */ true, /* verify_checksum */ true, &error_msg, &dex_files));
Jeff Hao042e8982016-10-19 11:17:11 -0700803 EXPECT_EQ(dex_files.size(), 1U);
804 std::unique_ptr<const DexFile>& old_dex_file = dex_files[0];
805
Jeff Hao608f2ce2016-10-19 11:17:11 -0700806 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
Jeff Hao042e8982016-10-19 11:17:11 -0700807 std::unique_ptr<const DexFile> new_dex_file = oat_dex_file->OpenDexFile(&error_msg);
808 ASSERT_TRUE(new_dex_file != nullptr);
809 uint32_t class_def_count = new_dex_file->NumClassDefs();
Jeff Hao608f2ce2016-10-19 11:17:11 -0700810 ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
Jeff Hao042e8982016-10-19 11:17:11 -0700811 ASSERT_GE(class_def_count, 2U);
812
Mathieu Chartier24066ec2017-10-21 16:01:08 -0700813 // Make sure the indexes stay the same.
Jeff Hao042e8982016-10-19 11:17:11 -0700814 std::string old_class0 = old_dex_file->PrettyType(old_dex_file->GetClassDef(0).class_idx_);
815 std::string old_class1 = old_dex_file->PrettyType(old_dex_file->GetClassDef(1).class_idx_);
816 std::string new_class0 = new_dex_file->PrettyType(new_dex_file->GetClassDef(0).class_idx_);
817 std::string new_class1 = new_dex_file->PrettyType(new_dex_file->GetClassDef(1).class_idx_);
Mathieu Chartier24066ec2017-10-21 16:01:08 -0700818 EXPECT_EQ(old_class0, new_class0);
819 EXPECT_EQ(old_class1, new_class1);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700820 }
821
Jeff Haoc155b052017-01-17 17:43:29 -0800822 EXPECT_EQ(odex_file->GetCompilerFilter(), CompilerFilter::kSpeedProfile);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800823
824 if (!app_image_file_name.empty()) {
825 // Go peek at the image header to make sure it was large enough to contain the class.
826 std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file_name.c_str()));
827 ImageHeader image_header;
828 bool success = file->ReadFully(&image_header, sizeof(image_header));
829 ASSERT_TRUE(success);
830 ASSERT_TRUE(image_header.IsValid());
Vladimir Markocd87c3e2017-09-05 13:11:57 +0100831 EXPECT_GT(image_header.GetObjectsSection().Size(), 0u);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800832 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700833 }
834
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800835 // Check whether the dex2oat run was really successful.
836 void CheckValidity() {
837 if (kIsTargetBuild) {
838 CheckTargetValidity();
839 } else {
840 CheckHostValidity();
Jeff Hao608f2ce2016-10-19 11:17:11 -0700841 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800842 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700843
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800844 void CheckTargetValidity() {
845 // TODO: Ignore for now.
846 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700847
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800848 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
849 void CheckHostValidity() {
850 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
851 }
852};
Jeff Hao608f2ce2016-10-19 11:17:11 -0700853
854TEST_F(Dex2oatLayoutTest, TestLayout) {
Mathieu Chartier046854b2017-03-01 17:16:22 -0800855 RunTest(/* app-image */ false);
856}
857
858TEST_F(Dex2oatLayoutTest, TestLayoutAppImage) {
859 RunTest(/* app-image */ true);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700860}
861
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800862TEST_F(Dex2oatLayoutTest, TestVdexLayout) {
863 RunTestVDex();
864}
865
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100866class Dex2oatUnquickenTest : public Dex2oatTest {
867 protected:
868 void RunUnquickenMultiDex() {
869 std::string dex_location = GetScratchDir() + "/UnquickenMultiDex.jar";
870 std::string odex_location = GetOdexDir() + "/UnquickenMultiDex.odex";
871 std::string vdex_location = GetOdexDir() + "/UnquickenMultiDex.vdex";
872 Copy(GetTestDexFileName("MultiDex"), dex_location);
873
874 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
875 CHECK(vdex_file1 != nullptr) << vdex_location;
876 // Quicken the dex file into a vdex file.
877 {
878 std::string input_vdex = "--input-vdex-fd=-1";
879 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
880 GenerateOdexForTest(dex_location,
881 odex_location,
882 CompilerFilter::kQuicken,
Mathieu Chartierf1609832018-01-31 03:09:56 -0800883 { input_vdex, output_vdex },
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100884 /* expect_success */ true,
885 /* use_fd */ true);
886 EXPECT_GT(vdex_file1->GetLength(), 0u);
887 }
888 // Unquicken by running the verify compiler filter on the vdex file.
889 {
890 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
891 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
892 GenerateOdexForTest(dex_location,
893 odex_location,
894 CompilerFilter::kVerify,
Mathieu Chartier02129102017-12-22 11:04:01 -0800895 { input_vdex, output_vdex, kDisableCompactDex },
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100896 /* expect_success */ true,
897 /* use_fd */ true);
898 }
899 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
900 CheckResult(dex_location, odex_location);
901 ASSERT_TRUE(success_);
902 }
903
Mathieu Chartierd27923c2018-02-08 21:00:03 -0800904 void RunUnquickenMultiDexCDex() {
905 std::string dex_location = GetScratchDir() + "/UnquickenMultiDex.jar";
906 std::string odex_location = GetOdexDir() + "/UnquickenMultiDex.odex";
907 std::string odex_location2 = GetOdexDir() + "/UnquickenMultiDex2.odex";
908 std::string vdex_location = GetOdexDir() + "/UnquickenMultiDex.vdex";
909 std::string vdex_location2 = GetOdexDir() + "/UnquickenMultiDex2.vdex";
910 Copy(GetTestDexFileName("MultiDex"), dex_location);
911
912 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
913 std::unique_ptr<File> vdex_file2(OS::CreateEmptyFile(vdex_location2.c_str()));
914 CHECK(vdex_file1 != nullptr) << vdex_location;
915 CHECK(vdex_file2 != nullptr) << vdex_location2;
916
917 // Quicken the dex file into a vdex file.
918 {
919 std::string input_vdex = "--input-vdex-fd=-1";
920 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
921 GenerateOdexForTest(dex_location,
922 odex_location,
923 CompilerFilter::kQuicken,
924 { input_vdex, output_vdex, "--compact-dex-level=fast"},
925 /* expect_success */ true,
926 /* use_fd */ true);
927 EXPECT_GT(vdex_file1->GetLength(), 0u);
928 }
929
930 // Unquicken by running the verify compiler filter on the vdex file.
931 {
932 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
933 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2->Fd());
934 GenerateOdexForTest(dex_location,
935 odex_location2,
936 CompilerFilter::kVerify,
937 { input_vdex, output_vdex, "--compact-dex-level=none"},
938 /* expect_success */ true,
939 /* use_fd */ true);
940 }
941 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
942 ASSERT_EQ(vdex_file2->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
943 CheckResult(dex_location, odex_location2);
944 ASSERT_TRUE(success_);
945 }
946
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100947 void CheckResult(const std::string& dex_location, const std::string& odex_location) {
948 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +0100949 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
950 odex_location.c_str(),
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100951 odex_location.c_str(),
952 nullptr,
953 nullptr,
954 false,
955 /*low_4gb*/false,
956 dex_location.c_str(),
957 &error_msg));
958 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
959 ASSERT_GE(odex_file->GetOatDexFiles().size(), 1u);
960
961 // Iterate over the dex files and ensure there is no quickened instruction.
962 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
963 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
Mathieu Chartier2242ef12018-07-23 18:14:13 -0700964 for (ClassAccessor accessor : dex_file->GetClasses()) {
965 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
966 for (const DexInstructionPcPair& inst : method.GetInstructions()) {
967 ASSERT_FALSE(inst->IsQuickened()) << inst->Opcode() << " " << output_;
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100968 }
969 }
970 }
971 }
972 }
973};
974
975TEST_F(Dex2oatUnquickenTest, UnquickenMultiDex) {
976 RunUnquickenMultiDex();
977}
978
Mathieu Chartierd27923c2018-02-08 21:00:03 -0800979TEST_F(Dex2oatUnquickenTest, UnquickenMultiDexCDex) {
980 RunUnquickenMultiDexCDex();
981}
982
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800983class Dex2oatWatchdogTest : public Dex2oatTest {
984 protected:
985 void RunTest(bool expect_success, const std::vector<std::string>& extra_args = {}) {
986 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
987 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
988
989 Copy(GetTestDexFileName(), dex_location);
990
991 std::vector<std::string> copy(extra_args);
992
993 std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
994 copy.push_back("--swap-file=" + swap_location);
Andreas Gampe22fa3762017-10-23 20:58:12 -0700995 copy.push_back("-j512"); // Excessive idle threads just slow down dex2oat.
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800996 GenerateOdexForTest(dex_location,
997 odex_location,
998 CompilerFilter::kSpeed,
999 copy,
1000 expect_success);
1001 }
1002
1003 std::string GetTestDexFileName() {
1004 return GetDexSrc1();
1005 }
1006};
1007
1008TEST_F(Dex2oatWatchdogTest, TestWatchdogOK) {
1009 // Check with default.
1010 RunTest(true);
1011
1012 // Check with ten minutes.
1013 RunTest(true, { "--watchdog-timeout=600000" });
1014}
1015
1016TEST_F(Dex2oatWatchdogTest, TestWatchdogTrigger) {
Andreas Gampe80ddf272018-01-11 09:41:00 -08001017 // The watchdog is independent of dex2oat and will not delete intermediates. It is possible
1018 // that the compilation succeeds and the file is completely written by the time the watchdog
1019 // kills dex2oat (but the dex2oat threads must have been scheduled pretty badly).
1020 test_accepts_odex_file_on_failure = true;
1021
Andreas Gampe2e8a2562017-01-18 20:39:02 -08001022 // Check with ten milliseconds.
1023 RunTest(false, { "--watchdog-timeout=10" });
1024}
1025
Andreas Gampef7882972017-03-20 16:35:24 -07001026class Dex2oatReturnCodeTest : public Dex2oatTest {
1027 protected:
1028 int RunTest(const std::vector<std::string>& extra_args = {}) {
1029 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
1030 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
1031
1032 Copy(GetTestDexFileName(), dex_location);
1033
1034 std::string error_msg;
Mathieu Chartier9e050df2017-08-09 10:05:47 -07001035 return GenerateOdexForTestWithStatus({dex_location},
Andreas Gampef7882972017-03-20 16:35:24 -07001036 odex_location,
1037 CompilerFilter::kSpeed,
1038 &error_msg,
1039 extra_args);
1040 }
1041
1042 std::string GetTestDexFileName() {
1043 return GetDexSrc1();
1044 }
1045};
1046
1047TEST_F(Dex2oatReturnCodeTest, TestCreateRuntime) {
Andreas Gampefd80b172017-04-26 22:25:31 -07001048 TEST_DISABLED_FOR_MEMORY_TOOL(); // b/19100793
Andreas Gampef7882972017-03-20 16:35:24 -07001049 int status = RunTest({ "--boot-image=/this/does/not/exist/yolo.oat" });
1050 EXPECT_EQ(static_cast<int>(dex2oat::ReturnCode::kCreateRuntime), WEXITSTATUS(status)) << output_;
1051}
1052
Calin Juravle1ce70852017-06-28 10:59:03 -07001053class Dex2oatClassLoaderContextTest : public Dex2oatTest {
1054 protected:
1055 void RunTest(const char* class_loader_context,
1056 const char* expected_classpath_key,
1057 bool expected_success,
1058 bool use_second_source = false) {
1059 std::string dex_location = GetUsedDexLocation();
1060 std::string odex_location = GetUsedOatLocation();
1061
1062 Copy(use_second_source ? GetDexSrc2() : GetDexSrc1(), dex_location);
1063
1064 std::string error_msg;
1065 std::vector<std::string> extra_args;
1066 if (class_loader_context != nullptr) {
1067 extra_args.push_back(std::string("--class-loader-context=") + class_loader_context);
1068 }
1069 auto check_oat = [expected_classpath_key](const OatFile& oat_file) {
1070 ASSERT_TRUE(expected_classpath_key != nullptr);
1071 const char* classpath = oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
1072 ASSERT_TRUE(classpath != nullptr);
1073 ASSERT_STREQ(expected_classpath_key, classpath);
1074 };
1075
1076 GenerateOdexForTest(dex_location,
1077 odex_location,
1078 CompilerFilter::kQuicken,
1079 extra_args,
1080 expected_success,
1081 /*use_fd*/ false,
1082 check_oat);
1083 }
1084
1085 std::string GetUsedDexLocation() {
1086 return GetScratchDir() + "/Context.jar";
1087 }
1088
1089 std::string GetUsedOatLocation() {
1090 return GetOdexDir() + "/Context.odex";
1091 }
1092
Calin Juravle7b0648a2017-07-07 18:40:50 -07001093 const char* kEmptyClassPathKey = "PCL[]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001094};
1095
1096TEST_F(Dex2oatClassLoaderContextTest, InvalidContext) {
1097 RunTest("Invalid[]", /*expected_classpath_key*/ nullptr, /*expected_success*/ false);
1098}
1099
1100TEST_F(Dex2oatClassLoaderContextTest, EmptyContext) {
1101 RunTest("PCL[]", kEmptyClassPathKey, /*expected_success*/ true);
1102}
1103
1104TEST_F(Dex2oatClassLoaderContextTest, SpecialContext) {
1105 RunTest(OatFile::kSpecialSharedLibrary,
1106 OatFile::kSpecialSharedLibrary,
1107 /*expected_success*/ true);
1108}
1109
1110TEST_F(Dex2oatClassLoaderContextTest, ContextWithTheSourceDexFiles) {
1111 std::string context = "PCL[" + GetUsedDexLocation() + "]";
1112 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1113}
1114
1115TEST_F(Dex2oatClassLoaderContextTest, ContextWithOtherDexFiles) {
1116 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Nested");
Calin Juravle1ce70852017-06-28 10:59:03 -07001117
1118 std::string context = "PCL[" + dex_files[0]->GetLocation() + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -07001119 std::string expected_classpath_key = "PCL[" +
1120 dex_files[0]->GetLocation() + "*" + std::to_string(dex_files[0]->GetLocationChecksum()) + "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001121 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1122}
1123
1124TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFiles) {
1125 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
1126 Copy(GetStrippedDexSrc1(), stripped_classpath);
1127
1128 std::string context = "PCL[" + stripped_classpath + "]";
1129 // Expect an empty context because stripped dex files cannot be open.
Calin Juravle7b0648a2017-07-07 18:40:50 -07001130 RunTest(context.c_str(), kEmptyClassPathKey , /*expected_success*/ true);
Calin Juravle1ce70852017-06-28 10:59:03 -07001131}
1132
1133TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFilesBackedByOdex) {
1134 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
1135 std::string odex_for_classpath = GetOdexDir() + "/stripped_classpath.odex";
1136
1137 Copy(GetDexSrc1(), stripped_classpath);
1138
1139 GenerateOdexForTest(stripped_classpath,
1140 odex_for_classpath,
1141 CompilerFilter::kQuicken,
1142 {},
1143 true);
1144
1145 // Strip the dex file
1146 Copy(GetStrippedDexSrc1(), stripped_classpath);
1147
1148 std::string context = "PCL[" + stripped_classpath + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -07001149 std::string expected_classpath_key;
Calin Juravle1ce70852017-06-28 10:59:03 -07001150 {
1151 // Open the oat file to get the expected classpath.
Nicolas Geoffray29742602017-12-14 10:09:03 +00001152 OatFileAssistant oat_file_assistant(stripped_classpath.c_str(), kRuntimeISA, false, false);
Calin Juravle1ce70852017-06-28 10:59:03 -07001153 std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile());
1154 std::vector<std::unique_ptr<const DexFile>> oat_dex_files =
1155 OatFileAssistant::LoadDexFiles(*oat_file, stripped_classpath.c_str());
Calin Juravle7b0648a2017-07-07 18:40:50 -07001156 expected_classpath_key = "PCL[";
1157 for (size_t i = 0; i < oat_dex_files.size(); i++) {
1158 if (i > 0) {
1159 expected_classpath_key + ":";
1160 }
1161 expected_classpath_key += oat_dex_files[i]->GetLocation() + "*" +
1162 std::to_string(oat_dex_files[i]->GetLocationChecksum());
1163 }
1164 expected_classpath_key += "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001165 }
1166
1167 RunTest(context.c_str(),
Calin Juravle7b0648a2017-07-07 18:40:50 -07001168 expected_classpath_key.c_str(),
Calin Juravle1ce70852017-06-28 10:59:03 -07001169 /*expected_success*/ true,
1170 /*use_second_source*/ true);
1171}
1172
1173TEST_F(Dex2oatClassLoaderContextTest, ContextWithNotExistentDexFiles) {
1174 std::string context = "PCL[does_not_exists.dex]";
1175 // Expect an empty context because stripped dex files cannot be open.
1176 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1177}
1178
Calin Juravlec79470d2017-07-12 17:37:42 -07001179TEST_F(Dex2oatClassLoaderContextTest, ChainContext) {
1180 std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1181 std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1182
1183 std::string context = "PCL[" + GetTestDexFileName("Nested") + "];" +
1184 "DLC[" + GetTestDexFileName("MultiDex") + "]";
1185 std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "];" +
1186 "DLC[" + CreateClassPathWithChecksums(dex_files2) + "]";
1187
1188 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1189}
1190
Mathieu Chartier9e050df2017-08-09 10:05:47 -07001191class Dex2oatDeterminism : public Dex2oatTest {};
1192
1193TEST_F(Dex2oatDeterminism, UnloadCompile) {
1194 if (!kUseReadBarrier &&
1195 gc::kCollectorTypeDefault != gc::kCollectorTypeCMS &&
1196 gc::kCollectorTypeDefault != gc::kCollectorTypeMS) {
1197 LOG(INFO) << "Test requires determinism support.";
1198 return;
1199 }
1200 Runtime* const runtime = Runtime::Current();
1201 std::string out_dir = GetScratchDir();
1202 const std::string base_oat_name = out_dir + "/base.oat";
1203 const std::string base_vdex_name = out_dir + "/base.vdex";
1204 const std::string unload_oat_name = out_dir + "/unload.oat";
1205 const std::string unload_vdex_name = out_dir + "/unload.vdex";
1206 const std::string no_unload_oat_name = out_dir + "/nounload.oat";
1207 const std::string no_unload_vdex_name = out_dir + "/nounload.vdex";
1208 const std::string app_image_name = out_dir + "/unload.art";
1209 std::string error_msg;
1210 const std::vector<gc::space::ImageSpace*>& spaces = runtime->GetHeap()->GetBootImageSpaces();
1211 ASSERT_GT(spaces.size(), 0u);
1212 const std::string image_location = spaces[0]->GetImageLocation();
1213 // Without passing in an app image, it will unload in between compilations.
1214 const int res = GenerateOdexForTestWithStatus(
1215 GetLibCoreDexFileNames(),
1216 base_oat_name,
1217 CompilerFilter::Filter::kQuicken,
1218 &error_msg,
1219 {"--force-determinism", "--avoid-storing-invocation"});
1220 EXPECT_EQ(res, 0);
1221 Copy(base_oat_name, unload_oat_name);
1222 Copy(base_vdex_name, unload_vdex_name);
1223 std::unique_ptr<File> unload_oat(OS::OpenFileForReading(unload_oat_name.c_str()));
1224 std::unique_ptr<File> unload_vdex(OS::OpenFileForReading(unload_vdex_name.c_str()));
1225 ASSERT_TRUE(unload_oat != nullptr);
1226 ASSERT_TRUE(unload_vdex != nullptr);
1227 EXPECT_GT(unload_oat->GetLength(), 0u);
1228 EXPECT_GT(unload_vdex->GetLength(), 0u);
1229 // Regenerate with an app image to disable the dex2oat unloading and verify that the output is
1230 // the same.
1231 const int res2 = GenerateOdexForTestWithStatus(
1232 GetLibCoreDexFileNames(),
1233 base_oat_name,
1234 CompilerFilter::Filter::kQuicken,
1235 &error_msg,
1236 {"--force-determinism", "--avoid-storing-invocation", "--app-image-file=" + app_image_name});
1237 EXPECT_EQ(res2, 0);
1238 Copy(base_oat_name, no_unload_oat_name);
1239 Copy(base_vdex_name, no_unload_vdex_name);
1240 std::unique_ptr<File> no_unload_oat(OS::OpenFileForReading(no_unload_oat_name.c_str()));
1241 std::unique_ptr<File> no_unload_vdex(OS::OpenFileForReading(no_unload_vdex_name.c_str()));
1242 ASSERT_TRUE(no_unload_oat != nullptr);
1243 ASSERT_TRUE(no_unload_vdex != nullptr);
1244 EXPECT_GT(no_unload_oat->GetLength(), 0u);
1245 EXPECT_GT(no_unload_vdex->GetLength(), 0u);
1246 // Verify that both of the files are the same (odex and vdex).
1247 EXPECT_EQ(unload_oat->GetLength(), no_unload_oat->GetLength());
1248 EXPECT_EQ(unload_vdex->GetLength(), no_unload_vdex->GetLength());
1249 EXPECT_EQ(unload_oat->Compare(no_unload_oat.get()), 0)
1250 << unload_oat_name << " " << no_unload_oat_name;
1251 EXPECT_EQ(unload_vdex->Compare(no_unload_vdex.get()), 0)
1252 << unload_vdex_name << " " << no_unload_vdex_name;
1253 // App image file.
1254 std::unique_ptr<File> app_image_file(OS::OpenFileForReading(app_image_name.c_str()));
1255 ASSERT_TRUE(app_image_file != nullptr);
1256 EXPECT_GT(app_image_file->GetLength(), 0u);
1257}
1258
Mathieu Chartier120aa282017-08-05 16:03:03 -07001259// Test that dexlayout section info is correctly written to the oat file for profile based
1260// compilation.
1261TEST_F(Dex2oatTest, LayoutSections) {
1262 using Hotness = ProfileCompilationInfo::MethodHotness;
1263 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1264 ScratchFile profile_file;
1265 // We can only layout method indices with code items, figure out which ones have this property
1266 // first.
1267 std::vector<uint16_t> methods;
1268 {
1269 const DexFile::TypeId* type_id = dex->FindTypeId("LManyMethods;");
1270 dex::TypeIndex type_idx = dex->GetIndexForTypeId(*type_id);
Mathieu Chartier2242ef12018-07-23 18:14:13 -07001271 ClassAccessor accessor(*dex, *dex->FindClassDef(type_idx));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001272 std::set<size_t> code_item_offsets;
Mathieu Chartier2242ef12018-07-23 18:14:13 -07001273 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
1274 const uint16_t method_idx = method.GetIndex();
1275 const size_t code_item_offset = method.GetCodeItemOffset();
Mathieu Chartier120aa282017-08-05 16:03:03 -07001276 if (code_item_offsets.insert(code_item_offset).second) {
1277 // Unique code item, add the method index.
1278 methods.push_back(method_idx);
1279 }
1280 }
Mathieu Chartier120aa282017-08-05 16:03:03 -07001281 }
1282 ASSERT_GE(methods.size(), 8u);
1283 std::vector<uint16_t> hot_methods = {methods[1], methods[3], methods[5]};
1284 std::vector<uint16_t> startup_methods = {methods[1], methods[2], methods[7]};
1285 std::vector<uint16_t> post_methods = {methods[0], methods[2], methods[6]};
1286 // Here, we build the profile from the method lists.
1287 ProfileCompilationInfo info;
1288 info.AddMethodsForDex(
1289 static_cast<Hotness::Flag>(Hotness::kFlagHot | Hotness::kFlagStartup),
1290 dex.get(),
1291 hot_methods.begin(),
1292 hot_methods.end());
1293 info.AddMethodsForDex(
1294 Hotness::kFlagStartup,
1295 dex.get(),
1296 startup_methods.begin(),
1297 startup_methods.end());
1298 info.AddMethodsForDex(
1299 Hotness::kFlagPostStartup,
1300 dex.get(),
1301 post_methods.begin(),
1302 post_methods.end());
1303 for (uint16_t id : hot_methods) {
1304 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsHot());
1305 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsStartup());
1306 }
1307 for (uint16_t id : startup_methods) {
1308 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsStartup());
1309 }
1310 for (uint16_t id : post_methods) {
1311 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsPostStartup());
1312 }
1313 // Save the profile since we want to use it with dex2oat to produce an oat file.
1314 ASSERT_TRUE(info.Save(profile_file.GetFd()));
1315 // Generate a profile based odex.
1316 const std::string dir = GetScratchDir();
1317 const std::string oat_filename = dir + "/base.oat";
1318 const std::string vdex_filename = dir + "/base.vdex";
1319 std::string error_msg;
1320 const int res = GenerateOdexForTestWithStatus(
1321 {dex->GetLocation()},
1322 oat_filename,
1323 CompilerFilter::Filter::kQuicken,
1324 &error_msg,
1325 {"--profile-file=" + profile_file.GetFilename()});
1326 EXPECT_EQ(res, 0);
1327
1328 // Open our generated oat file.
Nicolas Geoffray30025092018-04-19 14:43:29 +01001329 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1330 oat_filename.c_str(),
Mathieu Chartier120aa282017-08-05 16:03:03 -07001331 oat_filename.c_str(),
1332 nullptr,
1333 nullptr,
1334 false,
1335 /*low_4gb*/false,
1336 dex->GetLocation().c_str(),
1337 &error_msg));
1338 ASSERT_TRUE(odex_file != nullptr);
1339 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1340 ASSERT_EQ(oat_dex_files.size(), 1u);
1341 // Check that the code sections match what we expect.
1342 for (const OatDexFile* oat_dex : oat_dex_files) {
1343 const DexLayoutSections* const sections = oat_dex->GetDexLayoutSections();
1344 // Testing of logging the sections.
1345 ASSERT_TRUE(sections != nullptr);
1346 LOG(INFO) << *sections;
1347
1348 // Load the sections into temporary variables for convenience.
1349 const DexLayoutSection& code_section =
1350 sections->sections_[static_cast<size_t>(DexLayoutSections::SectionType::kSectionTypeCode)];
1351 const DexLayoutSection::Subsection& section_hot_code =
1352 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeHot)];
1353 const DexLayoutSection::Subsection& section_sometimes_used =
1354 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeSometimesUsed)];
1355 const DexLayoutSection::Subsection& section_startup_only =
1356 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeStartupOnly)];
1357 const DexLayoutSection::Subsection& section_unused =
1358 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeUnused)];
1359
1360 // All the sections should be non-empty.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001361 EXPECT_GT(section_hot_code.Size(), 0u);
1362 EXPECT_GT(section_sometimes_used.Size(), 0u);
1363 EXPECT_GT(section_startup_only.Size(), 0u);
1364 EXPECT_GT(section_unused.Size(), 0u);
Mathieu Chartier120aa282017-08-05 16:03:03 -07001365
1366 // Open the dex file since we need to peek at the code items to verify the layout matches what
1367 // we expect.
1368 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1369 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1370 const DexFile::TypeId* type_id = dex_file->FindTypeId("LManyMethods;");
1371 ASSERT_TRUE(type_id != nullptr);
1372 dex::TypeIndex type_idx = dex_file->GetIndexForTypeId(*type_id);
1373 const DexFile::ClassDef* class_def = dex_file->FindClassDef(type_idx);
1374 ASSERT_TRUE(class_def != nullptr);
1375
1376 // Count how many code items are for each category, there should be at least one per category.
1377 size_t hot_count = 0;
1378 size_t post_startup_count = 0;
1379 size_t startup_count = 0;
1380 size_t unused_count = 0;
1381 // Visit all of the methdos of the main class and cross reference the method indices to their
1382 // corresponding code item offsets to verify the layout.
Mathieu Chartier2242ef12018-07-23 18:14:13 -07001383 ClassAccessor accessor(*dex_file, *class_def);
1384 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
1385 const size_t method_idx = method.GetIndex();
1386 const size_t code_item_offset = method.GetCodeItemOffset();
Mathieu Chartier120aa282017-08-05 16:03:03 -07001387 const bool is_hot = ContainsElement(hot_methods, method_idx);
1388 const bool is_startup = ContainsElement(startup_methods, method_idx);
1389 const bool is_post_startup = ContainsElement(post_methods, method_idx);
1390 if (is_hot) {
1391 // Hot is highest precedence, check that the hot methods are in the hot section.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001392 EXPECT_TRUE(section_hot_code.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001393 ++hot_count;
1394 } else if (is_post_startup) {
1395 // Post startup is sometimes used section.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001396 EXPECT_TRUE(section_sometimes_used.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001397 ++post_startup_count;
1398 } else if (is_startup) {
1399 // Startup at this point means not hot or post startup, these must be startup only then.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001400 EXPECT_TRUE(section_startup_only.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001401 ++startup_count;
1402 } else {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001403 if (section_unused.Contains(code_item_offset)) {
Alan Leung9595fd32017-10-17 17:08:19 -07001404 // If no flags are set, the method should be unused ...
1405 ++unused_count;
1406 } else {
1407 // or this method is part of the last code item and the end is 4 byte aligned.
Mathieu Chartier2242ef12018-07-23 18:14:13 -07001408 for (const ClassAccessor::Method& method2 : accessor.GetMethods()) {
1409 EXPECT_LE(method2.GetCodeItemOffset(), code_item_offset);
Alan Leung9595fd32017-10-17 17:08:19 -07001410 }
1411 uint32_t code_item_size = dex_file->FindCodeItemOffset(*class_def, method_idx);
1412 EXPECT_EQ((code_item_offset + code_item_size) % 4, 0u);
1413 }
Mathieu Chartier120aa282017-08-05 16:03:03 -07001414 }
1415 }
Mathieu Chartier120aa282017-08-05 16:03:03 -07001416 EXPECT_GT(hot_count, 0u);
1417 EXPECT_GT(post_startup_count, 0u);
1418 EXPECT_GT(startup_count, 0u);
1419 EXPECT_GT(unused_count, 0u);
1420 }
1421}
1422
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001423// Test that generating compact dex works.
1424TEST_F(Dex2oatTest, GenerateCompactDex) {
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001425 // Generate a compact dex based odex.
1426 const std::string dir = GetScratchDir();
1427 const std::string oat_filename = dir + "/base.oat";
1428 const std::string vdex_filename = dir + "/base.vdex";
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001429 const std::string dex_location = GetTestDexFileName("MultiDex");
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001430 std::string error_msg;
1431 const int res = GenerateOdexForTestWithStatus(
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001432 { dex_location },
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001433 oat_filename,
1434 CompilerFilter::Filter::kQuicken,
1435 &error_msg,
1436 {"--compact-dex-level=fast"});
1437 EXPECT_EQ(res, 0);
1438 // Open our generated oat file.
Nicolas Geoffray30025092018-04-19 14:43:29 +01001439 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1440 oat_filename.c_str(),
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001441 oat_filename.c_str(),
1442 nullptr,
1443 nullptr,
1444 false,
1445 /*low_4gb*/false,
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001446 dex_location.c_str(),
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001447 &error_msg));
1448 ASSERT_TRUE(odex_file != nullptr);
1449 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001450 ASSERT_GT(oat_dex_files.size(), 1u);
1451 // Check that each dex is a compact dex file.
1452 std::vector<std::unique_ptr<const CompactDexFile>> compact_dex_files;
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001453 for (const OatDexFile* oat_dex : oat_dex_files) {
1454 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1455 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1456 ASSERT_TRUE(dex_file->IsCompactDexFile());
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001457 compact_dex_files.push_back(
1458 std::unique_ptr<const CompactDexFile>(dex_file.release()->AsCompactDexFile()));
1459 }
1460 for (const std::unique_ptr<const CompactDexFile>& dex_file : compact_dex_files) {
1461 // Test that every code item is in the owned section.
1462 const CompactDexFile::Header& header = dex_file->GetHeader();
1463 EXPECT_LE(header.OwnedDataBegin(), header.OwnedDataEnd());
1464 EXPECT_LE(header.OwnedDataBegin(), header.data_size_);
1465 EXPECT_LE(header.OwnedDataEnd(), header.data_size_);
Mathieu Chartier2242ef12018-07-23 18:14:13 -07001466 for (ClassAccessor accessor : dex_file->GetClasses()) {
1467 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
1468 if (method.GetCodeItemOffset() != 0u) {
1469 ASSERT_GE(method.GetCodeItemOffset(), header.OwnedDataBegin());
1470 ASSERT_LT(method.GetCodeItemOffset(), header.OwnedDataEnd());
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001471 }
Mathieu Chartier2242ef12018-07-23 18:14:13 -07001472 }
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001473 }
1474 // Test that the owned sections don't overlap.
1475 for (const std::unique_ptr<const CompactDexFile>& other_dex : compact_dex_files) {
1476 if (dex_file != other_dex) {
1477 ASSERT_TRUE(
1478 (dex_file->GetHeader().OwnedDataBegin() >= other_dex->GetHeader().OwnedDataEnd()) ||
1479 (dex_file->GetHeader().OwnedDataEnd() <= other_dex->GetHeader().OwnedDataBegin()));
1480 }
1481 }
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001482 }
1483}
1484
Andreas Gampef39208f2017-10-19 15:06:59 -07001485class Dex2oatVerifierAbort : public Dex2oatTest {};
1486
1487TEST_F(Dex2oatVerifierAbort, HardFail) {
1488 // Use VerifierDeps as it has hard-failing classes.
1489 std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDeps"));
1490 std::string out_dir = GetScratchDir();
1491 const std::string base_oat_name = out_dir + "/base.oat";
1492 std::string error_msg;
1493 const int res_fail = GenerateOdexForTestWithStatus(
1494 {dex->GetLocation()},
1495 base_oat_name,
1496 CompilerFilter::Filter::kQuicken,
1497 &error_msg,
1498 {"--abort-on-hard-verifier-error"});
1499 EXPECT_NE(0, res_fail);
1500
1501 const int res_no_fail = GenerateOdexForTestWithStatus(
1502 {dex->GetLocation()},
1503 base_oat_name,
1504 CompilerFilter::Filter::kQuicken,
1505 &error_msg,
1506 {"--no-abort-on-hard-verifier-error"});
1507 EXPECT_EQ(0, res_no_fail);
1508}
1509
1510TEST_F(Dex2oatVerifierAbort, SoftFail) {
1511 // Use VerifierDepsMulti as it has hard-failing classes.
1512 std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDepsMulti"));
1513 std::string out_dir = GetScratchDir();
1514 const std::string base_oat_name = out_dir + "/base.oat";
1515 std::string error_msg;
1516 const int res_fail = GenerateOdexForTestWithStatus(
1517 {dex->GetLocation()},
1518 base_oat_name,
1519 CompilerFilter::Filter::kQuicken,
1520 &error_msg,
1521 {"--abort-on-soft-verifier-error"});
1522 EXPECT_NE(0, res_fail);
1523
1524 const int res_no_fail = GenerateOdexForTestWithStatus(
1525 {dex->GetLocation()},
1526 base_oat_name,
1527 CompilerFilter::Filter::kQuicken,
1528 &error_msg,
1529 {"--no-abort-on-soft-verifier-error"});
1530 EXPECT_EQ(0, res_no_fail);
1531}
1532
Andreas Gampecac31ad2017-11-06 20:01:17 -08001533class Dex2oatDedupeCode : public Dex2oatTest {};
1534
1535TEST_F(Dex2oatDedupeCode, DedupeTest) {
1536 // Use MyClassNatives. It has lots of native methods that will produce deduplicate-able code.
1537 std::unique_ptr<const DexFile> dex(OpenTestDexFile("MyClassNatives"));
1538 std::string out_dir = GetScratchDir();
1539 const std::string base_oat_name = out_dir + "/base.oat";
1540 size_t no_dedupe_size = 0;
1541 GenerateOdexForTest(dex->GetLocation(),
1542 base_oat_name,
1543 CompilerFilter::Filter::kSpeed,
1544 { "--deduplicate-code=false" },
1545 true, // expect_success
1546 false, // use_fd
1547 [&no_dedupe_size](const OatFile& o) {
1548 no_dedupe_size = o.Size();
1549 });
1550
1551 size_t dedupe_size = 0;
1552 GenerateOdexForTest(dex->GetLocation(),
1553 base_oat_name,
1554 CompilerFilter::Filter::kSpeed,
1555 { "--deduplicate-code=true" },
1556 true, // expect_success
1557 false, // use_fd
1558 [&dedupe_size](const OatFile& o) {
1559 dedupe_size = o.Size();
1560 });
1561
1562 EXPECT_LT(dedupe_size, no_dedupe_size);
1563}
1564
Nicolas Geoffrayf3075272018-01-08 12:41:19 +00001565TEST_F(Dex2oatTest, UncompressedTest) {
1566 std::unique_ptr<const DexFile> dex(OpenTestDexFile("MainUncompressed"));
1567 std::string out_dir = GetScratchDir();
1568 const std::string base_oat_name = out_dir + "/base.oat";
1569 GenerateOdexForTest(dex->GetLocation(),
1570 base_oat_name,
1571 CompilerFilter::Filter::kQuicken,
1572 { },
1573 true, // expect_success
1574 false, // use_fd
1575 [](const OatFile& o) {
1576 CHECK(!o.ContainsDexCode());
1577 });
1578}
1579
Mathieu Chartier700a9852018-02-06 18:27:38 -08001580TEST_F(Dex2oatTest, EmptyUncompressedDexTest) {
1581 std::string out_dir = GetScratchDir();
1582 const std::string base_oat_name = out_dir + "/base.oat";
1583 std::string error_msg;
1584 int status = GenerateOdexForTestWithStatus(
1585 { GetTestDexFileName("MainEmptyUncompressed") },
1586 base_oat_name,
1587 CompilerFilter::Filter::kQuicken,
1588 &error_msg,
1589 { },
1590 /*use_fd*/ false);
1591 // Expect to fail with code 1 and not SIGSEGV or SIGABRT.
1592 ASSERT_TRUE(WIFEXITED(status));
1593 ASSERT_EQ(WEXITSTATUS(status), 1) << error_msg;
1594}
1595
Mathieu Chartier05f90d12018-02-07 13:47:17 -08001596// Dex file that has duplicate methods have different code items and debug info.
1597static const char kDuplicateMethodInputDex[] =
1598 "ZGV4CjAzOQDEy8VPdj4qHpgPYFWtLCtOykfFP4kB8tGYDAAAcAAAAHhWNBIAAAAAAAAAANALAABI"
1599 "AAAAcAAAAA4AAACQAQAABQAAAMgBAAANAAAABAIAABkAAABsAgAABAAAADQDAADgCAAAuAMAADgI"
1600 "AABCCAAASggAAE8IAABcCAAAaggAAHkIAACICAAAlggAAKQIAACyCAAAwAgAAM4IAADcCAAA6ggA"
1601 "APgIAAD7CAAA/wgAABcJAAAuCQAARQkAAFQJAAB4CQAAmAkAALsJAADSCQAA5gkAAPoJAAAVCgAA"
1602 "KQoAADsKAABCCgAASgoAAFIKAABbCgAAZAoAAGwKAAB0CgAAfAoAAIQKAACMCgAAlAoAAJwKAACk"
1603 "CgAArQoAALcKAADACgAAwwoAAMcKAADcCgAA6QoAAPEKAAD3CgAA/QoAAAMLAAAJCwAAEAsAABcL"
1604 "AAAdCwAAIwsAACkLAAAvCwAANQsAADsLAABBCwAARwsAAE0LAABSCwAAWwsAAF4LAABoCwAAbwsA"
1605 "ABEAAAASAAAAEwAAABQAAAAVAAAAFgAAABcAAAAYAAAAGQAAABoAAAAbAAAAHAAAAC4AAAAwAAAA"
1606 "DwAAAAkAAAAAAAAAEAAAAAoAAACoBwAALgAAAAwAAAAAAAAALwAAAAwAAACoBwAALwAAAAwAAACw"
1607 "BwAAAgAJADUAAAACAAkANgAAAAIACQA3AAAAAgAJADgAAAACAAkAOQAAAAIACQA6AAAAAgAJADsA"
1608 "AAACAAkAPAAAAAIACQA9AAAAAgAJAD4AAAACAAkAPwAAAAIACQBAAAAACwAHAEIAAAAAAAIAAQAA"
1609 "AAAAAwAeAAAAAQACAAEAAAABAAMAHgAAAAIAAgAAAAAAAgACAAEAAAADAAIAAQAAAAMAAgAfAAAA"
1610 "AwACACAAAAADAAIAIQAAAAMAAgAiAAAAAwACACMAAAADAAIAJAAAAAMAAgAlAAAAAwACACYAAAAD"
1611 "AAIAJwAAAAMAAgAoAAAAAwACACkAAAADAAIAKgAAAAMABAA0AAAABwADAEMAAAAIAAIAAQAAAAoA"
1612 "AgABAAAACgABADIAAAAKAAAARQAAAAAAAAAAAAAACAAAAAAAAAAdAAAAaAcAALYHAAAAAAAAAQAA"
1613 "AAAAAAAIAAAAAAAAAB0AAAB4BwAAxAcAAAAAAAACAAAAAAAAAAgAAAAAAAAAHQAAAIgHAADSBwAA"
1614 "AAAAAAMAAAAAAAAACAAAAAAAAAAdAAAAmAcAAPoHAAAAAAAAAAAAAAEAAAAAAAAArAYAADEAAAAa"
1615 "AAMAaQAAABoABABpAAEAGgAHAGkABAAaAAgAaQAFABoACQBpAAYAGgAKAGkABwAaAAsAaQAIABoA"
1616 "DABpAAkAGgANAGkACgAaAA4AaQALABoABQBpAAIAGgAGAGkAAwAOAAAAAQABAAEAAACSBgAABAAA"
1617 "AHAQFQAAAA4ABAABAAIAAACWBgAAFwAAAGIADAAiAQoAcBAWAAEAGgICAG4gFwAhAG4gFwAxAG4Q"
1618 "GAABAAwBbiAUABAADgAAAAEAAQABAAAAngYAAAQAAABwEBUAAAAOAAIAAQACAAAAogYAAAYAAABi"
1619 "AAwAbiAUABAADgABAAEAAQAAAKgGAAAEAAAAcBAVAAAADgABAAEAAQAAALsGAAAEAAAAcBAVAAAA"
1620 "DgABAAAAAQAAAL8GAAAGAAAAYgAAAHEQAwAAAA4AAQAAAAEAAADEBgAABgAAAGIAAQBxEAMAAAAO"
1621 "AAEAAAABAAAA8QYAAAYAAABiAAIAcRABAAAADgABAAAAAQAAAPYGAAAGAAAAYgADAHEQAwAAAA4A"
1622 "AQAAAAEAAADJBgAABgAAAGIABABxEAMAAAAOAAEAAAABAAAAzgYAAAYAAABiAAEAcRADAAAADgAB"
1623 "AAAAAQAAANMGAAAGAAAAYgAGAHEQAwAAAA4AAQAAAAEAAADYBgAABgAAAGIABwBxEAMAAAAOAAEA"
1624 "AAABAAAA3QYAAAYAAABiAAgAcRABAAAADgABAAAAAQAAAOIGAAAGAAAAYgAJAHEQAwAAAA4AAQAA"
1625 "AAEAAADnBgAABgAAAGIACgBxEAMAAAAOAAEAAAABAAAA7AYAAAYAAABiAAsAcRABAAAADgABAAEA"
1626 "AAAAAPsGAAAlAAAAcQAHAAAAcQAIAAAAcQALAAAAcQAMAAAAcQANAAAAcQAOAAAAcQAPAAAAcQAQ"
1627 "AAAAcQARAAAAcQASAAAAcQAJAAAAcQAKAAAADgAnAA4AKQFFDgEWDwAhAA4AIwFFDloAEgAOABMA"
1628 "DktLS0tLS0tLS0tLABEADgAuAA5aADIADloANgAOWgA6AA5aAD4ADloAQgAOWgBGAA5aAEoADloA"
1629 "TgAOWgBSAA5aAFYADloAWgAOWgBeATQOPDw8PDw8PDw8PDw8AAIEAUYYAwIFAjEECEEXLAIFAjEE"
1630 "CEEXKwIFAjEECEEXLQIGAUYcAxgAGAEYAgAAAAIAAAAMBwAAEgcAAAIAAAAMBwAAGwcAAAIAAAAM"
1631 "BwAAJAcAAAEAAAAtBwAAPAcAAAAAAAAAAAAAAAAAAEgHAAAAAAAAAAAAAAAAAABUBwAAAAAAAAAA"
1632 "AAAAAAAAYAcAAAAAAAAAAAAAAAAAAAEAAAAJAAAAAQAAAA0AAAACAACAgASsCAEIxAgAAAIAAoCA"
1633 "BIQJAQicCQwAAgAACQEJAQkBCQEJAQkBCQEJAQkBCQEJAQkEiIAEuAcBgIAEuAkAAA4ABoCABNAJ"
1634 "AQnoCQAJhAoACaAKAAm8CgAJ2AoACfQKAAmQCwAJrAsACcgLAAnkCwAJgAwACZwMAAm4DAg8Y2xp"
1635 "bml0PgAGPGluaXQ+AANBQUEAC0hlbGxvIFdvcmxkAAxIZWxsbyBXb3JsZDEADUhlbGxvIFdvcmxk"
1636 "MTAADUhlbGxvIFdvcmxkMTEADEhlbGxvIFdvcmxkMgAMSGVsbG8gV29ybGQzAAxIZWxsbyBXb3Js"
1637 "ZDQADEhlbGxvIFdvcmxkNQAMSGVsbG8gV29ybGQ2AAxIZWxsbyBXb3JsZDcADEhlbGxvIFdvcmxk"
1638 "OAAMSGVsbG8gV29ybGQ5AAFMAAJMTAAWTE1hbnlNZXRob2RzJFByaW50ZXIyOwAVTE1hbnlNZXRo"
1639 "b2RzJFByaW50ZXI7ABVMTWFueU1ldGhvZHMkU3RyaW5nczsADUxNYW55TWV0aG9kczsAIkxkYWx2"
1640 "aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNs"
1641 "YXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNzZXM7ABVMamF2YS9pby9QcmludFN0"
1642 "cmVhbTsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABlMamF2YS9sYW5n"
1643 "L1N0cmluZ0J1aWxkZXI7ABJMamF2YS9sYW5nL1N5c3RlbTsAEE1hbnlNZXRob2RzLmphdmEABVBy"
1644 "aW50AAZQcmludDAABlByaW50MQAHUHJpbnQxMAAHUHJpbnQxMQAGUHJpbnQyAAZQcmludDMABlBy"
1645 "aW50NAAGUHJpbnQ1AAZQcmludDYABlByaW50NwAGUHJpbnQ4AAZQcmludDkAB1ByaW50ZXIACFBy"
1646 "aW50ZXIyAAdTdHJpbmdzAAFWAAJWTAATW0xqYXZhL2xhbmcvU3RyaW5nOwALYWNjZXNzRmxhZ3MA"
1647 "BmFwcGVuZAAEYXJncwAEbWFpbgAEbXNnMAAEbXNnMQAFbXNnMTAABW1zZzExAARtc2cyAARtc2cz"
1648 "AARtc2c0AARtc2c1AARtc2c2AARtc2c3AARtc2c4AARtc2c5AARuYW1lAANvdXQAB3ByaW50bG4A"
1649 "AXMACHRvU3RyaW5nAAV2YWx1ZQBffn5EOHsibWluLWFwaSI6MTAwMDAsInNoYS0xIjoiZmViODZj"
1650 "MDA2ZWZhY2YxZDc5ODRiODVlMTc5MGZlZjdhNzY3YWViYyIsInZlcnNpb24iOiJ2MS4xLjUtZGV2"
1651 "In0AEAAAAAAAAAABAAAAAAAAAAEAAABIAAAAcAAAAAIAAAAOAAAAkAEAAAMAAAAFAAAAyAEAAAQA"
1652 "AAANAAAABAIAAAUAAAAZAAAAbAIAAAYAAAAEAAAANAMAAAEgAAAUAAAAuAMAAAMgAAAUAAAAkgYA"
1653 "AAQgAAAFAAAADAcAAAMQAAAEAAAAOQcAAAYgAAAEAAAAaAcAAAEQAAACAAAAqAcAAAAgAAAEAAAA"
1654 "tgcAAAIgAABIAAAAOAgAAAAQAAABAAAA0AsAAAAAAAA=";
1655
1656static void WriteBase64ToFile(const char* base64, File* file) {
1657 // Decode base64.
1658 CHECK(base64 != nullptr);
1659 size_t length;
1660 std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
1661 CHECK(bytes != nullptr);
1662 if (!file->WriteFully(bytes.get(), length)) {
1663 PLOG(FATAL) << "Failed to write base64 as file";
1664 }
1665}
1666
1667TEST_F(Dex2oatTest, CompactDexGenerationFailure) {
1668 ScratchFile temp_dex;
1669 WriteBase64ToFile(kDuplicateMethodInputDex, temp_dex.GetFile());
1670 std::string out_dir = GetScratchDir();
1671 const std::string oat_filename = out_dir + "/base.oat";
1672 // The dex won't pass the method verifier, only use the verify filter.
1673 GenerateOdexForTest(temp_dex.GetFilename(),
1674 oat_filename,
1675 CompilerFilter::Filter::kVerify,
1676 { },
1677 true, // expect_success
1678 false, // use_fd
1679 [](const OatFile& o) {
1680 CHECK(o.ContainsDexCode());
1681 });
1682 // Open our generated oat file.
1683 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01001684 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1685 oat_filename.c_str(),
Mathieu Chartier05f90d12018-02-07 13:47:17 -08001686 oat_filename.c_str(),
1687 nullptr,
1688 nullptr,
1689 false,
1690 /*low_4gb*/false,
1691 temp_dex.GetFilename().c_str(),
1692 &error_msg));
1693 ASSERT_TRUE(odex_file != nullptr);
1694 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1695 ASSERT_EQ(oat_dex_files.size(), 1u);
1696 // The dexes should have failed to convert to compact dex.
1697 for (const OatDexFile* oat_dex : oat_dex_files) {
1698 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1699 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1700 ASSERT_TRUE(!dex_file->IsCompactDexFile());
1701 }
1702}
1703
Mathieu Chartiercda83be2018-03-01 23:55:55 -08001704TEST_F(Dex2oatTest, CompactDexGenerationFailureMultiDex) {
1705 // Create a multidex file with only one dex that gets rejected for cdex conversion.
1706 ScratchFile apk_file;
1707 {
1708 FILE* file = fdopen(apk_file.GetFd(), "w+b");
1709 ZipWriter writer(file);
1710 // Add vdex to zip.
1711 writer.StartEntry("classes.dex", ZipWriter::kCompress);
1712 size_t length = 0u;
1713 std::unique_ptr<uint8_t[]> bytes(DecodeBase64(kDuplicateMethodInputDex, &length));
1714 ASSERT_GE(writer.WriteBytes(&bytes[0], length), 0);
1715 writer.FinishEntry();
1716 writer.StartEntry("classes2.dex", ZipWriter::kCompress);
1717 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1718 ASSERT_GE(writer.WriteBytes(dex->Begin(), dex->Size()), 0);
1719 writer.FinishEntry();
1720 writer.Finish();
1721 ASSERT_EQ(apk_file.GetFile()->Flush(), 0);
1722 }
Andreas Gampebc802de2018-06-20 17:24:11 -07001723 const std::string& dex_location = apk_file.GetFilename();
Mathieu Chartiercda83be2018-03-01 23:55:55 -08001724 const std::string odex_location = GetOdexDir() + "/output.odex";
1725 GenerateOdexForTest(dex_location,
1726 odex_location,
1727 CompilerFilter::kQuicken,
1728 { "--compact-dex-level=fast" },
1729 true);
1730}
1731
Andreas Gampe25419b52018-02-08 21:30:26 -08001732TEST_F(Dex2oatTest, StderrLoggerOutput) {
1733 std::string dex_location = GetScratchDir() + "/Dex2OatStderrLoggerTest.jar";
1734 std::string odex_location = GetOdexDir() + "/Dex2OatStderrLoggerTest.odex";
1735
1736 // Test file doesn't matter.
1737 Copy(GetDexSrc1(), dex_location);
1738
1739 GenerateOdexForTest(dex_location,
1740 odex_location,
1741 CompilerFilter::kQuicken,
1742 { "--runtime-arg", "-Xuse-stderr-logger" },
1743 true);
1744 // Look for some random part of dex2oat logging. With the stderr logger this should be captured,
1745 // even on device.
1746 EXPECT_NE(std::string::npos, output_.find("dex2oat took"));
1747}
1748
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001749TEST_F(Dex2oatTest, VerifyCompilationReason) {
1750 std::string dex_location = GetScratchDir() + "/Dex2OatCompilationReason.jar";
1751 std::string odex_location = GetOdexDir() + "/Dex2OatCompilationReason.odex";
1752
1753 // Test file doesn't matter.
1754 Copy(GetDexSrc1(), dex_location);
1755
1756 GenerateOdexForTest(dex_location,
1757 odex_location,
1758 CompilerFilter::kVerify,
1759 { "--compilation-reason=install" },
1760 true);
1761 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01001762 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1763 odex_location.c_str(),
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001764 odex_location.c_str(),
1765 nullptr,
1766 nullptr,
1767 false,
1768 /*low_4gb*/false,
1769 dex_location.c_str(),
1770 &error_msg));
1771 ASSERT_TRUE(odex_file != nullptr);
1772 ASSERT_STREQ("install", odex_file->GetCompilationReason());
1773}
1774
1775TEST_F(Dex2oatTest, VerifyNoCompilationReason) {
1776 std::string dex_location = GetScratchDir() + "/Dex2OatNoCompilationReason.jar";
1777 std::string odex_location = GetOdexDir() + "/Dex2OatNoCompilationReason.odex";
1778
1779 // Test file doesn't matter.
1780 Copy(GetDexSrc1(), dex_location);
1781
1782 GenerateOdexForTest(dex_location,
1783 odex_location,
1784 CompilerFilter::kVerify,
1785 {},
1786 true);
1787 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01001788 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1789 odex_location.c_str(),
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001790 odex_location.c_str(),
1791 nullptr,
1792 nullptr,
1793 false,
1794 /*low_4gb*/false,
1795 dex_location.c_str(),
1796 &error_msg));
1797 ASSERT_TRUE(odex_file != nullptr);
1798 ASSERT_EQ(nullptr, odex_file->GetCompilationReason());
1799}
1800
Mathieu Chartier792111c2018-02-15 13:02:15 -08001801TEST_F(Dex2oatTest, DontExtract) {
1802 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1803 std::string error_msg;
1804 const std::string out_dir = GetScratchDir();
1805 const std::string dex_location = dex->GetLocation();
1806 const std::string odex_location = out_dir + "/base.oat";
1807 const std::string vdex_location = out_dir + "/base.vdex";
1808 GenerateOdexForTest(dex_location,
1809 odex_location,
1810 CompilerFilter::Filter::kVerify,
1811 { "--copy-dex-files=false" },
1812 true, // expect_success
1813 false, // use_fd
1814 [](const OatFile&) {
1815 });
1816 {
1817 // Check the vdex doesn't have dex.
1818 std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location.c_str(),
1819 /*writable*/ false,
1820 /*low_4gb*/ false,
1821 /*unquicken*/ false,
1822 &error_msg));
1823 ASSERT_TRUE(vdex != nullptr);
Nicolas Geoffray3a293552018-03-02 10:52:16 +00001824 EXPECT_FALSE(vdex->HasDexSection()) << output_;
Mathieu Chartier792111c2018-02-15 13:02:15 -08001825 }
Nicolas Geoffray30025092018-04-19 14:43:29 +01001826 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1827 odex_location.c_str(),
Mathieu Chartier792111c2018-02-15 13:02:15 -08001828 odex_location.c_str(),
1829 nullptr,
1830 nullptr,
1831 false,
1832 /*low_4gb*/ false,
1833 dex_location.c_str(),
1834 &error_msg));
1835 ASSERT_TRUE(odex_file != nullptr) << dex_location;
1836 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1837 ASSERT_EQ(oat_dex_files.size(), 1u);
1838 // Verify that the oat file can still open the dex files.
1839 for (const OatDexFile* oat_dex : oat_dex_files) {
1840 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1841 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1842 }
1843 // Create a dm file and use it to verify.
1844 // Add produced artifacts to a zip file that doesn't contain the classes.dex.
1845 ScratchFile dm_file;
1846 {
1847 std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_location.c_str()));
1848 ASSERT_TRUE(vdex_file != nullptr);
1849 ASSERT_GT(vdex_file->GetLength(), 0u);
1850 FILE* file = fdopen(dm_file.GetFd(), "w+b");
1851 ZipWriter writer(file);
1852 auto write_all_bytes = [&](File* file) {
1853 std::unique_ptr<uint8_t[]> bytes(new uint8_t[file->GetLength()]);
1854 ASSERT_TRUE(file->ReadFully(&bytes[0], file->GetLength()));
1855 ASSERT_GE(writer.WriteBytes(&bytes[0], file->GetLength()), 0);
1856 };
1857 // Add vdex to zip.
1858 writer.StartEntry(VdexFile::kVdexNameInDmFile, ZipWriter::kCompress);
1859 write_all_bytes(vdex_file.get());
1860 writer.FinishEntry();
1861 writer.Finish();
1862 ASSERT_EQ(dm_file.GetFile()->Flush(), 0);
1863 }
1864
Mathieu Chartier2eabc612018-05-25 14:31:16 -07001865 auto generate_and_check = [&](CompilerFilter::Filter filter) {
1866 GenerateOdexForTest(dex_location,
1867 odex_location,
1868 filter,
1869 { "--dump-timings",
1870 "--dm-file=" + dm_file.GetFilename(),
1871 // Pass -Xuse-stderr-logger have dex2oat output in output_ on target.
1872 "--runtime-arg",
1873 "-Xuse-stderr-logger" },
1874 true, // expect_success
1875 false, // use_fd
1876 [](const OatFile& o) {
1877 CHECK(o.ContainsDexCode());
1878 });
1879 // Check the output for "Fast verify", this is printed from --dump-timings.
1880 std::istringstream iss(output_);
1881 std::string line;
1882 bool found_fast_verify = false;
1883 const std::string kFastVerifyString = "Fast Verify";
1884 while (std::getline(iss, line) && !found_fast_verify) {
1885 found_fast_verify = found_fast_verify || line.find(kFastVerifyString) != std::string::npos;
1886 }
1887 EXPECT_TRUE(found_fast_verify) << "Expected to find " << kFastVerifyString << "\n" << output_;
1888 };
1889
Mathieu Chartier792111c2018-02-15 13:02:15 -08001890 // Generate a quickened dex by using the input dm file to verify.
Mathieu Chartier2eabc612018-05-25 14:31:16 -07001891 generate_and_check(CompilerFilter::Filter::kQuicken);
1892 // Use verify compiler filter to sanity check that FastVerify works for that filter too.
1893 generate_and_check(CompilerFilter::Filter::kVerify);
Mathieu Chartier792111c2018-02-15 13:02:15 -08001894}
1895
Mathieu Chartier2daa1342018-02-20 16:19:28 -08001896// Test that dex files with quickened opcodes aren't dequickened.
1897TEST_F(Dex2oatTest, QuickenedInput) {
1898 std::string error_msg;
1899 ScratchFile temp_dex;
1900 MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [] (DexFile* dex) {
1901 bool mutated_successfully = false;
1902 // Change the dex instructions to make an opcode that spans past the end of the code item.
Mathieu Chartier2242ef12018-07-23 18:14:13 -07001903 for (ClassAccessor accessor : dex->GetClasses()) {
1904 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
1905 CodeItemInstructionAccessor instructions = method.GetInstructions();
1906 // Make a quickened instruction that doesn't run past the end of the code item.
1907 if (instructions.InsnsSizeInCodeUnits() > 2) {
1908 const_cast<Instruction&>(instructions.InstructionAt(0)).SetOpcode(
1909 Instruction::IGET_BYTE_QUICK);
1910 mutated_successfully = true;
Mathieu Chartier2daa1342018-02-20 16:19:28 -08001911 }
Mathieu Chartier2daa1342018-02-20 16:19:28 -08001912 }
1913 }
1914 CHECK(mutated_successfully)
1915 << "Failed to find candidate code item with only one code unit in last instruction.";
1916 });
1917
Andreas Gampebc802de2018-06-20 17:24:11 -07001918 const std::string& dex_location = temp_dex.GetFilename();
Mathieu Chartier2daa1342018-02-20 16:19:28 -08001919 std::string odex_location = GetOdexDir() + "/quickened.odex";
1920 std::string vdex_location = GetOdexDir() + "/quickened.vdex";
1921 std::unique_ptr<File> vdex_output(OS::CreateEmptyFile(vdex_location.c_str()));
1922 // Quicken the dex
1923 {
1924 std::string input_vdex = "--input-vdex-fd=-1";
1925 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_output->Fd());
1926 GenerateOdexForTest(dex_location,
1927 odex_location,
1928 CompilerFilter::kQuicken,
1929 // Disable cdex since we want to compare against the original dex file
1930 // after unquickening.
1931 { input_vdex, output_vdex, kDisableCompactDex },
1932 /* expect_success */ true,
1933 /* use_fd */ true);
1934 }
1935 // Unquicken by running the verify compiler filter on the vdex file and verify it matches.
1936 std::string odex_location2 = GetOdexDir() + "/unquickened.odex";
1937 std::string vdex_location2 = GetOdexDir() + "/unquickened.vdex";
1938 std::unique_ptr<File> vdex_unquickened(OS::CreateEmptyFile(vdex_location2.c_str()));
1939 {
1940 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_output->Fd());
1941 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_unquickened->Fd());
1942 GenerateOdexForTest(dex_location,
1943 odex_location2,
1944 CompilerFilter::kVerify,
1945 // Disable cdex to avoid needing to write out the shared section.
1946 { input_vdex, output_vdex, kDisableCompactDex },
1947 /* expect_success */ true,
1948 /* use_fd */ true);
1949 }
1950 ASSERT_EQ(vdex_unquickened->Flush(), 0) << "Could not flush and close vdex file";
1951 ASSERT_TRUE(success_);
1952 {
1953 // Check that hte vdex has one dex and compare it to the original one.
1954 std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location2.c_str(),
1955 /*writable*/ false,
1956 /*low_4gb*/ false,
1957 /*unquicken*/ false,
1958 &error_msg));
1959 std::vector<std::unique_ptr<const DexFile>> dex_files;
1960 bool result = vdex->OpenAllDexFiles(&dex_files, &error_msg);
1961 ASSERT_TRUE(result) << error_msg;
1962 ASSERT_EQ(dex_files.size(), 1u) << error_msg;
1963 ScratchFile temp;
1964 ASSERT_TRUE(temp.GetFile()->WriteFully(dex_files[0]->Begin(), dex_files[0]->Size()));
1965 ASSERT_EQ(temp.GetFile()->Flush(), 0) << "Could not flush extracted dex";
1966 EXPECT_EQ(temp.GetFile()->Compare(temp_dex.GetFile()), 0);
1967 }
1968 ASSERT_EQ(vdex_output->FlushCloseOrErase(), 0) << "Could not flush and close";
1969 ASSERT_EQ(vdex_unquickened->FlushCloseOrErase(), 0) << "Could not flush and close";
1970}
1971
Mathieu Chartierd45863a2018-03-21 18:16:36 -07001972// Test that compact dex generation with invalid dex files doesn't crash dex2oat. b/75970654
1973TEST_F(Dex2oatTest, CompactDexInvalidSource) {
1974 ScratchFile invalid_dex;
1975 {
1976 FILE* file = fdopen(invalid_dex.GetFd(), "w+b");
1977 ZipWriter writer(file);
1978 writer.StartEntry("classes.dex", ZipWriter::kAlign32);
1979 DexFile::Header header = {};
1980 StandardDexFile::WriteMagic(header.magic_);
1981 StandardDexFile::WriteCurrentVersion(header.magic_);
1982 header.file_size_ = 4 * KB;
1983 header.data_size_ = 4 * KB;
1984 header.data_off_ = 10 * MB;
1985 header.map_off_ = 10 * MB;
1986 header.class_defs_off_ = 10 * MB;
1987 header.class_defs_size_ = 10000;
1988 ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
1989 writer.FinishEntry();
1990 writer.Finish();
1991 ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
1992 }
Andreas Gampebc802de2018-06-20 17:24:11 -07001993 const std::string& dex_location = invalid_dex.GetFilename();
Mathieu Chartierd45863a2018-03-21 18:16:36 -07001994 const std::string odex_location = GetOdexDir() + "/output.odex";
1995 std::string error_msg;
1996 int status = GenerateOdexForTestWithStatus(
1997 {dex_location},
1998 odex_location,
1999 CompilerFilter::kQuicken,
2000 &error_msg,
2001 { "--compact-dex-level=fast" });
2002 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
2003}
2004
Mathieu Chartier14e7bad2018-03-22 14:33:20 -07002005// Test that dex2oat with a CompactDex file in the APK fails.
2006TEST_F(Dex2oatTest, CompactDexInZip) {
2007 CompactDexFile::Header header = {};
2008 CompactDexFile::WriteMagic(header.magic_);
2009 CompactDexFile::WriteCurrentVersion(header.magic_);
2010 header.file_size_ = sizeof(CompactDexFile::Header);
2011 header.data_off_ = 10 * MB;
2012 header.map_off_ = 10 * MB;
2013 header.class_defs_off_ = 10 * MB;
2014 header.class_defs_size_ = 10000;
2015 // Create a zip containing the invalid dex.
2016 ScratchFile invalid_dex_zip;
2017 {
2018 FILE* file = fdopen(invalid_dex_zip.GetFd(), "w+b");
2019 ZipWriter writer(file);
2020 writer.StartEntry("classes.dex", ZipWriter::kCompress);
2021 ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
2022 writer.FinishEntry();
2023 writer.Finish();
2024 ASSERT_EQ(invalid_dex_zip.GetFile()->Flush(), 0);
2025 }
2026 // Create the dex file directly.
2027 ScratchFile invalid_dex;
2028 {
2029 ASSERT_GE(invalid_dex.GetFile()->WriteFully(&header, sizeof(header)), 0);
2030 ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
2031 }
2032 std::string error_msg;
2033 int status = 0u;
2034
2035 status = GenerateOdexForTestWithStatus(
2036 { invalid_dex_zip.GetFilename() },
2037 GetOdexDir() + "/output_apk.odex",
2038 CompilerFilter::kQuicken,
2039 &error_msg,
2040 { "--compact-dex-level=fast" });
2041 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
2042
2043 status = GenerateOdexForTestWithStatus(
2044 { invalid_dex.GetFilename() },
2045 GetOdexDir() + "/output.odex",
2046 CompilerFilter::kQuicken,
2047 &error_msg,
2048 { "--compact-dex-level=fast" });
2049 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
2050}
2051
Mathieu Chartierf85b3db2018-04-02 18:16:21 -07002052TEST_F(Dex2oatTest, AppImageNoProfile) {
2053 ScratchFile app_image_file;
2054 const std::string out_dir = GetScratchDir();
2055 const std::string odex_location = out_dir + "/base.odex";
2056 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2057 odex_location,
2058 CompilerFilter::Filter::kSpeedProfile,
2059 { "--app-image-fd=" + std::to_string(app_image_file.GetFd()) },
2060 true, // expect_success
2061 false, // use_fd
2062 [](const OatFile&) {});
2063 // Open our generated oat file.
2064 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01002065 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
2066 odex_location.c_str(),
Mathieu Chartierf85b3db2018-04-02 18:16:21 -07002067 odex_location.c_str(),
2068 nullptr,
2069 nullptr,
2070 false,
2071 /*low_4gb*/false,
2072 odex_location.c_str(),
2073 &error_msg));
2074 ASSERT_TRUE(odex_file != nullptr);
2075 ImageHeader header = {};
2076 ASSERT_TRUE(app_image_file.GetFile()->PreadFully(
2077 reinterpret_cast<void*>(&header),
2078 sizeof(header),
2079 /*offset*/ 0u)) << app_image_file.GetFile()->GetLength();
2080 EXPECT_GT(header.GetImageSection(ImageHeader::kSectionObjects).Size(), 0u);
2081 EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtMethods).Size(), 0u);
2082 EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtFields).Size(), 0u);
2083}
2084
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002085TEST_F(Dex2oatClassLoaderContextTest, StoredClassLoaderContext) {
Mathieu Chartierc4440772018-04-16 14:40:56 -07002086 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("MultiDex");
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002087 const std::string out_dir = GetScratchDir();
2088 const std::string odex_location = out_dir + "/base.odex";
Mathieu Chartierc4440772018-04-16 14:40:56 -07002089 const std::string valid_context = "PCL[" + dex_files[0]->GetLocation() + "]";
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002090 const std::string stored_context = "PCL[/system/not_real_lib.jar]";
Mathieu Chartierc4440772018-04-16 14:40:56 -07002091 std::string expected_stored_context = "PCL[";
2092 size_t index = 1;
2093 for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
2094 const bool is_first = index == 1u;
2095 if (!is_first) {
2096 expected_stored_context += ":";
2097 }
2098 expected_stored_context += "/system/not_real_lib.jar";
2099 if (!is_first) {
2100 expected_stored_context += "!classes" + std::to_string(index) + ".dex";
2101 }
2102 expected_stored_context += "*" + std::to_string(dex_file->GetLocationChecksum());
2103 ++index;
2104 }
2105 expected_stored_context += + "]";
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002106 // The class path should not be valid and should fail being stored.
2107 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2108 odex_location,
2109 CompilerFilter::Filter::kQuicken,
2110 { "--class-loader-context=" + stored_context },
2111 true, // expect_success
2112 false, // use_fd
2113 [&](const OatFile& oat_file) {
Mathieu Chartierc4440772018-04-16 14:40:56 -07002114 EXPECT_NE(oat_file.GetClassLoaderContext(), stored_context) << output_;
2115 EXPECT_NE(oat_file.GetClassLoaderContext(), valid_context) << output_;
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002116 });
2117 // The stored context should match what we expect even though it's invalid.
2118 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2119 odex_location,
2120 CompilerFilter::Filter::kQuicken,
2121 { "--class-loader-context=" + valid_context,
2122 "--stored-class-loader-context=" + stored_context },
2123 true, // expect_success
2124 false, // use_fd
2125 [&](const OatFile& oat_file) {
Mathieu Chartierc4440772018-04-16 14:40:56 -07002126 EXPECT_EQ(oat_file.GetClassLoaderContext(), expected_stored_context) << output_;
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002127 });
2128}
2129
Andreas Gampee1459ae2016-06-29 09:36:30 -07002130} // namespace art