blob: 12bceb3c1fda81ef2a0d81807f38b96334e93924 [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
Andreas Gampe7adeda82016-07-25 08:27:35 -070017#include <regex>
18#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
25#include "android-base/stringprintf.h"
26
Andreas Gampee1459ae2016-06-29 09:36:30 -070027#include "common_runtime_test.h"
28
29#include "base/logging.h"
30#include "base/macros.h"
Andreas Gampeb486a982017-06-01 13:45:54 -070031#include "base/mutex-inl.h"
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +010032#include "bytecode_utils.h"
Andreas Gampee1459ae2016-06-29 09:36:30 -070033#include "dex2oat_environment_test.h"
Andreas Gampef7882972017-03-20 16:35:24 -070034#include "dex2oat_return_codes.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070035#include "dex_file-inl.h"
Calin Juravle33083d62017-01-18 15:29:12 -080036#include "jit/profile_compilation_info.h"
Andreas Gampe67f02822016-06-24 21:05:23 -070037#include "oat.h"
38#include "oat_file.h"
Andreas Gampee1459ae2016-06-29 09:36:30 -070039#include "utils.h"
40
Andreas Gampee1459ae2016-06-29 09:36:30 -070041namespace art {
42
Mathieu Chartierea650f32017-05-24 12:04:13 -070043static constexpr size_t kMaxMethodIds = 65535;
44
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080045using android::base::StringPrintf;
46
Andreas Gampee1459ae2016-06-29 09:36:30 -070047class Dex2oatTest : public Dex2oatEnvironmentTest {
48 public:
49 virtual void TearDown() OVERRIDE {
50 Dex2oatEnvironmentTest::TearDown();
51
52 output_ = "";
53 error_msg_ = "";
54 success_ = false;
55 }
56
57 protected:
Andreas Gampef7882972017-03-20 16:35:24 -070058 int GenerateOdexForTestWithStatus(const std::string& dex_location,
59 const std::string& odex_location,
60 CompilerFilter::Filter filter,
61 std::string* error_msg,
62 const std::vector<std::string>& extra_args = {},
63 bool use_fd = false) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080064 std::unique_ptr<File> oat_file;
Andreas Gampee1459ae2016-06-29 09:36:30 -070065 std::vector<std::string> args;
66 args.push_back("--dex-file=" + dex_location);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080067 if (use_fd) {
68 oat_file.reset(OS::CreateEmptyFile(odex_location.c_str()));
69 CHECK(oat_file != nullptr) << odex_location;
70 args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
Mathieu Chartier046854b2017-03-01 17:16:22 -080071 args.push_back("--oat-location=" + odex_location);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080072 } else {
73 args.push_back("--oat-file=" + odex_location);
74 }
Andreas Gampee1459ae2016-06-29 09:36:30 -070075 args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
76 args.push_back("--runtime-arg");
77 args.push_back("-Xnorelocate");
78
79 args.insert(args.end(), extra_args.begin(), extra_args.end());
80
Andreas Gampef7882972017-03-20 16:35:24 -070081 int status = Dex2Oat(args, error_msg);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080082 if (oat_file != nullptr) {
Andreas Gampef7882972017-03-20 16:35:24 -070083 CHECK_EQ(oat_file->FlushClose(), 0) << "Could not flush and close oat file";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080084 }
Andreas Gampef7882972017-03-20 16:35:24 -070085 return status;
86 }
Andreas Gampee1459ae2016-06-29 09:36:30 -070087
Andreas Gampef7882972017-03-20 16:35:24 -070088 void GenerateOdexForTest(const std::string& dex_location,
89 const std::string& odex_location,
90 CompilerFilter::Filter filter,
91 const std::vector<std::string>& extra_args = {},
92 bool expect_success = true,
Calin Juravle1ce70852017-06-28 10:59:03 -070093 bool use_fd = false,
94 std::function<void(const OatFile&)> check_oat = [](const OatFile&) {}) {
Andreas Gampef7882972017-03-20 16:35:24 -070095 std::string error_msg;
96 int status = GenerateOdexForTestWithStatus(dex_location,
97 odex_location,
98 filter,
99 &error_msg,
100 extra_args,
101 use_fd);
102 bool success = (status == 0);
Andreas Gampee1459ae2016-06-29 09:36:30 -0700103 if (expect_success) {
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800104 ASSERT_TRUE(success) << error_msg << std::endl << output_;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700105
106 // Verify the odex file was generated as expected.
107 std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
108 odex_location.c_str(),
109 nullptr,
110 nullptr,
111 false,
112 /*low_4gb*/false,
113 dex_location.c_str(),
114 &error_msg));
115 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
116
117 CheckFilter(filter, odex_file->GetCompilerFilter());
Calin Juravle1ce70852017-06-28 10:59:03 -0700118 check_oat(*(odex_file.get()));
Andreas Gampee1459ae2016-06-29 09:36:30 -0700119 } else {
120 ASSERT_FALSE(success) << output_;
121
122 error_msg_ = error_msg;
123
124 // Verify there's no loadable odex file.
125 std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
126 odex_location.c_str(),
127 nullptr,
128 nullptr,
129 false,
130 /*low_4gb*/false,
131 dex_location.c_str(),
132 &error_msg));
133 ASSERT_TRUE(odex_file.get() == nullptr);
134 }
135 }
136
Calin Juravle1ccf6132017-08-02 17:46:53 -0700137 // Check the input compiler filter against the generated oat file's filter. May be overridden
Andreas Gampee1459ae2016-06-29 09:36:30 -0700138 // in subclasses when equality is not expected.
139 virtual void CheckFilter(CompilerFilter::Filter expected, CompilerFilter::Filter actual) {
140 EXPECT_EQ(expected, actual);
141 }
142
Andreas Gampef7882972017-03-20 16:35:24 -0700143 int Dex2Oat(const std::vector<std::string>& dex2oat_args, std::string* error_msg) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700144 Runtime* runtime = Runtime::Current();
145
146 const std::vector<gc::space::ImageSpace*>& image_spaces =
147 runtime->GetHeap()->GetBootImageSpaces();
148 if (image_spaces.empty()) {
149 *error_msg = "No image location found for Dex2Oat.";
150 return false;
151 }
152 std::string image_location = image_spaces[0]->GetImageLocation();
153
154 std::vector<std::string> argv;
155 argv.push_back(runtime->GetCompilerExecutable());
Calin Juravle1ccf6132017-08-02 17:46:53 -0700156
Nicolas Geoffray433b79a2017-01-30 20:54:45 +0000157 if (runtime->IsJavaDebuggable()) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700158 argv.push_back("--debuggable");
159 }
160 runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
161
162 if (!runtime->IsVerificationEnabled()) {
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100163 argv.push_back("--compiler-filter=assume-verified");
Andreas Gampee1459ae2016-06-29 09:36:30 -0700164 }
165
166 if (runtime->MustRelocateIfPossible()) {
167 argv.push_back("--runtime-arg");
168 argv.push_back("-Xrelocate");
169 } else {
170 argv.push_back("--runtime-arg");
171 argv.push_back("-Xnorelocate");
172 }
173
174 if (!kIsTargetBuild) {
175 argv.push_back("--host");
176 }
177
178 argv.push_back("--boot-image=" + image_location);
179
180 std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
181 argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
182
183 argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
184
185 // We must set --android-root.
186 const char* android_root = getenv("ANDROID_ROOT");
187 CHECK(android_root != nullptr);
188 argv.push_back("--android-root=" + std::string(android_root));
189
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100190 int link[2];
Andreas Gampee1459ae2016-06-29 09:36:30 -0700191
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100192 if (pipe(link) == -1) {
193 return false;
194 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700195
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100196 pid_t pid = fork();
197 if (pid == -1) {
198 return false;
199 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700200
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100201 if (pid == 0) {
202 // We need dex2oat to actually log things.
203 setenv("ANDROID_LOG_TAGS", "*:d", 1);
204 dup2(link[1], STDERR_FILENO);
205 close(link[0]);
206 close(link[1]);
207 std::vector<const char*> c_args;
208 for (const std::string& str : argv) {
209 c_args.push_back(str.c_str());
Andreas Gampee1459ae2016-06-29 09:36:30 -0700210 }
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100211 c_args.push_back(nullptr);
212 execv(c_args[0], const_cast<char* const*>(c_args.data()));
213 exit(1);
Andreas Gampef7882972017-03-20 16:35:24 -0700214 UNREACHABLE();
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100215 } else {
216 close(link[1]);
217 char buffer[128];
218 memset(buffer, 0, 128);
219 ssize_t bytes_read = 0;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700220
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100221 while (TEMP_FAILURE_RETRY(bytes_read = read(link[0], buffer, 128)) > 0) {
222 output_ += std::string(buffer, bytes_read);
223 }
224 close(link[0]);
Andreas Gampef7882972017-03-20 16:35:24 -0700225 int status = -1;
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100226 if (waitpid(pid, &status, 0) != -1) {
227 success_ = (status == 0);
228 }
Andreas Gampef7882972017-03-20 16:35:24 -0700229 return status;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700230 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700231 }
232
233 std::string output_ = "";
234 std::string error_msg_ = "";
235 bool success_ = false;
236};
237
238class Dex2oatSwapTest : public Dex2oatTest {
239 protected:
240 void RunTest(bool use_fd, bool expect_use, const std::vector<std::string>& extra_args = {}) {
241 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
242 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
243
Andreas Gampe7adeda82016-07-25 08:27:35 -0700244 Copy(GetTestDexFileName(), dex_location);
Andreas Gampee1459ae2016-06-29 09:36:30 -0700245
246 std::vector<std::string> copy(extra_args);
247
248 std::unique_ptr<ScratchFile> sf;
249 if (use_fd) {
250 sf.reset(new ScratchFile());
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800251 copy.push_back(android::base::StringPrintf("--swap-fd=%d", sf->GetFd()));
Andreas Gampee1459ae2016-06-29 09:36:30 -0700252 } else {
253 std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
254 copy.push_back("--swap-file=" + swap_location);
255 }
256 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, copy);
257
258 CheckValidity();
259 ASSERT_TRUE(success_);
260 CheckResult(expect_use);
261 }
262
Andreas Gampe7adeda82016-07-25 08:27:35 -0700263 virtual std::string GetTestDexFileName() {
Vladimir Marko15357702017-02-09 10:37:31 +0000264 return Dex2oatEnvironmentTest::GetTestDexFileName("VerifierDeps");
Andreas Gampe7adeda82016-07-25 08:27:35 -0700265 }
266
267 virtual void CheckResult(bool expect_use) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700268 if (kIsTargetBuild) {
269 CheckTargetResult(expect_use);
270 } else {
271 CheckHostResult(expect_use);
272 }
273 }
274
Andreas Gampe7adeda82016-07-25 08:27:35 -0700275 virtual void CheckTargetResult(bool expect_use ATTRIBUTE_UNUSED) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700276 // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
277 // something for variants with file descriptor where we can control the lifetime of
278 // the swap file and thus take a look at it.
279 }
280
Andreas Gampe7adeda82016-07-25 08:27:35 -0700281 virtual void CheckHostResult(bool expect_use) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700282 if (!kIsTargetBuild) {
283 if (expect_use) {
284 EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
285 << output_;
286 } else {
287 EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
288 << output_;
289 }
290 }
291 }
292
293 // Check whether the dex2oat run was really successful.
Andreas Gampe7adeda82016-07-25 08:27:35 -0700294 virtual void CheckValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700295 if (kIsTargetBuild) {
296 CheckTargetValidity();
297 } else {
298 CheckHostValidity();
299 }
300 }
301
Andreas Gampe7adeda82016-07-25 08:27:35 -0700302 virtual void CheckTargetValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700303 // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
304 // something for variants with file descriptor where we can control the lifetime of
305 // the swap file and thus take a look at it.
306 }
307
308 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
Andreas Gampe7adeda82016-07-25 08:27:35 -0700309 virtual void CheckHostValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700310 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
311 }
312};
313
314TEST_F(Dex2oatSwapTest, DoNotUseSwapDefaultSingleSmall) {
315 RunTest(false /* use_fd */, false /* expect_use */);
316 RunTest(true /* use_fd */, false /* expect_use */);
317}
318
319TEST_F(Dex2oatSwapTest, DoNotUseSwapSingle) {
320 RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
321 RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
322}
323
324TEST_F(Dex2oatSwapTest, DoNotUseSwapSmall) {
325 RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
326 RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
327}
328
329TEST_F(Dex2oatSwapTest, DoUseSwapSingleSmall) {
330 RunTest(false /* use_fd */,
331 true /* expect_use */,
332 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
333 RunTest(true /* use_fd */,
334 true /* expect_use */,
335 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
336}
337
Andreas Gampe7adeda82016-07-25 08:27:35 -0700338class Dex2oatSwapUseTest : public Dex2oatSwapTest {
339 protected:
340 void CheckHostResult(bool expect_use) OVERRIDE {
341 if (!kIsTargetBuild) {
342 if (expect_use) {
343 EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
344 << output_;
345 } else {
346 EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
347 << output_;
348 }
349 }
350 }
351
352 std::string GetTestDexFileName() OVERRIDE {
353 // Use Statics as it has a handful of functions.
354 return CommonRuntimeTest::GetTestDexFileName("Statics");
355 }
356
357 void GrabResult1() {
358 if (!kIsTargetBuild) {
359 native_alloc_1_ = ParseNativeAlloc();
360 swap_1_ = ParseSwap(false /* expected */);
361 } else {
362 native_alloc_1_ = std::numeric_limits<size_t>::max();
363 swap_1_ = 0;
364 }
365 }
366
367 void GrabResult2() {
368 if (!kIsTargetBuild) {
369 native_alloc_2_ = ParseNativeAlloc();
370 swap_2_ = ParseSwap(true /* expected */);
371 } else {
372 native_alloc_2_ = 0;
373 swap_2_ = std::numeric_limits<size_t>::max();
374 }
375 }
376
377 private:
378 size_t ParseNativeAlloc() {
379 std::regex native_alloc_regex("dex2oat took.*native alloc=[^ ]+ \\(([0-9]+)B\\)");
380 std::smatch native_alloc_match;
381 bool found = std::regex_search(output_, native_alloc_match, native_alloc_regex);
382 if (!found) {
383 EXPECT_TRUE(found);
384 return 0;
385 }
386 if (native_alloc_match.size() != 2U) {
387 EXPECT_EQ(native_alloc_match.size(), 2U);
388 return 0;
389 }
390
391 std::istringstream stream(native_alloc_match[1].str());
392 size_t value;
393 stream >> value;
394
395 return value;
396 }
397
398 size_t ParseSwap(bool expected) {
399 std::regex swap_regex("dex2oat took[^\\n]+swap=[^ ]+ \\(([0-9]+)B\\)");
400 std::smatch swap_match;
401 bool found = std::regex_search(output_, swap_match, swap_regex);
402 if (found != expected) {
403 EXPECT_EQ(expected, found);
404 return 0;
405 }
406
407 if (!found) {
408 return 0;
409 }
410
411 if (swap_match.size() != 2U) {
412 EXPECT_EQ(swap_match.size(), 2U);
413 return 0;
414 }
415
416 std::istringstream stream(swap_match[1].str());
417 size_t value;
418 stream >> value;
419
420 return value;
421 }
422
423 protected:
424 size_t native_alloc_1_;
425 size_t native_alloc_2_;
426
427 size_t swap_1_;
428 size_t swap_2_;
429};
430
431TEST_F(Dex2oatSwapUseTest, CheckSwapUsage) {
Andreas Gampef4a67fd2017-05-04 09:55:36 -0700432 // Native memory usage isn't correctly tracked under sanitization.
433 TEST_DISABLED_FOR_MEMORY_TOOL_ASAN();
434
Vladimir Marko57070da2017-02-14 16:16:30 +0000435 // The `native_alloc_2_ >= native_alloc_1_` assertion below may not
Roland Levillain19772bf2017-02-16 11:28:10 +0000436 // hold true on some x86 systems; disable this test while we
437 // investigate (b/29259363).
438 TEST_DISABLED_FOR_X86();
Vladimir Marko57070da2017-02-14 16:16:30 +0000439
Andreas Gampe7adeda82016-07-25 08:27:35 -0700440 RunTest(false /* use_fd */,
441 false /* expect_use */);
442 GrabResult1();
443 std::string output_1 = output_;
444
445 output_ = "";
446
447 RunTest(false /* use_fd */,
448 true /* expect_use */,
449 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
450 GrabResult2();
451 std::string output_2 = output_;
452
453 if (native_alloc_2_ >= native_alloc_1_ || swap_1_ >= swap_2_) {
454 EXPECT_LT(native_alloc_2_, native_alloc_1_);
455 EXPECT_LT(swap_1_, swap_2_);
456
457 LOG(ERROR) << output_1;
458 LOG(ERROR) << output_2;
459 }
460}
461
Andreas Gampe67f02822016-06-24 21:05:23 -0700462class Dex2oatVeryLargeTest : public Dex2oatTest {
463 protected:
464 void CheckFilter(CompilerFilter::Filter input ATTRIBUTE_UNUSED,
465 CompilerFilter::Filter result ATTRIBUTE_UNUSED) OVERRIDE {
466 // Ignore, we'll do our own checks.
467 }
468
469 void RunTest(CompilerFilter::Filter filter,
470 bool expect_large,
471 const std::vector<std::string>& extra_args = {}) {
472 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
473 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
474
475 Copy(GetDexSrc1(), dex_location);
476
Andreas Gampeca620d72016-11-08 08:09:33 -0800477 GenerateOdexForTest(dex_location, odex_location, filter, extra_args);
Andreas Gampe67f02822016-06-24 21:05:23 -0700478
479 CheckValidity();
480 ASSERT_TRUE(success_);
481 CheckResult(dex_location, odex_location, filter, expect_large);
482 }
483
484 void CheckResult(const std::string& dex_location,
485 const std::string& odex_location,
486 CompilerFilter::Filter filter,
487 bool expect_large) {
488 // Host/target independent checks.
489 std::string error_msg;
490 std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
491 odex_location.c_str(),
492 nullptr,
493 nullptr,
494 false,
495 /*low_4gb*/false,
496 dex_location.c_str(),
497 &error_msg));
498 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
499 if (expect_large) {
500 // Note: we cannot check the following:
501 // EXPECT_TRUE(CompilerFilter::IsAsGoodAs(CompilerFilter::kVerifyAtRuntime,
502 // odex_file->GetCompilerFilter()));
503 // The reason is that the filter override currently happens when the dex files are
504 // loaded in dex2oat, which is after the oat file has been started. Thus, the header
505 // store cannot be changed, and the original filter is set in stone.
506
507 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
508 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
509 ASSERT_TRUE(dex_file != nullptr);
510 uint32_t class_def_count = dex_file->NumClassDefs();
511 ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
512 for (uint16_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
513 OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
514 EXPECT_EQ(oat_class.GetType(), OatClassType::kOatClassNoneCompiled);
515 }
516 }
517
518 // If the input filter was "below," it should have been used.
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100519 if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kExtract, filter)) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700520 EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
521 }
522 } else {
523 EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
524 }
525
526 // Host/target dependent checks.
527 if (kIsTargetBuild) {
528 CheckTargetResult(expect_large);
529 } else {
530 CheckHostResult(expect_large);
531 }
532 }
533
534 void CheckTargetResult(bool expect_large ATTRIBUTE_UNUSED) {
535 // TODO: Ignore for now. May do something for fd things.
536 }
537
538 void CheckHostResult(bool expect_large) {
539 if (!kIsTargetBuild) {
540 if (expect_large) {
Mathieu Chartier010126f2017-07-15 15:44:18 -0700541 EXPECT_NE(output_.find("Very large app, downgrading to"),
Andreas Gampe67f02822016-06-24 21:05:23 -0700542 std::string::npos)
543 << output_;
544 } else {
Mathieu Chartier010126f2017-07-15 15:44:18 -0700545 EXPECT_EQ(output_.find("Very large app, downgrading to"),
Andreas Gampe67f02822016-06-24 21:05:23 -0700546 std::string::npos)
547 << output_;
548 }
549 }
550 }
551
552 // Check whether the dex2oat run was really successful.
553 void CheckValidity() {
554 if (kIsTargetBuild) {
555 CheckTargetValidity();
556 } else {
557 CheckHostValidity();
558 }
559 }
560
561 void CheckTargetValidity() {
562 // TODO: Ignore for now.
563 }
564
565 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
566 void CheckHostValidity() {
567 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
568 }
569};
570
571TEST_F(Dex2oatVeryLargeTest, DontUseVeryLarge) {
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100572 RunTest(CompilerFilter::kAssumeVerified, false);
573 RunTest(CompilerFilter::kExtract, false);
574 RunTest(CompilerFilter::kQuicken, false);
Andreas Gampe67f02822016-06-24 21:05:23 -0700575 RunTest(CompilerFilter::kSpeed, false);
576
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100577 RunTest(CompilerFilter::kAssumeVerified, false, { "--very-large-app-threshold=1000000" });
578 RunTest(CompilerFilter::kExtract, false, { "--very-large-app-threshold=1000000" });
579 RunTest(CompilerFilter::kQuicken, false, { "--very-large-app-threshold=1000000" });
Andreas Gampe67f02822016-06-24 21:05:23 -0700580 RunTest(CompilerFilter::kSpeed, false, { "--very-large-app-threshold=1000000" });
581}
582
583TEST_F(Dex2oatVeryLargeTest, UseVeryLarge) {
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100584 RunTest(CompilerFilter::kAssumeVerified, false, { "--very-large-app-threshold=100" });
585 RunTest(CompilerFilter::kExtract, false, { "--very-large-app-threshold=100" });
586 RunTest(CompilerFilter::kQuicken, true, { "--very-large-app-threshold=100" });
Andreas Gampe67f02822016-06-24 21:05:23 -0700587 RunTest(CompilerFilter::kSpeed, true, { "--very-large-app-threshold=100" });
588}
589
Mathieu Chartier97ab5e32017-02-22 13:35:44 -0800590// Regressin test for b/35665292.
591TEST_F(Dex2oatVeryLargeTest, SpeedProfileNoProfile) {
592 // Test that dex2oat doesn't crash with speed-profile but no input profile.
593 RunTest(CompilerFilter::kSpeedProfile, false);
594}
595
Jeff Hao608f2ce2016-10-19 11:17:11 -0700596class Dex2oatLayoutTest : public Dex2oatTest {
597 protected:
598 void CheckFilter(CompilerFilter::Filter input ATTRIBUTE_UNUSED,
599 CompilerFilter::Filter result ATTRIBUTE_UNUSED) OVERRIDE {
600 // Ignore, we'll do our own checks.
601 }
602
Jeff Hao41fba6a2016-11-28 11:53:33 -0800603 // Emits a profile with a single dex file with the given location and a single class index of 1.
604 void GenerateProfile(const std::string& test_profile,
605 const std::string& dex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800606 size_t num_classes,
Jeff Hao41fba6a2016-11-28 11:53:33 -0800607 uint32_t checksum) {
608 int profile_test_fd = open(test_profile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
609 CHECK_GE(profile_test_fd, 0);
610
611 ProfileCompilationInfo info;
612 std::string profile_key = ProfileCompilationInfo::GetProfileDexFileKey(dex_location);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800613 for (size_t i = 0; i < num_classes; ++i) {
Mathieu Chartierea650f32017-05-24 12:04:13 -0700614 info.AddClassIndex(profile_key, checksum, dex::TypeIndex(1 + i), kMaxMethodIds);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800615 }
Jeff Hao41fba6a2016-11-28 11:53:33 -0800616 bool result = info.Save(profile_test_fd);
617 close(profile_test_fd);
618 ASSERT_TRUE(result);
619 }
620
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800621 void CompileProfileOdex(const std::string& dex_location,
622 const std::string& odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800623 const std::string& app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800624 bool use_fd,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800625 size_t num_profile_classes,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000626 const std::vector<std::string>& extra_args = {},
627 bool expect_success = true) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800628 const std::string profile_location = GetScratchDir() + "/primary.prof";
Jeff Hao41fba6a2016-11-28 11:53:33 -0800629 const char* location = dex_location.c_str();
630 std::string error_msg;
631 std::vector<std::unique_ptr<const DexFile>> dex_files;
632 ASSERT_TRUE(DexFile::Open(location, location, true, &error_msg, &dex_files));
633 EXPECT_EQ(dex_files.size(), 1U);
634 std::unique_ptr<const DexFile>& dex_file = dex_files[0];
Mathieu Chartier046854b2017-03-01 17:16:22 -0800635 GenerateProfile(profile_location,
636 dex_location,
637 num_profile_classes,
638 dex_file->GetLocationChecksum());
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800639 std::vector<std::string> copy(extra_args);
640 copy.push_back("--profile-file=" + profile_location);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800641 std::unique_ptr<File> app_image_file;
642 if (!app_image_file_name.empty()) {
643 if (use_fd) {
644 app_image_file.reset(OS::CreateEmptyFile(app_image_file_name.c_str()));
645 copy.push_back("--app-image-fd=" + std::to_string(app_image_file->Fd()));
646 } else {
647 copy.push_back("--app-image-file=" + app_image_file_name);
648 }
649 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800650 GenerateOdexForTest(dex_location,
651 odex_location,
652 CompilerFilter::kSpeedProfile,
653 copy,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000654 expect_success,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800655 use_fd);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800656 if (app_image_file != nullptr) {
657 ASSERT_EQ(app_image_file->FlushCloseOrErase(), 0) << "Could not flush and close art file";
658 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800659 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700660
Mathieu Chartier046854b2017-03-01 17:16:22 -0800661 uint64_t GetImageSize(const std::string& image_file_name) {
662 EXPECT_FALSE(image_file_name.empty());
663 std::unique_ptr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
664 CHECK(file != nullptr);
665 ImageHeader image_header;
666 const bool success = file->ReadFully(&image_header, sizeof(image_header));
667 CHECK(success);
668 CHECK(image_header.IsValid());
669 ReaderMutexLock mu(Thread::Current(), *Locks::mutator_lock_);
670 return image_header.GetImageSize();
671 }
672
673 void RunTest(bool app_image) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800674 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
675 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Mathieu Chartier046854b2017-03-01 17:16:22 -0800676 std::string app_image_file = app_image ? (GetOdexDir() + "/DexOdexNoOat.art"): "";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800677 Copy(GetDexSrc2(), dex_location);
678
Mathieu Chartier046854b2017-03-01 17:16:22 -0800679 uint64_t image_file_empty_profile = 0;
680 if (app_image) {
681 CompileProfileOdex(dex_location,
682 odex_location,
683 app_image_file,
684 /* use_fd */ false,
685 /* num_profile_classes */ 0);
686 CheckValidity();
687 ASSERT_TRUE(success_);
688 // Don't check the result since CheckResult relies on the class being in the profile.
689 image_file_empty_profile = GetImageSize(app_image_file);
690 EXPECT_GT(image_file_empty_profile, 0u);
691 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700692
Mathieu Chartier046854b2017-03-01 17:16:22 -0800693 // Small profile.
694 CompileProfileOdex(dex_location,
695 odex_location,
696 app_image_file,
697 /* use_fd */ false,
698 /* num_profile_classes */ 1);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700699 CheckValidity();
700 ASSERT_TRUE(success_);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800701 CheckResult(dex_location, odex_location, app_image_file);
702
703 if (app_image) {
704 // Test that the profile made a difference by adding more classes.
705 const uint64_t image_file_small_profile = GetImageSize(app_image_file);
706 CHECK_LT(image_file_empty_profile, image_file_small_profile);
707 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700708 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800709
710 void RunTestVDex() {
711 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
712 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
713 std::string vdex_location = GetOdexDir() + "/DexOdexNoOat.vdex";
Mathieu Chartier046854b2017-03-01 17:16:22 -0800714 std::string app_image_file_name = GetOdexDir() + "/DexOdexNoOat.art";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800715 Copy(GetDexSrc2(), dex_location);
716
717 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
718 CHECK(vdex_file1 != nullptr) << vdex_location;
719 ScratchFile vdex_file2;
720 {
721 std::string input_vdex = "--input-vdex-fd=-1";
722 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
723 CompileProfileOdex(dex_location,
724 odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800725 app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800726 /* use_fd */ true,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800727 /* num_profile_classes */ 1,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800728 { input_vdex, output_vdex });
729 EXPECT_GT(vdex_file1->GetLength(), 0u);
730 }
731 {
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000732 // Test that vdex and dexlayout fail gracefully.
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800733 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
734 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2.GetFd());
735 CompileProfileOdex(dex_location,
736 odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800737 app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800738 /* use_fd */ true,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800739 /* num_profile_classes */ 1,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000740 { input_vdex, output_vdex },
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100741 /* expect_success */ true);
742 EXPECT_GT(vdex_file2.GetFile()->GetLength(), 0u);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800743 }
744 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
745 CheckValidity();
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100746 ASSERT_TRUE(success_);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800747 }
748
Mathieu Chartier046854b2017-03-01 17:16:22 -0800749 void CheckResult(const std::string& dex_location,
750 const std::string& odex_location,
751 const std::string& app_image_file_name) {
Jeff Hao608f2ce2016-10-19 11:17:11 -0700752 // Host/target independent checks.
753 std::string error_msg;
754 std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
755 odex_location.c_str(),
756 nullptr,
757 nullptr,
758 false,
759 /*low_4gb*/false,
760 dex_location.c_str(),
761 &error_msg));
762 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
763
Jeff Hao042e8982016-10-19 11:17:11 -0700764 const char* location = dex_location.c_str();
765 std::vector<std::unique_ptr<const DexFile>> dex_files;
766 ASSERT_TRUE(DexFile::Open(location, location, true, &error_msg, &dex_files));
767 EXPECT_EQ(dex_files.size(), 1U);
768 std::unique_ptr<const DexFile>& old_dex_file = dex_files[0];
769
Jeff Hao608f2ce2016-10-19 11:17:11 -0700770 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
Jeff Hao042e8982016-10-19 11:17:11 -0700771 std::unique_ptr<const DexFile> new_dex_file = oat_dex_file->OpenDexFile(&error_msg);
772 ASSERT_TRUE(new_dex_file != nullptr);
773 uint32_t class_def_count = new_dex_file->NumClassDefs();
Jeff Hao608f2ce2016-10-19 11:17:11 -0700774 ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
Jeff Hao042e8982016-10-19 11:17:11 -0700775 ASSERT_GE(class_def_count, 2U);
776
777 // The new layout swaps the classes at indexes 0 and 1.
778 std::string old_class0 = old_dex_file->PrettyType(old_dex_file->GetClassDef(0).class_idx_);
779 std::string old_class1 = old_dex_file->PrettyType(old_dex_file->GetClassDef(1).class_idx_);
780 std::string new_class0 = new_dex_file->PrettyType(new_dex_file->GetClassDef(0).class_idx_);
781 std::string new_class1 = new_dex_file->PrettyType(new_dex_file->GetClassDef(1).class_idx_);
782 EXPECT_EQ(old_class0, new_class1);
783 EXPECT_EQ(old_class1, new_class0);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700784 }
785
Jeff Haoc155b052017-01-17 17:43:29 -0800786 EXPECT_EQ(odex_file->GetCompilerFilter(), CompilerFilter::kSpeedProfile);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800787
788 if (!app_image_file_name.empty()) {
789 // Go peek at the image header to make sure it was large enough to contain the class.
790 std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file_name.c_str()));
791 ImageHeader image_header;
792 bool success = file->ReadFully(&image_header, sizeof(image_header));
793 ASSERT_TRUE(success);
794 ASSERT_TRUE(image_header.IsValid());
795 EXPECT_GT(image_header.GetImageSection(ImageHeader::kSectionObjects).Size(), 0u);
796 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700797 }
798
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800799 // Check whether the dex2oat run was really successful.
800 void CheckValidity() {
801 if (kIsTargetBuild) {
802 CheckTargetValidity();
803 } else {
804 CheckHostValidity();
Jeff Hao608f2ce2016-10-19 11:17:11 -0700805 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800806 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700807
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800808 void CheckTargetValidity() {
809 // TODO: Ignore for now.
810 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700811
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800812 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
813 void CheckHostValidity() {
814 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
815 }
816};
Jeff Hao608f2ce2016-10-19 11:17:11 -0700817
818TEST_F(Dex2oatLayoutTest, TestLayout) {
Mathieu Chartier046854b2017-03-01 17:16:22 -0800819 RunTest(/* app-image */ false);
820}
821
822TEST_F(Dex2oatLayoutTest, TestLayoutAppImage) {
823 RunTest(/* app-image */ true);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700824}
825
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800826TEST_F(Dex2oatLayoutTest, TestVdexLayout) {
827 RunTestVDex();
828}
829
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100830class Dex2oatUnquickenTest : public Dex2oatTest {
831 protected:
832 void RunUnquickenMultiDex() {
833 std::string dex_location = GetScratchDir() + "/UnquickenMultiDex.jar";
834 std::string odex_location = GetOdexDir() + "/UnquickenMultiDex.odex";
835 std::string vdex_location = GetOdexDir() + "/UnquickenMultiDex.vdex";
836 Copy(GetTestDexFileName("MultiDex"), dex_location);
837
838 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
839 CHECK(vdex_file1 != nullptr) << vdex_location;
840 // Quicken the dex file into a vdex file.
841 {
842 std::string input_vdex = "--input-vdex-fd=-1";
843 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
844 GenerateOdexForTest(dex_location,
845 odex_location,
846 CompilerFilter::kQuicken,
847 { input_vdex, output_vdex },
848 /* expect_success */ true,
849 /* use_fd */ true);
850 EXPECT_GT(vdex_file1->GetLength(), 0u);
851 }
852 // Unquicken by running the verify compiler filter on the vdex file.
853 {
854 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
855 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
856 GenerateOdexForTest(dex_location,
857 odex_location,
858 CompilerFilter::kVerify,
859 { input_vdex, output_vdex },
860 /* expect_success */ true,
861 /* use_fd */ true);
862 }
863 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
864 CheckResult(dex_location, odex_location);
865 ASSERT_TRUE(success_);
866 }
867
868 void CheckResult(const std::string& dex_location, const std::string& odex_location) {
869 std::string error_msg;
870 std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
871 odex_location.c_str(),
872 nullptr,
873 nullptr,
874 false,
875 /*low_4gb*/false,
876 dex_location.c_str(),
877 &error_msg));
878 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
879 ASSERT_GE(odex_file->GetOatDexFiles().size(), 1u);
880
881 // Iterate over the dex files and ensure there is no quickened instruction.
882 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
883 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
884 for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
885 const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
886 const uint8_t* class_data = dex_file->GetClassData(class_def);
887 if (class_data != nullptr) {
888 for (ClassDataItemIterator class_it(*dex_file, class_data);
889 class_it.HasNext();
890 class_it.Next()) {
891 if (class_it.IsAtMethod() && class_it.GetMethodCodeItem() != nullptr) {
892 for (CodeItemIterator it(*class_it.GetMethodCodeItem()); !it.Done(); it.Advance()) {
893 Instruction* inst = const_cast<Instruction*>(&it.CurrentInstruction());
894 ASSERT_FALSE(inst->IsQuickened());
895 }
896 }
897 }
898 }
899 }
900 }
901 }
902};
903
904TEST_F(Dex2oatUnquickenTest, UnquickenMultiDex) {
905 RunUnquickenMultiDex();
906}
907
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800908class Dex2oatWatchdogTest : public Dex2oatTest {
909 protected:
910 void RunTest(bool expect_success, const std::vector<std::string>& extra_args = {}) {
911 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
912 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
913
914 Copy(GetTestDexFileName(), dex_location);
915
916 std::vector<std::string> copy(extra_args);
917
918 std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
919 copy.push_back("--swap-file=" + swap_location);
920 GenerateOdexForTest(dex_location,
921 odex_location,
922 CompilerFilter::kSpeed,
923 copy,
924 expect_success);
925 }
926
927 std::string GetTestDexFileName() {
928 return GetDexSrc1();
929 }
930};
931
932TEST_F(Dex2oatWatchdogTest, TestWatchdogOK) {
933 // Check with default.
934 RunTest(true);
935
936 // Check with ten minutes.
937 RunTest(true, { "--watchdog-timeout=600000" });
938}
939
940TEST_F(Dex2oatWatchdogTest, TestWatchdogTrigger) {
941 // Check with ten milliseconds.
942 RunTest(false, { "--watchdog-timeout=10" });
943}
944
Andreas Gampef7882972017-03-20 16:35:24 -0700945class Dex2oatReturnCodeTest : public Dex2oatTest {
946 protected:
947 int RunTest(const std::vector<std::string>& extra_args = {}) {
948 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
949 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
950
951 Copy(GetTestDexFileName(), dex_location);
952
953 std::string error_msg;
954 return GenerateOdexForTestWithStatus(dex_location,
955 odex_location,
956 CompilerFilter::kSpeed,
957 &error_msg,
958 extra_args);
959 }
960
961 std::string GetTestDexFileName() {
962 return GetDexSrc1();
963 }
964};
965
966TEST_F(Dex2oatReturnCodeTest, TestCreateRuntime) {
Andreas Gampefd80b172017-04-26 22:25:31 -0700967 TEST_DISABLED_FOR_MEMORY_TOOL(); // b/19100793
Andreas Gampef7882972017-03-20 16:35:24 -0700968 int status = RunTest({ "--boot-image=/this/does/not/exist/yolo.oat" });
969 EXPECT_EQ(static_cast<int>(dex2oat::ReturnCode::kCreateRuntime), WEXITSTATUS(status)) << output_;
970}
971
Calin Juravle1ce70852017-06-28 10:59:03 -0700972class Dex2oatClassLoaderContextTest : public Dex2oatTest {
973 protected:
974 void RunTest(const char* class_loader_context,
975 const char* expected_classpath_key,
976 bool expected_success,
977 bool use_second_source = false) {
978 std::string dex_location = GetUsedDexLocation();
979 std::string odex_location = GetUsedOatLocation();
980
981 Copy(use_second_source ? GetDexSrc2() : GetDexSrc1(), dex_location);
982
983 std::string error_msg;
984 std::vector<std::string> extra_args;
985 if (class_loader_context != nullptr) {
986 extra_args.push_back(std::string("--class-loader-context=") + class_loader_context);
987 }
988 auto check_oat = [expected_classpath_key](const OatFile& oat_file) {
989 ASSERT_TRUE(expected_classpath_key != nullptr);
990 const char* classpath = oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
991 ASSERT_TRUE(classpath != nullptr);
992 ASSERT_STREQ(expected_classpath_key, classpath);
993 };
994
995 GenerateOdexForTest(dex_location,
996 odex_location,
997 CompilerFilter::kQuicken,
998 extra_args,
999 expected_success,
1000 /*use_fd*/ false,
1001 check_oat);
1002 }
1003
1004 std::string GetUsedDexLocation() {
1005 return GetScratchDir() + "/Context.jar";
1006 }
1007
1008 std::string GetUsedOatLocation() {
1009 return GetOdexDir() + "/Context.odex";
1010 }
1011
Calin Juravle7b0648a2017-07-07 18:40:50 -07001012 const char* kEmptyClassPathKey = "PCL[]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001013};
1014
1015TEST_F(Dex2oatClassLoaderContextTest, InvalidContext) {
1016 RunTest("Invalid[]", /*expected_classpath_key*/ nullptr, /*expected_success*/ false);
1017}
1018
1019TEST_F(Dex2oatClassLoaderContextTest, EmptyContext) {
1020 RunTest("PCL[]", kEmptyClassPathKey, /*expected_success*/ true);
1021}
1022
1023TEST_F(Dex2oatClassLoaderContextTest, SpecialContext) {
1024 RunTest(OatFile::kSpecialSharedLibrary,
1025 OatFile::kSpecialSharedLibrary,
1026 /*expected_success*/ true);
1027}
1028
1029TEST_F(Dex2oatClassLoaderContextTest, ContextWithTheSourceDexFiles) {
1030 std::string context = "PCL[" + GetUsedDexLocation() + "]";
1031 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1032}
1033
1034TEST_F(Dex2oatClassLoaderContextTest, ContextWithOtherDexFiles) {
1035 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Nested");
Calin Juravle1ce70852017-06-28 10:59:03 -07001036
1037 std::string context = "PCL[" + dex_files[0]->GetLocation() + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -07001038 std::string expected_classpath_key = "PCL[" +
1039 dex_files[0]->GetLocation() + "*" + std::to_string(dex_files[0]->GetLocationChecksum()) + "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001040 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1041}
1042
1043TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFiles) {
1044 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
1045 Copy(GetStrippedDexSrc1(), stripped_classpath);
1046
1047 std::string context = "PCL[" + stripped_classpath + "]";
1048 // Expect an empty context because stripped dex files cannot be open.
Calin Juravle7b0648a2017-07-07 18:40:50 -07001049 RunTest(context.c_str(), kEmptyClassPathKey , /*expected_success*/ true);
Calin Juravle1ce70852017-06-28 10:59:03 -07001050}
1051
1052TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFilesBackedByOdex) {
1053 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
1054 std::string odex_for_classpath = GetOdexDir() + "/stripped_classpath.odex";
1055
1056 Copy(GetDexSrc1(), stripped_classpath);
1057
1058 GenerateOdexForTest(stripped_classpath,
1059 odex_for_classpath,
1060 CompilerFilter::kQuicken,
1061 {},
1062 true);
1063
1064 // Strip the dex file
1065 Copy(GetStrippedDexSrc1(), stripped_classpath);
1066
1067 std::string context = "PCL[" + stripped_classpath + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -07001068 std::string expected_classpath_key;
Calin Juravle1ce70852017-06-28 10:59:03 -07001069 {
1070 // Open the oat file to get the expected classpath.
1071 OatFileAssistant oat_file_assistant(stripped_classpath.c_str(), kRuntimeISA, false);
1072 std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile());
1073 std::vector<std::unique_ptr<const DexFile>> oat_dex_files =
1074 OatFileAssistant::LoadDexFiles(*oat_file, stripped_classpath.c_str());
Calin Juravle7b0648a2017-07-07 18:40:50 -07001075 expected_classpath_key = "PCL[";
1076 for (size_t i = 0; i < oat_dex_files.size(); i++) {
1077 if (i > 0) {
1078 expected_classpath_key + ":";
1079 }
1080 expected_classpath_key += oat_dex_files[i]->GetLocation() + "*" +
1081 std::to_string(oat_dex_files[i]->GetLocationChecksum());
1082 }
1083 expected_classpath_key += "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001084 }
1085
1086 RunTest(context.c_str(),
Calin Juravle7b0648a2017-07-07 18:40:50 -07001087 expected_classpath_key.c_str(),
Calin Juravle1ce70852017-06-28 10:59:03 -07001088 /*expected_success*/ true,
1089 /*use_second_source*/ true);
1090}
1091
1092TEST_F(Dex2oatClassLoaderContextTest, ContextWithNotExistentDexFiles) {
1093 std::string context = "PCL[does_not_exists.dex]";
1094 // Expect an empty context because stripped dex files cannot be open.
1095 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1096}
1097
Calin Juravlec79470d2017-07-12 17:37:42 -07001098TEST_F(Dex2oatClassLoaderContextTest, ChainContext) {
1099 std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1100 std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1101
1102 std::string context = "PCL[" + GetTestDexFileName("Nested") + "];" +
1103 "DLC[" + GetTestDexFileName("MultiDex") + "]";
1104 std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "];" +
1105 "DLC[" + CreateClassPathWithChecksums(dex_files2) + "]";
1106
1107 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1108}
1109
Andreas Gampee1459ae2016-06-29 09:36:30 -07001110} // namespace art