def test_cross_reference_array_size_from_includes(): nodes = [ model.Include('x', [ model.Include('y', [ model.Constant('NUM_HEX', '0xf'), model.Constant('NUM_DEC', '3'), ]), model.Enum('E', [ model.EnumMember('E1', 'NUM_HEX'), model.EnumMember('E3', 'NUM_DEC'), ]), ]), model.Struct('X', [ model.StructMember('x', 'u32', size='NUM_DEC'), model.StructMember('y', 'u32', size='E1'), model.StructMember('z', 'u32', size='UNKNOWN'), model.StructMember('a', 'u32', size='E3'), ]) ] constants = model.cross_reference(nodes) assert nodes[1].members[0].numeric_size == 3 assert nodes[1].members[1].numeric_size == 15 assert nodes[1].members[2].numeric_size is None assert nodes[1].members[3].numeric_size == 3 assert constants == { 'E1': 15, 'E3': 3, 'NUM_DEC': 3, 'NUM_HEX': 15, }
def test_includes_rendering(): common_include = model.Include("foo", [ model.Constant("symbol_1", 1), model.Constant("number_12", 12), ]) nodes = [ common_include, model.Include("root/ni_knights", [ model.Include("../root/rabbit", [ common_include, model.Constant("pi", "3.14159"), model.Typedef("definition", "things", "r32", "docstring"), ]), model.Constant("symbol_2", 2), ]), model.Include("../root/baz_bar", []), model.Include( "many/numbers", [model.Constant("number_%s" % n, n) for n in reversed(range(20))]), ] ref = """\ from foo import number_12, symbol_1 from ni_knights import definition, pi, symbol_2 from numbers import ( number_0, number_1, number_10, number_11, number_13, number_14, number_15, number_16, number_17, number_18, number_19, number_2, number_3, number_4, number_5, number_6, number_7, number_8, number_9 ) """ # call twice to check if 'duplication avoidance' machinery in _PythonTranslator.translate_include works ok assert serialize(nodes) == ref assert serialize(nodes) == ref
def test_cross_reference_array_size_from_includes(): nodes = [ model.Include('x', [ model.Include('y', [ model.Constant('NUM', '3'), ]), model.Enum('E', [ model.EnumMember('E1', '1'), model.EnumMember('E3', 'NUM') ]), ]), model.Struct('X', [ model.StructMember('x', 'u32', size = 'NUM'), model.StructMember('y', 'u32', size = 'E1'), model.StructMember('z', 'u32', size = 'UNKNOWN'), model.StructMember('a', 'u32', size = 'E3') ]) ] model.cross_reference(nodes) assert nodes[1].members[0].numeric_size == 3 assert nodes[1].members[1].numeric_size == 1 assert nodes[1].members[2].numeric_size == None assert nodes[1].members[3].numeric_size == 3
def test_definitions_includes(): nodes = process([ model.Include("szydlo", []), model.Include("mydlo", []), model.Include("powidlo", []) ]) include_translator = _HppIncludesTranslator() assert include_translator(nodes, "") == """\
def test_definitions_includes(): nodes = [ model.Include("szydlo"), model.Include("mydlo"), model.Include("powidlo") ] assert generate_definitions(nodes) == """\
def test_definitions_includes(): nodes = process([ model.Include("szydlo", []), model.Include("mydlo", []), model.Include("powidlo", []) ]) assert generate_definitions(nodes) == """\
def test_includes_rendering(): nodes = [ model.Include("szydlo"), model.Include("mydlo"), model.Include("powidlo") ] ref = """\ from szydlo import * from mydlo import * from powidlo import * """ assert ref == serialize(nodes)
def test_includes_rendering(): nodes = [ model.Include("szydlo", []), model.Include("root/nowe_mydlo", []), model.Include("../root/nowiejsze_powidlo", []), ] ref = """\ from szydlo import * from nowe_mydlo import * from nowiejsze_powidlo import * """ assert ref == serialize(nodes)
def test_include_path(): assert parse('#include "x.prophy"') == [model.Include('x', [])] assert parse('#include "noext"') == [model.Include('noext', [])] assert parse('#include "102.prophy"') == [model.Include('102', [])] assert parse('#include "x/y/z.prophy"') == [model.Include('z', [])] assert parse('#include "./x.prophy"') == [model.Include('x', [])] assert parse('#include "../x.prophy"') == [model.Include('x', [])] assert parse('#include "x.y.z.prophy"') == [model.Include('x.y.z', [])] assert parse(' # include "x.prophy" ') == [model.Include('x', [])] assert parse('\n#\ninclude\n"x.prophy"\n') == [model.Include('x', [])]
def make_include(elem, process_file, warn): path = elem.get("href") try: nodes = process_file(path) except (CyclicIncludeError, FileNotFoundError) as e: if warn: warn(str(e)) nodes = [] return model.Include(os.path.splitext(path)[0], nodes)
def make_include(xml_elem, process_file, warn): if "include" in xml_elem.tag: path = xml_elem.get("href") try: nodes = process_file(path) except (CyclicIncludeError, FileNotFoundError) as e: if warn: warn(str(e)) nodes = [] return model.Include(os.path.splitext(path)[0], nodes, docstring=get_docstr(xml_elem))
def test_cross_symbols_from_includes(): nodes = [ model.Include('x', [ model.Include('y', [ model.Typedef('ala', 'u32') ]), model.Struct('ola', [ model.StructMember('a', 'ala'), ]) ]), model.Struct('ula', [ model.StructMember('a', 'ola'), model.StructMember('b', 'ala'), ]) ] model.cross_reference(nodes) assert nodes[1].members[0].definition.name == 'ola' assert nodes[1].members[1].definition.name == 'ala' # cross-reference only needs to link definitions of first level of nodes assert nodes[0].nodes[1].members[0].definition == None
def test_cross_reference_quadratic_complexity_include_performance_bug(): """ If type and numeric definitions from includes are processed each time, compilation times can skyrocket... """ FACTOR = 10 nodes = [model.Constant('X', 42), model.Typedef('Y', 'u8')] * FACTOR for i in range(FACTOR): nodes = [model.Include('inc%s' % i, nodes)] * FACTOR nodes.append(model.Struct('Z', [model.StructMember('x', 'u8', size='X')])) """This line will kill your cpu if cross-referencing algorithm is quadratic""" model.cross_reference(nodes) assert nodes[-1].members[0].numeric_size == 42
def test_evaluate_sizes_with_include(): nodes = process([ model.Include('input', [ model.Enum('E', [ model.EnumMember('E1', '1') ]) ]), model.Struct('X', [ model.StructMember('x', 'E'), model.StructMember('y', 'i8'), ]) ]) assert list(map(get_size_alignment_padding, get_members_and_node(nodes[1]))) == [ (4, 4, 0), (1, 1, 3), (8, 4) ]
def test_python_translator_1(): ih = [] th = [] for x in range(20, 200, 60): ih.append( model.Include("test_include_" + str(x), [model.Constant("n_%s" % x, x, "doc")])) th.append( model.Typedef("td_elem_name_" + str(x), "td_elem_val_" + str(x))) th.append( model.Typedef("td_elem_name_" + str(x), "i_td_elem_val_" + str(x))) th.append( model.Typedef("td_elem_name_" + str(x), "u_td_elem_val_" + str(x))) enum = [] for x in range(1, 100, 30): enum.append((model.EnumMember("elem_" + str(x), "val_" + str(x)))) name = "MAC_L2CallConfigResp" members = [model.StructMember('messageResult', 'SMessageResult')] msg_h = model.Struct(name, members) nodes = [] nodes += ih nodes += [ model.Constant("C_A", "5"), model.Constant("C_B", "5"), model.Constant("C_C", "C_B + C_A") ] nodes += th nodes += [model.Enum("test", enum)] nodes += [msg_h] python_translator = _PythonTranslator() output = python_translator(nodes, "") ref = """\ # -*- encoding: utf-8 -*- # This file has been generated by prophyc. import sys import prophy if sys.version_info < (3,): from test_include_20 import n_20 else: from .test_include_20 import n_20 if sys.version_info < (3,): from test_include_80 import n_80 else: from .test_include_80 import n_80 if sys.version_info < (3,): from test_include_140 import n_140 else: from .test_include_140 import n_140 C_A = 5 C_B = 5 C_C = C_B + C_A td_elem_name_20 = td_elem_val_20 td_elem_name_20 = i_td_elem_val_20 td_elem_name_20 = u_td_elem_val_20 td_elem_name_80 = td_elem_val_80 td_elem_name_80 = i_td_elem_val_80 td_elem_name_80 = u_td_elem_val_80 td_elem_name_140 = td_elem_val_140 td_elem_name_140 = i_td_elem_val_140 td_elem_name_140 = u_td_elem_val_140 class test(prophy.with_metaclass(prophy.enum_generator, prophy.enum)): _enumerators = [ ('elem_1', val_1), ('elem_31', val_31), ('elem_61', val_61), ('elem_91', val_91), ] elem_1 = val_1 elem_31 = val_31 elem_61 = val_61 elem_91 = val_91 class MAC_L2CallConfigResp(prophy.with_metaclass(prophy.struct_generator, prophy.struct)): _descriptor = [ ('messageResult', SMessageResult), ] """ assert output == ref
def test_bad_attribute(): a = model.Include("this", []) expected_message = "Use of value property is forbidden for Include. Use 'Include.members' instead." with pytest.raises(model.ModelError, match=expected_message): a.value
def larger_model(lorem_with_breaks): return [ model.Typedef('a', 'i16'), model.Typedef('c', 'a'), model.Include('some_defs', [ model.Struct('IncludedStruct', [ model.StructMember( 'member1', 'r32', docstring='doc for member1'), model.StructMember( 'member2', 'u64', docstring='docstring for member1') ]), model.Typedef('c', 'a'), ]), model.Include('cplx', [ model.Struct('cint16_t', [ model.StructMember('re', 'i16', docstring='real'), model.StructMember('im', 'i16', docstring='imaginary') ]), model.Struct('cint32_t', [ model.StructMember('re', 'i32', docstring='real'), model.StructMember('im', 'i32', docstring='imaginary') ]), ]), model.Union('the_union', [ model.UnionMember('a', 'IncludedStruct', 0), model.UnionMember( 'field_with_a_long_name', 'cint16_t', 1, docstring="Shorter"), model.UnionMember('field_with_a_longer_name', 'cint32_t', 2, docstring="Longer description"), model.UnionMember('other', 'i32', 4090, docstring='This one has larger discriminator'), ], "spec for that union"), model.Enum( 'E1', [ model.EnumMember('E1_A', '0', 'enum1 constant value A'), model.EnumMember('E1_B_has_a_long_name', '1', 'enum1 constant va3lue B'), model.EnumMember('E1_C_desc', '2', lorem_with_breaks[:150]), ], "Enumerator is a model type that is not supposed to be serialized. Its definition represents yet another " "syntax variation for typing a constant. Of course elements of it's type are serializable " "(as int32)"), model.Enum('E2', [ model.EnumMember('E2_A', '0', "Short\nmultiline\ndoc"), ]), model.Constant('CONST_A', '6'), model.Constant('CONST_B', '0'), model.Struct('StructMemberKinds', [ model.StructMember('member_without_docstring', 'i16'), model.StructMember('ext_size', 'i16', docstring='arbitrary sizer for dynamic arrays'), model.StructMember('optional_element', 'cint16_t', optional=True, docstring='optional array'), model.StructMember('fixed_array', 'cint16_t', size=3, docstring='Array with static size.'), model.StructMember('samples', 'cint16_t', bound='ext_size', docstring='dynamic (ext.sized) array'), model.StructMember('limited_array', 'r64', size=4, bound='ext_size', docstring='Has statically ' 'evaluable maximum size.'), model.StructMember('greedy', 'cint16_t', greedy=True, docstring='Represents array of arbitrary ' 'number of elements. Buffer size ' 'must be multiply of element size.'), ], lorem_with_breaks[:400]), ]
def make_include(elem): return model.Include(elem.get("href").split('.')[0])
def test_of_PythonGenerator(): ih = [] th = [] for x in range(20, 200, 60): ih.append(model.Include("test_include_" + str(x))) th.append( model.Typedef("td_elem_name_" + str(x), "td_elem_val_" + str(x))) th.append( model.Typedef("td_elem_name_" + str(x), "i_td_elem_val_" + str(x))) th.append( model.Typedef("td_elem_name_" + str(x), "u_td_elem_val_" + str(x))) enum = [] for x in range(1, 100, 30): enum.append(("elem_" + str(x), "val_" + str(x))) name = "MAC_L2CallConfigResp" members = [model.StructMember('messageResult', 'SMessageResult')] msg_h = model.Struct(name, members) nodes = [] nodes += ih nodes += [ model.Constant("C_A", "5"), model.Constant("C_B", "5"), model.Constant("C_C", "C_B + C_A") ] nodes += th nodes += [model.Enum("test", enum)] nodes += [msg_h] ps = PythonGenerator() output = ps.serialize_string(nodes) ref = """\ import prophy from test_include_20 import * from test_include_80 import * from test_include_140 import * C_A = 5 C_B = 5 C_C = C_B + C_A td_elem_name_20 = td_elem_val_20 td_elem_name_20 = i_td_elem_val_20 td_elem_name_20 = u_td_elem_val_20 td_elem_name_80 = td_elem_val_80 td_elem_name_80 = i_td_elem_val_80 td_elem_name_80 = u_td_elem_val_80 td_elem_name_140 = td_elem_val_140 td_elem_name_140 = i_td_elem_val_140 td_elem_name_140 = u_td_elem_val_140 class test(prophy.enum): __metaclass__ = prophy.enum_generator _enumerators = [('elem_1', val_1), ('elem_31', val_31), ('elem_61', val_61), ('elem_91', val_91)] elem_1 = val_1 elem_31 = val_31 elem_61 = val_61 elem_91 = val_91 class MAC_L2CallConfigResp(prophy.struct): __metaclass__ = prophy.struct_generator _descriptor = [('messageResult', SMessageResult)] """ assert ref == output