blob: f584378de1951df99459414f3b8a1c1ee7ad3034 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common/debug.h"
#include "compiler/compiler.h"
#include "inode2filename/inode_resolver.h"
#include <cstdio>
#include <fstream>
#include <string>
#include <vector>
#include <android-base/file.h>
#include <gtest/gtest.h>
namespace iorap::compiler {
static std::string GetTestDataPath(const std::string& fn) {
static std::string exec_dir = android::base::GetExecutableDirectory();
return exec_dir + "/tests/src/compiler/testdata/" + fn;
}
class CompilerTest: public ::testing::Test{
protected:
void SetUp() override {
ir_dependencies.data_source = inode2filename::DataSourceKind::kTextCache;
ir_dependencies.text_cache_filename = GetTestDataPath("common_textcache");
ir_dependencies.verify = inode2filename::VerifyKind::kNone; // required for determinism.
ir_dependencies.root_directories.push_back("/system");
ir_dependencies.root_directories.push_back("/apex");
ir_dependencies.root_directories.push_back("/data");
ir_dependencies.root_directories.push_back("/vendor");
ir_dependencies.root_directories.push_back("/product");
ir_dependencies.root_directories.push_back("/metadata");
}
inode2filename::InodeResolverDependencies ir_dependencies;
};
TEST_F(CompilerTest, SingleTraceDuration) {
std::vector<std::string> input_file_names{GetTestDataPath("common_perfetto_trace.pb")};
std::vector<uint64_t> timestamp_limit_ns{260390390018596UL};
TemporaryFile tmp_file;
char* output_file_name = tmp_file.path;
bool output_proto = false;
std::vector<CompilationInput> perfetto_traces =
MakeCompilationInputs(input_file_names, timestamp_limit_ns, /*pids=*/{});
bool result = PerformCompilation(perfetto_traces,
output_file_name,
output_proto,
/*blacklist_filter*/std::nullopt,
ir_dependencies);
std::ifstream ifs(output_file_name);
// The extra paren is needed to avoid compilation error:
// "parentheses were disambiguated as a function declaration".
std::string content{std::istreambuf_iterator<char>(ifs),
std::istreambuf_iterator<char>()};
EXPECT_EQ(result, true);
EXPECT_EQ(content, "{filename:\"/product/app/CalculatorGooglePrebuilt/"
"CalculatorGooglePrebuilt.apk\","
"timestamp:7641303,"
"add_to_page_cache:1,"
"index:540}\n");
}
TEST_F(CompilerTest, MultiTraceDuration) {
std::vector<std::string> input_file_names{GetTestDataPath("common_perfetto_trace.pb"),
GetTestDataPath("common_perfetto_trace2.pb")};
std::vector<uint64_t> timestamp_limit_ns{260390390018596UL, 333215840452006UL};
TemporaryFile tmp_file;
char* output_file_name = tmp_file.path;
bool output_proto = false;
std::vector<CompilationInput> perfetto_traces =
MakeCompilationInputs(input_file_names, timestamp_limit_ns, /*pids=*/{});
bool result = PerformCompilation(perfetto_traces,
output_file_name,
output_proto,
/*blacklist_filter*/std::nullopt,
ir_dependencies);
std::ifstream ifs(output_file_name);
std::string content{std::istreambuf_iterator<char>(ifs),
std::istreambuf_iterator<char>()};
EXPECT_EQ(result, true);
EXPECT_EQ(content, "{filename:\"/apex/com.android.art/lib64/libperfetto_hprof.so\","
"timestamp:4388958,"
"add_to_page_cache:1,"
"index:227}\n"
"{filename:\"/product/app/CalculatorGooglePrebuilt/"
"CalculatorGooglePrebuilt.apk\","
"timestamp:7641303,"
"add_to_page_cache:1,"
"index:540}\n");
}
TEST_F(CompilerTest, NoTraceDuration) {
std::vector<std::string> input_file_names{GetTestDataPath("common_perfetto_trace.pb")};
TemporaryFile tmp_file;
char* output_file_name = tmp_file.path;
bool output_proto = false;
std::vector<CompilationInput> perfetto_traces =
MakeCompilationInputs(input_file_names, /* timestamp_limit_ns= */{}, /*pids=*/{});
bool result = PerformCompilation(perfetto_traces,
output_file_name,
output_proto,
/*blacklist_filter*/std::nullopt,
ir_dependencies);
std::ifstream ifs(output_file_name);
size_t line_num = std::count((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>()),
'\n');
EXPECT_EQ(result, true);
EXPECT_EQ(line_num, 1675UL);
}
TEST_F(CompilerTest, BlacklistFilterArtFiles) {
std::vector<std::string> input_file_names{GetTestDataPath("common_perfetto_trace.pb")};
TemporaryFile tmp_file;
char* output_file_name = tmp_file.path;
bool output_proto = false;
std::string blacklist_filter = "[.](art|oat|odex|vdex|dex)$";
// iorap.cmd.compiler -op output.pb -it common_textcache -ot
// --denylist-filter "[.](art|oat|odex|vdex|dex)$" common_perfetto_trace.pb
std::vector<CompilationInput> perfetto_traces =
MakeCompilationInputs(input_file_names, /* timestamp_limit_ns= */{}, /*pids=*/{});
bool result = PerformCompilation(perfetto_traces,
output_file_name,
output_proto,
blacklist_filter,
ir_dependencies);
std::ifstream ifs(output_file_name);
size_t line_num = std::count((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>()),
'\n');
EXPECT_EQ(result, true);
EXPECT_EQ(line_num, 1617UL);
}
TEST_F(CompilerTest, PidFilter) {
std::vector<std::string> input_file_names{GetTestDataPath("common_perfetto_trace.pb")};
TemporaryFile tmp_file;
char* output_file_name = tmp_file.path;
bool output_proto = false;
std::vector<CompilationInput> perfetto_traces =
MakeCompilationInputs(input_file_names, /*timestamp_limit_ns=*/{}, /*pids=*/{30716});
bool result = PerformCompilation(perfetto_traces,
output_file_name,
output_proto,
/*deny_filter*/std::nullopt,
ir_dependencies);
std::ifstream ifs(output_file_name);
size_t line_num = std::count((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>()),
'\n');
EXPECT_EQ(result, true);
EXPECT_EQ(line_num, 13UL);
}
} // namespace iorap::compiler