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)33 TEST_F(OatFileTest, ResolveRelativeEncodedDexLocation) {
34   EXPECT_EQ(std::string("/data/app/foo/base.apk"),
35       OatFile::ResolveRelativeEncodedDexLocation(
36         nullptr, "/data/app/foo/base.apk"));
37 
38   EXPECT_EQ(std::string("/system/framework/base.apk"),
39       OatFile::ResolveRelativeEncodedDexLocation(
40         "/data/app/foo/base.apk", "/system/framework/base.apk"));
41 
42   EXPECT_EQ(std::string("/data/app/foo/base.apk"),
43       OatFile::ResolveRelativeEncodedDexLocation(
44         "/data/app/foo/base.apk", "base.apk"));
45 
46   EXPECT_EQ(std::string("/data/app/foo/base.apk"),
47       OatFile::ResolveRelativeEncodedDexLocation(
48         "/data/app/foo/base.apk", "foo/base.apk"));
49 
50   EXPECT_EQ(std::string("/data/app/foo/base.apk!classes2.dex"),
51       OatFile::ResolveRelativeEncodedDexLocation(
52         "/data/app/foo/base.apk", "base.apk!classes2.dex"));
53 
54   EXPECT_EQ(std::string("/data/app/foo/base.apk!classes11.dex"),
55       OatFile::ResolveRelativeEncodedDexLocation(
56         "/data/app/foo/base.apk", "base.apk!classes11.dex"));
57 
58   EXPECT_EQ(std::string("base.apk"),
59       OatFile::ResolveRelativeEncodedDexLocation(
60         "/data/app/foo/sludge.apk", "base.apk"));
61 
62   EXPECT_EQ(std::string("o/base.apk"),
63       OatFile::ResolveRelativeEncodedDexLocation(
64         "/data/app/foo/base.apk", "o/base.apk"));
65 }
66 
TEST_F(OatFileTest,LoadOat)67 TEST_F(OatFileTest, LoadOat) {
68   std::string dex_location = GetScratchDir() + "/LoadOat.jar";
69 
70   Copy(GetDexSrc1(), dex_location);
71   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
72 
73   std::string oat_location;
74   std::string error_msg;
75   ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
76         dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
77   std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
78                                                    oat_location.c_str(),
79                                                    oat_location.c_str(),
80                                                    nullptr,
81                                                    nullptr,
82                                                    false,
83                                                    /*low_4gb*/false,
84                                                    dex_location.c_str(),
85                                                    &error_msg));
86   ASSERT_TRUE(odex_file.get() != nullptr);
87 
88   // Check that the vdex file was loaded in the reserved space of odex file.
89   EXPECT_EQ(odex_file->GetVdexFile()->Begin(), odex_file->VdexBegin());
90 }
91 
TEST_F(OatFileTest,ChangingMultiDexUncompressed)92 TEST_F(OatFileTest, ChangingMultiDexUncompressed) {
93   std::string dex_location = GetScratchDir() + "/MultiDexUncompressed.jar";
94 
95   Copy(GetTestDexFileName("MultiDexUncompressed"), dex_location);
96   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
97 
98   std::string oat_location;
99   std::string error_msg;
100   ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
101         dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
102 
103   // Ensure we can load that file. Just a precondition.
104   {
105     std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
106                                                      oat_location.c_str(),
107                                                      oat_location.c_str(),
108                                                      nullptr,
109                                                      nullptr,
110                                                      false,
111                                                      /*low_4gb*/false,
112                                                      dex_location.c_str(),
113                                                      &error_msg));
114     ASSERT_TRUE(odex_file != nullptr);
115     ASSERT_EQ(2u, odex_file->GetOatDexFiles().size());
116   }
117 
118   // Now replace the source.
119   Copy(GetTestDexFileName("MainUncompressed"), dex_location);
120 
121   // And try to load again.
122   std::unique_ptr<OatFile> odex_file(OatFile::Open(/* zip_fd */ -1,
123                                                    oat_location.c_str(),
124                                                    oat_location.c_str(),
125                                                    nullptr,
126                                                    nullptr,
127                                                    false,
128                                                    /*low_4gb*/false,
129                                                    dex_location.c_str(),
130                                                    &error_msg));
131   EXPECT_TRUE(odex_file == nullptr);
132   EXPECT_NE(std::string::npos, error_msg.find("expected 2 uncompressed dex files, but found 1"))
133       << error_msg;
134 }
135 
136 }  // namespace art
137