blob: de22708f37a27193d3a4d97039e1bd6313f42758 [file] [log] [blame]
// Copyright 2020 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 "tools/symbolizer/log_parser.h"
#include <sstream>
#include <string_view>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace symbolizer {
namespace {
class MockSymbolizer : public Symbolizer {
public:
MOCK_METHOD(void, Reset, (), (override));
MOCK_METHOD(void, Module, (uint64_t id, std::string_view name, std::string_view build_id),
(override));
MOCK_METHOD(void, MMap,
(uint64_t address, uint64_t size, uint64_t module_id, std::string_view flags,
uint64_t module_offset),
(override));
MOCK_METHOD(void, Backtrace,
(int frame_id, uint64_t address, AddressType type, std::string_view message),
(override));
MOCK_METHOD(void, DumpFile, (std::string_view type, std::string_view name), (override));
};
class LogParserTest : public ::testing::Test {
public:
LogParserTest() : printer_(output_), log_parser(input_, &printer_, &symbolizer_) {}
void ProcessOneLine(const char* input) {
input_ << input << std::endl;
ASSERT_TRUE(log_parser.ProcessOneLine());
}
protected:
std::stringstream input_;
std::stringstream output_;
Printer printer_;
MockSymbolizer symbolizer_;
LogParser log_parser;
};
TEST_F(LogParserTest, NoMarkup) {
ProcessOneLine("normal content");
ASSERT_EQ(output_.str(), "normal content\n");
ProcessOneLine("{{{invalid_tag}}}");
ASSERT_EQ(output_.str(), "normal content\n{{{invalid_tag}}}\n");
}
TEST_F(LogParserTest, ResetWithContext) {
EXPECT_CALL(symbolizer_, Reset()).Times(1);
ProcessOneLine("context: {{{reset}}}");
ASSERT_EQ(output_.str(), "");
printer_.OutputWithContext("");
ASSERT_EQ(output_.str(), "context: \n");
}
TEST_F(LogParserTest, Module) {
EXPECT_CALL(symbolizer_, Module(0, std::string_view("libc.so"), std::string_view("8ce60b")));
ProcessOneLine("context1: {{{module:0x0:libc.so:elf:8ce60b}}}");
EXPECT_CALL(symbolizer_, Module(5, std::string_view("libc.so"), std::string_view("8ce60b")));
ProcessOneLine("context2: {{{module:0x5:libc.so:elf:8ce60b:unnecessary_content}}}");
EXPECT_CALL(symbolizer_, Module(3, std::string_view(""), std::string_view("8ce60b")));
ProcessOneLine("context3: {{{module:0x3::elf:8ce60b}}}");
ASSERT_EQ(output_.str(), "");
EXPECT_CALL(symbolizer_, Module).Times(0);
ProcessOneLine("context4: {{{module:0x5:libc.so:not_elf:8ce60b}}}");
ASSERT_EQ(output_.str(), "context4: {{{module:0x5:libc.so:not_elf:8ce60b}}}\n");
}
TEST_F(LogParserTest, MMap) {
EXPECT_CALL(symbolizer_, MMap(0xbb57d35000, 0x2000, 0, std::string_view("r"), 0));
ProcessOneLine("{{{mmap:0xbb57d35000:0x2000:load:0:r:0}}}");
}
TEST_F(LogParserTest, Backtrace) {
EXPECT_CALL(symbolizer_,
Backtrace(1, 0xbb57d370b0, Symbolizer::AddressType::kUnknown, std::string_view("")));
ProcessOneLine("{{{bt:1:0xbb57d370b0}}}");
EXPECT_CALL(symbolizer_, Backtrace(1, 0xbb57d370b0, Symbolizer::AddressType::kUnknown,
std::string_view("sp 0x3f540e65ef0")));
ProcessOneLine("{{{bt:1:0xbb57d370b0:sp 0x3f540e65ef0}}}");
EXPECT_CALL(symbolizer_, Backtrace(1, 0xbb57d370b0, Symbolizer::AddressType::kProgramCounter,
std::string_view("")));
ProcessOneLine("{{{bt:1:0xbb57d370b0:pc}}}");
EXPECT_CALL(symbolizer_, Backtrace(1, 0xbb57d370b0, Symbolizer::AddressType::kProgramCounter,
std::string_view("sp 0x3f540e65ef0")));
ProcessOneLine("{{{bt:1:0xbb57d370b0:pc:sp 0x3f540e65ef0}}}");
ASSERT_EQ(output_.str(), "");
}
TEST_F(LogParserTest, DumpFile) {
EXPECT_CALL(symbolizer_, DumpFile(std::string_view("type"), std::string_view("name")));
ProcessOneLine("{{{dumpfile:type:name}}}");
ASSERT_EQ(output_.str(), "");
}
} // namespace
} // namespace symbolizer