import sys import yaml import hashlib DEFINE = 'YAML_GEN_TESTS' EVENT_COUNT = 5 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': 'OnDocumentStart(_)'} else: return {'emit': 'BeginDoc', 'handle': 'OnDocumentStart(_)'} def doc_end(implicit=False): if implicit: return {'emit': '', 'handle': 'OnDocumentEnd()'} else: return {'emit': 'EndDoc', 'handle': 'OnDocumentEnd()'} def scalar(value, tag='', anchor='', anchor_id=0): emit = [] handle = [] if tag: emit += ['VerbatimTag("%s")' % encode(tag)] if anchor: emit += ['Anchor("%s")' % encode(anchor)] handle += ['OnAnchor(_, "%s")' % encode(anchor)] if tag: out_tag = encode(tag) else: if value == encode(value): out_tag = '?' else: out_tag = '!' emit += ['"%s"' % encode(value)] handle += ['OnScalar(_, "%s", %s, "%s")' % (out_tag, anchor_id, encode(value))] return {'emit': emit, 'handle': handle} def comment(value): return {'emit': 'Comment("%s")' % value, 'handle': ''} def seq_start(tag='', anchor='', anchor_id=0, style='_'): emit = [] handle = [] if tag: emit += ['VerbatimTag("%s")' % encode(tag)] if anchor: emit += ['Anchor("%s")' % encode(anchor)] handle += ['OnAnchor(_, "%s")' % encode(anchor)] if tag: out_tag = encode(tag) else: out_tag = '?' emit += ['BeginSeq'] handle += ['OnSequenceStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)] return {'emit': emit, 'handle': handle} def seq_end(): return {'emit': 'EndSeq', 'handle': 'OnSequenceEnd()'} def map_start(tag='', anchor='', anchor_id=0, style='_'): emit = [] handle = [] if tag: emit += ['VerbatimTag("%s")' % encode(tag)] if anchor: emit += ['Anchor("%s")' % encode(anchor)] handle += ['OnAnchor(_, "%s")' % encode(anchor)] if tag: out_tag = encode(tag) else: out_tag = '?' emit += ['BeginMap'] handle += ['OnMapStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)] return {'emit': emit, 'handle': handle} def map_end(): return {'emit': 'EndMap', 'handle': 'OnMapEnd()'} def gen_templates(): yield [[doc_start(), doc_start(True)], [scalar('foo'), scalar('foo\n'), scalar('foo', 'tag'), scalar('foo', '', 'anchor', 1)], [doc_end(), doc_end(True)]] yield [[doc_start(), doc_start(True)], [seq_start()], [[], [scalar('foo')], [scalar('foo', 'tag')], [scalar('foo', '', 'anchor', 1)], [scalar('foo', 'tag', 'anchor', 1)], [scalar('foo'), scalar('bar')], [scalar('foo', 'tag', 'anchor', 1), scalar('bar', 'tag', 'other', 2)]], [seq_end()], [doc_end(), doc_end(True)]] yield [[doc_start(), doc_start(True)], [map_start()], [[], [scalar('foo'), scalar('bar')], [scalar('foo', 'tag', 'anchor', 1), scalar('bar', 'tag', 'other', 2)]], [map_end()], [doc_end(), doc_end(True)]] yield [[doc_start(True)], [map_start()], [[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]], [[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]], [map_end()], [doc_end(True)]] yield [[doc_start(True)], [seq_start()], [[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]], [[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]], [seq_end()], [doc_end(True)]] def expand(template): if len(template) == 0: pass elif len(template) == 1: for item in template[0]: if isinstance(item, list): yield item else: yield [item] else: for car in expand(template[:1]): for cdr in expand(template[1:]): yield car + cdr def gen_events(): for template in gen_templates(): for events in expand(template): base = list(events) for i in range(0, len(base)+1): cpy = list(base) cpy.insert(i, comment('comment')) yield cpy def gen_tests(): for events in gen_events(): 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 = 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: 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.writeln('out << %s;' % e) elif emit: out.writeln('out << %s;' % emit) out.writeln('') for event in test['events']: handle = event['handle'] if isinstance(handle, list): for e in handle: out.writeln('EXPECT_CALL(handler, %s);' % e) elif handle: out.writeln('EXPECT_CALL(handler, %s);' % handle) out.writeln('Parse(out.c_str());') out.writeln('') if __name__ == '__main__': create_emitter_tests(sys.stdout)