blob: 74abab6c2b7971de43a4145991b79b0aa76a776d [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/symbols/code_block.h"
#include "garnet/bin/zxdb/symbols/symbol_context.h"
#include "gtest/gtest.h"
namespace zxdb {
TEST(CodeBlock, ContainsAddress) {
auto block = fxl::MakeRefCounted<CodeBlock>(Symbol::kTagLexicalBlock);
SymbolContext context = SymbolContext::ForRelativeAddresses();
// No code range: contains all addresses.
EXPECT_TRUE(block->ContainsAddress(context, 0));
EXPECT_TRUE(block->ContainsAddress(context, 0x2000));
// Set some ranges.
block->set_code_ranges(AddressRanges(
AddressRanges::kCanonical,
{AddressRange(0x1000, 0x2000), AddressRange(0x3000, 0x3001)}));
// Blocks should count the beginning but not the end as inside them.
EXPECT_TRUE(block->ContainsAddress(context, 0x1000));
EXPECT_TRUE(block->ContainsAddress(context, 0x1100));
EXPECT_FALSE(block->ContainsAddress(context, 0x2000));
EXPECT_FALSE(block->ContainsAddress(context, 0x2fff));
EXPECT_TRUE(block->ContainsAddress(context, 0x3000));
EXPECT_FALSE(block->ContainsAddress(context, 0x3001));
EXPECT_FALSE(block->ContainsAddress(context, 0x3002));
// Test with a non-relative symbol context.
constexpr uint64_t kBase = 0x10000000;
SymbolContext base_context(kBase);
EXPECT_FALSE(block->ContainsAddress(base_context, 0x1000));
EXPECT_TRUE(block->ContainsAddress(base_context, kBase + 0x1000));
}
TEST(CodeBlock, GetMostSpecificChild) {
auto outer = fxl::MakeRefCounted<CodeBlock>(Symbol::kTagLexicalBlock);
// Outer has two ranges.
outer->set_code_ranges(AddressRanges(
AddressRanges::kCanonical,
{AddressRange(0x1000, 0x2000), AddressRange(0x3000, 0x3001)}));
// There are two inner blocks, one covers partially the first range, the
// other covers exactly the second range.
auto first_child = fxl::MakeRefCounted<CodeBlock>(Symbol::kTagLexicalBlock);
first_child->set_code_ranges(AddressRanges(AddressRange(0x1000, 0x2000)));
auto second_child = fxl::MakeRefCounted<CodeBlock>(Symbol::kTagLexicalBlock);
second_child->set_code_ranges(AddressRanges(AddressRange(0x3000, 0x3001)));
// Append the child ranges.
std::vector<LazySymbol> outer_inner;
outer_inner.emplace_back(first_child);
outer_inner.emplace_back(second_child);
outer->set_inner_blocks(outer_inner);
// The first child has yet another child.
auto child_child = fxl::MakeRefCounted<CodeBlock>(Symbol::kTagLexicalBlock);
child_child->set_code_ranges(AddressRanges(AddressRange(0x1000, 0x1100)));
std::vector<LazySymbol> inner_inner;
inner_inner.emplace_back(child_child);
first_child->set_inner_blocks(inner_inner);
// The second child has an inner child with no defined range.
auto child_child2 = fxl::MakeRefCounted<CodeBlock>(Symbol::kTagLexicalBlock);
std::vector<LazySymbol> inner_inner2;
inner_inner2.emplace_back(child_child2);
second_child->set_inner_blocks(inner_inner2);
SymbolContext context = SymbolContext::ForRelativeAddresses();
// Querying for something out-of-range.
EXPECT_EQ(nullptr, outer->GetMostSpecificChild(context, 0x1));
// Something in the first level of children but not in the second.
EXPECT_EQ(first_child.get(), outer->GetMostSpecificChild(context, 0x1200));
// Lowest level of child.
EXPECT_EQ(child_child.get(), outer->GetMostSpecificChild(context, 0x1000));
EXPECT_EQ(child_child2.get(), outer->GetMostSpecificChild(context, 0x3000));
}
} // namespace zxdb