Files
FESADev/tests/unit/model/source_target_resolver_test.cpp

136 lines
5.6 KiB
C++

#include "fesa/model/source_target_resolver.h"
#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
namespace {
fesa::SourceTargetIndexEntry Entry(const fesa::SourceEntityKind entity_kind,
std::string instance_name,
std::string target_name,
const std::int64_t source_label,
std::string source_label_text,
const fesa::EntityIndex entity_index,
const std::size_t declaration_order) {
fesa::SourceEntityId source_id{instance_name, source_label,
std::move(source_label_text)};
return {entity_kind,
std::move(instance_name),
std::move(target_name),
std::move(source_id),
entity_index,
declaration_order};
}
std::vector<fesa::EntityIndex> Indices(
const std::vector<fesa::ResolvedSourceTarget>& targets) {
std::vector<fesa::EntityIndex> indices;
indices.reserve(targets.size());
for (const auto& target : targets) {
indices.push_back(target.entity_index);
}
return indices;
}
void ExpectFailure(const fesa::SourceTargetIndex& index,
fesa::SourceTargetQuery query, const std::string& code) {
const auto result = fesa::SourceTargetResolver{index}.Resolve(query);
ASSERT_FALSE(result.HasValue());
EXPECT_EQ(result.GetStatus().Category(), fesa::FailureCategory::kInput);
ASSERT_FALSE(result.GetStatus().Diagnostics().empty());
EXPECT_EQ(result.GetStatus().Diagnostics()[0U].code, code);
EXPECT_EQ(result.GetStatus().Diagnostics()[0U].entity_identity,
query.target_name_or_label);
}
} // namespace
TEST(SourceTargetResolver,
SeparatesNamespacesAndInstancesAndExpandsInDeclarationOrder) {
using fesa::SourceEntityKind;
fesa::SourceTargetIndex index{{
Entry(SourceEntityKind::kNode, "Beam-1", "Ends", 20, "0020", 1U, 30U),
Entry(SourceEntityKind::kElement, "Beam-1", "Ends", 700, "0700", 4U, 10U),
Entry(SourceEntityKind::kNode, "Beam-1", "Ends", 10, "0010", 0U, 20U),
Entry(SourceEntityKind::kNode, "Beam-2", "Ends", 10, "0010", 2U, 40U),
Entry(SourceEntityKind::kNode, "Beam-1", "", 10, "0010", 0U, 0U),
}};
const fesa::SourceTargetResolver resolver{index};
auto nodes = resolver.Resolve({SourceEntityKind::kNode, "bEaM-1", "eNdS"});
ASSERT_TRUE(nodes.HasValue());
EXPECT_EQ(Indices(nodes.Value()), (std::vector<fesa::EntityIndex>{0U, 1U}));
EXPECT_EQ(nodes.Value()[0U].source_id.instance_name, "Beam-1");
EXPECT_EQ(nodes.Value()[0U].source_id.source_label_text, "0010");
auto elements =
resolver.Resolve({SourceEntityKind::kElement, "BEAM-1", "ends"});
ASSERT_TRUE(elements.HasValue());
EXPECT_EQ(Indices(elements.Value()), (std::vector<fesa::EntityIndex>{4U}));
auto second_instance =
resolver.Resolve({SourceEntityKind::kNode, "beam-2", "ENDS"});
ASSERT_TRUE(second_instance.HasValue());
EXPECT_EQ(Indices(second_instance.Value()),
(std::vector<fesa::EntityIndex>{2U}));
auto direct = resolver.Resolve({SourceEntityKind::kNode, "Beam-1", "10"});
ASSERT_TRUE(direct.HasValue());
EXPECT_EQ(Indices(direct.Value()), (std::vector<fesa::EntityIndex>{0U}));
}
TEST(SourceTargetResolver, RejectsMissingAmbiguousAndNonpositiveTargets) {
using fesa::SourceEntityKind;
const fesa::SourceTargetIndex index{{
Entry(SourceEntityKind::kNode, "Beam-1", "", 10, "10", 0U, 0U),
Entry(SourceEntityKind::kNode, "Beam-2", "", 10, "10", 1U, 1U),
Entry(SourceEntityKind::kNode, "Beam-1", "10", 20, "20", 2U, 2U),
Entry(SourceEntityKind::kNode, "Beam-1", "Shared", 10, "10", 0U, 3U),
Entry(SourceEntityKind::kNode, "Beam-2", "Shared", 10, "10", 1U, 4U),
}};
ExpectFailure(index, {SourceEntityKind::kNode, "", "Missing"},
"unresolved-source-target");
ExpectFailure(index, {SourceEntityKind::kNode, "", "0"},
"invalid-source-target");
ExpectFailure(index, {SourceEntityKind::kNode, "", "-7"},
"invalid-source-target");
ExpectFailure(index, {SourceEntityKind::kNode, "", "10"},
"ambiguous-source-target");
ExpectFailure(index, {SourceEntityKind::kNode, "", "Shared"},
"ambiguous-source-target");
ExpectFailure(index, {SourceEntityKind::kNode, "Beam-1", "10"},
"ambiguous-source-target");
}
TEST(SourceTargetResolver,
ReportsDuplicateMembershipsInDeterministicDeclarationOrder) {
using fesa::SourceEntityKind;
const fesa::SourceTargetIndex index{{
Entry(SourceEntityKind::kNode, "Beam-1", "Duplicate", 10, "10", 0U, 1U),
Entry(SourceEntityKind::kNode, "Beam-1", "Duplicate", 10, "10", 0U, 9U),
Entry(SourceEntityKind::kNode, "Beam-1", "Duplicate", 20, "20", 1U, 2U),
Entry(SourceEntityKind::kNode, "Beam-1", "Duplicate", 20, "20", 1U, 7U),
}};
const auto result = fesa::SourceTargetResolver{index}.Resolve(
{SourceEntityKind::kNode, "Beam-1", "duplicate"});
ASSERT_FALSE(result.HasValue());
EXPECT_EQ(result.GetStatus().Category(), fesa::FailureCategory::kInput);
ASSERT_EQ(result.GetStatus().Diagnostics().size(), 2U);
EXPECT_EQ(result.GetStatus().Diagnostics()[0U].code,
"duplicate-source-target");
EXPECT_EQ(result.GetStatus().Diagnostics()[0U].message,
"Duplicate resolved source target 20.");
EXPECT_EQ(result.GetStatus().Diagnostics()[1U].code,
"duplicate-source-target");
EXPECT_EQ(result.GetStatus().Diagnostics()[1U].message,
"Duplicate resolved source target 10.");
}