blob: a48d15d40afeeb46a1a694369d388c1090e245f4 [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 Sehr8f4b0562018-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 Sehre6564f42018-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"
Calin Juravle33083d62017-01-18 15:29:12 -080041#include "jit/profile_compilation_info.h"
Andreas Gampe67f02822016-06-24 21:05:23 -070042#include "oat.h"
43#include "oat_file.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;
Calin Juravle5a0381f2020-11-23 19:21:09 -080050
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_ = "";
Andreas Gampee1459ae2016-06-29 09:36:30 -070062 }
63
64 protected:
Mathieu Chartier9e050df2017-08-09 10:05:47 -070065 int GenerateOdexForTestWithStatus(const std::vector<std::string>& dex_locations,
Andreas Gampef7882972017-03-20 16:35:24 -070066 const std::string& odex_location,
67 CompilerFilter::Filter filter,
68 std::string* error_msg,
69 const std::vector<std::string>& extra_args = {},
70 bool use_fd = false) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080071 std::unique_ptr<File> oat_file;
Andreas Gampee1459ae2016-06-29 09:36:30 -070072 std::vector<std::string> args;
Mathieu Chartier9e050df2017-08-09 10:05:47 -070073 // Add dex file args.
74 for (const std::string& dex_location : dex_locations) {
75 args.push_back("--dex-file=" + dex_location);
76 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080077 if (use_fd) {
78 oat_file.reset(OS::CreateEmptyFile(odex_location.c_str()));
79 CHECK(oat_file != nullptr) << odex_location;
80 args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
Mathieu Chartier046854b2017-03-01 17:16:22 -080081 args.push_back("--oat-location=" + odex_location);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080082 } else {
83 args.push_back("--oat-file=" + odex_location);
84 }
Andreas Gampee1459ae2016-06-29 09:36:30 -070085 args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
86 args.push_back("--runtime-arg");
87 args.push_back("-Xnorelocate");
88
89 args.insert(args.end(), extra_args.begin(), extra_args.end());
90
Calin Juravle5a0381f2020-11-23 19:21:09 -080091 int status = Dex2Oat(args, &output_, error_msg);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080092 if (oat_file != nullptr) {
Andreas Gampef7882972017-03-20 16:35:24 -070093 CHECK_EQ(oat_file->FlushClose(), 0) << "Could not flush and close oat file";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080094 }
Andreas Gampef7882972017-03-20 16:35:24 -070095 return status;
96 }
Andreas Gampee1459ae2016-06-29 09:36:30 -070097
Andreas Gampe641a4732017-08-24 13:21:35 -070098 void GenerateOdexForTest(
99 const std::string& dex_location,
100 const std::string& odex_location,
101 CompilerFilter::Filter filter,
102 const std::vector<std::string>& extra_args = {},
103 bool expect_success = true,
104 bool use_fd = false) {
105 GenerateOdexForTest(dex_location,
106 odex_location,
107 filter,
108 extra_args,
109 expect_success,
110 use_fd,
111 [](const OatFile&) {});
112 }
113
Andreas Gampe80ddf272018-01-11 09:41:00 -0800114 bool test_accepts_odex_file_on_failure = false;
115
Andreas Gampe641a4732017-08-24 13:21:35 -0700116 template <typename T>
117 void GenerateOdexForTest(
118 const std::string& dex_location,
119 const std::string& odex_location,
120 CompilerFilter::Filter filter,
121 const std::vector<std::string>& extra_args,
122 bool expect_success,
123 bool use_fd,
124 T check_oat) {
Andreas Gampef7882972017-03-20 16:35:24 -0700125 std::string error_msg;
Mathieu Chartier9e050df2017-08-09 10:05:47 -0700126 int status = GenerateOdexForTestWithStatus({dex_location},
Andreas Gampef7882972017-03-20 16:35:24 -0700127 odex_location,
128 filter,
129 &error_msg,
130 extra_args,
131 use_fd);
Andreas Gampe80ddf272018-01-11 09:41:00 -0800132 bool success = (WIFEXITED(status) && WEXITSTATUS(status) == 0);
Andreas Gampee1459ae2016-06-29 09:36:30 -0700133 if (expect_success) {
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800134 ASSERT_TRUE(success) << error_msg << std::endl << output_;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700135
136 // Verify the odex file was generated as expected.
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +0100137 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
138 odex_location.c_str(),
Andreas Gampee1459ae2016-06-29 09:36:30 -0700139 odex_location.c_str(),
140 nullptr,
141 nullptr,
142 false,
143 /*low_4gb*/false,
144 dex_location.c_str(),
145 &error_msg));
146 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
147
148 CheckFilter(filter, odex_file->GetCompilerFilter());
Calin Juravle1ce70852017-06-28 10:59:03 -0700149 check_oat(*(odex_file.get()));
Andreas Gampee1459ae2016-06-29 09:36:30 -0700150 } else {
151 ASSERT_FALSE(success) << output_;
152
153 error_msg_ = error_msg;
154
Andreas Gampe80ddf272018-01-11 09:41:00 -0800155 if (!test_accepts_odex_file_on_failure) {
156 // Verify there's no loadable odex file.
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +0100157 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
158 odex_location.c_str(),
Andreas Gampe80ddf272018-01-11 09:41:00 -0800159 odex_location.c_str(),
160 nullptr,
161 nullptr,
162 false,
163 /*low_4gb*/false,
164 dex_location.c_str(),
165 &error_msg));
166 ASSERT_TRUE(odex_file.get() == nullptr);
167 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700168 }
169 }
170
Calin Juravle1ccf6132017-08-02 17:46:53 -0700171 // Check the input compiler filter against the generated oat file's filter. May be overridden
Andreas Gampee1459ae2016-06-29 09:36:30 -0700172 // in subclasses when equality is not expected.
173 virtual void CheckFilter(CompilerFilter::Filter expected, CompilerFilter::Filter actual) {
174 EXPECT_EQ(expected, actual);
175 }
176
Andreas Gampee1459ae2016-06-29 09:36:30 -0700177 std::string output_ = "";
178 std::string error_msg_ = "";
Andreas Gampee1459ae2016-06-29 09:36:30 -0700179};
180
181class Dex2oatSwapTest : public Dex2oatTest {
182 protected:
183 void RunTest(bool use_fd, bool expect_use, const std::vector<std::string>& extra_args = {}) {
184 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
185 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
186
Andreas Gampe7adeda82016-07-25 08:27:35 -0700187 Copy(GetTestDexFileName(), dex_location);
Andreas Gampee1459ae2016-06-29 09:36:30 -0700188
189 std::vector<std::string> copy(extra_args);
190
191 std::unique_ptr<ScratchFile> sf;
192 if (use_fd) {
193 sf.reset(new ScratchFile());
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800194 copy.push_back(android::base::StringPrintf("--swap-fd=%d", sf->GetFd()));
Andreas Gampee1459ae2016-06-29 09:36:30 -0700195 } else {
196 std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
197 copy.push_back("--swap-file=" + swap_location);
198 }
199 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, copy);
200
201 CheckValidity();
Andreas Gampee1459ae2016-06-29 09:36:30 -0700202 CheckResult(expect_use);
203 }
204
Andreas Gampe7adeda82016-07-25 08:27:35 -0700205 virtual std::string GetTestDexFileName() {
Vladimir Marko15357702017-02-09 10:37:31 +0000206 return Dex2oatEnvironmentTest::GetTestDexFileName("VerifierDeps");
Andreas Gampe7adeda82016-07-25 08:27:35 -0700207 }
208
209 virtual void CheckResult(bool expect_use) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700210 if (kIsTargetBuild) {
211 CheckTargetResult(expect_use);
212 } else {
213 CheckHostResult(expect_use);
214 }
215 }
216
Andreas Gampe7adeda82016-07-25 08:27:35 -0700217 virtual void CheckTargetResult(bool expect_use ATTRIBUTE_UNUSED) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700218 // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
219 // something for variants with file descriptor where we can control the lifetime of
220 // the swap file and thus take a look at it.
221 }
222
Andreas Gampe7adeda82016-07-25 08:27:35 -0700223 virtual void CheckHostResult(bool expect_use) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700224 if (!kIsTargetBuild) {
225 if (expect_use) {
226 EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
227 << output_;
228 } else {
229 EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
230 << output_;
231 }
232 }
233 }
234
235 // Check whether the dex2oat run was really successful.
Andreas Gampe7adeda82016-07-25 08:27:35 -0700236 virtual void CheckValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700237 if (kIsTargetBuild) {
238 CheckTargetValidity();
239 } else {
240 CheckHostValidity();
241 }
242 }
243
Andreas Gampe7adeda82016-07-25 08:27:35 -0700244 virtual void CheckTargetValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700245 // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
246 // something for variants with file descriptor where we can control the lifetime of
247 // the swap file and thus take a look at it.
248 }
249
250 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
Andreas Gampe7adeda82016-07-25 08:27:35 -0700251 virtual void CheckHostValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700252 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
253 }
254};
255
256TEST_F(Dex2oatSwapTest, DoNotUseSwapDefaultSingleSmall) {
257 RunTest(false /* use_fd */, false /* expect_use */);
258 RunTest(true /* use_fd */, false /* expect_use */);
259}
260
261TEST_F(Dex2oatSwapTest, DoNotUseSwapSingle) {
262 RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
263 RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
264}
265
266TEST_F(Dex2oatSwapTest, DoNotUseSwapSmall) {
267 RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
268 RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
269}
270
271TEST_F(Dex2oatSwapTest, DoUseSwapSingleSmall) {
272 RunTest(false /* use_fd */,
273 true /* expect_use */,
274 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
275 RunTest(true /* use_fd */,
276 true /* expect_use */,
277 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
278}
279
Andreas Gampe7adeda82016-07-25 08:27:35 -0700280class Dex2oatSwapUseTest : public Dex2oatSwapTest {
281 protected:
282 void CheckHostResult(bool expect_use) OVERRIDE {
283 if (!kIsTargetBuild) {
284 if (expect_use) {
285 EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
286 << output_;
287 } else {
288 EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
289 << output_;
290 }
291 }
292 }
293
294 std::string GetTestDexFileName() OVERRIDE {
295 // Use Statics as it has a handful of functions.
296 return CommonRuntimeTest::GetTestDexFileName("Statics");
297 }
298
299 void GrabResult1() {
300 if (!kIsTargetBuild) {
301 native_alloc_1_ = ParseNativeAlloc();
302 swap_1_ = ParseSwap(false /* expected */);
303 } else {
304 native_alloc_1_ = std::numeric_limits<size_t>::max();
305 swap_1_ = 0;
306 }
307 }
308
309 void GrabResult2() {
310 if (!kIsTargetBuild) {
311 native_alloc_2_ = ParseNativeAlloc();
312 swap_2_ = ParseSwap(true /* expected */);
313 } else {
314 native_alloc_2_ = 0;
315 swap_2_ = std::numeric_limits<size_t>::max();
316 }
317 }
318
319 private:
320 size_t ParseNativeAlloc() {
321 std::regex native_alloc_regex("dex2oat took.*native alloc=[^ ]+ \\(([0-9]+)B\\)");
322 std::smatch native_alloc_match;
323 bool found = std::regex_search(output_, native_alloc_match, native_alloc_regex);
324 if (!found) {
325 EXPECT_TRUE(found);
326 return 0;
327 }
328 if (native_alloc_match.size() != 2U) {
329 EXPECT_EQ(native_alloc_match.size(), 2U);
330 return 0;
331 }
332
333 std::istringstream stream(native_alloc_match[1].str());
334 size_t value;
335 stream >> value;
336
337 return value;
338 }
339
340 size_t ParseSwap(bool expected) {
341 std::regex swap_regex("dex2oat took[^\\n]+swap=[^ ]+ \\(([0-9]+)B\\)");
342 std::smatch swap_match;
343 bool found = std::regex_search(output_, swap_match, swap_regex);
344 if (found != expected) {
345 EXPECT_EQ(expected, found);
346 return 0;
347 }
348
349 if (!found) {
350 return 0;
351 }
352
353 if (swap_match.size() != 2U) {
354 EXPECT_EQ(swap_match.size(), 2U);
355 return 0;
356 }
357
358 std::istringstream stream(swap_match[1].str());
359 size_t value;
360 stream >> value;
361
362 return value;
363 }
364
365 protected:
366 size_t native_alloc_1_;
367 size_t native_alloc_2_;
368
369 size_t swap_1_;
370 size_t swap_2_;
371};
372
373TEST_F(Dex2oatSwapUseTest, CheckSwapUsage) {
Andreas Gampef4a67fd2017-05-04 09:55:36 -0700374 // Native memory usage isn't correctly tracked under sanitization.
375 TEST_DISABLED_FOR_MEMORY_TOOL_ASAN();
376
Vladimir Marko57070da2017-02-14 16:16:30 +0000377 // The `native_alloc_2_ >= native_alloc_1_` assertion below may not
Roland Levillain19772bf2017-02-16 11:28:10 +0000378 // hold true on some x86 systems; disable this test while we
379 // investigate (b/29259363).
380 TEST_DISABLED_FOR_X86();
Vladimir Marko57070da2017-02-14 16:16:30 +0000381
Andreas Gampe7adeda82016-07-25 08:27:35 -0700382 RunTest(false /* use_fd */,
383 false /* expect_use */);
384 GrabResult1();
385 std::string output_1 = output_;
386
387 output_ = "";
388
389 RunTest(false /* use_fd */,
390 true /* expect_use */,
391 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
392 GrabResult2();
393 std::string output_2 = output_;
394
395 if (native_alloc_2_ >= native_alloc_1_ || swap_1_ >= swap_2_) {
396 EXPECT_LT(native_alloc_2_, native_alloc_1_);
397 EXPECT_LT(swap_1_, swap_2_);
398
399 LOG(ERROR) << output_1;
400 LOG(ERROR) << output_2;
401 }
402}
403
Andreas Gampe67f02822016-06-24 21:05:23 -0700404class Dex2oatVeryLargeTest : public Dex2oatTest {
405 protected:
406 void CheckFilter(CompilerFilter::Filter input ATTRIBUTE_UNUSED,
407 CompilerFilter::Filter result ATTRIBUTE_UNUSED) OVERRIDE {
408 // Ignore, we'll do our own checks.
409 }
410
411 void RunTest(CompilerFilter::Filter filter,
412 bool expect_large,
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700413 bool expect_downgrade,
Andreas Gampe67f02822016-06-24 21:05:23 -0700414 const std::vector<std::string>& extra_args = {}) {
415 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
416 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700417 std::string app_image_file = GetScratchDir() + "/Test.art";
Andreas Gampe67f02822016-06-24 21:05:23 -0700418
419 Copy(GetDexSrc1(), dex_location);
420
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700421 std::vector<std::string> new_args(extra_args);
422 new_args.push_back("--app-image-file=" + app_image_file);
423 GenerateOdexForTest(dex_location, odex_location, filter, new_args);
Andreas Gampe67f02822016-06-24 21:05:23 -0700424
425 CheckValidity();
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700426 CheckResult(dex_location,
427 odex_location,
428 app_image_file,
429 filter,
430 expect_large,
431 expect_downgrade);
Andreas Gampe67f02822016-06-24 21:05:23 -0700432 }
433
434 void CheckResult(const std::string& dex_location,
435 const std::string& odex_location,
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700436 const std::string& app_image_file,
Andreas Gampe67f02822016-06-24 21:05:23 -0700437 CompilerFilter::Filter filter,
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700438 bool expect_large,
439 bool expect_downgrade) {
440 if (expect_downgrade) {
441 EXPECT_TRUE(expect_large);
442 }
Andreas Gampe67f02822016-06-24 21:05:23 -0700443 // Host/target independent checks.
444 std::string error_msg;
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +0100445 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
446 odex_location.c_str(),
Andreas Gampe67f02822016-06-24 21:05:23 -0700447 odex_location.c_str(),
448 nullptr,
449 nullptr,
450 false,
451 /*low_4gb*/false,
452 dex_location.c_str(),
453 &error_msg));
454 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700455 EXPECT_GT(app_image_file.length(), 0u);
456 std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file.c_str()));
Andreas Gampe67f02822016-06-24 21:05:23 -0700457 if (expect_large) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700458 // Note: we cannot check the following
459 // EXPECT_FALSE(CompilerFilter::IsAotCompilationEnabled(odex_file->GetCompilerFilter()));
Andreas Gampe67f02822016-06-24 21:05:23 -0700460 // The reason is that the filter override currently happens when the dex files are
461 // loaded in dex2oat, which is after the oat file has been started. Thus, the header
462 // store cannot be changed, and the original filter is set in stone.
463
464 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
465 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
466 ASSERT_TRUE(dex_file != nullptr);
467 uint32_t class_def_count = dex_file->NumClassDefs();
468 ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
469 for (uint16_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
470 OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
471 EXPECT_EQ(oat_class.GetType(), OatClassType::kOatClassNoneCompiled);
472 }
473 }
474
475 // If the input filter was "below," it should have been used.
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100476 if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kExtract, filter)) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700477 EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
478 }
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700479
480 // If expect large, make sure the app image isn't generated or is empty.
481 if (file != nullptr) {
482 EXPECT_EQ(file->GetLength(), 0u);
483 }
Andreas Gampe67f02822016-06-24 21:05:23 -0700484 } else {
485 EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700486 ASSERT_TRUE(file != nullptr) << app_image_file;
487 EXPECT_GT(file->GetLength(), 0u);
Andreas Gampe67f02822016-06-24 21:05:23 -0700488 }
489
490 // Host/target dependent checks.
491 if (kIsTargetBuild) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700492 CheckTargetResult(expect_downgrade);
Andreas Gampe67f02822016-06-24 21:05:23 -0700493 } else {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700494 CheckHostResult(expect_downgrade);
Andreas Gampe67f02822016-06-24 21:05:23 -0700495 }
496 }
497
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700498 void CheckTargetResult(bool expect_downgrade ATTRIBUTE_UNUSED) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700499 // TODO: Ignore for now. May do something for fd things.
500 }
501
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700502 void CheckHostResult(bool expect_downgrade) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700503 if (!kIsTargetBuild) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700504 if (expect_downgrade) {
505 EXPECT_NE(output_.find("Very large app, downgrading to"), std::string::npos) << output_;
Andreas Gampe67f02822016-06-24 21:05:23 -0700506 } else {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700507 EXPECT_EQ(output_.find("Very large app, downgrading to"), std::string::npos) << output_;
Andreas Gampe67f02822016-06-24 21:05:23 -0700508 }
509 }
510 }
511
512 // Check whether the dex2oat run was really successful.
513 void CheckValidity() {
514 if (kIsTargetBuild) {
515 CheckTargetValidity();
516 } else {
517 CheckHostValidity();
518 }
519 }
520
521 void CheckTargetValidity() {
522 // TODO: Ignore for now.
523 }
524
525 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
526 void CheckHostValidity() {
527 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
528 }
529};
530
531TEST_F(Dex2oatVeryLargeTest, DontUseVeryLarge) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700532 RunTest(CompilerFilter::kAssumeVerified, false, false);
533 RunTest(CompilerFilter::kExtract, false, false);
534 RunTest(CompilerFilter::kQuicken, false, false);
535 RunTest(CompilerFilter::kSpeed, false, false);
Andreas Gampe67f02822016-06-24 21:05:23 -0700536
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700537 RunTest(CompilerFilter::kAssumeVerified, false, false, { "--very-large-app-threshold=10000000" });
538 RunTest(CompilerFilter::kExtract, false, false, { "--very-large-app-threshold=10000000" });
539 RunTest(CompilerFilter::kQuicken, false, false, { "--very-large-app-threshold=10000000" });
540 RunTest(CompilerFilter::kSpeed, false, false, { "--very-large-app-threshold=10000000" });
Andreas Gampe67f02822016-06-24 21:05:23 -0700541}
542
543TEST_F(Dex2oatVeryLargeTest, UseVeryLarge) {
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700544 RunTest(CompilerFilter::kAssumeVerified, true, false, { "--very-large-app-threshold=100" });
545 RunTest(CompilerFilter::kExtract, true, false, { "--very-large-app-threshold=100" });
546 RunTest(CompilerFilter::kQuicken, true, true, { "--very-large-app-threshold=100" });
547 RunTest(CompilerFilter::kSpeed, true, true, { "--very-large-app-threshold=100" });
Andreas Gampe67f02822016-06-24 21:05:23 -0700548}
549
Mathieu Chartier97ab5e32017-02-22 13:35:44 -0800550// Regressin test for b/35665292.
551TEST_F(Dex2oatVeryLargeTest, SpeedProfileNoProfile) {
552 // Test that dex2oat doesn't crash with speed-profile but no input profile.
Mathieu Chartier8cce65a2017-08-17 00:06:39 -0700553 RunTest(CompilerFilter::kSpeedProfile, false, false);
Mathieu Chartier97ab5e32017-02-22 13:35:44 -0800554}
555
Jeff Hao608f2ce2016-10-19 11:17:11 -0700556class Dex2oatLayoutTest : public Dex2oatTest {
557 protected:
558 void CheckFilter(CompilerFilter::Filter input ATTRIBUTE_UNUSED,
559 CompilerFilter::Filter result ATTRIBUTE_UNUSED) OVERRIDE {
560 // Ignore, we'll do our own checks.
561 }
562
Jeff Hao41fba6a2016-11-28 11:53:33 -0800563 // Emits a profile with a single dex file with the given location and a single class index of 1.
564 void GenerateProfile(const std::string& test_profile,
565 const std::string& dex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800566 size_t num_classes,
Jeff Hao41fba6a2016-11-28 11:53:33 -0800567 uint32_t checksum) {
568 int profile_test_fd = open(test_profile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
569 CHECK_GE(profile_test_fd, 0);
570
571 ProfileCompilationInfo info;
572 std::string profile_key = ProfileCompilationInfo::GetProfileDexFileKey(dex_location);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800573 for (size_t i = 0; i < num_classes; ++i) {
Mathieu Chartierea650f32017-05-24 12:04:13 -0700574 info.AddClassIndex(profile_key, checksum, dex::TypeIndex(1 + i), kMaxMethodIds);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800575 }
Jeff Hao41fba6a2016-11-28 11:53:33 -0800576 bool result = info.Save(profile_test_fd);
577 close(profile_test_fd);
578 ASSERT_TRUE(result);
579 }
580
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800581 void CompileProfileOdex(const std::string& dex_location,
582 const std::string& odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800583 const std::string& app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800584 bool use_fd,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800585 size_t num_profile_classes,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000586 const std::vector<std::string>& extra_args = {},
587 bool expect_success = true) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800588 const std::string profile_location = GetScratchDir() + "/primary.prof";
Jeff Hao41fba6a2016-11-28 11:53:33 -0800589 const char* location = dex_location.c_str();
590 std::string error_msg;
591 std::vector<std::unique_ptr<const DexFile>> dex_files;
David Sehr013fd802018-01-11 22:55:24 -0800592 const ArtDexFileLoader dex_file_loader;
593 ASSERT_TRUE(dex_file_loader.Open(
Nicolas Geoffray095c6c92017-10-19 13:59:55 +0100594 location, location, /* verify */ true, /* verify_checksum */ true, &error_msg, &dex_files));
Jeff Hao41fba6a2016-11-28 11:53:33 -0800595 EXPECT_EQ(dex_files.size(), 1U);
596 std::unique_ptr<const DexFile>& dex_file = dex_files[0];
Mathieu Chartier046854b2017-03-01 17:16:22 -0800597 GenerateProfile(profile_location,
598 dex_location,
599 num_profile_classes,
600 dex_file->GetLocationChecksum());
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800601 std::vector<std::string> copy(extra_args);
602 copy.push_back("--profile-file=" + profile_location);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800603 std::unique_ptr<File> app_image_file;
604 if (!app_image_file_name.empty()) {
605 if (use_fd) {
606 app_image_file.reset(OS::CreateEmptyFile(app_image_file_name.c_str()));
607 copy.push_back("--app-image-fd=" + std::to_string(app_image_file->Fd()));
608 } else {
609 copy.push_back("--app-image-file=" + app_image_file_name);
610 }
611 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800612 GenerateOdexForTest(dex_location,
613 odex_location,
614 CompilerFilter::kSpeedProfile,
615 copy,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000616 expect_success,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800617 use_fd);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800618 if (app_image_file != nullptr) {
619 ASSERT_EQ(app_image_file->FlushCloseOrErase(), 0) << "Could not flush and close art file";
620 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800621 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700622
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100623 uint64_t GetImageObjectSectionSize(const std::string& image_file_name) {
Mathieu Chartier046854b2017-03-01 17:16:22 -0800624 EXPECT_FALSE(image_file_name.empty());
625 std::unique_ptr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
626 CHECK(file != nullptr);
627 ImageHeader image_header;
628 const bool success = file->ReadFully(&image_header, sizeof(image_header));
629 CHECK(success);
630 CHECK(image_header.IsValid());
631 ReaderMutexLock mu(Thread::Current(), *Locks::mutator_lock_);
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100632 return image_header.GetObjectsSection().Size();
Mathieu Chartier046854b2017-03-01 17:16:22 -0800633 }
634
635 void RunTest(bool app_image) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800636 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
637 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Mathieu Chartier046854b2017-03-01 17:16:22 -0800638 std::string app_image_file = app_image ? (GetOdexDir() + "/DexOdexNoOat.art"): "";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800639 Copy(GetDexSrc2(), dex_location);
640
Mathieu Chartier046854b2017-03-01 17:16:22 -0800641 uint64_t image_file_empty_profile = 0;
642 if (app_image) {
643 CompileProfileOdex(dex_location,
644 odex_location,
645 app_image_file,
646 /* use_fd */ false,
647 /* num_profile_classes */ 0);
648 CheckValidity();
Mathieu Chartier046854b2017-03-01 17:16:22 -0800649 // Don't check the result since CheckResult relies on the class being in the profile.
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100650 image_file_empty_profile = GetImageObjectSectionSize(app_image_file);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800651 EXPECT_GT(image_file_empty_profile, 0u);
652 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700653
Mathieu Chartier046854b2017-03-01 17:16:22 -0800654 // Small profile.
655 CompileProfileOdex(dex_location,
656 odex_location,
657 app_image_file,
658 /* use_fd */ false,
659 /* num_profile_classes */ 1);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700660 CheckValidity();
Mathieu Chartier046854b2017-03-01 17:16:22 -0800661 CheckResult(dex_location, odex_location, app_image_file);
662
663 if (app_image) {
664 // Test that the profile made a difference by adding more classes.
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +0100665 const uint64_t image_file_small_profile = GetImageObjectSectionSize(app_image_file);
666 ASSERT_LT(image_file_empty_profile, image_file_small_profile);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800667 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700668 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800669
670 void RunTestVDex() {
671 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
672 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
673 std::string vdex_location = GetOdexDir() + "/DexOdexNoOat.vdex";
Mathieu Chartier046854b2017-03-01 17:16:22 -0800674 std::string app_image_file_name = GetOdexDir() + "/DexOdexNoOat.art";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800675 Copy(GetDexSrc2(), dex_location);
676
677 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
678 CHECK(vdex_file1 != nullptr) << vdex_location;
679 ScratchFile vdex_file2;
680 {
681 std::string input_vdex = "--input-vdex-fd=-1";
682 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
683 CompileProfileOdex(dex_location,
684 odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800685 app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800686 /* use_fd */ true,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800687 /* num_profile_classes */ 1,
Mathieu Chartierf1609832018-01-31 03:09:56 -0800688 { input_vdex, output_vdex });
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800689 EXPECT_GT(vdex_file1->GetLength(), 0u);
690 }
691 {
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000692 // Test that vdex and dexlayout fail gracefully.
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800693 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
694 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2.GetFd());
695 CompileProfileOdex(dex_location,
696 odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800697 app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800698 /* use_fd */ true,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800699 /* num_profile_classes */ 1,
Mathieu Chartierd27923c2018-02-08 21:00:03 -0800700 { input_vdex, output_vdex },
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100701 /* expect_success */ true);
702 EXPECT_GT(vdex_file2.GetFile()->GetLength(), 0u);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800703 }
704 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
705 CheckValidity();
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800706 }
707
Mathieu Chartier046854b2017-03-01 17:16:22 -0800708 void CheckResult(const std::string& dex_location,
709 const std::string& odex_location,
710 const std::string& app_image_file_name) {
Jeff Hao608f2ce2016-10-19 11:17:11 -0700711 // Host/target independent checks.
712 std::string error_msg;
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +0100713 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
714 odex_location.c_str(),
Jeff Hao608f2ce2016-10-19 11:17:11 -0700715 odex_location.c_str(),
716 nullptr,
717 nullptr,
718 false,
719 /*low_4gb*/false,
720 dex_location.c_str(),
721 &error_msg));
722 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
723
Jeff Hao042e8982016-10-19 11:17:11 -0700724 const char* location = dex_location.c_str();
725 std::vector<std::unique_ptr<const DexFile>> dex_files;
David Sehr013fd802018-01-11 22:55:24 -0800726 const ArtDexFileLoader dex_file_loader;
727 ASSERT_TRUE(dex_file_loader.Open(
Nicolas Geoffray095c6c92017-10-19 13:59:55 +0100728 location, location, /* verify */ true, /* verify_checksum */ true, &error_msg, &dex_files));
Jeff Hao042e8982016-10-19 11:17:11 -0700729 EXPECT_EQ(dex_files.size(), 1U);
730 std::unique_ptr<const DexFile>& old_dex_file = dex_files[0];
731
Jeff Hao608f2ce2016-10-19 11:17:11 -0700732 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
Jeff Hao042e8982016-10-19 11:17:11 -0700733 std::unique_ptr<const DexFile> new_dex_file = oat_dex_file->OpenDexFile(&error_msg);
734 ASSERT_TRUE(new_dex_file != nullptr);
735 uint32_t class_def_count = new_dex_file->NumClassDefs();
Jeff Hao608f2ce2016-10-19 11:17:11 -0700736 ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
Jeff Hao042e8982016-10-19 11:17:11 -0700737 ASSERT_GE(class_def_count, 2U);
738
Mathieu Chartier24066ec2017-10-21 16:01:08 -0700739 // Make sure the indexes stay the same.
Jeff Hao042e8982016-10-19 11:17:11 -0700740 std::string old_class0 = old_dex_file->PrettyType(old_dex_file->GetClassDef(0).class_idx_);
741 std::string old_class1 = old_dex_file->PrettyType(old_dex_file->GetClassDef(1).class_idx_);
742 std::string new_class0 = new_dex_file->PrettyType(new_dex_file->GetClassDef(0).class_idx_);
743 std::string new_class1 = new_dex_file->PrettyType(new_dex_file->GetClassDef(1).class_idx_);
Mathieu Chartier24066ec2017-10-21 16:01:08 -0700744 EXPECT_EQ(old_class0, new_class0);
745 EXPECT_EQ(old_class1, new_class1);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700746 }
747
Jeff Haoc155b052017-01-17 17:43:29 -0800748 EXPECT_EQ(odex_file->GetCompilerFilter(), CompilerFilter::kSpeedProfile);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800749
750 if (!app_image_file_name.empty()) {
751 // Go peek at the image header to make sure it was large enough to contain the class.
752 std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file_name.c_str()));
753 ImageHeader image_header;
754 bool success = file->ReadFully(&image_header, sizeof(image_header));
755 ASSERT_TRUE(success);
756 ASSERT_TRUE(image_header.IsValid());
Vladimir Markocd87c3e2017-09-05 13:11:57 +0100757 EXPECT_GT(image_header.GetObjectsSection().Size(), 0u);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800758 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700759 }
760
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800761 // Check whether the dex2oat run was really successful.
762 void CheckValidity() {
763 if (kIsTargetBuild) {
764 CheckTargetValidity();
765 } else {
766 CheckHostValidity();
Jeff Hao608f2ce2016-10-19 11:17:11 -0700767 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800768 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700769
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800770 void CheckTargetValidity() {
771 // TODO: Ignore for now.
772 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700773
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800774 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
775 void CheckHostValidity() {
776 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
777 }
778};
Jeff Hao608f2ce2016-10-19 11:17:11 -0700779
780TEST_F(Dex2oatLayoutTest, TestLayout) {
Mathieu Chartier046854b2017-03-01 17:16:22 -0800781 RunTest(/* app-image */ false);
782}
783
784TEST_F(Dex2oatLayoutTest, TestLayoutAppImage) {
785 RunTest(/* app-image */ true);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700786}
787
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800788TEST_F(Dex2oatLayoutTest, TestVdexLayout) {
789 RunTestVDex();
790}
791
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100792class Dex2oatUnquickenTest : public Dex2oatTest {
793 protected:
794 void RunUnquickenMultiDex() {
795 std::string dex_location = GetScratchDir() + "/UnquickenMultiDex.jar";
796 std::string odex_location = GetOdexDir() + "/UnquickenMultiDex.odex";
797 std::string vdex_location = GetOdexDir() + "/UnquickenMultiDex.vdex";
798 Copy(GetTestDexFileName("MultiDex"), dex_location);
799
800 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
801 CHECK(vdex_file1 != nullptr) << vdex_location;
802 // Quicken the dex file into a vdex file.
803 {
804 std::string input_vdex = "--input-vdex-fd=-1";
805 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
806 GenerateOdexForTest(dex_location,
807 odex_location,
808 CompilerFilter::kQuicken,
Mathieu Chartierf1609832018-01-31 03:09:56 -0800809 { input_vdex, output_vdex },
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100810 /* expect_success */ true,
811 /* use_fd */ true);
812 EXPECT_GT(vdex_file1->GetLength(), 0u);
813 }
814 // Unquicken by running the verify compiler filter on the vdex file.
815 {
816 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
817 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
818 GenerateOdexForTest(dex_location,
819 odex_location,
820 CompilerFilter::kVerify,
Mathieu Chartier02129102017-12-22 11:04:01 -0800821 { input_vdex, output_vdex, kDisableCompactDex },
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100822 /* expect_success */ true,
823 /* use_fd */ true);
824 }
825 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
826 CheckResult(dex_location, odex_location);
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100827 }
828
Mathieu Chartierd27923c2018-02-08 21:00:03 -0800829 void RunUnquickenMultiDexCDex() {
830 std::string dex_location = GetScratchDir() + "/UnquickenMultiDex.jar";
831 std::string odex_location = GetOdexDir() + "/UnquickenMultiDex.odex";
832 std::string odex_location2 = GetOdexDir() + "/UnquickenMultiDex2.odex";
833 std::string vdex_location = GetOdexDir() + "/UnquickenMultiDex.vdex";
834 std::string vdex_location2 = GetOdexDir() + "/UnquickenMultiDex2.vdex";
835 Copy(GetTestDexFileName("MultiDex"), dex_location);
836
837 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
838 std::unique_ptr<File> vdex_file2(OS::CreateEmptyFile(vdex_location2.c_str()));
839 CHECK(vdex_file1 != nullptr) << vdex_location;
840 CHECK(vdex_file2 != nullptr) << vdex_location2;
841
842 // Quicken the dex file into a vdex file.
843 {
844 std::string input_vdex = "--input-vdex-fd=-1";
845 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
846 GenerateOdexForTest(dex_location,
847 odex_location,
848 CompilerFilter::kQuicken,
849 { input_vdex, output_vdex, "--compact-dex-level=fast"},
850 /* expect_success */ true,
851 /* use_fd */ true);
852 EXPECT_GT(vdex_file1->GetLength(), 0u);
853 }
854
855 // Unquicken by running the verify compiler filter on the vdex file.
856 {
857 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
858 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2->Fd());
859 GenerateOdexForTest(dex_location,
860 odex_location2,
861 CompilerFilter::kVerify,
862 { input_vdex, output_vdex, "--compact-dex-level=none"},
863 /* expect_success */ true,
864 /* use_fd */ true);
865 }
866 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
867 ASSERT_EQ(vdex_file2->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
868 CheckResult(dex_location, odex_location2);
Mathieu Chartierd27923c2018-02-08 21:00:03 -0800869 }
870
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100871 void CheckResult(const std::string& dex_location, const std::string& odex_location) {
872 std::string error_msg;
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +0100873 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
874 odex_location.c_str(),
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100875 odex_location.c_str(),
876 nullptr,
877 nullptr,
878 false,
879 /*low_4gb*/false,
880 dex_location.c_str(),
881 &error_msg));
882 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
883 ASSERT_GE(odex_file->GetOatDexFiles().size(), 1u);
884
885 // Iterate over the dex files and ensure there is no quickened instruction.
886 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
887 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
888 for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
889 const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
890 const uint8_t* class_data = dex_file->GetClassData(class_def);
891 if (class_data != nullptr) {
892 for (ClassDataItemIterator class_it(*dex_file, class_data);
893 class_it.HasNext();
894 class_it.Next()) {
895 if (class_it.IsAtMethod() && class_it.GetMethodCodeItem() != nullptr) {
Mathieu Chartier0021feb2017-11-07 00:08:52 -0800896 for (const DexInstructionPcPair& inst :
Mathieu Chartier698ebbc2018-01-05 11:00:42 -0800897 CodeItemInstructionAccessor(*dex_file, class_it.GetMethodCodeItem())) {
Mathieu Chartier2daa1342018-02-20 16:19:28 -0800898 ASSERT_FALSE(inst->IsQuickened()) << inst->Opcode() << " " << output_;
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100899 }
900 }
901 }
902 }
903 }
904 }
905 }
906};
907
908TEST_F(Dex2oatUnquickenTest, UnquickenMultiDex) {
909 RunUnquickenMultiDex();
910}
911
Mathieu Chartierd27923c2018-02-08 21:00:03 -0800912TEST_F(Dex2oatUnquickenTest, UnquickenMultiDexCDex) {
913 RunUnquickenMultiDexCDex();
914}
915
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800916class Dex2oatWatchdogTest : public Dex2oatTest {
917 protected:
918 void RunTest(bool expect_success, const std::vector<std::string>& extra_args = {}) {
919 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
920 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
921
922 Copy(GetTestDexFileName(), dex_location);
923
924 std::vector<std::string> copy(extra_args);
925
926 std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
927 copy.push_back("--swap-file=" + swap_location);
Andreas Gampe22fa3762017-10-23 20:58:12 -0700928 copy.push_back("-j512"); // Excessive idle threads just slow down dex2oat.
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800929 GenerateOdexForTest(dex_location,
930 odex_location,
931 CompilerFilter::kSpeed,
932 copy,
933 expect_success);
934 }
935
936 std::string GetTestDexFileName() {
937 return GetDexSrc1();
938 }
939};
940
941TEST_F(Dex2oatWatchdogTest, TestWatchdogOK) {
942 // Check with default.
943 RunTest(true);
944
945 // Check with ten minutes.
946 RunTest(true, { "--watchdog-timeout=600000" });
947}
948
949TEST_F(Dex2oatWatchdogTest, TestWatchdogTrigger) {
Roland Levillain68db2252017-08-14 12:48:47 +0100950 TEST_DISABLED_FOR_MEMORY_TOOL_VALGRIND(); // b/63052624
Andreas Gampe80ddf272018-01-11 09:41:00 -0800951
952 // The watchdog is independent of dex2oat and will not delete intermediates. It is possible
953 // that the compilation succeeds and the file is completely written by the time the watchdog
954 // kills dex2oat (but the dex2oat threads must have been scheduled pretty badly).
955 test_accepts_odex_file_on_failure = true;
956
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800957 // Check with ten milliseconds.
958 RunTest(false, { "--watchdog-timeout=10" });
959}
960
Andreas Gampef7882972017-03-20 16:35:24 -0700961class Dex2oatReturnCodeTest : public Dex2oatTest {
962 protected:
963 int RunTest(const std::vector<std::string>& extra_args = {}) {
964 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
965 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
966
967 Copy(GetTestDexFileName(), dex_location);
968
969 std::string error_msg;
Mathieu Chartier9e050df2017-08-09 10:05:47 -0700970 return GenerateOdexForTestWithStatus({dex_location},
Andreas Gampef7882972017-03-20 16:35:24 -0700971 odex_location,
972 CompilerFilter::kSpeed,
973 &error_msg,
974 extra_args);
975 }
976
977 std::string GetTestDexFileName() {
978 return GetDexSrc1();
979 }
980};
981
982TEST_F(Dex2oatReturnCodeTest, TestCreateRuntime) {
Andreas Gampefd80b172017-04-26 22:25:31 -0700983 TEST_DISABLED_FOR_MEMORY_TOOL(); // b/19100793
Andreas Gampef7882972017-03-20 16:35:24 -0700984 int status = RunTest({ "--boot-image=/this/does/not/exist/yolo.oat" });
985 EXPECT_EQ(static_cast<int>(dex2oat::ReturnCode::kCreateRuntime), WEXITSTATUS(status)) << output_;
986}
987
Calin Juravle1ce70852017-06-28 10:59:03 -0700988class Dex2oatClassLoaderContextTest : public Dex2oatTest {
989 protected:
990 void RunTest(const char* class_loader_context,
991 const char* expected_classpath_key,
992 bool expected_success,
993 bool use_second_source = false) {
994 std::string dex_location = GetUsedDexLocation();
995 std::string odex_location = GetUsedOatLocation();
996
997 Copy(use_second_source ? GetDexSrc2() : GetDexSrc1(), dex_location);
998
999 std::string error_msg;
1000 std::vector<std::string> extra_args;
1001 if (class_loader_context != nullptr) {
1002 extra_args.push_back(std::string("--class-loader-context=") + class_loader_context);
1003 }
1004 auto check_oat = [expected_classpath_key](const OatFile& oat_file) {
1005 ASSERT_TRUE(expected_classpath_key != nullptr);
1006 const char* classpath = oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
1007 ASSERT_TRUE(classpath != nullptr);
1008 ASSERT_STREQ(expected_classpath_key, classpath);
1009 };
1010
1011 GenerateOdexForTest(dex_location,
1012 odex_location,
1013 CompilerFilter::kQuicken,
1014 extra_args,
1015 expected_success,
1016 /*use_fd*/ false,
1017 check_oat);
1018 }
1019
1020 std::string GetUsedDexLocation() {
1021 return GetScratchDir() + "/Context.jar";
1022 }
1023
1024 std::string GetUsedOatLocation() {
1025 return GetOdexDir() + "/Context.odex";
1026 }
1027
Calin Juravle7b0648a2017-07-07 18:40:50 -07001028 const char* kEmptyClassPathKey = "PCL[]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001029};
1030
1031TEST_F(Dex2oatClassLoaderContextTest, InvalidContext) {
1032 RunTest("Invalid[]", /*expected_classpath_key*/ nullptr, /*expected_success*/ false);
1033}
1034
1035TEST_F(Dex2oatClassLoaderContextTest, EmptyContext) {
1036 RunTest("PCL[]", kEmptyClassPathKey, /*expected_success*/ true);
1037}
1038
1039TEST_F(Dex2oatClassLoaderContextTest, SpecialContext) {
1040 RunTest(OatFile::kSpecialSharedLibrary,
1041 OatFile::kSpecialSharedLibrary,
1042 /*expected_success*/ true);
1043}
1044
1045TEST_F(Dex2oatClassLoaderContextTest, ContextWithTheSourceDexFiles) {
1046 std::string context = "PCL[" + GetUsedDexLocation() + "]";
1047 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1048}
1049
1050TEST_F(Dex2oatClassLoaderContextTest, ContextWithOtherDexFiles) {
1051 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Nested");
Calin Juravle1ce70852017-06-28 10:59:03 -07001052
1053 std::string context = "PCL[" + dex_files[0]->GetLocation() + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -07001054 std::string expected_classpath_key = "PCL[" +
1055 dex_files[0]->GetLocation() + "*" + std::to_string(dex_files[0]->GetLocationChecksum()) + "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001056 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1057}
1058
1059TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFiles) {
1060 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
1061 Copy(GetStrippedDexSrc1(), stripped_classpath);
1062
1063 std::string context = "PCL[" + stripped_classpath + "]";
1064 // Expect an empty context because stripped dex files cannot be open.
Calin Juravle7b0648a2017-07-07 18:40:50 -07001065 RunTest(context.c_str(), kEmptyClassPathKey , /*expected_success*/ true);
Calin Juravle1ce70852017-06-28 10:59:03 -07001066}
1067
1068TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFilesBackedByOdex) {
1069 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
1070 std::string odex_for_classpath = GetOdexDir() + "/stripped_classpath.odex";
1071
1072 Copy(GetDexSrc1(), stripped_classpath);
1073
1074 GenerateOdexForTest(stripped_classpath,
1075 odex_for_classpath,
1076 CompilerFilter::kQuicken,
1077 {},
1078 true);
1079
1080 // Strip the dex file
1081 Copy(GetStrippedDexSrc1(), stripped_classpath);
1082
1083 std::string context = "PCL[" + stripped_classpath + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -07001084 std::string expected_classpath_key;
Calin Juravle1ce70852017-06-28 10:59:03 -07001085 {
1086 // Open the oat file to get the expected classpath.
Nicolas Geoffray29742602017-12-14 10:09:03 +00001087 OatFileAssistant oat_file_assistant(stripped_classpath.c_str(), kRuntimeISA, false, false);
Calin Juravle1ce70852017-06-28 10:59:03 -07001088 std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile());
1089 std::vector<std::unique_ptr<const DexFile>> oat_dex_files =
1090 OatFileAssistant::LoadDexFiles(*oat_file, stripped_classpath.c_str());
Calin Juravle7b0648a2017-07-07 18:40:50 -07001091 expected_classpath_key = "PCL[";
1092 for (size_t i = 0; i < oat_dex_files.size(); i++) {
1093 if (i > 0) {
1094 expected_classpath_key + ":";
1095 }
1096 expected_classpath_key += oat_dex_files[i]->GetLocation() + "*" +
1097 std::to_string(oat_dex_files[i]->GetLocationChecksum());
1098 }
1099 expected_classpath_key += "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001100 }
1101
1102 RunTest(context.c_str(),
Calin Juravle7b0648a2017-07-07 18:40:50 -07001103 expected_classpath_key.c_str(),
Calin Juravle1ce70852017-06-28 10:59:03 -07001104 /*expected_success*/ true,
1105 /*use_second_source*/ true);
1106}
1107
1108TEST_F(Dex2oatClassLoaderContextTest, ContextWithNotExistentDexFiles) {
1109 std::string context = "PCL[does_not_exists.dex]";
1110 // Expect an empty context because stripped dex files cannot be open.
1111 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1112}
1113
Calin Juravlec79470d2017-07-12 17:37:42 -07001114TEST_F(Dex2oatClassLoaderContextTest, ChainContext) {
1115 std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1116 std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1117
1118 std::string context = "PCL[" + GetTestDexFileName("Nested") + "];" +
1119 "DLC[" + GetTestDexFileName("MultiDex") + "]";
1120 std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "];" +
1121 "DLC[" + CreateClassPathWithChecksums(dex_files2) + "]";
1122
1123 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1124}
1125
Mathieu Chartier9e050df2017-08-09 10:05:47 -07001126class Dex2oatDeterminism : public Dex2oatTest {};
1127
1128TEST_F(Dex2oatDeterminism, UnloadCompile) {
1129 if (!kUseReadBarrier &&
1130 gc::kCollectorTypeDefault != gc::kCollectorTypeCMS &&
1131 gc::kCollectorTypeDefault != gc::kCollectorTypeMS) {
1132 LOG(INFO) << "Test requires determinism support.";
1133 return;
1134 }
1135 Runtime* const runtime = Runtime::Current();
1136 std::string out_dir = GetScratchDir();
1137 const std::string base_oat_name = out_dir + "/base.oat";
1138 const std::string base_vdex_name = out_dir + "/base.vdex";
1139 const std::string unload_oat_name = out_dir + "/unload.oat";
1140 const std::string unload_vdex_name = out_dir + "/unload.vdex";
1141 const std::string no_unload_oat_name = out_dir + "/nounload.oat";
1142 const std::string no_unload_vdex_name = out_dir + "/nounload.vdex";
1143 const std::string app_image_name = out_dir + "/unload.art";
1144 std::string error_msg;
1145 const std::vector<gc::space::ImageSpace*>& spaces = runtime->GetHeap()->GetBootImageSpaces();
1146 ASSERT_GT(spaces.size(), 0u);
1147 const std::string image_location = spaces[0]->GetImageLocation();
1148 // Without passing in an app image, it will unload in between compilations.
1149 const int res = GenerateOdexForTestWithStatus(
1150 GetLibCoreDexFileNames(),
1151 base_oat_name,
1152 CompilerFilter::Filter::kQuicken,
1153 &error_msg,
1154 {"--force-determinism", "--avoid-storing-invocation"});
1155 EXPECT_EQ(res, 0);
1156 Copy(base_oat_name, unload_oat_name);
1157 Copy(base_vdex_name, unload_vdex_name);
1158 std::unique_ptr<File> unload_oat(OS::OpenFileForReading(unload_oat_name.c_str()));
1159 std::unique_ptr<File> unload_vdex(OS::OpenFileForReading(unload_vdex_name.c_str()));
1160 ASSERT_TRUE(unload_oat != nullptr);
1161 ASSERT_TRUE(unload_vdex != nullptr);
1162 EXPECT_GT(unload_oat->GetLength(), 0u);
1163 EXPECT_GT(unload_vdex->GetLength(), 0u);
1164 // Regenerate with an app image to disable the dex2oat unloading and verify that the output is
1165 // the same.
1166 const int res2 = GenerateOdexForTestWithStatus(
1167 GetLibCoreDexFileNames(),
1168 base_oat_name,
1169 CompilerFilter::Filter::kQuicken,
1170 &error_msg,
1171 {"--force-determinism", "--avoid-storing-invocation", "--app-image-file=" + app_image_name});
1172 EXPECT_EQ(res2, 0);
1173 Copy(base_oat_name, no_unload_oat_name);
1174 Copy(base_vdex_name, no_unload_vdex_name);
1175 std::unique_ptr<File> no_unload_oat(OS::OpenFileForReading(no_unload_oat_name.c_str()));
1176 std::unique_ptr<File> no_unload_vdex(OS::OpenFileForReading(no_unload_vdex_name.c_str()));
1177 ASSERT_TRUE(no_unload_oat != nullptr);
1178 ASSERT_TRUE(no_unload_vdex != nullptr);
1179 EXPECT_GT(no_unload_oat->GetLength(), 0u);
1180 EXPECT_GT(no_unload_vdex->GetLength(), 0u);
1181 // Verify that both of the files are the same (odex and vdex).
1182 EXPECT_EQ(unload_oat->GetLength(), no_unload_oat->GetLength());
1183 EXPECT_EQ(unload_vdex->GetLength(), no_unload_vdex->GetLength());
1184 EXPECT_EQ(unload_oat->Compare(no_unload_oat.get()), 0)
1185 << unload_oat_name << " " << no_unload_oat_name;
1186 EXPECT_EQ(unload_vdex->Compare(no_unload_vdex.get()), 0)
1187 << unload_vdex_name << " " << no_unload_vdex_name;
1188 // App image file.
1189 std::unique_ptr<File> app_image_file(OS::OpenFileForReading(app_image_name.c_str()));
1190 ASSERT_TRUE(app_image_file != nullptr);
1191 EXPECT_GT(app_image_file->GetLength(), 0u);
1192}
1193
Mathieu Chartier120aa282017-08-05 16:03:03 -07001194// Test that dexlayout section info is correctly written to the oat file for profile based
1195// compilation.
1196TEST_F(Dex2oatTest, LayoutSections) {
1197 using Hotness = ProfileCompilationInfo::MethodHotness;
1198 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1199 ScratchFile profile_file;
1200 // We can only layout method indices with code items, figure out which ones have this property
1201 // first.
1202 std::vector<uint16_t> methods;
1203 {
1204 const DexFile::TypeId* type_id = dex->FindTypeId("LManyMethods;");
1205 dex::TypeIndex type_idx = dex->GetIndexForTypeId(*type_id);
1206 const DexFile::ClassDef* class_def = dex->FindClassDef(type_idx);
1207 ClassDataItemIterator it(*dex, dex->GetClassData(*class_def));
1208 it.SkipAllFields();
1209 std::set<size_t> code_item_offsets;
Mathieu Chartierb7c273c2017-11-10 18:07:56 -08001210 for (; it.HasNextMethod(); it.Next()) {
Mathieu Chartier120aa282017-08-05 16:03:03 -07001211 const uint16_t method_idx = it.GetMemberIndex();
1212 const size_t code_item_offset = it.GetMethodCodeItemOffset();
1213 if (code_item_offsets.insert(code_item_offset).second) {
1214 // Unique code item, add the method index.
1215 methods.push_back(method_idx);
1216 }
1217 }
1218 DCHECK(!it.HasNext());
1219 }
1220 ASSERT_GE(methods.size(), 8u);
1221 std::vector<uint16_t> hot_methods = {methods[1], methods[3], methods[5]};
1222 std::vector<uint16_t> startup_methods = {methods[1], methods[2], methods[7]};
1223 std::vector<uint16_t> post_methods = {methods[0], methods[2], methods[6]};
1224 // Here, we build the profile from the method lists.
1225 ProfileCompilationInfo info;
1226 info.AddMethodsForDex(
1227 static_cast<Hotness::Flag>(Hotness::kFlagHot | Hotness::kFlagStartup),
1228 dex.get(),
1229 hot_methods.begin(),
1230 hot_methods.end());
1231 info.AddMethodsForDex(
1232 Hotness::kFlagStartup,
1233 dex.get(),
1234 startup_methods.begin(),
1235 startup_methods.end());
1236 info.AddMethodsForDex(
1237 Hotness::kFlagPostStartup,
1238 dex.get(),
1239 post_methods.begin(),
1240 post_methods.end());
1241 for (uint16_t id : hot_methods) {
1242 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsHot());
1243 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsStartup());
1244 }
1245 for (uint16_t id : startup_methods) {
1246 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsStartup());
1247 }
1248 for (uint16_t id : post_methods) {
1249 EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsPostStartup());
1250 }
1251 // Save the profile since we want to use it with dex2oat to produce an oat file.
1252 ASSERT_TRUE(info.Save(profile_file.GetFd()));
1253 // Generate a profile based odex.
1254 const std::string dir = GetScratchDir();
1255 const std::string oat_filename = dir + "/base.oat";
1256 const std::string vdex_filename = dir + "/base.vdex";
1257 std::string error_msg;
1258 const int res = GenerateOdexForTestWithStatus(
1259 {dex->GetLocation()},
1260 oat_filename,
1261 CompilerFilter::Filter::kQuicken,
1262 &error_msg,
1263 {"--profile-file=" + profile_file.GetFilename()});
1264 EXPECT_EQ(res, 0);
1265
1266 // Open our generated oat file.
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +01001267 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1268 oat_filename.c_str(),
Mathieu Chartier120aa282017-08-05 16:03:03 -07001269 oat_filename.c_str(),
1270 nullptr,
1271 nullptr,
1272 false,
1273 /*low_4gb*/false,
1274 dex->GetLocation().c_str(),
1275 &error_msg));
1276 ASSERT_TRUE(odex_file != nullptr);
1277 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1278 ASSERT_EQ(oat_dex_files.size(), 1u);
1279 // Check that the code sections match what we expect.
1280 for (const OatDexFile* oat_dex : oat_dex_files) {
1281 const DexLayoutSections* const sections = oat_dex->GetDexLayoutSections();
1282 // Testing of logging the sections.
1283 ASSERT_TRUE(sections != nullptr);
1284 LOG(INFO) << *sections;
1285
1286 // Load the sections into temporary variables for convenience.
1287 const DexLayoutSection& code_section =
1288 sections->sections_[static_cast<size_t>(DexLayoutSections::SectionType::kSectionTypeCode)];
1289 const DexLayoutSection::Subsection& section_hot_code =
1290 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeHot)];
1291 const DexLayoutSection::Subsection& section_sometimes_used =
1292 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeSometimesUsed)];
1293 const DexLayoutSection::Subsection& section_startup_only =
1294 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeStartupOnly)];
1295 const DexLayoutSection::Subsection& section_unused =
1296 code_section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeUnused)];
1297
1298 // All the sections should be non-empty.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001299 EXPECT_GT(section_hot_code.Size(), 0u);
1300 EXPECT_GT(section_sometimes_used.Size(), 0u);
1301 EXPECT_GT(section_startup_only.Size(), 0u);
1302 EXPECT_GT(section_unused.Size(), 0u);
Mathieu Chartier120aa282017-08-05 16:03:03 -07001303
1304 // Open the dex file since we need to peek at the code items to verify the layout matches what
1305 // we expect.
1306 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1307 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1308 const DexFile::TypeId* type_id = dex_file->FindTypeId("LManyMethods;");
1309 ASSERT_TRUE(type_id != nullptr);
1310 dex::TypeIndex type_idx = dex_file->GetIndexForTypeId(*type_id);
1311 const DexFile::ClassDef* class_def = dex_file->FindClassDef(type_idx);
1312 ASSERT_TRUE(class_def != nullptr);
1313
1314 // Count how many code items are for each category, there should be at least one per category.
1315 size_t hot_count = 0;
1316 size_t post_startup_count = 0;
1317 size_t startup_count = 0;
1318 size_t unused_count = 0;
1319 // Visit all of the methdos of the main class and cross reference the method indices to their
1320 // corresponding code item offsets to verify the layout.
1321 ClassDataItemIterator it(*dex_file, dex_file->GetClassData(*class_def));
1322 it.SkipAllFields();
Mathieu Chartierb7c273c2017-11-10 18:07:56 -08001323 for (; it.HasNextMethod(); it.Next()) {
Mathieu Chartier120aa282017-08-05 16:03:03 -07001324 const size_t method_idx = it.GetMemberIndex();
1325 const size_t code_item_offset = it.GetMethodCodeItemOffset();
1326 const bool is_hot = ContainsElement(hot_methods, method_idx);
1327 const bool is_startup = ContainsElement(startup_methods, method_idx);
1328 const bool is_post_startup = ContainsElement(post_methods, method_idx);
1329 if (is_hot) {
1330 // Hot is highest precedence, check that the hot methods are in the hot section.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001331 EXPECT_TRUE(section_hot_code.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001332 ++hot_count;
1333 } else if (is_post_startup) {
1334 // Post startup is sometimes used section.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001335 EXPECT_TRUE(section_sometimes_used.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001336 ++post_startup_count;
1337 } else if (is_startup) {
1338 // Startup at this point means not hot or post startup, these must be startup only then.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001339 EXPECT_TRUE(section_startup_only.Contains(code_item_offset));
Mathieu Chartier120aa282017-08-05 16:03:03 -07001340 ++startup_count;
1341 } else {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -08001342 if (section_unused.Contains(code_item_offset)) {
Alan Leung9595fd32017-10-17 17:08:19 -07001343 // If no flags are set, the method should be unused ...
1344 ++unused_count;
1345 } else {
1346 // or this method is part of the last code item and the end is 4 byte aligned.
1347 ClassDataItemIterator it2(*dex_file, dex_file->GetClassData(*class_def));
1348 it2.SkipAllFields();
Mathieu Chartierb7c273c2017-11-10 18:07:56 -08001349 for (; it2.HasNextMethod(); it2.Next()) {
Alan Leung9595fd32017-10-17 17:08:19 -07001350 EXPECT_LE(it2.GetMethodCodeItemOffset(), code_item_offset);
1351 }
1352 uint32_t code_item_size = dex_file->FindCodeItemOffset(*class_def, method_idx);
1353 EXPECT_EQ((code_item_offset + code_item_size) % 4, 0u);
1354 }
Mathieu Chartier120aa282017-08-05 16:03:03 -07001355 }
1356 }
1357 DCHECK(!it.HasNext());
1358 EXPECT_GT(hot_count, 0u);
1359 EXPECT_GT(post_startup_count, 0u);
1360 EXPECT_GT(startup_count, 0u);
1361 EXPECT_GT(unused_count, 0u);
1362 }
1363}
1364
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001365// Test that generating compact dex works.
1366TEST_F(Dex2oatTest, GenerateCompactDex) {
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001367 // Generate a compact dex based odex.
1368 const std::string dir = GetScratchDir();
1369 const std::string oat_filename = dir + "/base.oat";
1370 const std::string vdex_filename = dir + "/base.vdex";
Mathieu Chartier6f716502018-03-14 14:00:04 -07001371 const std::string dex_location = GetTestDexFileName("MultiDex");
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001372 std::string error_msg;
1373 const int res = GenerateOdexForTestWithStatus(
Mathieu Chartier6f716502018-03-14 14:00:04 -07001374 { dex_location },
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001375 oat_filename,
1376 CompilerFilter::Filter::kQuicken,
1377 &error_msg,
1378 {"--compact-dex-level=fast"});
1379 EXPECT_EQ(res, 0);
1380 // Open our generated oat file.
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +01001381 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1382 oat_filename.c_str(),
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001383 oat_filename.c_str(),
1384 nullptr,
1385 nullptr,
1386 false,
1387 /*low_4gb*/false,
Mathieu Chartier6f716502018-03-14 14:00:04 -07001388 dex_location.c_str(),
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001389 &error_msg));
1390 ASSERT_TRUE(odex_file != nullptr);
1391 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
Mathieu Chartier6f716502018-03-14 14:00:04 -07001392 ASSERT_GT(oat_dex_files.size(), 1u);
1393 // Check that each dex is a compact dex file.
1394 std::vector<std::unique_ptr<const CompactDexFile>> compact_dex_files;
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001395 for (const OatDexFile* oat_dex : oat_dex_files) {
1396 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1397 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1398 ASSERT_TRUE(dex_file->IsCompactDexFile());
Mathieu Chartier6f716502018-03-14 14:00:04 -07001399 compact_dex_files.push_back(
1400 std::unique_ptr<const CompactDexFile>(dex_file.release()->AsCompactDexFile()));
1401 }
1402 for (const std::unique_ptr<const CompactDexFile>& dex_file : compact_dex_files) {
1403 // Test that every code item is in the owned section.
1404 const CompactDexFile::Header& header = dex_file->GetHeader();
1405 EXPECT_LE(header.OwnedDataBegin(), header.OwnedDataEnd());
1406 EXPECT_LE(header.OwnedDataBegin(), header.data_size_);
1407 EXPECT_LE(header.OwnedDataEnd(), header.data_size_);
1408 for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
1409 const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
1410 class_def.VisitMethods(dex_file.get(), [&](const ClassDataItemIterator& it) {
1411 if (it.GetMethodCodeItemOffset() != 0u) {
1412 ASSERT_GE(it.GetMethodCodeItemOffset(), header.OwnedDataBegin());
1413 ASSERT_LT(it.GetMethodCodeItemOffset(), header.OwnedDataEnd());
1414 }
1415 });
1416 }
1417 // Test that the owned sections don't overlap.
1418 for (const std::unique_ptr<const CompactDexFile>& other_dex : compact_dex_files) {
1419 if (dex_file != other_dex) {
1420 ASSERT_TRUE(
1421 (dex_file->GetHeader().OwnedDataBegin() >= other_dex->GetHeader().OwnedDataEnd()) ||
1422 (dex_file->GetHeader().OwnedDataEnd() <= other_dex->GetHeader().OwnedDataBegin()));
1423 }
1424 }
Mathieu Chartier603ccab2017-10-20 14:34:28 -07001425 }
1426}
1427
Andreas Gampef39208f2017-10-19 15:06:59 -07001428class Dex2oatVerifierAbort : public Dex2oatTest {};
1429
1430TEST_F(Dex2oatVerifierAbort, HardFail) {
1431 // Use VerifierDeps as it has hard-failing classes.
1432 std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDeps"));
1433 std::string out_dir = GetScratchDir();
1434 const std::string base_oat_name = out_dir + "/base.oat";
1435 std::string error_msg;
1436 const int res_fail = GenerateOdexForTestWithStatus(
1437 {dex->GetLocation()},
1438 base_oat_name,
1439 CompilerFilter::Filter::kQuicken,
1440 &error_msg,
1441 {"--abort-on-hard-verifier-error"});
1442 EXPECT_NE(0, res_fail);
1443
1444 const int res_no_fail = GenerateOdexForTestWithStatus(
1445 {dex->GetLocation()},
1446 base_oat_name,
1447 CompilerFilter::Filter::kQuicken,
1448 &error_msg,
1449 {"--no-abort-on-hard-verifier-error"});
1450 EXPECT_EQ(0, res_no_fail);
1451}
1452
1453TEST_F(Dex2oatVerifierAbort, SoftFail) {
1454 // Use VerifierDepsMulti as it has hard-failing classes.
1455 std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDepsMulti"));
1456 std::string out_dir = GetScratchDir();
1457 const std::string base_oat_name = out_dir + "/base.oat";
1458 std::string error_msg;
1459 const int res_fail = GenerateOdexForTestWithStatus(
1460 {dex->GetLocation()},
1461 base_oat_name,
1462 CompilerFilter::Filter::kQuicken,
1463 &error_msg,
1464 {"--abort-on-soft-verifier-error"});
1465 EXPECT_NE(0, res_fail);
1466
1467 const int res_no_fail = GenerateOdexForTestWithStatus(
1468 {dex->GetLocation()},
1469 base_oat_name,
1470 CompilerFilter::Filter::kQuicken,
1471 &error_msg,
1472 {"--no-abort-on-soft-verifier-error"});
1473 EXPECT_EQ(0, res_no_fail);
1474}
1475
Andreas Gampecac31ad2017-11-06 20:01:17 -08001476class Dex2oatDedupeCode : public Dex2oatTest {};
1477
1478TEST_F(Dex2oatDedupeCode, DedupeTest) {
1479 // Use MyClassNatives. It has lots of native methods that will produce deduplicate-able code.
1480 std::unique_ptr<const DexFile> dex(OpenTestDexFile("MyClassNatives"));
1481 std::string out_dir = GetScratchDir();
1482 const std::string base_oat_name = out_dir + "/base.oat";
1483 size_t no_dedupe_size = 0;
1484 GenerateOdexForTest(dex->GetLocation(),
1485 base_oat_name,
1486 CompilerFilter::Filter::kSpeed,
1487 { "--deduplicate-code=false" },
1488 true, // expect_success
1489 false, // use_fd
1490 [&no_dedupe_size](const OatFile& o) {
1491 no_dedupe_size = o.Size();
1492 });
1493
1494 size_t dedupe_size = 0;
1495 GenerateOdexForTest(dex->GetLocation(),
1496 base_oat_name,
1497 CompilerFilter::Filter::kSpeed,
1498 { "--deduplicate-code=true" },
1499 true, // expect_success
1500 false, // use_fd
1501 [&dedupe_size](const OatFile& o) {
1502 dedupe_size = o.Size();
1503 });
1504
1505 EXPECT_LT(dedupe_size, no_dedupe_size);
1506}
1507
Nicolas Geoffrayf3075272018-01-08 12:41:19 +00001508TEST_F(Dex2oatTest, UncompressedTest) {
1509 std::unique_ptr<const DexFile> dex(OpenTestDexFile("MainUncompressed"));
1510 std::string out_dir = GetScratchDir();
1511 const std::string base_oat_name = out_dir + "/base.oat";
1512 GenerateOdexForTest(dex->GetLocation(),
1513 base_oat_name,
1514 CompilerFilter::Filter::kQuicken,
1515 { },
1516 true, // expect_success
1517 false, // use_fd
1518 [](const OatFile& o) {
1519 CHECK(!o.ContainsDexCode());
1520 });
1521}
1522
Mathieu Chartier700a9852018-02-06 18:27:38 -08001523TEST_F(Dex2oatTest, EmptyUncompressedDexTest) {
1524 std::string out_dir = GetScratchDir();
1525 const std::string base_oat_name = out_dir + "/base.oat";
1526 std::string error_msg;
1527 int status = GenerateOdexForTestWithStatus(
1528 { GetTestDexFileName("MainEmptyUncompressed") },
1529 base_oat_name,
1530 CompilerFilter::Filter::kQuicken,
1531 &error_msg,
1532 { },
1533 /*use_fd*/ false);
1534 // Expect to fail with code 1 and not SIGSEGV or SIGABRT.
1535 ASSERT_TRUE(WIFEXITED(status));
1536 ASSERT_EQ(WEXITSTATUS(status), 1) << error_msg;
1537}
1538
Mathieu Chartier05f90d12018-02-07 13:47:17 -08001539// Dex file that has duplicate methods have different code items and debug info.
1540static const char kDuplicateMethodInputDex[] =
1541 "ZGV4CjAzOQDEy8VPdj4qHpgPYFWtLCtOykfFP4kB8tGYDAAAcAAAAHhWNBIAAAAAAAAAANALAABI"
1542 "AAAAcAAAAA4AAACQAQAABQAAAMgBAAANAAAABAIAABkAAABsAgAABAAAADQDAADgCAAAuAMAADgI"
1543 "AABCCAAASggAAE8IAABcCAAAaggAAHkIAACICAAAlggAAKQIAACyCAAAwAgAAM4IAADcCAAA6ggA"
1544 "APgIAAD7CAAA/wgAABcJAAAuCQAARQkAAFQJAAB4CQAAmAkAALsJAADSCQAA5gkAAPoJAAAVCgAA"
1545 "KQoAADsKAABCCgAASgoAAFIKAABbCgAAZAoAAGwKAAB0CgAAfAoAAIQKAACMCgAAlAoAAJwKAACk"
1546 "CgAArQoAALcKAADACgAAwwoAAMcKAADcCgAA6QoAAPEKAAD3CgAA/QoAAAMLAAAJCwAAEAsAABcL"
1547 "AAAdCwAAIwsAACkLAAAvCwAANQsAADsLAABBCwAARwsAAE0LAABSCwAAWwsAAF4LAABoCwAAbwsA"
1548 "ABEAAAASAAAAEwAAABQAAAAVAAAAFgAAABcAAAAYAAAAGQAAABoAAAAbAAAAHAAAAC4AAAAwAAAA"
1549 "DwAAAAkAAAAAAAAAEAAAAAoAAACoBwAALgAAAAwAAAAAAAAALwAAAAwAAACoBwAALwAAAAwAAACw"
1550 "BwAAAgAJADUAAAACAAkANgAAAAIACQA3AAAAAgAJADgAAAACAAkAOQAAAAIACQA6AAAAAgAJADsA"
1551 "AAACAAkAPAAAAAIACQA9AAAAAgAJAD4AAAACAAkAPwAAAAIACQBAAAAACwAHAEIAAAAAAAIAAQAA"
1552 "AAAAAwAeAAAAAQACAAEAAAABAAMAHgAAAAIAAgAAAAAAAgACAAEAAAADAAIAAQAAAAMAAgAfAAAA"
1553 "AwACACAAAAADAAIAIQAAAAMAAgAiAAAAAwACACMAAAADAAIAJAAAAAMAAgAlAAAAAwACACYAAAAD"
1554 "AAIAJwAAAAMAAgAoAAAAAwACACkAAAADAAIAKgAAAAMABAA0AAAABwADAEMAAAAIAAIAAQAAAAoA"
1555 "AgABAAAACgABADIAAAAKAAAARQAAAAAAAAAAAAAACAAAAAAAAAAdAAAAaAcAALYHAAAAAAAAAQAA"
1556 "AAAAAAAIAAAAAAAAAB0AAAB4BwAAxAcAAAAAAAACAAAAAAAAAAgAAAAAAAAAHQAAAIgHAADSBwAA"
1557 "AAAAAAMAAAAAAAAACAAAAAAAAAAdAAAAmAcAAPoHAAAAAAAAAAAAAAEAAAAAAAAArAYAADEAAAAa"
1558 "AAMAaQAAABoABABpAAEAGgAHAGkABAAaAAgAaQAFABoACQBpAAYAGgAKAGkABwAaAAsAaQAIABoA"
1559 "DABpAAkAGgANAGkACgAaAA4AaQALABoABQBpAAIAGgAGAGkAAwAOAAAAAQABAAEAAACSBgAABAAA"
1560 "AHAQFQAAAA4ABAABAAIAAACWBgAAFwAAAGIADAAiAQoAcBAWAAEAGgICAG4gFwAhAG4gFwAxAG4Q"
1561 "GAABAAwBbiAUABAADgAAAAEAAQABAAAAngYAAAQAAABwEBUAAAAOAAIAAQACAAAAogYAAAYAAABi"
1562 "AAwAbiAUABAADgABAAEAAQAAAKgGAAAEAAAAcBAVAAAADgABAAEAAQAAALsGAAAEAAAAcBAVAAAA"
1563 "DgABAAAAAQAAAL8GAAAGAAAAYgAAAHEQAwAAAA4AAQAAAAEAAADEBgAABgAAAGIAAQBxEAMAAAAO"
1564 "AAEAAAABAAAA8QYAAAYAAABiAAIAcRABAAAADgABAAAAAQAAAPYGAAAGAAAAYgADAHEQAwAAAA4A"
1565 "AQAAAAEAAADJBgAABgAAAGIABABxEAMAAAAOAAEAAAABAAAAzgYAAAYAAABiAAEAcRADAAAADgAB"
1566 "AAAAAQAAANMGAAAGAAAAYgAGAHEQAwAAAA4AAQAAAAEAAADYBgAABgAAAGIABwBxEAMAAAAOAAEA"
1567 "AAABAAAA3QYAAAYAAABiAAgAcRABAAAADgABAAAAAQAAAOIGAAAGAAAAYgAJAHEQAwAAAA4AAQAA"
1568 "AAEAAADnBgAABgAAAGIACgBxEAMAAAAOAAEAAAABAAAA7AYAAAYAAABiAAsAcRABAAAADgABAAEA"
1569 "AAAAAPsGAAAlAAAAcQAHAAAAcQAIAAAAcQALAAAAcQAMAAAAcQANAAAAcQAOAAAAcQAPAAAAcQAQ"
1570 "AAAAcQARAAAAcQASAAAAcQAJAAAAcQAKAAAADgAnAA4AKQFFDgEWDwAhAA4AIwFFDloAEgAOABMA"
1571 "DktLS0tLS0tLS0tLABEADgAuAA5aADIADloANgAOWgA6AA5aAD4ADloAQgAOWgBGAA5aAEoADloA"
1572 "TgAOWgBSAA5aAFYADloAWgAOWgBeATQOPDw8PDw8PDw8PDw8AAIEAUYYAwIFAjEECEEXLAIFAjEE"
1573 "CEEXKwIFAjEECEEXLQIGAUYcAxgAGAEYAgAAAAIAAAAMBwAAEgcAAAIAAAAMBwAAGwcAAAIAAAAM"
1574 "BwAAJAcAAAEAAAAtBwAAPAcAAAAAAAAAAAAAAAAAAEgHAAAAAAAAAAAAAAAAAABUBwAAAAAAAAAA"
1575 "AAAAAAAAYAcAAAAAAAAAAAAAAAAAAAEAAAAJAAAAAQAAAA0AAAACAACAgASsCAEIxAgAAAIAAoCA"
1576 "BIQJAQicCQwAAgAACQEJAQkBCQEJAQkBCQEJAQkBCQEJAQkEiIAEuAcBgIAEuAkAAA4ABoCABNAJ"
1577 "AQnoCQAJhAoACaAKAAm8CgAJ2AoACfQKAAmQCwAJrAsACcgLAAnkCwAJgAwACZwMAAm4DAg8Y2xp"
1578 "bml0PgAGPGluaXQ+AANBQUEAC0hlbGxvIFdvcmxkAAxIZWxsbyBXb3JsZDEADUhlbGxvIFdvcmxk"
1579 "MTAADUhlbGxvIFdvcmxkMTEADEhlbGxvIFdvcmxkMgAMSGVsbG8gV29ybGQzAAxIZWxsbyBXb3Js"
1580 "ZDQADEhlbGxvIFdvcmxkNQAMSGVsbG8gV29ybGQ2AAxIZWxsbyBXb3JsZDcADEhlbGxvIFdvcmxk"
1581 "OAAMSGVsbG8gV29ybGQ5AAFMAAJMTAAWTE1hbnlNZXRob2RzJFByaW50ZXIyOwAVTE1hbnlNZXRo"
1582 "b2RzJFByaW50ZXI7ABVMTWFueU1ldGhvZHMkU3RyaW5nczsADUxNYW55TWV0aG9kczsAIkxkYWx2"
1583 "aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNs"
1584 "YXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNzZXM7ABVMamF2YS9pby9QcmludFN0"
1585 "cmVhbTsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABlMamF2YS9sYW5n"
1586 "L1N0cmluZ0J1aWxkZXI7ABJMamF2YS9sYW5nL1N5c3RlbTsAEE1hbnlNZXRob2RzLmphdmEABVBy"
1587 "aW50AAZQcmludDAABlByaW50MQAHUHJpbnQxMAAHUHJpbnQxMQAGUHJpbnQyAAZQcmludDMABlBy"
1588 "aW50NAAGUHJpbnQ1AAZQcmludDYABlByaW50NwAGUHJpbnQ4AAZQcmludDkAB1ByaW50ZXIACFBy"
1589 "aW50ZXIyAAdTdHJpbmdzAAFWAAJWTAATW0xqYXZhL2xhbmcvU3RyaW5nOwALYWNjZXNzRmxhZ3MA"
1590 "BmFwcGVuZAAEYXJncwAEbWFpbgAEbXNnMAAEbXNnMQAFbXNnMTAABW1zZzExAARtc2cyAARtc2cz"
1591 "AARtc2c0AARtc2c1AARtc2c2AARtc2c3AARtc2c4AARtc2c5AARuYW1lAANvdXQAB3ByaW50bG4A"
1592 "AXMACHRvU3RyaW5nAAV2YWx1ZQBffn5EOHsibWluLWFwaSI6MTAwMDAsInNoYS0xIjoiZmViODZj"
1593 "MDA2ZWZhY2YxZDc5ODRiODVlMTc5MGZlZjdhNzY3YWViYyIsInZlcnNpb24iOiJ2MS4xLjUtZGV2"
1594 "In0AEAAAAAAAAAABAAAAAAAAAAEAAABIAAAAcAAAAAIAAAAOAAAAkAEAAAMAAAAFAAAAyAEAAAQA"
1595 "AAANAAAABAIAAAUAAAAZAAAAbAIAAAYAAAAEAAAANAMAAAEgAAAUAAAAuAMAAAMgAAAUAAAAkgYA"
1596 "AAQgAAAFAAAADAcAAAMQAAAEAAAAOQcAAAYgAAAEAAAAaAcAAAEQAAACAAAAqAcAAAAgAAAEAAAA"
1597 "tgcAAAIgAABIAAAAOAgAAAAQAAABAAAA0AsAAAAAAAA=";
1598
1599static void WriteBase64ToFile(const char* base64, File* file) {
1600 // Decode base64.
1601 CHECK(base64 != nullptr);
1602 size_t length;
1603 std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
1604 CHECK(bytes != nullptr);
1605 if (!file->WriteFully(bytes.get(), length)) {
1606 PLOG(FATAL) << "Failed to write base64 as file";
1607 }
1608}
1609
1610TEST_F(Dex2oatTest, CompactDexGenerationFailure) {
1611 ScratchFile temp_dex;
1612 WriteBase64ToFile(kDuplicateMethodInputDex, temp_dex.GetFile());
1613 std::string out_dir = GetScratchDir();
1614 const std::string oat_filename = out_dir + "/base.oat";
1615 // The dex won't pass the method verifier, only use the verify filter.
1616 GenerateOdexForTest(temp_dex.GetFilename(),
1617 oat_filename,
1618 CompilerFilter::Filter::kVerify,
1619 { },
1620 true, // expect_success
1621 false, // use_fd
1622 [](const OatFile& o) {
1623 CHECK(o.ContainsDexCode());
1624 });
1625 // Open our generated oat file.
1626 std::string error_msg;
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +01001627 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1628 oat_filename.c_str(),
Mathieu Chartier05f90d12018-02-07 13:47:17 -08001629 oat_filename.c_str(),
1630 nullptr,
1631 nullptr,
1632 false,
1633 /*low_4gb*/false,
1634 temp_dex.GetFilename().c_str(),
1635 &error_msg));
1636 ASSERT_TRUE(odex_file != nullptr);
1637 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1638 ASSERT_EQ(oat_dex_files.size(), 1u);
1639 // The dexes should have failed to convert to compact dex.
1640 for (const OatDexFile* oat_dex : oat_dex_files) {
1641 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1642 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1643 ASSERT_TRUE(!dex_file->IsCompactDexFile());
1644 }
1645}
1646
Mathieu Chartiercda83be2018-03-01 23:55:55 -08001647TEST_F(Dex2oatTest, CompactDexGenerationFailureMultiDex) {
1648 // Create a multidex file with only one dex that gets rejected for cdex conversion.
1649 ScratchFile apk_file;
1650 {
1651 FILE* file = fdopen(apk_file.GetFd(), "w+b");
1652 ZipWriter writer(file);
1653 // Add vdex to zip.
1654 writer.StartEntry("classes.dex", ZipWriter::kCompress);
1655 size_t length = 0u;
1656 std::unique_ptr<uint8_t[]> bytes(DecodeBase64(kDuplicateMethodInputDex, &length));
1657 ASSERT_GE(writer.WriteBytes(&bytes[0], length), 0);
1658 writer.FinishEntry();
1659 writer.StartEntry("classes2.dex", ZipWriter::kCompress);
1660 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1661 ASSERT_GE(writer.WriteBytes(dex->Begin(), dex->Size()), 0);
1662 writer.FinishEntry();
1663 writer.Finish();
1664 ASSERT_EQ(apk_file.GetFile()->Flush(), 0);
1665 }
1666 const std::string dex_location = apk_file.GetFilename();
1667 const std::string odex_location = GetOdexDir() + "/output.odex";
1668 GenerateOdexForTest(dex_location,
1669 odex_location,
1670 CompilerFilter::kQuicken,
1671 { "--compact-dex-level=fast" },
1672 true);
1673}
1674
Andreas Gampe25419b52018-02-08 21:30:26 -08001675TEST_F(Dex2oatTest, StderrLoggerOutput) {
1676 std::string dex_location = GetScratchDir() + "/Dex2OatStderrLoggerTest.jar";
1677 std::string odex_location = GetOdexDir() + "/Dex2OatStderrLoggerTest.odex";
1678
1679 // Test file doesn't matter.
1680 Copy(GetDexSrc1(), dex_location);
1681
1682 GenerateOdexForTest(dex_location,
1683 odex_location,
1684 CompilerFilter::kQuicken,
1685 { "--runtime-arg", "-Xuse-stderr-logger" },
1686 true);
1687 // Look for some random part of dex2oat logging. With the stderr logger this should be captured,
1688 // even on device.
1689 EXPECT_NE(std::string::npos, output_.find("dex2oat took"));
1690}
1691
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001692TEST_F(Dex2oatTest, VerifyCompilationReason) {
1693 std::string dex_location = GetScratchDir() + "/Dex2OatCompilationReason.jar";
1694 std::string odex_location = GetOdexDir() + "/Dex2OatCompilationReason.odex";
1695
1696 // Test file doesn't matter.
1697 Copy(GetDexSrc1(), dex_location);
1698
1699 GenerateOdexForTest(dex_location,
1700 odex_location,
1701 CompilerFilter::kVerify,
1702 { "--compilation-reason=install" },
1703 true);
1704 std::string error_msg;
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +01001705 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1706 odex_location.c_str(),
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001707 odex_location.c_str(),
1708 nullptr,
1709 nullptr,
1710 false,
1711 /*low_4gb*/false,
1712 dex_location.c_str(),
1713 &error_msg));
1714 ASSERT_TRUE(odex_file != nullptr);
1715 ASSERT_STREQ("install", odex_file->GetCompilationReason());
1716}
1717
1718TEST_F(Dex2oatTest, VerifyNoCompilationReason) {
1719 std::string dex_location = GetScratchDir() + "/Dex2OatNoCompilationReason.jar";
1720 std::string odex_location = GetOdexDir() + "/Dex2OatNoCompilationReason.odex";
1721
1722 // Test file doesn't matter.
1723 Copy(GetDexSrc1(), dex_location);
1724
1725 GenerateOdexForTest(dex_location,
1726 odex_location,
1727 CompilerFilter::kVerify,
1728 {},
1729 true);
1730 std::string error_msg;
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +01001731 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1732 odex_location.c_str(),
Calin Juravle0e09dfc2018-02-12 19:01:09 -08001733 odex_location.c_str(),
1734 nullptr,
1735 nullptr,
1736 false,
1737 /*low_4gb*/false,
1738 dex_location.c_str(),
1739 &error_msg));
1740 ASSERT_TRUE(odex_file != nullptr);
1741 ASSERT_EQ(nullptr, odex_file->GetCompilationReason());
1742}
1743
Mathieu Chartier792111c2018-02-15 13:02:15 -08001744TEST_F(Dex2oatTest, DontExtract) {
1745 std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1746 std::string error_msg;
1747 const std::string out_dir = GetScratchDir();
1748 const std::string dex_location = dex->GetLocation();
1749 const std::string odex_location = out_dir + "/base.oat";
1750 const std::string vdex_location = out_dir + "/base.vdex";
1751 GenerateOdexForTest(dex_location,
1752 odex_location,
1753 CompilerFilter::Filter::kVerify,
1754 { "--copy-dex-files=false" },
1755 true, // expect_success
1756 false, // use_fd
1757 [](const OatFile&) {
1758 });
1759 {
1760 // Check the vdex doesn't have dex.
1761 std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location.c_str(),
1762 /*writable*/ false,
1763 /*low_4gb*/ false,
1764 /*unquicken*/ false,
1765 &error_msg));
1766 ASSERT_TRUE(vdex != nullptr);
Nicolas Geoffrayc334f832018-03-02 10:52:16 +00001767 EXPECT_FALSE(vdex->HasDexSection()) << output_;
Mathieu Chartier792111c2018-02-15 13:02:15 -08001768 }
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +01001769 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
1770 odex_location.c_str(),
Mathieu Chartier792111c2018-02-15 13:02:15 -08001771 odex_location.c_str(),
1772 nullptr,
1773 nullptr,
1774 false,
1775 /*low_4gb*/ false,
1776 dex_location.c_str(),
1777 &error_msg));
1778 ASSERT_TRUE(odex_file != nullptr) << dex_location;
1779 std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1780 ASSERT_EQ(oat_dex_files.size(), 1u);
1781 // Verify that the oat file can still open the dex files.
1782 for (const OatDexFile* oat_dex : oat_dex_files) {
1783 std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1784 ASSERT_TRUE(dex_file != nullptr) << error_msg;
1785 }
1786 // Create a dm file and use it to verify.
1787 // Add produced artifacts to a zip file that doesn't contain the classes.dex.
1788 ScratchFile dm_file;
1789 {
1790 std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_location.c_str()));
1791 ASSERT_TRUE(vdex_file != nullptr);
1792 ASSERT_GT(vdex_file->GetLength(), 0u);
1793 FILE* file = fdopen(dm_file.GetFd(), "w+b");
1794 ZipWriter writer(file);
1795 auto write_all_bytes = [&](File* file) {
1796 std::unique_ptr<uint8_t[]> bytes(new uint8_t[file->GetLength()]);
1797 ASSERT_TRUE(file->ReadFully(&bytes[0], file->GetLength()));
1798 ASSERT_GE(writer.WriteBytes(&bytes[0], file->GetLength()), 0);
1799 };
1800 // Add vdex to zip.
1801 writer.StartEntry(VdexFile::kVdexNameInDmFile, ZipWriter::kCompress);
1802 write_all_bytes(vdex_file.get());
1803 writer.FinishEntry();
1804 writer.Finish();
1805 ASSERT_EQ(dm_file.GetFile()->Flush(), 0);
1806 }
1807
1808 // Generate a quickened dex by using the input dm file to verify.
1809 GenerateOdexForTest(dex_location,
1810 odex_location,
1811 CompilerFilter::Filter::kQuicken,
Mathieu Chartier026dc0b2018-02-20 10:07:51 -08001812 { "--dump-timings",
1813 "--dm-file=" + dm_file.GetFilename(),
1814 // Pass -Xuse-stderr-logger have dex2oat output in output_ on target.
1815 "--runtime-arg",
1816 "-Xuse-stderr-logger" },
Mathieu Chartier792111c2018-02-15 13:02:15 -08001817 true, // expect_success
1818 false, // use_fd
1819 [](const OatFile& o) {
1820 CHECK(o.ContainsDexCode());
1821 });
Mathieu Chartier026dc0b2018-02-20 10:07:51 -08001822 // Check the output for "Fast verify", this is printed from --dump-timings.
1823 std::istringstream iss(output_);
1824 std::string line;
1825 bool found_fast_verify = false;
1826 const std::string kFastVerifyString = "Fast Verify";
1827 while (std::getline(iss, line) && !found_fast_verify) {
1828 found_fast_verify = found_fast_verify || line.find(kFastVerifyString) != std::string::npos;
Mathieu Chartier792111c2018-02-15 13:02:15 -08001829 }
Mathieu Chartier026dc0b2018-02-20 10:07:51 -08001830 EXPECT_TRUE(found_fast_verify) << "Expected to find " << kFastVerifyString << "\n" << output_;
Mathieu Chartier792111c2018-02-15 13:02:15 -08001831}
1832
Mathieu Chartier2daa1342018-02-20 16:19:28 -08001833// Test that dex files with quickened opcodes aren't dequickened.
1834TEST_F(Dex2oatTest, QuickenedInput) {
1835 std::string error_msg;
1836 ScratchFile temp_dex;
1837 MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [] (DexFile* dex) {
1838 bool mutated_successfully = false;
1839 // Change the dex instructions to make an opcode that spans past the end of the code item.
1840 for (size_t i = 0; i < dex->NumClassDefs(); ++i) {
1841 const DexFile::ClassDef& def = dex->GetClassDef(i);
1842 const uint8_t* data = dex->GetClassData(def);
1843 if (data == nullptr) {
1844 continue;
1845 }
1846 ClassDataItemIterator it(*dex, data);
1847 it.SkipAllFields();
1848 while (it.HasNextMethod()) {
1849 DexFile::CodeItem* item = const_cast<DexFile::CodeItem*>(it.GetMethodCodeItem());
1850 if (item != nullptr) {
1851 CodeItemInstructionAccessor instructions(*dex, item);
1852 // Make a quickened instruction that doesn't run past the end of the code item.
1853 if (instructions.InsnsSizeInCodeUnits() > 2) {
1854 const_cast<Instruction&>(instructions.InstructionAt(0)).SetOpcode(
1855 Instruction::IGET_BYTE_QUICK);
1856 mutated_successfully = true;
1857 }
1858 }
1859 it.Next();
1860 }
1861 }
1862 CHECK(mutated_successfully)
1863 << "Failed to find candidate code item with only one code unit in last instruction.";
1864 });
1865
1866 std::string dex_location = temp_dex.GetFilename();
1867 std::string odex_location = GetOdexDir() + "/quickened.odex";
1868 std::string vdex_location = GetOdexDir() + "/quickened.vdex";
1869 std::unique_ptr<File> vdex_output(OS::CreateEmptyFile(vdex_location.c_str()));
1870 // Quicken the dex
1871 {
1872 std::string input_vdex = "--input-vdex-fd=-1";
1873 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_output->Fd());
1874 GenerateOdexForTest(dex_location,
1875 odex_location,
1876 CompilerFilter::kQuicken,
1877 // Disable cdex since we want to compare against the original dex file
1878 // after unquickening.
1879 { input_vdex, output_vdex, kDisableCompactDex },
1880 /* expect_success */ true,
1881 /* use_fd */ true);
1882 }
1883 // Unquicken by running the verify compiler filter on the vdex file and verify it matches.
1884 std::string odex_location2 = GetOdexDir() + "/unquickened.odex";
1885 std::string vdex_location2 = GetOdexDir() + "/unquickened.vdex";
1886 std::unique_ptr<File> vdex_unquickened(OS::CreateEmptyFile(vdex_location2.c_str()));
1887 {
1888 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_output->Fd());
1889 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_unquickened->Fd());
1890 GenerateOdexForTest(dex_location,
1891 odex_location2,
1892 CompilerFilter::kVerify,
1893 // Disable cdex to avoid needing to write out the shared section.
1894 { input_vdex, output_vdex, kDisableCompactDex },
1895 /* expect_success */ true,
1896 /* use_fd */ true);
1897 }
1898 ASSERT_EQ(vdex_unquickened->Flush(), 0) << "Could not flush and close vdex file";
Mathieu Chartier2daa1342018-02-20 16:19:28 -08001899 {
1900 // Check that hte vdex has one dex and compare it to the original one.
1901 std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location2.c_str(),
1902 /*writable*/ false,
1903 /*low_4gb*/ false,
1904 /*unquicken*/ false,
1905 &error_msg));
1906 std::vector<std::unique_ptr<const DexFile>> dex_files;
1907 bool result = vdex->OpenAllDexFiles(&dex_files, &error_msg);
1908 ASSERT_TRUE(result) << error_msg;
1909 ASSERT_EQ(dex_files.size(), 1u) << error_msg;
1910 ScratchFile temp;
1911 ASSERT_TRUE(temp.GetFile()->WriteFully(dex_files[0]->Begin(), dex_files[0]->Size()));
1912 ASSERT_EQ(temp.GetFile()->Flush(), 0) << "Could not flush extracted dex";
1913 EXPECT_EQ(temp.GetFile()->Compare(temp_dex.GetFile()), 0);
1914 }
1915 ASSERT_EQ(vdex_output->FlushCloseOrErase(), 0) << "Could not flush and close";
1916 ASSERT_EQ(vdex_unquickened->FlushCloseOrErase(), 0) << "Could not flush and close";
1917}
1918
Mathieu Chartiere8a494d2018-03-21 18:16:36 -07001919// Test that compact dex generation with invalid dex files doesn't crash dex2oat. b/75970654
1920TEST_F(Dex2oatTest, CompactDexInvalidSource) {
1921 ScratchFile invalid_dex;
1922 {
1923 FILE* file = fdopen(invalid_dex.GetFd(), "w+b");
1924 ZipWriter writer(file);
1925 writer.StartEntry("classes.dex", ZipWriter::kAlign32);
1926 DexFile::Header header = {};
1927 StandardDexFile::WriteMagic(header.magic_);
1928 StandardDexFile::WriteCurrentVersion(header.magic_);
1929 header.file_size_ = 4 * KB;
1930 header.data_size_ = 4 * KB;
1931 header.data_off_ = 10 * MB;
1932 header.map_off_ = 10 * MB;
1933 header.class_defs_off_ = 10 * MB;
1934 header.class_defs_size_ = 10000;
1935 ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
1936 writer.FinishEntry();
1937 writer.Finish();
1938 ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
1939 }
1940 const std::string dex_location = invalid_dex.GetFilename();
1941 const std::string odex_location = GetOdexDir() + "/output.odex";
1942 std::string error_msg;
1943 int status = GenerateOdexForTestWithStatus(
1944 {dex_location},
1945 odex_location,
1946 CompilerFilter::kQuicken,
1947 &error_msg,
1948 { "--compact-dex-level=fast" });
1949 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
1950}
1951
Mathieu Chartier229512a2018-03-22 14:33:20 -07001952// Test that dex2oat with a CompactDex file in the APK fails.
1953TEST_F(Dex2oatTest, CompactDexInZip) {
1954 CompactDexFile::Header header = {};
1955 CompactDexFile::WriteMagic(header.magic_);
1956 CompactDexFile::WriteCurrentVersion(header.magic_);
1957 header.file_size_ = sizeof(CompactDexFile::Header);
1958 header.data_off_ = 10 * MB;
1959 header.map_off_ = 10 * MB;
1960 header.class_defs_off_ = 10 * MB;
1961 header.class_defs_size_ = 10000;
1962 // Create a zip containing the invalid dex.
1963 ScratchFile invalid_dex_zip;
1964 {
1965 FILE* file = fdopen(invalid_dex_zip.GetFd(), "w+b");
1966 ZipWriter writer(file);
1967 writer.StartEntry("classes.dex", ZipWriter::kCompress);
1968 ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
1969 writer.FinishEntry();
1970 writer.Finish();
1971 ASSERT_EQ(invalid_dex_zip.GetFile()->Flush(), 0);
1972 }
1973 // Create the dex file directly.
1974 ScratchFile invalid_dex;
1975 {
1976 ASSERT_GE(invalid_dex.GetFile()->WriteFully(&header, sizeof(header)), 0);
1977 ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
1978 }
1979 std::string error_msg;
1980 int status = 0u;
1981
1982 status = GenerateOdexForTestWithStatus(
1983 { invalid_dex_zip.GetFilename() },
1984 GetOdexDir() + "/output_apk.odex",
1985 CompilerFilter::kQuicken,
1986 &error_msg,
1987 { "--compact-dex-level=fast" });
1988 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
1989
1990 status = GenerateOdexForTestWithStatus(
1991 { invalid_dex.GetFilename() },
1992 GetOdexDir() + "/output.odex",
1993 CompilerFilter::kQuicken,
1994 &error_msg,
1995 { "--compact-dex-level=fast" });
1996 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
1997}
1998
Mathieu Chartier6f96bbe2018-04-02 18:16:21 -07001999TEST_F(Dex2oatTest, AppImageNoProfile) {
2000 ScratchFile app_image_file;
2001 const std::string out_dir = GetScratchDir();
2002 const std::string odex_location = out_dir + "/base.odex";
2003 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2004 odex_location,
2005 CompilerFilter::Filter::kSpeedProfile,
2006 { "--app-image-fd=" + std::to_string(app_image_file.GetFd()) },
2007 true, // expect_success
2008 false, // use_fd
2009 [](const OatFile&) {});
2010 // Open our generated oat file.
2011 std::string error_msg;
Nicolas Geoffray96dca1c2018-04-19 14:43:29 +01002012 std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
2013 odex_location.c_str(),
Mathieu Chartier6f96bbe2018-04-02 18:16:21 -07002014 odex_location.c_str(),
2015 nullptr,
2016 nullptr,
2017 false,
2018 /*low_4gb*/false,
2019 odex_location.c_str(),
2020 &error_msg));
2021 ASSERT_TRUE(odex_file != nullptr);
2022 ImageHeader header = {};
2023 ASSERT_TRUE(app_image_file.GetFile()->PreadFully(
2024 reinterpret_cast<void*>(&header),
2025 sizeof(header),
2026 /*offset*/ 0u)) << app_image_file.GetFile()->GetLength();
2027 EXPECT_GT(header.GetImageSection(ImageHeader::kSectionObjects).Size(), 0u);
2028 EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtMethods).Size(), 0u);
2029 EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtFields).Size(), 0u);
2030}
2031
Mathieu Chartier8548de12018-03-23 21:51:54 -07002032TEST_F(Dex2oatClassLoaderContextTest, StoredClassLoaderContext) {
Mathieu Chartier0d6736f2018-04-16 14:40:56 -07002033 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("MultiDex");
Mathieu Chartier8548de12018-03-23 21:51:54 -07002034 const std::string out_dir = GetScratchDir();
2035 const std::string odex_location = out_dir + "/base.odex";
Mathieu Chartier0d6736f2018-04-16 14:40:56 -07002036 const std::string valid_context = "PCL[" + dex_files[0]->GetLocation() + "]";
Mathieu Chartier8548de12018-03-23 21:51:54 -07002037 const std::string stored_context = "PCL[/system/not_real_lib.jar]";
Mathieu Chartier0d6736f2018-04-16 14:40:56 -07002038 std::string expected_stored_context = "PCL[";
2039 size_t index = 1;
2040 for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
2041 const bool is_first = index == 1u;
2042 if (!is_first) {
2043 expected_stored_context += ":";
2044 }
2045 expected_stored_context += "/system/not_real_lib.jar";
2046 if (!is_first) {
2047 expected_stored_context += "!classes" + std::to_string(index) + ".dex";
2048 }
2049 expected_stored_context += "*" + std::to_string(dex_file->GetLocationChecksum());
2050 ++index;
2051 }
2052 expected_stored_context += + "]";
Mathieu Chartier8548de12018-03-23 21:51:54 -07002053 // The class path should not be valid and should fail being stored.
2054 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2055 odex_location,
2056 CompilerFilter::Filter::kQuicken,
2057 { "--class-loader-context=" + stored_context },
2058 true, // expect_success
2059 false, // use_fd
2060 [&](const OatFile& oat_file) {
Mathieu Chartier0d6736f2018-04-16 14:40:56 -07002061 EXPECT_NE(oat_file.GetClassLoaderContext(), stored_context) << output_;
2062 EXPECT_NE(oat_file.GetClassLoaderContext(), valid_context) << output_;
Mathieu Chartier8548de12018-03-23 21:51:54 -07002063 });
2064 // The stored context should match what we expect even though it's invalid.
2065 GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
2066 odex_location,
2067 CompilerFilter::Filter::kQuicken,
2068 { "--class-loader-context=" + valid_context,
2069 "--stored-class-loader-context=" + stored_context },
2070 true, // expect_success
2071 false, // use_fd
2072 [&](const OatFile& oat_file) {
Mathieu Chartier0d6736f2018-04-16 14:40:56 -07002073 EXPECT_EQ(oat_file.GetClassLoaderContext(), expected_stored_context) << output_;
Mathieu Chartier8548de12018-03-23 21:51:54 -07002074 });
2075}
2076
Andreas Gampee1459ae2016-06-29 09:36:30 -07002077} // namespace art