blob: d9b44e11572b465253d0f5c6dd647b56f4e07559 [file] [log] [blame]
// Copyright 2020 Google Inc. All Rights Reserved.
//
// 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 "bloaty.h"
#include "test.h"
#include "report.pb.h"
TEST_F(BloatyTest, ProtobufOutput) {
std::string file = "05-binary.bin";
uint64_t size;
ASSERT_TRUE(GetFileSize(file, &size));
RunBloaty({"bloaty", "-d", "compileunits,symbols", file});
// Select protobuf output.
std::ostringstream stream;
bloaty::OutputOptions options;
options.output_format = bloaty::OutputFormat::kProtobuf;
output_->Print(options, &stream);
// Check Protobuf output.
bloaty_report::Report report;
ASSERT_TRUE(report.ParseFromString(stream.str()));
// These are the internal structure of `05-binary.bin`.
// They shouldn't change if the test data don't change.
// See below for a CSV version of the same output; here we ensure that
// the Protobuf output matches the CSV version.
// See also `BloatyTest.SimpleBinary` in `bloaty_test.cc`.
ASSERT_EQ(21, report.compile_units().size());
auto& bar_o = report.compile_units()[0];
ASSERT_EQ("bar.o.c", bar_o.name());
EXPECT_NEAR(4.36, bar_o.sizes().file_actual() / 1024.0, .01);
EXPECT_NEAR(3.99, bar_o.sizes().vm_actual() / 1024.0, .01);
ASSERT_GT(bar_o.symbols().size(), 0);
auto& bar_x = bar_o.symbols()[0];
ASSERT_EQ("bar_x", bar_x.name());
EXPECT_NEAR(3.94, bar_x.sizes().file_actual() / 1024.0, .01);
EXPECT_NEAR(3.91, bar_x.sizes().vm_actual() / 1024.0, .01);
ASSERT_GT(bar_o.symbols().size(), 1);
auto& debug_info = bar_o.symbols()[1];
ASSERT_EQ("[section .debug_info]", debug_info.name());
EXPECT_EQ(169, debug_info.sizes().file_actual());
EXPECT_EQ(0, debug_info.sizes().vm_actual());
EXPECT_NEAR(14.1, report.file_total() / 1024.0, .1);
EXPECT_NEAR(10.3, report.vm_total() / 1024.0, .1);
}
TEST_F(BloatyTest, ProtobufOutputFilterHotSymbolsAllHot) {
std::string file = "05-binary.bin";
uint64_t size;
ASSERT_TRUE(GetFileSize(file, &size));
RunBloaty({"bloaty", "-d", "accesspattern,compileunits,symbols", file,
// The first 32 KiB frame is accessed 100 times.
"--cold-bytes-filter", "0:100",
"--access-pattern-frame-size", "32768"});
// Select protobuf output.
std::ostringstream stream;
bloaty::OutputOptions options;
options.output_format = bloaty::OutputFormat::kProtobuf;
output_->Print(options, &stream);
// Check Protobuf output.
bloaty_report::Report report;
ASSERT_TRUE(report.ParseFromString(stream.str()));
// Since the test binary `05-binary.bin` is smaller than 32 KiB,
// every symbol (except zero-filled segments synthesized at run-time)
// inside the file will be hot, as designated by our command line
// arguments. So the list of compile units should be empty.
ASSERT_EQ(0, report.compile_units().size());
EXPECT_NEAR(14.1, report.file_total() / 1024.0, .1);
EXPECT_NEAR(10.3, report.vm_total() / 1024.0, .1);
}
TEST_F(BloatyTest, ProtobufOutputFilterHotSymbols) {
std::string file = "05-binary.bin";
uint64_t size;
ASSERT_TRUE(GetFileSize(file, &size));
RunBloaty({"bloaty", "-d", "accesspattern,compileunits,symbols", file,
// Default frame size is 8 KiB.
// The first 8 KiB frame is accessed 100 times.
"--cold-bytes-filter", "0:100"});
// Select protobuf output.
std::ostringstream stream;
bloaty::OutputOptions options;
options.output_format = bloaty::OutputFormat::kProtobuf;
output_->Print(options, &stream);
// Check Protobuf output.
bloaty_report::Report report;
ASSERT_TRUE(report.ParseFromString(stream.str()));
// This test is only run on x86_64.
// The test binary `05-binary.bin` is around 14 KiB.
// We would expect to see some compile units.
EXPECT_NEAR(13, report.compile_units().size(), 1);
EXPECT_NEAR(14.1, static_cast<double>(size) / 1024.0, .1);
EXPECT_NEAR(14.1, report.file_total() / 1024.0, .1);
EXPECT_NEAR(10.3, report.vm_total() / 1024.0, .1);
}
TEST_F(BloatyTest, ProtobufOutputFilterHotSymbolsPatternTooLarge) {
std::string file = "05-binary.bin";
std::string errmsg = "access pattern exceeded end of file";
AssertBloatyFails({"bloaty", "-d", "accesspattern,compileunits,symbols", file,
// Default frame size is 8 KiB.
// The file is 14 KiB, so specifying the non-existent
// third frame should fail.
"--cold-bytes-filter", "0:100,1:100,2:100"}, errmsg);
}
// Here is a regular bloaty print-out on the same file for reference:
//
// FILE SIZE VM SIZE
// -------------- --------------
// 30.9% 4.36Ki 38.8% 3.99Ki bar.o.c
// 90.3% 3.94Ki 97.9% 3.91Ki bar_x
// 3.8% 169 0.0% 0 [section .debug_info]
// 2.4% 109 1.9% 76 bar_func
// 1.3% 58 0.0% 0 [section .debug_line]
// 0.8% 34 0.1% 4 bar_y
// 0.7% 31 0.0% 0 [section .debug_str]
// 0.7% 30 0.1% 4 bar_z
// 3.9% 564 38.8% 3.98Ki foo.o.c
// 5.3% 30 98.0% 3.91Ki foo_x
// 27.7% 156 0.0% 0 [section .debug_abbrev]
// 26.2% 148 0.0% 0 [section .debug_info]
// 19.3% 109 1.9% 76 foo_func
// 10.3% 58 0.0% 0 [section .debug_line]
// 5.9% 33 0.0% 0 [section .debug_str]
// 5.3% 30 0.1% 4 foo_y
// 15.5% 2.19Ki 0.0% 0 [ELF Headers]
// 91.4% 2.00Ki NAN% 0 [ELF Headers]
// 5.7% 128 NAN% 0 __libc_csu_init
// 2.9% 64 NAN% 0 _IO_stdin_used
// 12.1% 1.71Ki 0.0% 0 [Unmapped]
// 11.6% 1.64Ki 0.0% 0 [section .symtab]
// 78.6% 1.29Ki NAN% 0 [section .symtab]
// 17.1% 288 NAN% 0 __libc_csu_init
// 1.4% 24 NAN% 0 _IO_stdin_used
// 1.4% 24 NAN% 0 __libc_csu_fini
// 1.4% 24 NAN% 0 completed.6973
// 4.1% 593 5.6% 593 [LOAD #2 [RX]]
// 3.9% 561 0.0% 0 [section .strtab]
// 53.5% 300 NAN% 0 [section .strtab]
// 38.3% 215 NAN% 0 __libc_csu_init
// 2.9% 16 NAN% 0 __libc_csu_fini
// 2.7% 15 NAN% 0 _IO_stdin_used
// 2.7% 15 NAN% 0 completed.6973
// 3.2% 464 4.4% 464 [section .dynamic]
// 3.0% 430 3.9% 405 [20 Others]
// 2.5% 356 3.4% 356 [section .text]
// 71.1% 253 71.1% 253 [section .text]
// 28.4% 101 28.4% 101 __libc_csu_init
// 0.6% 2 0.6% 2 __libc_csu_fini
// 2.3% 328 0.0% 0 [section .shstrtab]
// 1.5% 220 0.4% 46 main.o.c
// 37.3% 82 0.0% 0 [section .debug_info]
// 34.1% 75 100.0% 46 main
// 26.8% 59 0.0% 0 [section .debug_line]
// 1.8% 4 0.0% 0 [section .debug_str]
// 1.5% 212 2.0% 212 [section .eh_frame]
// 54.7% 116 54.7% 116 [section .eh_frame]
// 34.0% 72 34.0% 72 __libc_csu_init
// 11.3% 24 11.3% 24 __libc_csu_fini
// 1.0% 144 0.0% 0 [section .debug_aranges]
// 0.7% 101 0.0% 0 [section .debug_abbrev]
// 0.6% 93 0.0% 0
// 0.5% 72 0.7% 72 [section .dynsym]
// 0.4% 56 0.5% 56 [section .dynstr]
// 0.2% 24 0.5% 52 [LOAD #3 [RW]]
// 0.3% 48 0.5% 48 [section .plt]
// 0.3% 48 0.5% 48 [section .rela.plt]
// 50.0% 24 50.0% 24 [section .rela.plt]
// 50.0% 24 50.0% 24 __libc_csu_init
// 100.0% 14.1Ki 100.0% 10.3Ki TOTAL
TEST_F(BloatyTest, EncodeSymbolWithCrate) {
EXPECT_EQ(bloaty::EncodeSymbolWithCrateId("foo", "bar"), "foo, in crate bar");
}
TEST_F(BloatyTest, DecodeSymbolWithCrate) {
auto expected1 = bloaty::DecodeCrateIdResult{.symbol = "foo", .crate = ""};
EXPECT_EQ(bloaty::DecodeSymbolWithCrateId("foo"), expected1);
auto expected2 = bloaty::DecodeCrateIdResult{.symbol = "foo", .crate = "bar"};
EXPECT_EQ(bloaty::DecodeSymbolWithCrateId("foo, in crate bar"), expected2);
}