Updated emitter test script, and moved handler macros to own include file

This commit is contained in:
Jesse Beder 2012-05-22 21:59:12 -05:00
parent 8d529cbcf2
commit 115101d25d
3 changed files with 261 additions and 210 deletions

View File

@ -1,212 +1,10 @@
#include "spectests.h"
#include "handlermacros.h"
#include "specexamples.h"
#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <cassert>
#define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false)
namespace Test {
std::string Quote(const std::string& text) {
YAML::Emitter out;
out << YAML::DoubleQuoted << text;
return out.c_str();
}
struct Event {
enum Type { DocStart, DocEnd, Null, Alias, Scalar, SeqStart, SeqEnd, MapStart, MapEnd };
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
Event(Type type_, const std::string& tag_, anchor_t anchor_, const std::string& scalar_): type(type_), tag(tag_), anchor(anchor_), scalar(scalar_) {}
Type type;
std::string tag;
anchor_t anchor;
std::string scalar;
std::ostream& write(std::ostream& out) const {
switch(type) {
case DocStart:
return out << "DocStart";
case DocEnd:
return out << "DocEnd";
case Null:
return out << "Null(" << anchor << ")";
case Alias:
return out << "Alias(" << anchor << ")";
case Scalar:
return out << "Scalar(" << Quote(tag) << ", " << anchor << ", " << Quote(scalar) << ")";
case SeqStart:
return out << "SeqStart(" << Quote(tag) << ", " << anchor << ")";
case SeqEnd:
return out << "SeqEnd";
case MapStart:
return out << "MapStart(" << Quote(tag) << ", " << anchor << ")";
case MapEnd:
return out << "MapEnd";
}
assert(false);
return out;
}
};
std::ostream& operator << (std::ostream& out, const Event& event) {
return event.write(out);
}
bool operator == (const Event& a, const Event& b) {
return a.type == b.type && a.tag == b.tag && a.anchor == b.anchor && a.scalar == b.scalar;
}
bool operator != (const Event& a, const Event& b) {
return !(a == b);
}
class MockEventHandler: public YAML::EventHandler
{
public:
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
MockEventHandler() {}
virtual void OnDocumentStart(const Mark&) {
m_actualEvents.push_back(Event(Event::DocStart, "", 0, ""));
}
virtual void OnDocumentEnd() {
m_actualEvents.push_back(Event(Event::DocEnd, "", 0, ""));
}
virtual void OnNull(const Mark&, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::Null, "", anchor, ""));
}
virtual void OnAlias(const Mark&, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::Alias, "", anchor, ""));
}
virtual void OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value) {
m_actualEvents.push_back(Event(Event::Scalar, tag, anchor, value));
}
virtual void OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::SeqStart, tag, anchor, ""));
}
virtual void OnSequenceEnd() {
m_actualEvents.push_back(Event(Event::SeqEnd, "", 0, ""));
}
virtual void OnMapStart(const Mark&, const std::string& tag, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::MapStart, tag, anchor, ""));
}
virtual void OnMapEnd() {
m_actualEvents.push_back(Event(Event::MapEnd, "", 0, ""));
}
void Expect(const Event& event) { m_expectedEvents.push_back(event); }
Test::TEST Check() const {
std::size_t N = std::max(m_expectedEvents.size(), m_actualEvents.size());
for(std::size_t i=0;i<N;i++) {
if(i >= m_expectedEvents.size()) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: (no event expected)\n";
out << " ACTUAL : " << m_actualEvents[i] << "\n";
return out.str().c_str();
}
if(i >= m_actualEvents.size()) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: " << m_expectedEvents[i] << "\n";
out << " ACTUAL : (no event recorded)\n";
return out.str().c_str();
}
if(m_expectedEvents[i] != m_actualEvents[i]) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: " << m_expectedEvents[i] << "\n";
out << " ACTUAL : " << m_actualEvents[i] << "\n";
return out.str().c_str();
}
}
return true;
}
std::vector<Event> m_expectedEvents;
std::vector<Event> m_actualEvents;
};
#define HANDLE(ex)\
MockEventHandler handler;\
std::stringstream stream(ex);\
YAML::Parser parser(stream);\
while(parser.HandleNextDocument(handler))\
#define EXPECT_DOC_START()\
do {\
handler.Expect(Event(Event::DocStart, "", 0, ""));\
} while(false)
#define EXPECT_DOC_END()\
do {\
handler.Expect(Event(Event::DocEnd, "", 0, ""));\
} while(false)
#define EXPECT_NULL(anchor)\
do {\
handler.Expect(Event(Event::Null, "", anchor, ""));\
} while(false)
#define EXPECT_ALIAS(anchor)\
do {\
handler.Expect(Event(Event::Alias, "", anchor, ""));\
} while(false)
#define EXPECT_SCALAR(tag, anchor, value)\
do {\
handler.Expect(Event(Event::Scalar, tag, anchor, value));\
} while(false)
#define EXPECT_SEQ_START(tag, anchor)\
do {\
handler.Expect(Event(Event::SeqStart, tag, anchor, ""));\
} while(false)
#define EXPECT_SEQ_END()\
do {\
handler.Expect(Event(Event::SeqEnd, "", 0, ""));\
} while(false)
#define EXPECT_MAP_START(tag, anchor)\
do {\
handler.Expect(Event(Event::MapStart, tag, anchor, ""));\
} while(false)
#define EXPECT_MAP_END()\
do {\
handler.Expect(Event(Event::MapEnd, "", 0, ""));\
} while(false)
#define DONE()\
do {\
return handler.Check();\
} while(false)
namespace Spec {
// 2.1
TEST SeqScalars()

View File

@ -5,13 +5,52 @@ import hashlib
NS = 'Emitter'
EVENT_COUNT = 5
EVENTS = [
{'emit': 'YAML::DocStart', 'handle': 'DOC_START()'},
{'emit': 'YAML::DocEnd', 'handle': 'DOC_END()'},
]
def encode_stream(line):
for c in line:
if c == '\n':
yield '\\n'
elif c == '"':
yield '\\"'
elif c == '\t':
yield '\\t'
elif ord(c) < 0x20:
yield '\\x' + hex(ord(c))
else:
yield c
def encode(line):
return ''.join(encode_stream(line))
def doc_start(implicit=False):
if implicit:
return {'emit': '', 'handle': 'DOC_START()'}
else:
return {'emit': 'YAML::DocStart', 'handle': 'DOC_START()'}
def doc_end(implicit=False):
if implicit:
return {'emit': '', 'handle': 'DOC_END()'}
else:
return {'emit': 'YAML::DocEnd', 'handle': 'DOC_END()'}
def scalar(value, tag='', anchor='', anchor_id=0):
emit = []
if tag:
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['YAML::Anchor("%s")' % encode(anchor)]
emit += ['"%s"' % encode(value)]
return {'emit': emit, 'handle': 'SCALAR("%s", %s, "%s")' % (encode(tag), anchor_id, encode(value))}
def gen_outlines():
yield [doc_start(), scalar('foo\n'), doc_end()]
yield [doc_start(True), scalar('foo\n'), doc_end()]
yield [doc_start(), scalar('foo\n'), doc_end(True)]
yield [doc_start(True), scalar('foo\n'), doc_end(True)]
def gen_events():
pass
for events in gen_outlines():
yield events
def gen_tests():
for events in gen_events():
@ -23,11 +62,14 @@ def create_emitter_tests(out):
out.write('namespace %s {\n' % NS)
for test in gen_tests():
out.write('TEST %s(YAML::Emitter& out)\n' % test['name'])
out.write('inline TEST %s(YAML::Emitter& out)\n' % test['name'])
out.write('{\n')
for event in test['events']:
emit = event['emit']
if emit:
if isinstance(emit, list):
for e in emit:
out.write(' out << %s;\n' % e)
elif emit:
out.write(' out << %s;\n' % emit)
out.write('\n')
out.write(' HANDLE(out.c_str());\n')

211
test/handlermacros.h Normal file
View File

@ -0,0 +1,211 @@
#pragma once
#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <string>
#include <cassert>
#define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false)
namespace Test {
std::string Quote(const std::string& text) {
YAML::Emitter out;
out << YAML::DoubleQuoted << text;
return out.c_str();
}
struct Event {
enum Type { DocStart, DocEnd, Null, Alias, Scalar, SeqStart, SeqEnd, MapStart, MapEnd };
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
Event(Type type_, const std::string& tag_, anchor_t anchor_, const std::string& scalar_): type(type_), tag(tag_), anchor(anchor_), scalar(scalar_) {}
Type type;
std::string tag;
anchor_t anchor;
std::string scalar;
std::ostream& write(std::ostream& out) const {
switch(type) {
case DocStart:
return out << "DocStart";
case DocEnd:
return out << "DocEnd";
case Null:
return out << "Null(" << anchor << ")";
case Alias:
return out << "Alias(" << anchor << ")";
case Scalar:
return out << "Scalar(" << Quote(tag) << ", " << anchor << ", " << Quote(scalar) << ")";
case SeqStart:
return out << "SeqStart(" << Quote(tag) << ", " << anchor << ")";
case SeqEnd:
return out << "SeqEnd";
case MapStart:
return out << "MapStart(" << Quote(tag) << ", " << anchor << ")";
case MapEnd:
return out << "MapEnd";
}
assert(false);
return out;
}
};
std::ostream& operator << (std::ostream& out, const Event& event) {
return event.write(out);
}
bool operator == (const Event& a, const Event& b) {
return a.type == b.type && a.tag == b.tag && a.anchor == b.anchor && a.scalar == b.scalar;
}
bool operator != (const Event& a, const Event& b) {
return !(a == b);
}
class MockEventHandler: public YAML::EventHandler
{
public:
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
MockEventHandler() {}
virtual void OnDocumentStart(const Mark&) {
m_actualEvents.push_back(Event(Event::DocStart, "", 0, ""));
}
virtual void OnDocumentEnd() {
m_actualEvents.push_back(Event(Event::DocEnd, "", 0, ""));
}
virtual void OnNull(const Mark&, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::Null, "", anchor, ""));
}
virtual void OnAlias(const Mark&, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::Alias, "", anchor, ""));
}
virtual void OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value) {
m_actualEvents.push_back(Event(Event::Scalar, tag, anchor, value));
}
virtual void OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::SeqStart, tag, anchor, ""));
}
virtual void OnSequenceEnd() {
m_actualEvents.push_back(Event(Event::SeqEnd, "", 0, ""));
}
virtual void OnMapStart(const Mark&, const std::string& tag, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::MapStart, tag, anchor, ""));
}
virtual void OnMapEnd() {
m_actualEvents.push_back(Event(Event::MapEnd, "", 0, ""));
}
void Expect(const Event& event) { m_expectedEvents.push_back(event); }
Test::TEST Check() const {
std::size_t N = std::max(m_expectedEvents.size(), m_actualEvents.size());
for(std::size_t i=0;i<N;i++) {
if(i >= m_expectedEvents.size()) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: (no event expected)\n";
out << " ACTUAL : " << m_actualEvents[i] << "\n";
return out.str().c_str();
}
if(i >= m_actualEvents.size()) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: " << m_expectedEvents[i] << "\n";
out << " ACTUAL : (no event recorded)\n";
return out.str().c_str();
}
if(m_expectedEvents[i] != m_actualEvents[i]) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: " << m_expectedEvents[i] << "\n";
out << " ACTUAL : " << m_actualEvents[i] << "\n";
return out.str().c_str();
}
}
return true;
}
std::vector<Event> m_expectedEvents;
std::vector<Event> m_actualEvents;
};
#define HANDLE(ex)\
MockEventHandler handler;\
std::stringstream stream(ex);\
YAML::Parser parser(stream);\
while(parser.HandleNextDocument(handler))\
#define EXPECT_DOC_START()\
do {\
handler.Expect(Event(Event::DocStart, "", 0, ""));\
} while(false)
#define EXPECT_DOC_END()\
do {\
handler.Expect(Event(Event::DocEnd, "", 0, ""));\
} while(false)
#define EXPECT_NULL(anchor)\
do {\
handler.Expect(Event(Event::Null, "", anchor, ""));\
} while(false)
#define EXPECT_ALIAS(anchor)\
do {\
handler.Expect(Event(Event::Alias, "", anchor, ""));\
} while(false)
#define EXPECT_SCALAR(tag, anchor, value)\
do {\
handler.Expect(Event(Event::Scalar, tag, anchor, value));\
} while(false)
#define EXPECT_SEQ_START(tag, anchor)\
do {\
handler.Expect(Event(Event::SeqStart, tag, anchor, ""));\
} while(false)
#define EXPECT_SEQ_END()\
do {\
handler.Expect(Event(Event::SeqEnd, "", 0, ""));\
} while(false)
#define EXPECT_MAP_START(tag, anchor)\
do {\
handler.Expect(Event(Event::MapStart, tag, anchor, ""));\
} while(false)
#define EXPECT_MAP_END()\
do {\
handler.Expect(Event(Event::MapEnd, "", 0, ""));\
} while(false)
#define DONE()\
do {\
return handler.Check();\
} while(false)
}