xref: /aosp_15_r20/system/apex/apexd/apex_classpath_test.cpp (revision 33f3758387333dbd2962d7edbd98681940d895da)
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