blob: 0eddab61905416f3ac294f86a09e6a3e98c75034 [file] [log] [blame]
Calin Juravle5a0381f2020-11-23 19:21:09 -08001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <string>
18#include <vector>
19
20#include "common_runtime_test.h"
21#include "dex2oat_environment_test.h"
22
23#include "vdex_file.h"
24#include "verifier/verifier_deps.h"
25#include "ziparchive/zip_writer.h"
26
27namespace art {
28
29using verifier::VerifierDeps;
30
31class Dex2oatVdexTest : public Dex2oatEnvironmentTest {
32 public:
33 void TearDown() override {
34 Dex2oatEnvironmentTest::TearDown();
35
36 output_ = "";
37 error_msg_ = "";
38 opened_vdex_files_.clear();
39 }
40
41 protected:
42 bool RunDex2oat(const std::string& dex_location,
43 const std::string& odex_location,
44 bool copy_dex_files = false,
45 const std::vector<std::string>& extra_args = {}) {
46 std::vector<std::string> args;
47 args.push_back("--dex-file=" + dex_location);
48 args.push_back("--oat-file=" + odex_location);
49 args.push_back("--compiler-filter=" +
50 CompilerFilter::NameOfFilter(CompilerFilter::Filter::kVerify));
51 args.push_back("--runtime-arg");
52 args.push_back("-Xnorelocate");
53 if (!copy_dex_files) {
54 args.push_back("--copy-dex-files=false");
55 }
56 args.push_back("--runtime-arg");
57 args.push_back("-verbose:verifier,compiler");
58 // Use a single thread to facilitate debugging. We only compile tiny dex files.
59 args.push_back("-j1");
60
61 args.insert(args.end(), extra_args.begin(), extra_args.end());
62
63 return Dex2Oat(args, &output_, &error_msg_) == 0;
64 }
65
66 void CreateDexMetadata(const std::string& vdex, const std::string& out_dm) {
67 // Read the vdex bytes.
68 std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex.c_str()));
69 std::vector<uint8_t> data(vdex_file->GetLength());
70 ASSERT_TRUE(vdex_file->ReadFully(data.data(), data.size()));
71
72 // Zip the content.
73 FILE* file = fopen(out_dm.c_str(), "wb");
74 ZipWriter writer(file);
75 writer.StartEntry("primary.vdex", ZipWriter::kAlign32);
76 writer.WriteBytes(data.data(), data.size());
77 writer.FinishEntry();
78 writer.Finish();
79 fflush(file);
80 fclose(file);
81 }
82
83 std::string GetFilename(const std::unique_ptr<const DexFile>& dex_file) {
84 const std::string& str = dex_file->GetLocation();
85 size_t idx = str.rfind('/');
86 if (idx == std::string::npos) {
87 return str;
88 }
89 return str.substr(idx + 1);
90 }
91
92 std::string GetOdex(const std::unique_ptr<const DexFile>& dex_file,
93 const std::string& suffix = "") {
94 return GetScratchDir() + "/" + GetFilename(dex_file) + suffix + ".odex";
95 }
96
97 std::string GetVdex(const std::unique_ptr<const DexFile>& dex_file,
98 const std::string& suffix = "") {
99 return GetScratchDir() + "/" + GetFilename(dex_file) + suffix + ".vdex";
100 }
101
102 std::string output_;
103 std::string error_msg_;
104 std::vector<std::unique_ptr<VdexFile>> opened_vdex_files_;
105};
106
107// Check that if the input dm does contain dex files then the compilation fails
108TEST_F(Dex2oatVdexTest, VerifyPublicSdkStubsWithDexFiles) {
109 std::string error_msg;
110
111 // Dex2oatVdexTestDex is the subject app using normal APIs found in the boot classpath.
112 std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Dex2oatVdexTestDex"));
113
114 // Compile the subject app using the predefined API-stubs
115 ASSERT_TRUE(RunDex2oat(
116 dex_file->GetLocation(),
117 GetOdex(dex_file),
118 /*copy_dex_files=*/ true));
119
120 // Create the .dm file with the output.
121 std::string dm_file = GetScratchDir() + "/base.dm";
122 CreateDexMetadata(GetVdex(dex_file), dm_file);
123 std::vector<std::string> extra_args;
124 extra_args.push_back("--dm-file=" + dm_file);
125
126 // Recompile again with the .dm file which contains a vdex with code.
127 // The compilation should fail.
128 ASSERT_FALSE(RunDex2oat(
129 dex_file->GetLocation(),
130 GetOdex(dex_file, "v2"),
131 /*copy_dex_files=*/ true,
132 extra_args));
133}
134
135} // namespace art