xref: /aosp_15_r20/art/dex2oat/dex2oat_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include <sys/wait.h>
18*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <algorithm>
21*795d594fSAndroid Build Coastguard Worker #include <iterator>
22*795d594fSAndroid Build Coastguard Worker #include <optional>
23*795d594fSAndroid Build Coastguard Worker #include <regex>
24*795d594fSAndroid Build Coastguard Worker #include <sstream>
25*795d594fSAndroid Build Coastguard Worker #include <string>
26*795d594fSAndroid Build Coastguard Worker #include <vector>
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
29*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
30*795d594fSAndroid Build Coastguard Worker #include "android-base/result-gmock.h"
31*795d594fSAndroid Build Coastguard Worker #include "android-base/result.h"
32*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
33*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set_features.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/mutex-inl.h"
36*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
37*795d594fSAndroid Build Coastguard Worker #include "base/zip_archive.h"
38*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
39*795d594fSAndroid Build Coastguard Worker #include "dex/art_dex_file_loader.h"
40*795d594fSAndroid Build Coastguard Worker #include "dex/base64_test_util.h"
41*795d594fSAndroid Build Coastguard Worker #include "dex/bytecode_utils.h"
42*795d594fSAndroid Build Coastguard Worker #include "dex/class_accessor-inl.h"
43*795d594fSAndroid Build Coastguard Worker #include "dex/code_item_accessors-inl.h"
44*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
45*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_loader.h"
46*795d594fSAndroid Build Coastguard Worker #include "dex2oat_environment_test.h"
47*795d594fSAndroid Build Coastguard Worker #include "gc_root-inl.h"
48*795d594fSAndroid Build Coastguard Worker #include "intern_table-inl.h"
49*795d594fSAndroid Build Coastguard Worker #include "oat/elf_file.h"
50*795d594fSAndroid Build Coastguard Worker #include "oat/elf_file_impl.h"
51*795d594fSAndroid Build Coastguard Worker #include "oat/oat.h"
52*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file.h"
53*795d594fSAndroid Build Coastguard Worker #include "profile/profile_compilation_info.h"
54*795d594fSAndroid Build Coastguard Worker #include "vdex_file.h"
55*795d594fSAndroid Build Coastguard Worker #include "ziparchive/zip_writer.h"
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker namespace art {
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker using ::android::base::Result;
60*795d594fSAndroid Build Coastguard Worker using ::android::base::StringPrintf;
61*795d594fSAndroid Build Coastguard Worker using ::android::base::testing::HasValue;
62*795d594fSAndroid Build Coastguard Worker using ::android::base::testing::Ok;
63*795d594fSAndroid Build Coastguard Worker using ::testing::AssertionFailure;
64*795d594fSAndroid Build Coastguard Worker using ::testing::AssertionResult;
65*795d594fSAndroid Build Coastguard Worker using ::testing::AssertionSuccess;
66*795d594fSAndroid Build Coastguard Worker using ::testing::Ne;
67*795d594fSAndroid Build Coastguard Worker using ::testing::Not;
68*795d594fSAndroid Build Coastguard Worker 
69*795d594fSAndroid Build Coastguard Worker class Dex2oatTest : public Dex2oatEnvironmentTest {
70*795d594fSAndroid Build Coastguard Worker  public:
71*795d594fSAndroid Build Coastguard Worker   enum class Status { kFailCompile, kFailOpenOat, kSuccess };
72*795d594fSAndroid Build Coastguard Worker 
TearDown()73*795d594fSAndroid Build Coastguard Worker   void TearDown() override {
74*795d594fSAndroid Build Coastguard Worker     Dex2oatEnvironmentTest::TearDown();
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker     output_ = "";
77*795d594fSAndroid Build Coastguard Worker   }
78*795d594fSAndroid Build Coastguard Worker 
79*795d594fSAndroid Build Coastguard Worker  protected:
GenerateOdexForTestWithStatus(const std::vector<std::string> & dex_locations,const std::string & odex_location,CompilerFilter::Filter filter,const std::vector<std::string> & extra_args={},bool use_fd=false)80*795d594fSAndroid Build Coastguard Worker   Result<int> GenerateOdexForTestWithStatus(const std::vector<std::string>& dex_locations,
81*795d594fSAndroid Build Coastguard Worker                                             const std::string& odex_location,
82*795d594fSAndroid Build Coastguard Worker                                             CompilerFilter::Filter filter,
83*795d594fSAndroid Build Coastguard Worker                                             const std::vector<std::string>& extra_args = {},
84*795d594fSAndroid Build Coastguard Worker                                             bool use_fd = false) {
85*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<File> oat_file;
86*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> args;
87*795d594fSAndroid Build Coastguard Worker     args.reserve(dex_locations.size() + extra_args.size() + 6);
88*795d594fSAndroid Build Coastguard Worker     // Add dex file args.
89*795d594fSAndroid Build Coastguard Worker     for (const std::string& dex_location : dex_locations) {
90*795d594fSAndroid Build Coastguard Worker       args.push_back("--dex-file=" + dex_location);
91*795d594fSAndroid Build Coastguard Worker     }
92*795d594fSAndroid Build Coastguard Worker     if (use_fd) {
93*795d594fSAndroid Build Coastguard Worker       oat_file.reset(OS::CreateEmptyFile(odex_location.c_str()));
94*795d594fSAndroid Build Coastguard Worker       if (oat_file == nullptr) {
95*795d594fSAndroid Build Coastguard Worker         return ErrnoErrorf("CreateEmptyFile failed on {}", odex_location);
96*795d594fSAndroid Build Coastguard Worker       }
97*795d594fSAndroid Build Coastguard Worker       args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
98*795d594fSAndroid Build Coastguard Worker       args.push_back("--oat-location=" + odex_location);
99*795d594fSAndroid Build Coastguard Worker     } else {
100*795d594fSAndroid Build Coastguard Worker       args.push_back("--oat-file=" + odex_location);
101*795d594fSAndroid Build Coastguard Worker     }
102*795d594fSAndroid Build Coastguard Worker     args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
103*795d594fSAndroid Build Coastguard Worker     args.push_back("--runtime-arg");
104*795d594fSAndroid Build Coastguard Worker     args.push_back("-Xnorelocate");
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker     // Unless otherwise stated, use a small amount of threads, so that potential aborts are
107*795d594fSAndroid Build Coastguard Worker     // shorter. This can be overridden with extra_args.
108*795d594fSAndroid Build Coastguard Worker     args.push_back("-j4");
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker     args.insert(args.end(), extra_args.begin(), extra_args.end());
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker     int status = OR_RETURN(Dex2Oat(args, &output_));
113*795d594fSAndroid Build Coastguard Worker     if (oat_file != nullptr) {
114*795d594fSAndroid Build Coastguard Worker       int fc_errno = oat_file->FlushClose();
115*795d594fSAndroid Build Coastguard Worker       if (fc_errno != 0) {
116*795d594fSAndroid Build Coastguard Worker         return Errorf(
117*795d594fSAndroid Build Coastguard Worker             "Could not flush and close oat file {}: {}", odex_location, strerror(-fc_errno));
118*795d594fSAndroid Build Coastguard Worker       }
119*795d594fSAndroid Build Coastguard Worker     }
120*795d594fSAndroid Build Coastguard Worker     return status;
121*795d594fSAndroid Build Coastguard Worker   }
122*795d594fSAndroid Build Coastguard Worker 
GenerateOdexForTest(const std::string & dex_location,const std::string & odex_location,CompilerFilter::Filter filter,const std::vector<std::string> & extra_args={},Status expect_status=Status::kSuccess,bool use_fd=false,bool use_zip_fd=false)123*795d594fSAndroid Build Coastguard Worker   AssertionResult GenerateOdexForTest(const std::string& dex_location,
124*795d594fSAndroid Build Coastguard Worker                                       const std::string& odex_location,
125*795d594fSAndroid Build Coastguard Worker                                       CompilerFilter::Filter filter,
126*795d594fSAndroid Build Coastguard Worker                                       const std::vector<std::string>& extra_args = {},
127*795d594fSAndroid Build Coastguard Worker                                       Status expect_status = Status::kSuccess,
128*795d594fSAndroid Build Coastguard Worker                                       bool use_fd = false,
129*795d594fSAndroid Build Coastguard Worker                                       bool use_zip_fd = false) WARN_UNUSED {
130*795d594fSAndroid Build Coastguard Worker     return GenerateOdexForTest(dex_location,
131*795d594fSAndroid Build Coastguard Worker                                odex_location,
132*795d594fSAndroid Build Coastguard Worker                                filter,
133*795d594fSAndroid Build Coastguard Worker                                extra_args,
134*795d594fSAndroid Build Coastguard Worker                                expect_status,
135*795d594fSAndroid Build Coastguard Worker                                use_fd,
136*795d594fSAndroid Build Coastguard Worker                                use_zip_fd,
__anon4afa19db0102(const OatFile&) 137*795d594fSAndroid Build Coastguard Worker                                [](const OatFile&) {});
138*795d594fSAndroid Build Coastguard Worker   }
139*795d594fSAndroid Build Coastguard Worker 
140*795d594fSAndroid Build Coastguard Worker   bool test_accepts_odex_file_on_failure = false;
141*795d594fSAndroid Build Coastguard Worker 
142*795d594fSAndroid Build Coastguard Worker   template <typename T>
GenerateOdexForTest(const std::string & dex_location,const std::string & odex_location,CompilerFilter::Filter filter,const std::vector<std::string> & extra_args,Status expect_status,bool use_fd,bool use_zip_fd,T check_oat)143*795d594fSAndroid Build Coastguard Worker   AssertionResult GenerateOdexForTest(const std::string& dex_location,
144*795d594fSAndroid Build Coastguard Worker                                       const std::string& odex_location,
145*795d594fSAndroid Build Coastguard Worker                                       CompilerFilter::Filter filter,
146*795d594fSAndroid Build Coastguard Worker                                       const std::vector<std::string>& extra_args,
147*795d594fSAndroid Build Coastguard Worker                                       Status expect_status,
148*795d594fSAndroid Build Coastguard Worker                                       bool use_fd,
149*795d594fSAndroid Build Coastguard Worker                                       bool use_zip_fd,
150*795d594fSAndroid Build Coastguard Worker                                       T check_oat) WARN_UNUSED {
151*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> dex_locations;
152*795d594fSAndroid Build Coastguard Worker     if (use_zip_fd) {
153*795d594fSAndroid Build Coastguard Worker       std::string loc_arg = "--zip-location=" + dex_location;
154*795d594fSAndroid Build Coastguard Worker       CHECK(std::any_of(extra_args.begin(), extra_args.end(), [&](const std::string& s) {
155*795d594fSAndroid Build Coastguard Worker         return s == loc_arg;
156*795d594fSAndroid Build Coastguard Worker       }));
157*795d594fSAndroid Build Coastguard Worker       CHECK(std::any_of(extra_args.begin(), extra_args.end(), [](const std::string& s) {
158*795d594fSAndroid Build Coastguard Worker         return s.starts_with("--zip-fd=");
159*795d594fSAndroid Build Coastguard Worker       }));
160*795d594fSAndroid Build Coastguard Worker     } else {
161*795d594fSAndroid Build Coastguard Worker       dex_locations.push_back(dex_location);
162*795d594fSAndroid Build Coastguard Worker     }
163*795d594fSAndroid Build Coastguard Worker 
164*795d594fSAndroid Build Coastguard Worker     Result<int> status =
165*795d594fSAndroid Build Coastguard Worker         GenerateOdexForTestWithStatus(dex_locations, odex_location, filter, extra_args, use_fd);
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker     bool success = status.ok() && status.value() == 0;
168*795d594fSAndroid Build Coastguard Worker     if (expect_status != Status::kFailCompile) {
169*795d594fSAndroid Build Coastguard Worker       if (!success) {
170*795d594fSAndroid Build Coastguard Worker         return AssertionFailure() << "Failed to compile odex ("
171*795d594fSAndroid Build Coastguard Worker                                   << (status.ok() ? StringPrintf("status=%d", status.value()) :
172*795d594fSAndroid Build Coastguard Worker                                                     status.error().message())
173*795d594fSAndroid Build Coastguard Worker                                   << "): " << output_;
174*795d594fSAndroid Build Coastguard Worker       }
175*795d594fSAndroid Build Coastguard Worker 
176*795d594fSAndroid Build Coastguard Worker       // Verify the odex file was generated as expected.
177*795d594fSAndroid Build Coastguard Worker       std::string error_msg;
178*795d594fSAndroid Build Coastguard Worker       std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
179*795d594fSAndroid Build Coastguard Worker                                                        odex_location,
180*795d594fSAndroid Build Coastguard Worker                                                        odex_location,
181*795d594fSAndroid Build Coastguard Worker                                                        /*executable=*/false,
182*795d594fSAndroid Build Coastguard Worker                                                        /*low_4gb=*/false,
183*795d594fSAndroid Build Coastguard Worker                                                        dex_location,
184*795d594fSAndroid Build Coastguard Worker                                                        &error_msg));
185*795d594fSAndroid Build Coastguard Worker 
186*795d594fSAndroid Build Coastguard Worker       if (expect_status == Status::kFailOpenOat) {
187*795d594fSAndroid Build Coastguard Worker         return (odex_file == nullptr) ?
188*795d594fSAndroid Build Coastguard Worker                    AssertionSuccess() :
189*795d594fSAndroid Build Coastguard Worker                    AssertionFailure() << "Unexpectedly was able to open odex file";
190*795d594fSAndroid Build Coastguard Worker       }
191*795d594fSAndroid Build Coastguard Worker 
192*795d594fSAndroid Build Coastguard Worker       if (odex_file == nullptr) {
193*795d594fSAndroid Build Coastguard Worker         return AssertionFailure() << "Could not open odex file: " << error_msg;
194*795d594fSAndroid Build Coastguard Worker       }
195*795d594fSAndroid Build Coastguard Worker 
196*795d594fSAndroid Build Coastguard Worker       CheckFilter(filter, odex_file->GetCompilerFilter());
197*795d594fSAndroid Build Coastguard Worker       check_oat(*(odex_file.get()));
198*795d594fSAndroid Build Coastguard Worker     } else {
199*795d594fSAndroid Build Coastguard Worker       if (success) {
200*795d594fSAndroid Build Coastguard Worker         return AssertionFailure() << "Succeeded to compile odex: " << output_;
201*795d594fSAndroid Build Coastguard Worker       }
202*795d594fSAndroid Build Coastguard Worker 
203*795d594fSAndroid Build Coastguard Worker       if (!test_accepts_odex_file_on_failure) {
204*795d594fSAndroid Build Coastguard Worker         // Verify there's no loadable odex file.
205*795d594fSAndroid Build Coastguard Worker         std::string error_msg;
206*795d594fSAndroid Build Coastguard Worker         std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
207*795d594fSAndroid Build Coastguard Worker                                                          odex_location,
208*795d594fSAndroid Build Coastguard Worker                                                          odex_location,
209*795d594fSAndroid Build Coastguard Worker                                                          /*executable=*/false,
210*795d594fSAndroid Build Coastguard Worker                                                          /*low_4gb=*/false,
211*795d594fSAndroid Build Coastguard Worker                                                          dex_location,
212*795d594fSAndroid Build Coastguard Worker                                                          &error_msg));
213*795d594fSAndroid Build Coastguard Worker         if (odex_file != nullptr) {
214*795d594fSAndroid Build Coastguard Worker           return AssertionFailure() << "Could open odex file: " << error_msg;
215*795d594fSAndroid Build Coastguard Worker         }
216*795d594fSAndroid Build Coastguard Worker       }
217*795d594fSAndroid Build Coastguard Worker     }
218*795d594fSAndroid Build Coastguard Worker     return AssertionSuccess();
219*795d594fSAndroid Build Coastguard Worker   }
220*795d594fSAndroid Build Coastguard Worker 
221*795d594fSAndroid Build Coastguard Worker   // Check the input compiler filter against the generated oat file's filter. May be overridden
222*795d594fSAndroid Build Coastguard Worker   // in subclasses when equality is not expected.
CheckFilter(CompilerFilter::Filter expected,CompilerFilter::Filter actual)223*795d594fSAndroid Build Coastguard Worker   virtual void CheckFilter(CompilerFilter::Filter expected, CompilerFilter::Filter actual) {
224*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(expected, actual);
225*795d594fSAndroid Build Coastguard Worker   }
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker   std::string output_ = "";
228*795d594fSAndroid Build Coastguard Worker };
229*795d594fSAndroid Build Coastguard Worker 
230*795d594fSAndroid Build Coastguard Worker // This test class provides an easy way to validate an expected filter which is different
231*795d594fSAndroid Build Coastguard Worker // then the one pass to generate the odex file (compared to adding yet another argument
232*795d594fSAndroid Build Coastguard Worker // to what's already huge test methods).
233*795d594fSAndroid Build Coastguard Worker class Dex2oatWithExpectedFilterTest : public Dex2oatTest {
234*795d594fSAndroid Build Coastguard Worker  protected:
CheckFilter(CompilerFilter::Filter expected,CompilerFilter::Filter actual)235*795d594fSAndroid Build Coastguard Worker   void CheckFilter([[maybe_unused]] CompilerFilter::Filter expected,
236*795d594fSAndroid Build Coastguard Worker                    CompilerFilter::Filter actual) override {
237*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(expected_filter_, actual);
238*795d594fSAndroid Build Coastguard Worker   }
239*795d594fSAndroid Build Coastguard Worker 
240*795d594fSAndroid Build Coastguard Worker   CompilerFilter::Filter expected_filter_;
241*795d594fSAndroid Build Coastguard Worker };
242*795d594fSAndroid Build Coastguard Worker 
243*795d594fSAndroid Build Coastguard Worker class Dex2oatSwapTest : public Dex2oatTest {
244*795d594fSAndroid Build Coastguard Worker  protected:
RunTest(bool use_fd,bool expect_use,const std::vector<std::string> & extra_args={})245*795d594fSAndroid Build Coastguard Worker   void RunTest(bool use_fd, bool expect_use, const std::vector<std::string>& extra_args = {}) {
246*795d594fSAndroid Build Coastguard Worker     std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
247*795d594fSAndroid Build Coastguard Worker     std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
248*795d594fSAndroid Build Coastguard Worker 
249*795d594fSAndroid Build Coastguard Worker     Copy(GetTestDexFileName(), dex_location);
250*795d594fSAndroid Build Coastguard Worker 
251*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> copy(extra_args);
252*795d594fSAndroid Build Coastguard Worker 
253*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<ScratchFile> sf;
254*795d594fSAndroid Build Coastguard Worker     if (use_fd) {
255*795d594fSAndroid Build Coastguard Worker       sf.reset(new ScratchFile());
256*795d594fSAndroid Build Coastguard Worker       copy.push_back(android::base::StringPrintf("--swap-fd=%d", sf->GetFd()));
257*795d594fSAndroid Build Coastguard Worker     } else {
258*795d594fSAndroid Build Coastguard Worker       std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
259*795d594fSAndroid Build Coastguard Worker       copy.push_back("--swap-file=" + swap_location);
260*795d594fSAndroid Build Coastguard Worker     }
261*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, copy));
262*795d594fSAndroid Build Coastguard Worker 
263*795d594fSAndroid Build Coastguard Worker     CheckValidity();
264*795d594fSAndroid Build Coastguard Worker     CheckResult(expect_use);
265*795d594fSAndroid Build Coastguard Worker   }
266*795d594fSAndroid Build Coastguard Worker 
GetTestDexFileName()267*795d594fSAndroid Build Coastguard Worker   virtual std::string GetTestDexFileName() {
268*795d594fSAndroid Build Coastguard Worker     return Dex2oatEnvironmentTest::GetTestDexFileName("VerifierDeps");
269*795d594fSAndroid Build Coastguard Worker   }
270*795d594fSAndroid Build Coastguard Worker 
CheckResult(bool expect_use)271*795d594fSAndroid Build Coastguard Worker   virtual void CheckResult(bool expect_use) {
272*795d594fSAndroid Build Coastguard Worker     if (kIsTargetBuild) {
273*795d594fSAndroid Build Coastguard Worker       CheckTargetResult(expect_use);
274*795d594fSAndroid Build Coastguard Worker     } else {
275*795d594fSAndroid Build Coastguard Worker       CheckHostResult(expect_use);
276*795d594fSAndroid Build Coastguard Worker     }
277*795d594fSAndroid Build Coastguard Worker   }
278*795d594fSAndroid Build Coastguard Worker 
CheckTargetResult(bool expect_use)279*795d594fSAndroid Build Coastguard Worker   virtual void CheckTargetResult([[maybe_unused]] bool expect_use) {
280*795d594fSAndroid Build Coastguard Worker     // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
281*795d594fSAndroid Build Coastguard Worker     //       something for variants with file descriptor where we can control the lifetime of
282*795d594fSAndroid Build Coastguard Worker     //       the swap file and thus take a look at it.
283*795d594fSAndroid Build Coastguard Worker   }
284*795d594fSAndroid Build Coastguard Worker 
CheckHostResult(bool expect_use)285*795d594fSAndroid Build Coastguard Worker   virtual void CheckHostResult(bool expect_use) {
286*795d594fSAndroid Build Coastguard Worker     if (!kIsTargetBuild) {
287*795d594fSAndroid Build Coastguard Worker       if (expect_use) {
288*795d594fSAndroid Build Coastguard Worker         EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
289*795d594fSAndroid Build Coastguard Worker             << output_;
290*795d594fSAndroid Build Coastguard Worker       } else {
291*795d594fSAndroid Build Coastguard Worker         EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
292*795d594fSAndroid Build Coastguard Worker             << output_;
293*795d594fSAndroid Build Coastguard Worker       }
294*795d594fSAndroid Build Coastguard Worker     }
295*795d594fSAndroid Build Coastguard Worker   }
296*795d594fSAndroid Build Coastguard Worker 
297*795d594fSAndroid Build Coastguard Worker   // Check whether the dex2oat run was really successful.
CheckValidity()298*795d594fSAndroid Build Coastguard Worker   virtual void CheckValidity() {
299*795d594fSAndroid Build Coastguard Worker     if (kIsTargetBuild) {
300*795d594fSAndroid Build Coastguard Worker       CheckTargetValidity();
301*795d594fSAndroid Build Coastguard Worker     } else {
302*795d594fSAndroid Build Coastguard Worker       CheckHostValidity();
303*795d594fSAndroid Build Coastguard Worker     }
304*795d594fSAndroid Build Coastguard Worker   }
305*795d594fSAndroid Build Coastguard Worker 
CheckTargetValidity()306*795d594fSAndroid Build Coastguard Worker   virtual void CheckTargetValidity() {
307*795d594fSAndroid Build Coastguard Worker     // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
308*795d594fSAndroid Build Coastguard Worker     //       something for variants with file descriptor where we can control the lifetime of
309*795d594fSAndroid Build Coastguard Worker     //       the swap file and thus take a look at it.
310*795d594fSAndroid Build Coastguard Worker   }
311*795d594fSAndroid Build Coastguard Worker 
312*795d594fSAndroid Build Coastguard Worker   // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
CheckHostValidity()313*795d594fSAndroid Build Coastguard Worker   virtual void CheckHostValidity() {
314*795d594fSAndroid Build Coastguard Worker     EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
315*795d594fSAndroid Build Coastguard Worker   }
316*795d594fSAndroid Build Coastguard Worker };
317*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatSwapTest,DoNotUseSwapDefaultSingleSmall)318*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatSwapTest, DoNotUseSwapDefaultSingleSmall) {
319*795d594fSAndroid Build Coastguard Worker   RunTest(/*use_fd=*/false, /*expect_use=*/false);
320*795d594fSAndroid Build Coastguard Worker   RunTest(/*use_fd=*/true, /*expect_use=*/false);
321*795d594fSAndroid Build Coastguard Worker }
322*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatSwapTest,DoNotUseSwapSingle)323*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatSwapTest, DoNotUseSwapSingle) {
324*795d594fSAndroid Build Coastguard Worker   RunTest(/*use_fd=*/false, /*expect_use=*/false, {"--swap-dex-size-threshold=0"});
325*795d594fSAndroid Build Coastguard Worker   RunTest(/*use_fd=*/true, /*expect_use=*/false, {"--swap-dex-size-threshold=0"});
326*795d594fSAndroid Build Coastguard Worker }
327*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatSwapTest,DoNotUseSwapSmall)328*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatSwapTest, DoNotUseSwapSmall) {
329*795d594fSAndroid Build Coastguard Worker   RunTest(/*use_fd=*/false, /*expect_use=*/false, {"--swap-dex-count-threshold=0"});
330*795d594fSAndroid Build Coastguard Worker   RunTest(/*use_fd=*/true, /*expect_use=*/false, {"--swap-dex-count-threshold=0"});
331*795d594fSAndroid Build Coastguard Worker }
332*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatSwapTest,DoUseSwapSingleSmall)333*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatSwapTest, DoUseSwapSingleSmall) {
334*795d594fSAndroid Build Coastguard Worker   RunTest(/*use_fd=*/false,
335*795d594fSAndroid Build Coastguard Worker           /*expect_use=*/true,
336*795d594fSAndroid Build Coastguard Worker           {"--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0"});
337*795d594fSAndroid Build Coastguard Worker   RunTest(/*use_fd=*/true,
338*795d594fSAndroid Build Coastguard Worker           /*expect_use=*/true,
339*795d594fSAndroid Build Coastguard Worker           {"--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0"});
340*795d594fSAndroid Build Coastguard Worker }
341*795d594fSAndroid Build Coastguard Worker 
342*795d594fSAndroid Build Coastguard Worker class Dex2oatSwapUseTest : public Dex2oatSwapTest {
343*795d594fSAndroid Build Coastguard Worker  protected:
CheckHostResult(bool expect_use)344*795d594fSAndroid Build Coastguard Worker   void CheckHostResult(bool expect_use) override {
345*795d594fSAndroid Build Coastguard Worker     if (!kIsTargetBuild) {
346*795d594fSAndroid Build Coastguard Worker       if (expect_use) {
347*795d594fSAndroid Build Coastguard Worker         EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
348*795d594fSAndroid Build Coastguard Worker             << output_;
349*795d594fSAndroid Build Coastguard Worker       } else {
350*795d594fSAndroid Build Coastguard Worker         EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
351*795d594fSAndroid Build Coastguard Worker             << output_;
352*795d594fSAndroid Build Coastguard Worker       }
353*795d594fSAndroid Build Coastguard Worker     }
354*795d594fSAndroid Build Coastguard Worker   }
355*795d594fSAndroid Build Coastguard Worker 
GetTestDexFileName()356*795d594fSAndroid Build Coastguard Worker   std::string GetTestDexFileName() override {
357*795d594fSAndroid Build Coastguard Worker     // Use Statics as it has a handful of functions.
358*795d594fSAndroid Build Coastguard Worker     return CommonRuntimeTest::GetTestDexFileName("Statics");
359*795d594fSAndroid Build Coastguard Worker   }
360*795d594fSAndroid Build Coastguard Worker 
GrabResult1()361*795d594fSAndroid Build Coastguard Worker   void GrabResult1() {
362*795d594fSAndroid Build Coastguard Worker     if (!kIsTargetBuild) {
363*795d594fSAndroid Build Coastguard Worker       native_alloc_1_ = ParseNativeAlloc();
364*795d594fSAndroid Build Coastguard Worker       swap_1_ = ParseSwap(/*expected=*/false);
365*795d594fSAndroid Build Coastguard Worker     } else {
366*795d594fSAndroid Build Coastguard Worker       native_alloc_1_ = std::numeric_limits<size_t>::max();
367*795d594fSAndroid Build Coastguard Worker       swap_1_ = 0;
368*795d594fSAndroid Build Coastguard Worker     }
369*795d594fSAndroid Build Coastguard Worker   }
370*795d594fSAndroid Build Coastguard Worker 
GrabResult2()371*795d594fSAndroid Build Coastguard Worker   void GrabResult2() {
372*795d594fSAndroid Build Coastguard Worker     if (!kIsTargetBuild) {
373*795d594fSAndroid Build Coastguard Worker       native_alloc_2_ = ParseNativeAlloc();
374*795d594fSAndroid Build Coastguard Worker       swap_2_ = ParseSwap(/*expected=*/true);
375*795d594fSAndroid Build Coastguard Worker     } else {
376*795d594fSAndroid Build Coastguard Worker       native_alloc_2_ = 0;
377*795d594fSAndroid Build Coastguard Worker       swap_2_ = std::numeric_limits<size_t>::max();
378*795d594fSAndroid Build Coastguard Worker     }
379*795d594fSAndroid Build Coastguard Worker   }
380*795d594fSAndroid Build Coastguard Worker 
381*795d594fSAndroid Build Coastguard Worker  private:
ParseNativeAlloc()382*795d594fSAndroid Build Coastguard Worker   size_t ParseNativeAlloc() {
383*795d594fSAndroid Build Coastguard Worker     std::regex native_alloc_regex("dex2oat took.*native alloc=[^ ]+ \\(([0-9]+)B\\)");
384*795d594fSAndroid Build Coastguard Worker     std::smatch native_alloc_match;
385*795d594fSAndroid Build Coastguard Worker     bool found = std::regex_search(output_, native_alloc_match, native_alloc_regex);
386*795d594fSAndroid Build Coastguard Worker     if (!found) {
387*795d594fSAndroid Build Coastguard Worker       EXPECT_TRUE(found);
388*795d594fSAndroid Build Coastguard Worker       return 0;
389*795d594fSAndroid Build Coastguard Worker     }
390*795d594fSAndroid Build Coastguard Worker     if (native_alloc_match.size() != 2U) {
391*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(native_alloc_match.size(), 2U);
392*795d594fSAndroid Build Coastguard Worker       return 0;
393*795d594fSAndroid Build Coastguard Worker     }
394*795d594fSAndroid Build Coastguard Worker 
395*795d594fSAndroid Build Coastguard Worker     std::istringstream stream(native_alloc_match[1].str());
396*795d594fSAndroid Build Coastguard Worker     size_t value;
397*795d594fSAndroid Build Coastguard Worker     stream >> value;
398*795d594fSAndroid Build Coastguard Worker 
399*795d594fSAndroid Build Coastguard Worker     return value;
400*795d594fSAndroid Build Coastguard Worker   }
401*795d594fSAndroid Build Coastguard Worker 
ParseSwap(bool expected)402*795d594fSAndroid Build Coastguard Worker   size_t ParseSwap(bool expected) {
403*795d594fSAndroid Build Coastguard Worker     std::regex swap_regex("dex2oat took[^\\n]+swap=[^ ]+ \\(([0-9]+)B\\)");
404*795d594fSAndroid Build Coastguard Worker     std::smatch swap_match;
405*795d594fSAndroid Build Coastguard Worker     bool found = std::regex_search(output_, swap_match, swap_regex);
406*795d594fSAndroid Build Coastguard Worker     if (found != expected) {
407*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(expected, found);
408*795d594fSAndroid Build Coastguard Worker       return 0;
409*795d594fSAndroid Build Coastguard Worker     }
410*795d594fSAndroid Build Coastguard Worker 
411*795d594fSAndroid Build Coastguard Worker     if (!found) {
412*795d594fSAndroid Build Coastguard Worker       return 0;
413*795d594fSAndroid Build Coastguard Worker     }
414*795d594fSAndroid Build Coastguard Worker 
415*795d594fSAndroid Build Coastguard Worker     if (swap_match.size() != 2U) {
416*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(swap_match.size(), 2U);
417*795d594fSAndroid Build Coastguard Worker       return 0;
418*795d594fSAndroid Build Coastguard Worker     }
419*795d594fSAndroid Build Coastguard Worker 
420*795d594fSAndroid Build Coastguard Worker     std::istringstream stream(swap_match[1].str());
421*795d594fSAndroid Build Coastguard Worker     size_t value;
422*795d594fSAndroid Build Coastguard Worker     stream >> value;
423*795d594fSAndroid Build Coastguard Worker 
424*795d594fSAndroid Build Coastguard Worker     return value;
425*795d594fSAndroid Build Coastguard Worker   }
426*795d594fSAndroid Build Coastguard Worker 
427*795d594fSAndroid Build Coastguard Worker  protected:
428*795d594fSAndroid Build Coastguard Worker   size_t native_alloc_1_;
429*795d594fSAndroid Build Coastguard Worker   size_t native_alloc_2_;
430*795d594fSAndroid Build Coastguard Worker 
431*795d594fSAndroid Build Coastguard Worker   size_t swap_1_;
432*795d594fSAndroid Build Coastguard Worker   size_t swap_2_;
433*795d594fSAndroid Build Coastguard Worker };
434*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatSwapUseTest,CheckSwapUsage)435*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatSwapUseTest, CheckSwapUsage) {
436*795d594fSAndroid Build Coastguard Worker   // Native memory usage isn't correctly tracked when running under ASan.
437*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_MEMORY_TOOL();
438*795d594fSAndroid Build Coastguard Worker 
439*795d594fSAndroid Build Coastguard Worker   // The `native_alloc_2_ >= native_alloc_1_` assertion below may not
440*795d594fSAndroid Build Coastguard Worker   // hold true on some x86 or x86_64 systems; disable this test while we
441*795d594fSAndroid Build Coastguard Worker   // investigate (b/29259363).
442*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_X86();
443*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_X86_64();
444*795d594fSAndroid Build Coastguard Worker 
445*795d594fSAndroid Build Coastguard Worker   RunTest(/*use_fd=*/false,
446*795d594fSAndroid Build Coastguard Worker           /*expect_use=*/false);
447*795d594fSAndroid Build Coastguard Worker   GrabResult1();
448*795d594fSAndroid Build Coastguard Worker   std::string output_1 = output_;
449*795d594fSAndroid Build Coastguard Worker 
450*795d594fSAndroid Build Coastguard Worker   output_ = "";
451*795d594fSAndroid Build Coastguard Worker 
452*795d594fSAndroid Build Coastguard Worker   RunTest(/*use_fd=*/false,
453*795d594fSAndroid Build Coastguard Worker           /*expect_use=*/true,
454*795d594fSAndroid Build Coastguard Worker           {"--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0"});
455*795d594fSAndroid Build Coastguard Worker   GrabResult2();
456*795d594fSAndroid Build Coastguard Worker   std::string output_2 = output_;
457*795d594fSAndroid Build Coastguard Worker 
458*795d594fSAndroid Build Coastguard Worker   if (native_alloc_2_ >= native_alloc_1_ || swap_1_ >= swap_2_) {
459*795d594fSAndroid Build Coastguard Worker     EXPECT_LT(native_alloc_2_, native_alloc_1_);
460*795d594fSAndroid Build Coastguard Worker     EXPECT_LT(swap_1_, swap_2_);
461*795d594fSAndroid Build Coastguard Worker 
462*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << output_1;
463*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << output_2;
464*795d594fSAndroid Build Coastguard Worker   }
465*795d594fSAndroid Build Coastguard Worker }
466*795d594fSAndroid Build Coastguard Worker 
467*795d594fSAndroid Build Coastguard Worker class Dex2oatVeryLargeTest : public Dex2oatTest {
468*795d594fSAndroid Build Coastguard Worker  protected:
CheckFilter(CompilerFilter::Filter input,CompilerFilter::Filter result)469*795d594fSAndroid Build Coastguard Worker   void CheckFilter([[maybe_unused]] CompilerFilter::Filter input,
470*795d594fSAndroid Build Coastguard Worker                    [[maybe_unused]] CompilerFilter::Filter result) override {
471*795d594fSAndroid Build Coastguard Worker     // Ignore, we'll do our own checks.
472*795d594fSAndroid Build Coastguard Worker   }
473*795d594fSAndroid Build Coastguard Worker 
RunTest(CompilerFilter::Filter filter,bool expect_large,bool expect_downgrade,const std::vector<std::string> & extra_args={})474*795d594fSAndroid Build Coastguard Worker   void RunTest(CompilerFilter::Filter filter,
475*795d594fSAndroid Build Coastguard Worker                bool expect_large,
476*795d594fSAndroid Build Coastguard Worker                bool expect_downgrade,
477*795d594fSAndroid Build Coastguard Worker                const std::vector<std::string>& extra_args = {}) {
478*795d594fSAndroid Build Coastguard Worker     RunTest(filter, filter, expect_large, expect_downgrade, extra_args);
479*795d594fSAndroid Build Coastguard Worker   }
480*795d594fSAndroid Build Coastguard Worker 
RunTest(CompilerFilter::Filter filter,CompilerFilter::Filter expected_filter,bool expect_large,bool expect_downgrade,const std::vector<std::string> & extra_args={})481*795d594fSAndroid Build Coastguard Worker   void RunTest(CompilerFilter::Filter filter,
482*795d594fSAndroid Build Coastguard Worker                CompilerFilter::Filter expected_filter,
483*795d594fSAndroid Build Coastguard Worker                bool expect_large,
484*795d594fSAndroid Build Coastguard Worker                bool expect_downgrade,
485*795d594fSAndroid Build Coastguard Worker                const std::vector<std::string>& extra_args = {}) {
486*795d594fSAndroid Build Coastguard Worker     std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
487*795d594fSAndroid Build Coastguard Worker     std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
488*795d594fSAndroid Build Coastguard Worker     std::string app_image_file = GetScratchDir() + "/Test.art";
489*795d594fSAndroid Build Coastguard Worker 
490*795d594fSAndroid Build Coastguard Worker     Copy(GetDexSrc1(), dex_location);
491*795d594fSAndroid Build Coastguard Worker 
492*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> new_args(extra_args);
493*795d594fSAndroid Build Coastguard Worker     new_args.push_back("--app-image-file=" + app_image_file);
494*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(GenerateOdexForTest(dex_location, odex_location, filter, new_args));
495*795d594fSAndroid Build Coastguard Worker 
496*795d594fSAndroid Build Coastguard Worker     CheckValidity();
497*795d594fSAndroid Build Coastguard Worker     CheckResult(dex_location,
498*795d594fSAndroid Build Coastguard Worker                 odex_location,
499*795d594fSAndroid Build Coastguard Worker                 app_image_file,
500*795d594fSAndroid Build Coastguard Worker                 expected_filter,
501*795d594fSAndroid Build Coastguard Worker                 expect_large,
502*795d594fSAndroid Build Coastguard Worker                 expect_downgrade);
503*795d594fSAndroid Build Coastguard Worker   }
504*795d594fSAndroid Build Coastguard Worker 
CheckResult(const std::string & dex_location,const std::string & odex_location,const std::string & app_image_file,CompilerFilter::Filter expected_filter,bool expect_large,bool expect_downgrade)505*795d594fSAndroid Build Coastguard Worker   void CheckResult(const std::string& dex_location,
506*795d594fSAndroid Build Coastguard Worker                    const std::string& odex_location,
507*795d594fSAndroid Build Coastguard Worker                    const std::string& app_image_file,
508*795d594fSAndroid Build Coastguard Worker                    CompilerFilter::Filter expected_filter,
509*795d594fSAndroid Build Coastguard Worker                    bool expect_large,
510*795d594fSAndroid Build Coastguard Worker                    bool expect_downgrade) {
511*795d594fSAndroid Build Coastguard Worker     if (expect_downgrade) {
512*795d594fSAndroid Build Coastguard Worker       EXPECT_TRUE(expect_large);
513*795d594fSAndroid Build Coastguard Worker     }
514*795d594fSAndroid Build Coastguard Worker     // Host/target independent checks.
515*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
516*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
517*795d594fSAndroid Build Coastguard Worker                                                      odex_location,
518*795d594fSAndroid Build Coastguard Worker                                                      odex_location,
519*795d594fSAndroid Build Coastguard Worker                                                      /*executable=*/false,
520*795d594fSAndroid Build Coastguard Worker                                                      /*low_4gb=*/false,
521*795d594fSAndroid Build Coastguard Worker                                                      dex_location,
522*795d594fSAndroid Build Coastguard Worker                                                      &error_msg));
523*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
524*795d594fSAndroid Build Coastguard Worker     EXPECT_GT(app_image_file.length(), 0u);
525*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file.c_str()));
526*795d594fSAndroid Build Coastguard Worker     if (expect_large) {
527*795d594fSAndroid Build Coastguard Worker       // Note: we cannot check the following
528*795d594fSAndroid Build Coastguard Worker       // EXPECT_FALSE(CompilerFilter::IsAotCompilationEnabled(odex_file->GetCompilerFilter()));
529*795d594fSAndroid Build Coastguard Worker       // The reason is that the filter override currently happens when the dex files are
530*795d594fSAndroid Build Coastguard Worker       // loaded in dex2oat, which is after the oat file has been started. Thus, the header
531*795d594fSAndroid Build Coastguard Worker       // store cannot be changed, and the original filter is set in stone.
532*795d594fSAndroid Build Coastguard Worker 
533*795d594fSAndroid Build Coastguard Worker       for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
534*795d594fSAndroid Build Coastguard Worker         std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
535*795d594fSAndroid Build Coastguard Worker         ASSERT_TRUE(dex_file != nullptr);
536*795d594fSAndroid Build Coastguard Worker         uint32_t class_def_count = dex_file->NumClassDefs();
537*795d594fSAndroid Build Coastguard Worker         ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
538*795d594fSAndroid Build Coastguard Worker         for (uint16_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
539*795d594fSAndroid Build Coastguard Worker           OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
540*795d594fSAndroid Build Coastguard Worker           EXPECT_EQ(oat_class.GetType(), OatClassType::kNoneCompiled);
541*795d594fSAndroid Build Coastguard Worker         }
542*795d594fSAndroid Build Coastguard Worker       }
543*795d594fSAndroid Build Coastguard Worker 
544*795d594fSAndroid Build Coastguard Worker       // If the input filter was "below," it should have been used.
545*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(odex_file->GetCompilerFilter(), expected_filter);
546*795d594fSAndroid Build Coastguard Worker 
547*795d594fSAndroid Build Coastguard Worker       // If expect large, make sure the app image isn't generated or is empty.
548*795d594fSAndroid Build Coastguard Worker       if (file != nullptr) {
549*795d594fSAndroid Build Coastguard Worker         EXPECT_EQ(file->GetLength(), 0u);
550*795d594fSAndroid Build Coastguard Worker       }
551*795d594fSAndroid Build Coastguard Worker     } else {
552*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(odex_file->GetCompilerFilter(), expected_filter);
553*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(file != nullptr) << app_image_file;
554*795d594fSAndroid Build Coastguard Worker       EXPECT_GT(file->GetLength(), 0u);
555*795d594fSAndroid Build Coastguard Worker     }
556*795d594fSAndroid Build Coastguard Worker 
557*795d594fSAndroid Build Coastguard Worker     // Host/target dependent checks.
558*795d594fSAndroid Build Coastguard Worker     if (kIsTargetBuild) {
559*795d594fSAndroid Build Coastguard Worker       CheckTargetResult(expect_downgrade);
560*795d594fSAndroid Build Coastguard Worker     } else {
561*795d594fSAndroid Build Coastguard Worker       CheckHostResult(expect_downgrade);
562*795d594fSAndroid Build Coastguard Worker     }
563*795d594fSAndroid Build Coastguard Worker   }
564*795d594fSAndroid Build Coastguard Worker 
CheckTargetResult(bool expect_downgrade)565*795d594fSAndroid Build Coastguard Worker   void CheckTargetResult([[maybe_unused]] bool expect_downgrade) {
566*795d594fSAndroid Build Coastguard Worker     // TODO: Ignore for now. May do something for fd things.
567*795d594fSAndroid Build Coastguard Worker   }
568*795d594fSAndroid Build Coastguard Worker 
CheckHostResult(bool expect_downgrade)569*795d594fSAndroid Build Coastguard Worker   void CheckHostResult(bool expect_downgrade) {
570*795d594fSAndroid Build Coastguard Worker     if (!kIsTargetBuild) {
571*795d594fSAndroid Build Coastguard Worker       if (expect_downgrade) {
572*795d594fSAndroid Build Coastguard Worker         EXPECT_NE(output_.find("Very large app, downgrading to"), std::string::npos) << output_;
573*795d594fSAndroid Build Coastguard Worker       } else {
574*795d594fSAndroid Build Coastguard Worker         EXPECT_EQ(output_.find("Very large app, downgrading to"), std::string::npos) << output_;
575*795d594fSAndroid Build Coastguard Worker       }
576*795d594fSAndroid Build Coastguard Worker     }
577*795d594fSAndroid Build Coastguard Worker   }
578*795d594fSAndroid Build Coastguard Worker 
579*795d594fSAndroid Build Coastguard Worker   // Check whether the dex2oat run was really successful.
CheckValidity()580*795d594fSAndroid Build Coastguard Worker   void CheckValidity() {
581*795d594fSAndroid Build Coastguard Worker     if (kIsTargetBuild) {
582*795d594fSAndroid Build Coastguard Worker       CheckTargetValidity();
583*795d594fSAndroid Build Coastguard Worker     } else {
584*795d594fSAndroid Build Coastguard Worker       CheckHostValidity();
585*795d594fSAndroid Build Coastguard Worker     }
586*795d594fSAndroid Build Coastguard Worker   }
587*795d594fSAndroid Build Coastguard Worker 
CheckTargetValidity()588*795d594fSAndroid Build Coastguard Worker   void CheckTargetValidity() {
589*795d594fSAndroid Build Coastguard Worker     // TODO: Ignore for now.
590*795d594fSAndroid Build Coastguard Worker   }
591*795d594fSAndroid Build Coastguard Worker 
592*795d594fSAndroid Build Coastguard Worker   // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
CheckHostValidity()593*795d594fSAndroid Build Coastguard Worker   void CheckHostValidity() {
594*795d594fSAndroid Build Coastguard Worker     EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
595*795d594fSAndroid Build Coastguard Worker   }
596*795d594fSAndroid Build Coastguard Worker };
597*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatVeryLargeTest,DontUseVeryLarge)598*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatVeryLargeTest, DontUseVeryLarge) {
599*795d594fSAndroid Build Coastguard Worker   RunTest(CompilerFilter::kAssumeVerified, false, false);
600*795d594fSAndroid Build Coastguard Worker   RunTest(CompilerFilter::kSpeed, false, false);
601*795d594fSAndroid Build Coastguard Worker 
602*795d594fSAndroid Build Coastguard Worker   RunTest(CompilerFilter::kAssumeVerified, false, false, {"--very-large-app-threshold=10000000"});
603*795d594fSAndroid Build Coastguard Worker   RunTest(CompilerFilter::kSpeed, false, false, {"--very-large-app-threshold=10000000"});
604*795d594fSAndroid Build Coastguard Worker }
605*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatVeryLargeTest,UseVeryLarge)606*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatVeryLargeTest, UseVeryLarge) {
607*795d594fSAndroid Build Coastguard Worker   RunTest(CompilerFilter::kAssumeVerified, true, false, {"--very-large-app-threshold=100"});
608*795d594fSAndroid Build Coastguard Worker   RunTest(CompilerFilter::kSpeed, true, true, {"--very-large-app-threshold=100"});
609*795d594fSAndroid Build Coastguard Worker }
610*795d594fSAndroid Build Coastguard Worker 
611*795d594fSAndroid Build Coastguard Worker // Regressin test for b/35665292.
TEST_F(Dex2oatVeryLargeTest,SpeedProfileNoProfile)612*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatVeryLargeTest, SpeedProfileNoProfile) {
613*795d594fSAndroid Build Coastguard Worker   // Test that dex2oat doesn't crash with speed-profile but no input profile.
614*795d594fSAndroid Build Coastguard Worker   RunTest(CompilerFilter::kSpeedProfile, CompilerFilter::kVerify, false, false);
615*795d594fSAndroid Build Coastguard Worker }
616*795d594fSAndroid Build Coastguard Worker 
617*795d594fSAndroid Build Coastguard Worker class Dex2oatLayoutTest : public Dex2oatTest {
618*795d594fSAndroid Build Coastguard Worker  protected:
CheckFilter(CompilerFilter::Filter input,CompilerFilter::Filter result)619*795d594fSAndroid Build Coastguard Worker   void CheckFilter([[maybe_unused]] CompilerFilter::Filter input,
620*795d594fSAndroid Build Coastguard Worker                    [[maybe_unused]] CompilerFilter::Filter result) override {
621*795d594fSAndroid Build Coastguard Worker     // Ignore, we'll do our own checks.
622*795d594fSAndroid Build Coastguard Worker   }
623*795d594fSAndroid Build Coastguard Worker 
624*795d594fSAndroid Build Coastguard Worker   // Emits a profile with a single dex file with the given location and classes ranging
625*795d594fSAndroid Build Coastguard Worker   // from `class_offset` to `class_offset + num_classes`.
GenerateProfile(const std::string & test_profile,const std::string & dex_location,size_t num_classes,size_t class_offset=0)626*795d594fSAndroid Build Coastguard Worker   void GenerateProfile(const std::string& test_profile,
627*795d594fSAndroid Build Coastguard Worker                        const std::string& dex_location,
628*795d594fSAndroid Build Coastguard Worker                        size_t num_classes,
629*795d594fSAndroid Build Coastguard Worker                        size_t class_offset = 0) {
630*795d594fSAndroid Build Coastguard Worker     const char* location = dex_location.c_str();
631*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
632*795d594fSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<const DexFile>> dex_files;
633*795d594fSAndroid Build Coastguard Worker     ArtDexFileLoader dex_file_loader(location);
634*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(dex_file_loader.Open(
635*795d594fSAndroid Build Coastguard Worker         /*verify=*/true, /*verify_checksum=*/true, &error_msg, &dex_files));
636*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(dex_files.size(), 1U);
637*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<const DexFile>& dex_file = dex_files[0];
638*795d594fSAndroid Build Coastguard Worker 
639*795d594fSAndroid Build Coastguard Worker     int profile_test_fd =
640*795d594fSAndroid Build Coastguard Worker         open(test_profile.c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
641*795d594fSAndroid Build Coastguard Worker     CHECK_GE(profile_test_fd, 0);
642*795d594fSAndroid Build Coastguard Worker 
643*795d594fSAndroid Build Coastguard Worker     ProfileCompilationInfo info;
644*795d594fSAndroid Build Coastguard Worker     std::vector<dex::TypeIndex> classes;
645*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < num_classes; ++i) {
646*795d594fSAndroid Build Coastguard Worker       classes.push_back(dex::TypeIndex(class_offset + 1 + i));
647*795d594fSAndroid Build Coastguard Worker     }
648*795d594fSAndroid Build Coastguard Worker     info.AddClassesForDex(dex_file.get(), classes.begin(), classes.end());
649*795d594fSAndroid Build Coastguard Worker     bool result = info.Save(profile_test_fd);
650*795d594fSAndroid Build Coastguard Worker     close(profile_test_fd);
651*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(result);
652*795d594fSAndroid Build Coastguard Worker   }
653*795d594fSAndroid Build Coastguard Worker 
654*795d594fSAndroid Build Coastguard Worker   // Compiles a dex file with profiles.
CompileProfileOdex(const std::string & dex_location,const std::string & odex_location,const std::string & app_image_file_name,bool use_fd,const std::vector<std::string> & profile_locations,const std::vector<std::string> & extra_args={},Status expect_status=Status::kSuccess)655*795d594fSAndroid Build Coastguard Worker   void CompileProfileOdex(const std::string& dex_location,
656*795d594fSAndroid Build Coastguard Worker                           const std::string& odex_location,
657*795d594fSAndroid Build Coastguard Worker                           const std::string& app_image_file_name,
658*795d594fSAndroid Build Coastguard Worker                           bool use_fd,
659*795d594fSAndroid Build Coastguard Worker                           const std::vector<std::string>& profile_locations,
660*795d594fSAndroid Build Coastguard Worker                           const std::vector<std::string>& extra_args = {},
661*795d594fSAndroid Build Coastguard Worker                           Status expect_status = Status::kSuccess) {
662*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> copy(extra_args);
663*795d594fSAndroid Build Coastguard Worker     for (const std::string& profile_location : profile_locations) {
664*795d594fSAndroid Build Coastguard Worker       copy.push_back("--profile-file=" + profile_location);
665*795d594fSAndroid Build Coastguard Worker     }
666*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<File> app_image_file;
667*795d594fSAndroid Build Coastguard Worker     if (!app_image_file_name.empty()) {
668*795d594fSAndroid Build Coastguard Worker       if (use_fd) {
669*795d594fSAndroid Build Coastguard Worker         app_image_file.reset(OS::CreateEmptyFile(app_image_file_name.c_str()));
670*795d594fSAndroid Build Coastguard Worker         copy.push_back("--app-image-fd=" + std::to_string(app_image_file->Fd()));
671*795d594fSAndroid Build Coastguard Worker       } else {
672*795d594fSAndroid Build Coastguard Worker         copy.push_back("--app-image-file=" + app_image_file_name);
673*795d594fSAndroid Build Coastguard Worker       }
674*795d594fSAndroid Build Coastguard Worker     }
675*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(GenerateOdexForTest(
676*795d594fSAndroid Build Coastguard Worker         dex_location, odex_location, CompilerFilter::kSpeedProfile, copy, expect_status, use_fd));
677*795d594fSAndroid Build Coastguard Worker     if (app_image_file != nullptr) {
678*795d594fSAndroid Build Coastguard Worker       ASSERT_EQ(app_image_file->FlushCloseOrErase(), 0) << "Could not flush and close art file";
679*795d594fSAndroid Build Coastguard Worker     }
680*795d594fSAndroid Build Coastguard Worker   }
681*795d594fSAndroid Build Coastguard Worker 
682*795d594fSAndroid Build Coastguard Worker   // Same as above, but generates the profile internally with classes ranging from 0 to
683*795d594fSAndroid Build Coastguard Worker   // `num_profile_classes`.
CompileProfileOdex(const std::string & dex_location,const std::string & odex_location,const std::string & app_image_file_name,bool use_fd,size_t num_profile_classes,const std::vector<std::string> & extra_args={},Status expect_status=Status::kSuccess)684*795d594fSAndroid Build Coastguard Worker   void CompileProfileOdex(const std::string& dex_location,
685*795d594fSAndroid Build Coastguard Worker                           const std::string& odex_location,
686*795d594fSAndroid Build Coastguard Worker                           const std::string& app_image_file_name,
687*795d594fSAndroid Build Coastguard Worker                           bool use_fd,
688*795d594fSAndroid Build Coastguard Worker                           size_t num_profile_classes,
689*795d594fSAndroid Build Coastguard Worker                           const std::vector<std::string>& extra_args = {},
690*795d594fSAndroid Build Coastguard Worker                           Status expect_status = Status::kSuccess) {
691*795d594fSAndroid Build Coastguard Worker     const std::string profile_location = GetScratchDir() + "/primary.prof";
692*795d594fSAndroid Build Coastguard Worker     GenerateProfile(profile_location, dex_location, num_profile_classes);
693*795d594fSAndroid Build Coastguard Worker     CompileProfileOdex(dex_location,
694*795d594fSAndroid Build Coastguard Worker                        odex_location,
695*795d594fSAndroid Build Coastguard Worker                        app_image_file_name,
696*795d594fSAndroid Build Coastguard Worker                        use_fd,
697*795d594fSAndroid Build Coastguard Worker                        {profile_location},
698*795d594fSAndroid Build Coastguard Worker                        extra_args,
699*795d594fSAndroid Build Coastguard Worker                        expect_status);
700*795d594fSAndroid Build Coastguard Worker   }
701*795d594fSAndroid Build Coastguard Worker 
GetImageObjectSectionSize(const std::string & image_file_name)702*795d594fSAndroid Build Coastguard Worker   uint32_t GetImageObjectSectionSize(const std::string& image_file_name) {
703*795d594fSAndroid Build Coastguard Worker     EXPECT_FALSE(image_file_name.empty());
704*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
705*795d594fSAndroid Build Coastguard Worker     CHECK(file != nullptr);
706*795d594fSAndroid Build Coastguard Worker     ImageHeader image_header;
707*795d594fSAndroid Build Coastguard Worker     const bool success = file->ReadFully(&image_header, sizeof(image_header));
708*795d594fSAndroid Build Coastguard Worker     CHECK(success);
709*795d594fSAndroid Build Coastguard Worker     CHECK(image_header.IsValid());
710*795d594fSAndroid Build Coastguard Worker     ReaderMutexLock mu(Thread::Current(), *Locks::mutator_lock_);
711*795d594fSAndroid Build Coastguard Worker     return image_header.GetObjectsSection().Size();
712*795d594fSAndroid Build Coastguard Worker   }
713*795d594fSAndroid Build Coastguard Worker 
RunTest(bool app_image)714*795d594fSAndroid Build Coastguard Worker   void RunTest(bool app_image) {
715*795d594fSAndroid Build Coastguard Worker     std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
716*795d594fSAndroid Build Coastguard Worker     std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
717*795d594fSAndroid Build Coastguard Worker     std::string app_image_file = app_image ? (GetOdexDir() + "/DexOdexNoOat.art") : "";
718*795d594fSAndroid Build Coastguard Worker     Copy(GetDexSrc2(), dex_location);
719*795d594fSAndroid Build Coastguard Worker 
720*795d594fSAndroid Build Coastguard Worker     uint32_t image_file_empty_profile = 0;
721*795d594fSAndroid Build Coastguard Worker     if (app_image) {
722*795d594fSAndroid Build Coastguard Worker       CompileProfileOdex(dex_location,
723*795d594fSAndroid Build Coastguard Worker                          odex_location,
724*795d594fSAndroid Build Coastguard Worker                          app_image_file,
725*795d594fSAndroid Build Coastguard Worker                          /*use_fd=*/false,
726*795d594fSAndroid Build Coastguard Worker                          /*num_profile_classes=*/0);
727*795d594fSAndroid Build Coastguard Worker       CheckValidity();
728*795d594fSAndroid Build Coastguard Worker       // Don't check the result since CheckResult relies on the class being in the profile.
729*795d594fSAndroid Build Coastguard Worker       image_file_empty_profile = GetImageObjectSectionSize(app_image_file);
730*795d594fSAndroid Build Coastguard Worker       EXPECT_GT(image_file_empty_profile, 0u);
731*795d594fSAndroid Build Coastguard Worker       CheckCompilerFilter(dex_location, odex_location, CompilerFilter::Filter::kVerify);
732*795d594fSAndroid Build Coastguard Worker     }
733*795d594fSAndroid Build Coastguard Worker 
734*795d594fSAndroid Build Coastguard Worker     // Small profile.
735*795d594fSAndroid Build Coastguard Worker     CompileProfileOdex(dex_location,
736*795d594fSAndroid Build Coastguard Worker                        odex_location,
737*795d594fSAndroid Build Coastguard Worker                        app_image_file,
738*795d594fSAndroid Build Coastguard Worker                        /*use_fd=*/false,
739*795d594fSAndroid Build Coastguard Worker                        /*num_profile_classes=*/1);
740*795d594fSAndroid Build Coastguard Worker     CheckValidity();
741*795d594fSAndroid Build Coastguard Worker     CheckResult(dex_location, odex_location, app_image_file);
742*795d594fSAndroid Build Coastguard Worker     CheckCompilerFilter(dex_location, odex_location, CompilerFilter::Filter::kSpeedProfile);
743*795d594fSAndroid Build Coastguard Worker 
744*795d594fSAndroid Build Coastguard Worker     if (app_image) {
745*795d594fSAndroid Build Coastguard Worker       // Test that the profile made a difference by adding more classes.
746*795d594fSAndroid Build Coastguard Worker       const uint32_t image_file_small_profile = GetImageObjectSectionSize(app_image_file);
747*795d594fSAndroid Build Coastguard Worker       ASSERT_LT(image_file_empty_profile, image_file_small_profile);
748*795d594fSAndroid Build Coastguard Worker     }
749*795d594fSAndroid Build Coastguard Worker   }
750*795d594fSAndroid Build Coastguard Worker 
CheckCompilerFilter(const std::string & dex_location,const std::string & odex_location,CompilerFilter::Filter expected_filter)751*795d594fSAndroid Build Coastguard Worker   void CheckCompilerFilter(const std::string& dex_location,
752*795d594fSAndroid Build Coastguard Worker                            const std::string& odex_location,
753*795d594fSAndroid Build Coastguard Worker                            CompilerFilter::Filter expected_filter) {
754*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
755*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
756*795d594fSAndroid Build Coastguard Worker                                                      odex_location,
757*795d594fSAndroid Build Coastguard Worker                                                      odex_location,
758*795d594fSAndroid Build Coastguard Worker                                                      /*executable=*/false,
759*795d594fSAndroid Build Coastguard Worker                                                      /*low_4gb=*/false,
760*795d594fSAndroid Build Coastguard Worker                                                      dex_location,
761*795d594fSAndroid Build Coastguard Worker                                                      &error_msg));
762*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(odex_file->GetCompilerFilter(), expected_filter);
763*795d594fSAndroid Build Coastguard Worker   }
764*795d594fSAndroid Build Coastguard Worker 
RunTestVDex()765*795d594fSAndroid Build Coastguard Worker   void RunTestVDex() {
766*795d594fSAndroid Build Coastguard Worker     std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
767*795d594fSAndroid Build Coastguard Worker     std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
768*795d594fSAndroid Build Coastguard Worker     std::string vdex_location = GetOdexDir() + "/DexOdexNoOat.vdex";
769*795d594fSAndroid Build Coastguard Worker     std::string app_image_file_name = GetOdexDir() + "/DexOdexNoOat.art";
770*795d594fSAndroid Build Coastguard Worker     Copy(GetDexSrc2(), dex_location);
771*795d594fSAndroid Build Coastguard Worker 
772*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
773*795d594fSAndroid Build Coastguard Worker     CHECK(vdex_file1 != nullptr) << vdex_location;
774*795d594fSAndroid Build Coastguard Worker     ScratchFile vdex_file2;
775*795d594fSAndroid Build Coastguard Worker     {
776*795d594fSAndroid Build Coastguard Worker       std::string input_vdex = "--input-vdex-fd=-1";
777*795d594fSAndroid Build Coastguard Worker       std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
778*795d594fSAndroid Build Coastguard Worker       CompileProfileOdex(dex_location,
779*795d594fSAndroid Build Coastguard Worker                          odex_location,
780*795d594fSAndroid Build Coastguard Worker                          app_image_file_name,
781*795d594fSAndroid Build Coastguard Worker                          /*use_fd=*/true,
782*795d594fSAndroid Build Coastguard Worker                          /*num_profile_classes=*/1,
783*795d594fSAndroid Build Coastguard Worker                          {input_vdex, output_vdex});
784*795d594fSAndroid Build Coastguard Worker       EXPECT_GT(vdex_file1->GetLength(), 0u);
785*795d594fSAndroid Build Coastguard Worker     }
786*795d594fSAndroid Build Coastguard Worker     {
787*795d594fSAndroid Build Coastguard Worker       // Test that vdex and dexlayout fail gracefully.
788*795d594fSAndroid Build Coastguard Worker       std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
789*795d594fSAndroid Build Coastguard Worker       std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2.GetFd());
790*795d594fSAndroid Build Coastguard Worker       CompileProfileOdex(dex_location,
791*795d594fSAndroid Build Coastguard Worker                          odex_location,
792*795d594fSAndroid Build Coastguard Worker                          app_image_file_name,
793*795d594fSAndroid Build Coastguard Worker                          /*use_fd=*/true,
794*795d594fSAndroid Build Coastguard Worker                          /*num_profile_classes=*/1,
795*795d594fSAndroid Build Coastguard Worker                          {input_vdex, output_vdex},
796*795d594fSAndroid Build Coastguard Worker                          /*expect_status=*/Status::kSuccess);
797*795d594fSAndroid Build Coastguard Worker       EXPECT_GT(vdex_file2.GetFile()->GetLength(), 0u);
798*795d594fSAndroid Build Coastguard Worker     }
799*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
800*795d594fSAndroid Build Coastguard Worker     CheckValidity();
801*795d594fSAndroid Build Coastguard Worker   }
802*795d594fSAndroid Build Coastguard Worker 
CheckResult(const std::string & dex_location,const std::string & odex_location,const std::string & app_image_file_name)803*795d594fSAndroid Build Coastguard Worker   void CheckResult(const std::string& dex_location,
804*795d594fSAndroid Build Coastguard Worker                    const std::string& odex_location,
805*795d594fSAndroid Build Coastguard Worker                    const std::string& app_image_file_name) {
806*795d594fSAndroid Build Coastguard Worker     // Host/target independent checks.
807*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
808*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
809*795d594fSAndroid Build Coastguard Worker                                                      odex_location,
810*795d594fSAndroid Build Coastguard Worker                                                      odex_location,
811*795d594fSAndroid Build Coastguard Worker                                                      /*executable=*/false,
812*795d594fSAndroid Build Coastguard Worker                                                      /*low_4gb=*/false,
813*795d594fSAndroid Build Coastguard Worker                                                      dex_location,
814*795d594fSAndroid Build Coastguard Worker                                                      &error_msg));
815*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
816*795d594fSAndroid Build Coastguard Worker 
817*795d594fSAndroid Build Coastguard Worker     const char* location = dex_location.c_str();
818*795d594fSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<const DexFile>> dex_files;
819*795d594fSAndroid Build Coastguard Worker     ArtDexFileLoader dex_file_loader(location);
820*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(dex_file_loader.Open(
821*795d594fSAndroid Build Coastguard Worker         /*verify=*/true, /*verify_checksum=*/true, &error_msg, &dex_files));
822*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(dex_files.size(), 1U);
823*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<const DexFile>& old_dex_file = dex_files[0];
824*795d594fSAndroid Build Coastguard Worker 
825*795d594fSAndroid Build Coastguard Worker     for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
826*795d594fSAndroid Build Coastguard Worker       std::unique_ptr<const DexFile> new_dex_file = oat_dex_file->OpenDexFile(&error_msg);
827*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(new_dex_file != nullptr);
828*795d594fSAndroid Build Coastguard Worker       uint32_t class_def_count = new_dex_file->NumClassDefs();
829*795d594fSAndroid Build Coastguard Worker       ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
830*795d594fSAndroid Build Coastguard Worker       ASSERT_GE(class_def_count, 2U);
831*795d594fSAndroid Build Coastguard Worker 
832*795d594fSAndroid Build Coastguard Worker       // Make sure the indexes stay the same.
833*795d594fSAndroid Build Coastguard Worker       std::string old_class0 = old_dex_file->PrettyType(old_dex_file->GetClassDef(0).class_idx_);
834*795d594fSAndroid Build Coastguard Worker       std::string old_class1 = old_dex_file->PrettyType(old_dex_file->GetClassDef(1).class_idx_);
835*795d594fSAndroid Build Coastguard Worker       std::string new_class0 = new_dex_file->PrettyType(new_dex_file->GetClassDef(0).class_idx_);
836*795d594fSAndroid Build Coastguard Worker       std::string new_class1 = new_dex_file->PrettyType(new_dex_file->GetClassDef(1).class_idx_);
837*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(old_class0, new_class0);
838*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(old_class1, new_class1);
839*795d594fSAndroid Build Coastguard Worker     }
840*795d594fSAndroid Build Coastguard Worker 
841*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(odex_file->GetCompilerFilter(), CompilerFilter::kSpeedProfile);
842*795d594fSAndroid Build Coastguard Worker 
843*795d594fSAndroid Build Coastguard Worker     if (!app_image_file_name.empty()) {
844*795d594fSAndroid Build Coastguard Worker       // Go peek at the image header to make sure it was large enough to contain the class.
845*795d594fSAndroid Build Coastguard Worker       std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file_name.c_str()));
846*795d594fSAndroid Build Coastguard Worker       ImageHeader image_header;
847*795d594fSAndroid Build Coastguard Worker       bool success = file->ReadFully(&image_header, sizeof(image_header));
848*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(success);
849*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(image_header.IsValid());
850*795d594fSAndroid Build Coastguard Worker       EXPECT_GT(image_header.GetObjectsSection().Size(), 0u);
851*795d594fSAndroid Build Coastguard Worker     }
852*795d594fSAndroid Build Coastguard Worker   }
853*795d594fSAndroid Build Coastguard Worker 
854*795d594fSAndroid Build Coastguard Worker   // Check whether the dex2oat run was really successful.
CheckValidity()855*795d594fSAndroid Build Coastguard Worker   void CheckValidity() {
856*795d594fSAndroid Build Coastguard Worker     if (kIsTargetBuild) {
857*795d594fSAndroid Build Coastguard Worker       CheckTargetValidity();
858*795d594fSAndroid Build Coastguard Worker     } else {
859*795d594fSAndroid Build Coastguard Worker       CheckHostValidity();
860*795d594fSAndroid Build Coastguard Worker     }
861*795d594fSAndroid Build Coastguard Worker   }
862*795d594fSAndroid Build Coastguard Worker 
CheckTargetValidity()863*795d594fSAndroid Build Coastguard Worker   void CheckTargetValidity() {
864*795d594fSAndroid Build Coastguard Worker     // TODO: Ignore for now.
865*795d594fSAndroid Build Coastguard Worker   }
866*795d594fSAndroid Build Coastguard Worker 
867*795d594fSAndroid Build Coastguard Worker   // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
CheckHostValidity()868*795d594fSAndroid Build Coastguard Worker   void CheckHostValidity() {
869*795d594fSAndroid Build Coastguard Worker     EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
870*795d594fSAndroid Build Coastguard Worker   }
871*795d594fSAndroid Build Coastguard Worker };
872*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatLayoutTest,TestLayout)873*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatLayoutTest, TestLayout) { RunTest(/*app_image=*/false); }
874*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatLayoutTest,TestLayoutAppImage)875*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatLayoutTest, TestLayoutAppImage) { RunTest(/*app_image=*/true); }
876*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatLayoutTest,TestLayoutAppImageMissingBootImage)877*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatLayoutTest, TestLayoutAppImageMissingBootImage) {
878*795d594fSAndroid Build Coastguard Worker   std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
879*795d594fSAndroid Build Coastguard Worker   std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
880*795d594fSAndroid Build Coastguard Worker   std::string app_image_file = GetOdexDir() + "/DexOdexNoOat.art";
881*795d594fSAndroid Build Coastguard Worker   Copy(GetDexSrc2(), dex_location);
882*795d594fSAndroid Build Coastguard Worker 
883*795d594fSAndroid Build Coastguard Worker   CompileProfileOdex(dex_location,
884*795d594fSAndroid Build Coastguard Worker                      odex_location,
885*795d594fSAndroid Build Coastguard Worker                      app_image_file,
886*795d594fSAndroid Build Coastguard Worker                      /*use_fd=*/false,
887*795d594fSAndroid Build Coastguard Worker                      /*num_profile_classes=*/1,
888*795d594fSAndroid Build Coastguard Worker                      /*extra_args=*/{"--boot-image=/nonx/boot.art"},
889*795d594fSAndroid Build Coastguard Worker                      /*expect_status=*/Status::kSuccess);
890*795d594fSAndroid Build Coastguard Worker 
891*795d594fSAndroid Build Coastguard Worker   // Verify the odex file does not require an image.
892*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
893*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
894*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
895*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
896*795d594fSAndroid Build Coastguard Worker                                                    /*executable=*/false,
897*795d594fSAndroid Build Coastguard Worker                                                    /*low_4gb=*/false,
898*795d594fSAndroid Build Coastguard Worker                                                    dex_location,
899*795d594fSAndroid Build Coastguard Worker                                                    &error_msg));
900*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(odex_file != nullptr) << "Could not open odex file: " << error_msg;
901*795d594fSAndroid Build Coastguard Worker 
902*795d594fSAndroid Build Coastguard Worker   CheckFilter(CompilerFilter::kSpeedProfile, odex_file->GetCompilerFilter());
903*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(odex_file->GetOatHeader().RequiresImage());
904*795d594fSAndroid Build Coastguard Worker }
905*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatLayoutTest,TestLayoutMultipleProfiles)906*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatLayoutTest, TestLayoutMultipleProfiles) {
907*795d594fSAndroid Build Coastguard Worker   std::string dex_location = GetScratchDir() + "/Dex.jar";
908*795d594fSAndroid Build Coastguard Worker   std::string odex_location = GetOdexDir() + "/Dex.odex";
909*795d594fSAndroid Build Coastguard Worker   std::string app_image_file = GetOdexDir() + "/Dex.art";
910*795d594fSAndroid Build Coastguard Worker   Copy(GetDexSrc2(), dex_location);
911*795d594fSAndroid Build Coastguard Worker 
912*795d594fSAndroid Build Coastguard Worker   const std::string profile1_location = GetScratchDir() + "/primary.prof";
913*795d594fSAndroid Build Coastguard Worker   GenerateProfile(profile1_location, dex_location, /*num_classes=*/1, /*class_offset=*/0);
914*795d594fSAndroid Build Coastguard Worker   CompileProfileOdex(dex_location,
915*795d594fSAndroid Build Coastguard Worker                      odex_location,
916*795d594fSAndroid Build Coastguard Worker                      app_image_file,
917*795d594fSAndroid Build Coastguard Worker                      /*use_fd=*/false,
918*795d594fSAndroid Build Coastguard Worker                      {profile1_location});
919*795d594fSAndroid Build Coastguard Worker   uint32_t image_file_size_profile1 = GetImageObjectSectionSize(app_image_file);
920*795d594fSAndroid Build Coastguard Worker 
921*795d594fSAndroid Build Coastguard Worker   const std::string profile2_location = GetScratchDir() + "/secondary.prof";
922*795d594fSAndroid Build Coastguard Worker   GenerateProfile(profile2_location, dex_location, /*num_classes=*/1, /*class_offset=*/1);
923*795d594fSAndroid Build Coastguard Worker   CompileProfileOdex(dex_location,
924*795d594fSAndroid Build Coastguard Worker                      odex_location,
925*795d594fSAndroid Build Coastguard Worker                      app_image_file,
926*795d594fSAndroid Build Coastguard Worker                      /*use_fd=*/false,
927*795d594fSAndroid Build Coastguard Worker                      {profile2_location});
928*795d594fSAndroid Build Coastguard Worker   uint32_t image_file_size_profile2 = GetImageObjectSectionSize(app_image_file);
929*795d594fSAndroid Build Coastguard Worker 
930*795d594fSAndroid Build Coastguard Worker   CompileProfileOdex(dex_location,
931*795d594fSAndroid Build Coastguard Worker                      odex_location,
932*795d594fSAndroid Build Coastguard Worker                      app_image_file,
933*795d594fSAndroid Build Coastguard Worker                      /*use_fd=*/false,
934*795d594fSAndroid Build Coastguard Worker                      {profile1_location, profile2_location});
935*795d594fSAndroid Build Coastguard Worker   uint32_t image_file_size_multiple_profiles = GetImageObjectSectionSize(app_image_file);
936*795d594fSAndroid Build Coastguard Worker 
937*795d594fSAndroid Build Coastguard Worker   CheckCompilerFilter(dex_location, odex_location, CompilerFilter::Filter::kSpeedProfile);
938*795d594fSAndroid Build Coastguard Worker 
939*795d594fSAndroid Build Coastguard Worker   // The image file generated with multiple profiles should be larger than any image file generated
940*795d594fSAndroid Build Coastguard Worker   // with each profile.
941*795d594fSAndroid Build Coastguard Worker   ASSERT_GT(image_file_size_multiple_profiles, image_file_size_profile1);
942*795d594fSAndroid Build Coastguard Worker   ASSERT_GT(image_file_size_multiple_profiles, image_file_size_profile2);
943*795d594fSAndroid Build Coastguard Worker }
944*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatLayoutTest,TestLayoutMultipleProfilesChecksumMismatch)945*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatLayoutTest, TestLayoutMultipleProfilesChecksumMismatch) {
946*795d594fSAndroid Build Coastguard Worker   std::string dex_location = GetScratchDir() + "/Dex.jar";
947*795d594fSAndroid Build Coastguard Worker 
948*795d594fSAndroid Build Coastguard Worker   // Create two profiles whose dex locations are the same but checksums are different.
949*795d594fSAndroid Build Coastguard Worker   Copy(GetDexSrc1(), dex_location);
950*795d594fSAndroid Build Coastguard Worker   const std::string profile_old = GetScratchDir() + "/profile_old.prof";
951*795d594fSAndroid Build Coastguard Worker   GenerateProfile(profile_old, dex_location, /*num_classes=*/1, /*class_offset=*/0);
952*795d594fSAndroid Build Coastguard Worker 
953*795d594fSAndroid Build Coastguard Worker   Copy(GetDexSrc2(), dex_location);
954*795d594fSAndroid Build Coastguard Worker   const std::string profile_new = GetScratchDir() + "/profile_new.prof";
955*795d594fSAndroid Build Coastguard Worker   GenerateProfile(profile_new, dex_location, /*num_classes=*/1, /*class_offset=*/0);
956*795d594fSAndroid Build Coastguard Worker 
957*795d594fSAndroid Build Coastguard Worker   // Create an empty profile for reference.
958*795d594fSAndroid Build Coastguard Worker   const std::string profile_empty = GetScratchDir() + "/profile_empty.prof";
959*795d594fSAndroid Build Coastguard Worker   GenerateProfile(profile_empty, dex_location, /*num_classes=*/0, /*class_offset=*/0);
960*795d594fSAndroid Build Coastguard Worker 
961*795d594fSAndroid Build Coastguard Worker   std::string odex_location = GetOdexDir() + "/Dex.odex";
962*795d594fSAndroid Build Coastguard Worker   std::string app_image_file = GetOdexDir() + "/Dex.art";
963*795d594fSAndroid Build Coastguard Worker 
964*795d594fSAndroid Build Coastguard Worker   // This should produce a normal image because only `profile_new` is used and it has the right
965*795d594fSAndroid Build Coastguard Worker   // checksum.
966*795d594fSAndroid Build Coastguard Worker   CompileProfileOdex(dex_location,
967*795d594fSAndroid Build Coastguard Worker                      odex_location,
968*795d594fSAndroid Build Coastguard Worker                      app_image_file,
969*795d594fSAndroid Build Coastguard Worker                      /*use_fd=*/false,
970*795d594fSAndroid Build Coastguard Worker                      {profile_new, profile_old});
971*795d594fSAndroid Build Coastguard Worker   uint32_t image_size_right_checksum = GetImageObjectSectionSize(app_image_file);
972*795d594fSAndroid Build Coastguard Worker 
973*795d594fSAndroid Build Coastguard Worker   // This should produce an empty image because only `profile_old` is used and it has the wrong
974*795d594fSAndroid Build Coastguard Worker   // checksum. Note that dex2oat does not abort compilation when the profile verification fails
975*795d594fSAndroid Build Coastguard Worker   // (b/62602192, b/65260586).
976*795d594fSAndroid Build Coastguard Worker   CompileProfileOdex(dex_location,
977*795d594fSAndroid Build Coastguard Worker                      odex_location,
978*795d594fSAndroid Build Coastguard Worker                      app_image_file,
979*795d594fSAndroid Build Coastguard Worker                      /*use_fd=*/false,
980*795d594fSAndroid Build Coastguard Worker                      {profile_old, profile_new});
981*795d594fSAndroid Build Coastguard Worker   uint32_t image_size_wrong_checksum = GetImageObjectSectionSize(app_image_file);
982*795d594fSAndroid Build Coastguard Worker 
983*795d594fSAndroid Build Coastguard Worker   // Create an empty image using an empty profile for reference.
984*795d594fSAndroid Build Coastguard Worker   CompileProfileOdex(dex_location,
985*795d594fSAndroid Build Coastguard Worker                      odex_location,
986*795d594fSAndroid Build Coastguard Worker                      app_image_file,
987*795d594fSAndroid Build Coastguard Worker                      /*use_fd=*/false,
988*795d594fSAndroid Build Coastguard Worker                      {profile_empty});
989*795d594fSAndroid Build Coastguard Worker   uint32_t image_size_empty = GetImageObjectSectionSize(app_image_file);
990*795d594fSAndroid Build Coastguard Worker 
991*795d594fSAndroid Build Coastguard Worker   EXPECT_GT(image_size_right_checksum, image_size_empty);
992*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(image_size_wrong_checksum, image_size_empty);
993*795d594fSAndroid Build Coastguard Worker }
994*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatLayoutTest,TestVdexLayout)995*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatLayoutTest, TestVdexLayout) { RunTestVDex(); }
996*795d594fSAndroid Build Coastguard Worker 
997*795d594fSAndroid Build Coastguard Worker class Dex2oatWatchdogTest : public Dex2oatTest {
998*795d594fSAndroid Build Coastguard Worker  protected:
RunTest(Status expect_status,const std::vector<std::string> & extra_args={})999*795d594fSAndroid Build Coastguard Worker   void RunTest(Status expect_status, const std::vector<std::string>& extra_args = {}) {
1000*795d594fSAndroid Build Coastguard Worker     std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
1001*795d594fSAndroid Build Coastguard Worker     std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
1002*795d594fSAndroid Build Coastguard Worker 
1003*795d594fSAndroid Build Coastguard Worker     Copy(GetTestDexFileName(), dex_location);
1004*795d594fSAndroid Build Coastguard Worker 
1005*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> copy(extra_args);
1006*795d594fSAndroid Build Coastguard Worker 
1007*795d594fSAndroid Build Coastguard Worker     std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
1008*795d594fSAndroid Build Coastguard Worker     copy.push_back("--swap-file=" + swap_location);
1009*795d594fSAndroid Build Coastguard Worker     copy.push_back("-j512");  // Excessive idle threads just slow down dex2oat.
1010*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(GenerateOdexForTest(
1011*795d594fSAndroid Build Coastguard Worker         dex_location, odex_location, CompilerFilter::kSpeed, copy, expect_status));
1012*795d594fSAndroid Build Coastguard Worker   }
1013*795d594fSAndroid Build Coastguard Worker 
GetTestDexFileName()1014*795d594fSAndroid Build Coastguard Worker   std::string GetTestDexFileName() { return GetDexSrc1(); }
1015*795d594fSAndroid Build Coastguard Worker };
1016*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatWatchdogTest,TestWatchdogOK)1017*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatWatchdogTest, TestWatchdogOK) {
1018*795d594fSAndroid Build Coastguard Worker   // Check with default.
1019*795d594fSAndroid Build Coastguard Worker   RunTest(/*expect_status=*/Status::kSuccess);
1020*795d594fSAndroid Build Coastguard Worker 
1021*795d594fSAndroid Build Coastguard Worker   // Check with ten minutes.
1022*795d594fSAndroid Build Coastguard Worker   RunTest(/*expect_status=*/Status::kSuccess, {"--watchdog-timeout=600000"});
1023*795d594fSAndroid Build Coastguard Worker }
1024*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatWatchdogTest,TestWatchdogTrigger)1025*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatWatchdogTest, TestWatchdogTrigger) {
1026*795d594fSAndroid Build Coastguard Worker   // This test is frequently interrupted by signal_dumper on host (x86);
1027*795d594fSAndroid Build Coastguard Worker   // disable it while we investigate (b/121352534).
1028*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_X86();
1029*795d594fSAndroid Build Coastguard Worker 
1030*795d594fSAndroid Build Coastguard Worker   // The watchdog is independent of dex2oat and will not delete intermediates. It is possible
1031*795d594fSAndroid Build Coastguard Worker   // that the compilation succeeds and the file is completely written by the time the watchdog
1032*795d594fSAndroid Build Coastguard Worker   // kills dex2oat (but the dex2oat threads must have been scheduled pretty badly).
1033*795d594fSAndroid Build Coastguard Worker   test_accepts_odex_file_on_failure = true;
1034*795d594fSAndroid Build Coastguard Worker 
1035*795d594fSAndroid Build Coastguard Worker   // Check with ten milliseconds.
1036*795d594fSAndroid Build Coastguard Worker   RunTest(/*expect_status=*/Status::kFailCompile, {"--watchdog-timeout=10"});
1037*795d594fSAndroid Build Coastguard Worker }
1038*795d594fSAndroid Build Coastguard Worker 
1039*795d594fSAndroid Build Coastguard Worker class Dex2oatClassLoaderContextTest : public Dex2oatTest {
1040*795d594fSAndroid Build Coastguard Worker  protected:
RunTest(const char * class_loader_context,const char * expected_classpath_key,Status expect_status,bool use_second_source=false,bool generate_image=false)1041*795d594fSAndroid Build Coastguard Worker   void RunTest(const char* class_loader_context,
1042*795d594fSAndroid Build Coastguard Worker                const char* expected_classpath_key,
1043*795d594fSAndroid Build Coastguard Worker                Status expect_status,
1044*795d594fSAndroid Build Coastguard Worker                bool use_second_source = false,
1045*795d594fSAndroid Build Coastguard Worker                bool generate_image = false) {
1046*795d594fSAndroid Build Coastguard Worker     std::string dex_location = GetUsedDexLocation();
1047*795d594fSAndroid Build Coastguard Worker     std::string odex_location = GetUsedOatLocation();
1048*795d594fSAndroid Build Coastguard Worker 
1049*795d594fSAndroid Build Coastguard Worker     Copy(use_second_source ? GetDexSrc2() : GetDexSrc1(), dex_location);
1050*795d594fSAndroid Build Coastguard Worker 
1051*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> extra_args;
1052*795d594fSAndroid Build Coastguard Worker     if (class_loader_context != nullptr) {
1053*795d594fSAndroid Build Coastguard Worker       extra_args.push_back(std::string("--class-loader-context=") + class_loader_context);
1054*795d594fSAndroid Build Coastguard Worker     }
1055*795d594fSAndroid Build Coastguard Worker     if (generate_image) {
1056*795d594fSAndroid Build Coastguard Worker       extra_args.push_back(std::string("--app-image-file=") + GetUsedImageLocation());
1057*795d594fSAndroid Build Coastguard Worker     }
1058*795d594fSAndroid Build Coastguard Worker     auto check_oat = [expected_classpath_key](const OatFile& oat_file) {
1059*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(expected_classpath_key != nullptr);
1060*795d594fSAndroid Build Coastguard Worker       const char* classpath = oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
1061*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(classpath != nullptr);
1062*795d594fSAndroid Build Coastguard Worker       ASSERT_STREQ(expected_classpath_key, classpath);
1063*795d594fSAndroid Build Coastguard Worker     };
1064*795d594fSAndroid Build Coastguard Worker 
1065*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(GenerateOdexForTest(dex_location,
1066*795d594fSAndroid Build Coastguard Worker                                     odex_location,
1067*795d594fSAndroid Build Coastguard Worker                                     CompilerFilter::kVerify,
1068*795d594fSAndroid Build Coastguard Worker                                     extra_args,
1069*795d594fSAndroid Build Coastguard Worker                                     expect_status,
1070*795d594fSAndroid Build Coastguard Worker                                     /*use_fd=*/false,
1071*795d594fSAndroid Build Coastguard Worker                                     /*use_zip_fd=*/false,
1072*795d594fSAndroid Build Coastguard Worker                                     check_oat));
1073*795d594fSAndroid Build Coastguard Worker   }
1074*795d594fSAndroid Build Coastguard Worker 
GetUsedDexLocation()1075*795d594fSAndroid Build Coastguard Worker   std::string GetUsedDexLocation() { return GetScratchDir() + "/Context.jar"; }
1076*795d594fSAndroid Build Coastguard Worker 
GetUsedOatLocation()1077*795d594fSAndroid Build Coastguard Worker   std::string GetUsedOatLocation() { return GetOdexDir() + "/Context.odex"; }
1078*795d594fSAndroid Build Coastguard Worker 
GetUsedImageLocation()1079*795d594fSAndroid Build Coastguard Worker   std::string GetUsedImageLocation() { return GetOdexDir() + "/Context.art"; }
1080*795d594fSAndroid Build Coastguard Worker 
1081*795d594fSAndroid Build Coastguard Worker   const char* kEmptyClassPathKey = "PCL[]";
1082*795d594fSAndroid Build Coastguard Worker };
1083*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,InvalidContext)1084*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, InvalidContext) {
1085*795d594fSAndroid Build Coastguard Worker   RunTest("Invalid[]", /*expected_classpath_key=*/nullptr, /*expect_status=*/Status::kFailCompile);
1086*795d594fSAndroid Build Coastguard Worker }
1087*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,EmptyContext)1088*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, EmptyContext) {
1089*795d594fSAndroid Build Coastguard Worker   RunTest("PCL[]", kEmptyClassPathKey, /*expect_status=*/Status::kSuccess);
1090*795d594fSAndroid Build Coastguard Worker }
1091*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithTheSourceDexFiles)1092*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, ContextWithTheSourceDexFiles) {
1093*795d594fSAndroid Build Coastguard Worker   std::string context = "PCL[" + GetUsedDexLocation() + "]";
1094*795d594fSAndroid Build Coastguard Worker   RunTest(context.c_str(), kEmptyClassPathKey, /*expect_status=*/Status::kSuccess);
1095*795d594fSAndroid Build Coastguard Worker }
1096*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithOtherDexFiles)1097*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, ContextWithOtherDexFiles) {
1098*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Nested");
1099*795d594fSAndroid Build Coastguard Worker 
1100*795d594fSAndroid Build Coastguard Worker   uint32_t expected_checksum = DexFileLoader::GetMultiDexChecksum(dex_files);
1101*795d594fSAndroid Build Coastguard Worker 
1102*795d594fSAndroid Build Coastguard Worker   std::string context = "PCL[" + dex_files[0]->GetLocation() + "]";
1103*795d594fSAndroid Build Coastguard Worker   std::string expected_classpath_key =
1104*795d594fSAndroid Build Coastguard Worker       "PCL[" + dex_files[0]->GetLocation() + "*" + std::to_string(expected_checksum) + "]";
1105*795d594fSAndroid Build Coastguard Worker   RunTest(context.c_str(), expected_classpath_key.c_str(), /*expect_status=*/Status::kSuccess);
1106*795d594fSAndroid Build Coastguard Worker }
1107*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithResourceOnlyDexFiles)1108*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, ContextWithResourceOnlyDexFiles) {
1109*795d594fSAndroid Build Coastguard Worker   std::string resource_only_classpath = GetScratchDir() + "/resource_only_classpath.jar";
1110*795d594fSAndroid Build Coastguard Worker   Copy(GetResourceOnlySrc1(), resource_only_classpath);
1111*795d594fSAndroid Build Coastguard Worker 
1112*795d594fSAndroid Build Coastguard Worker   std::string context = "PCL[" + resource_only_classpath + "]";
1113*795d594fSAndroid Build Coastguard Worker   // Expect an empty context because resource only dex files cannot be open.
1114*795d594fSAndroid Build Coastguard Worker   RunTest(context.c_str(), kEmptyClassPathKey, /*expect_status=*/Status::kSuccess);
1115*795d594fSAndroid Build Coastguard Worker }
1116*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithNotExistentDexFiles)1117*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, ContextWithNotExistentDexFiles) {
1118*795d594fSAndroid Build Coastguard Worker   std::string context = "PCL[does_not_exists.dex]";
1119*795d594fSAndroid Build Coastguard Worker   // Expect an empty context because stripped dex files cannot be open.
1120*795d594fSAndroid Build Coastguard Worker   RunTest(context.c_str(), kEmptyClassPathKey, /*expect_status=*/Status::kSuccess);
1121*795d594fSAndroid Build Coastguard Worker }
1122*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,ChainContext)1123*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, ChainContext) {
1124*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1125*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1126*795d594fSAndroid Build Coastguard Worker 
1127*795d594fSAndroid Build Coastguard Worker   std::string context =
1128*795d594fSAndroid Build Coastguard Worker       "PCL[" + GetTestDexFileName("Nested") + "];" + "DLC[" + GetTestDexFileName("MultiDex") + "]";
1129*795d594fSAndroid Build Coastguard Worker   std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "];" +
1130*795d594fSAndroid Build Coastguard Worker                                        "DLC[" + CreateClassPathWithChecksums(dex_files2) + "]";
1131*795d594fSAndroid Build Coastguard Worker 
1132*795d594fSAndroid Build Coastguard Worker   RunTest(context.c_str(), expected_classpath_key.c_str(), /*expect_status=*/Status::kSuccess);
1133*795d594fSAndroid Build Coastguard Worker }
1134*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithSharedLibrary)1135*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, ContextWithSharedLibrary) {
1136*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1137*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1138*795d594fSAndroid Build Coastguard Worker 
1139*795d594fSAndroid Build Coastguard Worker   std::string context =
1140*795d594fSAndroid Build Coastguard Worker       "PCL[" + GetTestDexFileName("Nested") + "]" + "{PCL[" + GetTestDexFileName("MultiDex") + "]}";
1141*795d594fSAndroid Build Coastguard Worker   std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "]" +
1142*795d594fSAndroid Build Coastguard Worker                                        "{PCL[" + CreateClassPathWithChecksums(dex_files2) + "]}";
1143*795d594fSAndroid Build Coastguard Worker   RunTest(context.c_str(), expected_classpath_key.c_str(), /*expect_status=*/Status::kSuccess);
1144*795d594fSAndroid Build Coastguard Worker }
1145*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithSharedLibraryAndImage)1146*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, ContextWithSharedLibraryAndImage) {
1147*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1148*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1149*795d594fSAndroid Build Coastguard Worker 
1150*795d594fSAndroid Build Coastguard Worker   std::string context =
1151*795d594fSAndroid Build Coastguard Worker       "PCL[" + GetTestDexFileName("Nested") + "]" + "{PCL[" + GetTestDexFileName("MultiDex") + "]}";
1152*795d594fSAndroid Build Coastguard Worker   std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "]" +
1153*795d594fSAndroid Build Coastguard Worker                                        "{PCL[" + CreateClassPathWithChecksums(dex_files2) + "]}";
1154*795d594fSAndroid Build Coastguard Worker   RunTest(context.c_str(),
1155*795d594fSAndroid Build Coastguard Worker           expected_classpath_key.c_str(),
1156*795d594fSAndroid Build Coastguard Worker           /*expect_status=*/Status::kSuccess,
1157*795d594fSAndroid Build Coastguard Worker           /*use_second_source=*/false,
1158*795d594fSAndroid Build Coastguard Worker           /*generate_image=*/true);
1159*795d594fSAndroid Build Coastguard Worker }
1160*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithSameSharedLibrariesAndImage)1161*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, ContextWithSameSharedLibrariesAndImage) {
1162*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1163*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1164*795d594fSAndroid Build Coastguard Worker 
1165*795d594fSAndroid Build Coastguard Worker   std::string context = "PCL[" + GetTestDexFileName("Nested") + "]" + "{PCL[" +
1166*795d594fSAndroid Build Coastguard Worker                         GetTestDexFileName("MultiDex") + "]" + "#PCL[" +
1167*795d594fSAndroid Build Coastguard Worker                         GetTestDexFileName("MultiDex") + "]}";
1168*795d594fSAndroid Build Coastguard Worker   std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "]" +
1169*795d594fSAndroid Build Coastguard Worker                                        "{PCL[" + CreateClassPathWithChecksums(dex_files2) + "]" +
1170*795d594fSAndroid Build Coastguard Worker                                        "#PCL[" + CreateClassPathWithChecksums(dex_files2) + "]}";
1171*795d594fSAndroid Build Coastguard Worker   RunTest(context.c_str(),
1172*795d594fSAndroid Build Coastguard Worker           expected_classpath_key.c_str(),
1173*795d594fSAndroid Build Coastguard Worker           /*expect_status=*/Status::kSuccess,
1174*795d594fSAndroid Build Coastguard Worker           /*use_second_source=*/false,
1175*795d594fSAndroid Build Coastguard Worker           /*generate_image=*/true);
1176*795d594fSAndroid Build Coastguard Worker }
1177*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithSharedLibrariesDependenciesAndImage)1178*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, ContextWithSharedLibrariesDependenciesAndImage) {
1179*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1180*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1181*795d594fSAndroid Build Coastguard Worker 
1182*795d594fSAndroid Build Coastguard Worker   std::string context = "PCL[" + GetTestDexFileName("Nested") + "]" + "{PCL[" +
1183*795d594fSAndroid Build Coastguard Worker                         GetTestDexFileName("MultiDex") + "]" + "{PCL[" +
1184*795d594fSAndroid Build Coastguard Worker                         GetTestDexFileName("Nested") + "]}}";
1185*795d594fSAndroid Build Coastguard Worker   std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "]" +
1186*795d594fSAndroid Build Coastguard Worker                                        "{PCL[" + CreateClassPathWithChecksums(dex_files2) + "]" +
1187*795d594fSAndroid Build Coastguard Worker                                        "{PCL[" + CreateClassPathWithChecksums(dex_files1) + "]}}";
1188*795d594fSAndroid Build Coastguard Worker   RunTest(context.c_str(),
1189*795d594fSAndroid Build Coastguard Worker           expected_classpath_key.c_str(),
1190*795d594fSAndroid Build Coastguard Worker           /*expect_status=*/Status::kSuccess,
1191*795d594fSAndroid Build Coastguard Worker           /*use_second_source=*/false,
1192*795d594fSAndroid Build Coastguard Worker           /*generate_image=*/true);
1193*795d594fSAndroid Build Coastguard Worker }
1194*795d594fSAndroid Build Coastguard Worker 
1195*795d594fSAndroid Build Coastguard Worker class Dex2oatDeterminism : public Dex2oatTest {};
1196*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatDeterminism,UnloadCompile)1197*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatDeterminism, UnloadCompile) {
1198*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
1199*795d594fSAndroid Build Coastguard Worker   std::string out_dir = GetScratchDir();
1200*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = out_dir + "/base.oat";
1201*795d594fSAndroid Build Coastguard Worker   const std::string base_vdex_name = out_dir + "/base.vdex";
1202*795d594fSAndroid Build Coastguard Worker   const std::string unload_oat_name = out_dir + "/unload.oat";
1203*795d594fSAndroid Build Coastguard Worker   const std::string unload_vdex_name = out_dir + "/unload.vdex";
1204*795d594fSAndroid Build Coastguard Worker   const std::string no_unload_oat_name = out_dir + "/nounload.oat";
1205*795d594fSAndroid Build Coastguard Worker   const std::string no_unload_vdex_name = out_dir + "/nounload.vdex";
1206*795d594fSAndroid Build Coastguard Worker   const std::vector<gc::space::ImageSpace*>& spaces = runtime->GetHeap()->GetBootImageSpaces();
1207*795d594fSAndroid Build Coastguard Worker   ASSERT_GT(spaces.size(), 0u);
1208*795d594fSAndroid Build Coastguard Worker   const std::string image_location = spaces[0]->GetImageLocation();
1209*795d594fSAndroid Build Coastguard Worker   // Without passing in an app image, it will unload in between compilations.
1210*795d594fSAndroid Build Coastguard Worker   ASSERT_THAT(GenerateOdexForTestWithStatus(GetLibCoreDexFileNames(),
1211*795d594fSAndroid Build Coastguard Worker                                             base_oat_name,
1212*795d594fSAndroid Build Coastguard Worker                                             CompilerFilter::Filter::kVerify,
1213*795d594fSAndroid Build Coastguard Worker                                             {"--force-determinism", "--avoid-storing-invocation"}),
1214*795d594fSAndroid Build Coastguard Worker               HasValue(0));
1215*795d594fSAndroid Build Coastguard Worker   Copy(base_oat_name, unload_oat_name);
1216*795d594fSAndroid Build Coastguard Worker   Copy(base_vdex_name, unload_vdex_name);
1217*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> unload_oat(OS::OpenFileForReading(unload_oat_name.c_str()));
1218*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> unload_vdex(OS::OpenFileForReading(unload_vdex_name.c_str()));
1219*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(unload_oat != nullptr);
1220*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(unload_vdex != nullptr);
1221*795d594fSAndroid Build Coastguard Worker   EXPECT_GT(unload_oat->GetLength(), 0u);
1222*795d594fSAndroid Build Coastguard Worker   EXPECT_GT(unload_vdex->GetLength(), 0u);
1223*795d594fSAndroid Build Coastguard Worker   // Regenerate with an app image to disable the dex2oat unloading and verify that the output is
1224*795d594fSAndroid Build Coastguard Worker   // the same.
1225*795d594fSAndroid Build Coastguard Worker   ASSERT_THAT(GenerateOdexForTestWithStatus(
1226*795d594fSAndroid Build Coastguard Worker                   GetLibCoreDexFileNames(),
1227*795d594fSAndroid Build Coastguard Worker                   base_oat_name,
1228*795d594fSAndroid Build Coastguard Worker                   CompilerFilter::Filter::kVerify,
1229*795d594fSAndroid Build Coastguard Worker                   {"--force-determinism", "--avoid-storing-invocation", "--compile-individually"}),
1230*795d594fSAndroid Build Coastguard Worker               HasValue(0));
1231*795d594fSAndroid Build Coastguard Worker   Copy(base_oat_name, no_unload_oat_name);
1232*795d594fSAndroid Build Coastguard Worker   Copy(base_vdex_name, no_unload_vdex_name);
1233*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> no_unload_oat(OS::OpenFileForReading(no_unload_oat_name.c_str()));
1234*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> no_unload_vdex(OS::OpenFileForReading(no_unload_vdex_name.c_str()));
1235*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(no_unload_oat != nullptr);
1236*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(no_unload_vdex != nullptr);
1237*795d594fSAndroid Build Coastguard Worker   EXPECT_GT(no_unload_oat->GetLength(), 0u);
1238*795d594fSAndroid Build Coastguard Worker   EXPECT_GT(no_unload_vdex->GetLength(), 0u);
1239*795d594fSAndroid Build Coastguard Worker   // Verify that both of the files are the same (odex and vdex).
1240*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(unload_oat->GetLength(), no_unload_oat->GetLength());
1241*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(unload_vdex->GetLength(), no_unload_vdex->GetLength());
1242*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(unload_oat->Compare(no_unload_oat.get()), 0)
1243*795d594fSAndroid Build Coastguard Worker       << unload_oat_name << " " << no_unload_oat_name;
1244*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(unload_vdex->Compare(no_unload_vdex.get()), 0)
1245*795d594fSAndroid Build Coastguard Worker       << unload_vdex_name << " " << no_unload_vdex_name;
1246*795d594fSAndroid Build Coastguard Worker }
1247*795d594fSAndroid Build Coastguard Worker 
1248*795d594fSAndroid Build Coastguard Worker class Dex2oatVerifierAbort : public Dex2oatTest {};
1249*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatVerifierAbort,HardFail)1250*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatVerifierAbort, HardFail) {
1251*795d594fSAndroid Build Coastguard Worker   // Use VerifierDeps as it has hard-failing classes.
1252*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDeps"));
1253*795d594fSAndroid Build Coastguard Worker   std::string out_dir = GetScratchDir();
1254*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = out_dir + "/base.oat";
1255*795d594fSAndroid Build Coastguard Worker 
1256*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(GenerateOdexForTestWithStatus({dex->GetLocation()},
1257*795d594fSAndroid Build Coastguard Worker                                             base_oat_name,
1258*795d594fSAndroid Build Coastguard Worker                                             CompilerFilter::Filter::kVerify,
1259*795d594fSAndroid Build Coastguard Worker                                             {"--abort-on-hard-verifier-error"}),
1260*795d594fSAndroid Build Coastguard Worker               HasValue(Ne(0)));
1261*795d594fSAndroid Build Coastguard Worker 
1262*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(GenerateOdexForTestWithStatus({dex->GetLocation()},
1263*795d594fSAndroid Build Coastguard Worker                                             base_oat_name,
1264*795d594fSAndroid Build Coastguard Worker                                             CompilerFilter::Filter::kVerify,
1265*795d594fSAndroid Build Coastguard Worker                                             {"--no-abort-on-hard-verifier-error"}),
1266*795d594fSAndroid Build Coastguard Worker               HasValue(0));
1267*795d594fSAndroid Build Coastguard Worker }
1268*795d594fSAndroid Build Coastguard Worker 
1269*795d594fSAndroid Build Coastguard Worker class Dex2oatDedupeCode : public Dex2oatTest {};
1270*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatDedupeCode,DedupeTest)1271*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatDedupeCode, DedupeTest) {
1272*795d594fSAndroid Build Coastguard Worker   // Use MyClassNatives. It has lots of native methods that will produce deduplicate-able code.
1273*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const DexFile> dex(OpenTestDexFile("MyClassNatives"));
1274*795d594fSAndroid Build Coastguard Worker   std::string out_dir = GetScratchDir();
1275*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = out_dir + "/base.oat";
1276*795d594fSAndroid Build Coastguard Worker   size_t no_dedupe_size = 0;
1277*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(
1278*795d594fSAndroid Build Coastguard Worker       GenerateOdexForTest(dex->GetLocation(),
1279*795d594fSAndroid Build Coastguard Worker                           base_oat_name,
1280*795d594fSAndroid Build Coastguard Worker                           CompilerFilter::Filter::kSpeed,
1281*795d594fSAndroid Build Coastguard Worker                           {"--deduplicate-code=false"},
1282*795d594fSAndroid Build Coastguard Worker                           /*expect_status=*/Status::kSuccess,
1283*795d594fSAndroid Build Coastguard Worker                           /*use_fd=*/false,
1284*795d594fSAndroid Build Coastguard Worker                           /*use_zip_fd=*/false,
1285*795d594fSAndroid Build Coastguard Worker                           [&no_dedupe_size](const OatFile& o) { no_dedupe_size = o.Size(); }));
1286*795d594fSAndroid Build Coastguard Worker 
1287*795d594fSAndroid Build Coastguard Worker   size_t dedupe_size = 0;
1288*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex->GetLocation(),
1289*795d594fSAndroid Build Coastguard Worker                                   base_oat_name,
1290*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kSpeed,
1291*795d594fSAndroid Build Coastguard Worker                                   {"--deduplicate-code=true"},
1292*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
1293*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
1294*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/false,
1295*795d594fSAndroid Build Coastguard Worker                                   [&dedupe_size](const OatFile& o) { dedupe_size = o.Size(); }));
1296*795d594fSAndroid Build Coastguard Worker 
1297*795d594fSAndroid Build Coastguard Worker   EXPECT_LT(dedupe_size, no_dedupe_size);
1298*795d594fSAndroid Build Coastguard Worker }
1299*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,UncompressedTest)1300*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, UncompressedTest) {
1301*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const DexFile> dex(OpenTestDexFile("MainUncompressedAligned"));
1302*795d594fSAndroid Build Coastguard Worker   std::string out_dir = GetScratchDir();
1303*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = out_dir + "/base.oat";
1304*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex->GetLocation(),
1305*795d594fSAndroid Build Coastguard Worker                                   base_oat_name,
1306*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kVerify,
1307*795d594fSAndroid Build Coastguard Worker                                   {},
1308*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
1309*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
1310*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/false,
1311*795d594fSAndroid Build Coastguard Worker                                   [](const OatFile& o) { CHECK(!o.ContainsDexCode()); }));
1312*795d594fSAndroid Build Coastguard Worker }
1313*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,MissingBootImageTest)1314*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, MissingBootImageTest) {
1315*795d594fSAndroid Build Coastguard Worker   std::string out_dir = GetScratchDir();
1316*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = out_dir + "/base.oat";
1317*795d594fSAndroid Build Coastguard Worker   // The compilation should succeed even without the boot image.
1318*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(
1319*795d594fSAndroid Build Coastguard Worker       {GetTestDexFileName("MainUncompressedAligned")},
1320*795d594fSAndroid Build Coastguard Worker       base_oat_name,
1321*795d594fSAndroid Build Coastguard Worker       CompilerFilter::Filter::kVerify,
1322*795d594fSAndroid Build Coastguard Worker       // Note: Extra options go last and the second `--boot-image` option overrides the first.
1323*795d594fSAndroid Build Coastguard Worker       {"--boot-image=/nonx/boot.art"}));
1324*795d594fSAndroid Build Coastguard Worker }
1325*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,EmptyUncompressedDexTest)1326*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, EmptyUncompressedDexTest) {
1327*795d594fSAndroid Build Coastguard Worker   std::string out_dir = GetScratchDir();
1328*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = out_dir + "/base.oat";
1329*795d594fSAndroid Build Coastguard Worker   // Expect to fail with code 1 and not SIGSEGV or SIGABRT.
1330*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(GenerateOdexForTestWithStatus({GetTestDexFileName("MainEmptyUncompressed")},
1331*795d594fSAndroid Build Coastguard Worker                                             base_oat_name,
1332*795d594fSAndroid Build Coastguard Worker                                             CompilerFilter::Filter::kVerify,
1333*795d594fSAndroid Build Coastguard Worker                                             /*extra_args*/ {},
1334*795d594fSAndroid Build Coastguard Worker                                             /*use_fd*/ false),
1335*795d594fSAndroid Build Coastguard Worker               HasValue(1));
1336*795d594fSAndroid Build Coastguard Worker }
1337*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,EmptyUncompressedAlignedDexTest)1338*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, EmptyUncompressedAlignedDexTest) {
1339*795d594fSAndroid Build Coastguard Worker   std::string out_dir = GetScratchDir();
1340*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = out_dir + "/base.oat";
1341*795d594fSAndroid Build Coastguard Worker   // Expect to fail with code 1 and not SIGSEGV or SIGABRT.
1342*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(GenerateOdexForTestWithStatus({GetTestDexFileName("MainEmptyUncompressedAligned")},
1343*795d594fSAndroid Build Coastguard Worker                                             base_oat_name,
1344*795d594fSAndroid Build Coastguard Worker                                             CompilerFilter::Filter::kVerify,
1345*795d594fSAndroid Build Coastguard Worker                                             /*extra_args*/ {},
1346*795d594fSAndroid Build Coastguard Worker                                             /*use_fd*/ false),
1347*795d594fSAndroid Build Coastguard Worker               HasValue(1));
1348*795d594fSAndroid Build Coastguard Worker }
1349*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,StderrLoggerOutput)1350*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, StderrLoggerOutput) {
1351*795d594fSAndroid Build Coastguard Worker   std::string dex_location = GetScratchDir() + "/Dex2OatStderrLoggerTest.jar";
1352*795d594fSAndroid Build Coastguard Worker   std::string odex_location = GetOdexDir() + "/Dex2OatStderrLoggerTest.odex";
1353*795d594fSAndroid Build Coastguard Worker 
1354*795d594fSAndroid Build Coastguard Worker   // Test file doesn't matter.
1355*795d594fSAndroid Build Coastguard Worker   Copy(GetDexSrc1(), dex_location);
1356*795d594fSAndroid Build Coastguard Worker 
1357*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1358*795d594fSAndroid Build Coastguard Worker                                   odex_location,
1359*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::kVerify,
1360*795d594fSAndroid Build Coastguard Worker                                   {"--runtime-arg", "-Xuse-stderr-logger"},
1361*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess));
1362*795d594fSAndroid Build Coastguard Worker   // Look for some random part of dex2oat logging. With the stderr logger this should be captured,
1363*795d594fSAndroid Build Coastguard Worker   // even on device.
1364*795d594fSAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos, output_.find("dex2oat took"));
1365*795d594fSAndroid Build Coastguard Worker }
1366*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,VerifyCompilationReason)1367*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, VerifyCompilationReason) {
1368*795d594fSAndroid Build Coastguard Worker   std::string dex_location = GetScratchDir() + "/Dex2OatCompilationReason.jar";
1369*795d594fSAndroid Build Coastguard Worker   std::string odex_location = GetOdexDir() + "/Dex2OatCompilationReason.odex";
1370*795d594fSAndroid Build Coastguard Worker 
1371*795d594fSAndroid Build Coastguard Worker   // Test file doesn't matter.
1372*795d594fSAndroid Build Coastguard Worker   Copy(GetDexSrc1(), dex_location);
1373*795d594fSAndroid Build Coastguard Worker 
1374*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1375*795d594fSAndroid Build Coastguard Worker                                   odex_location,
1376*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::kVerify,
1377*795d594fSAndroid Build Coastguard Worker                                   {"--compilation-reason=install"},
1378*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess));
1379*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
1380*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1381*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1382*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1383*795d594fSAndroid Build Coastguard Worker                                                    /*executable=*/false,
1384*795d594fSAndroid Build Coastguard Worker                                                    /*low_4gb=*/false,
1385*795d594fSAndroid Build Coastguard Worker                                                    dex_location,
1386*795d594fSAndroid Build Coastguard Worker                                                    &error_msg));
1387*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(odex_file != nullptr);
1388*795d594fSAndroid Build Coastguard Worker   ASSERT_STREQ("install", odex_file->GetCompilationReason());
1389*795d594fSAndroid Build Coastguard Worker }
1390*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,VerifyNoCompilationReason)1391*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, VerifyNoCompilationReason) {
1392*795d594fSAndroid Build Coastguard Worker   std::string dex_location = GetScratchDir() + "/Dex2OatNoCompilationReason.jar";
1393*795d594fSAndroid Build Coastguard Worker   std::string odex_location = GetOdexDir() + "/Dex2OatNoCompilationReason.odex";
1394*795d594fSAndroid Build Coastguard Worker 
1395*795d594fSAndroid Build Coastguard Worker   // Test file doesn't matter.
1396*795d594fSAndroid Build Coastguard Worker   Copy(GetDexSrc1(), dex_location);
1397*795d594fSAndroid Build Coastguard Worker 
1398*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1399*795d594fSAndroid Build Coastguard Worker                                   odex_location,
1400*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::kVerify,
1401*795d594fSAndroid Build Coastguard Worker                                   /*extra_args=*/{},
1402*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess));
1403*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
1404*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1405*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1406*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1407*795d594fSAndroid Build Coastguard Worker                                                    /*executable=*/false,
1408*795d594fSAndroid Build Coastguard Worker                                                    /*low_4gb=*/false,
1409*795d594fSAndroid Build Coastguard Worker                                                    dex_location,
1410*795d594fSAndroid Build Coastguard Worker                                                    &error_msg));
1411*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(odex_file != nullptr);
1412*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(nullptr, odex_file->GetCompilationReason());
1413*795d594fSAndroid Build Coastguard Worker }
1414*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,DontExtract)1415*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, DontExtract) {
1416*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1417*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
1418*795d594fSAndroid Build Coastguard Worker   const std::string out_dir = GetScratchDir();
1419*795d594fSAndroid Build Coastguard Worker   const std::string dex_location = dex->GetLocation();
1420*795d594fSAndroid Build Coastguard Worker   const std::string odex_location = out_dir + "/base.oat";
1421*795d594fSAndroid Build Coastguard Worker   const std::string vdex_location = out_dir + "/base.vdex";
1422*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1423*795d594fSAndroid Build Coastguard Worker                                   odex_location,
1424*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kVerify,
1425*795d594fSAndroid Build Coastguard Worker                                   {"--copy-dex-files=false"},
1426*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
1427*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
1428*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/false,
1429*795d594fSAndroid Build Coastguard Worker                                   [](const OatFile&) {}));
1430*795d594fSAndroid Build Coastguard Worker   {
1431*795d594fSAndroid Build Coastguard Worker     // Check the vdex doesn't have dex.
1432*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location,
1433*795d594fSAndroid Build Coastguard Worker                                                   /*writable=*/false,
1434*795d594fSAndroid Build Coastguard Worker                                                   /*low_4gb=*/false,
1435*795d594fSAndroid Build Coastguard Worker                                                   &error_msg));
1436*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(vdex != nullptr);
1437*795d594fSAndroid Build Coastguard Worker     EXPECT_FALSE(vdex->HasDexSection()) << output_;
1438*795d594fSAndroid Build Coastguard Worker   }
1439*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1440*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1441*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1442*795d594fSAndroid Build Coastguard Worker                                                    /*executable=*/false,
1443*795d594fSAndroid Build Coastguard Worker                                                    /*low_4gb=*/false,
1444*795d594fSAndroid Build Coastguard Worker                                                    dex_location,
1445*795d594fSAndroid Build Coastguard Worker                                                    &error_msg));
1446*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(odex_file != nullptr) << dex_location;
1447*795d594fSAndroid Build Coastguard Worker   std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1448*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(oat_dex_files.size(), 1u);
1449*795d594fSAndroid Build Coastguard Worker   // Verify that the oat file can still open the dex files.
1450*795d594fSAndroid Build Coastguard Worker   for (const OatDexFile* oat_dex : oat_dex_files) {
1451*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1452*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(dex_file != nullptr) << error_msg;
1453*795d594fSAndroid Build Coastguard Worker   }
1454*795d594fSAndroid Build Coastguard Worker   // Create a dm file and use it to verify.
1455*795d594fSAndroid Build Coastguard Worker   // Add produced artifacts to a zip file that doesn't contain the classes.dex.
1456*795d594fSAndroid Build Coastguard Worker   ScratchFile dm_file;
1457*795d594fSAndroid Build Coastguard Worker   {
1458*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_location.c_str()));
1459*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(vdex_file != nullptr);
1460*795d594fSAndroid Build Coastguard Worker     ASSERT_GT(vdex_file->GetLength(), 0u);
1461*795d594fSAndroid Build Coastguard Worker     FILE* file = fdopen(DupCloexec(dm_file.GetFd()), "w+b");
1462*795d594fSAndroid Build Coastguard Worker     ZipWriter writer(file);
1463*795d594fSAndroid Build Coastguard Worker     auto write_all_bytes = [&](File* file) {
1464*795d594fSAndroid Build Coastguard Worker       std::unique_ptr<uint8_t[]> bytes(new uint8_t[file->GetLength()]);
1465*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(file->ReadFully(&bytes[0], file->GetLength()));
1466*795d594fSAndroid Build Coastguard Worker       ASSERT_GE(writer.WriteBytes(&bytes[0], file->GetLength()), 0);
1467*795d594fSAndroid Build Coastguard Worker     };
1468*795d594fSAndroid Build Coastguard Worker     // Add vdex to zip.
1469*795d594fSAndroid Build Coastguard Worker     writer.StartEntry(VdexFile::kVdexNameInDmFile, ZipWriter::kCompress);
1470*795d594fSAndroid Build Coastguard Worker     write_all_bytes(vdex_file.get());
1471*795d594fSAndroid Build Coastguard Worker     writer.FinishEntry();
1472*795d594fSAndroid Build Coastguard Worker     writer.Finish();
1473*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(dm_file.GetFile()->Flush(), 0);
1474*795d594fSAndroid Build Coastguard Worker   }
1475*795d594fSAndroid Build Coastguard Worker 
1476*795d594fSAndroid Build Coastguard Worker   auto generate_and_check = [&](CompilerFilter::Filter filter) {
1477*795d594fSAndroid Build Coastguard Worker     output_.clear();
1478*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(GenerateOdexForTest(dex_location,
1479*795d594fSAndroid Build Coastguard Worker                                     odex_location,
1480*795d594fSAndroid Build Coastguard Worker                                     filter,
1481*795d594fSAndroid Build Coastguard Worker                                     {"--dump-timings",
1482*795d594fSAndroid Build Coastguard Worker                                      "--dm-file=" + dm_file.GetFilename(),
1483*795d594fSAndroid Build Coastguard Worker                                      // Pass -Xuse-stderr-logger have dex2oat output in output_ on
1484*795d594fSAndroid Build Coastguard Worker                                      // target.
1485*795d594fSAndroid Build Coastguard Worker                                      "--runtime-arg",
1486*795d594fSAndroid Build Coastguard Worker                                      "-Xuse-stderr-logger"},
1487*795d594fSAndroid Build Coastguard Worker                                     /*expect_status=*/Status::kSuccess,
1488*795d594fSAndroid Build Coastguard Worker                                     /*use_fd=*/false,
1489*795d594fSAndroid Build Coastguard Worker                                     /*use_zip_fd=*/false,
1490*795d594fSAndroid Build Coastguard Worker                                     [](const OatFile& o) { CHECK(o.ContainsDexCode()); }));
1491*795d594fSAndroid Build Coastguard Worker     // Check the output for "Fast verify", this is printed from --dump-timings.
1492*795d594fSAndroid Build Coastguard Worker     std::istringstream iss(output_);
1493*795d594fSAndroid Build Coastguard Worker     std::string line;
1494*795d594fSAndroid Build Coastguard Worker     bool found_fast_verify = false;
1495*795d594fSAndroid Build Coastguard Worker     const std::string kFastVerifyString = "Fast Verify";
1496*795d594fSAndroid Build Coastguard Worker     while (std::getline(iss, line) && !found_fast_verify) {
1497*795d594fSAndroid Build Coastguard Worker       found_fast_verify = found_fast_verify || line.find(kFastVerifyString) != std::string::npos;
1498*795d594fSAndroid Build Coastguard Worker     }
1499*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(found_fast_verify) << "Expected to find " << kFastVerifyString << "\n" << output_;
1500*795d594fSAndroid Build Coastguard Worker   };
1501*795d594fSAndroid Build Coastguard Worker 
1502*795d594fSAndroid Build Coastguard Worker   // Use verify compiler filter to check that FastVerify works for that filter too.
1503*795d594fSAndroid Build Coastguard Worker   generate_and_check(CompilerFilter::Filter::kVerify);
1504*795d594fSAndroid Build Coastguard Worker }
1505*795d594fSAndroid Build Coastguard Worker 
1506*795d594fSAndroid Build Coastguard Worker // Test that compact dex generation with invalid dex files doesn't crash dex2oat. b/75970654
TEST_F(Dex2oatTest,CompactDexInvalidSource)1507*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, CompactDexInvalidSource) {
1508*795d594fSAndroid Build Coastguard Worker   ScratchFile invalid_dex;
1509*795d594fSAndroid Build Coastguard Worker   {
1510*795d594fSAndroid Build Coastguard Worker     FILE* file = fdopen(DupCloexec(invalid_dex.GetFd()), "w+b");
1511*795d594fSAndroid Build Coastguard Worker     ZipWriter writer(file);
1512*795d594fSAndroid Build Coastguard Worker     writer.StartEntry("classes.dex", ZipWriter::kAlign32);
1513*795d594fSAndroid Build Coastguard Worker     DexFile::Header header = {};
1514*795d594fSAndroid Build Coastguard Worker     StandardDexFile::WriteMagic(header.magic_.data());
1515*795d594fSAndroid Build Coastguard Worker     StandardDexFile::WriteCurrentVersion(header.magic_.data());
1516*795d594fSAndroid Build Coastguard Worker     header.file_size_ = 4 * KB;
1517*795d594fSAndroid Build Coastguard Worker     header.data_size_ = 4 * KB;
1518*795d594fSAndroid Build Coastguard Worker     header.data_off_ = 10 * MB;
1519*795d594fSAndroid Build Coastguard Worker     header.map_off_ = 10 * MB;
1520*795d594fSAndroid Build Coastguard Worker     header.class_defs_off_ = 10 * MB;
1521*795d594fSAndroid Build Coastguard Worker     header.class_defs_size_ = 10000;
1522*795d594fSAndroid Build Coastguard Worker     ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
1523*795d594fSAndroid Build Coastguard Worker     writer.FinishEntry();
1524*795d594fSAndroid Build Coastguard Worker     writer.Finish();
1525*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
1526*795d594fSAndroid Build Coastguard Worker   }
1527*795d594fSAndroid Build Coastguard Worker   const std::string& dex_location = invalid_dex.GetFilename();
1528*795d594fSAndroid Build Coastguard Worker   const std::string odex_location = GetOdexDir() + "/output.odex";
1529*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(GenerateOdexForTestWithStatus(
1530*795d594fSAndroid Build Coastguard Worker                   {dex_location}, odex_location, CompilerFilter::kVerify, /*extra_args*/ {}),
1531*795d594fSAndroid Build Coastguard Worker               HasValue(Ne(0)))
1532*795d594fSAndroid Build Coastguard Worker       << " " << output_;
1533*795d594fSAndroid Build Coastguard Worker }
1534*795d594fSAndroid Build Coastguard Worker 
1535*795d594fSAndroid Build Coastguard Worker // Retain the header magic for the now removed compact dex files.
1536*795d594fSAndroid Build Coastguard Worker class LegacyCompactDexFile : public DexFile {
1537*795d594fSAndroid Build Coastguard Worker  public:
1538*795d594fSAndroid Build Coastguard Worker   static constexpr uint8_t kDexMagic[kDexMagicSize] = { 'c', 'd', 'e', 'x' };
1539*795d594fSAndroid Build Coastguard Worker   static constexpr uint8_t kDexMagicVersion[] = {'0', '0', '1', '\0'};
1540*795d594fSAndroid Build Coastguard Worker 
WriteMagic(uint8_t * magic)1541*795d594fSAndroid Build Coastguard Worker   static void WriteMagic(uint8_t* magic) {
1542*795d594fSAndroid Build Coastguard Worker     std::copy_n(kDexMagic, kDexMagicSize, magic);
1543*795d594fSAndroid Build Coastguard Worker   }
1544*795d594fSAndroid Build Coastguard Worker 
WriteCurrentVersion(uint8_t * magic)1545*795d594fSAndroid Build Coastguard Worker   static void WriteCurrentVersion(uint8_t* magic) {
1546*795d594fSAndroid Build Coastguard Worker     std::copy_n(kDexMagicVersion, kDexVersionLen, magic + kDexMagicSize);
1547*795d594fSAndroid Build Coastguard Worker   }
1548*795d594fSAndroid Build Coastguard Worker };
1549*795d594fSAndroid Build Coastguard Worker 
1550*795d594fSAndroid Build Coastguard Worker // Test that dex2oat with a legacy CompactDex file in the APK fails.
TEST_F(Dex2oatTest,CompactDexInZip)1551*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, CompactDexInZip) {
1552*795d594fSAndroid Build Coastguard Worker   LegacyCompactDexFile::Header header = {};
1553*795d594fSAndroid Build Coastguard Worker   LegacyCompactDexFile::WriteMagic(header.magic_.data());
1554*795d594fSAndroid Build Coastguard Worker   LegacyCompactDexFile::WriteCurrentVersion(header.magic_.data());
1555*795d594fSAndroid Build Coastguard Worker   header.file_size_ = sizeof(LegacyCompactDexFile::Header);
1556*795d594fSAndroid Build Coastguard Worker   header.map_off_ = 10 * MB;
1557*795d594fSAndroid Build Coastguard Worker   header.class_defs_off_ = 10 * MB;
1558*795d594fSAndroid Build Coastguard Worker   header.class_defs_size_ = 10000;
1559*795d594fSAndroid Build Coastguard Worker   // Create a zip containing the invalid dex.
1560*795d594fSAndroid Build Coastguard Worker   ScratchFile invalid_dex_zip;
1561*795d594fSAndroid Build Coastguard Worker   {
1562*795d594fSAndroid Build Coastguard Worker     FILE* file = fdopen(DupCloexec(invalid_dex_zip.GetFd()), "w+b");
1563*795d594fSAndroid Build Coastguard Worker     ZipWriter writer(file);
1564*795d594fSAndroid Build Coastguard Worker     writer.StartEntry("classes.dex", ZipWriter::kCompress);
1565*795d594fSAndroid Build Coastguard Worker     ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
1566*795d594fSAndroid Build Coastguard Worker     writer.FinishEntry();
1567*795d594fSAndroid Build Coastguard Worker     writer.Finish();
1568*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(invalid_dex_zip.GetFile()->Flush(), 0);
1569*795d594fSAndroid Build Coastguard Worker   }
1570*795d594fSAndroid Build Coastguard Worker   // Create the dex file directly.
1571*795d594fSAndroid Build Coastguard Worker   ScratchFile invalid_dex;
1572*795d594fSAndroid Build Coastguard Worker   {
1573*795d594fSAndroid Build Coastguard Worker     ASSERT_GE(invalid_dex.GetFile()->WriteFully(&header, sizeof(header)), 0);
1574*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
1575*795d594fSAndroid Build Coastguard Worker   }
1576*795d594fSAndroid Build Coastguard Worker 
1577*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(GenerateOdexForTestWithStatus({invalid_dex_zip.GetFilename()},
1578*795d594fSAndroid Build Coastguard Worker                                             GetOdexDir() + "/output_apk.odex",
1579*795d594fSAndroid Build Coastguard Worker                                             CompilerFilter::kVerify,
1580*795d594fSAndroid Build Coastguard Worker                                             /*extra_args*/ {}),
1581*795d594fSAndroid Build Coastguard Worker               HasValue(Ne(0)))
1582*795d594fSAndroid Build Coastguard Worker       << " " << output_;
1583*795d594fSAndroid Build Coastguard Worker 
1584*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(GenerateOdexForTestWithStatus({invalid_dex.GetFilename()},
1585*795d594fSAndroid Build Coastguard Worker                                             GetOdexDir() + "/output.odex",
1586*795d594fSAndroid Build Coastguard Worker                                             CompilerFilter::kVerify,
1587*795d594fSAndroid Build Coastguard Worker                                             /*extra_args*/ {}),
1588*795d594fSAndroid Build Coastguard Worker               HasValue(Ne(0)))
1589*795d594fSAndroid Build Coastguard Worker       << " " << output_;
1590*795d594fSAndroid Build Coastguard Worker }
1591*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatWithExpectedFilterTest,AppImageNoProfile)1592*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatWithExpectedFilterTest, AppImageNoProfile) {
1593*795d594fSAndroid Build Coastguard Worker   // Set the expected filter.
1594*795d594fSAndroid Build Coastguard Worker   expected_filter_ = CompilerFilter::Filter::kVerify;
1595*795d594fSAndroid Build Coastguard Worker 
1596*795d594fSAndroid Build Coastguard Worker   ScratchFile app_image_file;
1597*795d594fSAndroid Build Coastguard Worker   const std::string out_dir = GetScratchDir();
1598*795d594fSAndroid Build Coastguard Worker   const std::string odex_location = out_dir + "/base.odex";
1599*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
1600*795d594fSAndroid Build Coastguard Worker                                   odex_location,
1601*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kSpeedProfile,
1602*795d594fSAndroid Build Coastguard Worker                                   {"--app-image-fd=" + std::to_string(app_image_file.GetFd())},
1603*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
1604*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
1605*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/false,
1606*795d594fSAndroid Build Coastguard Worker                                   [](const OatFile&) {}));
1607*795d594fSAndroid Build Coastguard Worker   // Open our generated oat file.
1608*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
1609*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1610*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1611*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1612*795d594fSAndroid Build Coastguard Worker                                                    /*executable=*/false,
1613*795d594fSAndroid Build Coastguard Worker                                                    /*low_4gb=*/false,
1614*795d594fSAndroid Build Coastguard Worker                                                    &error_msg));
1615*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(odex_file != nullptr);
1616*795d594fSAndroid Build Coastguard Worker   ImageHeader header = {};
1617*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(app_image_file.GetFile()->PreadFully(reinterpret_cast<void*>(&header),
1618*795d594fSAndroid Build Coastguard Worker                                                    sizeof(header),
1619*795d594fSAndroid Build Coastguard Worker                                                    /*offset*/ 0u))
1620*795d594fSAndroid Build Coastguard Worker       << app_image_file.GetFile()->GetLength();
1621*795d594fSAndroid Build Coastguard Worker   EXPECT_GT(header.GetImageSection(ImageHeader::kSectionObjects).Size(), 0u);
1622*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtMethods).Size(), 0u);
1623*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtFields).Size(), 0u);
1624*795d594fSAndroid Build Coastguard Worker }
1625*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,ZipFd)1626*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, ZipFd) {
1627*795d594fSAndroid Build Coastguard Worker   std::string zip_location = GetTestDexFileName("MainUncompressedAligned");
1628*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> dex_file(OS::OpenFileForReading(zip_location.c_str()));
1629*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> extra_args{
1630*795d594fSAndroid Build Coastguard Worker       StringPrintf("--zip-fd=%d", dex_file->Fd()),
1631*795d594fSAndroid Build Coastguard Worker       "--zip-location=" + zip_location,
1632*795d594fSAndroid Build Coastguard Worker   };
1633*795d594fSAndroid Build Coastguard Worker   std::string out_dir = GetScratchDir();
1634*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = out_dir + "/base.oat";
1635*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(zip_location,
1636*795d594fSAndroid Build Coastguard Worker                                   base_oat_name,
1637*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kVerify,
1638*795d594fSAndroid Build Coastguard Worker                                   extra_args,
1639*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
1640*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
1641*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/true));
1642*795d594fSAndroid Build Coastguard Worker }
1643*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatWithExpectedFilterTest,AppImageEmptyDex)1644*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatWithExpectedFilterTest, AppImageEmptyDex) {
1645*795d594fSAndroid Build Coastguard Worker   // Set the expected filter.
1646*795d594fSAndroid Build Coastguard Worker   expected_filter_ = CompilerFilter::Filter::kVerify;
1647*795d594fSAndroid Build Coastguard Worker 
1648*795d594fSAndroid Build Coastguard Worker   // Create a profile with the startup method marked.
1649*795d594fSAndroid Build Coastguard Worker   ScratchFile profile_file;
1650*795d594fSAndroid Build Coastguard Worker   ScratchFile temp_dex;
1651*795d594fSAndroid Build Coastguard Worker   const std::string& dex_location = temp_dex.GetFilename();
1652*795d594fSAndroid Build Coastguard Worker   std::vector<uint16_t> methods;
1653*795d594fSAndroid Build Coastguard Worker   std::vector<dex::TypeIndex> classes;
1654*795d594fSAndroid Build Coastguard Worker   {
1655*795d594fSAndroid Build Coastguard Worker     MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("StringLiterals"), [&](DexFile* dex) {
1656*795d594fSAndroid Build Coastguard Worker       // Modify the header to make the dex file valid but empty.
1657*795d594fSAndroid Build Coastguard Worker       DexFile::Header* header = const_cast<DexFile::Header*>(&dex->GetHeader());
1658*795d594fSAndroid Build Coastguard Worker       header->string_ids_size_ = 0;
1659*795d594fSAndroid Build Coastguard Worker       header->string_ids_off_ = 0;
1660*795d594fSAndroid Build Coastguard Worker       header->type_ids_size_ = 0;
1661*795d594fSAndroid Build Coastguard Worker       header->type_ids_off_ = 0;
1662*795d594fSAndroid Build Coastguard Worker       header->proto_ids_size_ = 0;
1663*795d594fSAndroid Build Coastguard Worker       header->proto_ids_off_ = 0;
1664*795d594fSAndroid Build Coastguard Worker       header->field_ids_size_ = 0;
1665*795d594fSAndroid Build Coastguard Worker       header->field_ids_off_ = 0;
1666*795d594fSAndroid Build Coastguard Worker       header->method_ids_size_ = 0;
1667*795d594fSAndroid Build Coastguard Worker       header->method_ids_off_ = 0;
1668*795d594fSAndroid Build Coastguard Worker       header->class_defs_size_ = 0;
1669*795d594fSAndroid Build Coastguard Worker       header->class_defs_off_ = 0;
1670*795d594fSAndroid Build Coastguard Worker       ASSERT_GT(header->file_size_,
1671*795d594fSAndroid Build Coastguard Worker                 sizeof(*header) + sizeof(dex::MapList) + sizeof(dex::MapItem) * 2);
1672*795d594fSAndroid Build Coastguard Worker       // Move map list to be right after the header.
1673*795d594fSAndroid Build Coastguard Worker       header->map_off_ = header->header_size_;
1674*795d594fSAndroid Build Coastguard Worker       dex::MapList* map_list = const_cast<dex::MapList*>(dex->GetMapList());
1675*795d594fSAndroid Build Coastguard Worker       map_list->list_[0].type_ = DexFile::kDexTypeHeaderItem;
1676*795d594fSAndroid Build Coastguard Worker       map_list->list_[0].size_ = 1u;
1677*795d594fSAndroid Build Coastguard Worker       map_list->list_[0].offset_ = 0u;
1678*795d594fSAndroid Build Coastguard Worker       map_list->list_[1].type_ = DexFile::kDexTypeMapList;
1679*795d594fSAndroid Build Coastguard Worker       map_list->list_[1].size_ = 1u;
1680*795d594fSAndroid Build Coastguard Worker       map_list->list_[1].offset_ = header->map_off_;
1681*795d594fSAndroid Build Coastguard Worker       map_list->size_ = 2;
1682*795d594fSAndroid Build Coastguard Worker       header->data_off_ = header->map_off_;
1683*795d594fSAndroid Build Coastguard Worker       header->data_size_ = map_list->Size();
1684*795d594fSAndroid Build Coastguard Worker       header->SetDexContainer(0, header->file_size_);
1685*795d594fSAndroid Build Coastguard Worker     });
1686*795d594fSAndroid Build Coastguard Worker   }
1687*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const DexFile> dex_file(OpenDexFile(temp_dex.GetFilename().c_str()));
1688*795d594fSAndroid Build Coastguard Worker   const std::string out_dir = GetScratchDir();
1689*795d594fSAndroid Build Coastguard Worker   const std::string odex_location = out_dir + "/base.odex";
1690*795d594fSAndroid Build Coastguard Worker   const std::string app_image_location = out_dir + "/base.art";
1691*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1692*795d594fSAndroid Build Coastguard Worker                                   odex_location,
1693*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kSpeedProfile,
1694*795d594fSAndroid Build Coastguard Worker                                   {"--app-image-file=" + app_image_location,
1695*795d594fSAndroid Build Coastguard Worker                                    "--resolve-startup-const-strings=true",
1696*795d594fSAndroid Build Coastguard Worker                                    "--profile-file=" + profile_file.GetFilename()},
1697*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
1698*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
1699*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/false,
1700*795d594fSAndroid Build Coastguard Worker                                   [](const OatFile&) {}));
1701*795d594fSAndroid Build Coastguard Worker   // Open our generated oat file.
1702*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
1703*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1704*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1705*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1706*795d594fSAndroid Build Coastguard Worker                                                    /*executable=*/false,
1707*795d594fSAndroid Build Coastguard Worker                                                    /*low_4gb=*/false,
1708*795d594fSAndroid Build Coastguard Worker                                                    &error_msg));
1709*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(odex_file != nullptr);
1710*795d594fSAndroid Build Coastguard Worker }
1711*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatWithExpectedFilterTest,AppImageNonexistentDex)1712*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatWithExpectedFilterTest, AppImageNonexistentDex) {
1713*795d594fSAndroid Build Coastguard Worker   const std::string out_dir = GetScratchDir();
1714*795d594fSAndroid Build Coastguard Worker   // Test that dex2oat does not crash trying to compile app image with zero DEX files.
1715*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(
1716*795d594fSAndroid Build Coastguard Worker       out_dir + "/base.apk",
1717*795d594fSAndroid Build Coastguard Worker       out_dir + "/base.odex",
1718*795d594fSAndroid Build Coastguard Worker       CompilerFilter::Filter::kSpeedProfile,
1719*795d594fSAndroid Build Coastguard Worker       {"--dex-file=nonexistent.apk", "--app-image-file=" + out_dir + "/base.art"},
1720*795d594fSAndroid Build Coastguard Worker       /*expect_status=*/Status::kFailOpenOat,
1721*795d594fSAndroid Build Coastguard Worker       /*use_fd=*/false,
1722*795d594fSAndroid Build Coastguard Worker       /*use_zip_fd=*/false,
1723*795d594fSAndroid Build Coastguard Worker       [](const OatFile&) {}));
1724*795d594fSAndroid Build Coastguard Worker }
1725*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,DexFileFd)1726*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, DexFileFd) {
1727*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
1728*795d594fSAndroid Build Coastguard Worker   std::string zip_location = GetTestDexFileName("Main");
1729*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> zip_file(OS::OpenFileForReading(zip_location.c_str()));
1730*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(-1, zip_file->Fd());
1731*795d594fSAndroid Build Coastguard Worker 
1732*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ZipArchive> zip_archive(
1733*795d594fSAndroid Build Coastguard Worker       ZipArchive::OpenFromFd(zip_file->Release(), zip_location.c_str(), &error_msg));
1734*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(zip_archive != nullptr);
1735*795d594fSAndroid Build Coastguard Worker 
1736*795d594fSAndroid Build Coastguard Worker   std::string entry_name = DexFileLoader::GetMultiDexClassesDexName(0);
1737*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ZipEntry> entry(zip_archive->Find(entry_name.c_str(), &error_msg));
1738*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(entry != nullptr);
1739*795d594fSAndroid Build Coastguard Worker 
1740*795d594fSAndroid Build Coastguard Worker   ScratchFile dex_file;
1741*795d594fSAndroid Build Coastguard Worker   const std::string& dex_location = dex_file.GetFilename();
1742*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = GetScratchDir() + "/base.oat";
1743*795d594fSAndroid Build Coastguard Worker 
1744*795d594fSAndroid Build Coastguard Worker   bool success = entry->ExtractToFile(*(dex_file.GetFile()), &error_msg);
1745*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(success);
1746*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, lseek(dex_file.GetFd(), 0, SEEK_SET));
1747*795d594fSAndroid Build Coastguard Worker 
1748*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> extra_args{
1749*795d594fSAndroid Build Coastguard Worker       StringPrintf("--zip-fd=%d", dex_file.GetFd()),
1750*795d594fSAndroid Build Coastguard Worker       "--zip-location=" + dex_location,
1751*795d594fSAndroid Build Coastguard Worker   };
1752*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1753*795d594fSAndroid Build Coastguard Worker                                   base_oat_name,
1754*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kVerify,
1755*795d594fSAndroid Build Coastguard Worker                                   extra_args,
1756*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
1757*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
1758*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/true));
1759*795d594fSAndroid Build Coastguard Worker }
1760*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,DontCopyPlainDex)1761*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, DontCopyPlainDex) {
1762*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDepsMulti"));
1763*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
1764*795d594fSAndroid Build Coastguard Worker   const std::string out_dir = GetScratchDir();
1765*795d594fSAndroid Build Coastguard Worker   const std::string dex_location = dex->GetLocation();
1766*795d594fSAndroid Build Coastguard Worker   const std::string odex_location = out_dir + "/base.oat";
1767*795d594fSAndroid Build Coastguard Worker   const std::string vdex_location = out_dir + "/base.vdex";
1768*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1769*795d594fSAndroid Build Coastguard Worker                                   odex_location,
1770*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kVerify,
1771*795d594fSAndroid Build Coastguard Worker                                   /*extra_args=*/{},
1772*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
1773*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
1774*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/false,
1775*795d594fSAndroid Build Coastguard Worker                                   [](const OatFile&) {}));
1776*795d594fSAndroid Build Coastguard Worker 
1777*795d594fSAndroid Build Coastguard Worker   // Check that the vdex doesn't have dex code.
1778*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location,
1779*795d594fSAndroid Build Coastguard Worker                                                 /*writable=*/false,
1780*795d594fSAndroid Build Coastguard Worker                                                 /*low_4gb=*/false,
1781*795d594fSAndroid Build Coastguard Worker                                                 &error_msg));
1782*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(vdex != nullptr);
1783*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(vdex->HasDexSection()) << output_;
1784*795d594fSAndroid Build Coastguard Worker }
1785*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatTest,AppImageResolveStrings)1786*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, AppImageResolveStrings) {
1787*795d594fSAndroid Build Coastguard Worker   using Hotness = ProfileCompilationInfo::MethodHotness;
1788*795d594fSAndroid Build Coastguard Worker   // Create a profile with the startup method marked.
1789*795d594fSAndroid Build Coastguard Worker   ScratchFile profile_file;
1790*795d594fSAndroid Build Coastguard Worker   ScratchFile temp_dex;
1791*795d594fSAndroid Build Coastguard Worker   const std::string& dex_location = temp_dex.GetFilename();
1792*795d594fSAndroid Build Coastguard Worker   std::vector<uint16_t> methods;
1793*795d594fSAndroid Build Coastguard Worker   std::vector<dex::TypeIndex> classes;
1794*795d594fSAndroid Build Coastguard Worker   {
1795*795d594fSAndroid Build Coastguard Worker     MutateDexFile(
1796*795d594fSAndroid Build Coastguard Worker         temp_dex.GetFile(), GetTestDexFileName("StringLiterals"), [&](DexFile* dex) {
1797*795d594fSAndroid Build Coastguard Worker           bool mutated_successfully = false;
1798*795d594fSAndroid Build Coastguard Worker           // Change the dex instructions to make an opcode that spans past the end of the code item.
1799*795d594fSAndroid Build Coastguard Worker           for (ClassAccessor accessor : dex->GetClasses()) {
1800*795d594fSAndroid Build Coastguard Worker             if (accessor.GetDescriptor() == std::string("LStringLiterals$StartupClass;")) {
1801*795d594fSAndroid Build Coastguard Worker               classes.push_back(accessor.GetClassIdx());
1802*795d594fSAndroid Build Coastguard Worker             }
1803*795d594fSAndroid Build Coastguard Worker             for (const ClassAccessor::Method& method : accessor.GetMethods()) {
1804*795d594fSAndroid Build Coastguard Worker               std::string method_name(dex->GetMethodName(dex->GetMethodId(method.GetIndex())));
1805*795d594fSAndroid Build Coastguard Worker               CodeItemInstructionAccessor instructions = method.GetInstructions();
1806*795d594fSAndroid Build Coastguard Worker               if (method_name == "startUpMethod2") {
1807*795d594fSAndroid Build Coastguard Worker                 // Make an instruction that runs past the end of the code item and verify that it
1808*795d594fSAndroid Build Coastguard Worker                 // doesn't cause dex2oat to crash.
1809*795d594fSAndroid Build Coastguard Worker                 ASSERT_TRUE(instructions.begin() != instructions.end());
1810*795d594fSAndroid Build Coastguard Worker                 DexInstructionIterator last_instruction = instructions.begin();
1811*795d594fSAndroid Build Coastguard Worker                 for (auto dex_it = instructions.begin(); dex_it != instructions.end(); ++dex_it) {
1812*795d594fSAndroid Build Coastguard Worker                   last_instruction = dex_it;
1813*795d594fSAndroid Build Coastguard Worker                 }
1814*795d594fSAndroid Build Coastguard Worker                 ASSERT_EQ(last_instruction->SizeInCodeUnits(), 1u);
1815*795d594fSAndroid Build Coastguard Worker                 // Set the opcode to something that will go past the end of the code item.
1816*795d594fSAndroid Build Coastguard Worker                 const_cast<Instruction&>(last_instruction.Inst())
1817*795d594fSAndroid Build Coastguard Worker                     .SetOpcode(Instruction::CONST_STRING_JUMBO);
1818*795d594fSAndroid Build Coastguard Worker                 mutated_successfully = true;
1819*795d594fSAndroid Build Coastguard Worker                 // Test that the safe iterator doesn't go past the end.
1820*795d594fSAndroid Build Coastguard Worker                 SafeDexInstructionIterator it2(instructions.begin(), instructions.end());
1821*795d594fSAndroid Build Coastguard Worker                 while (!it2.IsErrorState()) {
1822*795d594fSAndroid Build Coastguard Worker                   ++it2;
1823*795d594fSAndroid Build Coastguard Worker                 }
1824*795d594fSAndroid Build Coastguard Worker                 EXPECT_TRUE(it2 == last_instruction);
1825*795d594fSAndroid Build Coastguard Worker                 EXPECT_TRUE(it2 < instructions.end());
1826*795d594fSAndroid Build Coastguard Worker                 methods.push_back(method.GetIndex());
1827*795d594fSAndroid Build Coastguard Worker                 mutated_successfully = true;
1828*795d594fSAndroid Build Coastguard Worker               } else if (method_name == "startUpMethod") {
1829*795d594fSAndroid Build Coastguard Worker                 methods.push_back(method.GetIndex());
1830*795d594fSAndroid Build Coastguard Worker               }
1831*795d594fSAndroid Build Coastguard Worker             }
1832*795d594fSAndroid Build Coastguard Worker           }
1833*795d594fSAndroid Build Coastguard Worker           CHECK(mutated_successfully)
1834*795d594fSAndroid Build Coastguard Worker               << "Failed to find candidate code item with only one code unit in last instruction.";
1835*795d594fSAndroid Build Coastguard Worker         });
1836*795d594fSAndroid Build Coastguard Worker   }
1837*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const DexFile> dex_file(OpenDexFile(temp_dex.GetFilename().c_str()));
1838*795d594fSAndroid Build Coastguard Worker   {
1839*795d594fSAndroid Build Coastguard Worker     ASSERT_GT(classes.size(), 0u);
1840*795d594fSAndroid Build Coastguard Worker     ASSERT_GT(methods.size(), 0u);
1841*795d594fSAndroid Build Coastguard Worker     // Here, we build the profile from the method lists.
1842*795d594fSAndroid Build Coastguard Worker     ProfileCompilationInfo info;
1843*795d594fSAndroid Build Coastguard Worker     info.AddClassesForDex(dex_file.get(), classes.begin(), classes.end());
1844*795d594fSAndroid Build Coastguard Worker     info.AddMethodsForDex(Hotness::kFlagStartup, dex_file.get(), methods.begin(), methods.end());
1845*795d594fSAndroid Build Coastguard Worker     // Save the profile since we want to use it with dex2oat to produce an oat file.
1846*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(info.Save(profile_file.GetFd()));
1847*795d594fSAndroid Build Coastguard Worker   }
1848*795d594fSAndroid Build Coastguard Worker   const std::string out_dir = GetScratchDir();
1849*795d594fSAndroid Build Coastguard Worker   const std::string odex_location = out_dir + "/base.odex";
1850*795d594fSAndroid Build Coastguard Worker   const std::string app_image_location = out_dir + "/base.art";
1851*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1852*795d594fSAndroid Build Coastguard Worker                                   odex_location,
1853*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kSpeedProfile,
1854*795d594fSAndroid Build Coastguard Worker                                   {"--app-image-file=" + app_image_location,
1855*795d594fSAndroid Build Coastguard Worker                                    "--resolve-startup-const-strings=true",
1856*795d594fSAndroid Build Coastguard Worker                                    "--profile-file=" + profile_file.GetFilename()},
1857*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
1858*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
1859*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/false,
1860*795d594fSAndroid Build Coastguard Worker                                   [](const OatFile&) {}));
1861*795d594fSAndroid Build Coastguard Worker   // Open our generated oat file.
1862*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
1863*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1864*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1865*795d594fSAndroid Build Coastguard Worker                                                    odex_location,
1866*795d594fSAndroid Build Coastguard Worker                                                    /*executable=*/false,
1867*795d594fSAndroid Build Coastguard Worker                                                    /*low_4gb=*/false,
1868*795d594fSAndroid Build Coastguard Worker                                                    &error_msg));
1869*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(odex_file != nullptr);
1870*795d594fSAndroid Build Coastguard Worker   // Check the strings in the app image intern table only contain the "startup" strigs.
1871*795d594fSAndroid Build Coastguard Worker   {
1872*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<gc::space::ImageSpace> space = gc::space::ImageSpace::CreateFromAppImage(
1873*795d594fSAndroid Build Coastguard Worker         app_image_location.c_str(), odex_file.get(), &error_msg);
1874*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(space != nullptr) << error_msg;
1875*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
1876*795d594fSAndroid Build Coastguard Worker     std::set<std::string> seen;
1877*795d594fSAndroid Build Coastguard Worker     InternTable intern_table;
1878*795d594fSAndroid Build Coastguard Worker     intern_table.AddImageStringsToTable(
1879*795d594fSAndroid Build Coastguard Worker         space.get(), [&](InternTable::UnorderedSet& interns) REQUIRES_SHARED(Locks::mutator_lock_) {
1880*795d594fSAndroid Build Coastguard Worker           for (const GcRoot<mirror::String>& str : interns) {
1881*795d594fSAndroid Build Coastguard Worker             seen.insert(str.Read()->ToModifiedUtf8());
1882*795d594fSAndroid Build Coastguard Worker           }
1883*795d594fSAndroid Build Coastguard Worker         });
1884*795d594fSAndroid Build Coastguard Worker     // Normal methods
1885*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(seen.find("Loading ") != seen.end());
1886*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(seen.find("Starting up") != seen.end());
1887*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(seen.find("abcd.apk") != seen.end());
1888*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(seen.find("Unexpected error") == seen.end());
1889*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(seen.find("Shutting down!") == seen.end());
1890*795d594fSAndroid Build Coastguard Worker     // Classes initializers
1891*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(seen.find("Startup init") != seen.end());
1892*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(seen.find("Other class init") == seen.end());
1893*795d594fSAndroid Build Coastguard Worker     // Expect the sets match.
1894*795d594fSAndroid Build Coastguard Worker     EXPECT_GE(seen.size(), seen.size());
1895*795d594fSAndroid Build Coastguard Worker 
1896*795d594fSAndroid Build Coastguard Worker     // Verify what strings are marked as boot image.
1897*795d594fSAndroid Build Coastguard Worker     std::set<std::string> boot_image_strings;
1898*795d594fSAndroid Build Coastguard Worker     std::set<std::string> app_image_strings;
1899*795d594fSAndroid Build Coastguard Worker 
1900*795d594fSAndroid Build Coastguard Worker     MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
1901*795d594fSAndroid Build Coastguard Worker     intern_table.VisitInterns(
1902*795d594fSAndroid Build Coastguard Worker         [&](const GcRoot<mirror::String>& root) REQUIRES_SHARED(Locks::mutator_lock_) {
1903*795d594fSAndroid Build Coastguard Worker           boot_image_strings.insert(root.Read()->ToModifiedUtf8());
1904*795d594fSAndroid Build Coastguard Worker         },
1905*795d594fSAndroid Build Coastguard Worker         /*visit_boot_images=*/true,
1906*795d594fSAndroid Build Coastguard Worker         /*visit_non_boot_images=*/false);
1907*795d594fSAndroid Build Coastguard Worker     intern_table.VisitInterns(
1908*795d594fSAndroid Build Coastguard Worker         [&](const GcRoot<mirror::String>& root) REQUIRES_SHARED(Locks::mutator_lock_) {
1909*795d594fSAndroid Build Coastguard Worker           app_image_strings.insert(root.Read()->ToModifiedUtf8());
1910*795d594fSAndroid Build Coastguard Worker         },
1911*795d594fSAndroid Build Coastguard Worker         /*visit_boot_images=*/false,
1912*795d594fSAndroid Build Coastguard Worker         /*visit_non_boot_images=*/true);
1913*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(boot_image_strings.size(), 0u);
1914*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(app_image_strings == seen);
1915*795d594fSAndroid Build Coastguard Worker   }
1916*795d594fSAndroid Build Coastguard Worker }
1917*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatClassLoaderContextTest,StoredClassLoaderContext)1918*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatClassLoaderContextTest, StoredClassLoaderContext) {
1919*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("MultiDex");
1920*795d594fSAndroid Build Coastguard Worker   const std::string out_dir = GetScratchDir();
1921*795d594fSAndroid Build Coastguard Worker   const std::string odex_location = out_dir + "/base.odex";
1922*795d594fSAndroid Build Coastguard Worker   const std::string valid_context = "PCL[" + dex_files[0]->GetLocation() + "]";
1923*795d594fSAndroid Build Coastguard Worker   const std::string stored_context = "PCL[/system/not_real_lib.jar]";
1924*795d594fSAndroid Build Coastguard Worker   uint32_t checksum = DexFileLoader::GetMultiDexChecksum(dex_files);
1925*795d594fSAndroid Build Coastguard Worker   std::string expected_stored_context =
1926*795d594fSAndroid Build Coastguard Worker       "PCL[/system/not_real_lib.jar*" + std::to_string(checksum) + "]";
1927*795d594fSAndroid Build Coastguard Worker   // The class path should not be valid and should fail being stored.
1928*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
1929*795d594fSAndroid Build Coastguard Worker                                   odex_location,
1930*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kVerify,
1931*795d594fSAndroid Build Coastguard Worker                                   {"--class-loader-context=" + stored_context},
1932*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
1933*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
1934*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/false,
1935*795d594fSAndroid Build Coastguard Worker                                   [&](const OatFile& oat_file) {
1936*795d594fSAndroid Build Coastguard Worker                                     EXPECT_NE(oat_file.GetClassLoaderContext(), stored_context)
1937*795d594fSAndroid Build Coastguard Worker                                         << output_;
1938*795d594fSAndroid Build Coastguard Worker                                     EXPECT_NE(oat_file.GetClassLoaderContext(), valid_context)
1939*795d594fSAndroid Build Coastguard Worker                                         << output_;
1940*795d594fSAndroid Build Coastguard Worker                                   }));
1941*795d594fSAndroid Build Coastguard Worker   // The stored context should match what we expect even though it's invalid.
1942*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(GenerateOdexForTest(
1943*795d594fSAndroid Build Coastguard Worker       GetTestDexFileName("ManyMethods"),
1944*795d594fSAndroid Build Coastguard Worker       odex_location,
1945*795d594fSAndroid Build Coastguard Worker       CompilerFilter::Filter::kVerify,
1946*795d594fSAndroid Build Coastguard Worker       {"--class-loader-context=" + valid_context,
1947*795d594fSAndroid Build Coastguard Worker        "--stored-class-loader-context=" + stored_context},
1948*795d594fSAndroid Build Coastguard Worker       /*expect_status=*/Status::kSuccess,
1949*795d594fSAndroid Build Coastguard Worker       /*use_fd=*/false,
1950*795d594fSAndroid Build Coastguard Worker       /*use_zip_fd=*/false,
1951*795d594fSAndroid Build Coastguard Worker       [&](const OatFile& oat_file) {
1952*795d594fSAndroid Build Coastguard Worker         EXPECT_EQ(oat_file.GetClassLoaderContext(), expected_stored_context) << output_;
1953*795d594fSAndroid Build Coastguard Worker       }));
1954*795d594fSAndroid Build Coastguard Worker }
1955*795d594fSAndroid Build Coastguard Worker 
1956*795d594fSAndroid Build Coastguard Worker class Dex2oatISAFeaturesRuntimeDetectionTest : public Dex2oatTest {
1957*795d594fSAndroid Build Coastguard Worker  protected:
RunTest(const std::vector<std::string> & extra_args={})1958*795d594fSAndroid Build Coastguard Worker   void RunTest(const std::vector<std::string>& extra_args = {}) {
1959*795d594fSAndroid Build Coastguard Worker     std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
1960*795d594fSAndroid Build Coastguard Worker     std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
1961*795d594fSAndroid Build Coastguard Worker 
1962*795d594fSAndroid Build Coastguard Worker     Copy(GetTestDexFileName(), dex_location);
1963*795d594fSAndroid Build Coastguard Worker 
1964*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(
1965*795d594fSAndroid Build Coastguard Worker         GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, extra_args));
1966*795d594fSAndroid Build Coastguard Worker   }
1967*795d594fSAndroid Build Coastguard Worker 
GetTestDexFileName()1968*795d594fSAndroid Build Coastguard Worker   std::string GetTestDexFileName() { return GetDexSrc1(); }
1969*795d594fSAndroid Build Coastguard Worker };
1970*795d594fSAndroid Build Coastguard Worker 
TEST_F(Dex2oatISAFeaturesRuntimeDetectionTest,TestCurrentRuntimeFeaturesAsDex2OatArguments)1971*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatISAFeaturesRuntimeDetectionTest, TestCurrentRuntimeFeaturesAsDex2OatArguments) {
1972*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> argv;
1973*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
1974*795d594fSAndroid Build Coastguard Worker   auto option_pos =
1975*795d594fSAndroid Build Coastguard Worker       std::find(std::begin(argv), std::end(argv), "--instruction-set-features=runtime");
1976*795d594fSAndroid Build Coastguard Worker   if (InstructionSetFeatures::IsRuntimeDetectionSupported()) {
1977*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(kIsTargetBuild);
1978*795d594fSAndroid Build Coastguard Worker     EXPECT_NE(option_pos, std::end(argv));
1979*795d594fSAndroid Build Coastguard Worker   } else {
1980*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(option_pos, std::end(argv));
1981*795d594fSAndroid Build Coastguard Worker   }
1982*795d594fSAndroid Build Coastguard Worker 
1983*795d594fSAndroid Build Coastguard Worker   RunTest();
1984*795d594fSAndroid Build Coastguard Worker }
1985*795d594fSAndroid Build Coastguard Worker 
1986*795d594fSAndroid Build Coastguard Worker class LinkageTest : public Dex2oatTest {};
1987*795d594fSAndroid Build Coastguard Worker 
TEST_F(LinkageTest,LinkageEnabled)1988*795d594fSAndroid Build Coastguard Worker TEST_F(LinkageTest, LinkageEnabled) {
1989*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_TARGET();
1990*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const DexFile> dex(OpenTestDexFile("LinkageTest"));
1991*795d594fSAndroid Build Coastguard Worker   std::string out_dir = GetScratchDir();
1992*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = out_dir + "/base.oat";
1993*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(
1994*795d594fSAndroid Build Coastguard Worker       GenerateOdexForTestWithStatus({dex->GetLocation()},
1995*795d594fSAndroid Build Coastguard Worker                                     base_oat_name,
1996*795d594fSAndroid Build Coastguard Worker                                     CompilerFilter::Filter::kSpeed,
1997*795d594fSAndroid Build Coastguard Worker                                     {"--check-linkage-conditions", "--crash-on-linkage-violation"}),
1998*795d594fSAndroid Build Coastguard Worker       Not(Ok()));
1999*795d594fSAndroid Build Coastguard Worker 
2000*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(GenerateOdexForTestWithStatus({dex->GetLocation()},
2001*795d594fSAndroid Build Coastguard Worker                                             base_oat_name,
2002*795d594fSAndroid Build Coastguard Worker                                             CompilerFilter::Filter::kSpeed,
2003*795d594fSAndroid Build Coastguard Worker                                             {"--check-linkage-conditions"}),
2004*795d594fSAndroid Build Coastguard Worker               HasValue(0));
2005*795d594fSAndroid Build Coastguard Worker }
2006*795d594fSAndroid Build Coastguard Worker 
2007*795d594fSAndroid Build Coastguard Worker // Regression test for bug 179221298.
TEST_F(Dex2oatTest,LoadOutOfDateOatFile)2008*795d594fSAndroid Build Coastguard Worker TEST_F(Dex2oatTest, LoadOutOfDateOatFile) {
2009*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
2010*795d594fSAndroid Build Coastguard Worker   std::string out_dir = GetScratchDir();
2011*795d594fSAndroid Build Coastguard Worker   const std::string base_oat_name = out_dir + "/base.oat";
2012*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(GenerateOdexForTest(dex->GetLocation(),
2013*795d594fSAndroid Build Coastguard Worker                                   base_oat_name,
2014*795d594fSAndroid Build Coastguard Worker                                   CompilerFilter::Filter::kSpeed,
2015*795d594fSAndroid Build Coastguard Worker                                   {"--deduplicate-code=false"},
2016*795d594fSAndroid Build Coastguard Worker                                   /*expect_status=*/Status::kSuccess,
2017*795d594fSAndroid Build Coastguard Worker                                   /*use_fd=*/false,
2018*795d594fSAndroid Build Coastguard Worker                                   /*use_zip_fd=*/false));
2019*795d594fSAndroid Build Coastguard Worker 
2020*795d594fSAndroid Build Coastguard Worker   // Check that we can open the oat file as executable.
2021*795d594fSAndroid Build Coastguard Worker   {
2022*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
2023*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
2024*795d594fSAndroid Build Coastguard Worker                                                      base_oat_name,
2025*795d594fSAndroid Build Coastguard Worker                                                      base_oat_name,
2026*795d594fSAndroid Build Coastguard Worker                                                      /*executable=*/true,
2027*795d594fSAndroid Build Coastguard Worker                                                      /*low_4gb=*/false,
2028*795d594fSAndroid Build Coastguard Worker                                                      dex->GetLocation(),
2029*795d594fSAndroid Build Coastguard Worker                                                      &error_msg));
2030*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(odex_file != nullptr) << error_msg;
2031*795d594fSAndroid Build Coastguard Worker   }
2032*795d594fSAndroid Build Coastguard Worker 
2033*795d594fSAndroid Build Coastguard Worker   // Rewrite the oat file with wrong version and bogus contents.
2034*795d594fSAndroid Build Coastguard Worker   {
2035*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<File> file(OS::OpenFileReadWrite(base_oat_name.c_str()));
2036*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(file != nullptr);
2037*795d594fSAndroid Build Coastguard Worker     // Retrieve the offset and size of the embedded oat file.
2038*795d594fSAndroid Build Coastguard Worker     size_t oatdata_offset;
2039*795d594fSAndroid Build Coastguard Worker     size_t oatdata_size;
2040*795d594fSAndroid Build Coastguard Worker     {
2041*795d594fSAndroid Build Coastguard Worker       std::string error_msg;
2042*795d594fSAndroid Build Coastguard Worker       std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.get(),
2043*795d594fSAndroid Build Coastguard Worker                                                       /*writable=*/false,
2044*795d594fSAndroid Build Coastguard Worker                                                       /*program_header_only=*/true,
2045*795d594fSAndroid Build Coastguard Worker                                                       /*low_4gb=*/false,
2046*795d594fSAndroid Build Coastguard Worker                                                       &error_msg));
2047*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(elf_file != nullptr) << error_msg;
2048*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(elf_file->Load(file.get(),
2049*795d594fSAndroid Build Coastguard Worker                                  /*executable=*/false,
2050*795d594fSAndroid Build Coastguard Worker                                  /*low_4gb=*/false,
2051*795d594fSAndroid Build Coastguard Worker                                  /*reservation=*/nullptr,
2052*795d594fSAndroid Build Coastguard Worker                                  &error_msg))
2053*795d594fSAndroid Build Coastguard Worker           << error_msg;
2054*795d594fSAndroid Build Coastguard Worker       const uint8_t* base_address = elf_file->Is64Bit() ? elf_file->GetImpl64()->GetBaseAddress() :
2055*795d594fSAndroid Build Coastguard Worker                                                           elf_file->GetImpl32()->GetBaseAddress();
2056*795d594fSAndroid Build Coastguard Worker       const uint8_t* oatdata = elf_file->FindDynamicSymbolAddress("oatdata");
2057*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(oatdata != nullptr);
2058*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(oatdata > base_address);
2059*795d594fSAndroid Build Coastguard Worker       // Note: We're assuming here that the virtual address offset is the same
2060*795d594fSAndroid Build Coastguard Worker       // as file offset. This is currently true for all oat files we generate.
2061*795d594fSAndroid Build Coastguard Worker       oatdata_offset = static_cast<size_t>(oatdata - base_address);
2062*795d594fSAndroid Build Coastguard Worker       const uint8_t* oatlastword = elf_file->FindDynamicSymbolAddress("oatlastword");
2063*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(oatlastword != nullptr);
2064*795d594fSAndroid Build Coastguard Worker       ASSERT_TRUE(oatlastword > oatdata);
2065*795d594fSAndroid Build Coastguard Worker       oatdata_size = oatlastword - oatdata;
2066*795d594fSAndroid Build Coastguard Worker     }
2067*795d594fSAndroid Build Coastguard Worker 
2068*795d594fSAndroid Build Coastguard Worker     // Check that we have the right `oatdata_offset`.
2069*795d594fSAndroid Build Coastguard Worker     int64_t length = file->GetLength();
2070*795d594fSAndroid Build Coastguard Worker     ASSERT_GE(length, static_cast<ssize_t>(oatdata_offset + sizeof(OatHeader)));
2071*795d594fSAndroid Build Coastguard Worker     alignas(OatHeader) uint8_t header_data[sizeof(OatHeader)];
2072*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(file->PreadFully(header_data, sizeof(header_data), oatdata_offset));
2073*795d594fSAndroid Build Coastguard Worker     const OatHeader& header = reinterpret_cast<const OatHeader&>(header_data);
2074*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(header.IsValid()) << header.GetValidationErrorMessage();
2075*795d594fSAndroid Build Coastguard Worker 
2076*795d594fSAndroid Build Coastguard Worker     // Overwrite all oat data from version onwards with bytes with value 4.
2077*795d594fSAndroid Build Coastguard Worker     // (0x04040404 is not a valid version, we're using three decimal digits and '\0'.)
2078*795d594fSAndroid Build Coastguard Worker     //
2079*795d594fSAndroid Build Coastguard Worker     // We previously tried to find the value for key "debuggable" (bug 179221298)
2080*795d594fSAndroid Build Coastguard Worker     // in the key-value store before checking the oat header. This test tries to
2081*795d594fSAndroid Build Coastguard Worker     // ensure that such early processing of the key-value store shall crash.
2082*795d594fSAndroid Build Coastguard Worker     // Reading 0x04040404 as the size of the key-value store yields a bit over
2083*795d594fSAndroid Build Coastguard Worker     // 64MiB which should hopefully include some unmapped memory beyond the end
2084*795d594fSAndroid Build Coastguard Worker     // of the loaded oat file. Overwriting the whole embedded oat file ensures
2085*795d594fSAndroid Build Coastguard Worker     // that we do not match the key within the oat file but we could still
2086*795d594fSAndroid Build Coastguard Worker     // accidentally match it in the additional sections of the elf file, so this
2087*795d594fSAndroid Build Coastguard Worker     // approach could fail to catch similar issues. At the time of writing, this
2088*795d594fSAndroid Build Coastguard Worker     // test crashed when run without the fix on 64-bit host (but not 32-bit).
2089*795d594fSAndroid Build Coastguard Worker     static constexpr size_t kVersionOffset = sizeof(OatHeader::kOatMagic);
2090*795d594fSAndroid Build Coastguard Worker     static_assert(kVersionOffset < sizeof(OatHeader));
2091*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t> data(oatdata_size - kVersionOffset, 4u);
2092*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(file->PwriteFully(data.data(), data.size(), oatdata_offset + kVersionOffset));
2093*795d594fSAndroid Build Coastguard Worker     UNUSED(oatdata_size);
2094*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(file->FlushClose(), 0) << "Could not flush and close oat file";
2095*795d594fSAndroid Build Coastguard Worker   }
2096*795d594fSAndroid Build Coastguard Worker 
2097*795d594fSAndroid Build Coastguard Worker   // Check that we reject the oat file without crashing.
2098*795d594fSAndroid Build Coastguard Worker   {
2099*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
2100*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
2101*795d594fSAndroid Build Coastguard Worker                                                      base_oat_name,
2102*795d594fSAndroid Build Coastguard Worker                                                      base_oat_name,
2103*795d594fSAndroid Build Coastguard Worker                                                      /*executable=*/true,
2104*795d594fSAndroid Build Coastguard Worker                                                      /*low_4gb=*/false,
2105*795d594fSAndroid Build Coastguard Worker                                                      dex->GetLocation(),
2106*795d594fSAndroid Build Coastguard Worker                                                      &error_msg));
2107*795d594fSAndroid Build Coastguard Worker     ASSERT_FALSE(odex_file != nullptr);
2108*795d594fSAndroid Build Coastguard Worker   }
2109*795d594fSAndroid Build Coastguard Worker }
2110*795d594fSAndroid Build Coastguard Worker 
2111*795d594fSAndroid Build Coastguard Worker }  // namespace art
2112