blob: ad6740fb7fb2b427ba2ca962d434391f12e44549 [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 "src/developer/debug/zxdb/symbols/visit_scopes.h"
#include <gtest/gtest.h>
#include "src/developer/debug/zxdb/symbols/collection.h"
#include "src/developer/debug/zxdb/symbols/inheritance_path.h"
#include "src/developer/debug/zxdb/symbols/inherited_from.h"
namespace zxdb {
TEST(VisitScopes, ClassHierarchy) {
auto base1 = fxl::MakeRefCounted<Collection>(DwarfTag::kClassType);
auto mid1 = fxl::MakeRefCounted<Collection>(DwarfTag::kClassType);
auto mid2 = fxl::MakeRefCounted<Collection>(DwarfTag::kClassType);
auto derived = fxl::MakeRefCounted<Collection>(DwarfTag::kClassType);
// Stores the collections and their paths visited.
using VisitLog = std::vector<InheritancePath>;
VisitLog visited;
// A single class with no hierarchy.
VisitResult result = VisitClassHierarchy(derived.get(), [&visited](const InheritancePath& path) {
visited.push_back(path);
return VisitResult::kContinue;
});
EXPECT_EQ(VisitResult::kContinue, result);
VisitLog expected{{{derived}}};
EXPECT_EQ(expected, visited);
// Complex hierarchy:
// base1 -- mid1 --
// \
// mid2 ------ derived
uint64_t mid1_offset = 8;
uint64_t mid2_offset = 0;
uint64_t base1_offset = 32;
auto mid1_inh = fxl::MakeRefCounted<InheritedFrom>(mid1, mid1_offset);
auto mid2_inh = fxl::MakeRefCounted<InheritedFrom>(mid2, mid2_offset);
auto base1_inh = fxl::MakeRefCounted<InheritedFrom>(base1, base1_offset);
derived->set_inherited_from({LazySymbol(mid1_inh), LazySymbol(mid2_inh)});
mid1->set_inherited_from({LazySymbol(base1_inh)});
// Visit all of those, they're visited in depth-first-search order (the ordering was most
// convenient for the implementation, it can be changed in the future if there's a reason for a
// specific different order).
visited = VisitLog();
result = VisitClassHierarchy(derived.get(), [&visited](const InheritancePath& path) {
visited.push_back(path);
return VisitResult::kContinue;
});
EXPECT_EQ(VisitResult::kContinue, result);
expected = VisitLog{{{derived}},
{{derived}, {mid1_inh, mid1}},
{{derived}, {mid1_inh, mid1}, {base1_inh, base1}},
{{derived}, {mid2_inh, mid2}}};
EXPECT_EQ(expected, visited);
// Test early termination at mid1.
visited = VisitLog();
result = VisitClassHierarchy(derived.get(), [&visited, mid1](const InheritancePath& path) {
visited.emplace_back(path);
return path.base() == mid1.get() ? VisitResult::kDone : VisitResult::kContinue;
});
EXPECT_EQ(VisitResult::kDone, result); // Should have found mid1.
expected = VisitLog{{{derived}}, {{derived}, {mid1_inh, mid1}}};
EXPECT_EQ(expected, visited);
}
} // namespace zxdb