| // 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.50, 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(12, 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); |
| } |