blob: aa72847fbd3e3866f7a96451b689d0dabbd4c586 [file] [log] [blame]
// Copyright 2019 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 "src/developer/debug/zxdb/console/format_function.h"
#include "gtest/gtest.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"
#include "src/developer/debug/zxdb/symbols/collection.h"
#include "src/developer/debug/zxdb/symbols/function.h"
#include "src/developer/debug/zxdb/symbols/namespace.h"
#include "src/developer/debug/zxdb/symbols/type_test_support.h"
#include "src/developer/debug/zxdb/symbols/variable_test_support.h"
namespace zxdb {
TEST(FormatFunction, Regular) {
auto function = fxl::MakeRefCounted<Function>(DwarfTag::kSubprogram);
function->set_assigned_name("Function");
// Function with no parameters.
EXPECT_EQ("Function()", FormatFunctionName(function.get(), false).AsString());
EXPECT_EQ("Function()", FormatFunctionName(function.get(), true).AsString());
// Add two parameters.
auto int32_type = MakeInt32Type();
auto param_value = MakeVariableForTest("value", int32_type, 0x100, 0x200, std::vector<uint8_t>());
auto param_other =
MakeVariableForTest("other_param", int32_type, 0x100, 0x200, std::vector<uint8_t>());
function->set_parameters({LazySymbol(param_value), LazySymbol(param_other)});
EXPECT_EQ("Function(…)", FormatFunctionName(function.get(), false).AsString());
EXPECT_EQ("Function(int32_t, int32_t)", FormatFunctionName(function.get(), true).AsString());
// Put in a namespace and add some templates. This needs a new function
// because the name will be cached above.
function = fxl::MakeRefCounted<Function>(DwarfTag::kSubprogram);
function->set_assigned_name("Function<int>");
function->set_parameters({LazySymbol(param_value), LazySymbol(param_other)});
auto ns = fxl::MakeRefCounted<Namespace>();
ns->set_assigned_name("ns");
function->set_parent(LazySymbol(ns));
EXPECT_EQ(
"kNormal \"ns::\", "
"kHeading \"Function\", "
"kComment \"<int>(…)\"",
FormatFunctionName(function.get(), false).GetDebugString());
function->set_parent(LazySymbol());
}
TEST(FormatFunction, ClangLambda) {
// Clang lambdas are anonymous classes with an "operator()" function.
auto closure = fxl::MakeRefCounted<Collection>(DwarfTag::kClassType);
auto function = fxl::MakeRefCounted<Function>(DwarfTag::kSubprogram);
function->set_assigned_name("operator()");
function->set_parent(LazySymbol(closure));
EXPECT_EQ("λ()", FormatFunctionName(function.get(), false).AsString());
}
TEST(FormatFunction, GCCLambda) {
// GCC lambdas are specially-named structs with an "operator()" function.
auto closure = fxl::MakeRefCounted<Collection>(DwarfTag::kStructureType);
closure->set_assigned_name("<lambda()>");
auto function = fxl::MakeRefCounted<Function>(DwarfTag::kSubprogram);
function->set_assigned_name("operator()");
function->set_parent(LazySymbol(closure));
EXPECT_EQ("λ()", FormatFunctionName(function.get(), false).AsString());
}
TEST(FormatFunction, RustClosure) {
// Rust closures are named like:
// "fuchsia_async::executor::{{impl}}::run_singlethreaded::{{closure}}<()>"
// The function "assigned name" will be "{{closure}}<()>".
// Make a function for the closure to be inside of.
auto enclosing = fxl::MakeRefCounted<Function>(DwarfTag::kSubprogram);
enclosing->set_assigned_name("EnclosingFunction");
auto closure = fxl::MakeRefCounted<Function>(DwarfTag::kSubprogram);
closure->set_assigned_name("{{closure}}<()>");
closure->set_parent(LazySymbol(enclosing));
EXPECT_EQ("λ()", FormatFunctionName(closure.get(), false).AsString());
}
} // namespace zxdb