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