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