summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-03-03 14:34:14 +0100
committerAndreas Stöckel <andreas@somweyr.de>2015-03-03 14:34:14 +0100
commitfb8d4cdf01909b61e4e5d0806ec6de178ff0058c (patch)
tree8a38d4d6ab5966c0ce0e8f62c92b24c93b42d031
parent21aa94db203c0b1bcab18bc4858edcdb2afc894d (diff)
Finished stack and adapted all unit tests
-rw-r--r--src/core/parser/stack/Stack.cpp218
-rw-r--r--src/core/parser/stack/Stack.hpp4
-rw-r--r--test/core/parser/stack/StackTest.cpp772
3 files changed, 595 insertions, 399 deletions
diff --git a/src/core/parser/stack/Stack.cpp b/src/core/parser/stack/Stack.cpp
index 89217ea..f341f1d 100644
--- a/src/core/parser/stack/Stack.cpp
+++ b/src/core/parser/stack/Stack.cpp
@@ -30,9 +30,15 @@
#include "TokenRegistry.hpp"
#include "TokenStack.hpp"
+#define STACK_DEBUG_OUTPUT 0
+#if STACK_DEBUG_OUTPUT
+#include <iostream>
+#endif
+
namespace ousia {
namespace parser_stack {
namespace {
+
/* Class HandlerInfo */
/**
@@ -87,12 +93,6 @@ public:
bool inImplicitDefaultField : 1;
/**
- * Set to true if the handler current is in an implicitly started range
- * field.
- */
- bool inImplicitRangeField: 1;
-
- /**
* Set to false if this field is only opened pro-forma and does not accept
* any data. Otherwise set to true.
*/
@@ -109,11 +109,10 @@ public:
HandlerInfo();
/**
- * Constructor of the HandlerInfo class, allows to set all flags manually.
+ * Constructor of the HandlerInfo class, allows to set some flags manually.
*/
- HandlerInfo(bool valid, bool implicit, bool range, bool inField,
- bool inDefaultField, bool inImplicitDefaultField,
- bool inValidField);
+ HandlerInfo(bool implicit, bool inField, bool inDefaultField,
+ bool inImplicitDefaultField);
/**
* Constructor of the HandlerInfo class, taking a shared_ptr to the handler
@@ -178,18 +177,17 @@ HandlerInfo::HandlerInfo(std::shared_ptr<Handler> handler)
{
}
-HandlerInfo::HandlerInfo(bool valid, bool implicit, bool range, bool inField,
- bool inDefaultField, bool inImplicitDefaultField,
- bool inValidField)
+HandlerInfo::HandlerInfo(bool implicit, bool inField, bool inDefaultField,
+ bool inImplicitDefaultField)
: handler(nullptr),
fieldIdx(0),
- valid(valid),
+ valid(true),
implicit(implicit),
- range(range),
+ range(false),
inField(inField),
inDefaultField(inDefaultField),
inImplicitDefaultField(inImplicitDefaultField),
- inValidField(inValidField),
+ inValidField(true),
hadDefaultField(false)
{
}
@@ -235,7 +233,7 @@ void HandlerInfo::fieldEnd()
/**
* Stub instance of HandlerInfo containing no handler information.
*/
-static HandlerInfo EmptyHandlerInfo{true, true, false, true, true, false, true};
+static HandlerInfo EmptyHandlerInfo{true, true, true, true};
/**
* Small helper class makeing sure the reference at some variable is reset once
@@ -386,8 +384,10 @@ private:
/**
* Ends the current handler and removes the corresponding element from the
* stack.
+ *
+ * @return true if a command was ended, false otherwise.
*/
- void endCurrentHandler();
+ bool endCurrentHandler();
/**
* Ends all handlers that currently are not inside a field and already had
@@ -396,8 +396,10 @@ private:
* field yet. This method is called whenever the data(), startAnnotation(),
* startToken(), startCommand(), annotationStart() or annotationEnd() events
* are reached.
+ *
+ * @return true if the current command is in a valid field.
*/
- void prepareCurrentHandler();
+ bool prepareCurrentHandler(bool startImplicitDefaultField = true);
/**
* Returns true if all handlers on the stack are currently valid, or false
@@ -413,23 +415,23 @@ private:
*/
void handleData();
- /**
- * Called whenever there is a token waiting to be processed. If possible
- * tries to end a current handler with this token or to start a new handler
- * with the token.
- *
- * @param token is the token that should be handled.
- */
- void handleToken(const Token &token);
+ /**
+ * Called whenever there is a token waiting to be processed. If possible
+ * tries to end a current handler with this token or to start a new handler
+ * with the token.
+ *
+ * @param token is the token that should be handled.
+ */
+ void handleToken(const Token &token);
/**
* Called by the rangeEnd() and fieldEnd() methods to end the current ranged
* command.
*
- * @param rangeCommand specifies whether this should end the range of a
+ * @param endRange specifies whether this should end the range of a
* command with range.
*/
- void handleFieldEnd(bool rangeCommand);
+ void handleFieldEnd(bool endRange);
public:
StackImpl(ParserCallbacks &parser, ParserContext &ctx,
@@ -579,10 +581,10 @@ std::string StackImpl::currentCommandName() const
TokenSet StackImpl::currentTokens() const
{
// TODO: Implement
- return Tokens{};
+ return TokenSet{};
}
-WhitespaceMode currentWhitespaceMode() const
+WhitespaceMode StackImpl::currentWhitespaceMode() const
{
// TODO: Implement
return WhitespaceMode::COLLAPSE;
@@ -599,7 +601,7 @@ HandlerInfo &StackImpl::lastInfo()
/* Stack helper functions */
-void StackImpl::endCurrentHandler()
+bool StackImpl::endCurrentHandler()
{
if (!stack.empty()) {
// Fetch the handler info for the current top-level element
@@ -623,29 +625,43 @@ void StackImpl::endCurrentHandler()
// Remove the element from the stack
stack.pop_back();
+ return true;
}
+ return false;
}
-void StackImpl::prepareCurrentHandler()
+bool StackImpl::prepareCurrentHandler(bool startImplicitDefaultField)
{
// Repeat until a valid handler is found on the stack
- while (true) {
+ while (!stack.empty()) {
// Fetch the handler for the current top-level element
HandlerInfo &info = currentInfo();
// If the current Handler is in a field, there is nothing to be done,
// abort
if (info.inField) {
- return;
+ return true;
}
// If the current field already had a default field or is not valid,
// end it and repeat
- if (info.hadDefaultField || !info.valid) {
+ if ((info.hadDefaultField || !startImplicitDefaultField) ||
+ !info.valid) {
+ // We cannot end the command if it is marked as "range" command
+ if (info.range) {
+ return false;
+ }
+
+ // End the current handler
endCurrentHandler();
continue;
}
+ // Abort if starting new default fields is not allowed here
+ if (!startImplicitDefaultField) {
+ return false;
+ }
+
// Try to start a new default field, abort if this did not work
bool isDefault = true;
if (!info.handler->fieldStart(isDefault, info.fieldIdx)) {
@@ -655,8 +671,10 @@ void StackImpl::prepareCurrentHandler()
// Mark the field as started and return -- the field should be marked
// is implicit if this is not a field with range
- info.fieldStart(true, !info.range, true, info.range);
+ info.fieldStart(true, !info.range, true);
+ return true;
}
+ return false;
}
bool StackImpl::handlersValid()
@@ -675,7 +693,9 @@ void StackImpl::handleData()
while (true) {
// Prepare the stack -- make sure all overdue handlers are ended and
// we currently are in an open field
- prepareCurrentHandler();
+ if (stack.empty() || !prepareCurrentHandler()) {
+ throw LoggableException("Did not expect any data here");
+ }
// Fetch the current handler information
HandlerInfo &info = currentInfo();
@@ -684,7 +704,7 @@ void StackImpl::handleData()
// call the "data" handler
if (!info.inValidField) {
if (!info.hadDefaultField) {
- logger().error("Did not expect any data here", data);
+ logger().error("Did not expect any data here");
}
return;
}
@@ -722,24 +742,25 @@ void StackImpl::handleData()
// Commit the content of the logger fork. Do not change the valid flag.
loggerFork.commit();
+ return;
}
}
-void StackImpl::handleToken(const Token &token) {
+void StackImpl::handleToken(const Token &token)
+{
// TODO: Implement
// Just eat them for now
}
-void StackImpl::handleFieldEnd(bool rangedCommand)
+void StackImpl::handleFieldEnd(bool endRange)
{
- // Throw away all overdue handlers, start the default field at least once
- // if this has not been done yet (this is important for range commands)
- prepareStack();
+ // Throw away all overdue handlers
+ prepareCurrentHandler(false);
// Close all implicit default fields
while (!stack.empty()) {
HandlerInfo &info = currentInfo();
- if (!info.inImplicitDefaultField) {
+ if (!info.inImplicitDefaultField || info.range) {
break;
}
endCurrentHandler();
@@ -747,16 +768,37 @@ void StackImpl::handleFieldEnd(bool rangedCommand)
// Fetch the information attached to the current handler
HandlerInfo &info = currentInfo();
- if (!info.inField || stack.empty()) {
- logger().error("Got field end, but there is no field here to end");
+ if (stack.empty() || (!info.inField && !endRange) ||
+ (!info.range && endRange)) {
+ if (endRange) {
+ logger().error(
+ "Got end of range, but there is no command here to end");
+ } else {
+ logger().error("Got field end, but there is no field here to end");
+ }
return;
}
// Only continue if the current handler stack is in a valid state, do not
// call the fieldEnd function if something went wrong before
if (handlersValid()) {
- if (info.range && info.inDefaultField)
- info.handler->fieldEnd();
+ // End the current field if it is valid
+ if (info.inValidField) {
+ info.handler->fieldEnd();
+ info.fieldEnd();
+ }
+
+ // End the complete command if this is a range command, start the
+ // default field for once if range command did not have a default field
+ if (info.range && endRange) {
+ if (!info.hadDefaultField) {
+ bool isDefault = true;
+ info.handler->fieldStart(isDefault, true);
+ info.fieldStart(true, true, true);
+ }
+ endCurrentHandler();
+ return;
+ }
}
// This command no longer is in a field
@@ -768,6 +810,9 @@ void StackImpl::handleFieldEnd(bool rangedCommand)
void StackImpl::commandStart(const Variant &name, const Variant::mapType &args,
bool range)
{
+ // Call prepareCurrentHandler once to end all overdue commands
+ prepareCurrentHandler();
+
// Make sure the given identifier is valid (preventing "*" from being
// malicously passed to this function)
if (!Utils::isNamespacedIdentifier(name.asString())) {
@@ -787,8 +832,8 @@ void StackImpl::commandStart(const Variant &name, const Variant::mapType &args,
const State *targetState = findTargetStateOrWildcard(name.asString());
if (targetState == nullptr) {
HandlerInfo &info = currentInfo();
- if (info.inImplicitDefaultField || !info.inField) {
- endCurrentHandler();
+ if ((info.inImplicitDefaultField || !info.inField) &&
+ endCurrentHandler()) {
continue;
} else {
throw buildInvalidCommandException(name.asString(),
@@ -843,9 +888,10 @@ void StackImpl::commandStart(const Variant &name, const Variant::mapType &args,
// not valid -- remove both the new handler and the parent field from
// the stack
if (!info.valid && parentInfo.inImplicitDefaultField) {
- endCurrentHandler();
- endCurrentHandler();
- continue;
+ // Only continue if the parent handler could actually be removed
+ if (endCurrentHandler() && endCurrentHandler()) {
+ continue;
+ }
}
// If we ended up here, starting the command may or may not have
@@ -870,10 +916,7 @@ void StackImpl::annotationEnd(const Variant &className,
// TODO
}
-void StackImpl::rangeEnd()
-{
- handleFieldEnd(true);
-}
+void StackImpl::rangeEnd() { handleFieldEnd(true); }
void StackImpl::data(const TokenizedData &data)
{
@@ -882,7 +925,7 @@ void StackImpl::data(const TokenizedData &data)
// Use the GuardedTemporaryPointer to make sure that the member variable
// dataReader is resetted to nullptr once this scope is left.
- GuardedTemporaryPointer ptr(&reader, &dataReader);
+ GuardedTemporaryPointer<TokenizedDataReader> ptr(&reader, &dataReader);
// Peek a token from the reader, repeat until all tokens have been read
Token token;
@@ -952,10 +995,7 @@ void StackImpl::fieldStart(bool isDefault)
info.fieldStart(defaultField, false, valid);
}
-void StackImpl::fieldEnd()
-{
- handleFieldEnd(false);
-}
+void StackImpl::fieldEnd() { handleFieldEnd(false); }
/* Class StackImpl HandlerCallbacks */
@@ -1017,28 +1057,70 @@ std::string Stack::currentCommandName() const
void Stack::commandStart(const Variant &name, const Variant::mapType &args,
bool range)
{
+#if STACK_DEBUG_OUTPUT
+ std::cout << "STACK: commandStart " << name << " " << args << " " << range
+ << std::endl;
+#endif
impl->commandStart(name, args, range);
}
void Stack::annotationStart(const Variant &className, const Variant &args,
bool range)
{
+#if STACK_DEBUG_OUTPUT
+ std::cout << "STACK: annotationStart " << className << " " << args << " "
+ << range << std::endl;
+#endif
impl->annotationStart(className, args, range);
}
void Stack::annotationEnd(const Variant &className, const Variant &elementName)
{
+#if STACK_DEBUG_OUTPUT
+ std::cout << "STACK: annotationEnd " << className << " " << elementName
+ << std::endl;
+#endif
impl->annotationEnd(className, elementName);
}
-void Stack::rangeEnd() { impl->rangeEnd(); }
+void Stack::rangeEnd()
+{
+#if STACK_DEBUG_OUTPUT
+ std::cout << "STACK: rangeEnd" << std::endl;
+#endif
+ impl->rangeEnd();
+}
-void Stack::fieldStart(bool isDefault) { impl->fieldStart(isDefault); }
+void Stack::fieldStart(bool isDefault)
+{
+#if STACK_DEBUG_OUTPUT
+ std::cout << "STACK: fieldStart " << isDefault << std::endl;
+#endif
+ impl->fieldStart(isDefault);
+}
-void Stack::fieldEnd() { impl->fieldEnd(); }
+void Stack::fieldEnd()
+{
+#if STACK_DEBUG_OUTPUT
+ std::cout << "STACK: fieldEnd" << std::endl;
+#endif
+ impl->fieldEnd();
+}
-void Stack::data(const TokenizedData &data) { impl->data(data); }
+void Stack::data(const TokenizedData &data)
+{
+#if STACK_DEBUG_OUTPUT
+ std::cout << "STACK: data" << std::endl;
+#endif
+ impl->data(data);
+}
-void Stack::data(const std::string &str) { data(TokenizedData(str)); }
+void Stack::data(const std::string &str)
+{
+#if STACK_DEBUG_OUTPUT
+ std::cout << "STACK: data (string) " << str << std::endl;
+#endif
+ data(TokenizedData(str));
+}
}
}
diff --git a/src/core/parser/stack/Stack.hpp b/src/core/parser/stack/Stack.hpp
index 1de7cff..6d42f10 100644
--- a/src/core/parser/stack/Stack.hpp
+++ b/src/core/parser/stack/Stack.hpp
@@ -104,7 +104,7 @@ public:
* @param range if true, the started command has an explicit range.
*/
void commandStart(const Variant &name, const Variant::mapType &args,
- bool range);
+ bool range = false);
/**
* Function that should be called whenever an annotation starts.
@@ -115,7 +115,7 @@ public:
* @param range if true, the annotation fields have an explicit range.
*/
void annotationStart(const Variant &className, const Variant &args,
- bool range);
+ bool range = false);
/**
* Function that should be called whenever an annotation ends.
diff --git a/test/core/parser/stack/StackTest.cpp b/test/core/parser/stack/StackTest.cpp
index 8f6c4df..a831c32 100644
--- a/test/core/parser/stack/StackTest.cpp
+++ b/test/core/parser/stack/StackTest.cpp
@@ -70,6 +70,16 @@ struct Tracker {
bool fieldStartResult;
bool dataResult;
+ Variant::mapType startCommandArgs;
+ Variant::mapType startAnnotationArgs;
+
+ bool fieldStartReturnValue;
+ size_t fieldStartIdx;
+ bool fieldStartIsDefault;
+ bool fieldStartSetIsDefault;
+
+ Variant dataData;
+
Tracker() { reset(); }
void reset()
@@ -89,6 +99,15 @@ struct Tracker {
endTokenResult = Handler::EndTokenResult::ENDED_THIS;
fieldStartResult = true;
dataResult = true;
+
+ startCommandArgs = Variant::mapType{};
+ startAnnotationArgs = Variant::mapType{};
+
+ fieldStartIdx = 0;
+ fieldStartIsDefault = false;
+ fieldStartSetIsDefault = false;
+
+ dataData = Variant{};
}
void expect(int startCommandCount, int endCount, int fieldStartCount,
@@ -115,13 +134,20 @@ private:
public:
bool startCommand(Variant::mapType &args) override
{
+ tracker.startCommandArgs = args;
tracker.startCommandCount++;
+ if (!tracker.startCommandResult) {
+ logger().error(
+ "TestHandler was told not to allow a command start. "
+ "TestHandler always obeys its master.");
+ }
return tracker.startCommandResult;
}
bool startAnnotation(Variant::mapType &args,
AnnotationType annotationType) override
{
+ tracker.startAnnotationArgs = args;
tracker.startAnnotationCount++;
return tracker.startAnnotationResult;
}
@@ -142,6 +168,11 @@ public:
bool fieldStart(bool &isDefault, size_t fieldIdx) override
{
+ tracker.fieldStartIsDefault = isDefault;
+ tracker.fieldStartIdx = fieldIdx;
+ if (tracker.fieldStartSetIsDefault) {
+ isDefault = true;
+ }
tracker.fieldStartCount++;
return tracker.fieldStartResult;
}
@@ -150,6 +181,7 @@ public:
bool data() override
{
+ tracker.dataData = readData();
tracker.dataCount++;
return tracker.dataResult;
}
@@ -199,456 +231,518 @@ TEST(Stack, basicTest)
EXPECT_EQ("", s.currentCommandName());
EXPECT_EQ(&States::None, &s.currentState());
- s.commandStart("document", {}, true);
+ s.commandStart("document", {});
s.fieldStart(true);
s.data("test1");
EXPECT_EQ("document", s.currentCommandName());
EXPECT_EQ(&States::Document, &s.currentState());
- tracker.expect(1, 0, 1, 0, 1); // scc, ec, fsc, fse, dc, sac, stc, etc
+ tracker.expect(1, 0, 1, 0, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.commandStart("body", {}, true);
+ s.commandStart("body", {});
s.fieldStart(true);
s.data("test2");
EXPECT_EQ("body", s.currentCommandName());
EXPECT_EQ(&States::Body, &s.currentState());
- tracker.expect(2, 0, 2, 0, 2); // scc, ec, fsc, fse, dc, sac, stc, etc
+ tracker.expect(2, 0, 2, 0, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.commandStart("inner", {}, true);
+ s.commandStart("inner", {});
s.fieldStart(true);
EXPECT_EQ("inner", s.currentCommandName());
EXPECT_EQ(&States::BodyChildren, &s.currentState());
s.fieldEnd();
- tracker.expect(3, 0, 3, 1, 2); // scc, ec, fsc, fse, dc, sac, stc, etc
+ tracker.expect(3, 0, 3, 1, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
s.fieldEnd();
EXPECT_EQ("body", s.currentCommandName());
EXPECT_EQ(&States::Body, &s.currentState());
- tracker.expect(3, 1, 3, 2, 2); // scc, ec, fsc, fse, dc, sac, stc, etc
+ tracker.expect(3, 1, 3, 2, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.commandStart("body", {}, true);
+ s.commandStart("body", {});
EXPECT_EQ("body", s.currentCommandName());
EXPECT_EQ(&States::Body, &s.currentState());
- tracker.expect(4, 2, 3, 2, 2); // scc, ec, fsc, fse, dc, sac, stc, etc
+ tracker.expect(4, 2, 3, 2, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
s.fieldStart(true);
s.data("test3");
EXPECT_EQ("body", s.currentCommandName());
EXPECT_EQ(&States::Body, &s.currentState());
s.fieldEnd();
- tracker.expect(4, 2, 4, 3, 3); // scc, ec, fsc, fse, dc, sac, stc, etc
+ tracker.expect(4, 2, 4, 3, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
EXPECT_EQ("body", s.currentCommandName());
EXPECT_EQ(&States::Body, &s.currentState());
s.fieldEnd();
- tracker.expect(4, 3, 4, 4, 3); // scc, ec, fsc, fse, dc, sac, stc, etc
+ tracker.expect(4, 3, 4, 4, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
EXPECT_EQ("document", s.currentCommandName());
EXPECT_EQ(&States::Document, &s.currentState());
}
- tracker.expect(4, 4, 4, 4, 3); // scc, ec, fsc, fse, dc, sac, stc, etc
+ tracker.expect(4, 4, 4, 4, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
ASSERT_FALSE(logger.hasError());
}
-/*
+
+TEST(Stack, basicTestRangeCommands)
+{
+ tracker.reset();
+ logger.reset();
+ {
+ Stack s{parser, env.context, States::TestHandlers};
+
+ EXPECT_EQ("", s.currentCommandName());
+ EXPECT_EQ(&States::None, &s.currentState());
+
+ s.commandStart("document", {}, true);
+ EXPECT_EQ("document", s.currentCommandName());
+ EXPECT_EQ(&States::Document, &s.currentState());
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+
+ s.data("test1");
+ tracker.expect(1, 0, 1, 0, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
+
+ s.commandStart("body", {}, true);
+ tracker.expect(2, 0, 1, 0, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
+ s.data("test2");
+ tracker.expect(2, 0, 2, 0, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_EQ("body", s.currentCommandName());
+ EXPECT_EQ(&States::Body, &s.currentState());
+
+ s.commandStart("inner", {}, true);
+ tracker.expect(3, 0, 2, 0, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_EQ("inner", s.currentCommandName());
+ EXPECT_EQ(&States::BodyChildren, &s.currentState());
+ s.rangeEnd();
+ tracker.expect(3, 1, 3, 1, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_EQ("body", s.currentCommandName());
+ EXPECT_EQ(&States::Body, &s.currentState());
+ s.rangeEnd();
+ tracker.expect(3, 2, 3, 2, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
+
+ s.commandStart("body", {}, true);
+ EXPECT_EQ("body", s.currentCommandName());
+ EXPECT_EQ(&States::Body, &s.currentState());
+ tracker.expect(4, 2, 3, 2, 2); // scc, ec, fsc, fse, dc, sac, stc, etc
+ s.fieldStart(true);
+ tracker.expect(4, 2, 4, 2, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
+ s.data("test3");
+ tracker.expect(4, 2, 4, 2, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_EQ("body", s.currentCommandName());
+ EXPECT_EQ(&States::Body, &s.currentState());
+ s.fieldEnd();
+ tracker.expect(4, 2, 4, 3, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_EQ("body", s.currentCommandName());
+ EXPECT_EQ(&States::Body, &s.currentState());
+ s.rangeEnd();
+ tracker.expect(4, 3, 4, 3, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
+
+ EXPECT_EQ("document", s.currentCommandName());
+ EXPECT_EQ(&States::Document, &s.currentState());
+ s.rangeEnd();
+ tracker.expect(4, 4, 4, 4, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(4, 4, 4, 4, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
+}
+
TEST(Stack, errorInvalidCommands)
{
- Stack s{env.context, States::TestHandlers};
- tracker.reset();
- EXPECT_THROW(s.command("body", {}), LoggableException);
- s.command("document", {});
- s.fieldStart(true);
- EXPECT_THROW(s.command("document", {}), LoggableException);
- s.command("empty", {});
- s.fieldStart(true);
- EXPECT_THROW(s.command("body", {}), LoggableException);
- s.command("special", {});
- s.fieldStart(true);
- s.fieldEnd();
- s.fieldEnd();
- s.fieldEnd();
+ Stack s{parser, env.context, States::TestHandlers};
+ tracker.reset();
+ EXPECT_THROW(s.commandStart("body", {}), LoggableException);
+ s.commandStart("document", {});
+ s.fieldStart(true);
+ EXPECT_THROW(s.commandStart("document", {}), LoggableException);
+ s.commandStart("empty", {});
+ s.fieldStart(true);
+ EXPECT_THROW(s.commandStart("body", {}), LoggableException);
+ s.commandStart("special", {});
+ s.fieldStart(true);
+ s.fieldEnd();
+ s.fieldEnd();
+ s.fieldEnd();
- logger.reset();
- s.fieldEnd();
- ASSERT_TRUE(logger.hasError());
+ logger.reset();
+ s.fieldEnd();
+ ASSERT_TRUE(logger.hasError());
- EXPECT_THROW(s.data("test"), LoggableException);
- EXPECT_EQ(&States::None, &s.currentState());
+ EXPECT_THROW(s.data("test"), LoggableException);
+ EXPECT_EQ(&States::None, &s.currentState());
}
TEST(Stack, validation)
{
- Stack s{env.context, States::TestHandlers};
- tracker.reset();
- logger.reset();
+ Stack s{parser, env.context, States::TestHandlers};
+ tracker.reset();
+ logger.reset();
- s.command("arguments", {});
- EXPECT_TRUE(logger.hasError());
- s.fieldStart(true);
- s.fieldEnd();
+ s.commandStart("arguments", {});
+ EXPECT_TRUE(logger.hasError());
+ s.fieldStart(true);
+ s.fieldEnd();
- logger.reset();
- s.command("arguments", {{"a", 5}});
- EXPECT_TRUE(logger.hasError());
- s.fieldStart(true);
- s.fieldEnd();
+ logger.reset();
+ s.commandStart("arguments", {{"a", 5}}, false);
+ EXPECT_TRUE(logger.hasError());
+ s.fieldStart(true);
+ s.fieldEnd();
- logger.reset();
- s.command("arguments", {{"a", 5}, {"b", "test"}});
- EXPECT_FALSE(logger.hasError());
- s.fieldStart(true);
- s.fieldEnd();
+ logger.reset();
+ s.commandStart("arguments", {{"a", 5}, {"b", "test"}}, false);
+ EXPECT_FALSE(logger.hasError());
+ s.fieldStart(true);
+ s.fieldEnd();
}
TEST(Stack, invalidCommandName)
{
- tracker.reset();
- logger.reset();
+ tracker.reset();
+ logger.reset();
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- s.fieldStart(true);
- s.fieldEnd();
- tracker.expect(1, 0, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
-
- s.command("a_", {});
- tracker.expect(2, 1, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- s.fieldStart(true);
- s.fieldEnd();
- tracker.expect(2, 1, 2, 2, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
-
- s.command("a_:b", {});
- tracker.expect(3, 2, 2, 2, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- s.fieldStart(true);
- s.fieldEnd();
- tracker.expect(3, 2, 3, 3, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
-
- ASSERT_THROW(s.command("_a", {}), LoggableException);
- tracker.expect(3, 3, 3, 3, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
-
- ASSERT_THROW(s.command("a:", {}), LoggableException);
- tracker.expect(3, 3, 3, 3, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
-
- ASSERT_THROW(s.command("a:_b", {}), LoggableException);
- tracker.expect(3, 3, 3, 3, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ s.fieldStart(true);
+ s.fieldEnd();
+ tracker.expect(1, 0, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+
+ s.commandStart("a_", {});
+ tracker.expect(2, 1, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ s.fieldStart(true);
+ s.fieldEnd();
+ tracker.expect(2, 1, 2, 2, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+
+ s.commandStart("a_:b", {});
+ tracker.expect(3, 2, 2, 2, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ s.fieldStart(true);
+ s.fieldEnd();
+ tracker.expect(3, 2, 3, 3, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+
+ ASSERT_THROW(s.commandStart("_a", {}), LoggableException);
+ tracker.expect(3, 3, 3, 3, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+
+ ASSERT_THROW(s.commandStart("a:", {}), LoggableException);
+ tracker.expect(3, 3, 3, 3, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+
+ ASSERT_THROW(s.commandStart("a:_b", {}), LoggableException);
+ tracker.expect(3, 3, 3, 3, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
}
TEST(Stack, multipleFields)
{
- tracker.reset();
- logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
+ tracker.reset();
+ logger.reset();
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
- s.command("a", {{"a", false}});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- EXPECT_EQ("a", s.currentCommandName());
- EXPECT_EQ(Variant::mapType({{"a", false}}), tracker.startArgs);
+ s.commandStart("a", {{"a", false}}, false);
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_EQ("a", s.currentCommandName());
+ EXPECT_EQ(Variant::mapType({{"a", false}}), tracker.startCommandArgs);
- s.fieldStart(false);
- tracker.expect(1, 0, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- EXPECT_FALSE(tracker.fieldStartIsDefault);
- EXPECT_EQ(0U, tracker.fieldStartIdx);
+ s.fieldStart(false);
+ tracker.expect(1, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_FALSE(tracker.fieldStartIsDefault);
+ EXPECT_EQ(0U, tracker.fieldStartIdx);
- s.data("test");
- tracker.expect(1, 0, 1, 0, 0, 0, 1); // sc, ec, fsc, fse, asc, aec, dc
- EXPECT_EQ("test", tracker.dataData.text().asString());
+ s.data("test");
+ tracker.expect(1, 0, 1, 0, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_EQ("test", tracker.dataData.asString());
- s.fieldEnd();
- tracker.expect(1, 0, 1, 1, 0, 0, 1); // sc, ec, fsc, fse, asc, aec, dc
+ s.fieldEnd();
+ tracker.expect(1, 0, 1, 1, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.fieldStart(false);
- tracker.expect(1, 0, 2, 1, 0, 0, 1); // sc, ec, fsc, fse, asc, aec, dc
- EXPECT_FALSE(tracker.fieldStartIsDefault);
- EXPECT_EQ(1U, tracker.fieldStartIdx);
+ s.fieldStart(false);
+ tracker.expect(1, 0, 2, 1, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_FALSE(tracker.fieldStartIsDefault);
+ EXPECT_EQ(1U, tracker.fieldStartIdx);
- s.data("test2");
- tracker.expect(1, 0, 2, 1, 0, 0, 2); // sc, ec, fsc, fse, asc, aec, dc
- EXPECT_EQ("test2", tracker.dataData.text().asString());
+ s.data("test2");
+ tracker.expect(1, 0, 2, 1, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_EQ("test2", tracker.dataData.asString());
- s.fieldEnd();
- tracker.expect(1, 0, 2, 2, 0, 0, 2); // sc, ec, fsc, fse, asc, aec, dc
+ s.fieldEnd();
+ tracker.expect(1, 0, 2, 2, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.fieldStart(true);
- tracker.expect(1, 0, 3, 2, 0, 0, 2); // sc, ec, fsc, fse, asc, aec, dc
- EXPECT_TRUE(tracker.fieldStartIsDefault);
- EXPECT_EQ(2U, tracker.fieldStartIdx);
+ s.fieldStart(true);
+ tracker.expect(1, 0, 3, 2, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_TRUE(tracker.fieldStartIsDefault);
+ EXPECT_EQ(2U, tracker.fieldStartIdx);
- s.data("test3");
- tracker.expect(1, 0, 3, 2, 0, 0, 3); // sc, ec, fsc, fse, asc, aec, dc
- EXPECT_EQ("test3", tracker.dataData.text().asString());
+ s.data("test3");
+ tracker.expect(1, 0, 3, 2, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_EQ("test3", tracker.dataData.asString());
- s.fieldEnd();
- tracker.expect(1, 0, 3, 3, 0, 0, 3); // sc, ec, fsc, fse, asc, aec, dc
- }
- tracker.expect(1, 1, 3, 3, 0, 0, 3); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_FALSE(logger.hasError());
+ s.fieldEnd();
+ tracker.expect(1, 0, 3, 3, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(1, 1, 3, 3, 3); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
}
TEST(Stack, implicitDefaultFieldOnNewCommand)
{
- tracker.reset();
- logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
+ tracker.reset();
+ logger.reset();
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.command("b", {});
- tracker.expect(2, 0, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- }
- tracker.expect(2, 2, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_FALSE(logger.hasError());
+ s.commandStart("b", {});
+ tracker.expect(2, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(2, 2, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
}
TEST(Stack, implicitDefaultFieldOnNewCommandWithExplicitDefaultField)
{
- tracker.reset();
- logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
+ tracker.reset();
+ logger.reset();
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("a", s.currentCommandName());
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_EQ("a", s.currentCommandName());
- s.command("b", {});
- tracker.expect(2, 0, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("b", s.currentCommandName());
- s.fieldStart(true);
- s.fieldEnd();
- tracker.expect(2, 0, 2, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("b", s.currentCommandName());
- }
- tracker.expect(2, 2, 2, 2, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_FALSE(logger.hasError());
+ s.commandStart("b", {});
+ tracker.expect(2, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_EQ("b", s.currentCommandName());
+ s.fieldStart(true);
+ s.fieldEnd();
+ tracker.expect(2, 0, 2, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_EQ("b", s.currentCommandName());
+ }
+ tracker.expect(2, 2, 2, 2, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
}
TEST(Stack, noImplicitDefaultFieldOnIncompatibleCommand)
{
- tracker.reset();
- logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
+ tracker.reset();
+ logger.reset();
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("a", s.currentCommandName());
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_EQ("a", s.currentCommandName());
- tracker.fieldStartResult = false;
- s.command("b", {});
- tracker.expect(2, 1, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("b", s.currentCommandName());
- }
- tracker.expect(2, 2, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_FALSE(logger.hasError());
+ tracker.fieldStartResult = false;
+ s.commandStart("b", {});
+ tracker.expect(2, 1, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_EQ("b", s.currentCommandName());
+ }
+ tracker.expect(2, 2, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
}
TEST(Stack, noImplicitDefaultFieldIfDefaultFieldGiven)
{
- tracker.reset();
- logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
+ tracker.reset();
+ logger.reset();
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("a", s.currentCommandName());
- s.fieldStart(true);
- tracker.expect(1, 0, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("a", s.currentCommandName());
- s.fieldEnd();
- tracker.expect(1, 0, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("a", s.currentCommandName());
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_EQ("a", s.currentCommandName());
+ s.fieldStart(true);
+ tracker.expect(1, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_EQ("a", s.currentCommandName());
+ s.fieldEnd();
+ tracker.expect(1, 0, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_EQ("a", s.currentCommandName());
- s.command("b", {});
- tracker.expect(2, 1, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("b", s.currentCommandName());
- }
- tracker.expect(2, 2, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_FALSE(logger.hasError());
+ s.commandStart("b", {});
+ tracker.expect(2, 1, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_EQ("b", s.currentCommandName());
+ }
+ tracker.expect(2, 2, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
}
TEST(Stack, noEndIfStartFails)
{
- tracker.reset();
- logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
+ tracker.reset();
+ logger.reset();
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("a", s.currentCommandName());
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_EQ("a", s.currentCommandName());
- tracker.startResult = false;
- s.command("b", {});
- tracker.expect(3, 1, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_EQ("b", s.currentCommandName());
- }
- tracker.expect(3, 1, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_TRUE(logger.hasError());
+ tracker.startCommandResult = false;
+ s.commandStart("b", {});
+ tracker.expect(3, 1, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ EXPECT_EQ(&States::None, &s.currentState());
+ }
+ tracker.expect(3, 1, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_TRUE(logger.hasError());
}
TEST(Stack, implicitDefaultFieldOnData)
{
- tracker.reset();
- logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
+ tracker.reset();
+ logger.reset();
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.data("test");
- tracker.expect(1, 0, 1, 0, 0, 0, 1); // sc, ec, fsc, fse, asc, aec, dc
- }
- tracker.expect(1, 1, 1, 1, 0, 0, 1); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_FALSE(logger.hasError());
+ s.data("test");
+ tracker.expect(1, 0, 1, 0, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(1, 1, 1, 1, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
}
TEST(Stack, autoFieldEnd)
{
- tracker.reset();
- logger.reset();
+ tracker.reset();
+ logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- }
- tracker.expect(1, 1, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_FALSE(logger.hasError());
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(1, 1, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
}
TEST(Stack, autoImplicitFieldEnd)
{
- tracker.reset();
- logger.reset();
+ tracker.reset();
+ logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
- s.command("b", {});
- s.command("c", {});
- s.command("d", {});
- s.command("e", {});
- s.fieldStart(true);
- s.fieldEnd();
- tracker.expect(5, 0, 5, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- }
- tracker.expect(5, 5, 5, 5, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_FALSE(logger.hasError());
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
+ s.commandStart("b", {});
+ s.commandStart("c", {});
+ s.commandStart("d", {});
+ s.commandStart("e", {});
+ s.fieldStart(true);
+ s.fieldEnd();
+ tracker.expect(5, 0, 5, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(5, 5, 5, 5, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
}
TEST(Stack, invalidDefaultField)
{
- tracker.reset();
- logger.reset();
+ tracker.reset();
+ logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.fieldStartResult = false;
- s.fieldStart(true);
- s.fieldEnd();
- tracker.expect(1, 0, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- }
- tracker.expect(1, 1, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- ASSERT_FALSE(logger.hasError());
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
+ tracker.fieldStartResult = false;
+ s.fieldStart(true);
+ s.fieldEnd();
+ tracker.expect(1, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(1, 1, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
}
TEST(Stack, errorInvalidDefaultFieldData)
{
- tracker.reset();
- logger.reset();
+ tracker.reset();
+ logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.fieldStartResult = false;
- s.fieldStart(true);
- ASSERT_FALSE(logger.hasError());
- s.data("test");
- ASSERT_TRUE(logger.hasError());
- s.fieldEnd();
- tracker.expect(1, 0, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- }
- tracker.expect(1, 1, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
+ tracker.fieldStartResult = false;
+ s.fieldStart(true);
+ ASSERT_FALSE(logger.hasError());
+ s.data("test");
+ ASSERT_TRUE(logger.hasError());
+ s.fieldEnd();
+ tracker.expect(1, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(1, 1, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
}
TEST(Stack, errorInvalidFieldData)
{
- tracker.reset();
- logger.reset();
+ tracker.reset();
+ logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.fieldStartResult = false;
- ASSERT_FALSE(logger.hasError());
- s.fieldStart(false);
- ASSERT_TRUE(logger.hasError());
- s.data("test");
- s.fieldEnd();
- tracker.expect(1, 0, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- }
- tracker.expect(1, 1, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
+ tracker.fieldStartResult = false;
+ ASSERT_FALSE(logger.hasError());
+ s.fieldStart(false);
+ ASSERT_TRUE(logger.hasError());
+ s.data("test");
+ s.fieldEnd();
+ tracker.expect(1, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(1, 1, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
}
TEST(Stack, errorFieldStartNoCommand)
{
- tracker.reset();
- logger.reset();
+ tracker.reset();
+ logger.reset();
- Stack s{env.context, States::AnyHandlers};
- ASSERT_THROW(s.fieldStart(false), LoggableException);
- ASSERT_THROW(s.fieldStart(true), LoggableException);
- tracker.expect(0, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ Stack s{parser, env.context, States::AnyHandlers};
+ ASSERT_THROW(s.fieldStart(false), LoggableException);
+ ASSERT_THROW(s.fieldStart(true), LoggableException);
+ tracker.expect(0, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
}
TEST(Stack, errorMultipleFieldStarts)
{
- tracker.reset();
- logger.reset();
+ tracker.reset();
+ logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.fieldStart(false);
- ASSERT_FALSE(logger.hasError());
- s.fieldStart(false);
- ASSERT_TRUE(logger.hasError());
- tracker.expect(1, 0, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ s.fieldStart(false);
+ ASSERT_FALSE(logger.hasError());
+ s.fieldStart(false);
+ ASSERT_TRUE(logger.hasError());
+ tracker.expect(1, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.fieldEnd();
- tracker.expect(1, 0, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- }
- tracker.expect(1, 1, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ s.fieldEnd();
+ tracker.expect(1, 0, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(1, 1, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
}
TEST(Stack, errorMultipleFieldEnds)
{
- tracker.reset();
- logger.reset();
+ tracker.reset();
+ logger.reset();
- {
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.fieldStart(false);
- s.fieldEnd();
- ASSERT_FALSE(logger.hasError());
- tracker.expect(1, 0, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- s.fieldEnd();
- ASSERT_TRUE(logger.hasError());
- tracker.expect(1, 1, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
- }
- tracker.expect(1, 1, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ s.fieldStart(false);
+ s.fieldEnd();
+ ASSERT_FALSE(logger.hasError());
+ tracker.expect(1, 0, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ s.fieldEnd();
+ ASSERT_TRUE(logger.hasError());
+ tracker.expect(1, 1, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(1, 1, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
}
TEST(Stack, errorOpenField)
@@ -657,15 +751,15 @@ TEST(Stack, errorOpenField)
logger.reset();
{
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
s.fieldStart(false);
ASSERT_FALSE(logger.hasError());
}
ASSERT_TRUE(logger.hasError());
- tracker.expect(1, 1, 1, 1, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(1, 1, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
}
TEST(Stack, fieldEndWhenImplicitDefaultFieldOpen)
@@ -674,15 +768,15 @@ TEST(Stack, fieldEndWhenImplicitDefaultFieldOpen)
logger.reset();
{
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
s.fieldStart(true);
- s.command("b", {});
+ s.commandStart("b", {});
s.data("test");
s.fieldEnd();
- tracker.expect(2, 1, 2, 2, 0, 0, 1); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 1, 2, 2, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
}
- tracker.expect(2, 2, 2, 2, 0, 0, 1); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 2, 2, 2, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
ASSERT_FALSE(logger.hasError());
}
@@ -692,46 +786,66 @@ TEST(Stack, fieldAfterDefaultField)
logger.reset();
{
- Stack s{env.context, States::AnyHandlers};
- s.command("a", {});
- tracker.expect(1, 0, 0, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ Stack s{parser, env.context, States::AnyHandlers};
+ s.commandStart("a", {});
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
s.fieldStart(true);
- tracker.expect(1, 0, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(1, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
- s.command("b", {});
- tracker.expect(2, 0, 1, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ s.commandStart("b", {});
+ tracker.expect(2, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
s.fieldStart(false);
- tracker.expect(2, 0, 2, 0, 0, 0, 0); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 0, 2, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
s.data("f1");
- tracker.expect(2, 0, 2, 0, 0, 0, 1); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 0, 2, 0, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
s.fieldEnd();
- tracker.expect(2, 0, 2, 1, 0, 0, 1); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 0, 2, 1, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
tracker.fieldStartSetIsDefault = true;
s.fieldStart(false);
tracker.fieldStartSetIsDefault = false;
- tracker.expect(2, 0, 3, 1, 0, 0, 1); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 0, 3, 1, 1); // scc, ec, fsc, fec, dc, sac, stc, etc
s.data("f2");
- tracker.expect(2, 0, 3, 1, 0, 0, 2); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 0, 3, 1, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
s.fieldEnd();
- tracker.expect(2, 0, 3, 2, 0, 0, 2); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 0, 3, 2, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
ASSERT_FALSE(logger.hasError());
s.fieldStart(false);
ASSERT_TRUE(logger.hasError());
logger.reset();
- tracker.expect(2, 0, 3, 2, 0, 0, 2); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 0, 3, 2, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
s.data("f3");
- tracker.expect(2, 0, 3, 2, 0, 0, 2); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 0, 3, 2, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
s.fieldEnd();
- tracker.expect(2, 0, 3, 2, 0, 0, 2); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 0, 3, 2, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
s.fieldEnd();
- tracker.expect(2, 1, 3, 3, 0, 0, 2); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 1, 3, 3, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
}
- tracker.expect(2, 2, 3, 3, 0, 0, 2); // sc, ec, fsc, fse, asc, aec, dc
+ tracker.expect(2, 2, 3, 3, 2); // scc, ec, fsc, fec, dc, sac, stc, etc
ASSERT_FALSE(logger.hasError());
-}*/
+}
+
+TEST(Stack, rangeCommandUnranged)
+{
+ tracker.reset();
+ logger.reset();
+
+ {
+ Stack s{parser, env.context, States::AnyHandlers};
+ tracker.expect(0, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ s.commandStart("a", {}, true);
+ tracker.expect(1, 0, 0, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ s.commandStart("b", {});
+ tracker.expect(2, 0, 1, 0, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ s.rangeEnd();
+ tracker.expect(2, 2, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ }
+ tracker.expect(2, 2, 1, 1, 0); // scc, ec, fsc, fec, dc, sac, stc, etc
+ ASSERT_FALSE(logger.hasError());
+}
+
}
}