1 /*
2 * Copyright (C) 2021 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 "apex_classpath.h"
18
19 #include <android-base/file.h>
20 #include <android-base/result-gmock.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23
24 #include <fstream>
25 #include <string>
26
27 namespace android {
28 namespace apex {
29
30 using android::base::WriteStringToFile;
31 using android::base::testing::Ok;
32 using android::base::testing::WithMessage;
33 using ::testing::HasSubstr;
34
TEST(ApexClassPathUnitTest,ParseFromFile)35 TEST(ApexClassPathUnitTest, ParseFromFile) {
36 TemporaryFile output;
37 WriteStringToFile(
38 "export BOOTCLASSPATH /apex/a/jar1:/apex/b/jar2\n"
39 "export SYSTEMSERVERCLASSPATH\n"
40 "export UNEXPECTED /apex/c/\n",
41 output.path);
42 auto result = ClassPath::ParseFromFile(output.path);
43 ASSERT_THAT(result, Ok());
44
45 ASSERT_THAT(result->HasClassPathJars("a"), true);
46 ASSERT_THAT(result->HasClassPathJars("b"), true);
47 ASSERT_THAT(result->HasClassPathJars("c"), true);
48 ASSERT_THAT(result->HasClassPathJars("d"), false);
49 }
50
TEST(ApexClassPathUnitTest,ParseFromFileJarsNotInApex)51 TEST(ApexClassPathUnitTest, ParseFromFileJarsNotInApex) {
52 TemporaryFile output;
53 // We accept jars with regex: /apex/<package-name>/*
54 WriteStringToFile("export BOOTCLASSPATH a:b\n", output.path);
55 auto result = ClassPath::ParseFromFile(output.path);
56 ASSERT_THAT(result, Ok());
57
58 ASSERT_THAT(result->HasClassPathJars("a"), false);
59 ASSERT_THAT(result->HasClassPathJars("b"), false);
60 }
61
TEST(ApexClassPathUnitTest,ParseFromFilePackagesWithSamePrefix)62 TEST(ApexClassPathUnitTest, ParseFromFilePackagesWithSamePrefix) {
63 TemporaryFile output;
64 WriteStringToFile(
65 "export BOOTCLASSPATH /apex/media/:/apex/mediaprovider\n"
66 "export SYSTEMSERVERCLASSPATH /apex/mediafoo/\n",
67 output.path);
68 auto result = ClassPath::ParseFromFile(output.path);
69 ASSERT_THAT(result, Ok());
70
71 ASSERT_THAT(result->HasClassPathJars("media"), true);
72 // "/apex/mediaprovider" did not end with /
73 ASSERT_THAT(result->HasClassPathJars("mediaprovider"), false);
74 // A prefix of an apex name present should not be accepted
75 ASSERT_THAT(result->HasClassPathJars("m"), false);
76 }
77
TEST(ApexClassPathUnitTest,ParseFromFileDoesNotExist)78 TEST(ApexClassPathUnitTest, ParseFromFileDoesNotExist) {
79 auto result = ClassPath::ParseFromFile("/file/does/not/exist");
80 ASSERT_THAT(result, HasError(WithMessage(HasSubstr(
81 "Failed to read classpath info from file"))));
82 }
83
TEST(ApexClassPathUnitTest,ParseFromFileEmptyJars)84 TEST(ApexClassPathUnitTest, ParseFromFileEmptyJars) {
85 TemporaryFile output;
86 WriteStringToFile(
87 "export BOOTCLASSPATH\n"
88 "export SYSTEMSERVERCLASSPATH \n"
89 "export DEX2OATBOOTCLASSPATH \n",
90 output.path);
91 auto result = ClassPath::ParseFromFile(output.path);
92 ASSERT_THAT(result, Ok());
93 }
94
TEST(ApexClassPathUnitTest,DeriveClassPathNoStagedApex)95 TEST(ApexClassPathUnitTest, DeriveClassPathNoStagedApex) {
96 auto result = ClassPath::DeriveClassPath({});
97 ASSERT_THAT(
98 result,
99 HasError(WithMessage(HasSubstr(
100 "Invalid argument: There are no APEX to derive claspath from"))));
101 }
102
TEST(ApexClassPathUnitTest,DeriveClassPathPreferBinaryInStagedApex)103 TEST(ApexClassPathUnitTest, DeriveClassPathPreferBinaryInStagedApex) {
104 // Default location uses provided package name to compose binary path
105 auto result = ClassPath::DeriveClassPath({"/apex/temp@123"}, "different");
106 ASSERT_THAT(result,
107 HasError(WithMessage(HasSubstr(
108 "binary path: /apex/different/bin/derive_classpath"))));
109
110 // When staged apex has same package name, we use that location instead
111 result = ClassPath::DeriveClassPath({"/apex/temp@123"}, "temp");
112 ASSERT_THAT(result,
113 HasError(WithMessage(HasSubstr(
114 "binary path: /apex/temp@123/bin/derive_classpath"))));
115 }
116
117 } // namespace apex
118 } // namespace android
119