yaml-cpp/test/create-emitter-tests.py
2021-11-30 01:20:18 +00:00

292 lines
7.7 KiB
Python

import hashlib
import sys
import yaml
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)