Converted gen emitter tests to gtest, and removed the old testing framework from core

This commit is contained in:
Jesse Beder 2014-03-23 16:35:26 -05:00
parent ebf14ec83a
commit ad2953f660
10 changed files with 9840 additions and 10669 deletions

View File

@ -2,7 +2,6 @@ import sys
import yaml
import hashlib
NS = 'Emitter'
DEFINE = 'YAML_GEN_TESTS'
EVENT_COUNT = 5
@ -24,22 +23,22 @@ def encode(line):
def doc_start(implicit=False):
if implicit:
return {'emit': '', 'handle': 'DOC_START()'}
return {'emit': '', 'handle': 'OnDocumentStart(_)'}
else:
return {'emit': 'YAML::BeginDoc', 'handle': 'DOC_START()'}
return {'emit': 'BeginDoc', 'handle': 'OnDocumentStart(_)'}
def doc_end(implicit=False):
if implicit:
return {'emit': '', 'handle': 'DOC_END()'}
return {'emit': '', 'handle': 'OnDocumentEnd()'}
else:
return {'emit': 'YAML::EndDoc', 'handle': 'DOC_END()'}
return {'emit': 'EndDoc', 'handle': 'OnDocumentEnd()'}
def scalar(value, tag='', anchor='', anchor_id=0):
emit = []
if tag:
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
emit += ['VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['YAML::Anchor("%s")' % encode(anchor)]
emit += ['Anchor("%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
@ -48,42 +47,42 @@ def scalar(value, tag='', anchor='', anchor_id=0):
else:
out_tag = '!'
emit += ['"%s"' % encode(value)]
return {'emit': emit, 'handle': 'SCALAR("%s", %s, "%s")' % (out_tag, anchor_id, encode(value))}
return {'emit': emit, 'handle': 'OnScalar(_, "%s", %s, "%s")' % (out_tag, anchor_id, encode(value))}
def comment(value):
return {'emit': 'YAML::Comment("%s")' % value, 'handle': ''}
return {'emit': 'Comment("%s")' % value, 'handle': ''}
def seq_start(tag='', anchor='', anchor_id=0):
emit = []
if tag:
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
emit += ['VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['YAML::Anchor("%s")' % encode(anchor)]
emit += ['Anchor("%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
out_tag = '?'
emit += ['YAML::BeginSeq']
return {'emit': emit, 'handle': 'SEQ_START("%s", %s)' % (out_tag, anchor_id)}
emit += ['BeginSeq']
return {'emit': emit, 'handle': 'OnSequenceStart(_, "%s", %s)' % (out_tag, anchor_id)}
def seq_end():
return {'emit': 'YAML::EndSeq', 'handle': 'SEQ_END()'}
return {'emit': 'EndSeq', 'handle': 'OnSequenceEnd()'}
def map_start(tag='', anchor='', anchor_id=0):
emit = []
if tag:
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
emit += ['VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['YAML::Anchor("%s")' % encode(anchor)]
emit += ['Anchor("%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
out_tag = '?'
emit += ['YAML::BeginMap']
return {'emit': emit, 'handle': 'MAP_START("%s", %s)' % (out_tag, anchor_id)}
emit += ['BeginMap']
return {'emit': emit, 'handle': 'OnMapStart(_, "%s", %s)' % (out_tag, anchor_id)}
def map_end():
return {'emit': 'YAML::EndMap', 'handle': 'MAP_END()'}
return {'emit': 'EndMap', 'handle': 'OnMapEnd()'}
def gen_templates():
yield [[doc_start(), doc_start(True)],
@ -141,44 +140,72 @@ def gen_tests():
name = 'test' + hashlib.sha1(''.join(yaml.dump(event) for event in events)).hexdigest()[:20]
yield {'name': name, 'events': events}
class Writer(object):
def __init__(self, out):
self.out = out
self.indent = 0
def writeln(self, s):
self.out.write('%s%s\n' % (' ' * self.indent, s))
class Scope(object):
def __init__(self, writer, name, indent):
self.writer = writer
self.name = name
self.indent = indent
def __enter__(self):
self.writer.writeln('%s {' % self.name)
self.writer.indent += self.indent
def __exit__(self, type, value, traceback):
self.writer.indent -= self.indent
self.writer.writeln('}')
def create_emitter_tests(out):
out.write('#ifdef %s\n' % DEFINE)
out.write('namespace %s {\n' % NS)
out = Writer(out)
includes = [
'handler_test.h',
'yaml-cpp/yaml.h',
'gmock/gmock.h',
'gtest/gtest.h',
]
for include in includes:
out.writeln('#include "%s"' % include)
out.writeln('')
usings = [
'::testing::_',
]
for using in usings:
out.writeln('using %s;' % using)
out.writeln('')
with Scope(out, 'namespace YAML', 0) as _:
with Scope(out, 'namespace', 0) as _:
out.writeln('')
out.writeln('typedef HandlerTest GenEmitterTest;')
out.writeln('')
tests = list(gen_tests())
for test in tests:
out.write('TEST %s(YAML::Emitter& out)\n' % test['name'])
out.write('{\n')
with Scope(out, 'TEST_F(%s, %s)' % ('GenEmitterTest', test['name']), 2) as _:
out.writeln('Emitter out;')
for event in test['events']:
emit = event['emit']
if isinstance(emit, list):
for e in emit:
out.write(' out << %s;\n' % e)
out.writeln('out << %s;' % e)
elif emit:
out.write(' out << %s;\n' % emit)
out.write('\n')
out.write(' HANDLE(out.c_str());\n')
out.writeln('out << %s;' % emit)
out.writeln('')
for event in test['events']:
handle = event['handle']
if handle:
out.write(' EXPECT_%s;\n' % handle)
out.write(' DONE();\n')
out.write('}\n')
out.write('}\n')
out.write('#endif // %s\n\n' % DEFINE)
out.write('void RunGenEmitterTests(int& passed, int& total)\n')
out.write('{\n')
out.write('#ifdef %s\n' % DEFINE)
for test in tests:
out.write(' RunGenEmitterTest(&Emitter::%s, "%s", passed, total);\n' % (test['name'], encode(test['name'])))
out.write('#else // %s\n' % DEFINE)
out.write(' (void)passed; (void)total;\n')
out.write('#endif // %s\n' % DEFINE)
out.write('}\n')
out.writeln('EXPECT_CALL(handler, %s);' % handle)
out.writeln('Parse(out.c_str());')
out.writeln('')
if __name__ == '__main__':
create_emitter_tests(sys.stdout)

View File

@ -1,52 +0,0 @@
#include <iostream>
#include "teststruct.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/yaml.h" // IWYU pragma: keep
namespace Test {
namespace Emitter {
namespace {
void RunGenEmitterTest(TEST (*test)(YAML::Emitter&), const std::string& name,
int& passed, int& total) {
YAML::Emitter out;
TEST ret;
try {
ret = test(out);
}
catch (const YAML::Exception& e) {
ret.ok = false;
ret.error = std::string(" Exception caught: ") + e.what();
}
if (!out.good()) {
ret.ok = false;
ret.error = out.GetLastError();
}
if (!ret.ok) {
std::cout << "Generated emitter test failed: " << name << "\n";
std::cout << "Output:\n";
std::cout << out.c_str() << "<<<\n";
std::cout << ret.error << "\n";
}
if (ret.ok)
passed++;
total++;
}
}
}
#include "genemittertests.h"
bool RunEmitterTests() {
int passed = 0;
int total = 0;
RunGenEmitterTests(passed, total);
std::cout << "Emitter tests: " << passed << "/" << total << " passed\n";
return passed == total;
}
}

View File

@ -1,14 +0,0 @@
#ifndef EMITTERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERTESTS_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 RunEmitterTests();
}
#endif // EMITTERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

File diff suppressed because it is too large Load Diff

View File

@ -1,197 +0,0 @@
#include "teststruct.h"
#pragma once
#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <string>
#include <cassert>
namespace Test {
inline 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;
}
};
inline std::ostream& operator<<(std::ostream& out, const Event& event) {
return event.write(out);
}
inline 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;
}
inline 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() handler.Expect(Event(Event::DocStart, "", 0, ""))
#define EXPECT_DOC_END() handler.Expect(Event(Event::DocEnd, "", 0, ""))
#define EXPECT_NULL(anchor) handler.Expect(Event(Event::Null, "", anchor, ""))
#define EXPECT_ALIAS(anchor) handler.Expect(Event(Event::Alias, "", anchor, ""))
#define EXPECT_SCALAR(tag, anchor, value) \
handler.Expect(Event(Event::Scalar, tag, anchor, value))
#define EXPECT_SEQ_START(tag, anchor) \
handler.Expect(Event(Event::SeqStart, tag, anchor, ""))
#define EXPECT_SEQ_END() handler.Expect(Event(Event::SeqEnd, "", 0, ""))
#define EXPECT_MAP_START(tag, anchor) \
handler.Expect(Event(Event::MapStart, tag, anchor, ""))
#define EXPECT_MAP_END() handler.Expect(Event(Event::MapEnd, "", 0, ""))
#define DONE() return handler.Check()
}

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,6 @@
#include "tests.h"
#include "gtest/gtest.h"
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
Test::RunAll();
return RUN_ALL_TESTS();
}

View File

@ -1,18 +0,0 @@
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include "emittertests.h"
#include "tests.h"
namespace Test {
void RunAll() {
bool passed = true;
if (!RunEmitterTests())
passed = false;
if (passed)
std::cout << "All tests passed!\n";
}
}

View File

@ -1,56 +0,0 @@
#ifndef TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define TESTS_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
#include <string>
namespace Test {
void RunAll();
namespace Parser {
// scalar tests
void SimpleScalar(std::string& inputScalar, std::string& desiredOutput);
void MultiLineScalar(std::string& inputScalar, std::string& desiredOutput);
void LiteralScalar(std::string& inputScalar, std::string& desiredOutput);
void FoldedScalar(std::string& inputScalar, std::string& desiredOutput);
void ChompedFoldedScalar(std::string& inputScalar, std::string& desiredOutput);
void ChompedLiteralScalar(std::string& inputScalar, std::string& desiredOutput);
void FoldedScalarWithIndent(std::string& inputScalar,
std::string& desiredOutput);
void ColonScalar(std::string& inputScalar, std::string& desiredOutput);
void QuotedScalar(std::string& inputScalar, std::string& desiredOutput);
void CommaScalar(std::string& inputScalar, std::string& desiredOutput);
void DashScalar(std::string& inputScalar, std::string& desiredOutput);
void URLScalar(std::string& inputScalar, std::string& desiredOutput);
// misc tests
bool SimpleSeq();
bool SimpleMap();
bool FlowSeq();
bool FlowMap();
bool FlowMapWithOmittedKey();
bool FlowMapWithOmittedValue();
bool FlowMapWithSoloEntry();
bool FlowMapEndingWithSoloEntry();
bool QuotedSimpleKeys();
bool CompressedMapAndSeq();
bool NullBlockSeqEntry();
bool NullBlockMapKey();
bool NullBlockMapValue();
bool SimpleAlias();
bool AliasWithNull();
bool AnchorInSimpleKey();
bool AliasAsSimpleKey();
bool ExplicitDoc();
bool MultipleDocs();
bool ExplicitEndDoc();
bool MultipleDocsWithSomeExplicitIndicators();
}
}
#endif // TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@ -1,20 +0,0 @@
#pragma once
#include <string>
#define YAML_ASSERT(cond) \
do { \
if (!(cond)) \
return " Assert failed: " #cond; \
} while (false)
namespace Test {
struct TEST {
TEST() : ok(false) {}
TEST(bool ok_) : ok(ok_) {}
TEST(const char *error_) : ok(false), error(error_) {}
bool ok;
std::string error;
};
}