ConceptCore/ccl/cclLang/test/src/testReference.cpp
2024-04-15 22:16:14 +03:00

278 lines
9.5 KiB
C++

#define GTEST_LANG_CXX11 1
#include "gtest/gtest.h"
#include "FakeTermContext.hpp"
#include "MockTextProcessor.hpp"
#include "RefHelper.hpp"
#include "ccl/lang/TextEnvironment.h"
#include "ccl/lang/Reference.h"
#include "ccl/lang/Literals.h"
using ccl::lang::operator""_form;
using ccl::lang::operator""_ref;
class UTReference : public ::testing::Test {
protected:
using ReferenceType = ccl::lang::ReferenceType;
using Reference = ccl::lang::Reference;
using EntityRef = ccl::lang::EntityRef;
using CollaborationRef = ccl::lang::CollaborationRef;
using StrRange = ccl::StrRange;
using TextEnvironment = ccl::lang::TextEnvironment;
using TextProcessor = ccl::lang::TextProcessor;
protected:
static inline const std::string sampleCompanionRef { "@{-1|\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439}" };
static inline const std::string sampleRef { "\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439" };
static inline const std::string complexRefStr
{ "42 @{X1|nomn,sing} 43 @{-1|basic} 44 @{X1|nomn,sing} 45" };
static constexpr auto sampleOffset = -1;
static inline const Reference x1ref{ EntityRef{ "X1", "sing,nomn"_form } };
};
TEST_F(UTReference, Construction) {
{
const EntityRef term{ "X1", "sing,nomn"_form };
const Reference ref{ term, StrRange(1, 4) };
EXPECT_EQ(ref.position, StrRange(1, 4));
EXPECT_EQ(ref.resolvedText, "");
EXPECT_EQ(ref.GetType(), ReferenceType::entity);
EXPECT_EQ(ref.GetEntity(), term.entity);
EXPECT_EQ(ref.GetForm(), term.form);
}
{
const CollaborationRef collab{ "test", 4 };
const Reference ref{ collab, StrRange(2, 5) };
EXPECT_EQ(ref.position, StrRange(2, 5));
EXPECT_EQ(ref.resolvedText, "");
EXPECT_EQ(ref.GetType(), ReferenceType::collaboration);
EXPECT_EQ(ref.GetOffset(), collab.offset);
EXPECT_EQ(ref.GetNominal(), collab.nominal);
}
}
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable : 4834 ) // ignore not using return value
#endif
TEST_F(UTReference, ReferenceID) {
{
const Reference ref{ EntityRef{ "X1", "sing,nomn"_form } };
ASSERT_EQ(ref.GetType(), ReferenceType::entity);
EXPECT_TRUE(ref.IsEntity());
EXPECT_FALSE(ref.IsCollaboration());
EXPECT_EQ(ref.GetEntity(), "X1");
EXPECT_EQ(ref.GetForm(), "sing,nomn"_form);
}
{
const Reference ref{ CollaborationRef{ "text", 1337 }};
ASSERT_EQ(ref.GetType(), ReferenceType::collaboration);
EXPECT_FALSE(ref.IsEntity());
EXPECT_TRUE(ref.IsCollaboration());
EXPECT_EQ(ref.GetOffset(), 1337);
EXPECT_EQ(ref.GetNominal(), "text");
}
}
#ifdef _MSC_VER
#pragma warning( pop )
#endif
TEST_F(UTReference, ToString) {
{
const EntityRef term{ "X1", "sing,nomn"_form };
EXPECT_EQ(term.ToString(), tccl::EntityRef("X1"));
const Reference ref{ term };
EXPECT_EQ(ref.ToString(), term.ToString());
}
{
const CollaborationRef collab{ sampleRef, sampleOffset };
EXPECT_EQ(collab.ToString(), sampleCompanionRef);
const Reference ref{ collab };
EXPECT_EQ(ref.ToString(), collab.ToString());
}
}
TEST_F(UTReference, ParseErrors) {
EXPECT_FALSE(Reference::Parse("").IsValid());
EXPECT_FALSE(Reference::Parse("@{}").IsValid());
EXPECT_FALSE(Reference::Parse("@{ }").IsValid());
EXPECT_FALSE(Reference::Parse("@{|}").IsValid());
EXPECT_FALSE(Reference::Parse("@{ | }").IsValid());
EXPECT_FALSE(Reference::Parse("@{ || }").IsValid());
EXPECT_FALSE(Reference::Parse("@{-1a|text}").IsValid());
EXPECT_FALSE(Reference::Parse("invalid").IsValid());
EXPECT_FALSE(Reference::Parse(tccl::EntityRef("X1") + " " + tccl::EntityRef("X2")).IsValid());
}
TEST_F(UTReference, ParseEntity) {
auto ref = Reference::Parse(tccl::EntityRef("X1"));
ASSERT_TRUE(ref.IsValid());
ASSERT_TRUE(ref.IsEntity());
EXPECT_EQ(ref.GetEntity(), "X1");
EXPECT_EQ(ref.GetForm(), "sing,nomn"_form);
}
TEST_F(UTReference, ParseEntityLegacy) {
const auto form = "sing,nomn"_form;
{
auto ref = Reference::Parse("@{X1|nomn|sing|0}");
ASSERT_TRUE(ref.IsValid());
ASSERT_TRUE(ref.IsEntity());
EXPECT_EQ(ref.GetEntity(), "X1");
EXPECT_EQ(ref.GetForm(), "sing,nomn"_form);
}
{
auto ref = Reference::Parse("@{X1|nomn|sing}");
ASSERT_TRUE(ref.IsValid());
ASSERT_TRUE(ref.IsEntity());
EXPECT_EQ(ref.GetEntity(), "X1");
EXPECT_EQ(ref.GetForm(), "sing,nomn"_form);
}
}
TEST_F(UTReference, ParseCollaboration) {
auto ref = Reference::Parse(sampleCompanionRef);
ASSERT_TRUE(ref.IsValid());
ASSERT_TRUE(ref.IsCollaboration());
EXPECT_EQ(ref.GetOffset(), sampleOffset);
EXPECT_EQ(ref.GetNominal(), sampleRef);
}
TEST_F(UTReference, ParseReferences) {
const auto parsed = Reference::ExtractAll(complexRefStr);
ASSERT_EQ(3u, std::size(parsed));
{
EXPECT_EQ(parsed.at(0).position, StrRange(3, 18));
ASSERT_TRUE(parsed.at(0).IsEntity());
const auto& ref = parsed.at(0);
EXPECT_EQ(ref.GetEntity(), "X1");
EXPECT_EQ(ref.GetForm(), "sing,nomn"_form);
}
{
EXPECT_EQ(parsed.at(1).position, StrRange(22, 33));
ASSERT_TRUE(parsed.at(1).IsCollaboration());
const auto& ref = parsed.at(1);
EXPECT_EQ(ref.GetNominal(), "basic");
EXPECT_EQ(ref.GetOffset(), -1);
}
{
EXPECT_EQ(parsed.at(2).position, StrRange(37, 52));
ASSERT_TRUE(parsed.at(2).IsEntity());
const auto& ref = parsed.at(2);
EXPECT_EQ(ref.GetEntity(), "X1");
EXPECT_EQ(ref.GetForm(), "sing,nomn"_form);
}
}
TEST_F(UTReference, ReferenceLiteral) {
const auto ref = "@{X1|nomn,plur}"_ref;
ASSERT_TRUE(ref.IsEntity());
EXPECT_EQ(ref.GetEntity(), "X1");
EXPECT_EQ(ref.GetForm(), "nomn,plur"_form);
}
TEST_F(UTReference, TranslateEntity) {
auto ref = x1ref;
EXPECT_FALSE(ref.TranslateEntity(ccl::CreateTranslator({ { "X42", "X43" } })));
EXPECT_TRUE(ref.TranslateEntity(ccl::CreateTranslator({ { "X1", "X2" }, { "X2", "X3" } })));
EXPECT_EQ(ref.GetEntity(), "X2");
}
TEST_F(UTReference, ResolveEntity) {
TextEnvironment::SetProcessor(std::make_unique<tccl::MockTextProcessor>());
auto& processor = static_cast<tccl::MockTextProcessor&>(TextEnvironment::Processor());
FakeContext context{};
auto emptyRef = Reference{ EntityRef{"", ""_form} };
emptyRef.ResolveEntity(context);
EXPECT_EQ(emptyRef.resolvedText, "!Empty reference!");
EXPECT_EQ(size(processor.log), 0U);
auto ref = x1ref;
ref.ResolveEntity(context);
EXPECT_EQ(ref.resolvedText, "!Cannot find entity: 'X1'!");
EXPECT_EQ(size(processor.log), 0U);
context.Insert("X1", ccl::lang::LexicalTerm{ "Test" });
ref.ResolveEntity(context);
EXPECT_EQ(ref.resolvedText, "Test");
ASSERT_EQ(size(processor.log), 1U);
EXPECT_EQ(processor.log.at(0).type, tccl::MockTextProcessor::CallType::INFLECT);
EXPECT_EQ(processor.log.at(0).targetText, "Test");
EXPECT_EQ(processor.log.at(0).form, x1ref.GetForm());
processor.ClearAll();
context.Clear();
context.Insert("X1", ccl::lang::LexicalTerm{ "" });
ref.resolvedText.clear();
ref.ResolveEntity(context);
EXPECT_EQ(ref.resolvedText, "!Empty reference!");
ASSERT_EQ(size(processor.log), 1U);
EXPECT_EQ(processor.log.at(0).type, tccl::MockTextProcessor::CallType::INFLECT);
EXPECT_EQ(processor.log.at(0).targetText, "");
EXPECT_EQ(processor.log.at(0).form, x1ref.GetForm());
TextEnvironment::SetProcessor(std::make_unique<TextProcessor>());
}
TEST_F(UTReference, ResolveCollaborationEmpty) {
TextEnvironment::SetProcessor(std::make_unique<tccl::MockTextProcessor>());
auto& processor = static_cast<tccl::MockTextProcessor&>(TextEnvironment::Processor());
auto emptyRef = Reference{ CollaborationRef{ "", 1 } };
emptyRef.ResolveCollaboration(nullptr);
EXPECT_EQ(emptyRef.resolvedText, "!Empty reference!");
EXPECT_EQ(size(processor.log), 0U);
auto master = Reference{ x1ref };
master.resolvedText = "";
emptyRef.resolvedText = "";
emptyRef.ResolveCollaboration(&master);
EXPECT_EQ(emptyRef.resolvedText, "!Empty reference!");
EXPECT_EQ(size(processor.log), 0U);
master.resolvedText = "test";
emptyRef.resolvedText = "";
emptyRef.ResolveCollaboration(&master);
EXPECT_EQ(emptyRef.resolvedText, "!Empty reference!");
EXPECT_EQ(size(processor.log), 0U);
TextEnvironment::SetProcessor(std::make_unique<TextProcessor>());
}
TEST_F(UTReference, ResolveCollaborationValid) {
TextEnvironment::SetProcessor(std::make_unique<tccl::MockTextProcessor>());
auto& processor = static_cast<tccl::MockTextProcessor&>(TextEnvironment::Processor());
auto collabRef = Reference{ CollaborationRef{ "companion", 1 } };
collabRef.ResolveCollaboration(nullptr);
EXPECT_EQ(collabRef.resolvedText, "!Invalid offset for companion: '1'!");
EXPECT_EQ(size(processor.log), 0U);
auto master = Reference{ x1ref };
master.resolvedText = "";
collabRef.resolvedText = "";
collabRef.ResolveCollaboration(&master);
EXPECT_EQ(collabRef.resolvedText, "companion");
ASSERT_EQ(size(processor.log), 1U);
EXPECT_EQ(processor.log.at(0).type, tccl::MockTextProcessor::CallType::DEPENDANT);
EXPECT_EQ(processor.log.at(0).targetText, "companion");
EXPECT_EQ(processor.log.at(0).mainText, "");
processor.ClearAll();
master.resolvedText = "test";
collabRef.resolvedText = "";
processor.AddCollaboration(collabRef.GetNominal(), master.resolvedText, "companion_inflected");
collabRef.ResolveCollaboration(&master);
EXPECT_EQ(collabRef.resolvedText, "companion_inflected");
ASSERT_EQ(size(processor.log), 1U);
EXPECT_EQ(processor.log.at(0).type, tccl::MockTextProcessor::CallType::DEPENDANT);
EXPECT_EQ(processor.log.at(0).targetText, "companion");
EXPECT_EQ(processor.log.at(0).mainText, "test");
TextEnvironment::SetProcessor(std::make_unique<TextProcessor>());
}