blob: 18472743fb402cabf15c577319b1530e8a08ef58 [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>
Calin Juravle821a2592017-08-11 14:33:38 -070020#include <stdlib.h>
Calin Juravle87e2cb62017-06-13 21:48:45 -070021
Andreas Gampe72527382017-09-02 16:53:03 -070022#include "android-base/strings.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070023
24#include "base/dchecked_vector.h"
25#include "base/stl_util.h"
Calin Juravle821a2592017-08-11 14:33:38 -070026#include "class_loader_context.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070027#include "class_linker.h"
Calin Juravle821a2592017-08-11 14:33:38 -070028#include "common_runtime_test.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070029#include "dex_file.h"
Calin Juravle821a2592017-08-11 14:33:38 -070030#include "dex2oat_environment_test.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070031#include "handle_scope-inl.h"
32#include "mirror/class.h"
33#include "mirror/class_loader.h"
34#include "mirror/object-inl.h"
35#include "oat_file_assistant.h"
36#include "runtime.h"
37#include "scoped_thread_state_change-inl.h"
38#include "thread.h"
39#include "well_known_classes.h"
40
41namespace art {
42
43class ClassLoaderContextTest : public CommonRuntimeTest {
44 public:
45 void VerifyContextSize(ClassLoaderContext* context, size_t expected_size) {
46 ASSERT_TRUE(context != nullptr);
47 ASSERT_EQ(expected_size, context->class_loader_chain_.size());
48 }
49
50 void VerifyClassLoaderPCL(ClassLoaderContext* context,
51 size_t index,
Calin Juravle57d0acc2017-07-11 17:41:30 -070052 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070053 VerifyClassLoaderInfo(
54 context, index, ClassLoaderContext::kPathClassLoader, classpath);
55 }
56
57 void VerifyClassLoaderDLC(ClassLoaderContext* context,
58 size_t index,
Calin Juravle57d0acc2017-07-11 17:41:30 -070059 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070060 VerifyClassLoaderInfo(
61 context, index, ClassLoaderContext::kDelegateLastClassLoader, classpath);
62 }
63
Calin Juravle57d0acc2017-07-11 17:41:30 -070064 void VerifyClassLoaderPCLFromTestDex(ClassLoaderContext* context,
65 size_t index,
66 const std::string& test_name) {
67 VerifyClassLoaderFromTestDex(
68 context, index, ClassLoaderContext::kPathClassLoader, test_name);
69 }
70
71 void VerifyClassLoaderDLCFromTestDex(ClassLoaderContext* context,
72 size_t index,
73 const std::string& test_name) {
74 VerifyClassLoaderFromTestDex(
75 context, index, ClassLoaderContext::kDelegateLastClassLoader, test_name);
76 }
77
Andreas Gampe72527382017-09-02 16:53:03 -070078 enum class LocationCheck {
79 kEquals,
80 kEndsWith
81 };
82 enum class BaseLocationCheck {
83 kEquals,
84 kEndsWith
85 };
86
Calin Juravle87e2cb62017-06-13 21:48:45 -070087 void VerifyOpenDexFiles(
88 ClassLoaderContext* context,
89 size_t index,
Andreas Gampe72527382017-09-02 16:53:03 -070090 std::vector<std::vector<std::unique_ptr<const DexFile>>*>& all_dex_files,
91 LocationCheck mode = LocationCheck::kEquals,
92 BaseLocationCheck base_mode = BaseLocationCheck::kEquals) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070093 ASSERT_TRUE(context != nullptr);
94 ASSERT_TRUE(context->dex_files_open_attempted_);
95 ASSERT_TRUE(context->dex_files_open_result_);
96 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
97 ASSERT_EQ(all_dex_files.size(), info.classpath.size());
98 size_t cur_open_dex_index = 0;
99 for (size_t k = 0; k < all_dex_files.size(); k++) {
100 std::vector<std::unique_ptr<const DexFile>>& dex_files_for_cp_elem = *(all_dex_files[k]);
101 for (size_t i = 0; i < dex_files_for_cp_elem.size(); i++) {
102 ASSERT_LT(cur_open_dex_index, info.opened_dex_files.size());
103
104 std::unique_ptr<const DexFile>& opened_dex_file =
105 info.opened_dex_files[cur_open_dex_index++];
106 std::unique_ptr<const DexFile>& expected_dex_file = dex_files_for_cp_elem[i];
107
Calin Juravle821a2592017-08-11 14:33:38 -0700108 std::string expected_location = expected_dex_file->GetBaseLocation();
109 UniqueCPtr<const char[]> expected_real_location(
110 realpath(expected_location.c_str(), nullptr));
111 ASSERT_TRUE(expected_real_location != nullptr) << expected_location;
112 expected_location.assign(expected_real_location.get());
113 expected_location += DexFile::GetMultiDexSuffix(expected_dex_file->GetLocation());
114
Andreas Gampe72527382017-09-02 16:53:03 -0700115 switch (mode) {
116 case LocationCheck::kEquals:
117 ASSERT_EQ(expected_dex_file->GetLocation(), opened_dex_file->GetLocation());
118 break;
119 case LocationCheck::kEndsWith:
120 ASSERT_TRUE(android::base::EndsWith(expected_dex_file->GetLocation(),
121 opened_dex_file->GetLocation().c_str()))
122 << opened_dex_file->GetLocation() << " vs " << expected_dex_file->GetLocation();
123 break;
124 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700125 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
Calin Juravle821a2592017-08-11 14:33:38 -0700126
127 std::string class_path_location = info.classpath[k];
128 UniqueCPtr<const char[]> class_path_location_real(
129 realpath(class_path_location.c_str(), nullptr));
130 ASSERT_TRUE(class_path_location_real != nullptr);
131 class_path_location.assign(class_path_location_real.get());
Andreas Gampe72527382017-09-02 16:53:03 -0700132 switch (base_mode) {
133 case BaseLocationCheck::kEquals:
134 ASSERT_EQ(class_path_location, opened_dex_file->GetBaseLocation());
135 break;
136
137 case BaseLocationCheck::kEndsWith:
138 ASSERT_TRUE(android::base::EndsWith(opened_dex_file->GetBaseLocation(),
139 class_path_location.c_str()))
140 << info.classpath[k] << " vs " << opened_dex_file->GetBaseLocation();
141 break;
142 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700143 }
144 }
145 }
146
Calin Juravle57d0acc2017-07-11 17:41:30 -0700147 std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) {
148 return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
149 }
150
Calin Juravle3f918642017-07-11 19:04:20 -0700151 std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) {
152 std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext());
153 if (!context->Parse(context_spec, /*parse_checksums*/ true)) {
154 return nullptr;
155 }
156 return context;
157 }
158
Calin Juravle57d0acc2017-07-11 17:41:30 -0700159 void VerifyContextForClassLoader(ClassLoaderContext* context) {
160 ASSERT_TRUE(context != nullptr);
161 ASSERT_TRUE(context->dex_files_open_attempted_);
162 ASSERT_TRUE(context->dex_files_open_result_);
163 ASSERT_FALSE(context->owns_the_dex_files_);
164 ASSERT_FALSE(context->special_shared_library_);
165 }
166
Calin Juravlec79470d2017-07-12 17:37:42 -0700167 void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
168 Handle<mirror::ClassLoader> class_loader,
169 jclass type,
170 std::vector<const DexFile*>& expected_dex_files)
171 REQUIRES_SHARED(Locks::mutator_lock_) {
172 ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type));
173
174 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader);
175 ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size());
176
177 for (size_t i = 0; i < expected_dex_files.size(); i++) {
178 ASSERT_EQ(expected_dex_files[i]->GetLocation(),
179 class_loader_dex_files[i]->GetLocation());
180 ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(),
181 class_loader_dex_files[i]->GetLocationChecksum());
182 }
183 }
184
Calin Juravle87e2cb62017-06-13 21:48:45 -0700185 private:
186 void VerifyClassLoaderInfo(ClassLoaderContext* context,
187 size_t index,
188 ClassLoaderContext::ClassLoaderType type,
Calin Juravle57d0acc2017-07-11 17:41:30 -0700189 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700190 ASSERT_TRUE(context != nullptr);
191 ASSERT_GT(context->class_loader_chain_.size(), index);
192 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
193 ASSERT_EQ(type, info.type);
194 std::vector<std::string> expected_classpath;
195 Split(classpath, ':', &expected_classpath);
196 ASSERT_EQ(expected_classpath, info.classpath);
197 }
Calin Juravle57d0acc2017-07-11 17:41:30 -0700198
199 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
200 size_t index,
201 ClassLoaderContext::ClassLoaderType type,
202 const std::string& test_name) {
203 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
204 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files;
205 all_dex_files.push_back(&dex_files);
206
207 VerifyClassLoaderInfo(context, index, type, GetTestDexFileName(test_name.c_str()));
208 VerifyOpenDexFiles(context, index, all_dex_files);
209 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700210};
211
Calin Juravle1a509c82017-07-24 16:51:21 -0700212TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
213 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
214 // An empty context should create a single empty PathClassLoader.
215 VerifyContextSize(context.get(), 1);
216 VerifyClassLoaderPCL(context.get(), 0, "");
217}
218
219TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
220 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
221 // An shared library context should have no class loader in the chain.
222 VerifyContextSize(context.get(), 0);
223}
224
Calin Juravle87e2cb62017-06-13 21:48:45 -0700225TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
226 std::unique_ptr<ClassLoaderContext> context =
227 ClassLoaderContext::Create("PCL[a.dex]");
228 VerifyContextSize(context.get(), 1);
229 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
230}
231
232TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
233 std::unique_ptr<ClassLoaderContext> context =
234 ClassLoaderContext::Create("DLC[a.dex]");
235 VerifyContextSize(context.get(), 1);
236 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
237}
238
239TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
240 std::unique_ptr<ClassLoaderContext> context =
241 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
242 VerifyContextSize(context.get(), 3);
243 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
244 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
245 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
246}
247
248TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
249 std::unique_ptr<ClassLoaderContext> context =
250 ClassLoaderContext::Create("DLC[]");
251 VerifyContextSize(context.get(), 1);
252 VerifyClassLoaderDLC(context.get(), 0, "");
253}
254
255TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
256 std::unique_ptr<ClassLoaderContext> context =
257 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
258 VerifyContextSize(context.get(), 0);
259}
260
261TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
262 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
263 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
264 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
265 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
266 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
267 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
268}
269
270TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
271 std::unique_ptr<ClassLoaderContext> context =
272 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
273 VerifyContextSize(context.get(), 1);
274 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
275}
276
277TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
278 std::string multidex_name = GetTestDexFileName("MultiDex");
279 std::vector<std::unique_ptr<const DexFile>> multidex_files = OpenTestDexFiles("MultiDex");
280 std::string myclass_dex_name = GetTestDexFileName("MyClass");
281 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
282 std::string dex_name = GetTestDexFileName("Main");
283 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Main");
284
Calin Juravle87e2cb62017-06-13 21:48:45 -0700285 std::unique_ptr<ClassLoaderContext> context =
286 ClassLoaderContext::Create(
287 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
288 "DLC[" + dex_name + "]");
289
290 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
291
292 VerifyContextSize(context.get(), 2);
293 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
294 all_dex_files0.push_back(&multidex_files);
295 all_dex_files0.push_back(&myclass_dex_files);
296 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files1;
297 all_dex_files1.push_back(&dex_files);
298
299 VerifyOpenDexFiles(context.get(), 0, all_dex_files0);
300 VerifyOpenDexFiles(context.get(), 1, all_dex_files1);
301}
302
Calin Juravle821a2592017-08-11 14:33:38 -0700303class ScratchSymLink {
304 public:
305 explicit ScratchSymLink(const std::string& file) {
306 // Use a temporary scratch file to get a unique name for the link.
307 ScratchFile scratchFile;
308 scratch_link_name_ = scratchFile.GetFilename() + ".link.jar";
309 CHECK_EQ(0, symlink(file.c_str(), scratch_link_name_.c_str()));
310 }
311
312 ~ScratchSymLink() {
313 CHECK_EQ(0, unlink(scratch_link_name_.c_str()));
314 }
315
316 const std::string& GetFilename() { return scratch_link_name_; }
317
318 private:
319 std::string scratch_link_name_;
320};
321
322TEST_F(ClassLoaderContextTest, OpenValidDexFilesSymLink) {
323 std::string myclass_dex_name = GetTestDexFileName("MyClass");
324 // Now replace the dex location with a symlink.
325 ScratchSymLink link(myclass_dex_name);
326
327 std::unique_ptr<ClassLoaderContext> context =
328 ClassLoaderContext::Create("PCL[" + link.GetFilename() + "]");
329
330 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
331
332 VerifyContextSize(context.get(), 1);
333 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
334 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
335 all_dex_files0.push_back(&myclass_dex_files);
336
337 VerifyOpenDexFiles(context.get(), 0, all_dex_files0);
338}
339
Andreas Gampe72527382017-09-02 16:53:03 -0700340static std::string CreateRelativeString(const std::string& in, const char* cwd) {
Nicolas Geoffrayc4be2c82017-09-05 12:40:06 +0100341 int cwd_len = strlen(cwd);
342 if (!android::base::StartsWith(in, cwd) || (cwd_len < 1)) {
Andreas Gampe72527382017-09-02 16:53:03 -0700343 LOG(FATAL) << in << " " << cwd;
344 }
Nicolas Geoffrayc4be2c82017-09-05 12:40:06 +0100345 bool contains_trailing_slash = (cwd[cwd_len - 1] == '/');
346 int start_position = cwd_len + (contains_trailing_slash ? 0 : 1);
347 return in.substr(start_position);
Andreas Gampe72527382017-09-02 16:53:03 -0700348}
349
350TEST_F(ClassLoaderContextTest, OpenValidDexFilesRelative) {
351 char cwd_buf[4096];
352 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
353 PLOG(FATAL) << "Could not get working directory";
354 }
355 std::string multidex_name = CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf);
356 std::vector<std::unique_ptr<const DexFile>> multidex_files = OpenTestDexFiles("MultiDex");
357 std::string myclass_dex_name = CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf);
358 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
359 std::string dex_name = CreateRelativeString(GetTestDexFileName("Main"), cwd_buf);
360 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Main");
361
362
363 std::unique_ptr<ClassLoaderContext> context =
364 ClassLoaderContext::Create(
365 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
366 "DLC[" + dex_name + "]");
367
368 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
369
370 VerifyContextSize(context.get(), 2);
371 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
372 all_dex_files0.push_back(&multidex_files);
373 all_dex_files0.push_back(&myclass_dex_files);
374 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files1;
375 all_dex_files1.push_back(&dex_files);
376
377 VerifyOpenDexFiles(context.get(), 0, all_dex_files0, LocationCheck::kEndsWith);
378 VerifyOpenDexFiles(context.get(), 1, all_dex_files1, LocationCheck::kEndsWith);
379}
380
381TEST_F(ClassLoaderContextTest, OpenValidDexFilesClasspathDir) {
382 char cwd_buf[4096];
383 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
384 PLOG(FATAL) << "Could not get working directory";
385 }
386 std::string multidex_name = CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf);
387 std::vector<std::unique_ptr<const DexFile>> multidex_files = OpenTestDexFiles("MultiDex");
388 std::string myclass_dex_name = CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf);
389 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
390 std::string dex_name = CreateRelativeString(GetTestDexFileName("Main"), cwd_buf);
391 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Main");
392
393
394 std::unique_ptr<ClassLoaderContext> context =
395 ClassLoaderContext::Create(
396 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
397 "DLC[" + dex_name + "]");
398
399 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, cwd_buf));
400
401 VerifyContextSize(context.get(), 2);
402 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
403 all_dex_files0.push_back(&multidex_files);
404 all_dex_files0.push_back(&myclass_dex_files);
405 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files1;
406 all_dex_files1.push_back(&dex_files);
407
408 VerifyOpenDexFiles(
409 context.get(), 0, all_dex_files0, LocationCheck::kEquals, BaseLocationCheck::kEndsWith);
410 VerifyOpenDexFiles(
411 context.get(), 1, all_dex_files1, LocationCheck::kEquals, BaseLocationCheck::kEndsWith);
412}
413
Calin Juravle87e2cb62017-06-13 21:48:45 -0700414TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
415 std::string dex_name = GetTestDexFileName("Main");
416 std::unique_ptr<ClassLoaderContext> context =
417 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
418 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
419}
420
421TEST_F(ClassLoaderContextTest, CreateClassLoader) {
422 std::string dex_name = GetTestDexFileName("Main");
423 std::unique_ptr<ClassLoaderContext> context =
424 ClassLoaderContext::Create("PCL[" + dex_name + "]");
425 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
426
427 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
428 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
429
430 std::vector<const DexFile*> compilation_sources_raw =
431 MakeNonOwningPointerVector(compilation_sources);
432 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
433 ASSERT_TRUE(jclass_loader != nullptr);
434
435 ScopedObjectAccess soa(Thread::Current());
436
Calin Juravlec79470d2017-07-12 17:37:42 -0700437 StackHandleScope<1> hs(soa.Self());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700438 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
439 soa.Decode<mirror::ClassLoader>(jclass_loader));
440
441 ASSERT_TRUE(class_loader->GetClass() ==
442 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
443 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
444 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
445
Calin Juravlec79470d2017-07-12 17:37:42 -0700446 // For the first class loader the class path dex files must come first and then the
447 // compilation sources.
448 std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex);
449 for (auto& dex : compilation_sources_raw) {
450 expected_classpath.push_back(dex);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700451 }
452
Calin Juravlec79470d2017-07-12 17:37:42 -0700453 VerifyClassLoaderDexFiles(soa,
454 class_loader,
455 WellKnownClasses::dalvik_system_PathClassLoader,
456 expected_classpath);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700457}
458
Calin Juravle7b0648a2017-07-07 18:40:50 -0700459TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
460 std::unique_ptr<ClassLoaderContext> context =
461 ClassLoaderContext::Create("");
462 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
463
464 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
465
466 std::vector<const DexFile*> compilation_sources_raw =
467 MakeNonOwningPointerVector(compilation_sources);
468 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
469 ASSERT_TRUE(jclass_loader != nullptr);
470
471 ScopedObjectAccess soa(Thread::Current());
472
Calin Juravlec79470d2017-07-12 17:37:42 -0700473 StackHandleScope<1> hs(soa.Self());
Calin Juravle7b0648a2017-07-07 18:40:50 -0700474 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
475 soa.Decode<mirror::ClassLoader>(jclass_loader));
476
Calin Juravlec79470d2017-07-12 17:37:42 -0700477 // An empty context should create a single PathClassLoader with only the compilation sources.
478 VerifyClassLoaderDexFiles(soa,
479 class_loader,
480 WellKnownClasses::dalvik_system_PathClassLoader,
481 compilation_sources_raw);
Calin Juravle7b0648a2017-07-07 18:40:50 -0700482 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
483 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
Calin Juravle7b0648a2017-07-07 18:40:50 -0700484}
485
Calin Juravle1a509c82017-07-24 16:51:21 -0700486TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
487 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
488
489 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
490
491 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
492
493 std::vector<const DexFile*> compilation_sources_raw =
494 MakeNonOwningPointerVector(compilation_sources);
495 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
496 ASSERT_TRUE(jclass_loader != nullptr);
497
498 ScopedObjectAccess soa(Thread::Current());
499
500 StackHandleScope<1> hs(soa.Self());
501 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
502 soa.Decode<mirror::ClassLoader>(jclass_loader));
503
504 // A shared library context should create a single PathClassLoader with only the compilation
505 // sources.
506 VerifyClassLoaderDexFiles(soa,
507 class_loader,
508 WellKnownClasses::dalvik_system_PathClassLoader,
509 compilation_sources_raw);
510 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
511 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
512}
513
Calin Juravlec79470d2017-07-12 17:37:42 -0700514TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
515 // Setup the context.
516 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
517 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
518 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
519 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
520
521 std::string context_spec =
522 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" +
523 "DLC[" + CreateClassPath(classpath_dex_c) + "];" +
524 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
525
526 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
527 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
528
529 // Setup the compilation sources.
530 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
531 std::vector<const DexFile*> compilation_sources_raw =
532 MakeNonOwningPointerVector(compilation_sources);
533
534 // Create the class loader.
535 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
536 ASSERT_TRUE(jclass_loader != nullptr);
537
538 // Verify the class loader.
539 ScopedObjectAccess soa(Thread::Current());
540
541 StackHandleScope<3> hs(soa.Self());
542 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
543 soa.Decode<mirror::ClassLoader>(jclass_loader));
544
545 // Verify the first class loader
546
547 // For the first class loader the class path dex files must come first and then the
548 // compilation sources.
549 std::vector<const DexFile*> class_loader_1_dex_files =
550 MakeNonOwningPointerVector(classpath_dex_a);
551 for (auto& dex : classpath_dex_b) {
552 class_loader_1_dex_files.push_back(dex.get());
553 }
554 for (auto& dex : compilation_sources_raw) {
555 class_loader_1_dex_files.push_back(dex);
556 }
557 VerifyClassLoaderDexFiles(soa,
558 class_loader_1,
559 WellKnownClasses::dalvik_system_PathClassLoader,
560 class_loader_1_dex_files);
561
562 // Verify the second class loader
563 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent());
564 std::vector<const DexFile*> class_loader_2_dex_files =
565 MakeNonOwningPointerVector(classpath_dex_c);
566 VerifyClassLoaderDexFiles(soa,
567 class_loader_2,
568 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
569 class_loader_2_dex_files);
570
571 // Verify the third class loader
572 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent());
573 std::vector<const DexFile*> class_loader_3_dex_files =
574 MakeNonOwningPointerVector(classpath_dex_d);
575 VerifyClassLoaderDexFiles(soa,
576 class_loader_3,
577 WellKnownClasses::dalvik_system_PathClassLoader,
578 class_loader_3_dex_files);
579 // The last class loader should have the BootClassLoader as a parent.
580 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
581 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
582}
583
584
Calin Juravle87e2cb62017-06-13 21:48:45 -0700585TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
586 std::unique_ptr<ClassLoaderContext> context =
587 ClassLoaderContext::Create("PCL[a.dex]");
588 dchecked_vector<std::string> classpath_dex;
589 classpath_dex.push_back("a.dex");
590 dchecked_vector<std::string> compilation_sources;
591 compilation_sources.push_back("src.dex");
592
593 // Nothing should be removed.
594 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
595 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
596 // Classes should be removed.
597 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
598 VerifyClassLoaderPCL(context.get(), 0, "");
599}
600
601TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
602 std::string dex1_name = GetTestDexFileName("Main");
603 std::string dex2_name = GetTestDexFileName("MyClass");
604 std::unique_ptr<ClassLoaderContext> context =
605 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
606 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
607
608 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
609 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
610 std::string encoding = context->EncodeContextForOatFile("");
Calin Juravlec79470d2017-07-12 17:37:42 -0700611 std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" +
612 CreateClassPathWithChecksums(dex2) + "]";
Calin Juravle87e2cb62017-06-13 21:48:45 -0700613 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
614}
615
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700616TEST_F(ClassLoaderContextTest, EncodeForDex2oat) {
617 std::string dex1_name = GetTestDexFileName("Main");
618 std::string dex2_name = GetTestDexFileName("MultiDex");
619 std::unique_ptr<ClassLoaderContext> context =
620 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
621 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
622
623 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
624 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MultiDex");
625 std::string encoding = context->EncodeContextForDex2oat("");
626 std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]";
627 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
628}
629
Calin Juravle57d0acc2017-07-11 17:41:30 -0700630// TODO(calin) add a test which creates the context for a class loader together with dex_elements.
631TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
632 // The chain is
633 // ClassLoaderA (PathClassLoader)
634 // ^
635 // |
636 // ClassLoaderB (DelegateLastClassLoader)
637 // ^
638 // |
639 // ClassLoaderC (PathClassLoader)
640 // ^
641 // |
642 // ClassLoaderD (DelegateLastClassLoader)
643
644 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
645 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
646 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
647 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
648
649 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
650
651 VerifyContextForClassLoader(context.get());
652 VerifyContextSize(context.get(), 4);
653
654 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
655 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
656 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
657 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
658}
659
Calin Juravle3f918642017-07-11 19:04:20 -0700660TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
661 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
662 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
663
664 VerifyContextSize(context.get(), 2);
665 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
666 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
667
668 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_spec));
669
670 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
671 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_type));
672
673 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
674 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_order));
675
676 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
677 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_classpath_order));
678
679 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
680 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_checksum));
681
682 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
683 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader));
684
685 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
686 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_classpath));
687
688 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
689 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_spec));
690}
691
692TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
693 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
694 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
695 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
696 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
697
698 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
699
Calin Juravle1e96a5d2017-09-05 17:10:48 -0700700 std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
701 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_no_base_dir));
702
703 std::string dex_location = GetTestDexFileName("ForClassLoaderA");
704 size_t pos = dex_location.rfind('/');
705 ASSERT_NE(std::string::npos, pos);
706 std::string parent = dex_location.substr(0, pos);
707
708 std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
709 ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
710 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_base_dir));
Calin Juravle3f918642017-07-11 19:04:20 -0700711}
712
Calin Juravlea308a322017-07-18 16:51:51 -0700713TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) {
714 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
715
716 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
717
718 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
719}
720
Calin Juravle87e2cb62017-06-13 21:48:45 -0700721} // namespace art