yaml-cpp

FORK: A YAML parser and emitter in C++
git clone https://git.neptards.moe/neptards/yaml-cpp.git
Log | Files | Refs | README | LICENSE

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)