1 /*
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
17 #include "class_loader_context.h"
18
19 #include <gtest/gtest.h>
20
21 #include "android-base/strings.h"
22 #include "art_field-inl.h"
23 #include "base/dchecked_vector.h"
24 #include "base/stl_util.h"
25 #include "class_linker.h"
26 #include "class_root-inl.h"
27 #include "common_runtime_test.h"
28 #include "dex/dex_file.h"
29 #include "handle_scope-inl.h"
30 #include "jni/jni_internal.h"
31 #include "mirror/class.h"
32 #include "mirror/class_loader-inl.h"
33 #include "mirror/object-inl.h"
34 #include "mirror/object_array-alloc-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
41 namespace art {
42
43 class ClassLoaderContextTest : public CommonRuntimeTest {
44 public:
VerifyContextSize(ClassLoaderContext * context,size_t expected_size)45 void VerifyContextSize(ClassLoaderContext* context, size_t expected_size) {
46 ASSERT_TRUE(context != nullptr);
47 ASSERT_EQ(expected_size, context->GetParentChainSize());
48 }
49
VerifyClassLoaderPCL(ClassLoaderContext * context,size_t index,const std::string & classpath)50 void VerifyClassLoaderPCL(ClassLoaderContext* context,
51 size_t index,
52 const std::string& classpath) {
53 VerifyClassLoaderInfo(
54 context, index, ClassLoaderContext::kPathClassLoader, classpath);
55 }
56
VerifyClassLoaderDLC(ClassLoaderContext * context,size_t index,const std::string & classpath)57 void VerifyClassLoaderDLC(ClassLoaderContext* context,
58 size_t index,
59 const std::string& classpath) {
60 VerifyClassLoaderInfo(
61 context, index, ClassLoaderContext::kDelegateLastClassLoader, classpath);
62 }
63
VerifyClassLoaderIMC(ClassLoaderContext * context,size_t index,const std::string & classpath)64 void VerifyClassLoaderIMC(ClassLoaderContext* context,
65 size_t index,
66 const std::string& classpath) {
67 VerifyClassLoaderInfo(
68 context, index, ClassLoaderContext::kInMemoryDexClassLoader, classpath);
69 }
70
VerifyClassLoaderSharedLibraryPCL(ClassLoaderContext * context,size_t loader_index,size_t shared_library_index,const std::string & classpath)71 void VerifyClassLoaderSharedLibraryPCL(ClassLoaderContext* context,
72 size_t loader_index,
73 size_t shared_library_index,
74 const std::string& classpath) {
75 VerifyClassLoaderInfoSL(
76 context, loader_index, shared_library_index, ClassLoaderContext::kPathClassLoader,
77 classpath);
78 }
79
VerifyClassLoaderSharedLibraryIMC(ClassLoaderContext * context,size_t loader_index,size_t shared_library_index,const std::string & classpath)80 void VerifyClassLoaderSharedLibraryIMC(ClassLoaderContext* context,
81 size_t loader_index,
82 size_t shared_library_index,
83 const std::string& classpath) {
84 VerifyClassLoaderInfoSL(
85 context, loader_index, shared_library_index, ClassLoaderContext::kInMemoryDexClassLoader,
86 classpath);
87 }
88
VerifySharedLibrariesSize(ClassLoaderContext * context,size_t loader_index,size_t expected_size)89 void VerifySharedLibrariesSize(ClassLoaderContext* context,
90 size_t loader_index,
91 size_t expected_size) {
92 ASSERT_TRUE(context != nullptr);
93 ASSERT_GT(context->GetParentChainSize(), loader_index);
94 const ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(loader_index);
95 ASSERT_EQ(info.shared_libraries.size(), expected_size);
96 }
97
VerifyClassLoaderSharedLibraryDLC(ClassLoaderContext * context,size_t loader_index,size_t shared_library_index,const std::string & classpath)98 void VerifyClassLoaderSharedLibraryDLC(ClassLoaderContext* context,
99 size_t loader_index,
100 size_t shared_library_index,
101 const std::string& classpath) {
102 VerifyClassLoaderInfoSL(
103 context, loader_index, shared_library_index, ClassLoaderContext::kDelegateLastClassLoader,
104 classpath);
105 }
106
VerifyClassLoaderPCLFromTestDex(ClassLoaderContext * context,size_t index,const std::string & test_name)107 void VerifyClassLoaderPCLFromTestDex(ClassLoaderContext* context,
108 size_t index,
109 const std::string& test_name) {
110 VerifyClassLoaderFromTestDex(
111 context, index, ClassLoaderContext::kPathClassLoader, test_name);
112 }
113
VerifyClassLoaderDLCFromTestDex(ClassLoaderContext * context,size_t index,const std::string & test_name)114 void VerifyClassLoaderDLCFromTestDex(ClassLoaderContext* context,
115 size_t index,
116 const std::string& test_name) {
117 VerifyClassLoaderFromTestDex(
118 context, index, ClassLoaderContext::kDelegateLastClassLoader, test_name);
119 }
120
VerifyClassLoaderIMCFromTestDex(ClassLoaderContext * context,size_t index,const std::string & test_name)121 void VerifyClassLoaderIMCFromTestDex(ClassLoaderContext* context,
122 size_t index,
123 const std::string& test_name) {
124 VerifyClassLoaderFromTestDex(
125 context, index, ClassLoaderContext::kInMemoryDexClassLoader, test_name, "<unknown>");
126 }
127
128 enum class LocationCheck {
129 kEquals,
130 kEndsWith
131 };
132 enum class BaseLocationCheck {
133 kEquals,
134 kEndsWith
135 };
136
IsAbsoluteLocation(const std::string & location)137 static bool IsAbsoluteLocation(const std::string& location) {
138 return !location.empty() && location[0] == '/';
139 }
140
VerifyOpenDexFiles(ClassLoaderContext * context,size_t index,std::vector<std::unique_ptr<const DexFile>> * all_dex_files,bool classpath_matches_dex_location=true)141 void VerifyOpenDexFiles(
142 ClassLoaderContext* context,
143 size_t index,
144 std::vector<std::unique_ptr<const DexFile>>* all_dex_files,
145 bool classpath_matches_dex_location = true) {
146 ASSERT_TRUE(context != nullptr);
147 ASSERT_TRUE(context->dex_files_open_attempted_);
148 ASSERT_TRUE(context->dex_files_open_result_);
149 ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(index);
150 ASSERT_EQ(all_dex_files->size(), info.classpath.size());
151 ASSERT_EQ(all_dex_files->size(), info.opened_dex_files.size());
152 size_t cur_open_dex_index = 0;
153 for (size_t k = 0; k < all_dex_files->size(); k++) {
154 std::unique_ptr<const DexFile>& opened_dex_file =
155 info.opened_dex_files[cur_open_dex_index++];
156 std::unique_ptr<const DexFile>& expected_dex_file = (*all_dex_files)[k];
157
158 std::string expected_location = expected_dex_file->GetLocation();
159
160 const std::string& opened_location = opened_dex_file->GetLocation();
161 if (!IsAbsoluteLocation(opened_location)) {
162 // If the opened location is relative (it was open from a relative path without a
163 // classpath_dir) it might not match the expected location which is absolute in tests).
164 // So we compare the endings (the checksum will validate it's actually the same file).
165 ASSERT_EQ(0, expected_location.compare(
166 expected_location.length() - opened_location.length(),
167 opened_location.length(),
168 opened_location));
169 } else {
170 ASSERT_EQ(expected_location, opened_location);
171 }
172 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
173 if (classpath_matches_dex_location) {
174 ASSERT_EQ(info.classpath[k], opened_location);
175 }
176 }
177 }
178
CreateContextForClassLoader(jobject class_loader)179 std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) {
180 return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
181 }
182
ParseContextWithChecksums(const std::string & context_spec)183 std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) {
184 std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext());
185 if (!context->Parse(context_spec, /*parse_checksums=*/ true)) {
186 return nullptr;
187 }
188 return context;
189 }
190
VerifyContextForClassLoader(ClassLoaderContext * context)191 void VerifyContextForClassLoader(ClassLoaderContext* context) {
192 ASSERT_TRUE(context != nullptr);
193 ASSERT_TRUE(context->dex_files_open_attempted_);
194 ASSERT_TRUE(context->dex_files_open_result_);
195 ASSERT_FALSE(context->owns_the_dex_files_);
196 ASSERT_FALSE(context->special_shared_library_);
197 }
198
VerifyClassLoaderDexFiles(ScopedObjectAccess & soa,Handle<mirror::ClassLoader> class_loader,jclass type,std::vector<const DexFile * > & expected_dex_files)199 void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
200 Handle<mirror::ClassLoader> class_loader,
201 jclass type,
202 std::vector<const DexFile*>& expected_dex_files)
203 REQUIRES_SHARED(Locks::mutator_lock_) {
204 ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type));
205
206 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader);
207 ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size());
208
209 for (size_t i = 0; i < expected_dex_files.size(); i++) {
210 ASSERT_EQ(expected_dex_files[i]->GetLocation(),
211 class_loader_dex_files[i]->GetLocation());
212 ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(),
213 class_loader_dex_files[i]->GetLocationChecksum());
214 }
215 }
216
PretendContextOpenedDexFiles(ClassLoaderContext * context)217 void PretendContextOpenedDexFiles(ClassLoaderContext* context) {
218 context->dex_files_open_attempted_ = true;
219 context->dex_files_open_result_ = true;
220 }
221
222 private:
VerifyClassLoaderInfo(ClassLoaderContext * context,size_t index,ClassLoaderContext::ClassLoaderType type,const std::string & classpath)223 void VerifyClassLoaderInfo(ClassLoaderContext* context,
224 size_t index,
225 ClassLoaderContext::ClassLoaderType type,
226 const std::string& classpath) {
227 ASSERT_TRUE(context != nullptr);
228 ASSERT_GT(context->GetParentChainSize(), index);
229 ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(index);
230 ASSERT_EQ(type, info.type);
231 std::vector<std::string> expected_classpath;
232 Split(classpath, ':', &expected_classpath);
233 ASSERT_EQ(expected_classpath, info.classpath);
234 }
235
VerifyClassLoaderInfoSL(ClassLoaderContext * context,size_t loader_index,size_t shared_library_index,ClassLoaderContext::ClassLoaderType type,const std::string & classpath)236 void VerifyClassLoaderInfoSL(ClassLoaderContext* context,
237 size_t loader_index,
238 size_t shared_library_index,
239 ClassLoaderContext::ClassLoaderType type,
240 const std::string& classpath) {
241 ASSERT_TRUE(context != nullptr);
242 ASSERT_GT(context->GetParentChainSize(), loader_index);
243 const ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(loader_index);
244 ASSERT_GT(info.shared_libraries.size(), shared_library_index);
245 const ClassLoaderContext::ClassLoaderInfo& sl =
246 *info.shared_libraries[shared_library_index].get();
247 ASSERT_EQ(type, info.type);
248 std::vector<std::string> expected_classpath;
249 Split(classpath, ':', &expected_classpath);
250 ASSERT_EQ(expected_classpath, sl.classpath);
251 }
252
VerifyClassLoaderFromTestDex(ClassLoaderContext * context,size_t index,ClassLoaderContext::ClassLoaderType type,const std::string & test_name,const std::string & classpath="")253 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
254 size_t index,
255 ClassLoaderContext::ClassLoaderType type,
256 const std::string& test_name,
257 const std::string& classpath = "") {
258 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
259
260 // If `classpath` is set, override the expected value of ClassLoaderInfo::classpath.
261 // Otherwise assume it is equal to dex location (here test dex file name).
262 VerifyClassLoaderInfo(context,
263 index,
264 type,
265 classpath.empty() ? GetTestDexFileName(test_name.c_str()) : classpath);
266 VerifyOpenDexFiles(context,
267 index,
268 &dex_files,
269 /* classpath_matches_dex_location= */ classpath.empty());
270 }
271 };
272
TEST_F(ClassLoaderContextTest,ParseValidEmptyContext)273 TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
274 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
275 // An empty context should create a single empty PathClassLoader.
276 VerifyContextSize(context.get(), 1);
277 VerifyClassLoaderPCL(context.get(), 0, "");
278 }
279
TEST_F(ClassLoaderContextTest,ParseValidSharedLibraryContext)280 TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
281 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
282 // An shared library context should have no class loader in the chain.
283 VerifyContextSize(context.get(), 0);
284 }
285
TEST_F(ClassLoaderContextTest,ParseValidContextPCL)286 TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
287 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("PCL[a.dex]");
288 VerifyContextSize(context.get(), 1);
289 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
290 }
291
TEST_F(ClassLoaderContextTest,ParseValidContextDLC)292 TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
293 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("DLC[a.dex]");
294 VerifyContextSize(context.get(), 1);
295 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
296 }
297
TEST_F(ClassLoaderContextTest,ParseValidContextIMC)298 TEST_F(ClassLoaderContextTest, ParseValidContextIMC) {
299 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums("IMC[<unknown>*111]");
300 ASSERT_FALSE(context == nullptr);
301 }
302
TEST_F(ClassLoaderContextTest,ParseInvalidContextIMCNoChecksum)303 TEST_F(ClassLoaderContextTest, ParseInvalidContextIMCNoChecksum) {
304 // IMC is treated as an unknown class loader unless a checksum is provided.
305 // This is because the dex location is always bogus.
306 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("IMC[<unknown>]");
307 ASSERT_TRUE(context == nullptr);
308 }
309
TEST_F(ClassLoaderContextTest,ParseInvalidContextIMCWrongClasspathMagic)310 TEST_F(ClassLoaderContextTest, ParseInvalidContextIMCWrongClasspathMagic) {
311 // IMC does not support arbitrary dex location. A magic marker must be used
312 // otherwise the spec should be rejected.
313 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("IMC[a.dex*111]");
314 ASSERT_TRUE(context == nullptr);
315 }
316
TEST_F(ClassLoaderContextTest,ParseValidContextChain)317 TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
318 std::unique_ptr<ClassLoaderContext> context =
319 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
320 VerifyContextSize(context.get(), 3);
321 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
322 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
323 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
324 }
325
TEST_F(ClassLoaderContextTest,ParseSharedLibraries)326 TEST_F(ClassLoaderContextTest, ParseSharedLibraries) {
327 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(
328 "PCL[a.dex:b.dex]{PCL[s1.dex]#PCL[s2.dex:s3.dex]};DLC[c.dex:d.dex]{DLC[s4.dex]}");
329 VerifyContextSize(context.get(), 2);
330 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "s1.dex");
331 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 1, "s2.dex:s3.dex");
332 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
333 VerifyClassLoaderSharedLibraryDLC(context.get(), 1, 0, "s4.dex");
334 }
335
TEST_F(ClassLoaderContextTest,ParseEnclosingSharedLibraries)336 TEST_F(ClassLoaderContextTest, ParseEnclosingSharedLibraries) {
337 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(
338 "PCL[a.dex:b.dex]{PCL[s1.dex]{PCL[s2.dex:s3.dex];PCL[s4.dex]}}");
339 VerifyContextSize(context.get(), 1);
340 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "s1.dex");
341 }
342
TEST_F(ClassLoaderContextTest,ParseComplexSharedLibraries1)343 TEST_F(ClassLoaderContextTest, ParseComplexSharedLibraries1) {
344 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(
345 "PCL[]{PCL[s4.dex]{PCL[s5.dex]{PCL[s6.dex]}#PCL[s6.dex]}}");
346 VerifyContextSize(context.get(), 1);
347 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "s4.dex");
348 }
349
TEST_F(ClassLoaderContextTest,ParseComplexSharedLibraries2)350 TEST_F(ClassLoaderContextTest, ParseComplexSharedLibraries2) {
351 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(
352 "PCL[]{PCL[s1.dex]{PCL[s2.dex]}#PCL[s2.dex]#"
353 "PCL[s3.dex]#PCL[s4.dex]{PCL[s5.dex]{PCL[s6.dex]}#PCL[s6.dex]}#PCL[s5.dex]{PCL[s6.dex]}}");
354 VerifyContextSize(context.get(), 1);
355 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "s1.dex");
356 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 1, "s2.dex");
357 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 2, "s3.dex");
358 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 3, "s4.dex");
359 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 4, "s5.dex");
360 }
361
TEST_F(ClassLoaderContextTest,ParseValidEmptyContextDLC)362 TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
363 std::unique_ptr<ClassLoaderContext> context =
364 ClassLoaderContext::Create("DLC[]");
365 VerifyContextSize(context.get(), 1);
366 VerifyClassLoaderDLC(context.get(), 0, "");
367 }
368
TEST_F(ClassLoaderContextTest,ParseValidEmptyContextSharedLibrary)369 TEST_F(ClassLoaderContextTest, ParseValidEmptyContextSharedLibrary) {
370 std::unique_ptr<ClassLoaderContext> context =
371 ClassLoaderContext::Create("DLC[]{}");
372 VerifyContextSize(context.get(), 1);
373 VerifySharedLibrariesSize(context.get(), 0, 0);
374 }
375
TEST_F(ClassLoaderContextTest,ParseValidContextSpecialSymbol)376 TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
377 std::unique_ptr<ClassLoaderContext> context =
378 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
379 VerifyContextSize(context.get(), 0);
380 }
381
TEST_F(ClassLoaderContextTest,ParseInvalidValidContexts)382 TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
383 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
384 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
385 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
386 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
387 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
388 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
389 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex]{ABC};DLC[b.dex"));
390 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex]{};DLC[b.dex"));
391 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("DLC[s4.dex]}"));
392 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("DLC[s4.dex]{"));
393 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("DLC{DLC[s4.dex]}"));
394 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{##}"));
395 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{PCL[s4.dex]#}"));
396 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{PCL[s4.dex]##}"));
397 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{PCL[s4.dex]{PCL[s3.dex]}#}"));
398 }
399
TEST_F(ClassLoaderContextTest,OpenInvalidDexFiles)400 TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
401 std::unique_ptr<ClassLoaderContext> context =
402 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
403 VerifyContextSize(context.get(), 1);
404 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
405 }
406
TEST_F(ClassLoaderContextTest,OpenValidDexFiles)407 TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
408 std::string multidex_name = GetTestDexFileName("MultiDex");
409 std::string myclass_dex_name = GetTestDexFileName("MyClass");
410 std::string dex_name = GetTestDexFileName("Main");
411
412
413 std::unique_ptr<ClassLoaderContext> context =
414 ClassLoaderContext::Create(
415 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
416 "DLC[" + dex_name + "]");
417
418 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir=*/ ""));
419
420 VerifyContextSize(context.get(), 2);
421
422 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
423 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
424 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
425 all_dex_files0.emplace_back(myclass_dex_files[i].release());
426 }
427 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
428
429 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
430 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
431 }
432
433 // Creates a relative path from cwd to 'in'. Returns false if it cannot be done.
434 // TODO We should somehow support this in all situations. b/72042237.
CreateRelativeString(const std::string & in,const char * cwd,std::string * out)435 static bool CreateRelativeString(const std::string& in, const char* cwd, std::string* out) {
436 int cwd_len = strlen(cwd);
437 if (!android::base::StartsWith(in, cwd) || (cwd_len < 1)) {
438 return false;
439 }
440 bool contains_trailing_slash = (cwd[cwd_len - 1] == '/');
441 int start_position = cwd_len + (contains_trailing_slash ? 0 : 1);
442 *out = in.substr(start_position);
443 return true;
444 }
445
TEST_F(ClassLoaderContextTest,OpenValidDexFilesRelative)446 TEST_F(ClassLoaderContextTest, OpenValidDexFilesRelative) {
447 char cwd_buf[4096];
448 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
449 PLOG(FATAL) << "Could not get working directory";
450 }
451 std::string multidex_name;
452 std::string myclass_dex_name;
453 std::string dex_name;
454 if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) ||
455 !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) ||
456 !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) {
457 LOG(ERROR) << "Test OpenValidDexFilesRelative cannot be run because target dex files have no "
458 << "relative path.";
459 SUCCEED();
460 return;
461 }
462
463 std::unique_ptr<ClassLoaderContext> context =
464 ClassLoaderContext::Create(
465 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
466 "DLC[" + dex_name + "]");
467
468 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir=*/ ""));
469
470 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
471 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
472 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
473 all_dex_files0.emplace_back(myclass_dex_files[i].release());
474 }
475 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
476
477 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
478 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
479 }
480
TEST_F(ClassLoaderContextTest,OpenValidDexFilesClasspathDir)481 TEST_F(ClassLoaderContextTest, OpenValidDexFilesClasspathDir) {
482 char cwd_buf[4096];
483 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
484 PLOG(FATAL) << "Could not get working directory";
485 }
486 std::string multidex_name;
487 std::string myclass_dex_name;
488 std::string dex_name;
489 if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) ||
490 !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) ||
491 !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) {
492 LOG(ERROR) << "Test OpenValidDexFilesClasspathDir cannot be run because target dex files have "
493 << "no relative path.";
494 SUCCEED();
495 return;
496 }
497 std::unique_ptr<ClassLoaderContext> context =
498 ClassLoaderContext::Create(
499 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
500 "DLC[" + dex_name + "]");
501
502 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, cwd_buf));
503
504 VerifyContextSize(context.get(), 2);
505 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
506 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
507 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
508 all_dex_files0.emplace_back(myclass_dex_files[i].release());
509 }
510 VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
511
512 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
513 VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
514 }
515
TEST_F(ClassLoaderContextTest,OpenInvalidDexFilesMix)516 TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
517 std::string dex_name = GetTestDexFileName("Main");
518 std::unique_ptr<ClassLoaderContext> context =
519 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
520 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
521 }
522
TEST_F(ClassLoaderContextTest,OpenDexFilesForIMCFails)523 TEST_F(ClassLoaderContextTest, OpenDexFilesForIMCFails) {
524 std::unique_ptr<ClassLoaderContext> context;
525 std::string dex_name = GetTestDexFileName("Main");
526
527 context = ParseContextWithChecksums("IMC[<unknown>*111]");
528 VerifyContextSize(context.get(), 1);
529 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
530 }
531
TEST_F(ClassLoaderContextTest,CreateClassLoader)532 TEST_F(ClassLoaderContextTest, CreateClassLoader) {
533 std::string dex_name = GetTestDexFileName("Main");
534 std::unique_ptr<ClassLoaderContext> context =
535 ClassLoaderContext::Create("PCL[" + dex_name + "]");
536 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
537
538 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
539 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
540
541 std::vector<const DexFile*> compilation_sources_raw =
542 MakeNonOwningPointerVector(compilation_sources);
543 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
544 ASSERT_TRUE(jclass_loader != nullptr);
545
546 ScopedObjectAccess soa(Thread::Current());
547
548 StackHandleScope<1> hs(soa.Self());
549 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
550 soa.Decode<mirror::ClassLoader>(jclass_loader));
551
552 ASSERT_TRUE(class_loader->GetClass() ==
553 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
554 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
555 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
556
557 // For the first class loader the class path dex files must come first and then the
558 // compilation sources.
559 std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex);
560 for (auto& dex : compilation_sources_raw) {
561 expected_classpath.push_back(dex);
562 }
563
564 VerifyClassLoaderDexFiles(soa,
565 class_loader,
566 WellKnownClasses::dalvik_system_PathClassLoader,
567 expected_classpath);
568 }
569
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithEmptyContext)570 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
571 std::unique_ptr<ClassLoaderContext> context =
572 ClassLoaderContext::Create("");
573 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
574
575 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
576
577 std::vector<const DexFile*> compilation_sources_raw =
578 MakeNonOwningPointerVector(compilation_sources);
579 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
580 ASSERT_TRUE(jclass_loader != nullptr);
581
582 ScopedObjectAccess soa(Thread::Current());
583
584 StackHandleScope<1> hs(soa.Self());
585 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
586 soa.Decode<mirror::ClassLoader>(jclass_loader));
587
588 // An empty context should create a single PathClassLoader with only the compilation sources.
589 VerifyClassLoaderDexFiles(soa,
590 class_loader,
591 WellKnownClasses::dalvik_system_PathClassLoader,
592 compilation_sources_raw);
593 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
594 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
595 }
596
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithSharedLibraryContext)597 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
598 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
599
600 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
601
602 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
603
604 std::vector<const DexFile*> compilation_sources_raw =
605 MakeNonOwningPointerVector(compilation_sources);
606 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
607 ASSERT_TRUE(jclass_loader != nullptr);
608
609 ScopedObjectAccess soa(Thread::Current());
610
611 StackHandleScope<1> hs(soa.Self());
612 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
613 soa.Decode<mirror::ClassLoader>(jclass_loader));
614
615 // A shared library context should create a single PathClassLoader with only the compilation
616 // sources.
617 VerifyClassLoaderDexFiles(soa,
618 class_loader,
619 WellKnownClasses::dalvik_system_PathClassLoader,
620 compilation_sources_raw);
621 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
622 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
623 }
624
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithComplexChain)625 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
626 // Setup the context.
627 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
628 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
629 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
630 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
631
632 std::string context_spec =
633 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" +
634 "DLC[" + CreateClassPath(classpath_dex_c) + "];" +
635 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
636
637 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
638 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
639
640 // Setup the compilation sources.
641 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
642 std::vector<const DexFile*> compilation_sources_raw =
643 MakeNonOwningPointerVector(compilation_sources);
644
645 // Create the class loader.
646 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
647 ASSERT_TRUE(jclass_loader != nullptr);
648
649 // Verify the class loader.
650 ScopedObjectAccess soa(Thread::Current());
651
652 StackHandleScope<3> hs(soa.Self());
653 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
654 soa.Decode<mirror::ClassLoader>(jclass_loader));
655
656 // Verify the first class loader
657
658 // For the first class loader the class path dex files must come first and then the
659 // compilation sources.
660 std::vector<const DexFile*> class_loader_1_dex_files =
661 MakeNonOwningPointerVector(classpath_dex_a);
662 for (auto& dex : classpath_dex_b) {
663 class_loader_1_dex_files.push_back(dex.get());
664 }
665 for (auto& dex : compilation_sources_raw) {
666 class_loader_1_dex_files.push_back(dex);
667 }
668 VerifyClassLoaderDexFiles(soa,
669 class_loader_1,
670 WellKnownClasses::dalvik_system_PathClassLoader,
671 class_loader_1_dex_files);
672
673 // Verify the second class loader
674 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent());
675 std::vector<const DexFile*> class_loader_2_dex_files =
676 MakeNonOwningPointerVector(classpath_dex_c);
677 VerifyClassLoaderDexFiles(soa,
678 class_loader_2,
679 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
680 class_loader_2_dex_files);
681
682 // Verify the third class loader
683 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent());
684 std::vector<const DexFile*> class_loader_3_dex_files =
685 MakeNonOwningPointerVector(classpath_dex_d);
686 VerifyClassLoaderDexFiles(soa,
687 class_loader_3,
688 WellKnownClasses::dalvik_system_PathClassLoader,
689 class_loader_3_dex_files);
690 // The last class loader should have the BootClassLoader as a parent.
691 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
692 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
693 }
694
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithSharedLibraries)695 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraries) {
696 // Setup the context.
697 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
698 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
699 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
700 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
701
702 std::string context_spec =
703 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "]{" +
704 "DLC[" + CreateClassPath(classpath_dex_c) + "]#" +
705 "PCL[" + CreateClassPath(classpath_dex_d) + "]}";
706
707 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
708 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
709
710 // Setup the compilation sources.
711 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
712 std::vector<const DexFile*> compilation_sources_raw =
713 MakeNonOwningPointerVector(compilation_sources);
714
715 // Create the class loader.
716 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
717 ASSERT_TRUE(jclass_loader != nullptr);
718
719 // Verify the class loader.
720 ScopedObjectAccess soa(Thread::Current());
721
722 StackHandleScope<4> hs(soa.Self());
723 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
724 soa.Decode<mirror::ClassLoader>(jclass_loader));
725
726 // For the first class loader the class path dex files must come first and then the
727 // compilation sources.
728 std::vector<const DexFile*> class_loader_1_dex_files =
729 MakeNonOwningPointerVector(classpath_dex_a);
730 for (auto& dex : classpath_dex_b) {
731 class_loader_1_dex_files.push_back(dex.get());
732 }
733 for (auto& dex : compilation_sources_raw) {
734 class_loader_1_dex_files.push_back(dex);
735 }
736 VerifyClassLoaderDexFiles(soa,
737 class_loader_1,
738 WellKnownClasses::dalvik_system_PathClassLoader,
739 class_loader_1_dex_files);
740
741 // Verify the shared libraries.
742 ArtField* field =
743 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
744 ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader_1.Get());
745 ASSERT_TRUE(raw_shared_libraries != nullptr);
746
747 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries(
748 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
749 ASSERT_EQ(shared_libraries->GetLength(), 2);
750
751 // Verify the first shared library.
752 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(shared_libraries->Get(0));
753 std::vector<const DexFile*> class_loader_2_dex_files =
754 MakeNonOwningPointerVector(classpath_dex_c);
755 VerifyClassLoaderDexFiles(soa,
756 class_loader_2,
757 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
758 class_loader_2_dex_files);
759 raw_shared_libraries = field->GetObject(class_loader_2.Get());
760 ASSERT_TRUE(raw_shared_libraries == nullptr);
761
762 // Verify the second shared library.
763 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(shared_libraries->Get(1));
764 std::vector<const DexFile*> class_loader_3_dex_files =
765 MakeNonOwningPointerVector(classpath_dex_d);
766 VerifyClassLoaderDexFiles(soa,
767 class_loader_3,
768 WellKnownClasses::dalvik_system_PathClassLoader,
769 class_loader_3_dex_files);
770 raw_shared_libraries = field->GetObject(class_loader_3.Get());
771 ASSERT_TRUE(raw_shared_libraries == nullptr);
772
773 // All class loaders should have the BootClassLoader as a parent.
774 ASSERT_TRUE(class_loader_1->GetParent()->GetClass() ==
775 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
776 ASSERT_TRUE(class_loader_2->GetParent()->GetClass() ==
777 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
778 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
779 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
780 }
781
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithSharedLibrariesInParentToo)782 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibrariesInParentToo) {
783 // Setup the context.
784 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
785 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
786 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
787 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
788
789 std::string context_spec =
790 "PCL[" + CreateClassPath(classpath_dex_a) + "]{" +
791 "PCL[" + CreateClassPath(classpath_dex_b) + "]};" +
792 "PCL[" + CreateClassPath(classpath_dex_c) + "]{" +
793 "PCL[" + CreateClassPath(classpath_dex_d) + "]}";
794
795 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
796 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
797
798 // Setup the compilation sources.
799 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
800 std::vector<const DexFile*> compilation_sources_raw =
801 MakeNonOwningPointerVector(compilation_sources);
802
803 // Create the class loader.
804 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
805 ASSERT_TRUE(jclass_loader != nullptr);
806
807 // Verify the class loader.
808 ScopedObjectAccess soa(Thread::Current());
809
810 StackHandleScope<6> hs(soa.Self());
811 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
812 soa.Decode<mirror::ClassLoader>(jclass_loader));
813
814 // For the first class loader the class path dex files must come first and then the
815 // compilation sources.
816 std::vector<const DexFile*> class_loader_1_dex_files =
817 MakeNonOwningPointerVector(classpath_dex_a);
818 for (auto& dex : compilation_sources_raw) {
819 class_loader_1_dex_files.push_back(dex);
820 }
821 VerifyClassLoaderDexFiles(soa,
822 class_loader_1,
823 WellKnownClasses::dalvik_system_PathClassLoader,
824 class_loader_1_dex_files);
825
826 // Verify its shared library.
827 ArtField* field =
828 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
829 ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader_1.Get());
830 ASSERT_TRUE(raw_shared_libraries != nullptr);
831
832 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries(
833 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
834 ASSERT_EQ(shared_libraries->GetLength(), 1);
835
836 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(shared_libraries->Get(0));
837 std::vector<const DexFile*> class_loader_2_dex_files =
838 MakeNonOwningPointerVector(classpath_dex_b);
839 VerifyClassLoaderDexFiles(soa,
840 class_loader_2,
841 WellKnownClasses::dalvik_system_PathClassLoader,
842 class_loader_2_dex_files);
843 raw_shared_libraries = field->GetObject(class_loader_2.Get());
844 ASSERT_TRUE(raw_shared_libraries == nullptr);
845
846 // Verify the parent.
847 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_1->GetParent());
848 std::vector<const DexFile*> class_loader_3_dex_files =
849 MakeNonOwningPointerVector(classpath_dex_c);
850 VerifyClassLoaderDexFiles(soa,
851 class_loader_3,
852 WellKnownClasses::dalvik_system_PathClassLoader,
853 class_loader_3_dex_files);
854
855 // Verify its shared library.
856 raw_shared_libraries = field->GetObject(class_loader_3.Get());
857 ASSERT_TRUE(raw_shared_libraries != nullptr);
858
859 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries_2(
860 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
861 ASSERT_EQ(shared_libraries->GetLength(), 1);
862
863 Handle<mirror::ClassLoader> class_loader_4 = hs.NewHandle(shared_libraries_2->Get(0));
864 std::vector<const DexFile*> class_loader_4_dex_files =
865 MakeNonOwningPointerVector(classpath_dex_d);
866 VerifyClassLoaderDexFiles(soa,
867 class_loader_4,
868 WellKnownClasses::dalvik_system_PathClassLoader,
869 class_loader_4_dex_files);
870 raw_shared_libraries = field->GetObject(class_loader_4.Get());
871 ASSERT_TRUE(raw_shared_libraries == nullptr);
872
873 // Class loaders should have the BootClassLoader as a parent.
874 ASSERT_TRUE(class_loader_2->GetParent()->GetClass() ==
875 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
876 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
877 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
878 ASSERT_TRUE(class_loader_4->GetParent()->GetClass() ==
879 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
880 }
881
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithSharedLibrariesDependencies)882 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibrariesDependencies) {
883 // Setup the context.
884 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
885 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
886 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
887 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
888
889 std::string context_spec =
890 "PCL[" + CreateClassPath(classpath_dex_a) + "]{" +
891 "PCL[" + CreateClassPath(classpath_dex_b) + "]{" +
892 "PCL[" + CreateClassPath(classpath_dex_c) + "]}};" +
893 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
894
895 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
896 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
897
898 // Setup the compilation sources.
899 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
900 std::vector<const DexFile*> compilation_sources_raw =
901 MakeNonOwningPointerVector(compilation_sources);
902
903 // Create the class loader.
904 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
905 ASSERT_TRUE(jclass_loader != nullptr);
906
907 // Verify the class loader.
908 ScopedObjectAccess soa(Thread::Current());
909
910 StackHandleScope<6> hs(soa.Self());
911 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
912 soa.Decode<mirror::ClassLoader>(jclass_loader));
913
914 // For the first class loader the class path dex files must come first and then the
915 // compilation sources.
916 std::vector<const DexFile*> class_loader_1_dex_files =
917 MakeNonOwningPointerVector(classpath_dex_a);
918 for (auto& dex : compilation_sources_raw) {
919 class_loader_1_dex_files.push_back(dex);
920 }
921 VerifyClassLoaderDexFiles(soa,
922 class_loader_1,
923 WellKnownClasses::dalvik_system_PathClassLoader,
924 class_loader_1_dex_files);
925
926 // Verify its shared library.
927 ArtField* field =
928 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
929 ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader_1.Get());
930 ASSERT_TRUE(raw_shared_libraries != nullptr);
931
932 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries(
933 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
934 ASSERT_EQ(shared_libraries->GetLength(), 1);
935
936 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(shared_libraries->Get(0));
937 std::vector<const DexFile*> class_loader_2_dex_files =
938 MakeNonOwningPointerVector(classpath_dex_b);
939 VerifyClassLoaderDexFiles(soa,
940 class_loader_2,
941 WellKnownClasses::dalvik_system_PathClassLoader,
942 class_loader_2_dex_files);
943
944 // Verify the shared library dependency of the shared library.
945 raw_shared_libraries = field->GetObject(class_loader_2.Get());
946 ASSERT_TRUE(raw_shared_libraries != nullptr);
947
948 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries_2(
949 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
950 ASSERT_EQ(shared_libraries_2->GetLength(), 1);
951
952 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(shared_libraries_2->Get(0));
953 std::vector<const DexFile*> class_loader_3_dex_files =
954 MakeNonOwningPointerVector(classpath_dex_c);
955 VerifyClassLoaderDexFiles(soa,
956 class_loader_3,
957 WellKnownClasses::dalvik_system_PathClassLoader,
958 class_loader_3_dex_files);
959 raw_shared_libraries = field->GetObject(class_loader_3.Get());
960 ASSERT_TRUE(raw_shared_libraries == nullptr);
961
962 // Verify the parent.
963 Handle<mirror::ClassLoader> class_loader_4 = hs.NewHandle(class_loader_1->GetParent());
964 std::vector<const DexFile*> class_loader_4_dex_files =
965 MakeNonOwningPointerVector(classpath_dex_d);
966 VerifyClassLoaderDexFiles(soa,
967 class_loader_4,
968 WellKnownClasses::dalvik_system_PathClassLoader,
969 class_loader_4_dex_files);
970 raw_shared_libraries = field->GetObject(class_loader_4.Get());
971 ASSERT_TRUE(raw_shared_libraries == nullptr);
972
973 // Class loaders should have the BootClassLoader as a parent.
974 ASSERT_TRUE(class_loader_2->GetParent()->GetClass() ==
975 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
976 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
977 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
978 ASSERT_TRUE(class_loader_4->GetParent()->GetClass() ==
979 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
980 }
981
TEST_F(ClassLoaderContextTest,RemoveSourceLocations)982 TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
983 std::unique_ptr<ClassLoaderContext> context =
984 ClassLoaderContext::Create("PCL[a.dex]");
985 dchecked_vector<std::string> classpath_dex;
986 classpath_dex.push_back("a.dex");
987 dchecked_vector<std::string> compilation_sources;
988 compilation_sources.push_back("src.dex");
989
990 // Nothing should be removed.
991 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
992 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
993 // Classes should be removed.
994 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
995 VerifyClassLoaderPCL(context.get(), 0, "");
996 }
997
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithSameSharedLibraries)998 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSameSharedLibraries) {
999 // Setup the context.
1000 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
1001 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
1002 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
1003
1004 std::string context_spec =
1005 "PCL[" + CreateClassPath(classpath_dex_a) + "]{" +
1006 "PCL[" + CreateClassPath(classpath_dex_b) + "]};" +
1007 "PCL[" + CreateClassPath(classpath_dex_c) + "]{" +
1008 "PCL[" + CreateClassPath(classpath_dex_b) + "]}";
1009
1010 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
1011 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
1012
1013 // Setup the compilation sources.
1014 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
1015 std::vector<const DexFile*> compilation_sources_raw =
1016 MakeNonOwningPointerVector(compilation_sources);
1017
1018 // Create the class loader.
1019 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
1020 ASSERT_TRUE(jclass_loader != nullptr);
1021
1022 // Verify the class loader.
1023 ScopedObjectAccess soa(Thread::Current());
1024
1025 StackHandleScope<6> hs(soa.Self());
1026 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
1027 soa.Decode<mirror::ClassLoader>(jclass_loader));
1028
1029 // For the first class loader the class path dex files must come first and then the
1030 // compilation sources.
1031 std::vector<const DexFile*> class_loader_1_dex_files =
1032 MakeNonOwningPointerVector(classpath_dex_a);
1033 for (auto& dex : compilation_sources_raw) {
1034 class_loader_1_dex_files.push_back(dex);
1035 }
1036 VerifyClassLoaderDexFiles(soa,
1037 class_loader_1,
1038 WellKnownClasses::dalvik_system_PathClassLoader,
1039 class_loader_1_dex_files);
1040
1041 // Verify its shared library.
1042 ArtField* field =
1043 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
1044 ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader_1.Get());
1045 ASSERT_TRUE(raw_shared_libraries != nullptr);
1046
1047 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries(
1048 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
1049 ASSERT_EQ(shared_libraries->GetLength(), 1);
1050
1051 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(shared_libraries->Get(0));
1052 std::vector<const DexFile*> class_loader_2_dex_files =
1053 MakeNonOwningPointerVector(classpath_dex_b);
1054 VerifyClassLoaderDexFiles(soa,
1055 class_loader_2,
1056 WellKnownClasses::dalvik_system_PathClassLoader,
1057 class_loader_2_dex_files);
1058
1059 // Verify the parent.
1060 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_1->GetParent());
1061 std::vector<const DexFile*> class_loader_3_dex_files =
1062 MakeNonOwningPointerVector(classpath_dex_c);
1063 VerifyClassLoaderDexFiles(soa,
1064 class_loader_3,
1065 WellKnownClasses::dalvik_system_PathClassLoader,
1066 class_loader_3_dex_files);
1067
1068 // Verify its shared library is the same as the child.
1069 raw_shared_libraries = field->GetObject(class_loader_3.Get());
1070 ASSERT_TRUE(raw_shared_libraries != nullptr);
1071 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries_2(
1072 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
1073 ASSERT_EQ(shared_libraries_2->GetLength(), 1);
1074 ASSERT_OBJ_PTR_EQ(shared_libraries_2->Get(0), class_loader_2.Get());
1075
1076 // Class loaders should have the BootClassLoader as a parent.
1077 ASSERT_TRUE(class_loader_2->GetParent()->GetClass() ==
1078 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
1079 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
1080 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
1081 }
1082
TEST_F(ClassLoaderContextTest,EncodeInOatFile)1083 TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
1084 std::string dex1_name = GetTestDexFileName("Main");
1085 std::string dex2_name = GetTestDexFileName("MyClass");
1086 std::unique_ptr<ClassLoaderContext> context =
1087 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
1088 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
1089
1090 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
1091 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
1092 std::string encoding = context->EncodeContextForOatFile("");
1093 std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" +
1094 CreateClassPathWithChecksums(dex2) + "]";
1095 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
1096 }
1097
TEST_F(ClassLoaderContextTest,EncodeInOatFileIMC)1098 TEST_F(ClassLoaderContextTest, EncodeInOatFileIMC) {
1099 jobject class_loader_a = LoadDexInPathClassLoader("Main", nullptr);
1100 jobject class_loader_b = LoadDexInInMemoryDexClassLoader("MyClass", class_loader_a);
1101
1102 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
1103 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
1104
1105 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
1106 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
1107 ASSERT_EQ(dex2.size(), 1u);
1108
1109 std::string encoding = context->EncodeContextForOatFile("");
1110 std::string expected_encoding = "IMC[<unknown>*" + std::to_string(dex2[0]->GetLocationChecksum())
1111 + "];PCL[" + CreateClassPathWithChecksums(dex1) + "]";
1112 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
1113 }
1114
TEST_F(ClassLoaderContextTest,EncodeForDex2oat)1115 TEST_F(ClassLoaderContextTest, EncodeForDex2oat) {
1116 std::string dex1_name = GetTestDexFileName("Main");
1117 std::string dex2_name = GetTestDexFileName("MultiDex");
1118 std::unique_ptr<ClassLoaderContext> context =
1119 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
1120 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
1121
1122 std::string encoding = context->EncodeContextForDex2oat("");
1123 std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]";
1124 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
1125 }
1126
TEST_F(ClassLoaderContextTest,EncodeForDex2oatIMC)1127 TEST_F(ClassLoaderContextTest, EncodeForDex2oatIMC) {
1128 jobject class_loader_a = LoadDexInPathClassLoader("Main", nullptr);
1129 jobject class_loader_b = LoadDexInInMemoryDexClassLoader("MyClass", class_loader_a);
1130
1131 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
1132 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
1133
1134 std::string encoding = context->EncodeContextForDex2oat("");
1135 std::string expected_encoding = "IMC[<unknown>];PCL[" + GetTestDexFileName("Main") + "]";
1136 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
1137 }
1138
TEST_F(ClassLoaderContextTest,EncodeContextsSinglePath)1139 TEST_F(ClassLoaderContextTest, EncodeContextsSinglePath) {
1140 jobject class_loader = LoadDexInPathClassLoader("Main", nullptr);
1141 std::unique_ptr<ClassLoaderContext> context =
1142 CreateContextForClassLoader(class_loader);
1143
1144 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1145 ASSERT_EQ(1u, encodings.size());
1146 ASSERT_EQ("PCL[]", encodings.at(GetTestDexFileName("Main")));
1147 }
1148
TEST_F(ClassLoaderContextTest,EncodeContextsMultiDex)1149 TEST_F(ClassLoaderContextTest, EncodeContextsMultiDex) {
1150 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
1151 std::unique_ptr<ClassLoaderContext> context =
1152 CreateContextForClassLoader(class_loader);
1153
1154 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1155 ASSERT_EQ(1u, encodings.size());
1156 ASSERT_EQ("PCL[]", encodings.at(GetTestDexFileName("MultiDex")));
1157 }
1158
TEST_F(ClassLoaderContextTest,EncodeContextsRepeatedMultiDex)1159 TEST_F(ClassLoaderContextTest, EncodeContextsRepeatedMultiDex) {
1160 jobject top_class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
1161 jobject middle_class_loader =
1162 LoadDexInPathClassLoader("Main", top_class_loader);
1163 jobject bottom_class_loader =
1164 LoadDexInPathClassLoader("MultiDex", middle_class_loader);
1165 std::unique_ptr<ClassLoaderContext> context =
1166 CreateContextForClassLoader(bottom_class_loader);
1167
1168 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1169 ASSERT_EQ(1u, encodings.size());
1170
1171 std::string main_dex_name = GetTestDexFileName("Main");
1172 std::string multidex_dex_name = GetTestDexFileName("MultiDex");
1173 ASSERT_EQ(
1174 "PCL[];PCL[" + main_dex_name + "];PCL[" + multidex_dex_name + "]",
1175 encodings.at(multidex_dex_name));
1176 }
1177
TEST_F(ClassLoaderContextTest,EncodeContextsSinglePathWithShared)1178 TEST_F(ClassLoaderContextTest, EncodeContextsSinglePathWithShared) {
1179 jobject class_loader_a = LoadDexInPathClassLoader("MyClass", nullptr);
1180
1181 ScopedObjectAccess soa(Thread::Current());
1182 StackHandleScope<1> hs(soa.Self());
1183 Handle<mirror::ObjectArray<mirror::ClassLoader>> libraries = hs.NewHandle(
1184 mirror::ObjectArray<mirror::ClassLoader>::Alloc(
1185 soa.Self(),
1186 GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
1187 1));
1188 libraries->Set(0, soa.Decode<mirror::ClassLoader>(class_loader_a));
1189
1190 jobject class_loader_b = LoadDexInPathClassLoader(
1191 "Main", nullptr, soa.AddLocalReference<jobject>(libraries.Get()));
1192
1193 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
1194
1195 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1196 ASSERT_EQ(1u, encodings.size());
1197 ASSERT_EQ(
1198 "PCL[]{PCL[" + GetTestDexFileName("MyClass") + "]}",
1199 encodings.at(GetTestDexFileName("Main")));
1200 }
1201
TEST_F(ClassLoaderContextTest,EncodeContextsMultiplePaths)1202 TEST_F(ClassLoaderContextTest, EncodeContextsMultiplePaths) {
1203 jobject class_loader = LoadDexInPathClassLoader(
1204 std::vector<std::string>{ "Main", "MultiDex"}, nullptr);
1205
1206 std::unique_ptr<ClassLoaderContext> context =
1207 CreateContextForClassLoader(class_loader);
1208
1209 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1210 ASSERT_EQ(2u, encodings.size());
1211 ASSERT_EQ("PCL[]", encodings.at(GetTestDexFileName("Main")));
1212 ASSERT_EQ(
1213 "PCL[" + GetTestDexFileName("Main") + "]", encodings.at(GetTestDexFileName("MultiDex")));
1214 }
1215
TEST_F(ClassLoaderContextTest,EncodeContextsMultiplePathsWithShared)1216 TEST_F(ClassLoaderContextTest, EncodeContextsMultiplePathsWithShared) {
1217 jobject class_loader_a = LoadDexInPathClassLoader("MyClass", nullptr);
1218
1219 ScopedObjectAccess soa(Thread::Current());
1220 StackHandleScope<1> hs(soa.Self());
1221 Handle<mirror::ObjectArray<mirror::ClassLoader>> libraries = hs.NewHandle(
1222 mirror::ObjectArray<mirror::ClassLoader>::Alloc(
1223 soa.Self(),
1224 GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
1225 1));
1226 libraries->Set(0, soa.Decode<mirror::ClassLoader>(class_loader_a));
1227
1228 jobject class_loader_b = LoadDexInPathClassLoader(
1229 std::vector<std::string> { "Main", "MultiDex" },
1230 nullptr, soa.AddLocalReference<jobject>(libraries.Get()));
1231
1232 std::unique_ptr<ClassLoaderContext> context =
1233 CreateContextForClassLoader(class_loader_b);
1234
1235 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1236 ASSERT_EQ(2u, encodings.size());
1237 const std::string context_suffix =
1238 "{PCL[" + GetTestDexFileName("MyClass") + "]}";
1239 ASSERT_EQ("PCL[]" + context_suffix, encodings.at(GetTestDexFileName("Main")));
1240 ASSERT_EQ(
1241 "PCL[" + GetTestDexFileName("Main") + "]" + context_suffix,
1242 encodings.at(GetTestDexFileName("MultiDex")));
1243 }
1244
TEST_F(ClassLoaderContextTest,EncodeContextsIMC)1245 TEST_F(ClassLoaderContextTest, EncodeContextsIMC) {
1246 jobject class_loader_a = LoadDexInPathClassLoader("Main", nullptr);
1247 jobject class_loader_b =
1248 LoadDexInInMemoryDexClassLoader("MyClass", class_loader_a);
1249
1250 std::unique_ptr<ClassLoaderContext> context =
1251 CreateContextForClassLoader(class_loader_b);
1252
1253 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1254 ASSERT_EQ(1u, encodings.size());
1255 ASSERT_EQ(
1256 "IMC[];PCL[" + GetTestDexFileName("Main") + "]",
1257 encodings.at("<unknown>"));
1258 }
1259
TEST_F(ClassLoaderContextTest,EncodeContextsForSingleDex)1260 TEST_F(ClassLoaderContextTest, EncodeContextsForSingleDex) {
1261 jobject class_loader = LoadDexInPathClassLoader("Main", nullptr);
1262 std::map<std::string, std::string> encodings =
1263 ClassLoaderContext::EncodeClassPathContextsForClassLoader(class_loader);
1264 ASSERT_EQ(1u, encodings.size());
1265 ASSERT_EQ("PCL[]", encodings.at(GetTestDexFileName("Main")));
1266 }
1267
CreateForeignClassLoader()1268 static jobject CreateForeignClassLoader() {
1269 ScopedObjectAccess soa(Thread::Current());
1270 JNIEnv* env = soa.Env();
1271
1272 // We cannot instantiate a ClassLoader directly, so instead we allocate an Object to represent
1273 // our foreign ClassLoader (this works because the runtime does proper instanceof checks before
1274 // operating on this object.
1275 jmethodID ctor = env->GetMethodID(WellKnownClasses::java_lang_Object, "<init>", "()V");
1276 return env->NewObject(WellKnownClasses::java_lang_Object, ctor);
1277 }
1278
TEST_F(ClassLoaderContextTest,EncodeContextsForUnsupportedBase)1279 TEST_F(ClassLoaderContextTest, EncodeContextsForUnsupportedBase) {
1280 std::map<std::string, std::string> empty;
1281 ASSERT_EQ(
1282 empty, ClassLoaderContext::EncodeClassPathContextsForClassLoader(CreateForeignClassLoader()));
1283 }
1284
TEST_F(ClassLoaderContextTest,EncodeContextsForUnsupportedChain)1285 TEST_F(ClassLoaderContextTest, EncodeContextsForUnsupportedChain) {
1286 jobject class_loader = LoadDexInPathClassLoader("Main", CreateForeignClassLoader());
1287 std::map<std::string, std::string> encodings =
1288 ClassLoaderContext::EncodeClassPathContextsForClassLoader(class_loader);
1289 ASSERT_EQ(1u, encodings.size());
1290 ASSERT_EQ(
1291 ClassLoaderContext::kUnsupportedClassLoaderContextEncoding,
1292 encodings.at(GetTestDexFileName("Main")));
1293 }
1294
TEST_F(ClassLoaderContextTest,EncodeContextsForUnsupportedChainMultiPath)1295 TEST_F(ClassLoaderContextTest, EncodeContextsForUnsupportedChainMultiPath) {
1296 jobject class_loader = LoadDexInPathClassLoader(std::vector<std::string> { "Main", "MyClass" },
1297 CreateForeignClassLoader());
1298 std::map<std::string, std::string> encodings =
1299 ClassLoaderContext::EncodeClassPathContextsForClassLoader(class_loader);
1300 ASSERT_EQ(2u, encodings.size());
1301 ASSERT_EQ(
1302 ClassLoaderContext::kUnsupportedClassLoaderContextEncoding,
1303 encodings.at(GetTestDexFileName("Main")));
1304 ASSERT_EQ(
1305 ClassLoaderContext::kUnsupportedClassLoaderContextEncoding,
1306 encodings.at(GetTestDexFileName("MyClass")));
1307 }
1308
TEST_F(ClassLoaderContextTest,EncodeContextsForUnsupportedChainMultiDex)1309 TEST_F(ClassLoaderContextTest, EncodeContextsForUnsupportedChainMultiDex) {
1310 jobject class_loader = LoadDexInPathClassLoader("MultiDex", CreateForeignClassLoader());
1311 std::map<std::string, std::string> encodings =
1312 ClassLoaderContext::EncodeClassPathContextsForClassLoader(class_loader);
1313 ASSERT_EQ(1u, encodings.size());
1314 ASSERT_EQ(
1315 ClassLoaderContext::kUnsupportedClassLoaderContextEncoding,
1316 encodings.at(GetTestDexFileName("MultiDex")));
1317 }
1318
TEST_F(ClassLoaderContextTest,IsValidEncoding)1319 TEST_F(ClassLoaderContextTest, IsValidEncoding) {
1320 ASSERT_TRUE(ClassLoaderContext::IsValidEncoding("PCL[]"));
1321 ASSERT_TRUE(ClassLoaderContext::IsValidEncoding("PCL[foo.dex]"));
1322 ASSERT_TRUE(ClassLoaderContext::IsValidEncoding("PCL[foo.dex];PCL[bar.dex]"));
1323 ASSERT_TRUE(ClassLoaderContext::IsValidEncoding("DLC[];PCL[bar.dex]"));
1324 ASSERT_TRUE(
1325 ClassLoaderContext::IsValidEncoding(
1326 ClassLoaderContext::kUnsupportedClassLoaderContextEncoding));
1327 ASSERT_FALSE(ClassLoaderContext::IsValidEncoding("not_valid"));
1328 ASSERT_FALSE(ClassLoaderContext::IsValidEncoding("[]"));
1329 ASSERT_FALSE(ClassLoaderContext::IsValidEncoding("FCL[]"));
1330 ASSERT_FALSE(ClassLoaderContext::IsValidEncoding("foo.dex:bar.dex"));
1331 }
1332
1333 // TODO(calin) add a test which creates the context for a class loader together with dex_elements.
TEST_F(ClassLoaderContextTest,CreateContextForClassLoader)1334 TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
1335 // The chain is
1336 // ClassLoaderA (PathClassLoader)
1337 // ^
1338 // |
1339 // ClassLoaderB (DelegateLastClassLoader)
1340 // ^
1341 // |
1342 // ClassLoaderC (PathClassLoader)
1343 // ^
1344 // |
1345 // ClassLoaderD (DelegateLastClassLoader)
1346
1347 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1348 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
1349 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
1350 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
1351
1352 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
1353
1354 VerifyContextForClassLoader(context.get());
1355 VerifyContextSize(context.get(), 4);
1356
1357 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
1358 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
1359 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
1360 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
1361 }
1362
TEST_F(ClassLoaderContextTest,CreateContextForClassLoaderIMC)1363 TEST_F(ClassLoaderContextTest, CreateContextForClassLoaderIMC) {
1364 // The chain is
1365 // ClassLoaderA (PathClassLoader)
1366 // ^
1367 // |
1368 // ClassLoaderB (InMemoryDexClassLoader)
1369 // ^
1370 // |
1371 // ClassLoaderC (InMemoryDexClassLoader)
1372 // ^
1373 // |
1374 // ClassLoaderD (DelegateLastClassLoader)
1375
1376 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1377 jobject class_loader_b = LoadDexInInMemoryDexClassLoader("ForClassLoaderB", class_loader_a);
1378 jobject class_loader_c = LoadDexInInMemoryDexClassLoader("ForClassLoaderC", class_loader_b);
1379 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
1380
1381 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
1382
1383 VerifyContextForClassLoader(context.get());
1384 VerifyContextSize(context.get(), 4);
1385
1386 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
1387 VerifyClassLoaderIMCFromTestDex(context.get(), 1, "ForClassLoaderC");
1388 VerifyClassLoaderIMCFromTestDex(context.get(), 2, "ForClassLoaderB");
1389 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
1390 }
1391
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextFirstElement)1392 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextFirstElement) {
1393 std::string context_spec = "PCL[]";
1394 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
1395 ASSERT_TRUE(context != nullptr);
1396 PretendContextOpenedDexFiles(context.get());
1397 // Ensure that the special shared library marks as verified for the first thing in the class path.
1398 ASSERT_EQ(context->VerifyClassLoaderContextMatch(OatFile::kSpecialSharedLibrary),
1399 ClassLoaderContext::VerificationResult::kVerifies);
1400 }
1401
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatch)1402 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
1403 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
1404 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
1405 // Pretend that we successfully open the dex files to pass the DCHECKS.
1406 // (as it's much easier to test all the corner cases without relying on actual dex files).
1407 PretendContextOpenedDexFiles(context.get());
1408
1409 VerifyContextSize(context.get(), 2);
1410 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
1411 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
1412
1413 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec),
1414 ClassLoaderContext::VerificationResult::kVerifies);
1415
1416 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
1417 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_class_loader_type),
1418 ClassLoaderContext::VerificationResult::kMismatch);
1419
1420 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
1421 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_class_loader_order),
1422 ClassLoaderContext::VerificationResult::kMismatch);
1423
1424 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
1425 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_classpath_order),
1426 ClassLoaderContext::VerificationResult::kMismatch);
1427
1428 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
1429 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_checksum),
1430 ClassLoaderContext::VerificationResult::kMismatch);
1431
1432 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
1433 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader),
1434 ClassLoaderContext::VerificationResult::kMismatch);
1435
1436 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
1437 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_extra_classpath),
1438 ClassLoaderContext::VerificationResult::kMismatch);
1439
1440 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
1441 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_spec),
1442 ClassLoaderContext::VerificationResult::kMismatch);
1443 }
1444
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextWithIMCMatch)1445 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextWithIMCMatch) {
1446 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];IMC[<unknown>*111]";
1447 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
1448 // Pretend that we successfully open the dex files to pass the DCHECKS.
1449 // (as it's much easier to test all the corner cases without relying on actual dex files).
1450 PretendContextOpenedDexFiles(context.get());
1451
1452 VerifyContextSize(context.get(), 3);
1453 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
1454 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
1455 VerifyClassLoaderIMC(context.get(), 2, "<unknown>");
1456
1457 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec),
1458 ClassLoaderContext::VerificationResult::kVerifies);
1459 }
1460
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchSpecial)1461 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchSpecial) {
1462 std::string context_spec = "&";
1463 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
1464 // Pretend that we successfully open the dex files to pass the DCHECKS.
1465 // (as it's much easier to test all the corner cases without relying on actual dex files).
1466 PretendContextOpenedDexFiles(context.get());
1467
1468 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec),
1469 ClassLoaderContext::VerificationResult::kForcedToSkipChecks);
1470 }
1471
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchWithSL)1472 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchWithSL) {
1473 std::string context_spec =
1474 "PCL[a.dex*123:b.dex*456]{PCL[d.dex*321];PCL[e.dex*654]#PCL[f.dex*098:g.dex*999]}"
1475 ";DLC[c.dex*890]";
1476 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
1477 // Pretend that we successfully open the dex files to pass the DCHECKS.
1478 // (as it's much easier to test all the corner cases without relying on actual dex files).
1479 PretendContextOpenedDexFiles(context.get());
1480
1481 VerifyContextSize(context.get(), 2);
1482 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
1483 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
1484 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "d.dex");
1485 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 1, "f.dex:g.dex");
1486
1487 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec),
1488 ClassLoaderContext::VerificationResult::kVerifies);
1489
1490 std::string wrong_class_loader_type =
1491 "PCL[a.dex*123:b.dex*456]{DLC[d.dex*321];PCL[e.dex*654]#PCL[f.dex*098:g.dex*999]}"
1492 ";DLC[c.dex*890]";
1493 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_class_loader_type),
1494 ClassLoaderContext::VerificationResult::kMismatch);
1495
1496 std::string wrong_class_loader_order =
1497 "PCL[a.dex*123:b.dex*456]{PCL[f.dex#098:g.dex#999}#PCL[d.dex*321];PCL[e.dex*654]}"
1498 ";DLC[c.dex*890]";
1499 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_class_loader_order),
1500 ClassLoaderContext::VerificationResult::kMismatch);
1501
1502 std::string wrong_classpath_order =
1503 "PCL[a.dex*123:b.dex*456]{PCL[d.dex*321];PCL[e.dex*654]#PCL[g.dex*999:f.dex*098]}"
1504 ";DLC[c.dex*890]";
1505 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_classpath_order),
1506 ClassLoaderContext::VerificationResult::kMismatch);
1507
1508 std::string wrong_checksum =
1509 "PCL[a.dex*123:b.dex*456]{PCL[d.dex*333];PCL[e.dex*654]#PCL[g.dex*999:f.dex*098]}"
1510 ";DLC[c.dex*890]";
1511 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_checksum),
1512 ClassLoaderContext::VerificationResult::kMismatch);
1513
1514 std::string wrong_extra_class_loader =
1515 "PCL[a.dex*123:b.dex*456]"
1516 "{PCL[d.dex*321];PCL[e.dex*654]#PCL[f.dex*098:g.dex*999];PCL[i.dex#444]}"
1517 ";DLC[c.dex*890]";
1518 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader),
1519 ClassLoaderContext::VerificationResult::kMismatch);
1520
1521 std::string wrong_extra_classpath =
1522 "PCL[a.dex*123:b.dex*456]{PCL[d.dex*321:i.dex#444];PCL[e.dex*654]#PCL[f.dex*098:g.dex*999]}"
1523 ";DLC[c.dex*890]";
1524 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_extra_classpath),
1525 ClassLoaderContext::VerificationResult::kMismatch);
1526 }
1527
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchWithIMCSL)1528 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchWithIMCSL) {
1529 std::string context_spec =
1530 "IMC[<unknown>*123:<unknown>*456]"
1531 "{IMC[<unknown>*321];IMC[<unknown>*654]#IMC[<unknown>*098:<unknown>*999]};"
1532 "DLC[c.dex*890]";
1533 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
1534 // Pretend that we successfully open the dex files to pass the DCHECKS.
1535 // (as it's much easier to test all the corner cases without relying on actual dex files).
1536 PretendContextOpenedDexFiles(context.get());
1537
1538 VerifyContextSize(context.get(), 2);
1539 VerifyClassLoaderIMC(context.get(), 0, "<unknown>:<unknown>");
1540 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
1541 VerifyClassLoaderSharedLibraryIMC(context.get(), 0, 0, "<unknown>");
1542 VerifyClassLoaderSharedLibraryIMC(context.get(), 0, 1, "<unknown>:<unknown>");
1543
1544 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec),
1545 ClassLoaderContext::VerificationResult::kVerifies);
1546 }
1547
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchAfterEncoding)1548 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
1549 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1550 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
1551 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
1552 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
1553
1554 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
1555
1556 std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
1557 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_no_base_dir),
1558 ClassLoaderContext::VerificationResult::kVerifies);
1559
1560 std::string dex_location = GetTestDexFileName("ForClassLoaderA");
1561 size_t pos = dex_location.rfind('/');
1562 ASSERT_NE(std::string::npos, pos);
1563 std::string parent = dex_location.substr(0, pos);
1564
1565 std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
1566 ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
1567 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_base_dir),
1568 ClassLoaderContext::VerificationResult::kVerifies);
1569 }
1570
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchAfterEncodingIMC)1571 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingIMC) {
1572 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1573 jobject class_loader_b = LoadDexInInMemoryDexClassLoader("ForClassLoaderB", class_loader_a);
1574 jobject class_loader_c = LoadDexInInMemoryDexClassLoader("ForClassLoaderC", class_loader_b);
1575 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
1576
1577 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
1578
1579 std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
1580 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_no_base_dir),
1581 ClassLoaderContext::VerificationResult::kVerifies);
1582
1583 std::string dex_location = GetTestDexFileName("ForClassLoaderA");
1584 size_t pos = dex_location.rfind('/');
1585 ASSERT_NE(std::string::npos, pos);
1586 std::string parent = dex_location.substr(0, pos);
1587
1588 std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
1589 ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
1590 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_base_dir),
1591 ClassLoaderContext::VerificationResult::kVerifies);
1592 }
1593
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchAfterEncodingMultidex)1594 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) {
1595 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
1596
1597 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
1598
1599 std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
1600 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_no_base_dir),
1601 ClassLoaderContext::VerificationResult::kVerifies);
1602
1603 std::string dex_location = GetTestDexFileName("MultiDex");
1604 size_t pos = dex_location.rfind('/');
1605 ASSERT_NE(std::string::npos, pos);
1606 std::string parent = dex_location.substr(0, pos);
1607
1608 std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
1609 ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
1610 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_base_dir),
1611 ClassLoaderContext::VerificationResult::kVerifies);
1612 }
1613
TEST_F(ClassLoaderContextTest,CreateContextForClassLoaderWithSharedLibraries)1614 TEST_F(ClassLoaderContextTest, CreateContextForClassLoaderWithSharedLibraries) {
1615 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1616
1617 ScopedObjectAccess soa(Thread::Current());
1618 StackHandleScope<1> hs(soa.Self());
1619 Handle<mirror::ObjectArray<mirror::ClassLoader>> libraries = hs.NewHandle(
1620 mirror::ObjectArray<mirror::ClassLoader>::Alloc(
1621 soa.Self(),
1622 GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
1623 1));
1624 libraries->Set(0, soa.Decode<mirror::ClassLoader>(class_loader_a));
1625
1626 jobject class_loader_b = LoadDexInPathClassLoader(
1627 "ForClassLoaderB", nullptr, soa.AddLocalReference<jobject>(libraries.Get()));
1628
1629 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
1630 ASSERT_TRUE(context != nullptr);
1631 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ForClassLoaderB");
1632 VerifyClassLoaderPCL(context.get(), 0, dex_files[0]->GetLocation());
1633 dex_files = OpenTestDexFiles("ForClassLoaderA");
1634 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, dex_files[0]->GetLocation());
1635
1636 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")),
1637 ClassLoaderContext::VerificationResult::kVerifies);
1638 }
1639
TEST_F(ClassLoaderContextTest,CheckForDuplicateDexFilesNotFoundSingleCL)1640 TEST_F(ClassLoaderContextTest, CheckForDuplicateDexFilesNotFoundSingleCL) {
1641 jobject class_loader = LoadDexInPathClassLoader("Main", nullptr);
1642
1643 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
1644
1645 std::set<const DexFile*> result = context->CheckForDuplicateDexFiles(
1646 std::vector<const DexFile*>());
1647 ASSERT_EQ(0u, result.size());
1648
1649 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("ForClassLoaderA");
1650 std::vector<const DexFile*> dex1_raw = MakeNonOwningPointerVector(dex1);
1651 result = context->CheckForDuplicateDexFiles(dex1_raw);
1652 ASSERT_EQ(0u, result.size());
1653 }
1654
TEST_F(ClassLoaderContextTest,CheckForDuplicateDexFilesFound)1655 TEST_F(ClassLoaderContextTest, CheckForDuplicateDexFilesFound) {
1656 jobject class_loader = LoadDexInPathClassLoader(std::vector<std::string> { "Main", "Main" }, nullptr);
1657
1658 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
1659
1660 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
1661 std::vector<const DexFile*> dex1_raw = MakeNonOwningPointerVector(dex1);
1662 std::set<const DexFile*> result = context->CheckForDuplicateDexFiles(dex1_raw);
1663 ASSERT_EQ(1u, result.size()) << context->EncodeContextForOatFile("");
1664 ASSERT_EQ(dex1_raw[0], *(result.begin()));
1665 }
1666
1667
TEST_F(ClassLoaderContextTest,CheckForDuplicateCrossCLNotFound)1668 TEST_F(ClassLoaderContextTest, CheckForDuplicateCrossCLNotFound) {
1669 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1670 jobject class_loader_b = LoadDexInInMemoryDexClassLoader("ForClassLoaderB", class_loader_a);
1671
1672 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
1673
1674 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("ForClassLoaderA");
1675 std::vector<const DexFile*> dex1_raw = MakeNonOwningPointerVector(dex1);
1676 std::set<const DexFile*> result = context->CheckForDuplicateDexFiles(dex1_raw);
1677 ASSERT_EQ(0u, result.size());
1678 }
1679
1680 } // namespace art
1681