Tests: tst_ruletextparser.h: Add "lineIpPort" test

This commit is contained in:
Nodir Temirkhodjaev 2024-11-06 15:25:20 +05:00
parent 5b852bb78d
commit 7731f47cc4
3 changed files with 103 additions and 26 deletions

View File

@ -6,6 +6,23 @@
#include <util/conf/ruletextparser.h>
namespace {
bool compareStringList(const StringViewList &l1, const QStringList &l2)
{
if (l1.size() != l2.size())
return false;
for (int i = 0; i < l1.size(); ++i) {
if (l1[i] != l2[i])
return false;
}
return true;
}
}
class RuleTextParserTest : public Test
{
// Test interface
@ -26,3 +43,24 @@ TEST_F(RuleTextParserTest, emptyList)
ASSERT_EQ(p.ruleFilters().size(), 0);
}
TEST_F(RuleTextParserTest, lineIpPort)
{
RuleTextParser p("1.1.1.1:53");
ASSERT_TRUE(p.parse());
ASSERT_EQ(p.ruleFilters().size(), 4);
// Check IP
{
const RuleFilter &rf = p.ruleFilters()[2];
ASSERT_TRUE(compareStringList(rf.values, { "1.1.1.1" }));
}
// Check Port
{
const RuleFilter &rf = p.ruleFilters()[3];
ASSERT_TRUE(compareStringList(rf.values, { "53" }));
}
}

View File

