mudlet/test/TLinkStoreTest.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

267 lines
7.5 KiB
C++
Raw Permalink Normal View History

Refactoring/reimplementation of MXP support (#3625) Refactoring/reimplementation of MXP protocol Extracts MXP support from TBuffer Separates input parsing from protocol processing: input is parsed into MxpTag objects by the MxpNodeBuilder and are passed to be handled by the MxpTagProcessor Class hierarchy of MxpTagHandler for implementing support for each tag: allows for a clear separation of the implementation of each tag and makes it easier for adding support for new tags Defines a clear interface (MxpClient) separating the MXP implementation from other parts of the code Solves some limitations of previous implementation such as supporting element definitions not only for<SEND> tags, interpolating named and positional attributes and interpolating &text; placeholder by tag content Includes support for COLOR tag Handles FONT, U, I, B, VAR and !ENTITY tags, but so far no defined behavior (can be implemented in MxpMudlet) Attributes that hold MXP state are now in the Host class to avoid needless copies when TBuffer is copied around Introduces QtTests for some of the classes Other refactorings intended to simplify TBuffer class, extracting responbilities that aren't directly related to the buffer mgmt Extracted TEncodingTable from TBuffer, this class is responsible for mapping encoding names to tables. It also removes some bloat from TBuffer. TLinkStore to manage links and associated hints to be displayed. TEntityResolver to map character entities, such as &gt; &#32; &#x20; to their associated string values; supports interpolating strings replacing the entity placeholders by their values
2020-05-03 14:09:42 -03:00
#include <TLinkStore.h>
#include <QtTest/QtTest>
class TLinkStoreTest : public QObject
{
Q_OBJECT
Refactoring/reimplementation of MXP support (#3625) Refactoring/reimplementation of MXP protocol Extracts MXP support from TBuffer Separates input parsing from protocol processing: input is parsed into MxpTag objects by the MxpNodeBuilder and are passed to be handled by the MxpTagProcessor Class hierarchy of MxpTagHandler for implementing support for each tag: allows for a clear separation of the implementation of each tag and makes it easier for adding support for new tags Defines a clear interface (MxpClient) separating the MXP implementation from other parts of the code Solves some limitations of previous implementation such as supporting element definitions not only for<SEND> tags, interpolating named and positional attributes and interpolating &text; placeholder by tag content Includes support for COLOR tag Handles FONT, U, I, B, VAR and !ENTITY tags, but so far no defined behavior (can be implemented in MxpMudlet) Attributes that hold MXP state are now in the Host class to avoid needless copies when TBuffer is copied around Introduces QtTests for some of the classes Other refactorings intended to simplify TBuffer class, extracting responbilities that aren't directly related to the buffer mgmt Extracted TEncodingTable from TBuffer, this class is responsible for mapping encoding names to tables. It also removes some bloat from TBuffer. TLinkStore to manage links and associated hints to be displayed. TEntityResolver to map character entities, such as &gt; &#32; &#x20; to their associated string values; supports interpolating strings replacing the entity placeholders by their values
2020-05-03 14:09:42 -03:00
private:
private slots:
void initTestCase() {}
Refactoring/reimplementation of MXP support (#3625) Refactoring/reimplementation of MXP protocol Extracts MXP support from TBuffer Separates input parsing from protocol processing: input is parsed into MxpTag objects by the MxpNodeBuilder and are passed to be handled by the MxpTagProcessor Class hierarchy of MxpTagHandler for implementing support for each tag: allows for a clear separation of the implementation of each tag and makes it easier for adding support for new tags Defines a clear interface (MxpClient) separating the MXP implementation from other parts of the code Solves some limitations of previous implementation such as supporting element definitions not only for<SEND> tags, interpolating named and positional attributes and interpolating &text; placeholder by tag content Includes support for COLOR tag Handles FONT, U, I, B, VAR and !ENTITY tags, but so far no defined behavior (can be implemented in MxpMudlet) Attributes that hold MXP state are now in the Host class to avoid needless copies when TBuffer is copied around Introduces QtTests for some of the classes Other refactorings intended to simplify TBuffer class, extracting responbilities that aren't directly related to the buffer mgmt Extracted TEncodingTable from TBuffer, this class is responsible for mapping encoding names to tables. It also removes some bloat from TBuffer. TLinkStore to manage links and associated hints to be displayed. TEntityResolver to map character entities, such as &gt; &#32; &#x20; to their associated string values; supports interpolating strings replacing the entity placeholders by their values
2020-05-03 14:09:42 -03:00
void testAddAndGet()
{
TLinkStore store(3);
QStringList links;
links.append("GET &href;");
links.append("LOOK &href;");
QStringList hints;
hints.append("Get &href;");
hints.append("Look at &href;");
int id = store.addLinks(links, hints);
QStringList links2 = store.getLinks(id);
QCOMPARE(links2, links);
QCOMPARE(links2[1], "LOOK &href;");
QStringList hints2 = store.getHints(id);
QCOMPARE(hints2, hints);
QCOMPARE(hints2[1], "Look at &href;");
}
void testNewGeneratedID()
{
TLinkStore store(3);
QStringList links;
store.addLinks(links, links);
QCOMPARE(store.getCurrentLinkID(), 1);
store.addLinks(links, links);
QCOMPARE(store.getCurrentLinkID(), 2);
store.addLinks(links, links);
QCOMPARE(store.getCurrentLinkID(), 3);
store.addLinks(links, links);
QCOMPARE(store.getCurrentLinkID(), 1);
store.addLinks(links, links);
QCOMPARE(store.getCurrentLinkID(), 2);
}
void testMaxId()
{
TLinkStore store(3);
QStringList links;
links.append("GET &href;");
store.addLinks(links, links);
store.addLinks(links, links);
store.addLinks(links, links);
QCOMPARE(store.getCurrentLinkID(), 3);
QCOMPARE(store.getLinks(3), links);
}
void testRemoveUnreferencedLinks()
{
TLinkStore store(10);
QStringList links1;
links1.append("command1");
QStringList hints1;
hints1.append("hint1");
QStringList links2;
links2.append("command2");
QStringList hints2;
hints2.append("hint2");
QStringList links3;
links3.append("command3");
QStringList hints3;
hints3.append("hint3");
int id1 = store.addLinks(links1, hints1);
int id2 = store.addLinks(links2, hints2);
int id3 = store.addLinks(links3, hints3);
// Verify all links exist
QCOMPARE(store.getLinksConst(id1), links1);
QCOMPARE(store.getLinksConst(id2), links2);
QCOMPARE(store.getLinksConst(id3), links3);
// Simulate only id2 is still referenced in buffer
QSet<int> referencedIds;
referencedIds.insert(id2);
store.removeUnreferencedLinks(referencedIds, nullptr);
// id2 should still exist
QCOMPARE(store.getLinksConst(id2), links2);
QCOMPARE(store.getHintsConst(id2), hints2);
// id1 and id3 should be removed
QVERIFY(store.getLinksConst(id1).isEmpty());
QVERIFY(store.getHintsConst(id1).isEmpty());
QVERIFY(store.getLinksConst(id3).isEmpty());
QVERIFY(store.getHintsConst(id3).isEmpty());
}
void testRemoveUnreferencedLinksEmpty()
{
TLinkStore store(10);
QStringList links;
links.append("command");
QStringList hints;
hints.append("hint");
int id1 = store.addLinks(links, hints);
int id2 = store.addLinks(links, hints);
// Empty reference set - all links should be removed
QSet<int> emptySet;
store.removeUnreferencedLinks(emptySet, nullptr);
QVERIFY(store.getLinksConst(id1).isEmpty());
QVERIFY(store.getHintsConst(id1).isEmpty());
QVERIFY(store.getLinksConst(id2).isEmpty());
QVERIFY(store.getHintsConst(id2).isEmpty());
}
void testRemoveUnreferencedLinksNone()
{
TLinkStore store(10);
QStringList links;
links.append("command");
QStringList hints;
hints.append("hint");
int id1 = store.addLinks(links, hints);
int id2 = store.addLinks(links, hints);
// Both links referenced - none should be removed
QSet<int> referencedIds;
referencedIds.insert(id1);
referencedIds.insert(id2);
store.removeUnreferencedLinks(referencedIds, nullptr);
QCOMPARE(store.getLinksConst(id1), links);
QCOMPARE(store.getHintsConst(id1), hints);
QCOMPARE(store.getLinksConst(id2), links);
QCOMPARE(store.getHintsConst(id2), hints);
}
void testRemoveUnreferencedLinksWithExpireNames()
{
TLinkStore store(10);
QStringList links;
links.append("command");
QStringList hints;
hints.append("hint");
int id1 = store.addLinks(links, hints, nullptr, QVector<int>(), "expire_group");
int id2 = store.addLinks(links, hints);
// Verify expire name is set for id1
QCOMPARE(store.getExpireName(id1), QString("expire_group"));
QVERIFY(store.getExpireName(id2).isEmpty());
// Simulate only id2 is still referenced in buffer
QSet<int> referencedIds;
referencedIds.insert(id2);
store.removeUnreferencedLinks(referencedIds, nullptr);
// id1 should be removed along with its expire name
QVERIFY(store.getLinksConst(id1).isEmpty());
QVERIFY(store.getHintsConst(id1).isEmpty());
QVERIFY(store.getExpireName(id1).isEmpty());
// id2 should still exist
QCOMPARE(store.getLinksConst(id2), links);
QCOMPARE(store.getHintsConst(id2), hints);
}
void testRemoveUnreferencedLinksWithLuaReferences()
{
TLinkStore store(10);
QStringList links;
links.append("command");
QStringList hints;
hints.append("hint");
QVector<int> luaRefs;
luaRefs.append(42);
int id1 = store.addLinks(links, hints, nullptr, luaRefs);
int id2 = store.addLinks(links, hints);
// Simulate only id2 is still referenced in buffer
QSet<int> referencedIds;
referencedIds.insert(id2);
store.removeUnreferencedLinks(referencedIds, nullptr);
Infrastructure: speed up compilation of Mudlet by 25% (#9021) <!-- Keep the title short & concise so anyone non-technical can understand it, the title appears in PTB changelogs --> #### Brief overview of PR changes/additions Before: Each of the 16 unit test executables compiled its own copy of the source files it needed. For example, 10 MXP tests each compiled the same TMxpTagParser.cpp, MxpTag.cpp, TEntityResolver.cpp, etc- now they get compiled just once. After: The source files are compiled once into mudlet_core (which was already being built), and each test just links against that library. #### Motivation for adding to Mudlet 1. Faster test builds - source files aren't recompiled per-test. The 16 test executables now only need to compile their own single .cpp test file and link. 2. Tests exercise the real code - previously, tests could diverge from the production build. The LinkStore_Test define was a concrete example: it compiled a stripped-down TLinkStore without styling support or Lua reference freeing. Now the test links against the exact same compiled code that ships in the application. 3. No maintenance burden for test build config - previously, adding a new compile flag, dependency, or include path to src/CMakeLists.txt required mirroring it in test/CMakeLists.txt. Now the tests inherit everything transitively through the library target. 4. Simpler CMake - 114 lines reduced to 42. Adding a new test is one line (add the name to the list) instead of writing a custom add_executable with all its source file dependencies. #### Other info (issues closed, discussion etc) Compiling Mudlet plus test before - 120s, after - 90s. Co-authored-by: Vadim Peretokin <vadi2@users.noreply.github.com>
2026-03-09 09:24:52 +01:00
// id1 should be removed (freeReference is a no-op when pH is nullptr)
QVERIFY(store.getLinksConst(id1).isEmpty());
QVERIFY(store.getHintsConst(id1).isEmpty());
// id2 should still exist
QCOMPARE(store.getLinksConst(id2), links);
QCOMPARE(store.getHintsConst(id2), hints);
}
void testStylingClearedOnIdReuse()
Refactoring/reimplementation of MXP support (#3625) Refactoring/reimplementation of MXP protocol Extracts MXP support from TBuffer Separates input parsing from protocol processing: input is parsed into MxpTag objects by the MxpNodeBuilder and are passed to be handled by the MxpTagProcessor Class hierarchy of MxpTagHandler for implementing support for each tag: allows for a clear separation of the implementation of each tag and makes it easier for adding support for new tags Defines a clear interface (MxpClient) separating the MXP implementation from other parts of the code Solves some limitations of previous implementation such as supporting element definitions not only for<SEND> tags, interpolating named and positional attributes and interpolating &text; placeholder by tag content Includes support for COLOR tag Handles FONT, U, I, B, VAR and !ENTITY tags, but so far no defined behavior (can be implemented in MxpMudlet) Attributes that hold MXP state are now in the Host class to avoid needless copies when TBuffer is copied around Introduces QtTests for some of the classes Other refactorings intended to simplify TBuffer class, extracting responbilities that aren't directly related to the buffer mgmt Extracted TEncodingTable from TBuffer, this class is responsible for mapping encoding names to tables. It also removes some bloat from TBuffer. TLinkStore to manage links and associated hints to be displayed. TEntityResolver to map character entities, such as &gt; &#32; &#x20; to their associated string values; supports interpolating strings replacing the entity placeholders by their values
2020-05-03 14:09:42 -03:00
{
TLinkStore store(3);
QStringList links;
links.append("command");
QStringList hints;
hints.append("hint");
int id1 = store.addLinks(links, hints);
QCOMPARE(id1, 1);
Mudlet::HyperlinkStyling styling;
styling.hasCustomStyling = true;
styling.selection.group = "weapons";
styling.selection.value = "sword";
styling.selection.hasSelectionSettings = true;
store.setStyling(id1, styling);
QVERIFY(store.hasStyling(id1));
QCOMPARE(store.getLinkIdsByGroupValue("weapons", "sword"), QList<int>() << id1);
// Wrap the id counter around so id 1 is recycled by a link
// that provides no styling of its own
store.addLinks(links, hints);
store.addLinks(links, hints);
int recycledId = store.addLinks(links, hints);
QCOMPARE(recycledId, id1);
// The recycled id must not inherit the previous link's styling,
// nor remain findable under the old selection group/value
QVERIFY(!store.hasStyling(recycledId));
QVERIFY(store.getLinkIdsByGroupValue("weapons", "sword").isEmpty());
Refactoring/reimplementation of MXP support (#3625) Refactoring/reimplementation of MXP protocol Extracts MXP support from TBuffer Separates input parsing from protocol processing: input is parsed into MxpTag objects by the MxpNodeBuilder and are passed to be handled by the MxpTagProcessor Class hierarchy of MxpTagHandler for implementing support for each tag: allows for a clear separation of the implementation of each tag and makes it easier for adding support for new tags Defines a clear interface (MxpClient) separating the MXP implementation from other parts of the code Solves some limitations of previous implementation such as supporting element definitions not only for<SEND> tags, interpolating named and positional attributes and interpolating &text; placeholder by tag content Includes support for COLOR tag Handles FONT, U, I, B, VAR and !ENTITY tags, but so far no defined behavior (can be implemented in MxpMudlet) Attributes that hold MXP state are now in the Host class to avoid needless copies when TBuffer is copied around Introduces QtTests for some of the classes Other refactorings intended to simplify TBuffer class, extracting responbilities that aren't directly related to the buffer mgmt Extracted TEncodingTable from TBuffer, this class is responsible for mapping encoding names to tables. It also removes some bloat from TBuffer. TLinkStore to manage links and associated hints to be displayed. TEntityResolver to map character entities, such as &gt; &#32; &#x20; to their associated string values; supports interpolating strings replacing the entity placeholders by their values
2020-05-03 14:09:42 -03:00
}
void cleanupTestCase() {}
Refactoring/reimplementation of MXP support (#3625) Refactoring/reimplementation of MXP protocol Extracts MXP support from TBuffer Separates input parsing from protocol processing: input is parsed into MxpTag objects by the MxpNodeBuilder and are passed to be handled by the MxpTagProcessor Class hierarchy of MxpTagHandler for implementing support for each tag: allows for a clear separation of the implementation of each tag and makes it easier for adding support for new tags Defines a clear interface (MxpClient) separating the MXP implementation from other parts of the code Solves some limitations of previous implementation such as supporting element definitions not only for<SEND> tags, interpolating named and positional attributes and interpolating &text; placeholder by tag content Includes support for COLOR tag Handles FONT, U, I, B, VAR and !ENTITY tags, but so far no defined behavior (can be implemented in MxpMudlet) Attributes that hold MXP state are now in the Host class to avoid needless copies when TBuffer is copied around Introduces QtTests for some of the classes Other refactorings intended to simplify TBuffer class, extracting responbilities that aren't directly related to the buffer mgmt Extracted TEncodingTable from TBuffer, this class is responsible for mapping encoding names to tables. It also removes some bloat from TBuffer. TLinkStore to manage links and associated hints to be displayed. TEntityResolver to map character entities, such as &gt; &#32; &#x20; to their associated string values; supports interpolating strings replacing the entity placeholders by their values
2020-05-03 14:09:42 -03:00
};
#include "TLinkStoreTest.moc"
QTEST_MAIN(TLinkStoreTest)