You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
7.2 KiB

2 months ago
  1. import sys
  2. import yaml
  3. import hashlib
  4. DEFINE = 'YAML_GEN_TESTS'
  5. EVENT_COUNT = 5
  6. def encode_stream(line):
  7. for c in line:
  8. if c == '\n':
  9. yield '\\n'
  10. elif c == '"':
  11. yield '\\"'
  12. elif c == '\t':
  13. yield '\\t'
  14. elif ord(c) < 0x20:
  15. yield '\\x' + hex(ord(c))
  16. else:
  17. yield c
  18. def encode(line):
  19. return ''.join(encode_stream(line))
  20. def doc_start(implicit=False):
  21. if implicit:
  22. return {'emit': '', 'handle': 'OnDocumentStart(_)'}
  23. else:
  24. return {'emit': 'BeginDoc', 'handle': 'OnDocumentStart(_)'}
  25. def doc_end(implicit=False):
  26. if implicit:
  27. return {'emit': '', 'handle': 'OnDocumentEnd()'}
  28. else:
  29. return {'emit': 'EndDoc', 'handle': 'OnDocumentEnd()'}
  30. def scalar(value, tag='', anchor='', anchor_id=0):
  31. emit = []
  32. handle = []
  33. if tag:
  34. emit += ['VerbatimTag("%s")' % encode(tag)]
  35. if anchor:
  36. emit += ['Anchor("%s")' % encode(anchor)]
  37. handle += ['OnAnchor(_, "%s")' % encode(anchor)]
  38. if tag:
  39. out_tag = encode(tag)
  40. else:
  41. if value == encode(value):
  42. out_tag = '?'
  43. else:
  44. out_tag = '!'
  45. emit += ['"%s"' % encode(value)]
  46. handle += ['OnScalar(_, "%s", %s, "%s")' % (out_tag, anchor_id, encode(value))]
  47. return {'emit': emit, 'handle': handle}
  48. def comment(value):
  49. return {'emit': 'Comment("%s")' % value, 'handle': ''}
  50. def seq_start(tag='', anchor='', anchor_id=0, style='_'):
  51. emit = []
  52. handle = []
  53. if tag:
  54. emit += ['VerbatimTag("%s")' % encode(tag)]
  55. if anchor:
  56. emit += ['Anchor("%s")' % encode(anchor)]
  57. handle += ['OnAnchor(_, "%s")' % encode(anchor)]
  58. if tag:
  59. out_tag = encode(tag)
  60. else:
  61. out_tag = '?'
  62. emit += ['BeginSeq']
  63. handle += ['OnSequenceStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)]
  64. return {'emit': emit, 'handle': handle}
  65. def seq_end():
  66. return {'emit': 'EndSeq', 'handle': 'OnSequenceEnd()'}
  67. def map_start(tag='', anchor='', anchor_id=0, style='_'):
  68. emit = []
  69. handle = []
  70. if tag:
  71. emit += ['VerbatimTag("%s")' % encode(tag)]
  72. if anchor:
  73. emit += ['Anchor("%s")' % encode(anchor)]
  74. handle += ['OnAnchor(_, "%s")' % encode(anchor)]
  75. if tag:
  76. out_tag = encode(tag)
  77. else:
  78. out_tag = '?'
  79. emit += ['BeginMap']
  80. handle += ['OnMapStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)]
  81. return {'emit': emit, 'handle': handle}
  82. def map_end():
  83. return {'emit': 'EndMap', 'handle': 'OnMapEnd()'}
  84. def gen_templates():
  85. yield [[doc_start(), doc_start(True)],
  86. [scalar('foo'), scalar('foo\n'), scalar('foo', 'tag'), scalar('foo', '', 'anchor', 1)],
  87. [doc_end(), doc_end(True)]]
  88. yield [[doc_start(), doc_start(True)],
  89. [seq_start()],
  90. [[], [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)]],
  91. [seq_end()],
  92. [doc_end(), doc_end(True)]]
  93. yield [[doc_start(), doc_start(True)],
  94. [map_start()],
  95. [[], [scalar('foo'), scalar('bar')], [scalar('foo', 'tag', 'anchor', 1), scalar('bar', 'tag', 'other', 2)]],
  96. [map_end()],
  97. [doc_end(), doc_end(True)]]
  98. yield [[doc_start(True)],
  99. [map_start()],
  100. [[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
  101. [[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
  102. [map_end()],
  103. [doc_end(True)]]
  104. yield [[doc_start(True)],
  105. [seq_start()],
  106. [[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
  107. [[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
  108. [seq_end()],
  109. [doc_end(True)]]
  110. def expand(template):
  111. if len(template) == 0:
  112. pass
  113. elif len(template) == 1:
  114. for item in template[0]:
  115. if isinstance(item, list):
  116. yield item
  117. else:
  118. yield [item]
  119. else:
  120. for car in expand(template[:1]):
  121. for cdr in expand(template[1:]):
  122. yield car + cdr
  123. def gen_events():
  124. for template in gen_templates():
  125. for events in expand(template):
  126. base = list(events)
  127. for i in range(0, len(base)+1):
  128. cpy = list(base)
  129. cpy.insert(i, comment('comment'))
  130. yield cpy
  131. def gen_tests():
  132. for events in gen_events():
  133. name = 'test' + hashlib.sha1(''.join(yaml.dump(event) for event in events)).hexdigest()[:20]
  134. yield {'name': name, 'events': events}
  135. class Writer(object):
  136. def __init__(self, out):
  137. self.out = out
  138. self.indent = 0
  139. def writeln(self, s):
  140. self.out.write('%s%s\n' % (' ' * self.indent, s))
  141. class Scope(object):
  142. def __init__(self, writer, name, indent):
  143. self.writer = writer
  144. self.name = name
  145. self.indent = indent
  146. def __enter__(self):
  147. self.writer.writeln('%s {' % self.name)
  148. self.writer.indent += self.indent
  149. def __exit__(self, type, value, traceback):
  150. self.writer.indent -= self.indent
  151. self.writer.writeln('}')
  152. def create_emitter_tests(out):
  153. out = Writer(out)
  154. includes = [
  155. 'handler_test.h',
  156. 'yaml-cpp/yaml.h',
  157. 'gmock/gmock.h',
  158. 'gtest/gtest.h',
  159. ]
  160. for include in includes:
  161. out.writeln('#include "%s"' % include)
  162. out.writeln('')
  163. usings = [
  164. '::testing::_',
  165. ]
  166. for using in usings:
  167. out.writeln('using %s;' % using)
  168. out.writeln('')
  169. with Scope(out, 'namespace YAML', 0) as _:
  170. with Scope(out, 'namespace', 0) as _:
  171. out.writeln('')
  172. out.writeln('typedef HandlerTest GenEmitterTest;')
  173. out.writeln('')
  174. tests = list(gen_tests())
  175. for test in tests:
  176. with Scope(out, 'TEST_F(%s, %s)' % ('GenEmitterTest', test['name']), 2) as _:
  177. out.writeln('Emitter out;')
  178. for event in test['events']:
  179. emit = event['emit']
  180. if isinstance(emit, list):
  181. for e in emit:
  182. out.writeln('out << %s;' % e)
  183. elif emit:
  184. out.writeln('out << %s;' % emit)
  185. out.writeln('')
  186. for event in test['events']:
  187. handle = event['handle']
  188. if isinstance(handle, list):
  189. for e in handle:
  190. out.writeln('EXPECT_CALL(handler, %s);' % e)
  191. elif handle:
  192. out.writeln('EXPECT_CALL(handler, %s);' % handle)
  193. out.writeln('Parse(out.c_str());')
  194. out.writeln('')
  195. if __name__ == '__main__':
  196. create_emitter_tests(sys.stdout)