blob: 2cddf8ff4e900dddd3801d8bf1b4bc4093a03f8f [file] [log] [blame]
//===-- FormatEntityTest.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/FormatEntity.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
using namespace lldb_private;
using namespace llvm;
using Definition = FormatEntity::Entry::Definition;
using Entry = FormatEntity::Entry;
static Expected<std::string> Format(StringRef format_str) {
StreamString stream;
FormatEntity::Entry format;
Status status = FormatEntity::Parse(format_str, format);
if (status.Fail())
return status.ToError();
FormatEntity::Format(format, stream, nullptr, nullptr, nullptr, nullptr,
false, false);
return stream.GetString().str();
}
TEST(FormatEntityTest, DefinitionConstructionNameAndType) {
Definition d("foo", FormatEntity::Entry::Type::Invalid);
EXPECT_STREQ(d.name, "foo");
EXPECT_EQ(d.string, nullptr);
EXPECT_EQ(d.type, FormatEntity::Entry::Type::Invalid);
EXPECT_EQ(d.data, 0UL);
EXPECT_EQ(d.num_children, 0UL);
EXPECT_EQ(d.children, nullptr);
EXPECT_FALSE(d.keep_separator);
}
TEST(FormatEntityTest, DefinitionConstructionNameAndString) {
Definition d("foo", "string");
EXPECT_STREQ(d.name, "foo");
EXPECT_STREQ(d.string, "string");
EXPECT_EQ(d.type, FormatEntity::Entry::Type::EscapeCode);
EXPECT_EQ(d.data, 0UL);
EXPECT_EQ(d.num_children, 0UL);
EXPECT_EQ(d.children, nullptr);
EXPECT_FALSE(d.keep_separator);
}
TEST(FormatEntityTest, DefinitionConstructionNameTypeData) {
Definition d("foo", FormatEntity::Entry::Type::Invalid, 33);
EXPECT_STREQ(d.name, "foo");
EXPECT_EQ(d.string, nullptr);
EXPECT_EQ(d.type, FormatEntity::Entry::Type::Invalid);
EXPECT_EQ(d.data, 33UL);
EXPECT_EQ(d.num_children, 0UL);
EXPECT_EQ(d.children, nullptr);
EXPECT_FALSE(d.keep_separator);
}
TEST(FormatEntityTest, DefinitionConstructionNameTypeChildren) {
Definition d("foo", FormatEntity::Entry::Type::Invalid, 33);
Definition parent("parent", FormatEntity::Entry::Type::Invalid, 1, &d);
EXPECT_STREQ(parent.name, "parent");
EXPECT_STREQ(parent.string, nullptr);
EXPECT_EQ(parent.type, FormatEntity::Entry::Type::Invalid);
EXPECT_EQ(parent.num_children, 1UL);
EXPECT_EQ(parent.children, &d);
EXPECT_FALSE(parent.keep_separator);
EXPECT_STREQ(parent.children[0].name, "foo");
EXPECT_EQ(parent.children[0].string, nullptr);
EXPECT_EQ(parent.children[0].type, FormatEntity::Entry::Type::Invalid);
EXPECT_EQ(parent.children[0].data, 33UL);
EXPECT_EQ(parent.children[0].num_children, 0UL);
EXPECT_EQ(parent.children[0].children, nullptr);
EXPECT_FALSE(d.keep_separator);
}
constexpr llvm::StringRef lookupStrings[] = {
"${addr.load}",
"${addr.file}",
"${ansi.fg.black}",
"${ansi.fg.red}",
"${ansi.fg.green}",
"${ansi.fg.yellow}",
"${ansi.fg.blue}",
"${ansi.fg.purple}",
"${ansi.fg.cyan}",
"${ansi.fg.white}",
"${ansi.bg.black}",
"${ansi.bg.red}",
"${ansi.bg.green}",
"${ansi.bg.yellow}",
"${ansi.bg.blue}",
"${ansi.bg.purple}",
"${ansi.bg.cyan}",
"${ansi.bg.white}",
"${file.basename}",
"${file.dirname}",
"${file.fullpath}",
"${frame.index}",
"${frame.pc}",
"${frame.fp}",
"${frame.sp}",
"${frame.flags}",
"${frame.no-debug}",
"${frame.reg.*}",
"${frame.is-artificial}",
"${function.id}",
"${function.name}",
"${function.name-without-args}",
"${function.name-with-args}",
"${function.mangled-name}",
"${function.addr-offset}",
"${function.concrete-only-addr-offset-no-padding}",
"${function.line-offset}",
"${function.pc-offset}",
"${function.initial-function}",
"${function.changed}",
"${function.is-optimized}",
"${line.file.basename}",
"${line.file.dirname}",
"${line.file.fullpath}",
"${line.number}",
"${line.column}",
"${line.start-addr}",
"${line.end-addr}",
"${module.file.basename}",
"${module.file.dirname}",
"${module.file.fullpath}",
"${process.id}",
"${process.name}",
"${process.file.basename}",
"${process.file.dirname}",
"${process.file.fullpath}",
"${script.frame}",
"${script.process}",
"${script.target}",
"${script.thread}",
"${script.var}",
"${script.svar}",
"${script.thread}",
"${svar.dummy-svar-to-test-wildcard}",
"${thread.id}",
"${thread.protocol_id}",
"${thread.index}",
"${thread.info.*}",
"${thread.queue}",
"${thread.name}",
"${thread.stop-reason}",
"${thread.stop-reason-raw}",
"${thread.return-value}",
"${thread.completed-expression}",
"${target.arch}",
"${target.file.basename}",
"${target.file.dirname}",
"${target.file.fullpath}",
"${var.dummy-var-to-test-wildcard}"};
TEST(FormatEntityTest, LookupAllEntriesInTree) {
for (const llvm::StringRef testString : lookupStrings) {
Entry e;
EXPECT_TRUE(FormatEntity::Parse(testString, e).Success())
<< "Formatting " << testString << " did not succeed";
}
}
TEST(FormatEntityTest, Scope) {
// Scope with one alternative.
EXPECT_THAT_EXPECTED(Format("{${frame.pc}|foo}"), HasValue("foo"));
// Scope with multiple alternatives.
EXPECT_THAT_EXPECTED(Format("{${frame.pc}|${function.name}|foo}"),
HasValue("foo"));
// Escaped pipe inside a scope.
EXPECT_THAT_EXPECTED(Format("{foo\\|bar}"), HasValue("foo|bar"));
// Unescaped pipe outside a scope.
EXPECT_THAT_EXPECTED(Format("foo|bar"), HasValue("foo|bar"));
// Nested scopes. Note that scopes always resolve.
EXPECT_THAT_EXPECTED(Format("{{${frame.pc}|foo}|{bar}}"), HasValue("foo"));
EXPECT_THAT_EXPECTED(Format("{{${frame.pc}}|{bar}}"), HasValue(""));
// Pipe between scopes.
EXPECT_THAT_EXPECTED(Format("{foo}|{bar}"), HasValue("foo|bar"));
EXPECT_THAT_EXPECTED(Format("{foo}||{bar}"), HasValue("foo||bar"));
// Empty space between pipes.
EXPECT_THAT_EXPECTED(Format("{{foo}||{bar}}"), HasValue("foo"));
EXPECT_THAT_EXPECTED(Format("{${frame.pc}||{bar}}"), HasValue(""));
}