1 /*
2  * Copyright (C) 2015 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 "oat_file.h"
18 
19 #include <string>
20 
21 #include <gtest/gtest.h>
22 
23 #include "common_runtime_test.h"
24 #include "dexopt_test.h"
25 #include "scoped_thread_state_change-inl.h"
26 #include "vdex_file.h"
27 
28 namespace art {
29 
30 class OatFileTest : public DexoptTest {
31 };
32 
TEST_F(OatFileTest,ResolveRelativeEncodedDexLocation_NullAbsLocation)33 TEST_F(OatFileTest, ResolveRelativeEncodedDexLocation_NullAbsLocation) {
34   std::string dex_location;
35   std::string dex_file_name;
36   OatFile::ResolveRelativeEncodedDexLocation(nullptr,
37                                              "/data/app/foo/base.apk",
38                                              &dex_location,
39                                              &dex_file_name);
40   ASSERT_EQ("/data/app/foo/base.apk", dex_file_name);
41   ASSERT_EQ("/data/app/foo/base.apk", dex_location);
42 }
43 
TEST_F(OatFileTest,ResolveRelativeEncodedDexLocation_NullAbsLocation_Multidex)44 TEST_F(OatFileTest, ResolveRelativeEncodedDexLocation_NullAbsLocation_Multidex) {
45   std::string dex_location;
46   std::string dex_file_name;
47   OatFile::ResolveRelativeEncodedDexLocation(nullptr,
48                                              "/data/app/foo/base.apk!classes2.dex",
49                                              &dex_location,
50                                              &dex_file_name);
51   ASSERT_EQ("/data/app/foo/base.apk!classes2.dex", dex_file_name);
52   ASSERT_EQ("/data/app/foo/base.apk!classes2.dex", dex_location);
53 }
54 
TEST_F(OatFileTest,ResolveRelativeEncodedDexLocation_RelLocationAbsolute)55 TEST_F(OatFileTest, ResolveRelativeEncodedDexLocation_RelLocationAbsolute) {
56   std::string dex_location;
57   std::string dex_file_name;
58   OatFile::ResolveRelativeEncodedDexLocation("base.apk",
59                                              "/system/framework/base.apk",
60                                              &dex_location,
61                                              &dex_file_name);
62   ASSERT_EQ(kIsTargetBuild ? "/system/framework/base.apk" : "base.apk", dex_file_name);
63   ASSERT_EQ("/system/framework/base.apk", dex_location);
64 }
65 
TEST_F(OatFileTest,ResolveRelativeEncodedDexLocation_BothAbsoluteLocations)66 TEST_F(OatFileTest, ResolveRelativeEncodedDexLocation_BothAbsoluteLocations) {
67   std::string dex_location;
68   std::string dex_file_name;
69   OatFile::ResolveRelativeEncodedDexLocation("/data/app/foo/base.apk",
70                                              "/system/framework/base.apk",
71                                              &dex_location,
72                                              &dex_file_name);
73   ASSERT_EQ(kIsTargetBuild ? "/system/framework/base.apk" : "/data/app/foo/base.apk",
74             dex_file_name);
75   ASSERT_EQ("/system/framework/base.apk", dex_location);
76 }
77 
TEST_F(OatFileTest,ResolveRelativeEncodedDexLocation_RelSuffixOfAbsLocation1)78 TEST_F(OatFileTest, ResolveRelativeEncodedDexLocation_RelSuffixOfAbsLocation1) {
79   std::string dex_location;
80   std::string dex_file_name;
81   OatFile::ResolveRelativeEncodedDexLocation("/data/app/foo/base.apk",
82                                              "base.apk",
83                                              &dex_location,
84                                              &dex_file_name);
85   ASSERT_EQ("/data/app/foo/base.apk", dex_file_name);
86   ASSERT_EQ("/data/app/foo/base.apk", dex_location);
87 }
88 
TEST_F(OatFileTest,ResolveRelativeEncodedDexLocation_RelSuffixOfAbsLocation2)89 TEST_F(OatFileTest, ResolveRelativeEncodedDexLocation_RelSuffixOfAbsLocation2) {
90   std::string dex_location;
91   std::string dex_file_name;
92   OatFile::ResolveRelativeEncodedDexLocation("/data/app/foo/base.apk",
93                                              "foo/base.apk",
94                                              &dex_location,
95                                              &dex_file_name);
96   ASSERT_EQ("/data/app/foo/base.apk", dex_file_name);
97   ASSERT_EQ("/data/app/foo/base.apk", dex_location);
98 }
99 
TEST_F(OatFileTest,ResolveRelativeEncodedDexLocation_RelSuffixOfAbsLocation_Multidex)100 TEST_F(OatFileTest, ResolveRelativeEncodedDexLocation_RelSuffixOfAbsLocation_Multidex) {
101   std::string dex_location;
102   std::string dex_file_name;
103   OatFile::ResolveRelativeEncodedDexLocation("/data/app/foo/base.apk",
104                                              "base.apk!classes11.dex",
105                                              &dex_location,
106                                              &dex_file_name);
107   ASSERT_EQ("/data/app/foo/base.apk!classes11.dex", dex_file_name);
108   ASSERT_EQ("/data/app/foo/base.apk!classes11.dex", dex_location);
109 }
110 
TEST_F(OatFileTest,ResolveRelativeEncodedDexLocation_RelNotSuffixOfAbsLocation1)111 TEST_F(OatFileTest, ResolveRelativeEncodedDexLocation_RelNotSuffixOfAbsLocation1) {
112   std::string dex_location;
113   std::string dex_file_name;
114   OatFile::ResolveRelativeEncodedDexLocation("/data/app/foo/sludge.apk",
115                                              "base.apk!classes2.dex",
116                                              &dex_location,
117                                              &dex_file_name);
118   ASSERT_EQ(kIsTargetBuild ? "base.apk!classes2.dex" : "/data/app/foo/sludge.apk!classes2.dex",
119             dex_file_name);
120   ASSERT_EQ("base.apk!classes2.dex", dex_location);
121 }
122 
TEST_F(OatFileTest,ResolveRelativeEncodedDexLocation_RelNotSuffixOfAbsLocation2)123 TEST_F(OatFileTest, ResolveRelativeEncodedDexLocation_RelNotSuffixOfAbsLocation2) {
124   std::string dex_location;
125   std::string dex_file_name;
126   OatFile::ResolveRelativeEncodedDexLocation("/data/app/foo/sludge.apk",
127                                              "o/base.apk",
128                                              &dex_location,
129                                              &dex_file_name);
130   ASSERT_EQ(kIsTargetBuild ? "o/base.apk" : "/data/app/foo/sludge.apk", dex_file_name);
131   ASSERT_EQ("o/base.apk", dex_location);
132 }
133 
TEST_F(OatFileTest,LoadOat)134 TEST_F(OatFileTest, LoadOat) {
135   std::string dex_location = GetScratchDir() + "/LoadOat.jar";
136 
137   Copy(GetDexSrc1(), dex_location);
138   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
139 
140   std::string oat_location;
141   std::string error_msg;
142   ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
143         dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
144   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/ -1,
145                                                    oat_location.c_str(),
146                                                    oat_location.c_str(),
147                                                    /*executable=*/ false,
148                                                    /*low_4gb=*/ false,
149                                                    dex_location.c_str(),
150                                                    /*reservation=*/ nullptr,
151                                                    &error_msg));
152   ASSERT_TRUE(odex_file.get() != nullptr);
153 
154   // Check that the vdex file was loaded in the reserved space of odex file.
155   EXPECT_EQ(odex_file->GetVdexFile()->Begin(), odex_file->VdexBegin());
156 }
157 
TEST_F(OatFileTest,ChangingMultiDexUncompressed)158 TEST_F(OatFileTest, ChangingMultiDexUncompressed) {
159   std::string dex_location = GetScratchDir() + "/MultiDexUncompressed.jar";
160 
161   Copy(GetTestDexFileName("MultiDexUncompressed"), dex_location);
162   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
163 
164   std::string oat_location;
165   std::string error_msg;
166   ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
167         dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
168 
169   // Ensure we can load that file. Just a precondition.
170   {
171     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/ -1,
172                                                      oat_location.c_str(),
173                                                      oat_location.c_str(),
174                                                      /*executable=*/ false,
175                                                      /*low_4gb=*/ false,
176                                                      dex_location.c_str(),
177                                                      /*reservation=*/ nullptr,
178                                                      &error_msg));
179     ASSERT_TRUE(odex_file != nullptr);
180     ASSERT_EQ(2u, odex_file->GetOatDexFiles().size());
181   }
182 
183   // Now replace the source.
184   Copy(GetTestDexFileName("MainUncompressed"), dex_location);
185 
186   // And try to load again.
187   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/ -1,
188                                                    oat_location,
189                                                    oat_location,
190                                                    /*executable=*/ false,
191                                                    /*low_4gb=*/ false,
192                                                    dex_location.c_str(),
193                                                    /*reservation=*/ nullptr,
194                                                    &error_msg));
195   EXPECT_TRUE(odex_file == nullptr);
196   EXPECT_NE(std::string::npos, error_msg.find("expected 2 uncompressed dex files, but found 1"))
197       << error_msg;
198 }
199 
200 }  // namespace art
201