test: added QueryTree tests checking correct query syntax

This commit is contained in:
Eberhard Graether
2014-08-31 11:36:08 +02:00
parent c84972b96e
commit aee0b7c337
8 changed files with 392 additions and 14 deletions
-5
View File
@@ -40,11 +40,6 @@ bool QueryCommand::isComplete() const
void QueryCommand::print(std::ostream& ostream) const void QueryCommand::print(std::ostream& ostream) const
{ {
ostream << m_name; ostream << m_name;
if (!isComplete())
{
ostream << " INVALID";
}
} }
QueryCommand::CommandType QueryCommand::getType() const QueryCommand::CommandType QueryCommand::getType() const
+11
View File
@@ -2,6 +2,7 @@
QueryNode::QueryNode() QueryNode::QueryNode()
: m_isGroup(false) : m_isGroup(false)
, m_isComplete(true)
{ {
} }
@@ -28,6 +29,11 @@ void QueryNode::print(std::ostream& ostream, int n) const
ostream << ')'; ostream << ')';
} }
if (!m_isComplete || !isComplete())
{
ostream << " INVALID";
}
ostream << '\n'; ostream << '\n';
} }
@@ -40,3 +46,8 @@ void QueryNode::setIsGroup(bool isGroup)
{ {
m_isGroup = isGroup; m_isGroup = isGroup;
} }
void QueryNode::setIsComplete(bool isComplete)
{
m_isComplete = isComplete;
}
+3
View File
@@ -21,8 +21,11 @@ public:
bool isGroup() const; bool isGroup() const;
void setIsGroup(bool isGroup); void setIsGroup(bool isGroup);
void setIsComplete(bool isComplete);
private: private:
bool m_isGroup; bool m_isGroup;
bool m_isComplete;
}; };
#endif // QUERY_NODE_H #endif // QUERY_NODE_H
+1 -1
View File
@@ -86,7 +86,7 @@ bool QueryOperator::isComplete() const
void QueryOperator::print(std::ostream& ostream) const void QueryOperator::print(std::ostream& ostream) const
{ {
ostream << m_type; ostream << getOperator(m_type);
} }
void QueryOperator::print(std::ostream& ostream, int n) const void QueryOperator::print(std::ostream& ostream, int n) const
+20 -6
View File
@@ -45,7 +45,7 @@ void QueryTree::print(std::ostream& ostream) const
if (!m_valid) if (!m_valid)
{ {
ostream << " INVALID"; ostream << "INVALID";
} }
ostream << '\n'; ostream << '\n';
@@ -61,6 +61,12 @@ std::shared_ptr<QueryNode> QueryTree::buildTree(std::deque<std::string>& tokens,
std::shared_ptr<QueryNode> node = getNextNode(tokens); std::shared_ptr<QueryNode> node = getNextNode(tokens);
std::shared_ptr<QueryOperator> operatorNode = std::dynamic_pointer_cast<QueryOperator>(node); std::shared_ptr<QueryOperator> operatorNode = std::dynamic_pointer_cast<QueryOperator>(node);
if (!node)
{
m_valid = false;
return nullptr;
}
if (frontNode) if (frontNode)
{ {
if (node->isComplete()) if (node->isComplete())
@@ -109,7 +115,7 @@ std::shared_ptr<QueryNode> QueryTree::buildTree(std::deque<std::string>& tokens,
} }
} }
if (!node->isComplete()) if (!node || !node->isComplete())
{ {
m_valid = false; m_valid = false;
} }
@@ -122,6 +128,8 @@ std::shared_ptr<QueryNode> QueryTree::buildGroup(std::deque<std::string>& tokens
std::deque<std::string> group; std::deque<std::string> group;
std::string name; std::string name;
char delimiter = QueryOperator::getOperator(closeType); char delimiter = QueryOperator::getOperator(closeType);
bool valid = true;
while (tokens.front() != std::string(1, delimiter) && tokens.size()) while (tokens.front() != std::string(1, delimiter) && tokens.size())
{ {
group.push_back(tokens.front()); group.push_back(tokens.front());
@@ -135,6 +143,7 @@ std::shared_ptr<QueryNode> QueryTree::buildGroup(std::deque<std::string>& tokens
} }
else else
{ {
valid = false;
m_valid = false; m_valid = false;
} }
@@ -143,14 +152,18 @@ std::shared_ptr<QueryNode> QueryTree::buildGroup(std::deque<std::string>& tokens
return nullptr; return nullptr;
} }
std::shared_ptr<QueryNode> groupNode;
if (closeType == QueryOperator::OPERATOR_NAME) if (closeType == QueryOperator::OPERATOR_NAME)
{ {
return std::make_shared<QueryToken>(name); groupNode = std::make_shared<QueryToken>(name);
}
else
{
groupNode = buildTree(group, nullptr);
groupNode->setIsGroup(true);
} }
std::shared_ptr<QueryNode> groupNode = buildTree(group, nullptr); groupNode->setIsComplete(valid);
groupNode->setIsGroup(true);
return groupNode; return groupNode;
} }
@@ -195,6 +208,7 @@ std::shared_ptr<QueryNode> QueryTree::createCommand(std::string name)
if (node->getType() == QueryCommand::COMMAND_INVALID) if (node->getType() == QueryCommand::COMMAND_INVALID)
{ {
m_valid = false; m_valid = false;
return nullptr;
} }
return node; return node;
+5 -2
View File
@@ -100,8 +100,11 @@ ContainerType utility::tokenize(const ContainerType& list, const std::string& de
for (std::string str : list) for (std::string str : list)
{ {
ContainerType c2 = tokenize<ContainerType>(str, delimiter); if (str.size())
c.insert(c.end(), c2.begin(), c2.end()); {
ContainerType c2 = tokenize<ContainerType>(str, delimiter);
c.insert(c.end(), c2.begin(), c2.end());
}
} }
return c; return c;
+1
View File
@@ -11,6 +11,7 @@ add_files(
GraphTestSuite.h GraphTestSuite.h
LogManagerTestSuite.h LogManagerTestSuite.h
MessageQueueTestSuite.h MessageQueueTestSuite.h
QueryTreeTestSuite.h
SettingsTestSuite.h SettingsTestSuite.h
StorageTestSuite.h StorageTestSuite.h
TextAccessTestSuite.h TextAccessTestSuite.h
+351
View File
@@ -0,0 +1,351 @@
#include "cxxtest/TestSuite.h"
#include "data/query/QueryTree.h"
class QueryTreeTestSuite : public CxxTest::TestSuite
{
public:
void test_empty_query()
{
TS_ASSERT_EQUALS(
printedQueryTree(""),
"INVALID\n"
);
}
void test_invalid_query()
{
TS_ASSERT_EQUALS(
printedQueryTree(" -"),
"- INVALID\n"
);
}
void test_command_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("class"),
"class \n"
"class\n"
);
}
void test_invalid_command_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("banana"),
"banana INVALID\n"
);
}
void test_token_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("\"A\""),
"\" A \" \n"
"\"A\"\n"
);
}
void test_invalid_token_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("\"A"),
"\" A INVALID\n"
"\"A\" INVALID\n"
);
TS_ASSERT_EQUALS(
printedQueryTree("\"\""),
"\" \" INVALID\n"
);
TS_ASSERT_EQUALS(
printedQueryTree("A\""),
"A \" INVALID\n"
);
}
void test_operator_not_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("!field"),
"! field \n"
"!\n"
" field\n"
);
TS_ASSERT_EQUALS(
printedQueryTree("!!field"),
"! ! field \n"
"!\n"
" !\n"
" field\n"
);
}
void test_invalid_operator_not_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("!"),
"! INVALID\n"
"! INVALID\n"
);
TS_ASSERT_EQUALS(
printedQueryTree("field!"),
"field ! INVALID\n"
" field\n"
"! INVALID\n"
);
}
void test_operator_sub_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("\"A\".\"B\""),
"\" A \" . \" B \" \n"
" \"A\"\n"
".\n"
" \"B\"\n"
);
}
void test_invalid_operator_sub_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("\"A\"."),
"\" A \" . INVALID\n"
" \"A\"\n"
". INVALID\n"
);
TS_ASSERT_EQUALS(
printedQueryTree("."),
". INVALID\n"
". INVALID\n"
);
TS_ASSERT_EQUALS(
printedQueryTree(".\"A\""),
". \" A \" INVALID\n"
". INVALID\n"
" \"A\"\n"
);
TS_ASSERT_EQUALS(
printedQueryTree("\"A\"..\"B\""),
"\" A \" . . \" B \" INVALID\n"
" \"A\"\n"
".\n"
" . INVALID\n"
" \"B\"\n"
);
}
void test_operator_has_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("\"A\":\"B\""),
"\" A \" : \" B \" \n"
" \"A\"\n"
":\n"
" \"B\"\n"
);
}
void test_operator_and_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("\"A\"&\"B\""),
"\" A \" & \" B \" \n"
" \"A\"\n"
"&\n"
" \"B\"\n"
);
}
void test_operator_or_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("\"A\"|\"B\""),
"\" A \" | \" B \" \n"
" \"A\"\n"
"|\n"
" \"B\"\n"
);
}
void test_operator_group_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("(\"A\")"),
"( \" A \" ) \n"
"(\"A\")\n"
);
TS_ASSERT_EQUALS(
printedQueryTree("(\"A\"|\"B\")"),
"( \" A \" | \" B \" ) \n"
" \"A\"\n"
"(|)\n"
" \"B\"\n"
);
}
void test_invalid_operator_group_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("()"),
"( ) INVALID\n"
);
TS_ASSERT_EQUALS(
printedQueryTree("(\"A\""),
"( \" A \" INVALID\n"
"(\"A\") INVALID\n"
);
TS_ASSERT_EQUALS(
printedQueryTree("\"A\")"),
"\" A \" ) INVALID\n"
);
TS_ASSERT_EQUALS(
printedQueryTree(")("),
") ( INVALID\n"
);
}
void test_implicit_operator_sub_query()
{
TS_ASSERT_EQUALS(
printedQueryTree("\"A\"(\"B\")"),
"\" A \" ( \" B \" ) \n"
" \"A\"\n"
".\n"
" (\"B\")\n"
);
}
void test_operator_precedence_not_before_sub()
{
TS_ASSERT_EQUALS(
printedQueryTree("!method.!const"),
"! method . ! const \n"
" !\n"
" method\n"
".\n"
" !\n"
" const\n"
);
}
void test_operator_precedence_sub_before_has()
{
TS_ASSERT_EQUALS(
printedQueryTree("namespace.class:method"),
"namespace . class : method \n"
" namespace\n"
" .\n"
" class\n"
":\n"
" method\n"
);
}
void test_operator_precedence_has_before_or()
{
TS_ASSERT_EQUALS(
printedQueryTree("class:method|field"),
"class : method | field \n"
" class\n"
" :\n"
" method\n"
"|\n"
" field\n"
);
}
void test_operator_precedence_respects_groups()
{
TS_ASSERT_EQUALS(
printedQueryTree("namespace.(class:method)"),
"namespace . ( class : method ) \n"
" namespace\n"
".\n"
" class\n"
" (:)\n"
" method\n"
);
TS_ASSERT_EQUALS(
printedQueryTree("class:(method|field)"),
"class : ( method | field ) \n"
" class\n"
":\n"
" method\n"
" (|)\n"
" field\n"
);
}
void test_spaces_get_stripped_out_of_query()
{
TS_ASSERT_EQUALS(
printedQueryTree(" \"Field \":(method | field) .const | public "),
"\" Field \" : ( method | field ) . const | public \n"
" \"Field\"\n"
" :\n"
" method\n"
" (|)\n"
" field\n"
" .\n"
" const\n"
"|\n"
" public\n"
);
}
private:
std::string printedQueryTree(std::string query) const
{
QueryTree tree(query);
std::stringstream ss;
tree.print(ss);
return ss.str();
}
};