blob: 3538215f6b9b5c36bf52d6ed2f3ebd85149cea54 [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"
Jeff Hao608f2ce2016-10-19 11:17:11 -070032#include "dex_file-inl.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"
Calin Juravle33083d62017-01-18 15:29:12 -080035#include "jit/profile_compilation_info.h"
Andreas Gampe67f02822016-06-24 21:05:23 -070036#include "oat.h"
37#include "oat_file.h"
Andreas Gampee1459ae2016-06-29 09:36:30 -070038#include "utils.h"
39
Andreas Gampee1459ae2016-06-29 09:36:30 -070040namespace art {
41
Mathieu Chartierea650f32017-05-24 12:04:13 -070042static constexpr size_t kMaxMethodIds = 65535;
43
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080044using android::base::StringPrintf;
45
Andreas Gampee1459ae2016-06-29 09:36:30 -070046class Dex2oatTest : public Dex2oatEnvironmentTest {
47 public:
48 virtual void TearDown() OVERRIDE {
49 Dex2oatEnvironmentTest::TearDown();
50
51 output_ = "";
52 error_msg_ = "";
53 success_ = false;
54 }
55
56 protected:
Andreas Gampef7882972017-03-20 16:35:24 -070057 int GenerateOdexForTestWithStatus(const std::string& dex_location,
58 const std::string& odex_location,
59 CompilerFilter::Filter filter,
60 std::string* error_msg,
61 const std::vector<std::string>& extra_args = {},
62 bool use_fd = false) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080063 std::unique_ptr<File> oat_file;
Andreas Gampee1459ae2016-06-29 09:36:30 -070064 std::vector<std::string> args;
65 args.push_back("--dex-file=" + dex_location);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080066 if (use_fd) {
67 oat_file.reset(OS::CreateEmptyFile(odex_location.c_str()));
68 CHECK(oat_file != nullptr) << odex_location;
69 args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
Mathieu Chartier046854b2017-03-01 17:16:22 -080070 args.push_back("--oat-location=" + odex_location);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080071 } else {
72 args.push_back("--oat-file=" + odex_location);
73 }
Andreas Gampee1459ae2016-06-29 09:36:30 -070074 args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
75 args.push_back("--runtime-arg");
76 args.push_back("-Xnorelocate");
77
78 args.insert(args.end(), extra_args.begin(), extra_args.end());
79
Andreas Gampef7882972017-03-20 16:35:24 -070080 int status = Dex2Oat(args, error_msg);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080081 if (oat_file != nullptr) {
Andreas Gampef7882972017-03-20 16:35:24 -070082 CHECK_EQ(oat_file->FlushClose(), 0) << "Could not flush and close oat file";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -080083 }
Andreas Gampef7882972017-03-20 16:35:24 -070084 return status;
85 }
Andreas Gampee1459ae2016-06-29 09:36:30 -070086
Andreas Gampef7882972017-03-20 16:35:24 -070087 void GenerateOdexForTest(const std::string& dex_location,
88 const std::string& odex_location,
89 CompilerFilter::Filter filter,
90 const std::vector<std::string>& extra_args = {},
91 bool expect_success = true,
Calin Juravle1ce70852017-06-28 10:59:03 -070092 bool use_fd = false,
93 std::function<void(const OatFile&)> check_oat = [](const OatFile&) {}) {
Andreas Gampef7882972017-03-20 16:35:24 -070094 std::string error_msg;
95 int status = GenerateOdexForTestWithStatus(dex_location,
96 odex_location,
97 filter,
98 &error_msg,
99 extra_args,
100 use_fd);
101 bool success = (status == 0);
Andreas Gampee1459ae2016-06-29 09:36:30 -0700102 if (expect_success) {
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800103 ASSERT_TRUE(success) << error_msg << std::endl << output_;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700104
105 // Verify the odex file was generated as expected.
106 std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
107 odex_location.c_str(),
108 nullptr,
109 nullptr,
110 false,
111 /*low_4gb*/false,
112 dex_location.c_str(),
113 &error_msg));
114 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
115
116 CheckFilter(filter, odex_file->GetCompilerFilter());
Calin Juravle1ce70852017-06-28 10:59:03 -0700117 check_oat(*(odex_file.get()));
Andreas Gampee1459ae2016-06-29 09:36:30 -0700118 } else {
119 ASSERT_FALSE(success) << output_;
120
121 error_msg_ = error_msg;
122
123 // Verify there's no loadable odex file.
124 std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
125 odex_location.c_str(),
126 nullptr,
127 nullptr,
128 false,
129 /*low_4gb*/false,
130 dex_location.c_str(),
131 &error_msg));
132 ASSERT_TRUE(odex_file.get() == nullptr);
133 }
134 }
135
136 // Check the input compiler filter against the generated oat file's filter. Mayb be overridden
137 // in subclasses when equality is not expected.
138 virtual void CheckFilter(CompilerFilter::Filter expected, CompilerFilter::Filter actual) {
139 EXPECT_EQ(expected, actual);
140 }
141
Andreas Gampef7882972017-03-20 16:35:24 -0700142 int Dex2Oat(const std::vector<std::string>& dex2oat_args, std::string* error_msg) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700143 Runtime* runtime = Runtime::Current();
144
145 const std::vector<gc::space::ImageSpace*>& image_spaces =
146 runtime->GetHeap()->GetBootImageSpaces();
147 if (image_spaces.empty()) {
148 *error_msg = "No image location found for Dex2Oat.";
149 return false;
150 }
151 std::string image_location = image_spaces[0]->GetImageLocation();
152
153 std::vector<std::string> argv;
154 argv.push_back(runtime->GetCompilerExecutable());
155 argv.push_back("--runtime-arg");
156 argv.push_back("-classpath");
157 argv.push_back("--runtime-arg");
158 std::string class_path = runtime->GetClassPathString();
159 if (class_path == "") {
160 class_path = OatFile::kSpecialSharedLibrary;
161 }
162 argv.push_back(class_path);
Nicolas Geoffray433b79a2017-01-30 20:54:45 +0000163 if (runtime->IsJavaDebuggable()) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700164 argv.push_back("--debuggable");
165 }
166 runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
167
168 if (!runtime->IsVerificationEnabled()) {
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100169 argv.push_back("--compiler-filter=assume-verified");
Andreas Gampee1459ae2016-06-29 09:36:30 -0700170 }
171
172 if (runtime->MustRelocateIfPossible()) {
173 argv.push_back("--runtime-arg");
174 argv.push_back("-Xrelocate");
175 } else {
176 argv.push_back("--runtime-arg");
177 argv.push_back("-Xnorelocate");
178 }
179
180 if (!kIsTargetBuild) {
181 argv.push_back("--host");
182 }
183
184 argv.push_back("--boot-image=" + image_location);
185
186 std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
187 argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
188
189 argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
190
191 // We must set --android-root.
192 const char* android_root = getenv("ANDROID_ROOT");
193 CHECK(android_root != nullptr);
194 argv.push_back("--android-root=" + std::string(android_root));
195
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100196 int link[2];
Andreas Gampee1459ae2016-06-29 09:36:30 -0700197
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100198 if (pipe(link) == -1) {
199 return false;
200 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700201
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100202 pid_t pid = fork();
203 if (pid == -1) {
204 return false;
205 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700206
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100207 if (pid == 0) {
208 // We need dex2oat to actually log things.
209 setenv("ANDROID_LOG_TAGS", "*:d", 1);
210 dup2(link[1], STDERR_FILENO);
211 close(link[0]);
212 close(link[1]);
213 std::vector<const char*> c_args;
214 for (const std::string& str : argv) {
215 c_args.push_back(str.c_str());
Andreas Gampee1459ae2016-06-29 09:36:30 -0700216 }
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100217 c_args.push_back(nullptr);
218 execv(c_args[0], const_cast<char* const*>(c_args.data()));
219 exit(1);
Andreas Gampef7882972017-03-20 16:35:24 -0700220 UNREACHABLE();
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100221 } else {
222 close(link[1]);
223 char buffer[128];
224 memset(buffer, 0, 128);
225 ssize_t bytes_read = 0;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700226
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100227 while (TEMP_FAILURE_RETRY(bytes_read = read(link[0], buffer, 128)) > 0) {
228 output_ += std::string(buffer, bytes_read);
229 }
230 close(link[0]);
Andreas Gampef7882972017-03-20 16:35:24 -0700231 int status = -1;
Nicolas Geoffray56fe0f02016-06-30 15:07:46 +0100232 if (waitpid(pid, &status, 0) != -1) {
233 success_ = (status == 0);
234 }
Andreas Gampef7882972017-03-20 16:35:24 -0700235 return status;
Andreas Gampee1459ae2016-06-29 09:36:30 -0700236 }
Andreas Gampee1459ae2016-06-29 09:36:30 -0700237 }
238
239 std::string output_ = "";
240 std::string error_msg_ = "";
241 bool success_ = false;
242};
243
244class Dex2oatSwapTest : public Dex2oatTest {
245 protected:
246 void RunTest(bool use_fd, bool expect_use, const std::vector<std::string>& extra_args = {}) {
247 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
248 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
249
Andreas Gampe7adeda82016-07-25 08:27:35 -0700250 Copy(GetTestDexFileName(), dex_location);
Andreas Gampee1459ae2016-06-29 09:36:30 -0700251
252 std::vector<std::string> copy(extra_args);
253
254 std::unique_ptr<ScratchFile> sf;
255 if (use_fd) {
256 sf.reset(new ScratchFile());
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800257 copy.push_back(android::base::StringPrintf("--swap-fd=%d", sf->GetFd()));
Andreas Gampee1459ae2016-06-29 09:36:30 -0700258 } else {
259 std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
260 copy.push_back("--swap-file=" + swap_location);
261 }
262 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, copy);
263
264 CheckValidity();
265 ASSERT_TRUE(success_);
266 CheckResult(expect_use);
267 }
268
Andreas Gampe7adeda82016-07-25 08:27:35 -0700269 virtual std::string GetTestDexFileName() {
Vladimir Marko15357702017-02-09 10:37:31 +0000270 return Dex2oatEnvironmentTest::GetTestDexFileName("VerifierDeps");
Andreas Gampe7adeda82016-07-25 08:27:35 -0700271 }
272
273 virtual void CheckResult(bool expect_use) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700274 if (kIsTargetBuild) {
275 CheckTargetResult(expect_use);
276 } else {
277 CheckHostResult(expect_use);
278 }
279 }
280
Andreas Gampe7adeda82016-07-25 08:27:35 -0700281 virtual void CheckTargetResult(bool expect_use ATTRIBUTE_UNUSED) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700282 // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
283 // something for variants with file descriptor where we can control the lifetime of
284 // the swap file and thus take a look at it.
285 }
286
Andreas Gampe7adeda82016-07-25 08:27:35 -0700287 virtual void CheckHostResult(bool expect_use) {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700288 if (!kIsTargetBuild) {
289 if (expect_use) {
290 EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
291 << output_;
292 } else {
293 EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
294 << output_;
295 }
296 }
297 }
298
299 // Check whether the dex2oat run was really successful.
Andreas Gampe7adeda82016-07-25 08:27:35 -0700300 virtual void CheckValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700301 if (kIsTargetBuild) {
302 CheckTargetValidity();
303 } else {
304 CheckHostValidity();
305 }
306 }
307
Andreas Gampe7adeda82016-07-25 08:27:35 -0700308 virtual void CheckTargetValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700309 // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
310 // something for variants with file descriptor where we can control the lifetime of
311 // the swap file and thus take a look at it.
312 }
313
314 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
Andreas Gampe7adeda82016-07-25 08:27:35 -0700315 virtual void CheckHostValidity() {
Andreas Gampee1459ae2016-06-29 09:36:30 -0700316 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
317 }
318};
319
320TEST_F(Dex2oatSwapTest, DoNotUseSwapDefaultSingleSmall) {
321 RunTest(false /* use_fd */, false /* expect_use */);
322 RunTest(true /* use_fd */, false /* expect_use */);
323}
324
325TEST_F(Dex2oatSwapTest, DoNotUseSwapSingle) {
326 RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
327 RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
328}
329
330TEST_F(Dex2oatSwapTest, DoNotUseSwapSmall) {
331 RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
332 RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
333}
334
335TEST_F(Dex2oatSwapTest, DoUseSwapSingleSmall) {
336 RunTest(false /* use_fd */,
337 true /* expect_use */,
338 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
339 RunTest(true /* use_fd */,
340 true /* expect_use */,
341 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
342}
343
Andreas Gampe7adeda82016-07-25 08:27:35 -0700344class Dex2oatSwapUseTest : public Dex2oatSwapTest {
345 protected:
346 void CheckHostResult(bool expect_use) OVERRIDE {
347 if (!kIsTargetBuild) {
348 if (expect_use) {
349 EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
350 << output_;
351 } else {
352 EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
353 << output_;
354 }
355 }
356 }
357
358 std::string GetTestDexFileName() OVERRIDE {
359 // Use Statics as it has a handful of functions.
360 return CommonRuntimeTest::GetTestDexFileName("Statics");
361 }
362
363 void GrabResult1() {
364 if (!kIsTargetBuild) {
365 native_alloc_1_ = ParseNativeAlloc();
366 swap_1_ = ParseSwap(false /* expected */);
367 } else {
368 native_alloc_1_ = std::numeric_limits<size_t>::max();
369 swap_1_ = 0;
370 }
371 }
372
373 void GrabResult2() {
374 if (!kIsTargetBuild) {
375 native_alloc_2_ = ParseNativeAlloc();
376 swap_2_ = ParseSwap(true /* expected */);
377 } else {
378 native_alloc_2_ = 0;
379 swap_2_ = std::numeric_limits<size_t>::max();
380 }
381 }
382
383 private:
384 size_t ParseNativeAlloc() {
385 std::regex native_alloc_regex("dex2oat took.*native alloc=[^ ]+ \\(([0-9]+)B\\)");
386 std::smatch native_alloc_match;
387 bool found = std::regex_search(output_, native_alloc_match, native_alloc_regex);
388 if (!found) {
389 EXPECT_TRUE(found);
390 return 0;
391 }
392 if (native_alloc_match.size() != 2U) {
393 EXPECT_EQ(native_alloc_match.size(), 2U);
394 return 0;
395 }
396
397 std::istringstream stream(native_alloc_match[1].str());
398 size_t value;
399 stream >> value;
400
401 return value;
402 }
403
404 size_t ParseSwap(bool expected) {
405 std::regex swap_regex("dex2oat took[^\\n]+swap=[^ ]+ \\(([0-9]+)B\\)");
406 std::smatch swap_match;
407 bool found = std::regex_search(output_, swap_match, swap_regex);
408 if (found != expected) {
409 EXPECT_EQ(expected, found);
410 return 0;
411 }
412
413 if (!found) {
414 return 0;
415 }
416
417 if (swap_match.size() != 2U) {
418 EXPECT_EQ(swap_match.size(), 2U);
419 return 0;
420 }
421
422 std::istringstream stream(swap_match[1].str());
423 size_t value;
424 stream >> value;
425
426 return value;
427 }
428
429 protected:
430 size_t native_alloc_1_;
431 size_t native_alloc_2_;
432
433 size_t swap_1_;
434 size_t swap_2_;
435};
436
437TEST_F(Dex2oatSwapUseTest, CheckSwapUsage) {
Andreas Gampef4a67fd2017-05-04 09:55:36 -0700438 // Native memory usage isn't correctly tracked under sanitization.
439 TEST_DISABLED_FOR_MEMORY_TOOL_ASAN();
440
Vladimir Marko57070da2017-02-14 16:16:30 +0000441 // The `native_alloc_2_ >= native_alloc_1_` assertion below may not
Roland Levillain19772bf2017-02-16 11:28:10 +0000442 // hold true on some x86 systems; disable this test while we
443 // investigate (b/29259363).
444 TEST_DISABLED_FOR_X86();
Vladimir Marko57070da2017-02-14 16:16:30 +0000445
Andreas Gampe7adeda82016-07-25 08:27:35 -0700446 RunTest(false /* use_fd */,
447 false /* expect_use */);
448 GrabResult1();
449 std::string output_1 = output_;
450
451 output_ = "";
452
453 RunTest(false /* use_fd */,
454 true /* expect_use */,
455 { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
456 GrabResult2();
457 std::string output_2 = output_;
458
459 if (native_alloc_2_ >= native_alloc_1_ || swap_1_ >= swap_2_) {
460 EXPECT_LT(native_alloc_2_, native_alloc_1_);
461 EXPECT_LT(swap_1_, swap_2_);
462
463 LOG(ERROR) << output_1;
464 LOG(ERROR) << output_2;
465 }
466}
467
Andreas Gampe67f02822016-06-24 21:05:23 -0700468class Dex2oatVeryLargeTest : public Dex2oatTest {
469 protected:
470 void CheckFilter(CompilerFilter::Filter input ATTRIBUTE_UNUSED,
471 CompilerFilter::Filter result ATTRIBUTE_UNUSED) OVERRIDE {
472 // Ignore, we'll do our own checks.
473 }
474
475 void RunTest(CompilerFilter::Filter filter,
476 bool expect_large,
477 const std::vector<std::string>& extra_args = {}) {
478 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
479 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
480
481 Copy(GetDexSrc1(), dex_location);
482
Andreas Gampeca620d72016-11-08 08:09:33 -0800483 GenerateOdexForTest(dex_location, odex_location, filter, extra_args);
Andreas Gampe67f02822016-06-24 21:05:23 -0700484
485 CheckValidity();
486 ASSERT_TRUE(success_);
487 CheckResult(dex_location, odex_location, filter, expect_large);
488 }
489
490 void CheckResult(const std::string& dex_location,
491 const std::string& odex_location,
492 CompilerFilter::Filter filter,
493 bool expect_large) {
494 // Host/target independent checks.
495 std::string error_msg;
496 std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
497 odex_location.c_str(),
498 nullptr,
499 nullptr,
500 false,
501 /*low_4gb*/false,
502 dex_location.c_str(),
503 &error_msg));
504 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
505 if (expect_large) {
506 // Note: we cannot check the following:
507 // EXPECT_TRUE(CompilerFilter::IsAsGoodAs(CompilerFilter::kVerifyAtRuntime,
508 // odex_file->GetCompilerFilter()));
509 // The reason is that the filter override currently happens when the dex files are
510 // loaded in dex2oat, which is after the oat file has been started. Thus, the header
511 // store cannot be changed, and the original filter is set in stone.
512
513 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
514 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
515 ASSERT_TRUE(dex_file != nullptr);
516 uint32_t class_def_count = dex_file->NumClassDefs();
517 ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
518 for (uint16_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
519 OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
520 EXPECT_EQ(oat_class.GetType(), OatClassType::kOatClassNoneCompiled);
521 }
522 }
523
524 // If the input filter was "below," it should have been used.
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100525 if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kExtract, filter)) {
Andreas Gampe67f02822016-06-24 21:05:23 -0700526 EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
527 }
528 } else {
529 EXPECT_EQ(odex_file->GetCompilerFilter(), filter);
530 }
531
532 // Host/target dependent checks.
533 if (kIsTargetBuild) {
534 CheckTargetResult(expect_large);
535 } else {
536 CheckHostResult(expect_large);
537 }
538 }
539
540 void CheckTargetResult(bool expect_large ATTRIBUTE_UNUSED) {
541 // TODO: Ignore for now. May do something for fd things.
542 }
543
544 void CheckHostResult(bool expect_large) {
545 if (!kIsTargetBuild) {
546 if (expect_large) {
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100547 EXPECT_NE(output_.find("Very large app, downgrading to extract."),
Andreas Gampe67f02822016-06-24 21:05:23 -0700548 std::string::npos)
549 << output_;
550 } else {
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100551 EXPECT_EQ(output_.find("Very large app, downgrading to extract."),
Andreas Gampe67f02822016-06-24 21:05:23 -0700552 std::string::npos)
553 << output_;
554 }
555 }
556 }
557
558 // Check whether the dex2oat run was really successful.
559 void CheckValidity() {
560 if (kIsTargetBuild) {
561 CheckTargetValidity();
562 } else {
563 CheckHostValidity();
564 }
565 }
566
567 void CheckTargetValidity() {
568 // TODO: Ignore for now.
569 }
570
571 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
572 void CheckHostValidity() {
573 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
574 }
575};
576
577TEST_F(Dex2oatVeryLargeTest, DontUseVeryLarge) {
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100578 RunTest(CompilerFilter::kAssumeVerified, false);
579 RunTest(CompilerFilter::kExtract, false);
580 RunTest(CompilerFilter::kQuicken, false);
Andreas Gampe67f02822016-06-24 21:05:23 -0700581 RunTest(CompilerFilter::kSpeed, false);
582
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100583 RunTest(CompilerFilter::kAssumeVerified, false, { "--very-large-app-threshold=1000000" });
584 RunTest(CompilerFilter::kExtract, false, { "--very-large-app-threshold=1000000" });
585 RunTest(CompilerFilter::kQuicken, false, { "--very-large-app-threshold=1000000" });
Andreas Gampe67f02822016-06-24 21:05:23 -0700586 RunTest(CompilerFilter::kSpeed, false, { "--very-large-app-threshold=1000000" });
587}
588
589TEST_F(Dex2oatVeryLargeTest, UseVeryLarge) {
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100590 RunTest(CompilerFilter::kAssumeVerified, false, { "--very-large-app-threshold=100" });
591 RunTest(CompilerFilter::kExtract, false, { "--very-large-app-threshold=100" });
592 RunTest(CompilerFilter::kQuicken, true, { "--very-large-app-threshold=100" });
Andreas Gampe67f02822016-06-24 21:05:23 -0700593 RunTest(CompilerFilter::kSpeed, true, { "--very-large-app-threshold=100" });
594}
595
Mathieu Chartier97ab5e32017-02-22 13:35:44 -0800596// Regressin test for b/35665292.
597TEST_F(Dex2oatVeryLargeTest, SpeedProfileNoProfile) {
598 // Test that dex2oat doesn't crash with speed-profile but no input profile.
599 RunTest(CompilerFilter::kSpeedProfile, false);
600}
601
Jeff Hao608f2ce2016-10-19 11:17:11 -0700602class Dex2oatLayoutTest : public Dex2oatTest {
603 protected:
604 void CheckFilter(CompilerFilter::Filter input ATTRIBUTE_UNUSED,
605 CompilerFilter::Filter result ATTRIBUTE_UNUSED) OVERRIDE {
606 // Ignore, we'll do our own checks.
607 }
608
Jeff Hao41fba6a2016-11-28 11:53:33 -0800609 // Emits a profile with a single dex file with the given location and a single class index of 1.
610 void GenerateProfile(const std::string& test_profile,
611 const std::string& dex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800612 size_t num_classes,
Jeff Hao41fba6a2016-11-28 11:53:33 -0800613 uint32_t checksum) {
614 int profile_test_fd = open(test_profile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
615 CHECK_GE(profile_test_fd, 0);
616
617 ProfileCompilationInfo info;
618 std::string profile_key = ProfileCompilationInfo::GetProfileDexFileKey(dex_location);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800619 for (size_t i = 0; i < num_classes; ++i) {
Mathieu Chartierea650f32017-05-24 12:04:13 -0700620 info.AddClassIndex(profile_key, checksum, dex::TypeIndex(1 + i), kMaxMethodIds);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800621 }
Jeff Hao41fba6a2016-11-28 11:53:33 -0800622 bool result = info.Save(profile_test_fd);
623 close(profile_test_fd);
624 ASSERT_TRUE(result);
625 }
626
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800627 void CompileProfileOdex(const std::string& dex_location,
628 const std::string& odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800629 const std::string& app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800630 bool use_fd,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800631 size_t num_profile_classes,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000632 const std::vector<std::string>& extra_args = {},
633 bool expect_success = true) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800634 const std::string profile_location = GetScratchDir() + "/primary.prof";
Jeff Hao41fba6a2016-11-28 11:53:33 -0800635 const char* location = dex_location.c_str();
636 std::string error_msg;
637 std::vector<std::unique_ptr<const DexFile>> dex_files;
638 ASSERT_TRUE(DexFile::Open(location, location, true, &error_msg, &dex_files));
639 EXPECT_EQ(dex_files.size(), 1U);
640 std::unique_ptr<const DexFile>& dex_file = dex_files[0];
Mathieu Chartier046854b2017-03-01 17:16:22 -0800641 GenerateProfile(profile_location,
642 dex_location,
643 num_profile_classes,
644 dex_file->GetLocationChecksum());
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800645 std::vector<std::string> copy(extra_args);
646 copy.push_back("--profile-file=" + profile_location);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800647 std::unique_ptr<File> app_image_file;
648 if (!app_image_file_name.empty()) {
649 if (use_fd) {
650 app_image_file.reset(OS::CreateEmptyFile(app_image_file_name.c_str()));
651 copy.push_back("--app-image-fd=" + std::to_string(app_image_file->Fd()));
652 } else {
653 copy.push_back("--app-image-file=" + app_image_file_name);
654 }
655 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800656 GenerateOdexForTest(dex_location,
657 odex_location,
658 CompilerFilter::kSpeedProfile,
659 copy,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000660 expect_success,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800661 use_fd);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800662 if (app_image_file != nullptr) {
663 ASSERT_EQ(app_image_file->FlushCloseOrErase(), 0) << "Could not flush and close art file";
664 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800665 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700666
Mathieu Chartier046854b2017-03-01 17:16:22 -0800667 uint64_t GetImageSize(const std::string& image_file_name) {
668 EXPECT_FALSE(image_file_name.empty());
669 std::unique_ptr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
670 CHECK(file != nullptr);
671 ImageHeader image_header;
672 const bool success = file->ReadFully(&image_header, sizeof(image_header));
673 CHECK(success);
674 CHECK(image_header.IsValid());
675 ReaderMutexLock mu(Thread::Current(), *Locks::mutator_lock_);
676 return image_header.GetImageSize();
677 }
678
679 void RunTest(bool app_image) {
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800680 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
681 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Mathieu Chartier046854b2017-03-01 17:16:22 -0800682 std::string app_image_file = app_image ? (GetOdexDir() + "/DexOdexNoOat.art"): "";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800683 Copy(GetDexSrc2(), dex_location);
684
Mathieu Chartier046854b2017-03-01 17:16:22 -0800685 uint64_t image_file_empty_profile = 0;
686 if (app_image) {
687 CompileProfileOdex(dex_location,
688 odex_location,
689 app_image_file,
690 /* use_fd */ false,
691 /* num_profile_classes */ 0);
692 CheckValidity();
693 ASSERT_TRUE(success_);
694 // Don't check the result since CheckResult relies on the class being in the profile.
695 image_file_empty_profile = GetImageSize(app_image_file);
696 EXPECT_GT(image_file_empty_profile, 0u);
697 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700698
Mathieu Chartier046854b2017-03-01 17:16:22 -0800699 // Small profile.
700 CompileProfileOdex(dex_location,
701 odex_location,
702 app_image_file,
703 /* use_fd */ false,
704 /* num_profile_classes */ 1);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700705 CheckValidity();
706 ASSERT_TRUE(success_);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800707 CheckResult(dex_location, odex_location, app_image_file);
708
709 if (app_image) {
710 // Test that the profile made a difference by adding more classes.
711 const uint64_t image_file_small_profile = GetImageSize(app_image_file);
712 CHECK_LT(image_file_empty_profile, image_file_small_profile);
713 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700714 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800715
716 void RunTestVDex() {
717 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
718 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
719 std::string vdex_location = GetOdexDir() + "/DexOdexNoOat.vdex";
Mathieu Chartier046854b2017-03-01 17:16:22 -0800720 std::string app_image_file_name = GetOdexDir() + "/DexOdexNoOat.art";
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800721 Copy(GetDexSrc2(), dex_location);
722
723 std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
724 CHECK(vdex_file1 != nullptr) << vdex_location;
725 ScratchFile vdex_file2;
726 {
727 std::string input_vdex = "--input-vdex-fd=-1";
728 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
729 CompileProfileOdex(dex_location,
730 odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800731 app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800732 /* use_fd */ true,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800733 /* num_profile_classes */ 1,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800734 { input_vdex, output_vdex });
735 EXPECT_GT(vdex_file1->GetLength(), 0u);
736 }
737 {
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000738 // Test that vdex and dexlayout fail gracefully.
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800739 std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
740 std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2.GetFd());
741 CompileProfileOdex(dex_location,
742 odex_location,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800743 app_image_file_name,
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800744 /* use_fd */ true,
Mathieu Chartier046854b2017-03-01 17:16:22 -0800745 /* num_profile_classes */ 1,
Nicolas Geoffray97fa9922017-03-09 13:13:25 +0000746 { input_vdex, output_vdex },
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100747 /* expect_success */ true);
748 EXPECT_GT(vdex_file2.GetFile()->GetLength(), 0u);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800749 }
750 ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
751 CheckValidity();
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100752 ASSERT_TRUE(success_);
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800753 }
754
Mathieu Chartier046854b2017-03-01 17:16:22 -0800755 void CheckResult(const std::string& dex_location,
756 const std::string& odex_location,
757 const std::string& app_image_file_name) {
Jeff Hao608f2ce2016-10-19 11:17:11 -0700758 // Host/target independent checks.
759 std::string error_msg;
760 std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
761 odex_location.c_str(),
762 nullptr,
763 nullptr,
764 false,
765 /*low_4gb*/false,
766 dex_location.c_str(),
767 &error_msg));
768 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
769
Jeff Hao042e8982016-10-19 11:17:11 -0700770 const char* location = dex_location.c_str();
771 std::vector<std::unique_ptr<const DexFile>> dex_files;
772 ASSERT_TRUE(DexFile::Open(location, location, true, &error_msg, &dex_files));
773 EXPECT_EQ(dex_files.size(), 1U);
774 std::unique_ptr<const DexFile>& old_dex_file = dex_files[0];
775
Jeff Hao608f2ce2016-10-19 11:17:11 -0700776 for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
Jeff Hao042e8982016-10-19 11:17:11 -0700777 std::unique_ptr<const DexFile> new_dex_file = oat_dex_file->OpenDexFile(&error_msg);
778 ASSERT_TRUE(new_dex_file != nullptr);
779 uint32_t class_def_count = new_dex_file->NumClassDefs();
Jeff Hao608f2ce2016-10-19 11:17:11 -0700780 ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
Jeff Hao042e8982016-10-19 11:17:11 -0700781 ASSERT_GE(class_def_count, 2U);
782
783 // The new layout swaps the classes at indexes 0 and 1.
784 std::string old_class0 = old_dex_file->PrettyType(old_dex_file->GetClassDef(0).class_idx_);
785 std::string old_class1 = old_dex_file->PrettyType(old_dex_file->GetClassDef(1).class_idx_);
786 std::string new_class0 = new_dex_file->PrettyType(new_dex_file->GetClassDef(0).class_idx_);
787 std::string new_class1 = new_dex_file->PrettyType(new_dex_file->GetClassDef(1).class_idx_);
788 EXPECT_EQ(old_class0, new_class1);
789 EXPECT_EQ(old_class1, new_class0);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700790 }
791
Jeff Haoc155b052017-01-17 17:43:29 -0800792 EXPECT_EQ(odex_file->GetCompilerFilter(), CompilerFilter::kSpeedProfile);
Mathieu Chartier046854b2017-03-01 17:16:22 -0800793
794 if (!app_image_file_name.empty()) {
795 // Go peek at the image header to make sure it was large enough to contain the class.
796 std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file_name.c_str()));
797 ImageHeader image_header;
798 bool success = file->ReadFully(&image_header, sizeof(image_header));
799 ASSERT_TRUE(success);
800 ASSERT_TRUE(image_header.IsValid());
801 EXPECT_GT(image_header.GetImageSection(ImageHeader::kSectionObjects).Size(), 0u);
802 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700803 }
804
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800805 // Check whether the dex2oat run was really successful.
806 void CheckValidity() {
807 if (kIsTargetBuild) {
808 CheckTargetValidity();
809 } else {
810 CheckHostValidity();
Jeff Hao608f2ce2016-10-19 11:17:11 -0700811 }
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800812 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700813
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800814 void CheckTargetValidity() {
815 // TODO: Ignore for now.
816 }
Jeff Hao608f2ce2016-10-19 11:17:11 -0700817
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800818 // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
819 void CheckHostValidity() {
820 EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
821 }
822};
Jeff Hao608f2ce2016-10-19 11:17:11 -0700823
824TEST_F(Dex2oatLayoutTest, TestLayout) {
Mathieu Chartier046854b2017-03-01 17:16:22 -0800825 RunTest(/* app-image */ false);
826}
827
828TEST_F(Dex2oatLayoutTest, TestLayoutAppImage) {
829 RunTest(/* app-image */ true);
Jeff Hao608f2ce2016-10-19 11:17:11 -0700830}
831
Mathieu Chartier8bc343b2017-03-01 15:20:30 -0800832TEST_F(Dex2oatLayoutTest, TestVdexLayout) {
833 RunTestVDex();
834}
835
Andreas Gampe2e8a2562017-01-18 20:39:02 -0800836class Dex2oatWatchdogTest : public Dex2oatTest {
837 protected:
838 void RunTest(bool expect_success, const std::vector<std::string>& extra_args = {}) {
839 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
840 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
841
842 Copy(GetTestDexFileName(), dex_location);
843
844 std::vector<std::string> copy(extra_args);
845
846 std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
847 copy.push_back("--swap-file=" + swap_location);
848 GenerateOdexForTest(dex_location,
849 odex_location,
850 CompilerFilter::kSpeed,
851 copy,
852 expect_success);
853 }
854
855 std::string GetTestDexFileName() {
856 return GetDexSrc1();
857 }
858};
859
860TEST_F(Dex2oatWatchdogTest, TestWatchdogOK) {
861 // Check with default.
862 RunTest(true);
863
864 // Check with ten minutes.
865 RunTest(true, { "--watchdog-timeout=600000" });
866}
867
868TEST_F(Dex2oatWatchdogTest, TestWatchdogTrigger) {
869 // Check with ten milliseconds.
870 RunTest(false, { "--watchdog-timeout=10" });
871}
872
Andreas Gampef7882972017-03-20 16:35:24 -0700873class Dex2oatReturnCodeTest : public Dex2oatTest {
874 protected:
875 int RunTest(const std::vector<std::string>& extra_args = {}) {
876 std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
877 std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
878
879 Copy(GetTestDexFileName(), dex_location);
880
881 std::string error_msg;
882 return GenerateOdexForTestWithStatus(dex_location,
883 odex_location,
884 CompilerFilter::kSpeed,
885 &error_msg,
886 extra_args);
887 }
888
889 std::string GetTestDexFileName() {
890 return GetDexSrc1();
891 }
892};
893
894TEST_F(Dex2oatReturnCodeTest, TestCreateRuntime) {
Andreas Gampefd80b172017-04-26 22:25:31 -0700895 TEST_DISABLED_FOR_MEMORY_TOOL(); // b/19100793
Andreas Gampef7882972017-03-20 16:35:24 -0700896 int status = RunTest({ "--boot-image=/this/does/not/exist/yolo.oat" });
897 EXPECT_EQ(static_cast<int>(dex2oat::ReturnCode::kCreateRuntime), WEXITSTATUS(status)) << output_;
898}
899
Calin Juravle1ce70852017-06-28 10:59:03 -0700900class Dex2oatClassLoaderContextTest : public Dex2oatTest {
901 protected:
902 void RunTest(const char* class_loader_context,
903 const char* expected_classpath_key,
904 bool expected_success,
905 bool use_second_source = false) {
906 std::string dex_location = GetUsedDexLocation();
907 std::string odex_location = GetUsedOatLocation();
908
909 Copy(use_second_source ? GetDexSrc2() : GetDexSrc1(), dex_location);
910
911 std::string error_msg;
912 std::vector<std::string> extra_args;
913 if (class_loader_context != nullptr) {
914 extra_args.push_back(std::string("--class-loader-context=") + class_loader_context);
915 }
916 auto check_oat = [expected_classpath_key](const OatFile& oat_file) {
917 ASSERT_TRUE(expected_classpath_key != nullptr);
918 const char* classpath = oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
919 ASSERT_TRUE(classpath != nullptr);
920 ASSERT_STREQ(expected_classpath_key, classpath);
921 };
922
923 GenerateOdexForTest(dex_location,
924 odex_location,
925 CompilerFilter::kQuicken,
926 extra_args,
927 expected_success,
928 /*use_fd*/ false,
929 check_oat);
930 }
931
932 std::string GetUsedDexLocation() {
933 return GetScratchDir() + "/Context.jar";
934 }
935
936 std::string GetUsedOatLocation() {
937 return GetOdexDir() + "/Context.odex";
938 }
939
Calin Juravle7b0648a2017-07-07 18:40:50 -0700940 const char* kEmptyClassPathKey = "PCL[]";
Calin Juravle1ce70852017-06-28 10:59:03 -0700941};
942
943TEST_F(Dex2oatClassLoaderContextTest, InvalidContext) {
944 RunTest("Invalid[]", /*expected_classpath_key*/ nullptr, /*expected_success*/ false);
945}
946
947TEST_F(Dex2oatClassLoaderContextTest, EmptyContext) {
948 RunTest("PCL[]", kEmptyClassPathKey, /*expected_success*/ true);
949}
950
951TEST_F(Dex2oatClassLoaderContextTest, SpecialContext) {
952 RunTest(OatFile::kSpecialSharedLibrary,
953 OatFile::kSpecialSharedLibrary,
954 /*expected_success*/ true);
955}
956
957TEST_F(Dex2oatClassLoaderContextTest, ContextWithTheSourceDexFiles) {
958 std::string context = "PCL[" + GetUsedDexLocation() + "]";
959 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
960}
961
962TEST_F(Dex2oatClassLoaderContextTest, ContextWithOtherDexFiles) {
963 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Nested");
Calin Juravle1ce70852017-06-28 10:59:03 -0700964
965 std::string context = "PCL[" + dex_files[0]->GetLocation() + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -0700966 std::string expected_classpath_key = "PCL[" +
967 dex_files[0]->GetLocation() + "*" + std::to_string(dex_files[0]->GetLocationChecksum()) + "]";
Calin Juravle1ce70852017-06-28 10:59:03 -0700968 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
969}
970
971TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFiles) {
972 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
973 Copy(GetStrippedDexSrc1(), stripped_classpath);
974
975 std::string context = "PCL[" + stripped_classpath + "]";
976 // Expect an empty context because stripped dex files cannot be open.
Calin Juravle7b0648a2017-07-07 18:40:50 -0700977 RunTest(context.c_str(), kEmptyClassPathKey , /*expected_success*/ true);
Calin Juravle1ce70852017-06-28 10:59:03 -0700978}
979
980TEST_F(Dex2oatClassLoaderContextTest, ContextWithStrippedDexFilesBackedByOdex) {
981 std::string stripped_classpath = GetScratchDir() + "/stripped_classpath.jar";
982 std::string odex_for_classpath = GetOdexDir() + "/stripped_classpath.odex";
983
984 Copy(GetDexSrc1(), stripped_classpath);
985
986 GenerateOdexForTest(stripped_classpath,
987 odex_for_classpath,
988 CompilerFilter::kQuicken,
989 {},
990 true);
991
992 // Strip the dex file
993 Copy(GetStrippedDexSrc1(), stripped_classpath);
994
995 std::string context = "PCL[" + stripped_classpath + "]";
Calin Juravle7b0648a2017-07-07 18:40:50 -0700996 std::string expected_classpath_key;
Calin Juravle1ce70852017-06-28 10:59:03 -0700997 {
998 // Open the oat file to get the expected classpath.
999 OatFileAssistant oat_file_assistant(stripped_classpath.c_str(), kRuntimeISA, false);
1000 std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile());
1001 std::vector<std::unique_ptr<const DexFile>> oat_dex_files =
1002 OatFileAssistant::LoadDexFiles(*oat_file, stripped_classpath.c_str());
Calin Juravle7b0648a2017-07-07 18:40:50 -07001003 expected_classpath_key = "PCL[";
1004 for (size_t i = 0; i < oat_dex_files.size(); i++) {
1005 if (i > 0) {
1006 expected_classpath_key + ":";
1007 }
1008 expected_classpath_key += oat_dex_files[i]->GetLocation() + "*" +
1009 std::to_string(oat_dex_files[i]->GetLocationChecksum());
1010 }
1011 expected_classpath_key += "]";
Calin Juravle1ce70852017-06-28 10:59:03 -07001012 }
1013
1014 RunTest(context.c_str(),
Calin Juravle7b0648a2017-07-07 18:40:50 -07001015 expected_classpath_key.c_str(),
Calin Juravle1ce70852017-06-28 10:59:03 -07001016 /*expected_success*/ true,
1017 /*use_second_source*/ true);
1018}
1019
1020TEST_F(Dex2oatClassLoaderContextTest, ContextWithNotExistentDexFiles) {
1021 std::string context = "PCL[does_not_exists.dex]";
1022 // Expect an empty context because stripped dex files cannot be open.
1023 RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1024}
1025
Calin Juravlec79470d2017-07-12 17:37:42 -07001026TEST_F(Dex2oatClassLoaderContextTest, ChainContext) {
1027 std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1028 std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1029
1030 std::string context = "PCL[" + GetTestDexFileName("Nested") + "];" +
1031 "DLC[" + GetTestDexFileName("MultiDex") + "]";
1032 std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "];" +
1033 "DLC[" + CreateClassPathWithChecksums(dex_files2) + "]";
1034
1035 RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1036}
1037
Andreas Gampee1459ae2016-06-29 09:36:30 -07001038} // namespace art