blob: ad44624f762ea85aa8ecf20f306e808a10f6bda1 [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"
David Sehr9e734c72018-01-04 17:56:19 -080036#include "dex/code_item_accessors-inl.h"
37#include "dex/dex_file-inl.h"
38#include "dex/dex_file_loader.h"
Andreas Gampee1459ae2016-06-29 09:36:30 -070039#include "dex2oat_environment_test.h"
Andreas Gampef7882972017-03-20 16:35:24 -070040#include "dex2oat_return_codes.h"
Andreas Gampe67f02822016-06-24 21:05:23 -070041#include "oat.h"
42#include "oat_file.h"
David Sehr82d046e2018-04-23 08:14:19 -070043#include "profile/profile_compilation_info.h"
Mathieu Chartier792111c2018-02-15 13:02:15 -080044#include "vdex_file.h"
45#include "ziparchive/zip_writer.h"
Andreas Gampee1459ae2016-06-29 09:36:30 -070046
Andreas Gampee1459ae2016-06-29 09:36:30 -070047namespace art {
48
Mathieu Chartierea650f32017-05-24 12:04:13 -070049static constexpr size_t kMaxMethodIds = 65535;
Mathieu Chartier9e050df2017-08-09 10:05:47 -070050static constexpr bool kDebugArgs = false;
Mathieu Chartier02129102017-12-22 11:04:01 -080051static const char* kDisableCompactDex = "--compact-dex-level=none";
Mathieu Chartierea650f32017-05-24 12:04:13 -070052
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080053using android::base::StringPrintf;
54
Andreas Gampee1459ae2016-06-29 09:36:30 -070055class Dex2oatTest : public Dex2oatEnvironmentTest {
56 public:
57 virtual void TearDown() OVERRIDE {
58 Dex2oatEnvironmentTest::TearDown();
59
60 output_ = "";
61 error_msg_ = "";
62 success_ = false;
63 }
64
65 protected:
Mathieu Chartier9e050df2017-08-09 10:05:47 -070066 int GenerateOdexForTestWithStatus(const std::vector<std::string>& dex_locations,
Andreas Gampef7882972017-03-20 16:35:24 -070067 const std::string& odex_location,
68 CompilerFilter::Filter filter,
69 std::string* error_msg,
70 const std::vector<std::string>& extra_args = {},
71 bool use_fd = false) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080072 std::unique_ptr<File> oat_file;
Andreas Gampee1459ae2016-06-29 09:36:30 -070073 std::vector<std::string> args;
Mathieu Chartier9e050df2017-08-09 10:05:47 -070074 // Add dex file args.
75 for (const std::string& dex_location : dex_locations) {
76 args.push_back("--dex-file=" + dex_location);
77 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080078 if (use_fd) {
79 oat_file.reset(OS::CreateEmptyFile(odex_location.c_str()));
80 CHECK(oat_file != nullptr) << odex_location;
81 args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
Mathieu Chartier046854b2017-03-01 17:16:22 -080082 args.push_back("--oat-location=" + odex_location);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080083 } else {
84 args.push_back("--oat-file=" + odex_location);
85 }
Andreas Gampee1459ae2016-06-29 09:36:30 -070086 args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
87 args.push_back("--runtime-arg");
88 args.push_back("-Xnorelocate");
89
90 args.insert(args.end(), extra_args.begin(), extra_args.end());
91
Andreas Gampef7882972017-03-20 16:35:24 -070092 int status = Dex2Oat(args, error_msg);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080093 if (oat_file != nullptr) {
Andreas Gampef7882972017-03-20 16:35:24 -070094 CHECK_EQ(oat_file->FlushClose(), 0) << "Could not flush and close oat file";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080095 }
Andreas Gampef7882972017-03-20 16:35:24 -070096 return status;
97 }
Andreas Gampee1459ae2016-06-29 09:36:30 -070098
Andreas Gampe641a4732017-08-24 13:21:35 -070099 void GenerateOdexForTest(
100 const std::string& dex_location,
101 const std::string& odex_location,
102 CompilerFilter::Filter filter,
103 const std::vector<std::string>& extra_args = {},
104 bool expect_success = true,
105 bool use_fd = false) {
106 GenerateOdexForTest(dex_location,
107 odex_location,
108 filter,
109 extra_args,
110 expect_success,
111 use_fd,
112 [](const OatFile&) {});
113 }
114
Andreas Gampe80ddf272018-01-11 09:41:00 -0800115 bool test_accepts_odex_file_on_failure = false;
116
Andreas Gampe641a4732017-08-24 13:21:35 -0700117 template <typename T>
118 void GenerateOdexForTest(
119 const std::string& dex_location,
120 const std::string& odex_location,
121 CompilerFilter::Filter filter,
122 const std::vector<std::string>& extra_args,
123 bool expect_success,
124 bool use_fd,
125 T check_oat) {
Andreas Gampef7882972017-03-20 16:35:24 -0700126 std::string error_msg;
Mathieu Chartier9e050df2017-08-09 10:05:47 -0700127 int status = GenerateOdexForTestWithStatus({dex_location},
Andreas Gampef7882972017-03-20 16:35:24 -0700128 odex_location,
129 filter,
130 &error_msg,
131 extra_args,
132 use_fd);
Andreas Gampe80ddf272018-01-11 09:41:00 -0800133 bool success = (WIFEXITED(status) && WEXITSTATUS(status) == 0);
Andreas Gampee1459ae2016-06-29 09:36:30 -0700134 if (expect_success) {
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800135 ASSERT_TRUE(success) << error_msg << std::endl << output_;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700136
137 // Verify the odex file was generated as expected.
Nicolas Geoffray30025092018-04-19 14:43:29 +0100138 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
139 odex_location.c_str(),
Andreas Gampee1459ae2016-06-29 09:36:30 -0700140 odex_location.c_str(),
141 nullptr,
142 nullptr,
143 false,
144 /*low_4gb*/false,
145 dex_location.c_str(),
146 &error_msg));
147 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
148
149 CheckFilter(filter, odex_file->GetCompilerFilter());
Calin Juravle1ce70852017-06-28 10:59:03 -0700150 check_oat(*(odex_file.get()));
Andreas Gampee1459ae2016-06-29 09:36:30 -0700151 } else {
152 ASSERT_FALSE(success) << output_;
153
154 error_msg_ = error_msg;
155
Andreas Gampe80ddf272018-01-11 09:41:00 -0800156 if (!test_accepts_odex_file_on_failure) {
157 // Verify there's no loadable odex file.
Nicolas Geoffray30025092018-04-19 14:43:29 +0100158 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
159 odex_location.c_str(),
Andreas Gampe80ddf272018-01-11 09:41:00 -0800160 odex_location.c_str(),
161 nullptr,
162 nullptr,
163 false,
164 /*low_4gb*/false,
165 dex_location.c_str(),
166 &error_msg));
167 ASSERT_TRUE(odex_file.get() == nullptr);
168 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700169 }
170 }
171
Calin Juravle1ccf6132017-08-02 17:46:53 -0700172 // Check the input compiler filter against the generated oat file's filter. May be overridden
Andreas Gampee1459ae2016-06-29 09:36:30 -0700173 // in subclasses when equality is not expected.
174 virtual void CheckFilter(CompilerFilter::Filter expected, CompilerFilter::Filter actual) {
175 EXPECT_EQ(expected, actual);
176 }
177
Andreas Gampef7882972017-03-20 16:35:24 -0700178 int Dex2Oat(const std::vector<std::string>& dex2oat_args, std::string* error_msg) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700179 Runtime* runtime = Runtime::Current();
180
181 const std::vector<gc::space::ImageSpace*>& image_spaces =
182 runtime->GetHeap()->GetBootImageSpaces();
183 if (image_spaces.empty()) {
184 *error_msg = "No image location found for Dex2Oat.";
185 return false;
186 }
187 std::string image_location = image_spaces[0]->GetImageLocation();
188
189 std::vector<std::string> argv;
190 argv.push_back(runtime->GetCompilerExecutable());
Calin Juravle1ccf6132017-08-02 17:46:53 -0700191
Nicolas Geoffray433b79a2017-01-30 20:54:45 +0000192 if (runtime->IsJavaDebuggable()) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700193 argv.push_back("--debuggable");
194 }
195 runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
196
197 if (!runtime->IsVerificationEnabled()) {
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100198 argv.push_back("--compiler-filter=assume-verified");
Andreas Gampee1459ae2016-06-29 09:36:30 -0700199 }
200
201 if (runtime->MustRelocateIfPossible()) {
202 argv.push_back("--runtime-arg");
203 argv.push_back("-Xrelocate");
204 } else {
205 argv.push_back("--runtime-arg");
206 argv.push_back("-Xnorelocate");
207 }
208
209 if (!kIsTargetBuild) {
210 argv.push_back("--host");
211 }
212
213 argv.push_back("--boot-image=" + image_location);
214
215 std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
216 argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
217
218 argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
219
220 // We must set --android-root.
221 const char* android_root = getenv("ANDROID_ROOT");
222 CHECK(android_root != nullptr);
223 argv.push_back("--android-root=" + std::string(android_root));
224
Mathieu Chartier9e050df2017-08-09 10:05:47 -0700225 if (kDebugArgs) {
226 std::string all_args;
227 for (const std::string& arg : argv) {
228 all_args += arg + " ";
229 }
230 LOG(ERROR) << all_args;
231 }
232
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100233 int link[2];
Andreas Gampee1459ae2016-06-29 09:36:30 -0700234
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100235 if (pipe(link) == -1) {
236 return false;
237 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700238
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100239 pid_t pid = fork();
240 if (pid == -1) {
241 return false;
242 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700243
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100244 if (pid == 0) {
245 // We need dex2oat to actually log things.
246 setenv("ANDROID_LOG_TAGS", "*:d", 1);
247 dup2(link[1], STDERR_FILENO);
248 close(link[0]);
249 close(link[1]);
250 std::vector<const char*> c_args;
251 for (const std::string& str : argv) {
252 c_args.push_back(str.c_str());
Andreas Gampee1459ae2016-06-29 09:36:30 -0700253 }
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100254 c_args.push_back(nullptr);
255 execv(c_args[0], const_cast<char* const*>(c_args.data()));
256 exit(1);
Andreas Gampef7882972017-03-20 16:35:24 -0700257 UNREACHABLE();
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100258 } else {
259 close(link[1]);
260 char buffer[128];
261 memset(buffer, 0, 128);
262 ssize_t bytes_read = 0;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700263
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100264 while (TEMP_FAILURE_RETRY(bytes_read = read(link[0], buffer, 128)) > 0) {
265 output_ += std::string(buffer, bytes_read);
266 }
267 close(link[0]);
Andreas Gampef7882972017-03-20 16:35:24 -0700268 int status = -1;
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100269 if (waitpid(pid, &status, 0) != -1) {
270 success_ = (status == 0);
271 }
Andreas Gampef7882972017-03-20 16:35:24 -0700272 return status;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700273 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700274 }
275
276 std::string output_ = "";
277 std::string error_msg_ = "";
278 bool success_ = false;
279};
280
281class Dex2oatSwapTest : public Dex2oatTest {
282 protected:
283 void RunTest(bool use_fd, bool expect_use, const std::vector<std::string>& extra_args = {}) {
284 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
285 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
286
Andreas Gampe7adeda82016-07-25 08:27:35 -0700287 Copy(GetTestDexFileName(), dex_location);
Andreas Gampee1459ae2016-06-29 09:36:30 -0700288
289 std::vector<std::string> copy(extra_args);
290
291 std::unique_ptr<ScratchFile> sf;
292 if (use_fd) {
293 sf.reset(new ScratchFile());
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800294 copy.push_back(android::base::StringPrintf("--swap-fd=%d", sf->GetFd()));
Andreas Gampee1459ae2016-06-29 09:36:30 -0700295 } else {
296 std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
297 copy.push_back("--swap-file=" + swap_location);
298 }
299 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, copy);
300
301 CheckValidity();
302 ASSERT_TRUE(success_);
303 CheckResult(expect_use);
304 }
305
Andreas Gampe7adeda82016-07-25 08:27:35 -0700306 virtual std::string GetTestDexFileName() {
Vladimir Marko15357702017-02-09 10:37:31 +0000307 return Dex2oatEnvironmentTest::GetTestDexFileName("VerifierDeps");
Andreas Gampe7adeda82016-07-25 08:27:35 -0700308 }
309
310 virtual void CheckResult(bool expect_use) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700311 if (kIsTargetBuild) {
312 CheckTargetResult(expect_use);
313 } else {
314 CheckHostResult(expect_use);
315 }
316 }
317
Andreas Gampe7adeda82016-07-25 08:27:35 -0700318 virtual void CheckTargetResult(bool expect_use ATTRIBUTE_UNUSED) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700319 // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
320 // something for variants with file descriptor where we can control the lifetime of
321 // the swap file and thus take a look at it.
322 }
323
Andreas Gampe7adeda82016-07-25 08:27:35 -0700324 virtual void CheckHostResult(bool expect_use) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700325 if (!kIsTargetBuild) {
326 if (expect_use) {
327 EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
328 << output_;
329 } else {
330 EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
331 << output_;
332 }
333 }
334 }
335
336 // Check whether the dex2oat run was really successful.
Andreas Gampe7adeda82016-07-25 08:27:35 -0700337 virtual void CheckValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700338 if (kIsTargetBuild) {
339 CheckTargetValidity();
340 } else {
341 CheckHostValidity();
342 }
343 }
344
Andreas Gampe7adeda82016-07-25 08:27:35 -0700345 virtual void CheckTargetValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700346 // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
347 // something for variants with file descriptor where we can control the lifetime of
348 // the swap file and thus take a look at it.
349 }
350
351 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
Andreas Gampe7adeda82016-07-25 08:27:35 -0700352 virtual void CheckHostValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700353 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
354 }
355};
356
357TEST_F(Dex2oatSwapTest, DoNotUseSwapDefaultSingleSmall) {
358 RunTest(false /* use_fd */, false /* expect_use */);
359 RunTest(true /* use_fd */, false /* expect_use */);
360}
361
362TEST_F(Dex2oatSwapTest, DoNotUseSwapSingle) {
363 RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
364 RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
365}
366
367TEST_F(Dex2oatSwapTest, DoNotUseSwapSmall) {
368 RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
369 RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
370}
371
372TEST_F(Dex2oatSwapTest, DoUseSwapSingleSmall) {
373 RunTest(false /* use_fd */,
374 true /* expect_use */,
375 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
376 RunTest(true /* use_fd */,
377 true /* expect_use */,
378 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
379}
380
Andreas Gampe7adeda82016-07-25 08:27:35 -0700381class Dex2oatSwapUseTest : public Dex2oatSwapTest {
382 protected:
383 void CheckHostResult(bool expect_use) OVERRIDE {
384 if (!kIsTargetBuild) {
385 if (expect_use) {
386 EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
387 << output_;
388 } else {
389 EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
390 << output_;
391 }
392 }
393 }
394
395 std::string GetTestDexFileName() OVERRIDE {
396 // Use Statics as it has a handful of functions.
397 return CommonRuntimeTest::GetTestDexFileName("Statics");
398 }
399
400 void GrabResult1() {
401 if (!kIsTargetBuild) {
402 native_alloc_1_ = ParseNativeAlloc();
403 swap_1_ = ParseSwap(false /* expected */);
404 } else {
405 native_alloc_1_ = std::numeric_limits<size_t>::max();
406 swap_1_ = 0;
407 }
408 }
409
410 void GrabResult2() {
411 if (!kIsTargetBuild) {
412 native_alloc_2_ = ParseNativeAlloc();
413 swap_2_ = ParseSwap(true /* expected */);
414 } else {
415 native_alloc_2_ = 0;
416 swap_2_ = std::numeric_limits<size_t>::max();
417 }
418 }
419
420 private:
421 size_t ParseNativeAlloc() {
422 std::regex native_alloc_regex("dex2oat took.*native alloc=[^ ]+ \\(([0-9]+)B\\)");
423 std::smatch native_alloc_match;
424 bool found = std::regex_search(output_, native_alloc_match, native_alloc_regex);
425 if (!found) {
426 EXPECT_TRUE(found);
427 return 0;
428 }
429 if (native_alloc_match.size() != 2U) {
430 EXPECT_EQ(native_alloc_match.size(), 2U);
431 return 0;
432 }
433
434 std::istringstream stream(native_alloc_match[1].str());
435 size_t value;
436 stream >> value;
437
438 return value;
439 }
440
441 size_t ParseSwap(bool expected) {
442 std::regex swap_regex("dex2oat took[^\\n]+swap=[^ ]+ \\(([0-9]+)B\\)");
443 std::smatch swap_match;
444 bool found = std::regex_search(output_, swap_match, swap_regex);
445 if (found != expected) {
446 EXPECT_EQ(expected, found);
447 return 0;
448 }
449
450 if (!found) {
451 return 0;
452 }
453
454 if (swap_match.size() != 2U) {
455 EXPECT_EQ(swap_match.size(), 2U);
456 return 0;
457 }
458
459 std::istringstream stream(swap_match[1].str());
460 size_t value;
461 stream >> value;
462
463 return value;
464 }
465
466 protected:
467 size_t native_alloc_1_;
468 size_t native_alloc_2_;
469
470 size_t swap_1_;
471 size_t swap_2_;
472};
473
474TEST_F(Dex2oatSwapUseTest, CheckSwapUsage) {
Roland Levillain05e34f42018-05-24 13:19:05 +0000475 // Native memory usage isn't correctly tracked when running under ASan.
476 TEST_DISABLED_FOR_MEMORY_TOOL();
Andreas Gampef4a67fd2017-05-04 09:55:36 -0700477
Vladimir Marko57070da2017-02-14 16:16:30 +0000478 // The `native_alloc_2_ >= native_alloc_1_` assertion below may not
Roland Levillain19772bf2017-02-16 11:28:10 +0000479 // hold true on some x86 systems; disable this test while we
480 // investigate (b/29259363).
481 TEST_DISABLED_FOR_X86();
Vladimir Marko57070da2017-02-14 16:16:30 +0000482
Andreas Gampe7adeda82016-07-25 08:27:35 -0700483 RunTest(false /* use_fd */,
484 false /* expect_use */);
485 GrabResult1();
486 std::string output_1 = output_;
487
488 output_ = "";
489
490 RunTest(false /* use_fd */,
491 true /* expect_use */,
492 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
493 GrabResult2();
494 std::string output_2 = output_;
495
496 if (native_alloc_2_ >= native_alloc_1_ || swap_1_ >= swap_2_) {
497 EXPECT_LT(native_alloc_2_, native_alloc_1_);
498 EXPECT_LT(swap_1_, swap_2_);
499
500 LOG(ERROR) << output_1;
501 LOG(ERROR) << output_2;
502 }
503}
504
Andreas Gampe67f02822016-06-24 21:05:23 -0700505class Dex2oatVeryLargeTest : public Dex2oatTest {
506 protected:
507 void CheckFilter(CompilerFilter::Filter input ATTRIBUTE_UNUSED,
508 CompilerFilter::Filter result ATTRIBUTE_UNUSED) OVERRIDE {
509 // Ignore, we'll do our own checks.
510 }
511
512 void RunTest(CompilerFilter::Filter filter,
513 bool expect_large,
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700514 bool expect_downgrade,
Andreas Gampe67f02822016-06-24 21:05:23 -0700515 const std::vector<std::string>& extra_args = {}) {
516 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
517 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700518 std::string app_image_file = GetScratchDir() + "/Test.art";
Andreas Gampe67f02822016-06-24 21:05:23 -0700519
520 Copy(GetDexSrc1(), dex_location);
521
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700522 std::vector<std::string> new_args(extra_args);
523 new_args.push_back("--app-image-file=" + app_image_file);
524 GenerateOdexForTest(dex_location, odex_location, filter, new_args);
Andreas Gampe67f02822016-06-24 21:05:23 -0700525
526 CheckValidity();
527 ASSERT_TRUE(success_);
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700528 CheckResult(dex_location,
529 odex_location,
530 app_image_file,
531 filter,
532 expect_large,
533 expect_downgrade);
Andreas Gampe67f02822016-06-24 21:05:23 -0700534 }
535
536 void CheckResult(const std::string& dex_location,
537 const std::string& odex_location,
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700538 const std::string& app_image_file,
Andreas Gampe67f02822016-06-24 21:05:23 -0700539 CompilerFilter::Filter filter,
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700540 bool expect_large,
541 bool expect_downgrade) {
542 if (expect_downgrade) {
543 EXPECT_TRUE(expect_large);
544 }
Andreas Gampe67f02822016-06-24 21:05:23 -0700545 // Host/target independent checks.
546 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +0100547 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
548 odex_location.c_str(),
Andreas Gampe67f02822016-06-24 21:05:23 -0700549 odex_location.c_str(),
550 nullptr,
551 nullptr,
552 false,
553 /*low_4gb*/false,
554 dex_location.c_str(),
555 &error_msg));
556 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700557 EXPECT_GT(app_image_file.length(), 0u);
558 std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file.c_str()));
Andreas Gampe67f02822016-06-24 21:05:23 -0700559 if (expect_large) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700560 // Note: we cannot check the following
561 // EXPECT_FALSE(CompilerFilter::IsAotCompilationEnabled(odex_file->GetCompilerFilter()));
Andreas Gampe67f02822016-06-24 21:05:23 -0700562 // The reason is that the filter override currently happens when the dex files are
563 // loaded in dex2oat, which is after the oat file has been started. Thus, the header
564 // store cannot be changed, and the original filter is set in stone.
565
566 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
567 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
568 ASSERT_TRUE(dex_file != nullptr);
569 uint32_t class_def_count = dex_file->NumClassDefs();
570 ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
571 for (uint16_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
572 OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
573 EXPECT_EQ(oat_class.GetType(), OatClassType::kOatClassNoneCompiled);
574 }
575 }
576
577 // If the input filter was "below," it should have been used.
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100578 if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kExtract, filter)) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700579 EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
580 }
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700581
582 // If expect large, make sure the app image isn't generated or is empty.
583 if (file != nullptr) {
584 EXPECT_EQ(file->GetLength(), 0u);
585 }
Andreas Gampe67f02822016-06-24 21:05:23 -0700586 } else {
587 EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700588 ASSERT_TRUE(file != nullptr) << app_image_file;
589 EXPECT_GT(file->GetLength(), 0u);
Andreas Gampe67f02822016-06-24 21:05:23 -0700590 }
591
592 // Host/target dependent checks.
593 if (kIsTargetBuild) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700594 CheckTargetResult(expect_downgrade);
Andreas Gampe67f02822016-06-24 21:05:23 -0700595 } else {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700596 CheckHostResult(expect_downgrade);
Andreas Gampe67f02822016-06-24 21:05:23 -0700597 }
598 }
599
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700600 void CheckTargetResult(bool expect_downgrade ATTRIBUTE_UNUSED) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700601 // TODO: Ignore for now. May do something for fd things.
602 }
603
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700604 void CheckHostResult(bool expect_downgrade) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700605 if (!kIsTargetBuild) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700606 if (expect_downgrade) {
607 EXPECT_NE(output_.find("Very large app, downgrading to"), std::string::npos) << output_;
Andreas Gampe67f02822016-06-24 21:05:23 -0700608 } else {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700609 EXPECT_EQ(output_.find("Very large app, downgrading to"), std::string::npos) << output_;
Andreas Gampe67f02822016-06-24 21:05:23 -0700610 }
611 }
612 }
613
614 // Check whether the dex2oat run was really successful.
615 void CheckValidity() {
616 if (kIsTargetBuild) {
617 CheckTargetValidity();
618 } else {
619 CheckHostValidity();
620 }
621 }
622
623 void CheckTargetValidity() {
624 // TODO: Ignore for now.
625 }
626
627 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
628 void CheckHostValidity() {
629 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
630 }
631};
632
633TEST_F(Dex2oatVeryLargeTest, DontUseVeryLarge) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700634 RunTest(CompilerFilter::kAssumeVerified, false, false);
635 RunTest(CompilerFilter::kExtract, false, false);
636 RunTest(CompilerFilter::kQuicken, false, false);
637 RunTest(CompilerFilter::kSpeed, false, false);
Andreas Gampe67f02822016-06-24 21:05:23 -0700638
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700639 RunTest(CompilerFilter::kAssumeVerified, false, false, { "--very-large-app-threshold=10000000" });
640 RunTest(CompilerFilter::kExtract, false, false, { "--very-large-app-threshold=10000000" });
641 RunTest(CompilerFilter::kQuicken, false, false, { "--very-large-app-threshold=10000000" });
642 RunTest(CompilerFilter::kSpeed, false, false, { "--very-large-app-threshold=10000000" });
Andreas Gampe67f02822016-06-24 21:05:23 -0700643}
644
645TEST_F(Dex2oatVeryLargeTest, UseVeryLarge) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700646 RunTest(CompilerFilter::kAssumeVerified, true, false, { "--very-large-app-threshold=100" });
647 RunTest(CompilerFilter::kExtract, true, false, { "--very-large-app-threshold=100" });
648 RunTest(CompilerFilter::kQuicken, true, true, { "--very-large-app-threshold=100" });
649 RunTest(CompilerFilter::kSpeed, true, true, { "--very-large-app-threshold=100" });
Andreas Gampe67f02822016-06-24 21:05:23 -0700650}
651
Mathieu Chartier97ab5e32017-02-22 13:35:44 -0800652// Regressin test for b/35665292.
653TEST_F(Dex2oatVeryLargeTest, SpeedProfileNoProfile) {
654 // Test that dex2oat doesn't crash with speed-profile but no input profile.
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700655 RunTest(CompilerFilter::kSpeedProfile, false, false);
Mathieu Chartier97ab5e32017-02-22 13:35:44 -0800656}
657
Jeff Hao608f2ce2016-10-19 11:17:11 -0700658class Dex2oatLayoutTest : public Dex2oatTest {
659 protected:
660 void CheckFilter(CompilerFilter::Filter input ATTRIBUTE_UNUSED,
661 CompilerFilter::Filter result ATTRIBUTE_UNUSED) OVERRIDE {
662 // Ignore, we'll do our own checks.
663 }
664
Jeff Hao41fba6a2016-11-28 11:53:33 -0800665 // Emits a profile with a single dex file with the given location and a single class index of 1.
666 void GenerateProfile(const std::string& test_profile,
667 const std::string& dex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800668 size_t num_classes,
Jeff Hao41fba6a2016-11-28 11:53:33 -0800669 uint32_t checksum) {
670 int profile_test_fd = open(test_profile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
671 CHECK_GE(profile_test_fd, 0);
672
673 ProfileCompilationInfo info;
674 std::string profile_key = ProfileCompilationInfo::GetProfileDexFileKey(dex_location);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800675 for (size_t i = 0; i < num_classes; ++i) {
Mathieu Chartierea650f32017-05-24 12:04:13 -0700676 info.AddClassIndex(profile_key, checksum, dex::TypeIndex(1 + i), kMaxMethodIds);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800677 }
Jeff Hao41fba6a2016-11-28 11:53:33 -0800678 bool result = info.Save(profile_test_fd);
679 close(profile_test_fd);
680 ASSERT_TRUE(result);
681 }
682
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800683 void CompileProfileOdex(const std::string& dex_location,
684 const std::string& odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800685 const std::string& app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800686 bool use_fd,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800687 size_t num_profile_classes,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000688 const std::vector<std::string>& extra_args = {},
689 bool expect_success = true) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800690 const std::string profile_location = GetScratchDir() + "/primary.prof";
Jeff Hao41fba6a2016-11-28 11:53:33 -0800691 const char* location = dex_location.c_str();
692 std::string error_msg;
693 std::vector<std::unique_ptr<const DexFile>> dex_files;
David Sehr013fd802018-01-11 22:55:24 -0800694 const ArtDexFileLoader dex_file_loader;
695 ASSERT_TRUE(dex_file_loader.Open(
Nicolas Geoffray095c6c92017-10-19 13:59:55 +0100696 location, location, /* verify */ true, /* verify_checksum */ true, &error_msg, &dex_files));
Jeff Hao41fba6a2016-11-28 11:53:33 -0800697 EXPECT_EQ(dex_files.size(), 1U);
698 std::unique_ptr<const DexFile>& dex_file = dex_files[0];
Mathieu Chartier046854b2017-03-01 17:16:22 -0800699 GenerateProfile(profile_location,
700 dex_location,
701 num_profile_classes,
702 dex_file->GetLocationChecksum());
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800703 std::vector<std::string> copy(extra_args);
704 copy.push_back("--profile-file=" + profile_location);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800705 std::unique_ptr<File> app_image_file;
706 if (!app_image_file_name.empty()) {
707 if (use_fd) {
708 app_image_file.reset(OS::CreateEmptyFile(app_image_file_name.c_str()));
709 copy.push_back("--app-image-fd=" + std::to_string(app_image_file->Fd()));
710 } else {
711 copy.push_back("--app-image-file=" + app_image_file_name);
712 }
713 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800714 GenerateOdexForTest(dex_location,
715 odex_location,
716 CompilerFilter::kSpeedProfile,
717 copy,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000718 expect_success,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800719 use_fd);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800720 if (app_image_file != nullptr) {
721 ASSERT_EQ(app_image_file->FlushCloseOrErase(), 0) << "Could not flush and close art file";
722 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800723 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700724
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100725 uint64_t GetImageObjectSectionSize(const std::string& image_file_name) {
Mathieu Chartier046854b2017-03-01 17:16:22 -0800726 EXPECT_FALSE(image_file_name.empty());
727 std::unique_ptr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
728 CHECK(file != nullptr);
729 ImageHeader image_header;
730 const bool success = file->ReadFully(&image_header, sizeof(image_header));
731 CHECK(success);
732 CHECK(image_header.IsValid());
733 ReaderMutexLock mu(Thread::Current(), *Locks::mutator_lock_);
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100734 return image_header.GetObjectsSection().Size();
Mathieu Chartier046854b2017-03-01 17:16:22 -0800735 }
736
737 void RunTest(bool app_image) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800738 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
739 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Mathieu Chartier046854b2017-03-01 17:16:22 -0800740 std::string app_image_file = app_image ? (GetOdexDir() + "/DexOdexNoOat.art"): "";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800741 Copy(GetDexSrc2(), dex_location);
742
Mathieu Chartier046854b2017-03-01 17:16:22 -0800743 uint64_t image_file_empty_profile = 0;
744 if (app_image) {
745 CompileProfileOdex(dex_location,
746 odex_location,
747 app_image_file,
748 /* use_fd */ false,
749 /* num_profile_classes */ 0);
750 CheckValidity();
751 ASSERT_TRUE(success_);
752 // Don't check the result since CheckResult relies on the class being in the profile.
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100753 image_file_empty_profile = GetImageObjectSectionSize(app_image_file);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800754 EXPECT_GT(image_file_empty_profile, 0u);
755 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700756
Mathieu Chartier046854b2017-03-01 17:16:22 -0800757 // Small profile.
758 CompileProfileOdex(dex_location,
759 odex_location,
760 app_image_file,
761 /* use_fd */ false,
762 /* num_profile_classes */ 1);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700763 CheckValidity();
764 ASSERT_TRUE(success_);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800765 CheckResult(dex_location, odex_location, app_image_file);
766
767 if (app_image) {
768 // Test that the profile made a difference by adding more classes.
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100769 const uint64_t image_file_small_profile = GetImageObjectSectionSize(app_image_file);
770 ASSERT_LT(image_file_empty_profile, image_file_small_profile);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800771 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700772 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800773
774 void RunTestVDex() {
775 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
776 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
777 std::string vdex_location = GetOdexDir() + "/DexOdexNoOat.vdex";
Mathieu Chartier046854b2017-03-01 17:16:22 -0800778 std::string app_image_file_name = GetOdexDir() + "/DexOdexNoOat.art";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800779 Copy(GetDexSrc2(), dex_location);
780
781 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
782 CHECK(vdex_file1 != nullptr) << vdex_location;
783 ScratchFile vdex_file2;
784 {
785 std::string input_vdex = "--input-vdex-fd=-1";
786 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
787 CompileProfileOdex(dex_location,
788 odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800789 app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800790 /* use_fd */ true,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800791 /* num_profile_classes */ 1,
Mathieu Chartierf1609832018-01-31 03:09:56 -0800792 { input_vdex, output_vdex });
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800793 EXPECT_GT(vdex_file1->GetLength(), 0u);
794 }
795 {
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000796 // Test that vdex and dexlayout fail gracefully.
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800797 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
798 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2.GetFd());
799 CompileProfileOdex(dex_location,
800 odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800801 app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800802 /* use_fd */ true,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800803 /* num_profile_classes */ 1,
Mathieu Chartierd27923c2018-02-08 21:00:03 -0800804 { input_vdex, output_vdex },
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100805 /* expect_success */ true);
806 EXPECT_GT(vdex_file2.GetFile()->GetLength(), 0u);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800807 }
808 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
809 CheckValidity();
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100810 ASSERT_TRUE(success_);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800811 }
812
Mathieu Chartier046854b2017-03-01 17:16:22 -0800813 void CheckResult(const std::string& dex_location,
814 const std::string& odex_location,
815 const std::string& app_image_file_name) {
Jeff Hao608f2ce2016-10-19 11:17:11 -0700816 // Host/target independent checks.
817 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +0100818 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
819 odex_location.c_str(),
Jeff Hao608f2ce2016-10-19 11:17:11 -0700820 odex_location.c_str(),
821 nullptr,
822 nullptr,
823 false,
824 /*low_4gb*/false,
825 dex_location.c_str(),
826 &error_msg));
827 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
828
Jeff Hao042e8982016-10-19 11:17:11 -0700829 const char* location = dex_location.c_str();
830 std::vector<std::unique_ptr<const DexFile>> dex_files;
David Sehr013fd802018-01-11 22:55:24 -0800831 const ArtDexFileLoader dex_file_loader;
832 ASSERT_TRUE(dex_file_loader.Open(
Nicolas Geoffray095c6c92017-10-19 13:59:55 +0100833 location, location, /* verify */ true, /* verify_checksum */ true, &error_msg, &dex_files));
Jeff Hao042e8982016-10-19 11:17:11 -0700834 EXPECT_EQ(dex_files.size(), 1U);
835 std::unique_ptr<const DexFile>& old_dex_file = dex_files[0];
836
Jeff Hao608f2ce2016-10-19 11:17:11 -0700837 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
Jeff Hao042e8982016-10-19 11:17:11 -0700838 std::unique_ptr<const DexFile> new_dex_file = oat_dex_file->OpenDexFile(&error_msg);
839 ASSERT_TRUE(new_dex_file != nullptr);
840 uint32_t class_def_count = new_dex_file->NumClassDefs();
Jeff Hao608f2ce2016-10-19 11:17:11 -0700841 ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
Jeff Hao042e8982016-10-19 11:17:11 -0700842 ASSERT_GE(class_def_count, 2U);
843
Mathieu Chartier24066ec2017-10-21 16:01:08 -0700844 // Make sure the indexes stay the same.
Jeff Hao042e8982016-10-19 11:17:11 -0700845 std::string old_class0 = old_dex_file->PrettyType(old_dex_file->GetClassDef(0).class_idx_);
846 std::string old_class1 = old_dex_file->PrettyType(old_dex_file->GetClassDef(1).class_idx_);
847 std::string new_class0 = new_dex_file->PrettyType(new_dex_file->GetClassDef(0).class_idx_);
848 std::string new_class1 = new_dex_file->PrettyType(new_dex_file->GetClassDef(1).class_idx_);
Mathieu Chartier24066ec2017-10-21 16:01:08 -0700849 EXPECT_EQ(old_class0, new_class0);
850 EXPECT_EQ(old_class1, new_class1);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700851 }
852
Jeff Haoc155b052017-01-17 17:43:29 -0800853 EXPECT_EQ(odex_file->GetCompilerFilter(), CompilerFilter::kSpeedProfile);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800854
855 if (!app_image_file_name.empty()) {
856 // Go peek at the image header to make sure it was large enough to contain the class.
857 std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file_name.c_str()));
858 ImageHeader image_header;
859 bool success = file->ReadFully(&image_header, sizeof(image_header));
860 ASSERT_TRUE(success);
861 ASSERT_TRUE(image_header.IsValid());
Vladimir Markocd87c3e2017-09-05 13:11:57 +0100862 EXPECT_GT(image_header.GetObjectsSection().Size(), 0u);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800863 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700864 }
865
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800866 // Check whether the dex2oat run was really successful.
867 void CheckValidity() {
868 if (kIsTargetBuild) {
869 CheckTargetValidity();
870 } else {
871 CheckHostValidity();
Jeff Hao608f2ce2016-10-19 11:17:11 -0700872 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800873 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700874
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800875 void CheckTargetValidity() {
876 // TODO: Ignore for now.
877 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700878
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800879 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
880 void CheckHostValidity() {
881 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
882 }
883};
Jeff Hao608f2ce2016-10-19 11:17:11 -0700884
885TEST_F(Dex2oatLayoutTest, TestLayout) {
Mathieu Chartier046854b2017-03-01 17:16:22 -0800886 RunTest(/* app-image */ false);
887}
888
889TEST_F(Dex2oatLayoutTest, TestLayoutAppImage) {
890 RunTest(/* app-image */ true);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700891}
892
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800893TEST_F(Dex2oatLayoutTest, TestVdexLayout) {
894 RunTestVDex();
895}
896
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100897class Dex2oatUnquickenTest : public Dex2oatTest {
898 protected:
899 void RunUnquickenMultiDex() {
900 std::string dex_location = GetScratchDir() + "/UnquickenMultiDex.jar";
901 std::string odex_location = GetOdexDir() + "/UnquickenMultiDex.odex";
902 std::string vdex_location = GetOdexDir() + "/UnquickenMultiDex.vdex";
903 Copy(GetTestDexFileName("MultiDex"), dex_location);
904
905 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
906 CHECK(vdex_file1 != nullptr) << vdex_location;
907 // Quicken the dex file into a vdex file.
908 {
909 std::string input_vdex = "--input-vdex-fd=-1";
910 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
911 GenerateOdexForTest(dex_location,
912 odex_location,
913 CompilerFilter::kQuicken,
Mathieu Chartierf1609832018-01-31 03:09:56 -0800914 { input_vdex, output_vdex },
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100915 /* expect_success */ true,
916 /* use_fd */ true);
917 EXPECT_GT(vdex_file1->GetLength(), 0u);
918 }
919 // Unquicken by running the verify compiler filter on the vdex file.
920 {
921 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
922 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
923 GenerateOdexForTest(dex_location,
924 odex_location,
925 CompilerFilter::kVerify,
Mathieu Chartier02129102017-12-22 11:04:01 -0800926 { input_vdex, output_vdex, kDisableCompactDex },
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100927 /* expect_success */ true,
928 /* use_fd */ true);
929 }
930 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
931 CheckResult(dex_location, odex_location);
932 ASSERT_TRUE(success_);
933 }
934
Mathieu Chartierd27923c2018-02-08 21:00:03 -0800935 void RunUnquickenMultiDexCDex() {
936 std::string dex_location = GetScratchDir() + "/UnquickenMultiDex.jar";
937 std::string odex_location = GetOdexDir() + "/UnquickenMultiDex.odex";
938 std::string odex_location2 = GetOdexDir() + "/UnquickenMultiDex2.odex";
939 std::string vdex_location = GetOdexDir() + "/UnquickenMultiDex.vdex";
940 std::string vdex_location2 = GetOdexDir() + "/UnquickenMultiDex2.vdex";
941 Copy(GetTestDexFileName("MultiDex"), dex_location);
942
943 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
944 std::unique_ptr<File> vdex_file2(OS::CreateEmptyFile(vdex_location2.c_str()));
945 CHECK(vdex_file1 != nullptr) << vdex_location;
946 CHECK(vdex_file2 != nullptr) << vdex_location2;
947
948 // Quicken the dex file into a vdex file.
949 {
950 std::string input_vdex = "--input-vdex-fd=-1";
951 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
952 GenerateOdexForTest(dex_location,
953 odex_location,
954 CompilerFilter::kQuicken,
955 { input_vdex, output_vdex, "--compact-dex-level=fast"},
956 /* expect_success */ true,
957 /* use_fd */ true);
958 EXPECT_GT(vdex_file1->GetLength(), 0u);
959 }
960
961 // Unquicken by running the verify compiler filter on the vdex file.
962 {
963 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
964 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2->Fd());
965 GenerateOdexForTest(dex_location,
966 odex_location2,
967 CompilerFilter::kVerify,
968 { input_vdex, output_vdex, "--compact-dex-level=none"},
969 /* expect_success */ true,
970 /* use_fd */ true);
971 }
972 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
973 ASSERT_EQ(vdex_file2->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
974 CheckResult(dex_location, odex_location2);
975 ASSERT_TRUE(success_);
976 }
977
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100978 void CheckResult(const std::string& dex_location, const std::string& odex_location) {
979 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +0100980 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
981 odex_location.c_str(),
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100982 odex_location.c_str(),
983 nullptr,
984 nullptr,
985 false,
986 /*low_4gb*/false,
987 dex_location.c_str(),
988 &error_msg));
989 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
990 ASSERT_GE(odex_file->GetOatDexFiles().size(), 1u);
991
992 // Iterate over the dex files and ensure there is no quickened instruction.
993 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
994 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
995 for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
996 const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
997 const uint8_t* class_data = dex_file->GetClassData(class_def);
998 if (class_data != nullptr) {
999 for (ClassDataItemIterator class_it(*dex_file, class_data);
1000 class_it.HasNext();
1001 class_it.Next()) {
1002 if (class_it.IsAtMethod() && class_it.GetMethodCodeItem() != nullptr) {
Mathieu Chartier0021feb2017-11-07 00:08:52 -08001003 for (const DexInstructionPcPair& inst :
Mathieu Chartier698ebbc2018-01-05 11:00:42 -08001004 CodeItemInstructionAccessor(*dex_file, class_it.GetMethodCodeItem())) {
Mathieu Chartier2daa1342018-02-20 16:19:28 -08001005 ASSERT_FALSE(inst->IsQuickened()) << inst->Opcode() << " " << output_;
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +01001006 }
1007 }
1008 }
1009 }
1010 }
1011 }
1012 }
1013};
1014
1015TEST_F(Dex2oatUnquickenTest, UnquickenMultiDex) {
1016 RunUnquickenMultiDex();
1017}
1018
Mathieu Chartierd27923c2018-02-08 21:00:03 -08001019TEST_F(Dex2oatUnquickenTest, UnquickenMultiDexCDex) {
1020 RunUnquickenMultiDexCDex();
1021}
1022
Andreas Gampe2e8a2562017-01-18 20:39:02 -08001023class Dex2oatWatchdogTest : public Dex2oatTest {
1024 protected:
1025 void RunTest(bool expect_success, const std::vector<std::string>& extra_args = {}) {
1026 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
1027 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
1028
1029 Copy(GetTestDexFileName(), dex_location);
1030
1031 std::vector<std::string> copy(extra_args);
1032
1033 std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
1034 copy.push_back("--swap-file=" + swap_location);
Andreas Gampe22fa3762017-10-23 20:58:12 -07001035 copy.push_back("-j512"); // Excessive idle threads just slow down dex2oat.
Andreas Gampe2e8a2562017-01-18 20:39:02 -08001036 GenerateOdexForTest(dex_location,
1037 odex_location,
1038 CompilerFilter::kSpeed,
1039 copy,
1040 expect_success);
1041 }
1042
1043 std::string GetTestDexFileName() {
1044 return GetDexSrc1();
1045 }
1046};
1047
1048TEST_F(Dex2oatWatchdogTest, TestWatchdogOK) {
1049 // Check with default.
1050 RunTest(true);
1051
1052 // Check with ten minutes.
1053 RunTest(true, { "--watchdog-timeout=600000" });
1054}
1055
1056TEST_F(Dex2oatWatchdogTest, TestWatchdogTrigger) {
Andreas Gampe80ddf272018-01-11 09:41:00 -08001057 // The watchdog is independent of dex2oat and will not delete intermediates. It is possible
1058 // that the compilation succeeds and the file is completely written by the time the watchdog
1059 // kills dex2oat (but the dex2oat threads must have been scheduled pretty badly).
1060 test_accepts_odex_file_on_failure = true;
1061
Andreas Gampe2e8a2562017-01-18 20:39:02 -08001062 // Check with ten milliseconds.
1063 RunTest(false, { "--watchdog-timeout=10" });
1064}
1065
Andreas Gampef7882972017-03-20 16:35:24 -07001066class Dex2oatReturnCodeTest : public Dex2oatTest {
1067 protected:
1068 int RunTest(const std::vector<std::string>& extra_args = {}) {
1069 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
1070 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
1071
1072 Copy(GetTestDexFileName(), dex_location);
1073
1074 std::string error_msg;
Mathieu Chartier9e050df2017-08-09 10:05:47 -07001075 return GenerateOdexForTestWithStatus({dex_location},
Andreas Gampef7882972017-03-20 16:35:24 -07001076 odex_location,
1077 CompilerFilter::kSpeed,
1078 &error_msg,
1079 extra_args);
1080 }
1081
1082 std::string GetTestDexFileName() {
1083 return GetDexSrc1();
1084 }
1085};
1086
1087TEST_F(Dex2oatReturnCodeTest, TestCreateRuntime) {
Andreas Gampefd80b172017-04-26 22:25:31 -07001088 TEST_DISABLED_FOR_MEMORY_TOOL(); // b/19100793
Andreas Gampef7882972017-03-20 16:35:24 -07001089 int status = RunTest({ "--boot-image=/this/does/not/exist/yolo.oat" });
1090 EXPECT_EQ(static_cast<int>(dex2oat::ReturnCode::kCreateRuntime), WEXITSTATUS(status)) << output_;
1091}
1092
Calin Juravle1ce70852017-06-28 10:59:03 -07001093class Dex2oatClassLoaderContextTest : public Dex2oatTest {
1094 protected:
1095 void RunTest(const char* class_loader_context,
1096 const char* expected_classpath_key,
1097 bool expected_success,
1098 bool use_second_source = false) {
1099 std::string dex_location = GetUsedDexLocation();
1100 std::string odex_location = GetUsedOatLocation();
1101
1102 Copy(use_second_source ? GetDexSrc2() : GetDexSrc1(), dex_location);
1103
1104 std::string error_msg;
1105 std::vector<std::string> extra_args;
1106 if (class_loader_context != nullptr) {
1107 extra_args.push_back(std::string("--class-loader-context=") + class_loader_context);
1108 }
1109 auto check_oat = [expected_classpath_key](const OatFile& oat_file) {
1110 ASSERT_TRUE(expected_classpath_key != nullptr);
1111 const char* classpath = oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
1112 ASSERT_TRUE(classpath != nullptr);
1113 ASSERT_STREQ(expected_classpath_key, classpath);
1114 };
1115
1116 GenerateOdexForTest(dex_location,
1117 odex_location,
1118 CompilerFilter::kQuicken,
1119 extra_args,
1120 expected_success,
1121 /*use_fd*/ false,
1122 check_oat);
1123 }
1124
1125 std::string GetUsedDexLocation() {
1126 return GetScratchDir() + "/Context.jar";
1127 }
1128
1129 std::string GetUsedOatLocation() {
1130 return GetOdexDir() + "/Context.odex";
1131 }
1132
Calin Juravle7b0648a2017-07-07 18:40:50 -07001133 const char* kEmptyClassPathKey = "PCL[]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001134};
1135
1136TEST_F(Dex2oatClassLoaderContextTest, InvalidContext) {
1137 RunTest("Invalid[]", /*expected_classpath_key*/ nullptr, /*expected_success*/ false);
1138}
1139
1140TEST_F(Dex2oatClassLoaderContextTest, EmptyContext) {
1141 RunTest("PCL[]", kEmptyClassPathKey, /*expected_success*/ true);
1142}
1143
1144TEST_F(Dex2oatClassLoaderContextTest, SpecialContext) {
1145 RunTest(OatFile::kSpecialSharedLibrary,
1146 OatFile::kSpecialSharedLibrary,
1147 /*expected_success*/ true);
1148}
1149
1150TEST_F(Dex2oatClassLoaderContextTest, ContextWithTheSourceDexFiles) {
1151 std::string context = "PCL[" + GetUsedDexLocation() + "]";
1152 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1153}
1154
1155TEST_F(Dex2oatClassLoaderContextTest, ContextWithOtherDexFiles) {
1156 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Nested");
Calin Juravle1ce70852017-06-28 10:59:03 -07001157
1158 std::string context = "PCL[" + dex_files[0]->GetLocation() + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -07001159 std::string expected_classpath_key = "PCL[" +
1160 dex_files[0]->GetLocation() + "*" + std::to_string(dex_files[0]->GetLocationChecksum()) + "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001161 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1162}
1163
1164TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFiles) {
1165 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
1166 Copy(GetStrippedDexSrc1(), stripped_classpath);
1167
1168 std::string context = "PCL[" + stripped_classpath + "]";
1169 // Expect an empty context because stripped dex files cannot be open.
Calin Juravle7b0648a2017-07-07 18:40:50 -07001170 RunTest(context.c_str(), kEmptyClassPathKey , /*expected_success*/ true);
Calin Juravle1ce70852017-06-28 10:59:03 -07001171}
1172
1173TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFilesBackedByOdex) {
1174 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
1175 std::string odex_for_classpath = GetOdexDir() + "/stripped_classpath.odex";
1176
1177 Copy(GetDexSrc1(), stripped_classpath);
1178
1179 GenerateOdexForTest(stripped_classpath,
1180 odex_for_classpath,
1181 CompilerFilter::kQuicken,
1182 {},
1183 true);
1184
1185 // Strip the dex file
1186 Copy(GetStrippedDexSrc1(), stripped_classpath);
1187
1188 std::string context = "PCL[" + stripped_classpath + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -07001189 std::string expected_classpath_key;
Calin Juravle1ce70852017-06-28 10:59:03 -07001190 {
1191 // Open the oat file to get the expected classpath.
Nicolas Geoffray29742602017-12-14 10:09:03 +00001192 OatFileAssistant oat_file_assistant(stripped_classpath.c_str(), kRuntimeISA, false, false);
Calin Juravle1ce70852017-06-28 10:59:03 -07001193 std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile());
1194 std::vector<std::unique_ptr<const DexFile>> oat_dex_files =
1195 OatFileAssistant::LoadDexFiles(*oat_file, stripped_classpath.c_str());
Calin Juravle7b0648a2017-07-07 18:40:50 -07001196 expected_classpath_key = "PCL[";
1197 for (size_t i = 0; i < oat_dex_files.size(); i++) {
1198 if (i > 0) {
1199 expected_classpath_key + ":";
1200 }
1201 expected_classpath_key += oat_dex_files[i]->GetLocation() + "*" +
1202 std::to_string(oat_dex_files[i]->GetLocationChecksum());
1203 }
1204 expected_classpath_key += "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001205 }
1206
1207 RunTest(context.c_str(),
Calin Juravle7b0648a2017-07-07 18:40:50 -07001208 expected_classpath_key.c_str(),
Calin Juravle1ce70852017-06-28 10:59:03 -07001209 /*expected_success*/ true,
1210 /*use_second_source*/ true);
1211}
1212
1213TEST_F(Dex2oatClassLoaderContextTest, ContextWithNotExistentDexFiles) {
1214 std::string context = "PCL[does_not_exists.dex]";
1215 // Expect an empty context because stripped dex files cannot be open.
1216 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1217}
1218
Calin Juravlec79470d2017-07-12 17:37:42 -07001219TEST_F(Dex2oatClassLoaderContextTest, ChainContext) {
1220 std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1221 std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1222
1223 std::string context = "PCL[" + GetTestDexFileName("Nested") + "];" +
1224 "DLC[" + GetTestDexFileName("MultiDex") + "]";
1225 std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "];" +
1226 "DLC[" + CreateClassPathWithChecksums(dex_files2) + "]";
1227
1228 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1229}
1230
Mathieu Chartier9e050df2017-08-09 10:05:47 -07001231class Dex2oatDeterminism : public Dex2oatTest {};
1232
1233TEST_F(Dex2oatDeterminism, UnloadCompile) {
1234 if (!kUseReadBarrier &&
1235 gc::kCollectorTypeDefault != gc::kCollectorTypeCMS &&
1236 gc::kCollectorTypeDefault != gc::kCollectorTypeMS) {
1237 LOG(INFO) << "Test requires determinism support.";
1238 return;
1239 }
1240 Runtime* const runtime = Runtime::Current();
1241 std::string out_dir = GetScratchDir();
1242 const std::string base_oat_name = out_dir + "/base.oat";
1243 const std::string base_vdex_name = out_dir + "/base.vdex";
1244 const std::string unload_oat_name = out_dir + "/unload.oat";
1245 const std::string unload_vdex_name = out_dir + "/unload.vdex";
1246 const std::string no_unload_oat_name = out_dir + "/nounload.oat";
1247 const std::string no_unload_vdex_name = out_dir + "/nounload.vdex";
1248 const std::string app_image_name = out_dir + "/unload.art";
1249 std::string error_msg;
1250 const std::vector<gc::space::ImageSpace*>& spaces = runtime->GetHeap()->GetBootImageSpaces();
1251 ASSERT_GT(spaces.size(), 0u);
1252 const std::string image_location = spaces[0]->GetImageLocation();
1253 // Without passing in an app image, it will unload in between compilations.
1254 const int res = GenerateOdexForTestWithStatus(
1255 GetLibCoreDexFileNames(),
1256 base_oat_name,
1257 CompilerFilter::Filter::kQuicken,
1258 &error_msg,
1259 {"--force-determinism", "--avoid-storing-invocation"});
1260 EXPECT_EQ(res, 0);
1261 Copy(base_oat_name, unload_oat_name);
1262 Copy(base_vdex_name, unload_vdex_name);
1263 std::unique_ptr<File> unload_oat(OS::OpenFileForReading(unload_oat_name.c_str()));
1264 std::unique_ptr<File> unload_vdex(OS::OpenFileForReading(unload_vdex_name.c_str()));
1265 ASSERT_TRUE(unload_oat != nullptr);
1266 ASSERT_TRUE(unload_vdex != nullptr);
1267 EXPECT_GT(unload_oat->GetLength(), 0u);
1268 EXPECT_GT(unload_vdex->GetLength(), 0u);
1269 // Regenerate with an app image to disable the dex2oat unloading and verify that the output is
1270 // the same.
1271 const int res2 = GenerateOdexForTestWithStatus(
1272 GetLibCoreDexFileNames(),
1273 base_oat_name,
1274 CompilerFilter::Filter::kQuicken,
1275 &error_msg,
1276 {"--force-determinism", "--avoid-storing-invocation", "--app-image-file=" + app_image_name});
1277 EXPECT_EQ(res2, 0);
1278 Copy(base_oat_name, no_unload_oat_name);
1279 Copy(base_vdex_name, no_unload_vdex_name);
1280 std::unique_ptr<File> no_unload_oat(OS::OpenFileForReading(no_unload_oat_name.c_str()));
1281 std::unique_ptr<File> no_unload_vdex(OS::OpenFileForReading(no_unload_vdex_name.c_str()));
1282 ASSERT_TRUE(no_unload_oat != nullptr);
1283 ASSERT_TRUE(no_unload_vdex != nullptr);
1284 EXPECT_GT(no_unload_oat->GetLength(), 0u);
1285 EXPECT_GT(no_unload_vdex->GetLength(), 0u);
1286 // Verify that both of the files are the same (odex and vdex).
1287 EXPECT_EQ(unload_oat->GetLength(), no_unload_oat->GetLength());
1288 EXPECT_EQ(unload_vdex->GetLength(), no_unload_vdex->GetLength());
1289 EXPECT_EQ(unload_oat->Compare(no_unload_oat.get()), 0)
1290 << unload_oat_name << " " << no_unload_oat_name;
1291 EXPECT_EQ(unload_vdex->Compare(no_unload_vdex.get()), 0)
1292 << unload_vdex_name << " " << no_unload_vdex_name;
1293 // App image file.
1294 std::unique_ptr<File> app_image_file(OS::OpenFileForReading(app_image_name.c_str()));
1295 ASSERT_TRUE(app_image_file != nullptr);
1296 EXPECT_GT(app_image_file->GetLength(), 0u);
1297}
1298
Mathieu Chartier120aa282017-08-05 16:03:03 -07001299// Test that dexlayout section info is correctly written to the oat file for profile based
1300// compilation.
1301TEST_F(Dex2oatTest, LayoutSections) {
1302 using Hotness = ProfileCompilationInfo::MethodHotness;
1303 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1304 ScratchFile profile_file;
1305 // We can only layout method indices with code items, figure out which ones have this property
1306 // first.
1307 std::vector<uint16_t> methods;
1308 {
1309 const DexFile::TypeId* type_id = dex->FindTypeId("LManyMethods;");
1310 dex::TypeIndex type_idx = dex->GetIndexForTypeId(*type_id);
1311 const DexFile::ClassDef* class_def = dex->FindClassDef(type_idx);
1312 ClassDataItemIterator it(*dex, dex->GetClassData(*class_def));
1313 it.SkipAllFields();
1314 std::set<size_t> code_item_offsets;
Mathieu Chartierb7c273c2017-11-10 18:07:56 -08001315 for (; it.HasNextMethod(); it.Next()) {
Mathieu Chartier120aa282017-08-05 16:03:03 -07001316 const uint16_t method_idx = it.GetMemberIndex();
1317 const size_t code_item_offset = it.GetMethodCodeItemOffset();
1318 if (code_item_offsets.insert(code_item_offset).second) {
1319 // Unique code item, add the method index.
1320 methods.push_back(method_idx);
1321 }
1322 }
1323 DCHECK(!it.HasNext());
1324 }
1325 ASSERT_GE(methods.size(), 8u);
1326 std::vector<uint16_t> hot_methods = {methods[1], methods[3], methods[5]};
1327 std::vector<uint16_t> startup_methods = {methods[1], methods[2], methods[7]};
1328 std::vector<uint16_t> post_methods = {methods[0], methods[2], methods[6]};
1329 // Here, we build the profile from the method lists.
1330 ProfileCompilationInfo info;
1331 info.AddMethodsForDex(
1332 static_cast<Hotness::Flag>(Hotness::kFlagHot | Hotness::kFlagStartup),
1333 dex.get(),
1334 hot_methods.begin(),
1335 hot_methods.end());
1336 info.AddMethodsForDex(
1337 Hotness::kFlagStartup,
1338 dex.get(),
1339 startup_methods.begin(),
1340 startup_methods.end());
1341 info.AddMethodsForDex(
1342 Hotness::kFlagPostStartup,
1343 dex.get(),
1344 post_methods.begin(),
1345 post_methods.end());
1346 for (uint16_t id : hot_methods) {
1347 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsHot());
1348 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsStartup());
1349 }
1350 for (uint16_t id : startup_methods) {
1351 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsStartup());
1352 }
1353 for (uint16_t id : post_methods) {
1354 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsPostStartup());
1355 }
1356 // Save the profile since we want to use it with dex2oat to produce an oat file.
1357 ASSERT_TRUE(info.Save(profile_file.GetFd()));
1358 // Generate a profile based odex.
1359 const std::string dir = GetScratchDir();
1360 const std::string oat_filename = dir + "/base.oat";
1361 const std::string vdex_filename = dir + "/base.vdex";
1362 std::string error_msg;
1363 const int res = GenerateOdexForTestWithStatus(
1364 {dex->GetLocation()},
1365 oat_filename,
1366 CompilerFilter::Filter::kQuicken,
1367 &error_msg,
1368 {"--profile-file=" + profile_file.GetFilename()});
1369 EXPECT_EQ(res, 0);
1370
1371 // Open our generated oat file.
Nicolas Geoffray30025092018-04-19 14:43:29 +01001372 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1373 oat_filename.c_str(),
Mathieu Chartier120aa282017-08-05 16:03:03 -07001374 oat_filename.c_str(),
1375 nullptr,
1376 nullptr,
1377 false,
1378 /*low_4gb*/false,
1379 dex->GetLocation().c_str(),
1380 &error_msg));
1381 ASSERT_TRUE(odex_file != nullptr);
1382 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1383 ASSERT_EQ(oat_dex_files.size(), 1u);
1384 // Check that the code sections match what we expect.
1385 for (const OatDexFile* oat_dex : oat_dex_files) {
1386 const DexLayoutSections* const sections = oat_dex->GetDexLayoutSections();
1387 // Testing of logging the sections.
1388 ASSERT_TRUE(sections != nullptr);
1389 LOG(INFO) << *sections;
1390
1391 // Load the sections into temporary variables for convenience.
1392 const DexLayoutSection& code_section =
1393 sections->sections_[static_cast<size_t>(DexLayoutSections::SectionType::kSectionTypeCode)];
1394 const DexLayoutSection::Subsection& section_hot_code =
1395 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeHot)];
1396 const DexLayoutSection::Subsection& section_sometimes_used =
1397 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeSometimesUsed)];
1398 const DexLayoutSection::Subsection& section_startup_only =
1399 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeStartupOnly)];
1400 const DexLayoutSection::Subsection& section_unused =
1401 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeUnused)];
1402
1403 // All the sections should be non-empty.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001404 EXPECT_GT(section_hot_code.Size(), 0u);
1405 EXPECT_GT(section_sometimes_used.Size(), 0u);
1406 EXPECT_GT(section_startup_only.Size(), 0u);
1407 EXPECT_GT(section_unused.Size(), 0u);
Mathieu Chartier120aa282017-08-05 16:03:03 -07001408
1409 // Open the dex file since we need to peek at the code items to verify the layout matches what
1410 // we expect.
1411 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1412 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1413 const DexFile::TypeId* type_id = dex_file->FindTypeId("LManyMethods;");
1414 ASSERT_TRUE(type_id != nullptr);
1415 dex::TypeIndex type_idx = dex_file->GetIndexForTypeId(*type_id);
1416 const DexFile::ClassDef* class_def = dex_file->FindClassDef(type_idx);
1417 ASSERT_TRUE(class_def != nullptr);
1418
1419 // Count how many code items are for each category, there should be at least one per category.
1420 size_t hot_count = 0;
1421 size_t post_startup_count = 0;
1422 size_t startup_count = 0;
1423 size_t unused_count = 0;
1424 // Visit all of the methdos of the main class and cross reference the method indices to their
1425 // corresponding code item offsets to verify the layout.
1426 ClassDataItemIterator it(*dex_file, dex_file->GetClassData(*class_def));
1427 it.SkipAllFields();
Mathieu Chartierb7c273c2017-11-10 18:07:56 -08001428 for (; it.HasNextMethod(); it.Next()) {
Mathieu Chartier120aa282017-08-05 16:03:03 -07001429 const size_t method_idx = it.GetMemberIndex();
1430 const size_t code_item_offset = it.GetMethodCodeItemOffset();
1431 const bool is_hot = ContainsElement(hot_methods, method_idx);
1432 const bool is_startup = ContainsElement(startup_methods, method_idx);
1433 const bool is_post_startup = ContainsElement(post_methods, method_idx);
1434 if (is_hot) {
1435 // Hot is highest precedence, check that the hot methods are in the hot section.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001436 EXPECT_TRUE(section_hot_code.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001437 ++hot_count;
1438 } else if (is_post_startup) {
1439 // Post startup is sometimes used section.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001440 EXPECT_TRUE(section_sometimes_used.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001441 ++post_startup_count;
1442 } else if (is_startup) {
1443 // Startup at this point means not hot or post startup, these must be startup only then.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001444 EXPECT_TRUE(section_startup_only.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001445 ++startup_count;
1446 } else {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001447 if (section_unused.Contains(code_item_offset)) {
Alan Leung9595fd32017-10-17 17:08:19 -07001448 // If no flags are set, the method should be unused ...
1449 ++unused_count;
1450 } else {
1451 // or this method is part of the last code item and the end is 4 byte aligned.
1452 ClassDataItemIterator it2(*dex_file, dex_file->GetClassData(*class_def));
1453 it2.SkipAllFields();
Mathieu Chartierb7c273c2017-11-10 18:07:56 -08001454 for (; it2.HasNextMethod(); it2.Next()) {
Alan Leung9595fd32017-10-17 17:08:19 -07001455 EXPECT_LE(it2.GetMethodCodeItemOffset(), code_item_offset);
1456 }
1457 uint32_t code_item_size = dex_file->FindCodeItemOffset(*class_def, method_idx);
1458 EXPECT_EQ((code_item_offset + code_item_size) % 4, 0u);
1459 }
Mathieu Chartier120aa282017-08-05 16:03:03 -07001460 }
1461 }
1462 DCHECK(!it.HasNext());
1463 EXPECT_GT(hot_count, 0u);
1464 EXPECT_GT(post_startup_count, 0u);
1465 EXPECT_GT(startup_count, 0u);
1466 EXPECT_GT(unused_count, 0u);
1467 }
1468}
1469
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001470// Test that generating compact dex works.
1471TEST_F(Dex2oatTest, GenerateCompactDex) {
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001472 // Generate a compact dex based odex.
1473 const std::string dir = GetScratchDir();
1474 const std::string oat_filename = dir + "/base.oat";
1475 const std::string vdex_filename = dir + "/base.vdex";
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001476 const std::string dex_location = GetTestDexFileName("MultiDex");
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001477 std::string error_msg;
1478 const int res = GenerateOdexForTestWithStatus(
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001479 { dex_location },
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001480 oat_filename,
1481 CompilerFilter::Filter::kQuicken,
1482 &error_msg,
1483 {"--compact-dex-level=fast"});
1484 EXPECT_EQ(res, 0);
1485 // Open our generated oat file.
Nicolas Geoffray30025092018-04-19 14:43:29 +01001486 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1487 oat_filename.c_str(),
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001488 oat_filename.c_str(),
1489 nullptr,
1490 nullptr,
1491 false,
1492 /*low_4gb*/false,
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001493 dex_location.c_str(),
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001494 &error_msg));
1495 ASSERT_TRUE(odex_file != nullptr);
1496 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001497 ASSERT_GT(oat_dex_files.size(), 1u);
1498 // Check that each dex is a compact dex file.
1499 std::vector<std::unique_ptr<const CompactDexFile>> compact_dex_files;
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001500 for (const OatDexFile* oat_dex : oat_dex_files) {
1501 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1502 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1503 ASSERT_TRUE(dex_file->IsCompactDexFile());
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001504 compact_dex_files.push_back(
1505 std::unique_ptr<const CompactDexFile>(dex_file.release()->AsCompactDexFile()));
1506 }
1507 for (const std::unique_ptr<const CompactDexFile>& dex_file : compact_dex_files) {
1508 // Test that every code item is in the owned section.
1509 const CompactDexFile::Header& header = dex_file->GetHeader();
1510 EXPECT_LE(header.OwnedDataBegin(), header.OwnedDataEnd());
1511 EXPECT_LE(header.OwnedDataBegin(), header.data_size_);
1512 EXPECT_LE(header.OwnedDataEnd(), header.data_size_);
1513 for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
1514 const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
1515 class_def.VisitMethods(dex_file.get(), [&](const ClassDataItemIterator& it) {
1516 if (it.GetMethodCodeItemOffset() != 0u) {
1517 ASSERT_GE(it.GetMethodCodeItemOffset(), header.OwnedDataBegin());
1518 ASSERT_LT(it.GetMethodCodeItemOffset(), header.OwnedDataEnd());
1519 }
1520 });
1521 }
1522 // Test that the owned sections don't overlap.
1523 for (const std::unique_ptr<const CompactDexFile>& other_dex : compact_dex_files) {
1524 if (dex_file != other_dex) {
1525 ASSERT_TRUE(
1526 (dex_file->GetHeader().OwnedDataBegin() >= other_dex->GetHeader().OwnedDataEnd()) ||
1527 (dex_file->GetHeader().OwnedDataEnd() <= other_dex->GetHeader().OwnedDataBegin()));
1528 }
1529 }
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001530 }
1531}
1532
Andreas Gampef39208f2017-10-19 15:06:59 -07001533class Dex2oatVerifierAbort : public Dex2oatTest {};
1534
1535TEST_F(Dex2oatVerifierAbort, HardFail) {
1536 // Use VerifierDeps as it has hard-failing classes.
1537 std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDeps"));
1538 std::string out_dir = GetScratchDir();
1539 const std::string base_oat_name = out_dir + "/base.oat";
1540 std::string error_msg;
1541 const int res_fail = GenerateOdexForTestWithStatus(
1542 {dex->GetLocation()},
1543 base_oat_name,
1544 CompilerFilter::Filter::kQuicken,
1545 &error_msg,
1546 {"--abort-on-hard-verifier-error"});
1547 EXPECT_NE(0, res_fail);
1548
1549 const int res_no_fail = GenerateOdexForTestWithStatus(
1550 {dex->GetLocation()},
1551 base_oat_name,
1552 CompilerFilter::Filter::kQuicken,
1553 &error_msg,
1554 {"--no-abort-on-hard-verifier-error"});
1555 EXPECT_EQ(0, res_no_fail);
1556}
1557
1558TEST_F(Dex2oatVerifierAbort, SoftFail) {
1559 // Use VerifierDepsMulti as it has hard-failing classes.
1560 std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDepsMulti"));
1561 std::string out_dir = GetScratchDir();
1562 const std::string base_oat_name = out_dir + "/base.oat";
1563 std::string error_msg;
1564 const int res_fail = GenerateOdexForTestWithStatus(
1565 {dex->GetLocation()},
1566 base_oat_name,
1567 CompilerFilter::Filter::kQuicken,
1568 &error_msg,
1569 {"--abort-on-soft-verifier-error"});
1570 EXPECT_NE(0, res_fail);
1571
1572 const int res_no_fail = GenerateOdexForTestWithStatus(
1573 {dex->GetLocation()},
1574 base_oat_name,
1575 CompilerFilter::Filter::kQuicken,
1576 &error_msg,
1577 {"--no-abort-on-soft-verifier-error"});
1578 EXPECT_EQ(0, res_no_fail);
1579}
1580
Andreas Gampecac31ad2017-11-06 20:01:17 -08001581class Dex2oatDedupeCode : public Dex2oatTest {};
1582
1583TEST_F(Dex2oatDedupeCode, DedupeTest) {
1584 // Use MyClassNatives. It has lots of native methods that will produce deduplicate-able code.
1585 std::unique_ptr<const DexFile> dex(OpenTestDexFile("MyClassNatives"));
1586 std::string out_dir = GetScratchDir();
1587 const std::string base_oat_name = out_dir + "/base.oat";
1588 size_t no_dedupe_size = 0;
1589 GenerateOdexForTest(dex->GetLocation(),
1590 base_oat_name,
1591 CompilerFilter::Filter::kSpeed,
1592 { "--deduplicate-code=false" },
1593 true, // expect_success
1594 false, // use_fd
1595 [&no_dedupe_size](const OatFile& o) {
1596 no_dedupe_size = o.Size();
1597 });
1598
1599 size_t dedupe_size = 0;
1600 GenerateOdexForTest(dex->GetLocation(),
1601 base_oat_name,
1602 CompilerFilter::Filter::kSpeed,
1603 { "--deduplicate-code=true" },
1604 true, // expect_success
1605 false, // use_fd
1606 [&dedupe_size](const OatFile& o) {
1607 dedupe_size = o.Size();
1608 });
1609
1610 EXPECT_LT(dedupe_size, no_dedupe_size);
1611}
1612
Nicolas Geoffrayf3075272018-01-08 12:41:19 +00001613TEST_F(Dex2oatTest, UncompressedTest) {
1614 std::unique_ptr<const DexFile> dex(OpenTestDexFile("MainUncompressed"));
1615 std::string out_dir = GetScratchDir();
1616 const std::string base_oat_name = out_dir + "/base.oat";
1617 GenerateOdexForTest(dex->GetLocation(),
1618 base_oat_name,
1619 CompilerFilter::Filter::kQuicken,
1620 { },
1621 true, // expect_success
1622 false, // use_fd
1623 [](const OatFile& o) {
1624 CHECK(!o.ContainsDexCode());
1625 });
1626}
1627
Mathieu Chartier700a9852018-02-06 18:27:38 -08001628TEST_F(Dex2oatTest, EmptyUncompressedDexTest) {
1629 std::string out_dir = GetScratchDir();
1630 const std::string base_oat_name = out_dir + "/base.oat";
1631 std::string error_msg;
1632 int status = GenerateOdexForTestWithStatus(
1633 { GetTestDexFileName("MainEmptyUncompressed") },
1634 base_oat_name,
1635 CompilerFilter::Filter::kQuicken,
1636 &error_msg,
1637 { },
1638 /*use_fd*/ false);
1639 // Expect to fail with code 1 and not SIGSEGV or SIGABRT.
1640 ASSERT_TRUE(WIFEXITED(status));
1641 ASSERT_EQ(WEXITSTATUS(status), 1) << error_msg;
1642}
1643
Mathieu Chartier05f90d12018-02-07 13:47:17 -08001644// Dex file that has duplicate methods have different code items and debug info.
1645static const char kDuplicateMethodInputDex[] =
1646 "ZGV4CjAzOQDEy8VPdj4qHpgPYFWtLCtOykfFP4kB8tGYDAAAcAAAAHhWNBIAAAAAAAAAANALAABI"
1647 "AAAAcAAAAA4AAACQAQAABQAAAMgBAAANAAAABAIAABkAAABsAgAABAAAADQDAADgCAAAuAMAADgI"
1648 "AABCCAAASggAAE8IAABcCAAAaggAAHkIAACICAAAlggAAKQIAACyCAAAwAgAAM4IAADcCAAA6ggA"
1649 "APgIAAD7CAAA/wgAABcJAAAuCQAARQkAAFQJAAB4CQAAmAkAALsJAADSCQAA5gkAAPoJAAAVCgAA"
1650 "KQoAADsKAABCCgAASgoAAFIKAABbCgAAZAoAAGwKAAB0CgAAfAoAAIQKAACMCgAAlAoAAJwKAACk"
1651 "CgAArQoAALcKAADACgAAwwoAAMcKAADcCgAA6QoAAPEKAAD3CgAA/QoAAAMLAAAJCwAAEAsAABcL"
1652 "AAAdCwAAIwsAACkLAAAvCwAANQsAADsLAABBCwAARwsAAE0LAABSCwAAWwsAAF4LAABoCwAAbwsA"
1653 "ABEAAAASAAAAEwAAABQAAAAVAAAAFgAAABcAAAAYAAAAGQAAABoAAAAbAAAAHAAAAC4AAAAwAAAA"
1654 "DwAAAAkAAAAAAAAAEAAAAAoAAACoBwAALgAAAAwAAAAAAAAALwAAAAwAAACoBwAALwAAAAwAAACw"
1655 "BwAAAgAJADUAAAACAAkANgAAAAIACQA3AAAAAgAJADgAAAACAAkAOQAAAAIACQA6AAAAAgAJADsA"
1656 "AAACAAkAPAAAAAIACQA9AAAAAgAJAD4AAAACAAkAPwAAAAIACQBAAAAACwAHAEIAAAAAAAIAAQAA"
1657 "AAAAAwAeAAAAAQACAAEAAAABAAMAHgAAAAIAAgAAAAAAAgACAAEAAAADAAIAAQAAAAMAAgAfAAAA"
1658 "AwACACAAAAADAAIAIQAAAAMAAgAiAAAAAwACACMAAAADAAIAJAAAAAMAAgAlAAAAAwACACYAAAAD"
1659 "AAIAJwAAAAMAAgAoAAAAAwACACkAAAADAAIAKgAAAAMABAA0AAAABwADAEMAAAAIAAIAAQAAAAoA"
1660 "AgABAAAACgABADIAAAAKAAAARQAAAAAAAAAAAAAACAAAAAAAAAAdAAAAaAcAALYHAAAAAAAAAQAA"
1661 "AAAAAAAIAAAAAAAAAB0AAAB4BwAAxAcAAAAAAAACAAAAAAAAAAgAAAAAAAAAHQAAAIgHAADSBwAA"
1662 "AAAAAAMAAAAAAAAACAAAAAAAAAAdAAAAmAcAAPoHAAAAAAAAAAAAAAEAAAAAAAAArAYAADEAAAAa"
1663 "AAMAaQAAABoABABpAAEAGgAHAGkABAAaAAgAaQAFABoACQBpAAYAGgAKAGkABwAaAAsAaQAIABoA"
1664 "DABpAAkAGgANAGkACgAaAA4AaQALABoABQBpAAIAGgAGAGkAAwAOAAAAAQABAAEAAACSBgAABAAA"
1665 "AHAQFQAAAA4ABAABAAIAAACWBgAAFwAAAGIADAAiAQoAcBAWAAEAGgICAG4gFwAhAG4gFwAxAG4Q"
1666 "GAABAAwBbiAUABAADgAAAAEAAQABAAAAngYAAAQAAABwEBUAAAAOAAIAAQACAAAAogYAAAYAAABi"
1667 "AAwAbiAUABAADgABAAEAAQAAAKgGAAAEAAAAcBAVAAAADgABAAEAAQAAALsGAAAEAAAAcBAVAAAA"
1668 "DgABAAAAAQAAAL8GAAAGAAAAYgAAAHEQAwAAAA4AAQAAAAEAAADEBgAABgAAAGIAAQBxEAMAAAAO"
1669 "AAEAAAABAAAA8QYAAAYAAABiAAIAcRABAAAADgABAAAAAQAAAPYGAAAGAAAAYgADAHEQAwAAAA4A"
1670 "AQAAAAEAAADJBgAABgAAAGIABABxEAMAAAAOAAEAAAABAAAAzgYAAAYAAABiAAEAcRADAAAADgAB"
1671 "AAAAAQAAANMGAAAGAAAAYgAGAHEQAwAAAA4AAQAAAAEAAADYBgAABgAAAGIABwBxEAMAAAAOAAEA"
1672 "AAABAAAA3QYAAAYAAABiAAgAcRABAAAADgABAAAAAQAAAOIGAAAGAAAAYgAJAHEQAwAAAA4AAQAA"
1673 "AAEAAADnBgAABgAAAGIACgBxEAMAAAAOAAEAAAABAAAA7AYAAAYAAABiAAsAcRABAAAADgABAAEA"
1674 "AAAAAPsGAAAlAAAAcQAHAAAAcQAIAAAAcQALAAAAcQAMAAAAcQANAAAAcQAOAAAAcQAPAAAAcQAQ"
1675 "AAAAcQARAAAAcQASAAAAcQAJAAAAcQAKAAAADgAnAA4AKQFFDgEWDwAhAA4AIwFFDloAEgAOABMA"
1676 "DktLS0tLS0tLS0tLABEADgAuAA5aADIADloANgAOWgA6AA5aAD4ADloAQgAOWgBGAA5aAEoADloA"
1677 "TgAOWgBSAA5aAFYADloAWgAOWgBeATQOPDw8PDw8PDw8PDw8AAIEAUYYAwIFAjEECEEXLAIFAjEE"
1678 "CEEXKwIFAjEECEEXLQIGAUYcAxgAGAEYAgAAAAIAAAAMBwAAEgcAAAIAAAAMBwAAGwcAAAIAAAAM"
1679 "BwAAJAcAAAEAAAAtBwAAPAcAAAAAAAAAAAAAAAAAAEgHAAAAAAAAAAAAAAAAAABUBwAAAAAAAAAA"
1680 "AAAAAAAAYAcAAAAAAAAAAAAAAAAAAAEAAAAJAAAAAQAAAA0AAAACAACAgASsCAEIxAgAAAIAAoCA"
1681 "BIQJAQicCQwAAgAACQEJAQkBCQEJAQkBCQEJAQkBCQEJAQkEiIAEuAcBgIAEuAkAAA4ABoCABNAJ"
1682 "AQnoCQAJhAoACaAKAAm8CgAJ2AoACfQKAAmQCwAJrAsACcgLAAnkCwAJgAwACZwMAAm4DAg8Y2xp"
1683 "bml0PgAGPGluaXQ+AANBQUEAC0hlbGxvIFdvcmxkAAxIZWxsbyBXb3JsZDEADUhlbGxvIFdvcmxk"
1684 "MTAADUhlbGxvIFdvcmxkMTEADEhlbGxvIFdvcmxkMgAMSGVsbG8gV29ybGQzAAxIZWxsbyBXb3Js"
1685 "ZDQADEhlbGxvIFdvcmxkNQAMSGVsbG8gV29ybGQ2AAxIZWxsbyBXb3JsZDcADEhlbGxvIFdvcmxk"
1686 "OAAMSGVsbG8gV29ybGQ5AAFMAAJMTAAWTE1hbnlNZXRob2RzJFByaW50ZXIyOwAVTE1hbnlNZXRo"
1687 "b2RzJFByaW50ZXI7ABVMTWFueU1ldGhvZHMkU3RyaW5nczsADUxNYW55TWV0aG9kczsAIkxkYWx2"
1688 "aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNs"
1689 "YXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNzZXM7ABVMamF2YS9pby9QcmludFN0"
1690 "cmVhbTsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABlMamF2YS9sYW5n"
1691 "L1N0cmluZ0J1aWxkZXI7ABJMamF2YS9sYW5nL1N5c3RlbTsAEE1hbnlNZXRob2RzLmphdmEABVBy"
1692 "aW50AAZQcmludDAABlByaW50MQAHUHJpbnQxMAAHUHJpbnQxMQAGUHJpbnQyAAZQcmludDMABlBy"
1693 "aW50NAAGUHJpbnQ1AAZQcmludDYABlByaW50NwAGUHJpbnQ4AAZQcmludDkAB1ByaW50ZXIACFBy"
1694 "aW50ZXIyAAdTdHJpbmdzAAFWAAJWTAATW0xqYXZhL2xhbmcvU3RyaW5nOwALYWNjZXNzRmxhZ3MA"
1695 "BmFwcGVuZAAEYXJncwAEbWFpbgAEbXNnMAAEbXNnMQAFbXNnMTAABW1zZzExAARtc2cyAARtc2cz"
1696 "AARtc2c0AARtc2c1AARtc2c2AARtc2c3AARtc2c4AARtc2c5AARuYW1lAANvdXQAB3ByaW50bG4A"
1697 "AXMACHRvU3RyaW5nAAV2YWx1ZQBffn5EOHsibWluLWFwaSI6MTAwMDAsInNoYS0xIjoiZmViODZj"
1698 "MDA2ZWZhY2YxZDc5ODRiODVlMTc5MGZlZjdhNzY3YWViYyIsInZlcnNpb24iOiJ2MS4xLjUtZGV2"
1699 "In0AEAAAAAAAAAABAAAAAAAAAAEAAABIAAAAcAAAAAIAAAAOAAAAkAEAAAMAAAAFAAAAyAEAAAQA"
1700 "AAANAAAABAIAAAUAAAAZAAAAbAIAAAYAAAAEAAAANAMAAAEgAAAUAAAAuAMAAAMgAAAUAAAAkgYA"
1701 "AAQgAAAFAAAADAcAAAMQAAAEAAAAOQcAAAYgAAAEAAAAaAcAAAEQAAACAAAAqAcAAAAgAAAEAAAA"
1702 "tgcAAAIgAABIAAAAOAgAAAAQAAABAAAA0AsAAAAAAAA=";
1703
1704static void WriteBase64ToFile(const char* base64, File* file) {
1705 // Decode base64.
1706 CHECK(base64 != nullptr);
1707 size_t length;
1708 std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
1709 CHECK(bytes != nullptr);
1710 if (!file->WriteFully(bytes.get(), length)) {
1711 PLOG(FATAL) << "Failed to write base64 as file";
1712 }
1713}
1714
1715TEST_F(Dex2oatTest, CompactDexGenerationFailure) {
1716 ScratchFile temp_dex;
1717 WriteBase64ToFile(kDuplicateMethodInputDex, temp_dex.GetFile());
1718 std::string out_dir = GetScratchDir();
1719 const std::string oat_filename = out_dir + "/base.oat";
1720 // The dex won't pass the method verifier, only use the verify filter.
1721 GenerateOdexForTest(temp_dex.GetFilename(),
1722 oat_filename,
1723 CompilerFilter::Filter::kVerify,
1724 { },
1725 true, // expect_success
1726 false, // use_fd
1727 [](const OatFile& o) {
1728 CHECK(o.ContainsDexCode());
1729 });
1730 // Open our generated oat file.
1731 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01001732 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1733 oat_filename.c_str(),
Mathieu Chartier05f90d12018-02-07 13:47:17 -08001734 oat_filename.c_str(),
1735 nullptr,
1736 nullptr,
1737 false,
1738 /*low_4gb*/false,
1739 temp_dex.GetFilename().c_str(),
1740 &error_msg));
1741 ASSERT_TRUE(odex_file != nullptr);
1742 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1743 ASSERT_EQ(oat_dex_files.size(), 1u);
1744 // The dexes should have failed to convert to compact dex.
1745 for (const OatDexFile* oat_dex : oat_dex_files) {
1746 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1747 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1748 ASSERT_TRUE(!dex_file->IsCompactDexFile());
1749 }
1750}
1751
Mathieu Chartiercda83be2018-03-01 23:55:55 -08001752TEST_F(Dex2oatTest, CompactDexGenerationFailureMultiDex) {
1753 // Create a multidex file with only one dex that gets rejected for cdex conversion.
1754 ScratchFile apk_file;
1755 {
1756 FILE* file = fdopen(apk_file.GetFd(), "w+b");
1757 ZipWriter writer(file);
1758 // Add vdex to zip.
1759 writer.StartEntry("classes.dex", ZipWriter::kCompress);
1760 size_t length = 0u;
1761 std::unique_ptr<uint8_t[]> bytes(DecodeBase64(kDuplicateMethodInputDex, &length));
1762 ASSERT_GE(writer.WriteBytes(&bytes[0], length), 0);
1763 writer.FinishEntry();
1764 writer.StartEntry("classes2.dex", ZipWriter::kCompress);
1765 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1766 ASSERT_GE(writer.WriteBytes(dex->Begin(), dex->Size()), 0);
1767 writer.FinishEntry();
1768 writer.Finish();
1769 ASSERT_EQ(apk_file.GetFile()->Flush(), 0);
1770 }
Andreas Gampebc802de2018-06-20 17:24:11 -07001771 const std::string& dex_location = apk_file.GetFilename();
Mathieu Chartiercda83be2018-03-01 23:55:55 -08001772 const std::string odex_location = GetOdexDir() + "/output.odex";
1773 GenerateOdexForTest(dex_location,
1774 odex_location,
1775 CompilerFilter::kQuicken,
1776 { "--compact-dex-level=fast" },
1777 true);
1778}
1779
Andreas Gampe25419b52018-02-08 21:30:26 -08001780TEST_F(Dex2oatTest, StderrLoggerOutput) {
1781 std::string dex_location = GetScratchDir() + "/Dex2OatStderrLoggerTest.jar";
1782 std::string odex_location = GetOdexDir() + "/Dex2OatStderrLoggerTest.odex";
1783
1784 // Test file doesn't matter.
1785 Copy(GetDexSrc1(), dex_location);
1786
1787 GenerateOdexForTest(dex_location,
1788 odex_location,
1789 CompilerFilter::kQuicken,
1790 { "--runtime-arg", "-Xuse-stderr-logger" },
1791 true);
1792 // Look for some random part of dex2oat logging. With the stderr logger this should be captured,
1793 // even on device.
1794 EXPECT_NE(std::string::npos, output_.find("dex2oat took"));
1795}
1796
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001797TEST_F(Dex2oatTest, VerifyCompilationReason) {
1798 std::string dex_location = GetScratchDir() + "/Dex2OatCompilationReason.jar";
1799 std::string odex_location = GetOdexDir() + "/Dex2OatCompilationReason.odex";
1800
1801 // Test file doesn't matter.
1802 Copy(GetDexSrc1(), dex_location);
1803
1804 GenerateOdexForTest(dex_location,
1805 odex_location,
1806 CompilerFilter::kVerify,
1807 { "--compilation-reason=install" },
1808 true);
1809 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01001810 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1811 odex_location.c_str(),
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001812 odex_location.c_str(),
1813 nullptr,
1814 nullptr,
1815 false,
1816 /*low_4gb*/false,
1817 dex_location.c_str(),
1818 &error_msg));
1819 ASSERT_TRUE(odex_file != nullptr);
1820 ASSERT_STREQ("install", odex_file->GetCompilationReason());
1821}
1822
1823TEST_F(Dex2oatTest, VerifyNoCompilationReason) {
1824 std::string dex_location = GetScratchDir() + "/Dex2OatNoCompilationReason.jar";
1825 std::string odex_location = GetOdexDir() + "/Dex2OatNoCompilationReason.odex";
1826
1827 // Test file doesn't matter.
1828 Copy(GetDexSrc1(), dex_location);
1829
1830 GenerateOdexForTest(dex_location,
1831 odex_location,
1832 CompilerFilter::kVerify,
1833 {},
1834 true);
1835 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01001836 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1837 odex_location.c_str(),
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001838 odex_location.c_str(),
1839 nullptr,
1840 nullptr,
1841 false,
1842 /*low_4gb*/false,
1843 dex_location.c_str(),
1844 &error_msg));
1845 ASSERT_TRUE(odex_file != nullptr);
1846 ASSERT_EQ(nullptr, odex_file->GetCompilationReason());
1847}
1848
Mathieu Chartier792111c2018-02-15 13:02:15 -08001849TEST_F(Dex2oatTest, DontExtract) {
1850 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1851 std::string error_msg;
1852 const std::string out_dir = GetScratchDir();
1853 const std::string dex_location = dex->GetLocation();
1854 const std::string odex_location = out_dir + "/base.oat";
1855 const std::string vdex_location = out_dir + "/base.vdex";
1856 GenerateOdexForTest(dex_location,
1857 odex_location,
1858 CompilerFilter::Filter::kVerify,
1859 { "--copy-dex-files=false" },
1860 true, // expect_success
1861 false, // use_fd
1862 [](const OatFile&) {
1863 });
1864 {
1865 // Check the vdex doesn't have dex.
1866 std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location.c_str(),
1867 /*writable*/ false,
1868 /*low_4gb*/ false,
1869 /*unquicken*/ false,
1870 &error_msg));
1871 ASSERT_TRUE(vdex != nullptr);
Nicolas Geoffray3a293552018-03-02 10:52:16 +00001872 EXPECT_FALSE(vdex->HasDexSection()) << output_;
Mathieu Chartier792111c2018-02-15 13:02:15 -08001873 }
Nicolas Geoffray30025092018-04-19 14:43:29 +01001874 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1875 odex_location.c_str(),
Mathieu Chartier792111c2018-02-15 13:02:15 -08001876 odex_location.c_str(),
1877 nullptr,
1878 nullptr,
1879 false,
1880 /*low_4gb*/ false,
1881 dex_location.c_str(),
1882 &error_msg));
1883 ASSERT_TRUE(odex_file != nullptr) << dex_location;
1884 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1885 ASSERT_EQ(oat_dex_files.size(), 1u);
1886 // Verify that the oat file can still open the dex files.
1887 for (const OatDexFile* oat_dex : oat_dex_files) {
1888 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1889 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1890 }
1891 // Create a dm file and use it to verify.
1892 // Add produced artifacts to a zip file that doesn't contain the classes.dex.
1893 ScratchFile dm_file;
1894 {
1895 std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_location.c_str()));
1896 ASSERT_TRUE(vdex_file != nullptr);
1897 ASSERT_GT(vdex_file->GetLength(), 0u);
1898 FILE* file = fdopen(dm_file.GetFd(), "w+b");
1899 ZipWriter writer(file);
1900 auto write_all_bytes = [&](File* file) {
1901 std::unique_ptr<uint8_t[]> bytes(new uint8_t[file->GetLength()]);
1902 ASSERT_TRUE(file->ReadFully(&bytes[0], file->GetLength()));
1903 ASSERT_GE(writer.WriteBytes(&bytes[0], file->GetLength()), 0);
1904 };
1905 // Add vdex to zip.
1906 writer.StartEntry(VdexFile::kVdexNameInDmFile, ZipWriter::kCompress);
1907 write_all_bytes(vdex_file.get());
1908 writer.FinishEntry();
1909 writer.Finish();
1910 ASSERT_EQ(dm_file.GetFile()->Flush(), 0);
1911 }
1912
Mathieu Chartier2eabc612018-05-25 14:31:16 -07001913 auto generate_and_check = [&](CompilerFilter::Filter filter) {
1914 GenerateOdexForTest(dex_location,
1915 odex_location,
1916 filter,
1917 { "--dump-timings",
1918 "--dm-file=" + dm_file.GetFilename(),
1919 // Pass -Xuse-stderr-logger have dex2oat output in output_ on target.
1920 "--runtime-arg",
1921 "-Xuse-stderr-logger" },
1922 true, // expect_success
1923 false, // use_fd
1924 [](const OatFile& o) {
1925 CHECK(o.ContainsDexCode());
1926 });
1927 // Check the output for "Fast verify", this is printed from --dump-timings.
1928 std::istringstream iss(output_);
1929 std::string line;
1930 bool found_fast_verify = false;
1931 const std::string kFastVerifyString = "Fast Verify";
1932 while (std::getline(iss, line) && !found_fast_verify) {
1933 found_fast_verify = found_fast_verify || line.find(kFastVerifyString) != std::string::npos;
1934 }
1935 EXPECT_TRUE(found_fast_verify) << "Expected to find " << kFastVerifyString << "\n" << output_;
1936 };
1937
Mathieu Chartier792111c2018-02-15 13:02:15 -08001938 // Generate a quickened dex by using the input dm file to verify.
Mathieu Chartier2eabc612018-05-25 14:31:16 -07001939 generate_and_check(CompilerFilter::Filter::kQuicken);
1940 // Use verify compiler filter to sanity check that FastVerify works for that filter too.
1941 generate_and_check(CompilerFilter::Filter::kVerify);
Mathieu Chartier792111c2018-02-15 13:02:15 -08001942}
1943
Mathieu Chartier2daa1342018-02-20 16:19:28 -08001944// Test that dex files with quickened opcodes aren't dequickened.
1945TEST_F(Dex2oatTest, QuickenedInput) {
1946 std::string error_msg;
1947 ScratchFile temp_dex;
1948 MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [] (DexFile* dex) {
1949 bool mutated_successfully = false;
1950 // Change the dex instructions to make an opcode that spans past the end of the code item.
1951 for (size_t i = 0; i < dex->NumClassDefs(); ++i) {
1952 const DexFile::ClassDef& def = dex->GetClassDef(i);
1953 const uint8_t* data = dex->GetClassData(def);
1954 if (data == nullptr) {
1955 continue;
1956 }
1957 ClassDataItemIterator it(*dex, data);
1958 it.SkipAllFields();
1959 while (it.HasNextMethod()) {
1960 DexFile::CodeItem* item = const_cast<DexFile::CodeItem*>(it.GetMethodCodeItem());
1961 if (item != nullptr) {
1962 CodeItemInstructionAccessor instructions(*dex, item);
1963 // Make a quickened instruction that doesn't run past the end of the code item.
1964 if (instructions.InsnsSizeInCodeUnits() > 2) {
1965 const_cast<Instruction&>(instructions.InstructionAt(0)).SetOpcode(
1966 Instruction::IGET_BYTE_QUICK);
1967 mutated_successfully = true;
1968 }
1969 }
1970 it.Next();
1971 }
1972 }
1973 CHECK(mutated_successfully)
1974 << "Failed to find candidate code item with only one code unit in last instruction.";
1975 });
1976
Andreas Gampebc802de2018-06-20 17:24:11 -07001977 const std::string& dex_location = temp_dex.GetFilename();
Mathieu Chartier2daa1342018-02-20 16:19:28 -08001978 std::string odex_location = GetOdexDir() + "/quickened.odex";
1979 std::string vdex_location = GetOdexDir() + "/quickened.vdex";
1980 std::unique_ptr<File> vdex_output(OS::CreateEmptyFile(vdex_location.c_str()));
1981 // Quicken the dex
1982 {
1983 std::string input_vdex = "--input-vdex-fd=-1";
1984 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_output->Fd());
1985 GenerateOdexForTest(dex_location,
1986 odex_location,
1987 CompilerFilter::kQuicken,
1988 // Disable cdex since we want to compare against the original dex file
1989 // after unquickening.
1990 { input_vdex, output_vdex, kDisableCompactDex },
1991 /* expect_success */ true,
1992 /* use_fd */ true);
1993 }
1994 // Unquicken by running the verify compiler filter on the vdex file and verify it matches.
1995 std::string odex_location2 = GetOdexDir() + "/unquickened.odex";
1996 std::string vdex_location2 = GetOdexDir() + "/unquickened.vdex";
1997 std::unique_ptr<File> vdex_unquickened(OS::CreateEmptyFile(vdex_location2.c_str()));
1998 {
1999 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_output->Fd());
2000 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_unquickened->Fd());
2001 GenerateOdexForTest(dex_location,
2002 odex_location2,
2003 CompilerFilter::kVerify,
2004 // Disable cdex to avoid needing to write out the shared section.
2005 { input_vdex, output_vdex, kDisableCompactDex },
2006 /* expect_success */ true,
2007 /* use_fd */ true);
2008 }
2009 ASSERT_EQ(vdex_unquickened->Flush(), 0) << "Could not flush and close vdex file";
2010 ASSERT_TRUE(success_);
2011 {
2012 // Check that hte vdex has one dex and compare it to the original one.
2013 std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location2.c_str(),
2014 /*writable*/ false,
2015 /*low_4gb*/ false,
2016 /*unquicken*/ false,
2017 &error_msg));
2018 std::vector<std::unique_ptr<const DexFile>> dex_files;
2019 bool result = vdex->OpenAllDexFiles(&dex_files, &error_msg);
2020 ASSERT_TRUE(result) << error_msg;
2021 ASSERT_EQ(dex_files.size(), 1u) << error_msg;
2022 ScratchFile temp;
2023 ASSERT_TRUE(temp.GetFile()->WriteFully(dex_files[0]->Begin(), dex_files[0]->Size()));
2024 ASSERT_EQ(temp.GetFile()->Flush(), 0) << "Could not flush extracted dex";
2025 EXPECT_EQ(temp.GetFile()->Compare(temp_dex.GetFile()), 0);
2026 }
2027 ASSERT_EQ(vdex_output->FlushCloseOrErase(), 0) << "Could not flush and close";
2028 ASSERT_EQ(vdex_unquickened->FlushCloseOrErase(), 0) << "Could not flush and close";
2029}
2030
Mathieu Chartierd45863a2018-03-21 18:16:36 -07002031// Test that compact dex generation with invalid dex files doesn't crash dex2oat. b/75970654
2032TEST_F(Dex2oatTest, CompactDexInvalidSource) {
2033 ScratchFile invalid_dex;
2034 {
2035 FILE* file = fdopen(invalid_dex.GetFd(), "w+b");
2036 ZipWriter writer(file);
2037 writer.StartEntry("classes.dex", ZipWriter::kAlign32);
2038 DexFile::Header header = {};
2039 StandardDexFile::WriteMagic(header.magic_);
2040 StandardDexFile::WriteCurrentVersion(header.magic_);
2041 header.file_size_ = 4 * KB;
2042 header.data_size_ = 4 * KB;
2043 header.data_off_ = 10 * MB;
2044 header.map_off_ = 10 * MB;
2045 header.class_defs_off_ = 10 * MB;
2046 header.class_defs_size_ = 10000;
2047 ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
2048 writer.FinishEntry();
2049 writer.Finish();
2050 ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
2051 }
Andreas Gampebc802de2018-06-20 17:24:11 -07002052 const std::string& dex_location = invalid_dex.GetFilename();
Mathieu Chartierd45863a2018-03-21 18:16:36 -07002053 const std::string odex_location = GetOdexDir() + "/output.odex";
2054 std::string error_msg;
2055 int status = GenerateOdexForTestWithStatus(
2056 {dex_location},
2057 odex_location,
2058 CompilerFilter::kQuicken,
2059 &error_msg,
2060 { "--compact-dex-level=fast" });
2061 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
2062}
2063
Mathieu Chartier14e7bad2018-03-22 14:33:20 -07002064// Test that dex2oat with a CompactDex file in the APK fails.
2065TEST_F(Dex2oatTest, CompactDexInZip) {
2066 CompactDexFile::Header header = {};
2067 CompactDexFile::WriteMagic(header.magic_);
2068 CompactDexFile::WriteCurrentVersion(header.magic_);
2069 header.file_size_ = sizeof(CompactDexFile::Header);
2070 header.data_off_ = 10 * MB;
2071 header.map_off_ = 10 * MB;
2072 header.class_defs_off_ = 10 * MB;
2073 header.class_defs_size_ = 10000;
2074 // Create a zip containing the invalid dex.
2075 ScratchFile invalid_dex_zip;
2076 {
2077 FILE* file = fdopen(invalid_dex_zip.GetFd(), "w+b");
2078 ZipWriter writer(file);
2079 writer.StartEntry("classes.dex", ZipWriter::kCompress);
2080 ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
2081 writer.FinishEntry();
2082 writer.Finish();
2083 ASSERT_EQ(invalid_dex_zip.GetFile()->Flush(), 0);
2084 }
2085 // Create the dex file directly.
2086 ScratchFile invalid_dex;
2087 {
2088 ASSERT_GE(invalid_dex.GetFile()->WriteFully(&header, sizeof(header)), 0);
2089 ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
2090 }
2091 std::string error_msg;
2092 int status = 0u;
2093
2094 status = GenerateOdexForTestWithStatus(
2095 { invalid_dex_zip.GetFilename() },
2096 GetOdexDir() + "/output_apk.odex",
2097 CompilerFilter::kQuicken,
2098 &error_msg,
2099 { "--compact-dex-level=fast" });
2100 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
2101
2102 status = GenerateOdexForTestWithStatus(
2103 { invalid_dex.GetFilename() },
2104 GetOdexDir() + "/output.odex",
2105 CompilerFilter::kQuicken,
2106 &error_msg,
2107 { "--compact-dex-level=fast" });
2108 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
2109}
2110
Mathieu Chartierf85b3db2018-04-02 18:16:21 -07002111TEST_F(Dex2oatTest, AppImageNoProfile) {
2112 ScratchFile app_image_file;
2113 const std::string out_dir = GetScratchDir();
2114 const std::string odex_location = out_dir + "/base.odex";
2115 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2116 odex_location,
2117 CompilerFilter::Filter::kSpeedProfile,
2118 { "--app-image-fd=" + std::to_string(app_image_file.GetFd()) },
2119 true, // expect_success
2120 false, // use_fd
2121 [](const OatFile&) {});
2122 // Open our generated oat file.
2123 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01002124 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
2125 odex_location.c_str(),
Mathieu Chartierf85b3db2018-04-02 18:16:21 -07002126 odex_location.c_str(),
2127 nullptr,
2128 nullptr,
2129 false,
2130 /*low_4gb*/false,
2131 odex_location.c_str(),
2132 &error_msg));
2133 ASSERT_TRUE(odex_file != nullptr);
2134 ImageHeader header = {};
2135 ASSERT_TRUE(app_image_file.GetFile()->PreadFully(
2136 reinterpret_cast<void*>(&header),
2137 sizeof(header),
2138 /*offset*/ 0u)) << app_image_file.GetFile()->GetLength();
2139 EXPECT_GT(header.GetImageSection(ImageHeader::kSectionObjects).Size(), 0u);
2140 EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtMethods).Size(), 0u);
2141 EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtFields).Size(), 0u);
2142}
2143
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002144TEST_F(Dex2oatClassLoaderContextTest, StoredClassLoaderContext) {
Mathieu Chartierc4440772018-04-16 14:40:56 -07002145 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("MultiDex");
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002146 const std::string out_dir = GetScratchDir();
2147 const std::string odex_location = out_dir + "/base.odex";
Mathieu Chartierc4440772018-04-16 14:40:56 -07002148 const std::string valid_context = "PCL[" + dex_files[0]->GetLocation() + "]";
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002149 const std::string stored_context = "PCL[/system/not_real_lib.jar]";
Mathieu Chartierc4440772018-04-16 14:40:56 -07002150 std::string expected_stored_context = "PCL[";
2151 size_t index = 1;
2152 for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
2153 const bool is_first = index == 1u;
2154 if (!is_first) {
2155 expected_stored_context += ":";
2156 }
2157 expected_stored_context += "/system/not_real_lib.jar";
2158 if (!is_first) {
2159 expected_stored_context += "!classes" + std::to_string(index) + ".dex";
2160 }
2161 expected_stored_context += "*" + std::to_string(dex_file->GetLocationChecksum());
2162 ++index;
2163 }
2164 expected_stored_context += + "]";
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002165 // The class path should not be valid and should fail being stored.
2166 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2167 odex_location,
2168 CompilerFilter::Filter::kQuicken,
2169 { "--class-loader-context=" + stored_context },
2170 true, // expect_success
2171 false, // use_fd
2172 [&](const OatFile& oat_file) {
Mathieu Chartierc4440772018-04-16 14:40:56 -07002173 EXPECT_NE(oat_file.GetClassLoaderContext(), stored_context) << output_;
2174 EXPECT_NE(oat_file.GetClassLoaderContext(), valid_context) << output_;
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002175 });
2176 // The stored context should match what we expect even though it's invalid.
2177 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2178 odex_location,
2179 CompilerFilter::Filter::kQuicken,
2180 { "--class-loader-context=" + valid_context,
2181 "--stored-class-loader-context=" + stored_context },
2182 true, // expect_success
2183 false, // use_fd
2184 [&](const OatFile& oat_file) {
Mathieu Chartierc4440772018-04-16 14:40:56 -07002185 EXPECT_EQ(oat_file.GetClassLoaderContext(), expected_stored_context) << output_;
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002186 });
2187}
2188
Andreas Gampee1459ae2016-06-29 09:36:30 -07002189} // namespace art