| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "garnet/bin/zxdb/symbols/find_line.h" |
| #include "garnet/bin/zxdb/symbols/mock_line_table.h" |
| #include "gtest/gtest.h" |
| |
| namespace zxdb { |
| |
| namespace { |
| |
| llvm::DWARFDebugLine::Row MakeStatementRow(uint64_t address, uint16_t file, |
| uint32_t line) { |
| llvm::DWARFDebugLine::Row result; |
| result.Address = address; |
| result.Line = line; |
| result.Column = 0; |
| result.File = file; |
| result.Discriminator = 0; |
| result.Isa = 0; |
| result.IsStmt = 1; |
| result.BasicBlock = 0; |
| result.EndSequence = 0; |
| result.PrologueEnd = 0; |
| result.EpilogueBegin = 0; |
| |
| return result; |
| } |
| |
| } // namespace |
| |
| TEST(FindLine, GetAllLineTableMatchesInUnit) { |
| MockLineTable::FileNameVector files; |
| files.push_back("file1.cc"); // Name for file ID #1. |
| files.push_back("file2.cc"); // Name for file ID #2. |
| |
| MockLineTable::RowVector rows; |
| rows.push_back(MakeStatementRow(0x1000, 1, 1)); // File #1, line 1. |
| rows.push_back(MakeStatementRow(0x1001, 1, 2)); |
| rows.push_back(MakeStatementRow(0x1002, 2, 1)); // File #2, line 1. |
| rows.push_back(MakeStatementRow(0x1003, 1, 1)); // Dupe for File 1, line 1. |
| rows.push_back(MakeStatementRow(0x1004, 1, 90)); |
| rows.push_back(MakeStatementRow(0x1005, 1, 100)); |
| rows.push_back(MakeStatementRow(0x1006, 1, 95)); |
| rows.push_back(MakeStatementRow(0x1007, 1, 100)); |
| rows.push_back(MakeStatementRow(0x1008, 1, 98)); |
| |
| MockLineTable table(files, rows); |
| |
| // There are two exact matches for line 1. |
| auto out = GetAllLineTableMatchesInUnit(table, "file1.cc", 1); |
| ASSERT_EQ(2u, out.size()); |
| EXPECT_EQ(LineMatch(0x1000, 1, 0), out[0]); |
| EXPECT_EQ(LineMatch(0x1003, 1, 0), out[1]); |
| |
| // Searching for line 99 should catch both the 90->100 and the 95->100 |
| // transitions. |
| out = GetAllLineTableMatchesInUnit(table, "file1.cc", 99); |
| ASSERT_EQ(2u, out.size()); |
| EXPECT_EQ(LineMatch(0x1005, 100, 0), out[0]); |
| EXPECT_EQ(LineMatch(0x1007, 100, 0), out[1]); |
| |
| // Searching for something greater than 100 should fail. |
| out = GetAllLineTableMatchesInUnit(table, "file1.cc", 101); |
| EXPECT_TRUE(out.empty()); |
| } |
| |
| // Out-of-order lines. In this case there was some later code moved before |
| // the line being searched for, even though the transition of addresses |
| // goes in the opposite direction (high to low), we should find the line. |
| TEST(FindLine, GetAllLineTableMatchesInUnit_Reverse) { |
| MockLineTable::FileNameVector files = {"file1.cc"}; |
| |
| MockLineTable::RowVector rows; |
| rows.push_back(MakeStatementRow(0x1000, 1, 105)); // Later code moved before. |
| rows.push_back(MakeStatementRow(0x1001, 1, 101)); // Best match. |
| rows.push_back(MakeStatementRow(0x1002, 1, 91)); // |
| rows.push_back(MakeStatementRow(0x1003, 1, 103)); // Less-good match. |
| |
| MockLineTable table(files, rows); |
| |
| auto out = GetAllLineTableMatchesInUnit(table, "file1.cc", 100); |
| ASSERT_EQ(1u, out.size()); |
| EXPECT_EQ(LineMatch(0x1001, 101, 0), out[0]); |
| } |
| |
| TEST(FindLine, GetBestLineMatches) { |
| // Empty input. |
| auto out = GetBestLineMatches({}); |
| EXPECT_TRUE(out.empty()); |
| |
| // Should return the smallest line #. |
| out = GetBestLineMatches({LineMatch(0x1000, 10, 0), LineMatch(0x1001, 7, 0), |
| LineMatch(0x1002, 100, 0)}); |
| ASSERT_EQ(1u, out.size()); |
| EXPECT_EQ(LineMatch(0x1001, 7, 0), out[0]); |
| |
| // When the smallest match has dupes, all should be returned assuming |
| // the functions are different. |
| out = |
| GetBestLineMatches({LineMatch(0x1000, 10, 0), LineMatch(0x1001, 20, 1), |
| LineMatch(0x1002, 10, 2), LineMatch(0x1003, 30, 3)}); |
| ASSERT_EQ(2u, out.size()); |
| EXPECT_EQ(LineMatch(0x1000, 10, 0), out[0]); |
| EXPECT_EQ(LineMatch(0x1002, 10, 2), out[1]); |
| |
| // Dupes in the same function should return the smallest match. |
| out = GetBestLineMatches( |
| {LineMatch(0x1002, 10, 0), // Match, discarded due to higher addr. |
| LineMatch(0x1001, 20, 0), // No line match. |
| LineMatch(0x1000, 10, 0), // Match, this one last lowest addr. |
| LineMatch(0x1003, 10, 1)}); // Same line, different function. |
| ASSERT_EQ(2u, out.size()); |
| EXPECT_EQ(LineMatch(0x1000, 10, 0), out[0]); |
| EXPECT_EQ(LineMatch(0x1003, 10, 1), out[1]); |
| } |
| |
| } // namespace zxdb |