blob: ae3dcecb4a210905b4f18e735c67fe6261f1162d [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,
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 Juravlec5b215f2017-09-12 14:49:37 -0700103 std::string expected_location = expected_dex_file->GetBaseLocation();
104 UniqueCPtr<const char[]> expected_real_location(
105 realpath(expected_location.c_str(), nullptr));
106 ASSERT_TRUE(expected_real_location != nullptr) << expected_location;
107 expected_location.assign(expected_real_location.get());
108 expected_location += DexFile::GetMultiDexSuffix(expected_dex_file->GetLocation());
Calin Juravle821a2592017-08-11 14:33:38 -0700109
Calin Juravlec5b215f2017-09-12 14:49:37 -0700110 ASSERT_EQ(expected_location, opened_dex_file->GetLocation());
111 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
112 ASSERT_EQ(info.classpath[k], opened_dex_file->GetLocation());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700113 }
114 }
115
Calin Juravle57d0acc2017-07-11 17:41:30 -0700116 std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) {
117 return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
118 }
119
Calin Juravle3f918642017-07-11 19:04:20 -0700120 std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) {
121 std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext());
122 if (!context->Parse(context_spec, /*parse_checksums*/ true)) {
123 return nullptr;
124 }
125 return context;
126 }
127
Calin Juravle57d0acc2017-07-11 17:41:30 -0700128 void VerifyContextForClassLoader(ClassLoaderContext* context) {
129 ASSERT_TRUE(context != nullptr);
130 ASSERT_TRUE(context->dex_files_open_attempted_);
131 ASSERT_TRUE(context->dex_files_open_result_);
132 ASSERT_FALSE(context->owns_the_dex_files_);
133 ASSERT_FALSE(context->special_shared_library_);
134 }
135
Calin Juravlec79470d2017-07-12 17:37:42 -0700136 void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
137 Handle<mirror::ClassLoader> class_loader,
138 jclass type,
139 std::vector<const DexFile*>& expected_dex_files)
140 REQUIRES_SHARED(Locks::mutator_lock_) {
141 ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type));
142
143 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader);
144 ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size());
145
146 for (size_t i = 0; i < expected_dex_files.size(); i++) {
147 ASSERT_EQ(expected_dex_files[i]->GetLocation(),
148 class_loader_dex_files[i]->GetLocation());
149 ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(),
150 class_loader_dex_files[i]->GetLocationChecksum());
151 }
152 }
153
Calin Juravlec5b215f2017-09-12 14:49:37 -0700154 void PretendContextOpenedDexFiles(ClassLoaderContext* context) {
155 context->dex_files_open_attempted_ = true;
156 context->dex_files_open_result_ = true;
157 }
158
Calin Juravle87e2cb62017-06-13 21:48:45 -0700159 private:
160 void VerifyClassLoaderInfo(ClassLoaderContext* context,
161 size_t index,
162 ClassLoaderContext::ClassLoaderType type,
Calin Juravle57d0acc2017-07-11 17:41:30 -0700163 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700164 ASSERT_TRUE(context != nullptr);
165 ASSERT_GT(context->class_loader_chain_.size(), index);
166 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
167 ASSERT_EQ(type, info.type);
168 std::vector<std::string> expected_classpath;
169 Split(classpath, ':', &expected_classpath);
170 ASSERT_EQ(expected_classpath, info.classpath);
171 }
Calin Juravle57d0acc2017-07-11 17:41:30 -0700172
173 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
174 size_t index,
175 ClassLoaderContext::ClassLoaderType type,
176 const std::string& test_name) {
177 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
Calin Juravle57d0acc2017-07-11 17:41:30 -0700178
179 VerifyClassLoaderInfo(context, index, type, GetTestDexFileName(test_name.c_str()));
Calin Juravlec5b215f2017-09-12 14:49:37 -0700180 VerifyOpenDexFiles(context, index, &dex_files);
Calin Juravle57d0acc2017-07-11 17:41:30 -0700181 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700182};
183
Calin Juravle1a509c82017-07-24 16:51:21 -0700184TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
185 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
186 // An empty context should create a single empty PathClassLoader.
187 VerifyContextSize(context.get(), 1);
188 VerifyClassLoaderPCL(context.get(), 0, "");
189}
190
191TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
192 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
193 // An shared library context should have no class loader in the chain.
194 VerifyContextSize(context.get(), 0);
195}
196
Calin Juravle87e2cb62017-06-13 21:48:45 -0700197TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
198 std::unique_ptr<ClassLoaderContext> context =
199 ClassLoaderContext::Create("PCL[a.dex]");
200 VerifyContextSize(context.get(), 1);
201 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
202}
203
204TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
205 std::unique_ptr<ClassLoaderContext> context =
206 ClassLoaderContext::Create("DLC[a.dex]");
207 VerifyContextSize(context.get(), 1);
208 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
209}
210
211TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
212 std::unique_ptr<ClassLoaderContext> context =
213 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
214 VerifyContextSize(context.get(), 3);
215 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
216 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
217 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
218}
219
220TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
221 std::unique_ptr<ClassLoaderContext> context =
222 ClassLoaderContext::Create("DLC[]");
223 VerifyContextSize(context.get(), 1);
224 VerifyClassLoaderDLC(context.get(), 0, "");
225}
226
227TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
228 std::unique_ptr<ClassLoaderContext> context =
229 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
230 VerifyContextSize(context.get(), 0);
231}
232
233TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
234 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
235 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
236 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
237 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
238 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
239 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
240}
241
242TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
243 std::unique_ptr<ClassLoaderContext> context =
244 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
245 VerifyContextSize(context.get(), 1);
246 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
247}
248
249TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
250 std::string multidex_name = GetTestDexFileName("MultiDex");
Calin Juravle87e2cb62017-06-13 21:48:45 -0700251 std::string myclass_dex_name = GetTestDexFileName("MyClass");
Calin Juravle87e2cb62017-06-13 21:48:45 -0700252 std::string dex_name = GetTestDexFileName("Main");
Calin Juravle87e2cb62017-06-13 21:48:45 -0700253
Calin Juravle87e2cb62017-06-13 21:48:45 -0700254 std::unique_ptr<ClassLoaderContext> context =
255 ClassLoaderContext::Create(
256 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
257 "DLC[" + dex_name + "]");
258
259 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
260
261 VerifyContextSize(context.get(), 2);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700262
Calin Juravlec5b215f2017-09-12 14:49:37 -0700263 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
264 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
265 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
266 all_dex_files0.emplace_back(myclass_dex_files[i].release());
267 }
268 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
269
270 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
271 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700272}
273
Calin Juravle821a2592017-08-11 14:33:38 -0700274class ScratchSymLink {
275 public:
276 explicit ScratchSymLink(const std::string& file) {
277 // Use a temporary scratch file to get a unique name for the link.
278 ScratchFile scratchFile;
279 scratch_link_name_ = scratchFile.GetFilename() + ".link.jar";
280 CHECK_EQ(0, symlink(file.c_str(), scratch_link_name_.c_str()));
281 }
282
283 ~ScratchSymLink() {
284 CHECK_EQ(0, unlink(scratch_link_name_.c_str()));
285 }
286
287 const std::string& GetFilename() { return scratch_link_name_; }
288
289 private:
290 std::string scratch_link_name_;
291};
292
293TEST_F(ClassLoaderContextTest, OpenValidDexFilesSymLink) {
294 std::string myclass_dex_name = GetTestDexFileName("MyClass");
295 // Now replace the dex location with a symlink.
296 ScratchSymLink link(myclass_dex_name);
297
298 std::unique_ptr<ClassLoaderContext> context =
299 ClassLoaderContext::Create("PCL[" + link.GetFilename() + "]");
300
301 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
302
303 VerifyContextSize(context.get(), 1);
Calin Juravle821a2592017-08-11 14:33:38 -0700304
Calin Juravlec5b215f2017-09-12 14:49:37 -0700305 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
306
307 VerifyOpenDexFiles(context.get(), 0, &myclass_dex_files);
Calin Juravle821a2592017-08-11 14:33:38 -0700308}
309
Andreas Gampe72527382017-09-02 16:53:03 -0700310static std::string CreateRelativeString(const std::string& in, const char* cwd) {
Nicolas Geoffrayc4be2c82017-09-05 12:40:06 +0100311 int cwd_len = strlen(cwd);
312 if (!android::base::StartsWith(in, cwd) || (cwd_len < 1)) {
Andreas Gampe72527382017-09-02 16:53:03 -0700313 LOG(FATAL) << in << " " << cwd;
314 }
Nicolas Geoffrayc4be2c82017-09-05 12:40:06 +0100315 bool contains_trailing_slash = (cwd[cwd_len - 1] == '/');
316 int start_position = cwd_len + (contains_trailing_slash ? 0 : 1);
317 return in.substr(start_position);
Andreas Gampe72527382017-09-02 16:53:03 -0700318}
319
320TEST_F(ClassLoaderContextTest, OpenValidDexFilesRelative) {
321 char cwd_buf[4096];
322 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
323 PLOG(FATAL) << "Could not get working directory";
324 }
325 std::string multidex_name = CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700326 std::string myclass_dex_name = CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700327 std::string dex_name = CreateRelativeString(GetTestDexFileName("Main"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700328
329
330 std::unique_ptr<ClassLoaderContext> context =
331 ClassLoaderContext::Create(
332 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
333 "DLC[" + dex_name + "]");
334
335 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
336
Calin Juravlec5b215f2017-09-12 14:49:37 -0700337 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
338 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
339 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
340 all_dex_files0.emplace_back(myclass_dex_files[i].release());
341 }
342 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
Andreas Gampe72527382017-09-02 16:53:03 -0700343
Calin Juravlec5b215f2017-09-12 14:49:37 -0700344 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
345 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
Andreas Gampe72527382017-09-02 16:53:03 -0700346}
347
348TEST_F(ClassLoaderContextTest, OpenValidDexFilesClasspathDir) {
349 char cwd_buf[4096];
350 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
351 PLOG(FATAL) << "Could not get working directory";
352 }
353 std::string multidex_name = CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700354 std::string myclass_dex_name = CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700355 std::string dex_name = CreateRelativeString(GetTestDexFileName("Main"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700356
357 std::unique_ptr<ClassLoaderContext> context =
358 ClassLoaderContext::Create(
359 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
360 "DLC[" + dex_name + "]");
361
362 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, cwd_buf));
363
364 VerifyContextSize(context.get(), 2);
Calin Juravlec5b215f2017-09-12 14:49:37 -0700365 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
366 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
367 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
368 all_dex_files0.emplace_back(myclass_dex_files[i].release());
369 }
370 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
Andreas Gampe72527382017-09-02 16:53:03 -0700371
Calin Juravlec5b215f2017-09-12 14:49:37 -0700372 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
373 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
Andreas Gampe72527382017-09-02 16:53:03 -0700374}
375
Calin Juravle87e2cb62017-06-13 21:48:45 -0700376TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
377 std::string dex_name = GetTestDexFileName("Main");
378 std::unique_ptr<ClassLoaderContext> context =
379 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
380 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
381}
382
383TEST_F(ClassLoaderContextTest, CreateClassLoader) {
384 std::string dex_name = GetTestDexFileName("Main");
385 std::unique_ptr<ClassLoaderContext> context =
386 ClassLoaderContext::Create("PCL[" + dex_name + "]");
387 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
388
389 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
390 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
391
392 std::vector<const DexFile*> compilation_sources_raw =
393 MakeNonOwningPointerVector(compilation_sources);
394 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
395 ASSERT_TRUE(jclass_loader != nullptr);
396
397 ScopedObjectAccess soa(Thread::Current());
398
Calin Juravlec79470d2017-07-12 17:37:42 -0700399 StackHandleScope<1> hs(soa.Self());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700400 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
401 soa.Decode<mirror::ClassLoader>(jclass_loader));
402
403 ASSERT_TRUE(class_loader->GetClass() ==
404 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
405 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
406 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
407
Calin Juravlec79470d2017-07-12 17:37:42 -0700408 // For the first class loader the class path dex files must come first and then the
409 // compilation sources.
410 std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex);
411 for (auto& dex : compilation_sources_raw) {
412 expected_classpath.push_back(dex);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700413 }
414
Calin Juravlec79470d2017-07-12 17:37:42 -0700415 VerifyClassLoaderDexFiles(soa,
416 class_loader,
417 WellKnownClasses::dalvik_system_PathClassLoader,
418 expected_classpath);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700419}
420
Calin Juravle7b0648a2017-07-07 18:40:50 -0700421TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
422 std::unique_ptr<ClassLoaderContext> context =
423 ClassLoaderContext::Create("");
424 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
425
426 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
427
428 std::vector<const DexFile*> compilation_sources_raw =
429 MakeNonOwningPointerVector(compilation_sources);
430 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
431 ASSERT_TRUE(jclass_loader != nullptr);
432
433 ScopedObjectAccess soa(Thread::Current());
434
Calin Juravlec79470d2017-07-12 17:37:42 -0700435 StackHandleScope<1> hs(soa.Self());
Calin Juravle7b0648a2017-07-07 18:40:50 -0700436 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
437 soa.Decode<mirror::ClassLoader>(jclass_loader));
438
Calin Juravlec79470d2017-07-12 17:37:42 -0700439 // An empty context should create a single PathClassLoader with only the compilation sources.
440 VerifyClassLoaderDexFiles(soa,
441 class_loader,
442 WellKnownClasses::dalvik_system_PathClassLoader,
443 compilation_sources_raw);
Calin Juravle7b0648a2017-07-07 18:40:50 -0700444 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
445 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
Calin Juravle7b0648a2017-07-07 18:40:50 -0700446}
447
Calin Juravle1a509c82017-07-24 16:51:21 -0700448TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
449 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
450
451 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
452
453 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
454
455 std::vector<const DexFile*> compilation_sources_raw =
456 MakeNonOwningPointerVector(compilation_sources);
457 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
458 ASSERT_TRUE(jclass_loader != nullptr);
459
460 ScopedObjectAccess soa(Thread::Current());
461
462 StackHandleScope<1> hs(soa.Self());
463 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
464 soa.Decode<mirror::ClassLoader>(jclass_loader));
465
466 // A shared library context should create a single PathClassLoader with only the compilation
467 // sources.
468 VerifyClassLoaderDexFiles(soa,
469 class_loader,
470 WellKnownClasses::dalvik_system_PathClassLoader,
471 compilation_sources_raw);
472 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
473 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
474}
475
Calin Juravlec79470d2017-07-12 17:37:42 -0700476TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
477 // Setup the context.
478 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
479 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
480 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
481 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
482
483 std::string context_spec =
484 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" +
485 "DLC[" + CreateClassPath(classpath_dex_c) + "];" +
486 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
487
488 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
489 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
490
491 // Setup the compilation sources.
492 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
493 std::vector<const DexFile*> compilation_sources_raw =
494 MakeNonOwningPointerVector(compilation_sources);
495
496 // Create the class loader.
497 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
498 ASSERT_TRUE(jclass_loader != nullptr);
499
500 // Verify the class loader.
501 ScopedObjectAccess soa(Thread::Current());
502
503 StackHandleScope<3> hs(soa.Self());
504 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
505 soa.Decode<mirror::ClassLoader>(jclass_loader));
506
507 // Verify the first class loader
508
509 // For the first class loader the class path dex files must come first and then the
510 // compilation sources.
511 std::vector<const DexFile*> class_loader_1_dex_files =
512 MakeNonOwningPointerVector(classpath_dex_a);
513 for (auto& dex : classpath_dex_b) {
514 class_loader_1_dex_files.push_back(dex.get());
515 }
516 for (auto& dex : compilation_sources_raw) {
517 class_loader_1_dex_files.push_back(dex);
518 }
519 VerifyClassLoaderDexFiles(soa,
520 class_loader_1,
521 WellKnownClasses::dalvik_system_PathClassLoader,
522 class_loader_1_dex_files);
523
524 // Verify the second class loader
525 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent());
526 std::vector<const DexFile*> class_loader_2_dex_files =
527 MakeNonOwningPointerVector(classpath_dex_c);
528 VerifyClassLoaderDexFiles(soa,
529 class_loader_2,
530 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
531 class_loader_2_dex_files);
532
533 // Verify the third class loader
534 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent());
535 std::vector<const DexFile*> class_loader_3_dex_files =
536 MakeNonOwningPointerVector(classpath_dex_d);
537 VerifyClassLoaderDexFiles(soa,
538 class_loader_3,
539 WellKnownClasses::dalvik_system_PathClassLoader,
540 class_loader_3_dex_files);
541 // The last class loader should have the BootClassLoader as a parent.
542 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
543 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
544}
545
546
Calin Juravle87e2cb62017-06-13 21:48:45 -0700547TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
548 std::unique_ptr<ClassLoaderContext> context =
549 ClassLoaderContext::Create("PCL[a.dex]");
550 dchecked_vector<std::string> classpath_dex;
551 classpath_dex.push_back("a.dex");
552 dchecked_vector<std::string> compilation_sources;
553 compilation_sources.push_back("src.dex");
554
555 // Nothing should be removed.
556 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
557 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
558 // Classes should be removed.
559 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
560 VerifyClassLoaderPCL(context.get(), 0, "");
561}
562
563TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
564 std::string dex1_name = GetTestDexFileName("Main");
565 std::string dex2_name = GetTestDexFileName("MyClass");
566 std::unique_ptr<ClassLoaderContext> context =
567 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
568 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
569
570 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
571 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
572 std::string encoding = context->EncodeContextForOatFile("");
Calin Juravlec79470d2017-07-12 17:37:42 -0700573 std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" +
574 CreateClassPathWithChecksums(dex2) + "]";
Calin Juravle87e2cb62017-06-13 21:48:45 -0700575 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
576}
577
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700578TEST_F(ClassLoaderContextTest, EncodeForDex2oat) {
579 std::string dex1_name = GetTestDexFileName("Main");
580 std::string dex2_name = GetTestDexFileName("MultiDex");
581 std::unique_ptr<ClassLoaderContext> context =
582 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
583 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
584
585 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
586 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MultiDex");
587 std::string encoding = context->EncodeContextForDex2oat("");
588 std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]";
589 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
590}
591
Calin Juravle57d0acc2017-07-11 17:41:30 -0700592// TODO(calin) add a test which creates the context for a class loader together with dex_elements.
593TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
594 // The chain is
595 // ClassLoaderA (PathClassLoader)
596 // ^
597 // |
598 // ClassLoaderB (DelegateLastClassLoader)
599 // ^
600 // |
601 // ClassLoaderC (PathClassLoader)
602 // ^
603 // |
604 // ClassLoaderD (DelegateLastClassLoader)
605
606 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
607 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
608 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
609 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
610
611 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
612
613 VerifyContextForClassLoader(context.get());
614 VerifyContextSize(context.get(), 4);
615
616 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
617 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
618 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
619 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
620}
621
Calin Juravle3f918642017-07-11 19:04:20 -0700622TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
623 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
624 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
Calin Juravlec5b215f2017-09-12 14:49:37 -0700625 // Pretend that we successfully open the dex files to pass the DCHECKS.
626 // (as it's much easier to test all the corner cases without relying on actual dex files).
627 PretendContextOpenedDexFiles(context.get());
Calin Juravle3f918642017-07-11 19:04:20 -0700628
629 VerifyContextSize(context.get(), 2);
630 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
631 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
632
633 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_spec));
634
635 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
636 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_type));
637
638 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
639 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_order));
640
641 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
642 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_classpath_order));
643
644 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
645 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_checksum));
646
647 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
648 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader));
649
650 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
651 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_classpath));
652
653 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
654 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_spec));
655}
656
657TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
658 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
659 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
660 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
661 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
662
663 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
664
Calin Juravle1e96a5d2017-09-05 17:10:48 -0700665 std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
666 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_no_base_dir));
667
668 std::string dex_location = GetTestDexFileName("ForClassLoaderA");
669 size_t pos = dex_location.rfind('/');
670 ASSERT_NE(std::string::npos, pos);
671 std::string parent = dex_location.substr(0, pos);
672
673 std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
674 ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
675 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_base_dir));
Calin Juravle3f918642017-07-11 19:04:20 -0700676}
677
Calin Juravlea308a322017-07-18 16:51:51 -0700678TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) {
679 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
680
681 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
682
683 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
684}
685
Calin Juravle87e2cb62017-06-13 21:48:45 -0700686} // namespace art