1 /*
2 * Copyright (C) 2019 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 "common/debug.h"
18 #include "compiler/compiler.h"
19 #include "inode2filename/inode_resolver.h"
20
21 #include <cstdio>
22 #include <fstream>
23 #include <string>
24 #include <vector>
25
26 #include <android-base/file.h>
27 #include <gtest/gtest.h>
28
29 namespace iorap::compiler {
30
GetTestDataPath(const std::string & fn)31 static std::string GetTestDataPath(const std::string& fn) {
32 static std::string exec_dir = android::base::GetExecutableDirectory();
33 return exec_dir + "/tests/src/compiler/testdata/" + fn;
34 }
35
36 class CompilerTest: public ::testing::Test{
37 protected:
SetUp()38 void SetUp() override {
39 ir_dependencies.data_source = inode2filename::DataSourceKind::kTextCache;
40 ir_dependencies.text_cache_filename = GetTestDataPath("common_textcache");
41 ir_dependencies.verify = inode2filename::VerifyKind::kNone; // required for determinism.
42 ir_dependencies.root_directories.push_back("/system");
43 ir_dependencies.root_directories.push_back("/apex");
44 ir_dependencies.root_directories.push_back("/data");
45 ir_dependencies.root_directories.push_back("/vendor");
46 ir_dependencies.root_directories.push_back("/product");
47 ir_dependencies.root_directories.push_back("/metadata");
48 }
49
50 inode2filename::InodeResolverDependencies ir_dependencies;
51 };
52
TEST_F(CompilerTest,SingleTraceDuration)53 TEST_F(CompilerTest, SingleTraceDuration) {
54 std::vector<std::string> input_file_names{GetTestDataPath("common_perfetto_trace.pb")};
55 std::vector<uint64_t> timestamp_limit_ns{260390390018596UL};
56 TemporaryFile tmp_file;
57 char* output_file_name = tmp_file.path;
58 bool output_proto = false;
59
60
61 std::vector<CompilationInput> perfetto_traces =
62 MakeCompilationInputs(input_file_names, timestamp_limit_ns);
63 bool result = PerformCompilation(perfetto_traces,
64 output_file_name,
65 output_proto,
66 /*blacklist_filter*/std::nullopt,
67 ir_dependencies);
68 std::ifstream ifs(output_file_name);
69
70 // The extra paren is needed to avoid compilation error:
71 // "parentheses were disambiguated as a function declaration".
72 std::string content{std::istreambuf_iterator<char>(ifs),
73 std::istreambuf_iterator<char>()};
74
75 EXPECT_EQ(result, true);
76 EXPECT_EQ(content, "{filename:\"/product/app/CalculatorGooglePrebuilt/"
77 "CalculatorGooglePrebuilt.apk\","
78 "timestamp:7641303,"
79 "add_to_page_cache:1,"
80 "index:540}\n");
81 }
82
TEST_F(CompilerTest,MultiTraceDuration)83 TEST_F(CompilerTest, MultiTraceDuration) {
84 std::vector<std::string> input_file_names{GetTestDataPath("common_perfetto_trace.pb"),
85 GetTestDataPath("common_perfetto_trace2.pb")};
86 std::vector<uint64_t> timestamp_limit_ns{260390390018596UL, 333215840452006UL};
87 TemporaryFile tmp_file;
88 char* output_file_name = tmp_file.path;
89 bool output_proto = false;
90
91 std::vector<CompilationInput> perfetto_traces =
92 MakeCompilationInputs(input_file_names, timestamp_limit_ns);
93 bool result = PerformCompilation(perfetto_traces,
94 output_file_name,
95 output_proto,
96 /*blacklist_filter*/std::nullopt,
97 ir_dependencies);
98 std::ifstream ifs(output_file_name);
99 std::string content{std::istreambuf_iterator<char>(ifs),
100 std::istreambuf_iterator<char>()};
101
102 EXPECT_EQ(result, true);
103 EXPECT_EQ(content, "{filename:\"/apex/com.android.art/lib64/libperfetto_hprof.so\","
104 "timestamp:4388958,"
105 "add_to_page_cache:1,"
106 "index:227}\n"
107 "{filename:\"/product/app/CalculatorGooglePrebuilt/"
108 "CalculatorGooglePrebuilt.apk\","
109 "timestamp:7641303,"
110 "add_to_page_cache:1,"
111 "index:540}\n");
112 }
113
TEST_F(CompilerTest,NoTraceDuration)114 TEST_F(CompilerTest, NoTraceDuration) {
115 std::vector<std::string> input_file_names{GetTestDataPath("common_perfetto_trace.pb")};
116 TemporaryFile tmp_file;
117 char* output_file_name = tmp_file.path;
118 bool output_proto = false;
119
120 std::vector<CompilationInput> perfetto_traces =
121 MakeCompilationInputs(input_file_names, /* timestamp_limit_ns= */{});
122 bool result = PerformCompilation(perfetto_traces,
123 output_file_name,
124 output_proto,
125 /*blacklist_filter*/std::nullopt,
126 ir_dependencies);
127 std::ifstream ifs(output_file_name);
128 size_t line_num = std::count((std::istreambuf_iterator<char>(ifs)),
129 (std::istreambuf_iterator<char>()),
130 '\n');
131
132 EXPECT_EQ(result, true);
133 EXPECT_EQ(line_num, 1675UL);
134 }
135
TEST_F(CompilerTest,BlacklistFilterArtFiles)136 TEST_F(CompilerTest, BlacklistFilterArtFiles) {
137 std::vector<std::string> input_file_names{GetTestDataPath("common_perfetto_trace.pb")};
138 TemporaryFile tmp_file;
139 char* output_file_name = tmp_file.path;
140 bool output_proto = false;
141
142 std::string blacklist_filter = "[.](art|oat|odex|vdex|dex)$";
143
144 // iorap.cmd.compiler -op output.pb -it common_textcache -ot
145 // --blacklist-filter "[.](art|oat|odex|vdex|dex)$" common_perfetto_trace.pb
146
147 std::vector<CompilationInput> perfetto_traces =
148 MakeCompilationInputs(input_file_names, /* timestamp_limit_ns= */{});
149 bool result = PerformCompilation(perfetto_traces,
150 output_file_name,
151 output_proto,
152 blacklist_filter,
153 ir_dependencies);
154 std::ifstream ifs(output_file_name);
155 size_t line_num = std::count((std::istreambuf_iterator<char>(ifs)),
156 (std::istreambuf_iterator<char>()),
157 '\n');
158
159 EXPECT_EQ(result, true);
160 EXPECT_EQ(line_num, 1617UL);
161 }
162 } // namespace iorap::compiler
163