@ -7,7 +7,8 @@
namespace {
const char *const extraNameChars = "_";
const char *const extraValueChars = ".:-/";
const char *const extraValueChars = ".-/";
const char *const extraValueEndChars = ".-/:";
int getCharIndex(const char *chars, const char c)
{
@ -89,7 +90,7 @@ void RuleTextParser::parseLines()
const int nodeIndex = beginList(FORT_RULE_FILTER_TYPE_LIST_OR);
for (;;) {
if (!skipComments(CharAnyBegin))
if (!skipComments(CharLineBegin))
break;
if (!parseLine())
@ -103,20 +104,31 @@ bool RuleTextParser::parseLine()
{
const int nodeIndex = beginList(FORT_RULE_FILTER_TYPE_LIST_AND);
m_ruleFilter.type = FORT_RULE_FILTER_TYPE_ADDRESS; // default type
RuleCharTypes expectedSeparator = CharNone;
m_ruleFilter.type = FORT_RULE_FILTER_TYPE_ADDRESS; // Default type
for (;;) {
if (!parseLineSection())
if (!parseLineSection(expectedSeparator))
break;
if (m_ruleFilter.isLineEnd || m_ruleFilter.isListEnd)
break;
const bool isSectionEnd = m_ruleFilter.isSectionEnd;
if (!checkAddFilter())
return false;
if (!m_ruleFilter.hasFilterName) {
// next default type, if applicable
resetFilter();
// Next default type, if applicable
if (!isSectionEnd && !m_ruleFilter.hasFilterName) {
m_ruleFilter.type = m_ruleFilter.isTypeAddress() ? FORT_RULE_FILTER_TYPE_PORT
: FORT_RULE_FILTER_TYPE_INVALID;
}
expectedSeparator = CharColon | CharNewLine;
}
endList(nodeIndex);
@ -124,10 +136,10 @@ bool RuleTextParser::parseLine()
return true;
}
bool RuleTextParser::parseLineSection()
bool RuleTextParser::parseLineSection(RuleCharTypes expectedSeparator)
{
for (;;) {
if (!nextCharType(CharAnyBegin, CharSpace))
if (!nextCharType(CharLineBegin | expectedSeparator, CharSpace))
return false;
if (!processSection())
@ -157,7 +169,9 @@ bool RuleTextParser::processSectionBlock()
} break;
case CharDigit:
case CharValueBegin: {
parseValue();
const bool expectValueEnd = (m_charType == CharValueBegin);
parseValue(expectValueEnd);
} break;
}
@ -174,10 +188,12 @@ bool RuleTextParser::processSectionChar()
m_ruleFilter.isNot = !m_ruleFilter.isNot;
return true;
} break;
case CharColon:
case CharNewLine: {
case CharColon: {
m_ruleFilter.isSectionEnd = true;
} break;
case CharNewLine: {
m_ruleFilter.isLineEnd = true;
} break;
case CharListEnd: {
m_ruleFilter.isListEnd = true;
checkListEnd();
@ -278,27 +294,36 @@ bool RuleTextParser::parseBracketValue(RuleCharTypes expectedSeparator)
resetParsedCharTypes();
if (!parseChars(CharValueBegin | CharValue,
CharSpaceComment | CharBracketEnd | expectedSeparator, extraValueChars))
CharSpaceComment | CharBracketEnd | expectedSeparator, extraValueEndChars))
return false;
if ((m_parsedCharTypes & CharBracketEnd) != 0)
if (hasParsedCharTypes(CharBracketEnd))
return false;
if ((m_parsedCharTypes & expectedSeparator) == 0) {
if (!hasParsedCharTypes(expectedSeparator)) {
setErrorMessage(tr("Unexpected end of values list"));
return false;
}
return parseValue();
const bool expectValueEnd = hasParsedCharTypes(CharValueBegin);
return parseValue(expectValueEnd);
}
bool RuleTextParser::parseValue()
bool RuleTextParser::parseValue(bool expectValueEnd)
{
const QChar *value = parsedCharPtr();
if (!parseChars(CharLetter | CharValue | CharValueEnd, extraValueChars))
const char *extraChars = expectValueEnd ? extraValueEndChars : extraValueChars;
if (!parseChars(CharLetter | CharValue, extraChars))
return false;
if (expectValueEnd && m_charType != CharValueEnd) {
setErrorMessage(tr("Unexpected end of value"));
return false;
}
const QStringView valueView(value, currentCharPtr() - value);
m_ruleFilter.addValue(valueView);
@ -309,7 +334,7 @@ bool RuleTextParser::parseValue()
bool RuleTextParser::checkAddFilter()
{
if (!m_ruleFilter.hasValues()) {
if (m_ruleFilter.isSectionEnd) {
if (!m_ruleFilter.isSectionEnd) {
setErrorMessage(tr("Unexpected end of line section"));
return false;
}
@ -332,6 +357,7 @@ void RuleTextParser::resetFilter()
m_ruleFilter.isNot = false;
m_ruleFilter.hasFilterName = false;
m_ruleFilter.isListEnd = false;
m_ruleFilter.isLineEnd = false;
m_ruleFilter.isSectionEnd = false;
// m_ruleFilter.type is not reset
@ -342,8 +368,6 @@ void RuleTextParser::resetFilter()
void RuleTextParser::addFilter()
{
m_ruleFilters.append(m_ruleFilter);
resetFilter();
}
int RuleTextParser::beginList(qint8 listType)
@ -354,6 +378,8 @@ int RuleTextParser::beginList(qint8 listType)
addFilter();
resetFilter();
return nodeIndex;
}
@ -392,11 +418,18 @@ bool RuleTextParser::parseChars(
return false;
}
ungetChar();
ungetParsedChar();
return true;
}
void RuleTextParser::ungetParsedChar()
{
if (!isEmpty()) {
ungetChar();
}
}
bool RuleTextParser::nextCharType(
RuleCharTypes expectedCharTypes, RuleCharTypes skipCharTypes, const char *extraChars)
{
@ -406,7 +439,7 @@ bool RuleTextParser::nextCharType(
m_charType = CharNone;
while (m_p < m_end) {
while (!isEmpty()) {
const QChar c = *m_p++;
m_charType = getCharType(m_charType, c, extraChars);

View File

@ -26,10 +26,10 @@ enum RuleCharType : RuleCharTypes {
CharNot = (1 << 13), // !
CharExtra = (1 << 14), // Name | Value
// Complex types
CharAnyBegin = (CharListBegin | CharListEnd | CharBracketBegin | CharLetter | CharDigit
CharLineBegin = (CharListBegin | CharListEnd | CharBracketBegin | CharLetter | CharDigit
| CharValueBegin | CharNot),
CharName = (CharLetter | CharExtra), // a-zA-Z_
CharValue = (CharDigit | CharExtra), // 0-9.:-/
CharValue = (CharDigit | CharExtra), // 0-9.-/:
CharSpaceComment = (CharSpace | CharComment),
};
@ -43,6 +43,7 @@ struct RuleFilter
bool isNot : 1 = false;
bool hasFilterName : 1 = false;
bool isListEnd : 1 = false;
bool isLineEnd : 1 = false;
bool isSectionEnd : 1 = false;
qint8 type = 0;
@ -74,7 +75,7 @@ private:
void parseLines();
bool parseLine();
bool parseLineSection();
bool parseLineSection(RuleCharTypes expectedSeparator);
bool processSection();
bool processSectionBlock();
bool processSectionChar();
@ -86,7 +87,7 @@ private:
void parseBracketValues();
bool parseBracketValue(RuleCharTypes expectedSeparator);
bool parseValue();
bool parseValue(bool expectValueEnd);
bool checkAddFilter();
@ -97,12 +98,15 @@ private:
void endList(int nodeIndex);
void resetParsedCharTypes() { m_parsedCharTypes = CharNone; }
bool hasParsedCharTypes(RuleCharTypes v) { return v != 0 && (m_parsedCharTypes & v) != 0; }
void ungetChar() { --m_p; }
const QChar *currentCharPtr() const { return m_p; }
const QChar *parsedCharPtr() const { return m_p - 1; }
bool isEmpty() const { return m_p >= m_end; }
RuleFilter &listNode(int listIndex) { return m_ruleFilters[listIndex]; }
bool skipComments(RuleCharTypes expectedCharTypes);
@ -115,6 +119,8 @@ private:
bool parseChars(RuleCharTypes expectedCharTypes, RuleCharTypes skipCharTypes,
const char *extraChars = nullptr);
void ungetParsedChar();
bool nextCharType(RuleCharTypes expectedCharTypes, RuleCharTypes skipCharTypes,
const char *extraChars = nullptr);