From 2d815c5d6af52f2b1d30f024cfd7284d4a81d39b Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Sat, 9 Jun 2012 14:26:44 -0500 Subject: [PATCH 1/2] Added extra parser tests for the core; in particular, one that asserts instead of throwing --- test/core/parsertests.cpp | 51 +++++++++++++++++++++++++++++++++++++++ test/parsertests.h | 13 ++++++++++ test/tests.cpp | 4 +++ 3 files changed, 68 insertions(+) create mode 100644 test/core/parsertests.cpp create mode 100644 test/parsertests.h diff --git a/test/core/parsertests.cpp b/test/core/parsertests.cpp new file mode 100644 index 0000000..0f99b6f --- /dev/null +++ b/test/core/parsertests.cpp @@ -0,0 +1,51 @@ +#include "parsertests.h" +#include "handlermacros.h" +#include "yaml-cpp/yaml.h" +#include + +namespace Test +{ + namespace Parser { + TEST BadDocStart() + { + try { + HANDLE("---{header: {id: 1"); + } catch(const YAML::ParserException& e) { + YAML_ASSERT(true); + return true; + } + return " no exception caught"; + } + } + + namespace { + void RunParserTest(TEST (*test)(), const std::string& name, int& passed, int& total) { + TEST ret; + try { + ret = test(); + } catch(const YAML::Exception& e) { + ret.ok = false; + ret.error = std::string(" Exception caught: ") + e.what(); + } + + if(!ret.ok) { + std::cout << "Spec test " << index << " failed: " << name << "\n"; + std::cout << ret.error << "\n"; + } + + if(ret.ok) + passed++; + total++; + } + } + + bool RunParserTests() + { + int passed = 0; + int total = 0; + RunParserTest(&Parser::BadDocStart, "Bad doc start", passed, total); + + std::cout << "Parser tests: " << passed << "/" << total << " passed\n"; + return passed == total; + } +} diff --git a/test/parsertests.h b/test/parsertests.h new file mode 100644 index 0000000..f3de1b8 --- /dev/null +++ b/test/parsertests.h @@ -0,0 +1,13 @@ +#ifndef PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +namespace Test { + bool RunParserTests(); +} + +#endif // PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + diff --git a/test/tests.cpp b/test/tests.cpp index ce8d338..96bc901 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -1,5 +1,6 @@ #include "tests.h" #include "emittertests.h" +#include "parsertests.h" #include "spectests.h" #include "yaml-cpp/yaml.h" #include @@ -17,6 +18,9 @@ namespace Test if(!RunSpecTests()) passed = false; + + if(!RunParserTests()) + passed = false; if(passed) std::cout << "All tests passed!\n"; From 68dd9b5d18f6978a12a7d6b0f2373d676e2493e4 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Sat, 9 Jun 2012 14:39:00 -0500 Subject: [PATCH 2/2] Fixed bug where the parser doesn't find the end of a map or seq flow --- src/scanner.cpp | 7 +++++++ src/scanner.h | 1 + src/singledocparser.cpp | 16 +++++++++++----- test/core/parsertests.cpp | 6 +++--- util/sandbox.cpp | 30 +++++++++++++++++++++++++----- 5 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/scanner.cpp b/src/scanner.cpp index 199ef25..767637e 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -51,6 +51,13 @@ namespace YAML return m_tokens.front(); } + // mark + // . Returns the current mark in the stream + Mark Scanner::mark() const + { + return INPUT.mark(); + } + // EnsureTokensInQueue // . Scan until there's a valid token at the front of the queue, // or we're sure the queue is empty. diff --git a/src/scanner.h b/src/scanner.h index bc8dcbe..fe71124 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -31,6 +31,7 @@ namespace YAML bool empty(); void pop(); Token& peek(); + Mark mark() const; private: struct IndentMarker { diff --git a/src/singledocparser.cpp b/src/singledocparser.cpp index d05fd57..d02e9ac 100644 --- a/src/singledocparser.cpp +++ b/src/singledocparser.cpp @@ -48,7 +48,7 @@ namespace YAML { // an empty node *is* a possibility if(m_scanner.empty()) { - eventHandler.OnNull(Mark::null(), NullAnchor); + eventHandler.OnNull(m_scanner.mark(), NullAnchor); return; } @@ -136,7 +136,7 @@ namespace YAML while(1) { if(m_scanner.empty()) - throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ); + throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ); Token token = m_scanner.peek(); if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END) @@ -169,7 +169,7 @@ namespace YAML while(1) { if(m_scanner.empty()) - throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW); + throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW); // first check for end if(m_scanner.peek().type == Token::FLOW_SEQ_END) { @@ -179,6 +179,9 @@ namespace YAML // then read the node HandleNode(eventHandler); + + if(m_scanner.empty()) + throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW); // now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node) Token& token = m_scanner.peek(); @@ -211,7 +214,7 @@ namespace YAML while(1) { if(m_scanner.empty()) - throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP); + throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP); Token token = m_scanner.peek(); if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END) @@ -250,7 +253,7 @@ namespace YAML while(1) { if(m_scanner.empty()) - throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW); + throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW); Token& token = m_scanner.peek(); const Mark mark = token.mark; @@ -275,6 +278,9 @@ namespace YAML } else { eventHandler.OnNull(mark, NullAnchor); } + + if(m_scanner.empty()) + throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW); // now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node) Token& nextToken = m_scanner.peek(); diff --git a/test/core/parsertests.cpp b/test/core/parsertests.cpp index 0f99b6f..05f7358 100644 --- a/test/core/parsertests.cpp +++ b/test/core/parsertests.cpp @@ -6,12 +6,12 @@ namespace Test { namespace Parser { - TEST BadDocStart() + TEST NoEndOfMapFlow() { try { HANDLE("---{header: {id: 1"); } catch(const YAML::ParserException& e) { - YAML_ASSERT(true); + YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::END_OF_MAP_FLOW)); return true; } return " no exception caught"; @@ -43,7 +43,7 @@ namespace Test { int passed = 0; int total = 0; - RunParserTest(&Parser::BadDocStart, "Bad doc start", passed, total); + RunParserTest(&Parser::NoEndOfMapFlow, "No end of map flow", passed, total); std::cout << "Parser tests: " << passed << "/" << total << " passed\n"; return passed == total; diff --git a/util/sandbox.cpp b/util/sandbox.cpp index 6da95d0..9b48738 100644 --- a/util/sandbox.cpp +++ b/util/sandbox.cpp @@ -1,12 +1,32 @@ #include "yaml-cpp/yaml.h" +#include "yaml-cpp/eventhandler.h" #include +class NullEventHandler: public YAML::EventHandler +{ +public: + typedef YAML::Mark Mark; + typedef YAML::anchor_t anchor_t; + + NullEventHandler() {} + + virtual void OnDocumentStart(const Mark&) {} + virtual void OnDocumentEnd() {} + virtual void OnNull(const Mark&, anchor_t) {} + virtual void OnAlias(const Mark&, anchor_t) {} + virtual void OnScalar(const Mark&, const std::string&, anchor_t, const std::string&) {} + virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t) {} + virtual void OnSequenceEnd() {} + virtual void OnMapStart(const Mark&, const std::string&, anchor_t) {} + virtual void OnMapEnd() {} +}; + int main() { - YAML::Emitter out(std::cout); - out << YAML::BeginSeq; - out << "item 1"; - out << YAML::BeginSeq << "foo 1" << "bar 2" << YAML::EndSeq; - out << YAML::EndSeq; + std::stringstream stream("---{header: {id: 1"); + YAML::Parser parser(stream); +// parser.PrintTokens(std::cout); + NullEventHandler handler; + parser.HandleNextDocument(handler); return 0; }