blob: be6acde4a9ffbbfff7e519f8f416093420a52426 [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
Mathieu Chartier79c87da2017-10-10 11:54:29 -0700103 std::string expected_location =
104 DexFileLoader::GetBaseLocation(expected_dex_file->GetLocation());
Calin Juravlec5b215f2017-09-12 14:49:37 -0700105 UniqueCPtr<const char[]> expected_real_location(
106 realpath(expected_location.c_str(), nullptr));
107 ASSERT_TRUE(expected_real_location != nullptr) << expected_location;
108 expected_location.assign(expected_real_location.get());
Mathieu Chartier79c87da2017-10-10 11:54:29 -0700109 expected_location += DexFileLoader::GetMultiDexSuffix(expected_dex_file->GetLocation());
Calin Juravle821a2592017-08-11 14:33:38 -0700110
Calin Juravlec5b215f2017-09-12 14:49:37 -0700111 ASSERT_EQ(expected_location, opened_dex_file->GetLocation());
112 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
113 ASSERT_EQ(info.classpath[k], opened_dex_file->GetLocation());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700114 }
115 }
116
Calin Juravle57d0acc2017-07-11 17:41:30 -0700117 std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) {
118 return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
119 }
120
Calin Juravle3f918642017-07-11 19:04:20 -0700121 std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) {
122 std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext());
123 if (!context->Parse(context_spec, /*parse_checksums*/ true)) {
124 return nullptr;
125 }
126 return context;
127 }
128
Calin Juravle57d0acc2017-07-11 17:41:30 -0700129 void VerifyContextForClassLoader(ClassLoaderContext* context) {
130 ASSERT_TRUE(context != nullptr);
131 ASSERT_TRUE(context->dex_files_open_attempted_);
132 ASSERT_TRUE(context->dex_files_open_result_);
133 ASSERT_FALSE(context->owns_the_dex_files_);
134 ASSERT_FALSE(context->special_shared_library_);
135 }
136
Calin Juravlec79470d2017-07-12 17:37:42 -0700137 void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
138 Handle<mirror::ClassLoader> class_loader,
139 jclass type,
140 std::vector<const DexFile*>& expected_dex_files)
141 REQUIRES_SHARED(Locks::mutator_lock_) {
142 ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type));
143
144 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader);
145 ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size());
146
147 for (size_t i = 0; i < expected_dex_files.size(); i++) {
148 ASSERT_EQ(expected_dex_files[i]->GetLocation(),
149 class_loader_dex_files[i]->GetLocation());
150 ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(),
151 class_loader_dex_files[i]->GetLocationChecksum());
152 }
153 }
154
Calin Juravlec5b215f2017-09-12 14:49:37 -0700155 void PretendContextOpenedDexFiles(ClassLoaderContext* context) {
156 context->dex_files_open_attempted_ = true;
157 context->dex_files_open_result_ = true;
158 }
159
Calin Juravle87e2cb62017-06-13 21:48:45 -0700160 private:
161 void VerifyClassLoaderInfo(ClassLoaderContext* context,
162 size_t index,
163 ClassLoaderContext::ClassLoaderType type,
Calin Juravle57d0acc2017-07-11 17:41:30 -0700164 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700165 ASSERT_TRUE(context != nullptr);
166 ASSERT_GT(context->class_loader_chain_.size(), index);
167 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
168 ASSERT_EQ(type, info.type);
169 std::vector<std::string> expected_classpath;
170 Split(classpath, ':', &expected_classpath);
171 ASSERT_EQ(expected_classpath, info.classpath);
172 }
Calin Juravle57d0acc2017-07-11 17:41:30 -0700173
174 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
175 size_t index,
176 ClassLoaderContext::ClassLoaderType type,
177 const std::string& test_name) {
178 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
Calin Juravle57d0acc2017-07-11 17:41:30 -0700179
180 VerifyClassLoaderInfo(context, index, type, GetTestDexFileName(test_name.c_str()));
Calin Juravlec5b215f2017-09-12 14:49:37 -0700181 VerifyOpenDexFiles(context, index, &dex_files);
Calin Juravle57d0acc2017-07-11 17:41:30 -0700182 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700183};
184
Calin Juravle1a509c82017-07-24 16:51:21 -0700185TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
186 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
187 // An empty context should create a single empty PathClassLoader.
188 VerifyContextSize(context.get(), 1);
189 VerifyClassLoaderPCL(context.get(), 0, "");
190}
191
192TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
193 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
194 // An shared library context should have no class loader in the chain.
195 VerifyContextSize(context.get(), 0);
196}
197
Calin Juravle87e2cb62017-06-13 21:48:45 -0700198TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
199 std::unique_ptr<ClassLoaderContext> context =
200 ClassLoaderContext::Create("PCL[a.dex]");
201 VerifyContextSize(context.get(), 1);
202 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
203}
204
205TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
206 std::unique_ptr<ClassLoaderContext> context =
207 ClassLoaderContext::Create("DLC[a.dex]");
208 VerifyContextSize(context.get(), 1);
209 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
210}
211
212TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
213 std::unique_ptr<ClassLoaderContext> context =
214 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
215 VerifyContextSize(context.get(), 3);
216 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
217 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
218 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
219}
220
221TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
222 std::unique_ptr<ClassLoaderContext> context =
223 ClassLoaderContext::Create("DLC[]");
224 VerifyContextSize(context.get(), 1);
225 VerifyClassLoaderDLC(context.get(), 0, "");
226}
227
228TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
229 std::unique_ptr<ClassLoaderContext> context =
230 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
231 VerifyContextSize(context.get(), 0);
232}
233
234TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
235 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
236 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
237 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
238 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
239 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
240 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
241}
242
243TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
244 std::unique_ptr<ClassLoaderContext> context =
245 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
246 VerifyContextSize(context.get(), 1);
247 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
248}
249
250TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
251 std::string multidex_name = GetTestDexFileName("MultiDex");
Calin Juravle87e2cb62017-06-13 21:48:45 -0700252 std::string myclass_dex_name = GetTestDexFileName("MyClass");
Calin Juravle87e2cb62017-06-13 21:48:45 -0700253 std::string dex_name = GetTestDexFileName("Main");
Calin Juravle87e2cb62017-06-13 21:48:45 -0700254
Calin Juravle87e2cb62017-06-13 21:48:45 -0700255 std::unique_ptr<ClassLoaderContext> context =
256 ClassLoaderContext::Create(
257 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
258 "DLC[" + dex_name + "]");
259
260 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
261
262 VerifyContextSize(context.get(), 2);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700263
Calin Juravlec5b215f2017-09-12 14:49:37 -0700264 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
265 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
266 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
267 all_dex_files0.emplace_back(myclass_dex_files[i].release());
268 }
269 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
270
271 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
272 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700273}
274
Calin Juravle821a2592017-08-11 14:33:38 -0700275class ScratchSymLink {
276 public:
277 explicit ScratchSymLink(const std::string& file) {
278 // Use a temporary scratch file to get a unique name for the link.
279 ScratchFile scratchFile;
280 scratch_link_name_ = scratchFile.GetFilename() + ".link.jar";
281 CHECK_EQ(0, symlink(file.c_str(), scratch_link_name_.c_str()));
282 }
283
284 ~ScratchSymLink() {
285 CHECK_EQ(0, unlink(scratch_link_name_.c_str()));
286 }
287
288 const std::string& GetFilename() { return scratch_link_name_; }
289
290 private:
291 std::string scratch_link_name_;
292};
293
294TEST_F(ClassLoaderContextTest, OpenValidDexFilesSymLink) {
295 std::string myclass_dex_name = GetTestDexFileName("MyClass");
296 // Now replace the dex location with a symlink.
297 ScratchSymLink link(myclass_dex_name);
298
299 std::unique_ptr<ClassLoaderContext> context =
300 ClassLoaderContext::Create("PCL[" + link.GetFilename() + "]");
301
302 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
303
304 VerifyContextSize(context.get(), 1);
Calin Juravle821a2592017-08-11 14:33:38 -0700305
Calin Juravlec5b215f2017-09-12 14:49:37 -0700306 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
307
308 VerifyOpenDexFiles(context.get(), 0, &myclass_dex_files);
Calin Juravle821a2592017-08-11 14:33:38 -0700309}
310
Andreas Gampe72527382017-09-02 16:53:03 -0700311static std::string CreateRelativeString(const std::string& in, const char* cwd) {
Nicolas Geoffrayc4be2c82017-09-05 12:40:06 +0100312 int cwd_len = strlen(cwd);
313 if (!android::base::StartsWith(in, cwd) || (cwd_len < 1)) {
Andreas Gampe72527382017-09-02 16:53:03 -0700314 LOG(FATAL) << in << " " << cwd;
315 }
Nicolas Geoffrayc4be2c82017-09-05 12:40:06 +0100316 bool contains_trailing_slash = (cwd[cwd_len - 1] == '/');
317 int start_position = cwd_len + (contains_trailing_slash ? 0 : 1);
318 return in.substr(start_position);
Andreas Gampe72527382017-09-02 16:53:03 -0700319}
320
321TEST_F(ClassLoaderContextTest, OpenValidDexFilesRelative) {
322 char cwd_buf[4096];
323 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
324 PLOG(FATAL) << "Could not get working directory";
325 }
326 std::string multidex_name = CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700327 std::string myclass_dex_name = CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700328 std::string dex_name = CreateRelativeString(GetTestDexFileName("Main"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700329
330
331 std::unique_ptr<ClassLoaderContext> context =
332 ClassLoaderContext::Create(
333 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
334 "DLC[" + dex_name + "]");
335
336 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
337
Calin Juravlec5b215f2017-09-12 14:49:37 -0700338 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
339 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
340 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
341 all_dex_files0.emplace_back(myclass_dex_files[i].release());
342 }
343 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
Andreas Gampe72527382017-09-02 16:53:03 -0700344
Calin Juravlec5b215f2017-09-12 14:49:37 -0700345 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
346 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
Andreas Gampe72527382017-09-02 16:53:03 -0700347}
348
349TEST_F(ClassLoaderContextTest, OpenValidDexFilesClasspathDir) {
350 char cwd_buf[4096];
351 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
352 PLOG(FATAL) << "Could not get working directory";
353 }
354 std::string multidex_name = CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700355 std::string myclass_dex_name = CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700356 std::string dex_name = CreateRelativeString(GetTestDexFileName("Main"), cwd_buf);
Andreas Gampe72527382017-09-02 16:53:03 -0700357
358 std::unique_ptr<ClassLoaderContext> context =
359 ClassLoaderContext::Create(
360 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
361 "DLC[" + dex_name + "]");
362
363 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, cwd_buf));
364
365 VerifyContextSize(context.get(), 2);
Calin Juravlec5b215f2017-09-12 14:49:37 -0700366 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
367 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
368 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
369 all_dex_files0.emplace_back(myclass_dex_files[i].release());
370 }
371 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
Andreas Gampe72527382017-09-02 16:53:03 -0700372
Calin Juravlec5b215f2017-09-12 14:49:37 -0700373 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
374 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
Andreas Gampe72527382017-09-02 16:53:03 -0700375}
376
Calin Juravle87e2cb62017-06-13 21:48:45 -0700377TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
378 std::string dex_name = GetTestDexFileName("Main");
379 std::unique_ptr<ClassLoaderContext> context =
380 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
381 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
382}
383
384TEST_F(ClassLoaderContextTest, CreateClassLoader) {
385 std::string dex_name = GetTestDexFileName("Main");
386 std::unique_ptr<ClassLoaderContext> context =
387 ClassLoaderContext::Create("PCL[" + dex_name + "]");
388 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
389
390 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
391 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
392
393 std::vector<const DexFile*> compilation_sources_raw =
394 MakeNonOwningPointerVector(compilation_sources);
395 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
396 ASSERT_TRUE(jclass_loader != nullptr);
397
398 ScopedObjectAccess soa(Thread::Current());
399
Calin Juravlec79470d2017-07-12 17:37:42 -0700400 StackHandleScope<1> hs(soa.Self());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700401 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
402 soa.Decode<mirror::ClassLoader>(jclass_loader));
403
404 ASSERT_TRUE(class_loader->GetClass() ==
405 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
406 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
407 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
408
Calin Juravlec79470d2017-07-12 17:37:42 -0700409 // For the first class loader the class path dex files must come first and then the
410 // compilation sources.
411 std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex);
412 for (auto& dex : compilation_sources_raw) {
413 expected_classpath.push_back(dex);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700414 }
415
Calin Juravlec79470d2017-07-12 17:37:42 -0700416 VerifyClassLoaderDexFiles(soa,
417 class_loader,
418 WellKnownClasses::dalvik_system_PathClassLoader,
419 expected_classpath);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700420}
421
Calin Juravle7b0648a2017-07-07 18:40:50 -0700422TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
423 std::unique_ptr<ClassLoaderContext> context =
424 ClassLoaderContext::Create("");
425 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
426
427 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
428
429 std::vector<const DexFile*> compilation_sources_raw =
430 MakeNonOwningPointerVector(compilation_sources);
431 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
432 ASSERT_TRUE(jclass_loader != nullptr);
433
434 ScopedObjectAccess soa(Thread::Current());
435
Calin Juravlec79470d2017-07-12 17:37:42 -0700436 StackHandleScope<1> hs(soa.Self());
Calin Juravle7b0648a2017-07-07 18:40:50 -0700437 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
438 soa.Decode<mirror::ClassLoader>(jclass_loader));
439
Calin Juravlec79470d2017-07-12 17:37:42 -0700440 // An empty context should create a single PathClassLoader with only the compilation sources.
441 VerifyClassLoaderDexFiles(soa,
442 class_loader,
443 WellKnownClasses::dalvik_system_PathClassLoader,
444 compilation_sources_raw);
Calin Juravle7b0648a2017-07-07 18:40:50 -0700445 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
446 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
Calin Juravle7b0648a2017-07-07 18:40:50 -0700447}
448
Calin Juravle1a509c82017-07-24 16:51:21 -0700449TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
450 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
451
452 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
453
454 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
455
456 std::vector<const DexFile*> compilation_sources_raw =
457 MakeNonOwningPointerVector(compilation_sources);
458 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
459 ASSERT_TRUE(jclass_loader != nullptr);
460
461 ScopedObjectAccess soa(Thread::Current());
462
463 StackHandleScope<1> hs(soa.Self());
464 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
465 soa.Decode<mirror::ClassLoader>(jclass_loader));
466
467 // A shared library context should create a single PathClassLoader with only the compilation
468 // sources.
469 VerifyClassLoaderDexFiles(soa,
470 class_loader,
471 WellKnownClasses::dalvik_system_PathClassLoader,
472 compilation_sources_raw);
473 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
474 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
475}
476
Calin Juravlec79470d2017-07-12 17:37:42 -0700477TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
478 // Setup the context.
479 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
480 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
481 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
482 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
483
484 std::string context_spec =
485 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" +
486 "DLC[" + CreateClassPath(classpath_dex_c) + "];" +
487 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
488
489 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
490 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
491
492 // Setup the compilation sources.
493 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
494 std::vector<const DexFile*> compilation_sources_raw =
495 MakeNonOwningPointerVector(compilation_sources);
496
497 // Create the class loader.
498 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
499 ASSERT_TRUE(jclass_loader != nullptr);
500
501 // Verify the class loader.
502 ScopedObjectAccess soa(Thread::Current());
503
504 StackHandleScope<3> hs(soa.Self());
505 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
506 soa.Decode<mirror::ClassLoader>(jclass_loader));
507
508 // Verify the first class loader
509
510 // For the first class loader the class path dex files must come first and then the
511 // compilation sources.
512 std::vector<const DexFile*> class_loader_1_dex_files =
513 MakeNonOwningPointerVector(classpath_dex_a);
514 for (auto& dex : classpath_dex_b) {
515 class_loader_1_dex_files.push_back(dex.get());
516 }
517 for (auto& dex : compilation_sources_raw) {
518 class_loader_1_dex_files.push_back(dex);
519 }
520 VerifyClassLoaderDexFiles(soa,
521 class_loader_1,
522 WellKnownClasses::dalvik_system_PathClassLoader,
523 class_loader_1_dex_files);
524
525 // Verify the second class loader
526 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent());
527 std::vector<const DexFile*> class_loader_2_dex_files =
528 MakeNonOwningPointerVector(classpath_dex_c);
529 VerifyClassLoaderDexFiles(soa,
530 class_loader_2,
531 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
532 class_loader_2_dex_files);
533
534 // Verify the third class loader
535 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent());
536 std::vector<const DexFile*> class_loader_3_dex_files =
537 MakeNonOwningPointerVector(classpath_dex_d);
538 VerifyClassLoaderDexFiles(soa,
539 class_loader_3,
540 WellKnownClasses::dalvik_system_PathClassLoader,
541 class_loader_3_dex_files);
542 // The last class loader should have the BootClassLoader as a parent.
543 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
544 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
545}
546
547
Calin Juravle87e2cb62017-06-13 21:48:45 -0700548TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
549 std::unique_ptr<ClassLoaderContext> context =
550 ClassLoaderContext::Create("PCL[a.dex]");
551 dchecked_vector<std::string> classpath_dex;
552 classpath_dex.push_back("a.dex");
553 dchecked_vector<std::string> compilation_sources;
554 compilation_sources.push_back("src.dex");
555
556 // Nothing should be removed.
557 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
558 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
559 // Classes should be removed.
560 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
561 VerifyClassLoaderPCL(context.get(), 0, "");
562}
563
564TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
565 std::string dex1_name = GetTestDexFileName("Main");
566 std::string dex2_name = GetTestDexFileName("MyClass");
567 std::unique_ptr<ClassLoaderContext> context =
568 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
569 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
570
571 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
572 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
573 std::string encoding = context->EncodeContextForOatFile("");
Calin Juravlec79470d2017-07-12 17:37:42 -0700574 std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" +
575 CreateClassPathWithChecksums(dex2) + "]";
Calin Juravle87e2cb62017-06-13 21:48:45 -0700576 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
577}
578
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700579TEST_F(ClassLoaderContextTest, EncodeForDex2oat) {
580 std::string dex1_name = GetTestDexFileName("Main");
581 std::string dex2_name = GetTestDexFileName("MultiDex");
582 std::unique_ptr<ClassLoaderContext> context =
583 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
584 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
585
586 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
587 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MultiDex");
588 std::string encoding = context->EncodeContextForDex2oat("");
589 std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]";
590 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
591}
592
Calin Juravle57d0acc2017-07-11 17:41:30 -0700593// TODO(calin) add a test which creates the context for a class loader together with dex_elements.
594TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
595 // The chain is
596 // ClassLoaderA (PathClassLoader)
597 // ^
598 // |
599 // ClassLoaderB (DelegateLastClassLoader)
600 // ^
601 // |
602 // ClassLoaderC (PathClassLoader)
603 // ^
604 // |
605 // ClassLoaderD (DelegateLastClassLoader)
606
607 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
608 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
609 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
610 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
611
612 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
613
614 VerifyContextForClassLoader(context.get());
615 VerifyContextSize(context.get(), 4);
616
617 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
618 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
619 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
620 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
621}
622
Calin Juravle3f918642017-07-11 19:04:20 -0700623TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
624 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
625 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
Calin Juravlec5b215f2017-09-12 14:49:37 -0700626 // Pretend that we successfully open the dex files to pass the DCHECKS.
627 // (as it's much easier to test all the corner cases without relying on actual dex files).
628 PretendContextOpenedDexFiles(context.get());
Calin Juravle3f918642017-07-11 19:04:20 -0700629
630 VerifyContextSize(context.get(), 2);
631 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
632 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
633
634 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_spec));
635
636 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
637 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_type));
638
639 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
640 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_order));
641
642 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
643 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_classpath_order));
644
645 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
646 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_checksum));
647
648 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
649 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader));
650
651 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
652 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_classpath));
653
654 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
655 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_spec));
656}
657
658TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
659 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
660 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
661 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
662 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
663
664 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
665
Calin Juravle1e96a5d2017-09-05 17:10:48 -0700666 std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
667 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_no_base_dir));
668
669 std::string dex_location = GetTestDexFileName("ForClassLoaderA");
670 size_t pos = dex_location.rfind('/');
671 ASSERT_NE(std::string::npos, pos);
672 std::string parent = dex_location.substr(0, pos);
673
674 std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
675 ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
676 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_base_dir));
Calin Juravle3f918642017-07-11 19:04:20 -0700677}
678
Calin Juravlea308a322017-07-18 16:51:51 -0700679TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) {
680 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
681
682 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
683
684 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
685}
686
Calin Juravle87e2cb62017-06-13 21:48:45 -0700687} // namespace art