blob: 096f5c7bad95456d4045ee9237af2d9da035bf50 [file] [log] [blame]
// 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/console/format_frame.h"
#include "garnet/bin/zxdb/client/mock_frame.h"
#include "garnet/bin/zxdb/client/session.h"
#include "garnet/bin/zxdb/console/format_value.h"
#include "garnet/bin/zxdb/console/mock_format_value_process_context.h"
#include "garnet/bin/zxdb/console/output_buffer.h"
#include "garnet/bin/zxdb/symbols/function.h"
#include "garnet/bin/zxdb/symbols/location.h"
#include "garnet/bin/zxdb/symbols/symbol_context.h"
#include "garnet/lib/debug_ipc/helper/platform_message_loop.h"
#include "gtest/gtest.h"
namespace zxdb {
namespace {
// Synchronous wrapper around asynchronous long formatting.
std::string SyncFormatFrameLong(const Frame* frame,
const FormatExprValueOptions& options) {
debug_ipc::PlatformMessageLoop loop;
loop.Init();
auto helper = fxl::MakeRefCounted<FormatValue>(
std::make_unique<MockFormatValueProcessContext>());
FormatFrameLong(frame, false, helper.get(), FormatExprValueOptions());
std::string out_string;
bool complete = false;
helper->Complete([&loop, &out_string, &complete](OutputBuffer out) {
complete = true;
out_string = out.AsString();
loop.QuitNow();
});
if (!complete) {
// Did not complete synchronously, run the loop.
loop.Run();
}
EXPECT_TRUE(complete);
loop.Cleanup();
return out_string;
}
} // namespace
TEST(FormatFrame, Unsymbolized) {
debug_ipc::StackFrame stack_frame;
stack_frame.ip = 0x12345678;
stack_frame.bp = 0xdeadbeef;
stack_frame.sp = 0x567890;
MockFrame frame(nullptr, nullptr, stack_frame,
Location(Location::State::kSymbolized, stack_frame.ip));
OutputBuffer out;
// Short format just prints the address.
FormatFrame(&frame, false, &out);
EXPECT_EQ("0x12345678", out.AsString());
// Long version should do the same (not duplicate it).
EXPECT_EQ("\n IP = 0x12345678, BP = 0xdeadbeef, SP = 0x567890",
SyncFormatFrameLong(&frame, FormatExprValueOptions()));
// With index.
out = OutputBuffer();
FormatFrame(&frame, false, &out, 3);
EXPECT_EQ("Frame 3 0x12345678", out.AsString());
}
TEST(FormatFrame, Inline) {
debug_ipc::StackFrame stack_frame;
stack_frame.ip = 0x12345678;
stack_frame.bp = 0xdeadbeef;
stack_frame.sp = 0x567890;
// This is to have some place for the inline frame to refer to as the
// underlying physical frame. The values are ignored.
MockFrame physical_frame(
nullptr, nullptr, stack_frame,
Location(Location::State::kSymbolized, stack_frame.ip));
SymbolContext symbol_context = SymbolContext::ForRelativeAddresses();
auto function = fxl::MakeRefCounted<Function>(Symbol::kTagInlinedSubroutine);
function->set_assigned_name("Function");
MockFrame inline_frame(nullptr, nullptr, stack_frame,
Location(stack_frame.ip, FileLine("file.cc", 22), 0,
symbol_context, LazySymbol(function)),
&physical_frame);
EXPECT_EQ("Function() • file.cc:22 (inline)\n"
" IP = 0x12345678, BP = 0xdeadbeef, SP = 0x567890",
SyncFormatFrameLong(&inline_frame, FormatExprValueOptions()));
}
} // namespace zxdb