blob: 96d7dba2259d1c2cc41b98c4a0fdea78c76ac250 [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) {
Andreas Gampe8b362a82018-05-22 20:54:14 +0000475 // Native memory usage isn't correctly tracked under sanitization.
476 TEST_DISABLED_FOR_MEMORY_TOOL_ASAN();
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 Gampe8b362a82018-05-22 20:54:14 +00001057 TEST_DISABLED_FOR_MEMORY_TOOL_VALGRIND(); // b/63052624
1058
Andreas Gampe80ddf272018-01-11 09:41:00 -08001059 // The watchdog is independent of dex2oat and will not delete intermediates. It is possible
1060 // that the compilation succeeds and the file is completely written by the time the watchdog
1061 // kills dex2oat (but the dex2oat threads must have been scheduled pretty badly).
1062 test_accepts_odex_file_on_failure = true;
1063
Andreas Gampe2e8a2562017-01-18 20:39:02 -08001064 // Check with ten milliseconds.
1065 RunTest(false, { "--watchdog-timeout=10" });
1066}
1067
Andreas Gampef7882972017-03-20 16:35:24 -07001068class Dex2oatReturnCodeTest : public Dex2oatTest {
1069 protected:
1070 int RunTest(const std::vector<std::string>& extra_args = {}) {
1071 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
1072 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
1073
1074 Copy(GetTestDexFileName(), dex_location);
1075
1076 std::string error_msg;
Mathieu Chartier9e050df2017-08-09 10:05:47 -07001077 return GenerateOdexForTestWithStatus({dex_location},
Andreas Gampef7882972017-03-20 16:35:24 -07001078 odex_location,
1079 CompilerFilter::kSpeed,
1080 &error_msg,
1081 extra_args);
1082 }
1083
1084 std::string GetTestDexFileName() {
1085 return GetDexSrc1();
1086 }
1087};
1088
1089TEST_F(Dex2oatReturnCodeTest, TestCreateRuntime) {
Andreas Gampefd80b172017-04-26 22:25:31 -07001090 TEST_DISABLED_FOR_MEMORY_TOOL(); // b/19100793
Andreas Gampef7882972017-03-20 16:35:24 -07001091 int status = RunTest({ "--boot-image=/this/does/not/exist/yolo.oat" });
1092 EXPECT_EQ(static_cast<int>(dex2oat::ReturnCode::kCreateRuntime), WEXITSTATUS(status)) << output_;
1093}
1094
Calin Juravle1ce70852017-06-28 10:59:03 -07001095class Dex2oatClassLoaderContextTest : public Dex2oatTest {
1096 protected:
1097 void RunTest(const char* class_loader_context,
1098 const char* expected_classpath_key,
1099 bool expected_success,
1100 bool use_second_source = false) {
1101 std::string dex_location = GetUsedDexLocation();
1102 std::string odex_location = GetUsedOatLocation();
1103
1104 Copy(use_second_source ? GetDexSrc2() : GetDexSrc1(), dex_location);
1105
1106 std::string error_msg;
1107 std::vector<std::string> extra_args;
1108 if (class_loader_context != nullptr) {
1109 extra_args.push_back(std::string("--class-loader-context=") + class_loader_context);
1110 }
1111 auto check_oat = [expected_classpath_key](const OatFile& oat_file) {
1112 ASSERT_TRUE(expected_classpath_key != nullptr);
1113 const char* classpath = oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
1114 ASSERT_TRUE(classpath != nullptr);
1115 ASSERT_STREQ(expected_classpath_key, classpath);
1116 };
1117
1118 GenerateOdexForTest(dex_location,
1119 odex_location,
1120 CompilerFilter::kQuicken,
1121 extra_args,
1122 expected_success,
1123 /*use_fd*/ false,
1124 check_oat);
1125 }
1126
1127 std::string GetUsedDexLocation() {
1128 return GetScratchDir() + "/Context.jar";
1129 }
1130
1131 std::string GetUsedOatLocation() {
1132 return GetOdexDir() + "/Context.odex";
1133 }
1134
Calin Juravle7b0648a2017-07-07 18:40:50 -07001135 const char* kEmptyClassPathKey = "PCL[]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001136};
1137
1138TEST_F(Dex2oatClassLoaderContextTest, InvalidContext) {
1139 RunTest("Invalid[]", /*expected_classpath_key*/ nullptr, /*expected_success*/ false);
1140}
1141
1142TEST_F(Dex2oatClassLoaderContextTest, EmptyContext) {
1143 RunTest("PCL[]", kEmptyClassPathKey, /*expected_success*/ true);
1144}
1145
1146TEST_F(Dex2oatClassLoaderContextTest, SpecialContext) {
1147 RunTest(OatFile::kSpecialSharedLibrary,
1148 OatFile::kSpecialSharedLibrary,
1149 /*expected_success*/ true);
1150}
1151
1152TEST_F(Dex2oatClassLoaderContextTest, ContextWithTheSourceDexFiles) {
1153 std::string context = "PCL[" + GetUsedDexLocation() + "]";
1154 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1155}
1156
1157TEST_F(Dex2oatClassLoaderContextTest, ContextWithOtherDexFiles) {
1158 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Nested");
Calin Juravle1ce70852017-06-28 10:59:03 -07001159
1160 std::string context = "PCL[" + dex_files[0]->GetLocation() + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -07001161 std::string expected_classpath_key = "PCL[" +
1162 dex_files[0]->GetLocation() + "*" + std::to_string(dex_files[0]->GetLocationChecksum()) + "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001163 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1164}
1165
1166TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFiles) {
1167 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
1168 Copy(GetStrippedDexSrc1(), stripped_classpath);
1169
1170 std::string context = "PCL[" + stripped_classpath + "]";
1171 // Expect an empty context because stripped dex files cannot be open.
Calin Juravle7b0648a2017-07-07 18:40:50 -07001172 RunTest(context.c_str(), kEmptyClassPathKey , /*expected_success*/ true);
Calin Juravle1ce70852017-06-28 10:59:03 -07001173}
1174
1175TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFilesBackedByOdex) {
1176 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
1177 std::string odex_for_classpath = GetOdexDir() + "/stripped_classpath.odex";
1178
1179 Copy(GetDexSrc1(), stripped_classpath);
1180
1181 GenerateOdexForTest(stripped_classpath,
1182 odex_for_classpath,
1183 CompilerFilter::kQuicken,
1184 {},
1185 true);
1186
1187 // Strip the dex file
1188 Copy(GetStrippedDexSrc1(), stripped_classpath);
1189
1190 std::string context = "PCL[" + stripped_classpath + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -07001191 std::string expected_classpath_key;
Calin Juravle1ce70852017-06-28 10:59:03 -07001192 {
1193 // Open the oat file to get the expected classpath.
Nicolas Geoffray29742602017-12-14 10:09:03 +00001194 OatFileAssistant oat_file_assistant(stripped_classpath.c_str(), kRuntimeISA, false, false);
Calin Juravle1ce70852017-06-28 10:59:03 -07001195 std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile());
1196 std::vector<std::unique_ptr<const DexFile>> oat_dex_files =
1197 OatFileAssistant::LoadDexFiles(*oat_file, stripped_classpath.c_str());
Calin Juravle7b0648a2017-07-07 18:40:50 -07001198 expected_classpath_key = "PCL[";
1199 for (size_t i = 0; i < oat_dex_files.size(); i++) {
1200 if (i > 0) {
1201 expected_classpath_key + ":";
1202 }
1203 expected_classpath_key += oat_dex_files[i]->GetLocation() + "*" +
1204 std::to_string(oat_dex_files[i]->GetLocationChecksum());
1205 }
1206 expected_classpath_key += "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001207 }
1208
1209 RunTest(context.c_str(),
Calin Juravle7b0648a2017-07-07 18:40:50 -07001210 expected_classpath_key.c_str(),
Calin Juravle1ce70852017-06-28 10:59:03 -07001211 /*expected_success*/ true,
1212 /*use_second_source*/ true);
1213}
1214
1215TEST_F(Dex2oatClassLoaderContextTest, ContextWithNotExistentDexFiles) {
1216 std::string context = "PCL[does_not_exists.dex]";
1217 // Expect an empty context because stripped dex files cannot be open.
1218 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1219}
1220
Calin Juravlec79470d2017-07-12 17:37:42 -07001221TEST_F(Dex2oatClassLoaderContextTest, ChainContext) {
1222 std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1223 std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1224
1225 std::string context = "PCL[" + GetTestDexFileName("Nested") + "];" +
1226 "DLC[" + GetTestDexFileName("MultiDex") + "]";
1227 std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "];" +
1228 "DLC[" + CreateClassPathWithChecksums(dex_files2) + "]";
1229
1230 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1231}
1232
Mathieu Chartier9e050df2017-08-09 10:05:47 -07001233class Dex2oatDeterminism : public Dex2oatTest {};
1234
1235TEST_F(Dex2oatDeterminism, UnloadCompile) {
1236 if (!kUseReadBarrier &&
1237 gc::kCollectorTypeDefault != gc::kCollectorTypeCMS &&
1238 gc::kCollectorTypeDefault != gc::kCollectorTypeMS) {
1239 LOG(INFO) << "Test requires determinism support.";
1240 return;
1241 }
1242 Runtime* const runtime = Runtime::Current();
1243 std::string out_dir = GetScratchDir();
1244 const std::string base_oat_name = out_dir + "/base.oat";
1245 const std::string base_vdex_name = out_dir + "/base.vdex";
1246 const std::string unload_oat_name = out_dir + "/unload.oat";
1247 const std::string unload_vdex_name = out_dir + "/unload.vdex";
1248 const std::string no_unload_oat_name = out_dir + "/nounload.oat";
1249 const std::string no_unload_vdex_name = out_dir + "/nounload.vdex";
1250 const std::string app_image_name = out_dir + "/unload.art";
1251 std::string error_msg;
1252 const std::vector<gc::space::ImageSpace*>& spaces = runtime->GetHeap()->GetBootImageSpaces();
1253 ASSERT_GT(spaces.size(), 0u);
1254 const std::string image_location = spaces[0]->GetImageLocation();
1255 // Without passing in an app image, it will unload in between compilations.
1256 const int res = GenerateOdexForTestWithStatus(
1257 GetLibCoreDexFileNames(),
1258 base_oat_name,
1259 CompilerFilter::Filter::kQuicken,
1260 &error_msg,
1261 {"--force-determinism", "--avoid-storing-invocation"});
1262 EXPECT_EQ(res, 0);
1263 Copy(base_oat_name, unload_oat_name);
1264 Copy(base_vdex_name, unload_vdex_name);
1265 std::unique_ptr<File> unload_oat(OS::OpenFileForReading(unload_oat_name.c_str()));
1266 std::unique_ptr<File> unload_vdex(OS::OpenFileForReading(unload_vdex_name.c_str()));
1267 ASSERT_TRUE(unload_oat != nullptr);
1268 ASSERT_TRUE(unload_vdex != nullptr);
1269 EXPECT_GT(unload_oat->GetLength(), 0u);
1270 EXPECT_GT(unload_vdex->GetLength(), 0u);
1271 // Regenerate with an app image to disable the dex2oat unloading and verify that the output is
1272 // the same.
1273 const int res2 = GenerateOdexForTestWithStatus(
1274 GetLibCoreDexFileNames(),
1275 base_oat_name,
1276 CompilerFilter::Filter::kQuicken,
1277 &error_msg,
1278 {"--force-determinism", "--avoid-storing-invocation", "--app-image-file=" + app_image_name});
1279 EXPECT_EQ(res2, 0);
1280 Copy(base_oat_name, no_unload_oat_name);
1281 Copy(base_vdex_name, no_unload_vdex_name);
1282 std::unique_ptr<File> no_unload_oat(OS::OpenFileForReading(no_unload_oat_name.c_str()));
1283 std::unique_ptr<File> no_unload_vdex(OS::OpenFileForReading(no_unload_vdex_name.c_str()));
1284 ASSERT_TRUE(no_unload_oat != nullptr);
1285 ASSERT_TRUE(no_unload_vdex != nullptr);
1286 EXPECT_GT(no_unload_oat->GetLength(), 0u);
1287 EXPECT_GT(no_unload_vdex->GetLength(), 0u);
1288 // Verify that both of the files are the same (odex and vdex).
1289 EXPECT_EQ(unload_oat->GetLength(), no_unload_oat->GetLength());
1290 EXPECT_EQ(unload_vdex->GetLength(), no_unload_vdex->GetLength());
1291 EXPECT_EQ(unload_oat->Compare(no_unload_oat.get()), 0)
1292 << unload_oat_name << " " << no_unload_oat_name;
1293 EXPECT_EQ(unload_vdex->Compare(no_unload_vdex.get()), 0)
1294 << unload_vdex_name << " " << no_unload_vdex_name;
1295 // App image file.
1296 std::unique_ptr<File> app_image_file(OS::OpenFileForReading(app_image_name.c_str()));
1297 ASSERT_TRUE(app_image_file != nullptr);
1298 EXPECT_GT(app_image_file->GetLength(), 0u);
1299}
1300
Mathieu Chartier120aa282017-08-05 16:03:03 -07001301// Test that dexlayout section info is correctly written to the oat file for profile based
1302// compilation.
1303TEST_F(Dex2oatTest, LayoutSections) {
1304 using Hotness = ProfileCompilationInfo::MethodHotness;
1305 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1306 ScratchFile profile_file;
1307 // We can only layout method indices with code items, figure out which ones have this property
1308 // first.
1309 std::vector<uint16_t> methods;
1310 {
1311 const DexFile::TypeId* type_id = dex->FindTypeId("LManyMethods;");
1312 dex::TypeIndex type_idx = dex->GetIndexForTypeId(*type_id);
1313 const DexFile::ClassDef* class_def = dex->FindClassDef(type_idx);
1314 ClassDataItemIterator it(*dex, dex->GetClassData(*class_def));
1315 it.SkipAllFields();
1316 std::set<size_t> code_item_offsets;
Mathieu Chartierb7c273c2017-11-10 18:07:56 -08001317 for (; it.HasNextMethod(); it.Next()) {
Mathieu Chartier120aa282017-08-05 16:03:03 -07001318 const uint16_t method_idx = it.GetMemberIndex();
1319 const size_t code_item_offset = it.GetMethodCodeItemOffset();
1320 if (code_item_offsets.insert(code_item_offset).second) {
1321 // Unique code item, add the method index.
1322 methods.push_back(method_idx);
1323 }
1324 }
1325 DCHECK(!it.HasNext());
1326 }
1327 ASSERT_GE(methods.size(), 8u);
1328 std::vector<uint16_t> hot_methods = {methods[1], methods[3], methods[5]};
1329 std::vector<uint16_t> startup_methods = {methods[1], methods[2], methods[7]};
1330 std::vector<uint16_t> post_methods = {methods[0], methods[2], methods[6]};
1331 // Here, we build the profile from the method lists.
1332 ProfileCompilationInfo info;
1333 info.AddMethodsForDex(
1334 static_cast<Hotness::Flag>(Hotness::kFlagHot | Hotness::kFlagStartup),
1335 dex.get(),
1336 hot_methods.begin(),
1337 hot_methods.end());
1338 info.AddMethodsForDex(
1339 Hotness::kFlagStartup,
1340 dex.get(),
1341 startup_methods.begin(),
1342 startup_methods.end());
1343 info.AddMethodsForDex(
1344 Hotness::kFlagPostStartup,
1345 dex.get(),
1346 post_methods.begin(),
1347 post_methods.end());
1348 for (uint16_t id : hot_methods) {
1349 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsHot());
1350 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsStartup());
1351 }
1352 for (uint16_t id : startup_methods) {
1353 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsStartup());
1354 }
1355 for (uint16_t id : post_methods) {
1356 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsPostStartup());
1357 }
1358 // Save the profile since we want to use it with dex2oat to produce an oat file.
1359 ASSERT_TRUE(info.Save(profile_file.GetFd()));
1360 // Generate a profile based odex.
1361 const std::string dir = GetScratchDir();
1362 const std::string oat_filename = dir + "/base.oat";
1363 const std::string vdex_filename = dir + "/base.vdex";
1364 std::string error_msg;
1365 const int res = GenerateOdexForTestWithStatus(
1366 {dex->GetLocation()},
1367 oat_filename,
1368 CompilerFilter::Filter::kQuicken,
1369 &error_msg,
1370 {"--profile-file=" + profile_file.GetFilename()});
1371 EXPECT_EQ(res, 0);
1372
1373 // Open our generated oat file.
Nicolas Geoffray30025092018-04-19 14:43:29 +01001374 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1375 oat_filename.c_str(),
Mathieu Chartier120aa282017-08-05 16:03:03 -07001376 oat_filename.c_str(),
1377 nullptr,
1378 nullptr,
1379 false,
1380 /*low_4gb*/false,
1381 dex->GetLocation().c_str(),
1382 &error_msg));
1383 ASSERT_TRUE(odex_file != nullptr);
1384 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1385 ASSERT_EQ(oat_dex_files.size(), 1u);
1386 // Check that the code sections match what we expect.
1387 for (const OatDexFile* oat_dex : oat_dex_files) {
1388 const DexLayoutSections* const sections = oat_dex->GetDexLayoutSections();
1389 // Testing of logging the sections.
1390 ASSERT_TRUE(sections != nullptr);
1391 LOG(INFO) << *sections;
1392
1393 // Load the sections into temporary variables for convenience.
1394 const DexLayoutSection& code_section =
1395 sections->sections_[static_cast<size_t>(DexLayoutSections::SectionType::kSectionTypeCode)];
1396 const DexLayoutSection::Subsection& section_hot_code =
1397 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeHot)];
1398 const DexLayoutSection::Subsection& section_sometimes_used =
1399 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeSometimesUsed)];
1400 const DexLayoutSection::Subsection& section_startup_only =
1401 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeStartupOnly)];
1402 const DexLayoutSection::Subsection& section_unused =
1403 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeUnused)];
1404
1405 // All the sections should be non-empty.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001406 EXPECT_GT(section_hot_code.Size(), 0u);
1407 EXPECT_GT(section_sometimes_used.Size(), 0u);
1408 EXPECT_GT(section_startup_only.Size(), 0u);
1409 EXPECT_GT(section_unused.Size(), 0u);
Mathieu Chartier120aa282017-08-05 16:03:03 -07001410
1411 // Open the dex file since we need to peek at the code items to verify the layout matches what
1412 // we expect.
1413 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1414 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1415 const DexFile::TypeId* type_id = dex_file->FindTypeId("LManyMethods;");
1416 ASSERT_TRUE(type_id != nullptr);
1417 dex::TypeIndex type_idx = dex_file->GetIndexForTypeId(*type_id);
1418 const DexFile::ClassDef* class_def = dex_file->FindClassDef(type_idx);
1419 ASSERT_TRUE(class_def != nullptr);
1420
1421 // Count how many code items are for each category, there should be at least one per category.
1422 size_t hot_count = 0;
1423 size_t post_startup_count = 0;
1424 size_t startup_count = 0;
1425 size_t unused_count = 0;
1426 // Visit all of the methdos of the main class and cross reference the method indices to their
1427 // corresponding code item offsets to verify the layout.
1428 ClassDataItemIterator it(*dex_file, dex_file->GetClassData(*class_def));
1429 it.SkipAllFields();
Mathieu Chartierb7c273c2017-11-10 18:07:56 -08001430 for (; it.HasNextMethod(); it.Next()) {
Mathieu Chartier120aa282017-08-05 16:03:03 -07001431 const size_t method_idx = it.GetMemberIndex();
1432 const size_t code_item_offset = it.GetMethodCodeItemOffset();
1433 const bool is_hot = ContainsElement(hot_methods, method_idx);
1434 const bool is_startup = ContainsElement(startup_methods, method_idx);
1435 const bool is_post_startup = ContainsElement(post_methods, method_idx);
1436 if (is_hot) {
1437 // Hot is highest precedence, check that the hot methods are in the hot section.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001438 EXPECT_TRUE(section_hot_code.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001439 ++hot_count;
1440 } else if (is_post_startup) {
1441 // Post startup is sometimes used section.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001442 EXPECT_TRUE(section_sometimes_used.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001443 ++post_startup_count;
1444 } else if (is_startup) {
1445 // Startup at this point means not hot or post startup, these must be startup only then.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001446 EXPECT_TRUE(section_startup_only.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001447 ++startup_count;
1448 } else {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001449 if (section_unused.Contains(code_item_offset)) {
Alan Leung9595fd32017-10-17 17:08:19 -07001450 // If no flags are set, the method should be unused ...
1451 ++unused_count;
1452 } else {
1453 // or this method is part of the last code item and the end is 4 byte aligned.
1454 ClassDataItemIterator it2(*dex_file, dex_file->GetClassData(*class_def));
1455 it2.SkipAllFields();
Mathieu Chartierb7c273c2017-11-10 18:07:56 -08001456 for (; it2.HasNextMethod(); it2.Next()) {
Alan Leung9595fd32017-10-17 17:08:19 -07001457 EXPECT_LE(it2.GetMethodCodeItemOffset(), code_item_offset);
1458 }
1459 uint32_t code_item_size = dex_file->FindCodeItemOffset(*class_def, method_idx);
1460 EXPECT_EQ((code_item_offset + code_item_size) % 4, 0u);
1461 }
Mathieu Chartier120aa282017-08-05 16:03:03 -07001462 }
1463 }
1464 DCHECK(!it.HasNext());
1465 EXPECT_GT(hot_count, 0u);
1466 EXPECT_GT(post_startup_count, 0u);
1467 EXPECT_GT(startup_count, 0u);
1468 EXPECT_GT(unused_count, 0u);
1469 }
1470}
1471
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001472// Test that generating compact dex works.
1473TEST_F(Dex2oatTest, GenerateCompactDex) {
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001474 // Generate a compact dex based odex.
1475 const std::string dir = GetScratchDir();
1476 const std::string oat_filename = dir + "/base.oat";
1477 const std::string vdex_filename = dir + "/base.vdex";
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001478 const std::string dex_location = GetTestDexFileName("MultiDex");
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001479 std::string error_msg;
1480 const int res = GenerateOdexForTestWithStatus(
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001481 { dex_location },
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001482 oat_filename,
1483 CompilerFilter::Filter::kQuicken,
1484 &error_msg,
1485 {"--compact-dex-level=fast"});
1486 EXPECT_EQ(res, 0);
1487 // Open our generated oat file.
Nicolas Geoffray30025092018-04-19 14:43:29 +01001488 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1489 oat_filename.c_str(),
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001490 oat_filename.c_str(),
1491 nullptr,
1492 nullptr,
1493 false,
1494 /*low_4gb*/false,
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001495 dex_location.c_str(),
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001496 &error_msg));
1497 ASSERT_TRUE(odex_file != nullptr);
1498 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001499 ASSERT_GT(oat_dex_files.size(), 1u);
1500 // Check that each dex is a compact dex file.
1501 std::vector<std::unique_ptr<const CompactDexFile>> compact_dex_files;
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001502 for (const OatDexFile* oat_dex : oat_dex_files) {
1503 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1504 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1505 ASSERT_TRUE(dex_file->IsCompactDexFile());
Mathieu Chartierc17b7d82018-03-14 14:00:04 -07001506 compact_dex_files.push_back(
1507 std::unique_ptr<const CompactDexFile>(dex_file.release()->AsCompactDexFile()));
1508 }
1509 for (const std::unique_ptr<const CompactDexFile>& dex_file : compact_dex_files) {
1510 // Test that every code item is in the owned section.
1511 const CompactDexFile::Header& header = dex_file->GetHeader();
1512 EXPECT_LE(header.OwnedDataBegin(), header.OwnedDataEnd());
1513 EXPECT_LE(header.OwnedDataBegin(), header.data_size_);
1514 EXPECT_LE(header.OwnedDataEnd(), header.data_size_);
1515 for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
1516 const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
1517 class_def.VisitMethods(dex_file.get(), [&](const ClassDataItemIterator& it) {
1518 if (it.GetMethodCodeItemOffset() != 0u) {
1519 ASSERT_GE(it.GetMethodCodeItemOffset(), header.OwnedDataBegin());
1520 ASSERT_LT(it.GetMethodCodeItemOffset(), header.OwnedDataEnd());
1521 }
1522 });
1523 }
1524 // Test that the owned sections don't overlap.
1525 for (const std::unique_ptr<const CompactDexFile>& other_dex : compact_dex_files) {
1526 if (dex_file != other_dex) {
1527 ASSERT_TRUE(
1528 (dex_file->GetHeader().OwnedDataBegin() >= other_dex->GetHeader().OwnedDataEnd()) ||
1529 (dex_file->GetHeader().OwnedDataEnd() <= other_dex->GetHeader().OwnedDataBegin()));
1530 }
1531 }
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001532 }
1533}
1534
Andreas Gampef39208f2017-10-19 15:06:59 -07001535class Dex2oatVerifierAbort : public Dex2oatTest {};
1536
1537TEST_F(Dex2oatVerifierAbort, HardFail) {
1538 // Use VerifierDeps as it has hard-failing classes.
1539 std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDeps"));
1540 std::string out_dir = GetScratchDir();
1541 const std::string base_oat_name = out_dir + "/base.oat";
1542 std::string error_msg;
1543 const int res_fail = GenerateOdexForTestWithStatus(
1544 {dex->GetLocation()},
1545 base_oat_name,
1546 CompilerFilter::Filter::kQuicken,
1547 &error_msg,
1548 {"--abort-on-hard-verifier-error"});
1549 EXPECT_NE(0, res_fail);
1550
1551 const int res_no_fail = GenerateOdexForTestWithStatus(
1552 {dex->GetLocation()},
1553 base_oat_name,
1554 CompilerFilter::Filter::kQuicken,
1555 &error_msg,
1556 {"--no-abort-on-hard-verifier-error"});
1557 EXPECT_EQ(0, res_no_fail);
1558}
1559
1560TEST_F(Dex2oatVerifierAbort, SoftFail) {
1561 // Use VerifierDepsMulti as it has hard-failing classes.
1562 std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDepsMulti"));
1563 std::string out_dir = GetScratchDir();
1564 const std::string base_oat_name = out_dir + "/base.oat";
1565 std::string error_msg;
1566 const int res_fail = GenerateOdexForTestWithStatus(
1567 {dex->GetLocation()},
1568 base_oat_name,
1569 CompilerFilter::Filter::kQuicken,
1570 &error_msg,
1571 {"--abort-on-soft-verifier-error"});
1572 EXPECT_NE(0, res_fail);
1573
1574 const int res_no_fail = GenerateOdexForTestWithStatus(
1575 {dex->GetLocation()},
1576 base_oat_name,
1577 CompilerFilter::Filter::kQuicken,
1578 &error_msg,
1579 {"--no-abort-on-soft-verifier-error"});
1580 EXPECT_EQ(0, res_no_fail);
1581}
1582
Andreas Gampecac31ad2017-11-06 20:01:17 -08001583class Dex2oatDedupeCode : public Dex2oatTest {};
1584
1585TEST_F(Dex2oatDedupeCode, DedupeTest) {
1586 // Use MyClassNatives. It has lots of native methods that will produce deduplicate-able code.
1587 std::unique_ptr<const DexFile> dex(OpenTestDexFile("MyClassNatives"));
1588 std::string out_dir = GetScratchDir();
1589 const std::string base_oat_name = out_dir + "/base.oat";
1590 size_t no_dedupe_size = 0;
1591 GenerateOdexForTest(dex->GetLocation(),
1592 base_oat_name,
1593 CompilerFilter::Filter::kSpeed,
1594 { "--deduplicate-code=false" },
1595 true, // expect_success
1596 false, // use_fd
1597 [&no_dedupe_size](const OatFile& o) {
1598 no_dedupe_size = o.Size();
1599 });
1600
1601 size_t dedupe_size = 0;
1602 GenerateOdexForTest(dex->GetLocation(),
1603 base_oat_name,
1604 CompilerFilter::Filter::kSpeed,
1605 { "--deduplicate-code=true" },
1606 true, // expect_success
1607 false, // use_fd
1608 [&dedupe_size](const OatFile& o) {
1609 dedupe_size = o.Size();
1610 });
1611
1612 EXPECT_LT(dedupe_size, no_dedupe_size);
1613}
1614
Nicolas Geoffrayf3075272018-01-08 12:41:19 +00001615TEST_F(Dex2oatTest, UncompressedTest) {
1616 std::unique_ptr<const DexFile> dex(OpenTestDexFile("MainUncompressed"));
1617 std::string out_dir = GetScratchDir();
1618 const std::string base_oat_name = out_dir + "/base.oat";
1619 GenerateOdexForTest(dex->GetLocation(),
1620 base_oat_name,
1621 CompilerFilter::Filter::kQuicken,
1622 { },
1623 true, // expect_success
1624 false, // use_fd
1625 [](const OatFile& o) {
1626 CHECK(!o.ContainsDexCode());
1627 });
1628}
1629
Mathieu Chartier700a9852018-02-06 18:27:38 -08001630TEST_F(Dex2oatTest, EmptyUncompressedDexTest) {
1631 std::string out_dir = GetScratchDir();
1632 const std::string base_oat_name = out_dir + "/base.oat";
1633 std::string error_msg;
1634 int status = GenerateOdexForTestWithStatus(
1635 { GetTestDexFileName("MainEmptyUncompressed") },
1636 base_oat_name,
1637 CompilerFilter::Filter::kQuicken,
1638 &error_msg,
1639 { },
1640 /*use_fd*/ false);
1641 // Expect to fail with code 1 and not SIGSEGV or SIGABRT.
1642 ASSERT_TRUE(WIFEXITED(status));
1643 ASSERT_EQ(WEXITSTATUS(status), 1) << error_msg;
1644}
1645
Mathieu Chartier05f90d12018-02-07 13:47:17 -08001646// Dex file that has duplicate methods have different code items and debug info.
1647static const char kDuplicateMethodInputDex[] =
1648 "ZGV4CjAzOQDEy8VPdj4qHpgPYFWtLCtOykfFP4kB8tGYDAAAcAAAAHhWNBIAAAAAAAAAANALAABI"
1649 "AAAAcAAAAA4AAACQAQAABQAAAMgBAAANAAAABAIAABkAAABsAgAABAAAADQDAADgCAAAuAMAADgI"
1650 "AABCCAAASggAAE8IAABcCAAAaggAAHkIAACICAAAlggAAKQIAACyCAAAwAgAAM4IAADcCAAA6ggA"
1651 "APgIAAD7CAAA/wgAABcJAAAuCQAARQkAAFQJAAB4CQAAmAkAALsJAADSCQAA5gkAAPoJAAAVCgAA"
1652 "KQoAADsKAABCCgAASgoAAFIKAABbCgAAZAoAAGwKAAB0CgAAfAoAAIQKAACMCgAAlAoAAJwKAACk"
1653 "CgAArQoAALcKAADACgAAwwoAAMcKAADcCgAA6QoAAPEKAAD3CgAA/QoAAAMLAAAJCwAAEAsAABcL"
1654 "AAAdCwAAIwsAACkLAAAvCwAANQsAADsLAABBCwAARwsAAE0LAABSCwAAWwsAAF4LAABoCwAAbwsA"
1655 "ABEAAAASAAAAEwAAABQAAAAVAAAAFgAAABcAAAAYAAAAGQAAABoAAAAbAAAAHAAAAC4AAAAwAAAA"
1656 "DwAAAAkAAAAAAAAAEAAAAAoAAACoBwAALgAAAAwAAAAAAAAALwAAAAwAAACoBwAALwAAAAwAAACw"
1657 "BwAAAgAJADUAAAACAAkANgAAAAIACQA3AAAAAgAJADgAAAACAAkAOQAAAAIACQA6AAAAAgAJADsA"
1658 "AAACAAkAPAAAAAIACQA9AAAAAgAJAD4AAAACAAkAPwAAAAIACQBAAAAACwAHAEIAAAAAAAIAAQAA"
1659 "AAAAAwAeAAAAAQACAAEAAAABAAMAHgAAAAIAAgAAAAAAAgACAAEAAAADAAIAAQAAAAMAAgAfAAAA"
1660 "AwACACAAAAADAAIAIQAAAAMAAgAiAAAAAwACACMAAAADAAIAJAAAAAMAAgAlAAAAAwACACYAAAAD"
1661 "AAIAJwAAAAMAAgAoAAAAAwACACkAAAADAAIAKgAAAAMABAA0AAAABwADAEMAAAAIAAIAAQAAAAoA"
1662 "AgABAAAACgABADIAAAAKAAAARQAAAAAAAAAAAAAACAAAAAAAAAAdAAAAaAcAALYHAAAAAAAAAQAA"
1663 "AAAAAAAIAAAAAAAAAB0AAAB4BwAAxAcAAAAAAAACAAAAAAAAAAgAAAAAAAAAHQAAAIgHAADSBwAA"
1664 "AAAAAAMAAAAAAAAACAAAAAAAAAAdAAAAmAcAAPoHAAAAAAAAAAAAAAEAAAAAAAAArAYAADEAAAAa"
1665 "AAMAaQAAABoABABpAAEAGgAHAGkABAAaAAgAaQAFABoACQBpAAYAGgAKAGkABwAaAAsAaQAIABoA"
1666 "DABpAAkAGgANAGkACgAaAA4AaQALABoABQBpAAIAGgAGAGkAAwAOAAAAAQABAAEAAACSBgAABAAA"
1667 "AHAQFQAAAA4ABAABAAIAAACWBgAAFwAAAGIADAAiAQoAcBAWAAEAGgICAG4gFwAhAG4gFwAxAG4Q"
1668 "GAABAAwBbiAUABAADgAAAAEAAQABAAAAngYAAAQAAABwEBUAAAAOAAIAAQACAAAAogYAAAYAAABi"
1669 "AAwAbiAUABAADgABAAEAAQAAAKgGAAAEAAAAcBAVAAAADgABAAEAAQAAALsGAAAEAAAAcBAVAAAA"
1670 "DgABAAAAAQAAAL8GAAAGAAAAYgAAAHEQAwAAAA4AAQAAAAEAAADEBgAABgAAAGIAAQBxEAMAAAAO"
1671 "AAEAAAABAAAA8QYAAAYAAABiAAIAcRABAAAADgABAAAAAQAAAPYGAAAGAAAAYgADAHEQAwAAAA4A"
1672 "AQAAAAEAAADJBgAABgAAAGIABABxEAMAAAAOAAEAAAABAAAAzgYAAAYAAABiAAEAcRADAAAADgAB"
1673 "AAAAAQAAANMGAAAGAAAAYgAGAHEQAwAAAA4AAQAAAAEAAADYBgAABgAAAGIABwBxEAMAAAAOAAEA"
1674 "AAABAAAA3QYAAAYAAABiAAgAcRABAAAADgABAAAAAQAAAOIGAAAGAAAAYgAJAHEQAwAAAA4AAQAA"
1675 "AAEAAADnBgAABgAAAGIACgBxEAMAAAAOAAEAAAABAAAA7AYAAAYAAABiAAsAcRABAAAADgABAAEA"
1676 "AAAAAPsGAAAlAAAAcQAHAAAAcQAIAAAAcQALAAAAcQAMAAAAcQANAAAAcQAOAAAAcQAPAAAAcQAQ"
1677 "AAAAcQARAAAAcQASAAAAcQAJAAAAcQAKAAAADgAnAA4AKQFFDgEWDwAhAA4AIwFFDloAEgAOABMA"
1678 "DktLS0tLS0tLS0tLABEADgAuAA5aADIADloANgAOWgA6AA5aAD4ADloAQgAOWgBGAA5aAEoADloA"
1679 "TgAOWgBSAA5aAFYADloAWgAOWgBeATQOPDw8PDw8PDw8PDw8AAIEAUYYAwIFAjEECEEXLAIFAjEE"
1680 "CEEXKwIFAjEECEEXLQIGAUYcAxgAGAEYAgAAAAIAAAAMBwAAEgcAAAIAAAAMBwAAGwcAAAIAAAAM"
1681 "BwAAJAcAAAEAAAAtBwAAPAcAAAAAAAAAAAAAAAAAAEgHAAAAAAAAAAAAAAAAAABUBwAAAAAAAAAA"
1682 "AAAAAAAAYAcAAAAAAAAAAAAAAAAAAAEAAAAJAAAAAQAAAA0AAAACAACAgASsCAEIxAgAAAIAAoCA"
1683 "BIQJAQicCQwAAgAACQEJAQkBCQEJAQkBCQEJAQkBCQEJAQkEiIAEuAcBgIAEuAkAAA4ABoCABNAJ"
1684 "AQnoCQAJhAoACaAKAAm8CgAJ2AoACfQKAAmQCwAJrAsACcgLAAnkCwAJgAwACZwMAAm4DAg8Y2xp"
1685 "bml0PgAGPGluaXQ+AANBQUEAC0hlbGxvIFdvcmxkAAxIZWxsbyBXb3JsZDEADUhlbGxvIFdvcmxk"
1686 "MTAADUhlbGxvIFdvcmxkMTEADEhlbGxvIFdvcmxkMgAMSGVsbG8gV29ybGQzAAxIZWxsbyBXb3Js"
1687 "ZDQADEhlbGxvIFdvcmxkNQAMSGVsbG8gV29ybGQ2AAxIZWxsbyBXb3JsZDcADEhlbGxvIFdvcmxk"
1688 "OAAMSGVsbG8gV29ybGQ5AAFMAAJMTAAWTE1hbnlNZXRob2RzJFByaW50ZXIyOwAVTE1hbnlNZXRo"
1689 "b2RzJFByaW50ZXI7ABVMTWFueU1ldGhvZHMkU3RyaW5nczsADUxNYW55TWV0aG9kczsAIkxkYWx2"
1690 "aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNs"
1691 "YXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNzZXM7ABVMamF2YS9pby9QcmludFN0"
1692 "cmVhbTsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABlMamF2YS9sYW5n"
1693 "L1N0cmluZ0J1aWxkZXI7ABJMamF2YS9sYW5nL1N5c3RlbTsAEE1hbnlNZXRob2RzLmphdmEABVBy"
1694 "aW50AAZQcmludDAABlByaW50MQAHUHJpbnQxMAAHUHJpbnQxMQAGUHJpbnQyAAZQcmludDMABlBy"
1695 "aW50NAAGUHJpbnQ1AAZQcmludDYABlByaW50NwAGUHJpbnQ4AAZQcmludDkAB1ByaW50ZXIACFBy"
1696 "aW50ZXIyAAdTdHJpbmdzAAFWAAJWTAATW0xqYXZhL2xhbmcvU3RyaW5nOwALYWNjZXNzRmxhZ3MA"
1697 "BmFwcGVuZAAEYXJncwAEbWFpbgAEbXNnMAAEbXNnMQAFbXNnMTAABW1zZzExAARtc2cyAARtc2cz"
1698 "AARtc2c0AARtc2c1AARtc2c2AARtc2c3AARtc2c4AARtc2c5AARuYW1lAANvdXQAB3ByaW50bG4A"
1699 "AXMACHRvU3RyaW5nAAV2YWx1ZQBffn5EOHsibWluLWFwaSI6MTAwMDAsInNoYS0xIjoiZmViODZj"
1700 "MDA2ZWZhY2YxZDc5ODRiODVlMTc5MGZlZjdhNzY3YWViYyIsInZlcnNpb24iOiJ2MS4xLjUtZGV2"
1701 "In0AEAAAAAAAAAABAAAAAAAAAAEAAABIAAAAcAAAAAIAAAAOAAAAkAEAAAMAAAAFAAAAyAEAAAQA"
1702 "AAANAAAABAIAAAUAAAAZAAAAbAIAAAYAAAAEAAAANAMAAAEgAAAUAAAAuAMAAAMgAAAUAAAAkgYA"
1703 "AAQgAAAFAAAADAcAAAMQAAAEAAAAOQcAAAYgAAAEAAAAaAcAAAEQAAACAAAAqAcAAAAgAAAEAAAA"
1704 "tgcAAAIgAABIAAAAOAgAAAAQAAABAAAA0AsAAAAAAAA=";
1705
1706static void WriteBase64ToFile(const char* base64, File* file) {
1707 // Decode base64.
1708 CHECK(base64 != nullptr);
1709 size_t length;
1710 std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
1711 CHECK(bytes != nullptr);
1712 if (!file->WriteFully(bytes.get(), length)) {
1713 PLOG(FATAL) << "Failed to write base64 as file";
1714 }
1715}
1716
1717TEST_F(Dex2oatTest, CompactDexGenerationFailure) {
1718 ScratchFile temp_dex;
1719 WriteBase64ToFile(kDuplicateMethodInputDex, temp_dex.GetFile());
1720 std::string out_dir = GetScratchDir();
1721 const std::string oat_filename = out_dir + "/base.oat";
1722 // The dex won't pass the method verifier, only use the verify filter.
1723 GenerateOdexForTest(temp_dex.GetFilename(),
1724 oat_filename,
1725 CompilerFilter::Filter::kVerify,
1726 { },
1727 true, // expect_success
1728 false, // use_fd
1729 [](const OatFile& o) {
1730 CHECK(o.ContainsDexCode());
1731 });
1732 // Open our generated oat file.
1733 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01001734 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1735 oat_filename.c_str(),
Mathieu Chartier05f90d12018-02-07 13:47:17 -08001736 oat_filename.c_str(),
1737 nullptr,
1738 nullptr,
1739 false,
1740 /*low_4gb*/false,
1741 temp_dex.GetFilename().c_str(),
1742 &error_msg));
1743 ASSERT_TRUE(odex_file != nullptr);
1744 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1745 ASSERT_EQ(oat_dex_files.size(), 1u);
1746 // The dexes should have failed to convert to compact dex.
1747 for (const OatDexFile* oat_dex : oat_dex_files) {
1748 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1749 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1750 ASSERT_TRUE(!dex_file->IsCompactDexFile());
1751 }
1752}
1753
Mathieu Chartiercda83be2018-03-01 23:55:55 -08001754TEST_F(Dex2oatTest, CompactDexGenerationFailureMultiDex) {
1755 // Create a multidex file with only one dex that gets rejected for cdex conversion.
1756 ScratchFile apk_file;
1757 {
1758 FILE* file = fdopen(apk_file.GetFd(), "w+b");
1759 ZipWriter writer(file);
1760 // Add vdex to zip.
1761 writer.StartEntry("classes.dex", ZipWriter::kCompress);
1762 size_t length = 0u;
1763 std::unique_ptr<uint8_t[]> bytes(DecodeBase64(kDuplicateMethodInputDex, &length));
1764 ASSERT_GE(writer.WriteBytes(&bytes[0], length), 0);
1765 writer.FinishEntry();
1766 writer.StartEntry("classes2.dex", ZipWriter::kCompress);
1767 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1768 ASSERT_GE(writer.WriteBytes(dex->Begin(), dex->Size()), 0);
1769 writer.FinishEntry();
1770 writer.Finish();
1771 ASSERT_EQ(apk_file.GetFile()->Flush(), 0);
1772 }
1773 const std::string dex_location = apk_file.GetFilename();
1774 const std::string odex_location = GetOdexDir() + "/output.odex";
1775 GenerateOdexForTest(dex_location,
1776 odex_location,
1777 CompilerFilter::kQuicken,
1778 { "--compact-dex-level=fast" },
1779 true);
1780}
1781
Andreas Gampe25419b52018-02-08 21:30:26 -08001782TEST_F(Dex2oatTest, StderrLoggerOutput) {
1783 std::string dex_location = GetScratchDir() + "/Dex2OatStderrLoggerTest.jar";
1784 std::string odex_location = GetOdexDir() + "/Dex2OatStderrLoggerTest.odex";
1785
1786 // Test file doesn't matter.
1787 Copy(GetDexSrc1(), dex_location);
1788
1789 GenerateOdexForTest(dex_location,
1790 odex_location,
1791 CompilerFilter::kQuicken,
1792 { "--runtime-arg", "-Xuse-stderr-logger" },
1793 true);
1794 // Look for some random part of dex2oat logging. With the stderr logger this should be captured,
1795 // even on device.
1796 EXPECT_NE(std::string::npos, output_.find("dex2oat took"));
1797}
1798
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001799TEST_F(Dex2oatTest, VerifyCompilationReason) {
1800 std::string dex_location = GetScratchDir() + "/Dex2OatCompilationReason.jar";
1801 std::string odex_location = GetOdexDir() + "/Dex2OatCompilationReason.odex";
1802
1803 // Test file doesn't matter.
1804 Copy(GetDexSrc1(), dex_location);
1805
1806 GenerateOdexForTest(dex_location,
1807 odex_location,
1808 CompilerFilter::kVerify,
1809 { "--compilation-reason=install" },
1810 true);
1811 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01001812 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1813 odex_location.c_str(),
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001814 odex_location.c_str(),
1815 nullptr,
1816 nullptr,
1817 false,
1818 /*low_4gb*/false,
1819 dex_location.c_str(),
1820 &error_msg));
1821 ASSERT_TRUE(odex_file != nullptr);
1822 ASSERT_STREQ("install", odex_file->GetCompilationReason());
1823}
1824
1825TEST_F(Dex2oatTest, VerifyNoCompilationReason) {
1826 std::string dex_location = GetScratchDir() + "/Dex2OatNoCompilationReason.jar";
1827 std::string odex_location = GetOdexDir() + "/Dex2OatNoCompilationReason.odex";
1828
1829 // Test file doesn't matter.
1830 Copy(GetDexSrc1(), dex_location);
1831
1832 GenerateOdexForTest(dex_location,
1833 odex_location,
1834 CompilerFilter::kVerify,
1835 {},
1836 true);
1837 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01001838 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1839 odex_location.c_str(),
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001840 odex_location.c_str(),
1841 nullptr,
1842 nullptr,
1843 false,
1844 /*low_4gb*/false,
1845 dex_location.c_str(),
1846 &error_msg));
1847 ASSERT_TRUE(odex_file != nullptr);
1848 ASSERT_EQ(nullptr, odex_file->GetCompilationReason());
1849}
1850
Mathieu Chartier792111c2018-02-15 13:02:15 -08001851TEST_F(Dex2oatTest, DontExtract) {
1852 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1853 std::string error_msg;
1854 const std::string out_dir = GetScratchDir();
1855 const std::string dex_location = dex->GetLocation();
1856 const std::string odex_location = out_dir + "/base.oat";
1857 const std::string vdex_location = out_dir + "/base.vdex";
1858 GenerateOdexForTest(dex_location,
1859 odex_location,
1860 CompilerFilter::Filter::kVerify,
1861 { "--copy-dex-files=false" },
1862 true, // expect_success
1863 false, // use_fd
1864 [](const OatFile&) {
1865 });
1866 {
1867 // Check the vdex doesn't have dex.
1868 std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location.c_str(),
1869 /*writable*/ false,
1870 /*low_4gb*/ false,
1871 /*unquicken*/ false,
1872 &error_msg));
1873 ASSERT_TRUE(vdex != nullptr);
Nicolas Geoffray3a293552018-03-02 10:52:16 +00001874 EXPECT_FALSE(vdex->HasDexSection()) << output_;
Mathieu Chartier792111c2018-02-15 13:02:15 -08001875 }
Nicolas Geoffray30025092018-04-19 14:43:29 +01001876 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1877 odex_location.c_str(),
Mathieu Chartier792111c2018-02-15 13:02:15 -08001878 odex_location.c_str(),
1879 nullptr,
1880 nullptr,
1881 false,
1882 /*low_4gb*/ false,
1883 dex_location.c_str(),
1884 &error_msg));
1885 ASSERT_TRUE(odex_file != nullptr) << dex_location;
1886 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1887 ASSERT_EQ(oat_dex_files.size(), 1u);
1888 // Verify that the oat file can still open the dex files.
1889 for (const OatDexFile* oat_dex : oat_dex_files) {
1890 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1891 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1892 }
1893 // Create a dm file and use it to verify.
1894 // Add produced artifacts to a zip file that doesn't contain the classes.dex.
1895 ScratchFile dm_file;
1896 {
1897 std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_location.c_str()));
1898 ASSERT_TRUE(vdex_file != nullptr);
1899 ASSERT_GT(vdex_file->GetLength(), 0u);
1900 FILE* file = fdopen(dm_file.GetFd(), "w+b");
1901 ZipWriter writer(file);
1902 auto write_all_bytes = [&](File* file) {
1903 std::unique_ptr<uint8_t[]> bytes(new uint8_t[file->GetLength()]);
1904 ASSERT_TRUE(file->ReadFully(&bytes[0], file->GetLength()));
1905 ASSERT_GE(writer.WriteBytes(&bytes[0], file->GetLength()), 0);
1906 };
1907 // Add vdex to zip.
1908 writer.StartEntry(VdexFile::kVdexNameInDmFile, ZipWriter::kCompress);
1909 write_all_bytes(vdex_file.get());
1910 writer.FinishEntry();
1911 writer.Finish();
1912 ASSERT_EQ(dm_file.GetFile()->Flush(), 0);
1913 }
1914
Mathieu Chartier2eabc612018-05-25 14:31:16 -07001915 auto generate_and_check = [&](CompilerFilter::Filter filter) {
1916 GenerateOdexForTest(dex_location,
1917 odex_location,
1918 filter,
1919 { "--dump-timings",
1920 "--dm-file=" + dm_file.GetFilename(),
1921 // Pass -Xuse-stderr-logger have dex2oat output in output_ on target.
1922 "--runtime-arg",
1923 "-Xuse-stderr-logger" },
1924 true, // expect_success
1925 false, // use_fd
1926 [](const OatFile& o) {
1927 CHECK(o.ContainsDexCode());
1928 });
1929 // Check the output for "Fast verify", this is printed from --dump-timings.
1930 std::istringstream iss(output_);
1931 std::string line;
1932 bool found_fast_verify = false;
1933 const std::string kFastVerifyString = "Fast Verify";
1934 while (std::getline(iss, line) && !found_fast_verify) {
1935 found_fast_verify = found_fast_verify || line.find(kFastVerifyString) != std::string::npos;
1936 }
1937 EXPECT_TRUE(found_fast_verify) << "Expected to find " << kFastVerifyString << "\n" << output_;
1938 };
1939
Mathieu Chartier792111c2018-02-15 13:02:15 -08001940 // Generate a quickened dex by using the input dm file to verify.
Mathieu Chartier2eabc612018-05-25 14:31:16 -07001941 generate_and_check(CompilerFilter::Filter::kQuicken);
1942 // Use verify compiler filter to sanity check that FastVerify works for that filter too.
1943 generate_and_check(CompilerFilter::Filter::kVerify);
Mathieu Chartier792111c2018-02-15 13:02:15 -08001944}
1945
Mathieu Chartier2daa1342018-02-20 16:19:28 -08001946// Test that dex files with quickened opcodes aren't dequickened.
1947TEST_F(Dex2oatTest, QuickenedInput) {
1948 std::string error_msg;
1949 ScratchFile temp_dex;
1950 MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [] (DexFile* dex) {
1951 bool mutated_successfully = false;
1952 // Change the dex instructions to make an opcode that spans past the end of the code item.
1953 for (size_t i = 0; i < dex->NumClassDefs(); ++i) {
1954 const DexFile::ClassDef& def = dex->GetClassDef(i);
1955 const uint8_t* data = dex->GetClassData(def);
1956 if (data == nullptr) {
1957 continue;
1958 }
1959 ClassDataItemIterator it(*dex, data);
1960 it.SkipAllFields();
1961 while (it.HasNextMethod()) {
1962 DexFile::CodeItem* item = const_cast<DexFile::CodeItem*>(it.GetMethodCodeItem());
1963 if (item != nullptr) {
1964 CodeItemInstructionAccessor instructions(*dex, item);
1965 // Make a quickened instruction that doesn't run past the end of the code item.
1966 if (instructions.InsnsSizeInCodeUnits() > 2) {
1967 const_cast<Instruction&>(instructions.InstructionAt(0)).SetOpcode(
1968 Instruction::IGET_BYTE_QUICK);
1969 mutated_successfully = true;
1970 }
1971 }
1972 it.Next();
1973 }
1974 }
1975 CHECK(mutated_successfully)
1976 << "Failed to find candidate code item with only one code unit in last instruction.";
1977 });
1978
1979 std::string dex_location = temp_dex.GetFilename();
1980 std::string odex_location = GetOdexDir() + "/quickened.odex";
1981 std::string vdex_location = GetOdexDir() + "/quickened.vdex";
1982 std::unique_ptr<File> vdex_output(OS::CreateEmptyFile(vdex_location.c_str()));
1983 // Quicken the dex
1984 {
1985 std::string input_vdex = "--input-vdex-fd=-1";
1986 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_output->Fd());
1987 GenerateOdexForTest(dex_location,
1988 odex_location,
1989 CompilerFilter::kQuicken,
1990 // Disable cdex since we want to compare against the original dex file
1991 // after unquickening.
1992 { input_vdex, output_vdex, kDisableCompactDex },
1993 /* expect_success */ true,
1994 /* use_fd */ true);
1995 }
1996 // Unquicken by running the verify compiler filter on the vdex file and verify it matches.
1997 std::string odex_location2 = GetOdexDir() + "/unquickened.odex";
1998 std::string vdex_location2 = GetOdexDir() + "/unquickened.vdex";
1999 std::unique_ptr<File> vdex_unquickened(OS::CreateEmptyFile(vdex_location2.c_str()));
2000 {
2001 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_output->Fd());
2002 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_unquickened->Fd());
2003 GenerateOdexForTest(dex_location,
2004 odex_location2,
2005 CompilerFilter::kVerify,
2006 // Disable cdex to avoid needing to write out the shared section.
2007 { input_vdex, output_vdex, kDisableCompactDex },
2008 /* expect_success */ true,
2009 /* use_fd */ true);
2010 }
2011 ASSERT_EQ(vdex_unquickened->Flush(), 0) << "Could not flush and close vdex file";
2012 ASSERT_TRUE(success_);
2013 {
2014 // Check that hte vdex has one dex and compare it to the original one.
2015 std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location2.c_str(),
2016 /*writable*/ false,
2017 /*low_4gb*/ false,
2018 /*unquicken*/ false,
2019 &error_msg));
2020 std::vector<std::unique_ptr<const DexFile>> dex_files;
2021 bool result = vdex->OpenAllDexFiles(&dex_files, &error_msg);
2022 ASSERT_TRUE(result) << error_msg;
2023 ASSERT_EQ(dex_files.size(), 1u) << error_msg;
2024 ScratchFile temp;
2025 ASSERT_TRUE(temp.GetFile()->WriteFully(dex_files[0]->Begin(), dex_files[0]->Size()));
2026 ASSERT_EQ(temp.GetFile()->Flush(), 0) << "Could not flush extracted dex";
2027 EXPECT_EQ(temp.GetFile()->Compare(temp_dex.GetFile()), 0);
2028 }
2029 ASSERT_EQ(vdex_output->FlushCloseOrErase(), 0) << "Could not flush and close";
2030 ASSERT_EQ(vdex_unquickened->FlushCloseOrErase(), 0) << "Could not flush and close";
2031}
2032
Mathieu Chartierd45863a2018-03-21 18:16:36 -07002033// Test that compact dex generation with invalid dex files doesn't crash dex2oat. b/75970654
2034TEST_F(Dex2oatTest, CompactDexInvalidSource) {
2035 ScratchFile invalid_dex;
2036 {
2037 FILE* file = fdopen(invalid_dex.GetFd(), "w+b");
2038 ZipWriter writer(file);
2039 writer.StartEntry("classes.dex", ZipWriter::kAlign32);
2040 DexFile::Header header = {};
2041 StandardDexFile::WriteMagic(header.magic_);
2042 StandardDexFile::WriteCurrentVersion(header.magic_);
2043 header.file_size_ = 4 * KB;
2044 header.data_size_ = 4 * KB;
2045 header.data_off_ = 10 * MB;
2046 header.map_off_ = 10 * MB;
2047 header.class_defs_off_ = 10 * MB;
2048 header.class_defs_size_ = 10000;
2049 ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
2050 writer.FinishEntry();
2051 writer.Finish();
2052 ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
2053 }
2054 const std::string dex_location = invalid_dex.GetFilename();
2055 const std::string odex_location = GetOdexDir() + "/output.odex";
2056 std::string error_msg;
2057 int status = GenerateOdexForTestWithStatus(
2058 {dex_location},
2059 odex_location,
2060 CompilerFilter::kQuicken,
2061 &error_msg,
2062 { "--compact-dex-level=fast" });
2063 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
2064}
2065
Mathieu Chartier14e7bad2018-03-22 14:33:20 -07002066// Test that dex2oat with a CompactDex file in the APK fails.
2067TEST_F(Dex2oatTest, CompactDexInZip) {
2068 CompactDexFile::Header header = {};
2069 CompactDexFile::WriteMagic(header.magic_);
2070 CompactDexFile::WriteCurrentVersion(header.magic_);
2071 header.file_size_ = sizeof(CompactDexFile::Header);
2072 header.data_off_ = 10 * MB;
2073 header.map_off_ = 10 * MB;
2074 header.class_defs_off_ = 10 * MB;
2075 header.class_defs_size_ = 10000;
2076 // Create a zip containing the invalid dex.
2077 ScratchFile invalid_dex_zip;
2078 {
2079 FILE* file = fdopen(invalid_dex_zip.GetFd(), "w+b");
2080 ZipWriter writer(file);
2081 writer.StartEntry("classes.dex", ZipWriter::kCompress);
2082 ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
2083 writer.FinishEntry();
2084 writer.Finish();
2085 ASSERT_EQ(invalid_dex_zip.GetFile()->Flush(), 0);
2086 }
2087 // Create the dex file directly.
2088 ScratchFile invalid_dex;
2089 {
2090 ASSERT_GE(invalid_dex.GetFile()->WriteFully(&header, sizeof(header)), 0);
2091 ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
2092 }
2093 std::string error_msg;
2094 int status = 0u;
2095
2096 status = GenerateOdexForTestWithStatus(
2097 { invalid_dex_zip.GetFilename() },
2098 GetOdexDir() + "/output_apk.odex",
2099 CompilerFilter::kQuicken,
2100 &error_msg,
2101 { "--compact-dex-level=fast" });
2102 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
2103
2104 status = GenerateOdexForTestWithStatus(
2105 { invalid_dex.GetFilename() },
2106 GetOdexDir() + "/output.odex",
2107 CompilerFilter::kQuicken,
2108 &error_msg,
2109 { "--compact-dex-level=fast" });
2110 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
2111}
2112
Mathieu Chartierf85b3db2018-04-02 18:16:21 -07002113TEST_F(Dex2oatTest, AppImageNoProfile) {
2114 ScratchFile app_image_file;
2115 const std::string out_dir = GetScratchDir();
2116 const std::string odex_location = out_dir + "/base.odex";
2117 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2118 odex_location,
2119 CompilerFilter::Filter::kSpeedProfile,
2120 { "--app-image-fd=" + std::to_string(app_image_file.GetFd()) },
2121 true, // expect_success
2122 false, // use_fd
2123 [](const OatFile&) {});
2124 // Open our generated oat file.
2125 std::string error_msg;
Nicolas Geoffray30025092018-04-19 14:43:29 +01002126 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
2127 odex_location.c_str(),
Mathieu Chartierf85b3db2018-04-02 18:16:21 -07002128 odex_location.c_str(),
2129 nullptr,
2130 nullptr,
2131 false,
2132 /*low_4gb*/false,
2133 odex_location.c_str(),
2134 &error_msg));
2135 ASSERT_TRUE(odex_file != nullptr);
2136 ImageHeader header = {};
2137 ASSERT_TRUE(app_image_file.GetFile()->PreadFully(
2138 reinterpret_cast<void*>(&header),
2139 sizeof(header),
2140 /*offset*/ 0u)) << app_image_file.GetFile()->GetLength();
2141 EXPECT_GT(header.GetImageSection(ImageHeader::kSectionObjects).Size(), 0u);
2142 EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtMethods).Size(), 0u);
2143 EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtFields).Size(), 0u);
2144}
2145
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002146TEST_F(Dex2oatClassLoaderContextTest, StoredClassLoaderContext) {
Mathieu Chartierc4440772018-04-16 14:40:56 -07002147 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("MultiDex");
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002148 const std::string out_dir = GetScratchDir();
2149 const std::string odex_location = out_dir + "/base.odex";
Mathieu Chartierc4440772018-04-16 14:40:56 -07002150 const std::string valid_context = "PCL[" + dex_files[0]->GetLocation() + "]";
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002151 const std::string stored_context = "PCL[/system/not_real_lib.jar]";
Mathieu Chartierc4440772018-04-16 14:40:56 -07002152 std::string expected_stored_context = "PCL[";
2153 size_t index = 1;
2154 for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
2155 const bool is_first = index == 1u;
2156 if (!is_first) {
2157 expected_stored_context += ":";
2158 }
2159 expected_stored_context += "/system/not_real_lib.jar";
2160 if (!is_first) {
2161 expected_stored_context += "!classes" + std::to_string(index) + ".dex";
2162 }
2163 expected_stored_context += "*" + std::to_string(dex_file->GetLocationChecksum());
2164 ++index;
2165 }
2166 expected_stored_context += + "]";
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002167 // The class path should not be valid and should fail being stored.
2168 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2169 odex_location,
2170 CompilerFilter::Filter::kQuicken,
2171 { "--class-loader-context=" + stored_context },
2172 true, // expect_success
2173 false, // use_fd
2174 [&](const OatFile& oat_file) {
Mathieu Chartierc4440772018-04-16 14:40:56 -07002175 EXPECT_NE(oat_file.GetClassLoaderContext(), stored_context) << output_;
2176 EXPECT_NE(oat_file.GetClassLoaderContext(), valid_context) << output_;
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002177 });
2178 // The stored context should match what we expect even though it's invalid.
2179 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2180 odex_location,
2181 CompilerFilter::Filter::kQuicken,
2182 { "--class-loader-context=" + valid_context,
2183 "--stored-class-loader-context=" + stored_context },
2184 true, // expect_success
2185 false, // use_fd
2186 [&](const OatFile& oat_file) {
Mathieu Chartierc4440772018-04-16 14:40:56 -07002187 EXPECT_EQ(oat_file.GetClassLoaderContext(), expected_stored_context) << output_;
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07002188 });
2189}
2190
Andreas Gampee1459ae2016-06-29 09:36:30 -07002191} // namespace art