blob: 4689ae4c3f884abd011141e1d0130a574623f8e9 [file] [log] [blame]
Calin Juravle87e2cb62017-06-13 21:48:45 -07001/*
2 * Copyright (C) 2017 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 Gampe72527382017-09-02 16:53:03 -070017#include "class_loader_context.h"
18
Calin Juravle87e2cb62017-06-13 21:48:45 -070019#include <gtest/gtest.h>
20
Andreas Gampe72527382017-09-02 16:53:03 -070021#include "android-base/strings.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070022#include "base/dchecked_vector.h"
23#include "base/stl_util.h"
24#include "class_linker.h"
Calin Juravle821a2592017-08-11 14:33:38 -070025#include "common_runtime_test.h"
David Sehr9e734c72018-01-04 17:56:19 -080026#include "dex/dex_file.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070027#include "handle_scope-inl.h"
28#include "mirror/class.h"
29#include "mirror/class_loader.h"
30#include "mirror/object-inl.h"
31#include "oat_file_assistant.h"
32#include "runtime.h"
33#include "scoped_thread_state_change-inl.h"
34#include "thread.h"
35#include "well_known_classes.h"
36
37namespace art {
38
39class ClassLoaderContextTest : public CommonRuntimeTest {
40 public:
41 void VerifyContextSize(ClassLoaderContext* context, size_t expected_size) {
42 ASSERT_TRUE(context != nullptr);
43 ASSERT_EQ(expected_size, context->class_loader_chain_.size());
44 }
45
46 void VerifyClassLoaderPCL(ClassLoaderContext* context,
47 size_t index,
Calin Juravle57d0acc2017-07-11 17:41:30 -070048 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070049 VerifyClassLoaderInfo(
50 context, index, ClassLoaderContext::kPathClassLoader, classpath);
51 }
52
53 void VerifyClassLoaderDLC(ClassLoaderContext* context,
54 size_t index,
Calin Juravle57d0acc2017-07-11 17:41:30 -070055 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070056 VerifyClassLoaderInfo(
57 context, index, ClassLoaderContext::kDelegateLastClassLoader, classpath);
58 }
59
Calin Juravle57d0acc2017-07-11 17:41:30 -070060 void VerifyClassLoaderPCLFromTestDex(ClassLoaderContext* context,
61 size_t index,
62 const std::string& test_name) {
63 VerifyClassLoaderFromTestDex(
64 context, index, ClassLoaderContext::kPathClassLoader, test_name);
65 }
66
67 void VerifyClassLoaderDLCFromTestDex(ClassLoaderContext* context,
68 size_t index,
69 const std::string& test_name) {
70 VerifyClassLoaderFromTestDex(
71 context, index, ClassLoaderContext::kDelegateLastClassLoader, test_name);
72 }
73
Andreas Gampe72527382017-09-02 16:53:03 -070074 enum class LocationCheck {
75 kEquals,
76 kEndsWith
77 };
78 enum class BaseLocationCheck {
79 kEquals,
80 kEndsWith
81 };
82
Calin Juravle92003fe2017-09-06 02:22:57 +000083 static bool IsAbsoluteLocation(const std::string& location) {
84 return !location.empty() && location[0] == '/';
85 }
86
Calin Juravle87e2cb62017-06-13 21:48:45 -070087 void VerifyOpenDexFiles(
88 ClassLoaderContext* context,
89 size_t index,
Calin Juravlec5b215f2017-09-12 14:49:37 -070090 std::vector<std::unique_ptr<const DexFile>>* all_dex_files) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070091 ASSERT_TRUE(context != nullptr);
92 ASSERT_TRUE(context->dex_files_open_attempted_);
93 ASSERT_TRUE(context->dex_files_open_result_);
94 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
Calin Juravlec5b215f2017-09-12 14:49:37 -070095 ASSERT_EQ(all_dex_files->size(), info.classpath.size());
96 ASSERT_EQ(all_dex_files->size(), info.opened_dex_files.size());
Calin Juravle87e2cb62017-06-13 21:48:45 -070097 size_t cur_open_dex_index = 0;
Calin Juravlec5b215f2017-09-12 14:49:37 -070098 for (size_t k = 0; k < all_dex_files->size(); k++) {
99 std::unique_ptr<const DexFile>& opened_dex_file =
Calin Juravle87e2cb62017-06-13 21:48:45 -0700100 info.opened_dex_files[cur_open_dex_index++];
Calin Juravlec5b215f2017-09-12 14:49:37 -0700101 std::unique_ptr<const DexFile>& expected_dex_file = (*all_dex_files)[k];
Calin Juravle87e2cb62017-06-13 21:48:45 -0700102
Calin Juravle92003fe2017-09-06 02:22:57 +0000103 std::string expected_location = expected_dex_file->GetLocation();
Calin Juravle821a2592017-08-11 14:33:38 -0700104
Calin Juravle92003fe2017-09-06 02:22:57 +0000105 const std::string& opened_location = opened_dex_file->GetLocation();
106 if (!IsAbsoluteLocation(opened_location)) {
107 // If the opened location is relative (it was open from a relative path without a
108 // classpath_dir) it might not match the expected location which is absolute in tests).
109 // So we compare the endings (the checksum will validate it's actually the same file).
110 ASSERT_EQ(0, expected_location.compare(
111 expected_location.length() - opened_location.length(),
112 opened_location.length(),
113 opened_location));
114 } else {
115 ASSERT_EQ(expected_location, opened_location);
116 }
Calin Juravlec5b215f2017-09-12 14:49:37 -0700117 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
Calin Juravle92003fe2017-09-06 02:22:57 +0000118 ASSERT_EQ(info.classpath[k], opened_location);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700119 }
120 }
121
Calin Juravle57d0acc2017-07-11 17:41:30 -0700122 std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) {
123 return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
124 }
125
Calin Juravle3f918642017-07-11 19:04:20 -0700126 std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) {
127 std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext());
128 if (!context->Parse(context_spec, /*parse_checksums*/ true)) {
129 return nullptr;
130 }
131 return context;
132 }
133
Calin Juravle57d0acc2017-07-11 17:41:30 -0700134 void VerifyContextForClassLoader(ClassLoaderContext* context) {
135 ASSERT_TRUE(context != nullptr);
136 ASSERT_TRUE(context->dex_files_open_attempted_);
137 ASSERT_TRUE(context->dex_files_open_result_);
138 ASSERT_FALSE(context->owns_the_dex_files_);
139 ASSERT_FALSE(context->special_shared_library_);
140 }
141
Calin Juravlec79470d2017-07-12 17:37:42 -0700142 void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
143 Handle<mirror::ClassLoader> class_loader,
144 jclass type,
145 std::vector<const DexFile*>& expected_dex_files)
146 REQUIRES_SHARED(Locks::mutator_lock_) {
147 ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type));
148
149 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader);
150 ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size());
151
152 for (size_t i = 0; i < expected_dex_files.size(); i++) {
153 ASSERT_EQ(expected_dex_files[i]->GetLocation(),
154 class_loader_dex_files[i]->GetLocation());
155 ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(),
156 class_loader_dex_files[i]->GetLocationChecksum());
157 }
158 }
159
Calin Juravlec5b215f2017-09-12 14:49:37 -0700160 void PretendContextOpenedDexFiles(ClassLoaderContext* context) {
161 context->dex_files_open_attempted_ = true;
162 context->dex_files_open_result_ = true;
163 }
164
Calin Juravle87e2cb62017-06-13 21:48:45 -0700165 private:
166 void VerifyClassLoaderInfo(ClassLoaderContext* context,
167 size_t index,
168 ClassLoaderContext::ClassLoaderType type,
Calin Juravle57d0acc2017-07-11 17:41:30 -0700169 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700170 ASSERT_TRUE(context != nullptr);
171 ASSERT_GT(context->class_loader_chain_.size(), index);
172 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
173 ASSERT_EQ(type, info.type);
174 std::vector<std::string> expected_classpath;
175 Split(classpath, ':', &expected_classpath);
176 ASSERT_EQ(expected_classpath, info.classpath);
177 }
Calin Juravle57d0acc2017-07-11 17:41:30 -0700178
179 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
180 size_t index,
181 ClassLoaderContext::ClassLoaderType type,
182 const std::string& test_name) {
183 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
Calin Juravle57d0acc2017-07-11 17:41:30 -0700184
185 VerifyClassLoaderInfo(context, index, type, GetTestDexFileName(test_name.c_str()));
Calin Juravlec5b215f2017-09-12 14:49:37 -0700186 VerifyOpenDexFiles(context, index, &dex_files);
Calin Juravle57d0acc2017-07-11 17:41:30 -0700187 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700188};
189
Calin Juravle1a509c82017-07-24 16:51:21 -0700190TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
191 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
192 // An empty context should create a single empty PathClassLoader.
193 VerifyContextSize(context.get(), 1);
194 VerifyClassLoaderPCL(context.get(), 0, "");
195}
196
197TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
198 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
199 // An shared library context should have no class loader in the chain.
200 VerifyContextSize(context.get(), 0);
201}
202
Calin Juravle87e2cb62017-06-13 21:48:45 -0700203TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
204 std::unique_ptr<ClassLoaderContext> context =
205 ClassLoaderContext::Create("PCL[a.dex]");
206 VerifyContextSize(context.get(), 1);
207 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
208}
209
210TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
211 std::unique_ptr<ClassLoaderContext> context =
212 ClassLoaderContext::Create("DLC[a.dex]");
213 VerifyContextSize(context.get(), 1);
214 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
215}
216
217TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
218 std::unique_ptr<ClassLoaderContext> context =
219 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
220 VerifyContextSize(context.get(), 3);
221 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
222 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
223 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
224}
225
226TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
227 std::unique_ptr<ClassLoaderContext> context =
228 ClassLoaderContext::Create("DLC[]");
229 VerifyContextSize(context.get(), 1);
230 VerifyClassLoaderDLC(context.get(), 0, "");
231}
232
233TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
234 std::unique_ptr<ClassLoaderContext> context =
235 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
236 VerifyContextSize(context.get(), 0);
237}
238
239TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
240 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
241 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
242 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
243 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
244 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
245 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
246}
247
248TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
249 std::unique_ptr<ClassLoaderContext> context =
250 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
251 VerifyContextSize(context.get(), 1);
252 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
253}
254
255TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
256 std::string multidex_name = GetTestDexFileName("MultiDex");
Calin Juravle87e2cb62017-06-13 21:48:45 -0700257 std::string myclass_dex_name = GetTestDexFileName("MyClass");
Calin Juravle87e2cb62017-06-13 21:48:45 -0700258 std::string dex_name = GetTestDexFileName("Main");
Calin Juravle87e2cb62017-06-13 21:48:45 -0700259
Calin Juravle92003fe2017-09-06 02:22:57 +0000260
Calin Juravle87e2cb62017-06-13 21:48:45 -0700261 std::unique_ptr<ClassLoaderContext> context =
262 ClassLoaderContext::Create(
263 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
264 "DLC[" + dex_name + "]");
265
266 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
267
268 VerifyContextSize(context.get(), 2);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700269
Calin Juravlec5b215f2017-09-12 14:49:37 -0700270 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
271 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
272 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
273 all_dex_files0.emplace_back(myclass_dex_files[i].release());
274 }
275 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
276
277 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
278 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700279}
280
Alex Light77ef93b2018-01-12 11:18:31 -0800281// Creates a relative path from cwd to 'in'. Returns false if it cannot be done.
282// TODO We should somehow support this in all situations. b/72042237.
283static bool CreateRelativeString(const std::string& in, const char* cwd, std::string* out) {
Nicolas Geoffrayc4be2c82017-09-05 12:40:06 +0100284 int cwd_len = strlen(cwd);
285 if (!android::base::StartsWith(in, cwd) || (cwd_len < 1)) {
Alex Light77ef93b2018-01-12 11:18:31 -0800286 return false;
Andreas Gampe72527382017-09-02 16:53:03 -0700287 }
Nicolas Geoffrayc4be2c82017-09-05 12:40:06 +0100288 bool contains_trailing_slash = (cwd[cwd_len - 1] == '/');
289 int start_position = cwd_len + (contains_trailing_slash ? 0 : 1);
Alex Light77ef93b2018-01-12 11:18:31 -0800290 *out = in.substr(start_position);
291 return true;
Andreas Gampe72527382017-09-02 16:53:03 -0700292}
293
294TEST_F(ClassLoaderContextTest, OpenValidDexFilesRelative) {
295 char cwd_buf[4096];
296 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
297 PLOG(FATAL) << "Could not get working directory";
298 }
Alex Light77ef93b2018-01-12 11:18:31 -0800299 std::string multidex_name;
300 std::string myclass_dex_name;
301 std::string dex_name;
302 if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) ||
303 !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) ||
304 !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) {
305 LOG(ERROR) << "Test OpenValidDexFilesRelative cannot be run because target dex files have no "
306 << "relative path.";
307 SUCCEED();
308 return;
309 }
Andreas Gampe72527382017-09-02 16:53:03 -0700310
311
312 std::unique_ptr<ClassLoaderContext> context =
313 ClassLoaderContext::Create(
314 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
315 "DLC[" + dex_name + "]");
316
317 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
318
Calin Juravlec5b215f2017-09-12 14:49:37 -0700319 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
320 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
321 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
322 all_dex_files0.emplace_back(myclass_dex_files[i].release());
323 }
324 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
Andreas Gampe72527382017-09-02 16:53:03 -0700325
Calin Juravlec5b215f2017-09-12 14:49:37 -0700326 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
327 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
Andreas Gampe72527382017-09-02 16:53:03 -0700328}
329
330TEST_F(ClassLoaderContextTest, OpenValidDexFilesClasspathDir) {
331 char cwd_buf[4096];
332 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
333 PLOG(FATAL) << "Could not get working directory";
334 }
Alex Light77ef93b2018-01-12 11:18:31 -0800335 std::string multidex_name;
336 std::string myclass_dex_name;
337 std::string dex_name;
338 if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) ||
339 !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) ||
340 !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) {
341 LOG(ERROR) << "Test OpenValidDexFilesClasspathDir cannot be run because target dex files have "
342 << "no relative path.";
343 SUCCEED();
344 return;
345 }
Andreas Gampe72527382017-09-02 16:53:03 -0700346 std::unique_ptr<ClassLoaderContext> context =
347 ClassLoaderContext::Create(
348 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
349 "DLC[" + dex_name + "]");
350
351 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, cwd_buf));
352
353 VerifyContextSize(context.get(), 2);
Calin Juravlec5b215f2017-09-12 14:49:37 -0700354 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
355 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
356 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
357 all_dex_files0.emplace_back(myclass_dex_files[i].release());
358 }
359 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
Andreas Gampe72527382017-09-02 16:53:03 -0700360
Calin Juravlec5b215f2017-09-12 14:49:37 -0700361 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
362 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
Andreas Gampe72527382017-09-02 16:53:03 -0700363}
364
Calin Juravle87e2cb62017-06-13 21:48:45 -0700365TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
366 std::string dex_name = GetTestDexFileName("Main");
367 std::unique_ptr<ClassLoaderContext> context =
368 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
369 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
370}
371
372TEST_F(ClassLoaderContextTest, CreateClassLoader) {
373 std::string dex_name = GetTestDexFileName("Main");
374 std::unique_ptr<ClassLoaderContext> context =
375 ClassLoaderContext::Create("PCL[" + dex_name + "]");
376 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
377
378 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
379 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
380
381 std::vector<const DexFile*> compilation_sources_raw =
382 MakeNonOwningPointerVector(compilation_sources);
383 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
384 ASSERT_TRUE(jclass_loader != nullptr);
385
386 ScopedObjectAccess soa(Thread::Current());
387
Calin Juravlec79470d2017-07-12 17:37:42 -0700388 StackHandleScope<1> hs(soa.Self());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700389 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
390 soa.Decode<mirror::ClassLoader>(jclass_loader));
391
392 ASSERT_TRUE(class_loader->GetClass() ==
393 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
394 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
395 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
396
Calin Juravlec79470d2017-07-12 17:37:42 -0700397 // For the first class loader the class path dex files must come first and then the
398 // compilation sources.
399 std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex);
400 for (auto& dex : compilation_sources_raw) {
401 expected_classpath.push_back(dex);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700402 }
403
Calin Juravlec79470d2017-07-12 17:37:42 -0700404 VerifyClassLoaderDexFiles(soa,
405 class_loader,
406 WellKnownClasses::dalvik_system_PathClassLoader,
407 expected_classpath);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700408}
409
Calin Juravle7b0648a2017-07-07 18:40:50 -0700410TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
411 std::unique_ptr<ClassLoaderContext> context =
412 ClassLoaderContext::Create("");
413 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
414
415 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
416
417 std::vector<const DexFile*> compilation_sources_raw =
418 MakeNonOwningPointerVector(compilation_sources);
419 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
420 ASSERT_TRUE(jclass_loader != nullptr);
421
422 ScopedObjectAccess soa(Thread::Current());
423
Calin Juravlec79470d2017-07-12 17:37:42 -0700424 StackHandleScope<1> hs(soa.Self());
Calin Juravle7b0648a2017-07-07 18:40:50 -0700425 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
426 soa.Decode<mirror::ClassLoader>(jclass_loader));
427
Calin Juravlec79470d2017-07-12 17:37:42 -0700428 // An empty context should create a single PathClassLoader with only the compilation sources.
429 VerifyClassLoaderDexFiles(soa,
430 class_loader,
431 WellKnownClasses::dalvik_system_PathClassLoader,
432 compilation_sources_raw);
Calin Juravle7b0648a2017-07-07 18:40:50 -0700433 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
434 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
Calin Juravle7b0648a2017-07-07 18:40:50 -0700435}
436
Calin Juravle1a509c82017-07-24 16:51:21 -0700437TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
438 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
439
440 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
441
442 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
443
444 std::vector<const DexFile*> compilation_sources_raw =
445 MakeNonOwningPointerVector(compilation_sources);
446 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
447 ASSERT_TRUE(jclass_loader != nullptr);
448
449 ScopedObjectAccess soa(Thread::Current());
450
451 StackHandleScope<1> hs(soa.Self());
452 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
453 soa.Decode<mirror::ClassLoader>(jclass_loader));
454
455 // A shared library context should create a single PathClassLoader with only the compilation
456 // sources.
457 VerifyClassLoaderDexFiles(soa,
458 class_loader,
459 WellKnownClasses::dalvik_system_PathClassLoader,
460 compilation_sources_raw);
461 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
462 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
463}
464
Calin Juravlec79470d2017-07-12 17:37:42 -0700465TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
466 // Setup the context.
467 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
468 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
469 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
470 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
471
472 std::string context_spec =
473 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" +
474 "DLC[" + CreateClassPath(classpath_dex_c) + "];" +
475 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
476
477 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
478 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
479
480 // Setup the compilation sources.
481 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
482 std::vector<const DexFile*> compilation_sources_raw =
483 MakeNonOwningPointerVector(compilation_sources);
484
485 // Create the class loader.
486 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
487 ASSERT_TRUE(jclass_loader != nullptr);
488
489 // Verify the class loader.
490 ScopedObjectAccess soa(Thread::Current());
491
492 StackHandleScope<3> hs(soa.Self());
493 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
494 soa.Decode<mirror::ClassLoader>(jclass_loader));
495
496 // Verify the first class loader
497
498 // For the first class loader the class path dex files must come first and then the
499 // compilation sources.
500 std::vector<const DexFile*> class_loader_1_dex_files =
501 MakeNonOwningPointerVector(classpath_dex_a);
502 for (auto& dex : classpath_dex_b) {
503 class_loader_1_dex_files.push_back(dex.get());
504 }
505 for (auto& dex : compilation_sources_raw) {
506 class_loader_1_dex_files.push_back(dex);
507 }
508 VerifyClassLoaderDexFiles(soa,
509 class_loader_1,
510 WellKnownClasses::dalvik_system_PathClassLoader,
511 class_loader_1_dex_files);
512
513 // Verify the second class loader
514 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent());
515 std::vector<const DexFile*> class_loader_2_dex_files =
516 MakeNonOwningPointerVector(classpath_dex_c);
517 VerifyClassLoaderDexFiles(soa,
518 class_loader_2,
519 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
520 class_loader_2_dex_files);
521
522 // Verify the third class loader
523 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent());
524 std::vector<const DexFile*> class_loader_3_dex_files =
525 MakeNonOwningPointerVector(classpath_dex_d);
526 VerifyClassLoaderDexFiles(soa,
527 class_loader_3,
528 WellKnownClasses::dalvik_system_PathClassLoader,
529 class_loader_3_dex_files);
530 // The last class loader should have the BootClassLoader as a parent.
531 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
532 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
533}
534
535
Calin Juravle87e2cb62017-06-13 21:48:45 -0700536TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
537 std::unique_ptr<ClassLoaderContext> context =
538 ClassLoaderContext::Create("PCL[a.dex]");
539 dchecked_vector<std::string> classpath_dex;
540 classpath_dex.push_back("a.dex");
541 dchecked_vector<std::string> compilation_sources;
542 compilation_sources.push_back("src.dex");
543
544 // Nothing should be removed.
545 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
546 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
547 // Classes should be removed.
548 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
549 VerifyClassLoaderPCL(context.get(), 0, "");
550}
551
552TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
553 std::string dex1_name = GetTestDexFileName("Main");
554 std::string dex2_name = GetTestDexFileName("MyClass");
555 std::unique_ptr<ClassLoaderContext> context =
556 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
557 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
558
559 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
560 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
561 std::string encoding = context->EncodeContextForOatFile("");
Calin Juravlec79470d2017-07-12 17:37:42 -0700562 std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" +
563 CreateClassPathWithChecksums(dex2) + "]";
Calin Juravle87e2cb62017-06-13 21:48:45 -0700564 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
565}
566
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700567TEST_F(ClassLoaderContextTest, EncodeForDex2oat) {
568 std::string dex1_name = GetTestDexFileName("Main");
569 std::string dex2_name = GetTestDexFileName("MultiDex");
570 std::unique_ptr<ClassLoaderContext> context =
571 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
572 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
573
574 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
575 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MultiDex");
576 std::string encoding = context->EncodeContextForDex2oat("");
577 std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]";
578 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
579}
580
Calin Juravle57d0acc2017-07-11 17:41:30 -0700581// TODO(calin) add a test which creates the context for a class loader together with dex_elements.
582TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
583 // The chain is
584 // ClassLoaderA (PathClassLoader)
585 // ^
586 // |
587 // ClassLoaderB (DelegateLastClassLoader)
588 // ^
589 // |
590 // ClassLoaderC (PathClassLoader)
591 // ^
592 // |
593 // ClassLoaderD (DelegateLastClassLoader)
594
595 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
596 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
597 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
598 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
599
600 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
601
602 VerifyContextForClassLoader(context.get());
603 VerifyContextSize(context.get(), 4);
604
605 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
606 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
607 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
608 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
609}
610
Calin Juravle3f918642017-07-11 19:04:20 -0700611TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
612 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
613 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
Calin Juravlec5b215f2017-09-12 14:49:37 -0700614 // Pretend that we successfully open the dex files to pass the DCHECKS.
615 // (as it's much easier to test all the corner cases without relying on actual dex files).
616 PretendContextOpenedDexFiles(context.get());
Calin Juravle3f918642017-07-11 19:04:20 -0700617
618 VerifyContextSize(context.get(), 2);
619 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
620 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
621
622 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_spec));
623
624 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
625 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_type));
626
627 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
628 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_order));
629
630 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
631 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_classpath_order));
632
633 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
634 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_checksum));
635
636 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
637 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader));
638
639 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
640 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_classpath));
641
642 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
643 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_spec));
644}
645
646TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
647 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
648 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
649 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
650 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
651
652 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
653
Calin Juravle1e96a5d2017-09-05 17:10:48 -0700654 std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
655 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_no_base_dir));
656
657 std::string dex_location = GetTestDexFileName("ForClassLoaderA");
658 size_t pos = dex_location.rfind('/');
659 ASSERT_NE(std::string::npos, pos);
660 std::string parent = dex_location.substr(0, pos);
661
662 std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
663 ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
664 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_base_dir));
Calin Juravle3f918642017-07-11 19:04:20 -0700665}
666
Calin Juravlea308a322017-07-18 16:51:51 -0700667TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) {
668 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
669
670 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
671
672 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
673}
674
Calin Juravle87e2cb62017-06-13 21:48:45 -0700675} // namespace art