def test_cross_reference_structs(): nodes = [ model.Struct("A", [ model.StructMember("a", "u8") ]), model.Struct("B", [ model.StructMember("a", "A"), model.StructMember("b", "u8") ]), model.Struct("C", [ model.StructMember("a", "A"), model.StructMember("b", "B"), model.StructMember("c", "NON_EXISTENT") ]), model.Struct("D", [ model.StructMember("a", "A"), model.StructMember("b", "B"), model.StructMember("c", "C") ]) ] model.cross_reference(nodes) definition_names = [[x.definition.name if x.definition else None for x in y.members] for y in nodes] assert definition_names == [ [None], ['A', None], ['A', 'B', None], ['A', 'B', 'C'] ]
def test_evaluate_kinds_arrays(): nodes = [ model.Struct("A", [ model.StructMember("a", "u8"), model.StructMember("b", "u8", optional = True), model.StructMember("c", "u8", size = "5"), model.StructMember("d_len", "u8"), model.StructMember("d", "u8", bound = "d_len", size = "5"), model.StructMember("e_len", "u8"), model.StructMember("e", "u8", bound = "e_len"), model.StructMember("f", "u8", unlimited = True) ]) ] model.cross_reference(nodes) model.evaluate_kinds(nodes) assert [x.kind for x in nodes[0].members] == [ model.Kind.FIXED, model.Kind.FIXED, model.Kind.FIXED, model.Kind.FIXED, model.Kind.FIXED, model.Kind.FIXED, model.Kind.FIXED, model.Kind.FIXED, ]
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_evaluate_kinds_struct_records(): nodes = [ model.Struct("Fix", [ model.StructMember("a", "u8") ]), model.Struct("Dyn", [ model.StructMember("a_len", "u8"), model.StructMember("a", "u8", bound = "a_len") ]), model.Struct("X", [ model.StructMember("a", "Dyn"), model.StructMember("b_len", "u8"), model.StructMember("b", "Fix", bound = "b_len"), model.StructMember("c", "Fix", unlimited = True) ]) ] model.cross_reference(nodes) model.evaluate_kinds(nodes) assert [x.kind for x in nodes] == [ model.Kind.FIXED, model.Kind.DYNAMIC, model.Kind.UNLIMITED, ] assert [x.kind for x in nodes[2].members] == [ model.Kind.DYNAMIC, model.Kind.FIXED, model.Kind.FIXED, model.Kind.FIXED, ]
def test_cross_reference_expression_as_array_size(): nodes = [ model.Struct('X', [ model.StructMember('x', 'u32', size = '2 * 3'), ]) ] model.cross_reference(nodes) assert nodes[0].members[0].numeric_size == 6
def test_cross_reference_numeric_size_of_expression(): nodes = [ model.Constant('A', 12), model.Constant('B', 15), model.Constant('C', 'A*B'), model.Struct('X', [ model.StructMember('x', 'u32', size = 'C'), ]) ] model.cross_reference(nodes) assert nodes[3].members[0].numeric_size == 180
def test_partition_fixed(): nodes = [ model.Struct("Fixed", [ model.StructMember("a", "u8"), model.StructMember("b", "u8"), model.StructMember("c", "u8") ]) ] model.cross_reference(nodes) model.evaluate_kinds(nodes) main, parts = model.partition(nodes[0].members) assert [x.name for x in main] == ["a", "b", "c"] assert [[x.name for x in part] for part in parts] == []
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_cross_reference_typedef(): nodes = [ model.Struct("A", [model.StructMember("a", "u8")]), model.Typedef("B", "A"), model.Struct( "C", [model.StructMember("a", "A"), model.StructMember("b", "B")]), model.Typedef("D", "B") ] model.cross_reference(nodes) assert nodes[1].definition.name == "A" assert nodes[2].members[1].definition.definition.name == "A" assert nodes[3].definition.name == "B" assert nodes[3].definition.definition.name == "A"
def test_partition_many_arrays_mixed(): nodes = [ model.Struct("ManyArraysMixed", [ model.StructMember("num_of_a", "u8"), model.StructMember("num_of_b", "u8"), model.StructMember("a", "u8", bound = "num_of_a"), model.StructMember("b", "u8", bound = "num_of_b") ]), ] model.cross_reference(nodes) model.evaluate_kinds(nodes) main, parts = model.partition(nodes[0].members) assert [x.name for x in main] == ["num_of_a", "num_of_b", "a"] assert [[x.name for x in part] for part in parts] == [["b"]]
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_partition_many_dynamic_structs(): nodes = [ model.Struct("Dynamic", [ model.StructMember("num_of_a", "u8"), model.StructMember("a", "u8", bound = "num_of_a") ]), model.Struct("X", [ model.StructMember("a", "Dynamic"), model.StructMember("b", "Dynamic"), model.StructMember("c", "Dynamic") ]) ] model.cross_reference(nodes) model.evaluate_kinds(nodes) main, parts = model.partition(nodes[1].members) assert [x.name for x in main] == ["a"] assert [[x.name for x in part] for part in parts] == [["b"], ["c"]]
def test_cross_reference_typedef(): nodes = [ model.Struct("A", [ model.StructMember("a", "u8") ]), model.Typedef("B", "A"), model.Struct("C", [ model.StructMember("a", "A"), model.StructMember("b", "B") ]), model.Typedef("D", "B") ] model.cross_reference(nodes) assert nodes[1].definition.name == "A" assert nodes[2].members[1].definition.definition.name == "A" assert nodes[3].definition.name == "B" assert nodes[3].definition.definition.name == "A"
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_numeric_size_of_expression(): nodes = [ model.Constant('A', 12), model.Constant('B', 15), model.Constant('C', 'A*B'), model.Struct('X', [ model.StructMember('x', 'u32', size='C'), ]), ] constants = model.cross_reference(nodes) assert nodes[3].members[0].numeric_size == 180 assert constants == {'A': 12, 'B': 15, 'C': 180}
def test_cross_reference_structs(): nodes = [ model.Struct("A", [ model.StructMember("a", "u8"), ]), model.Struct("B", [ model.StructMember("a", "A"), model.StructMember("b", "u8"), ]), model.Struct("C", [ model.StructMember("a", "A"), model.StructMember("b", "B"), model.StructMember("c", "NON_EXISTENT"), ]), model.Struct("D", [ model.StructMember("a", "A"), model.StructMember("b", "B"), model.StructMember("c", "C"), ]) ] constants = model.cross_reference(nodes) assert [n.name for n in nodes] == ['A', 'B', 'C', 'D'] definition_names = [[ x.definition.name if x.definition else None for x in y.members ] for y in nodes] assert definition_names == [ [None], ['A', None], ['A', 'B', None], ['A', 'B', 'C'], ] assert [tuple(n.dependencies()) for n in nodes] == [ ('u8', ), ('A', 'u8'), ('A', 'B', 'NON_EXISTENT'), ('A', 'B', 'C'), ] assert constants == {}
def test_cross_reference_typedef_warnings(): nodes = [model.Typedef('X', 'Unknown')] warn = WarnFake() model.cross_reference(nodes, warn) assert warn.msgs == ["type 'Unknown' not found"]
def test_cross_reference_no_warning_about_primitive_types(): warn = WarnFake() model.cross_reference([model.Typedef('X', 'u8')], warn) model.cross_reference([model.Typedef('X', 'u16')], warn) model.cross_reference([model.Typedef('X', 'u32')], warn) model.cross_reference([model.Typedef('X', 'u64')], warn) model.cross_reference([model.Typedef('X', 'i8')], warn) model.cross_reference([model.Typedef('X', 'i16')], warn) model.cross_reference([model.Typedef('X', 'i32')], warn) model.cross_reference([model.Typedef('X', 'i64')], warn) model.cross_reference([model.Typedef('X', 'r32')], warn) model.cross_reference([model.Typedef('X', 'r64')], warn) model.cross_reference([model.Typedef('X', 'byte')], warn) assert warn.msgs == []
def test_cross_reference_union_warnings(): nodes = [model.Union('X', [model.UnionMember('x', 'TypeUnknown', '42')])] warn = WarnFake() model.cross_reference(nodes, warn) assert warn.msgs == ["type 'TypeUnknown' not found"]
def test_cross_reference_struct_warnings(): nodes = [model.Struct('X', [model.StructMember('x', 'TypeUnknown', size = '12 + NumUnknown')])] warn = WarnFake() model.cross_reference(nodes, warn) assert warn.msgs == ["type 'TypeUnknown' not found", "numeric constant 'NumUnknown' not found"]
def process_nodes(nodes): model.cross_reference(nodes) model.evaluate_kinds(nodes)
def test_evaluate_kinds_with_typedefs(): nodes = [ model.Struct("Empty", []), model.Struct("Dynamic", [ model.StructMember("a_len", "u8"), model.StructMember("a", "u8", bound = "a_len") ]), model.Struct("Fixed", [ model.StructMember("a", "u8", size = "10") ]), model.Struct("Limited", [ model.StructMember("a_len", "u8"), model.StructMember("a", "u8", bound = "a_len", size = "10") ]), model.Struct("Greedy", [ model.StructMember("a", "byte", unlimited = True) ]), model.Struct("DynamicWrapper", [ model.StructMember("a", "Dynamic") ]), model.Struct("GreedyWrapper", [ model.StructMember("a", "Greedy") ]), model.Struct("GreedyDynamic", [ model.StructMember("a", "Dynamic", unlimited = True) ]), model.Typedef("TU8", "u8"), model.Typedef("TDynamic", "Dynamic"), model.Typedef("TGreedy", "Greedy"), model.Struct("TypedefedU8", [ model.StructMember("a", "TU8") ]), model.Struct("TypedefedDynamic", [ model.StructMember("a", "TDynamic") ]), model.Struct("TypedefedGreedy", [ model.StructMember("a", "TGreedy") ]), model.Typedef("TTDynamic", "TDynamic"), model.Typedef("TTTDynamic", "TTDynamic"), model.Struct("DeeplyTypedefed", [ model.StructMember("a", "TTTDynamic") ]), ] model.cross_reference(nodes) model.evaluate_kinds(nodes) assert [x.kind for x in nodes if isinstance(x, model.Struct)] == [ model.Kind.FIXED, model.Kind.DYNAMIC, model.Kind.FIXED, model.Kind.FIXED, model.Kind.UNLIMITED, model.Kind.DYNAMIC, model.Kind.UNLIMITED, model.Kind.UNLIMITED, model.Kind.FIXED, model.Kind.DYNAMIC, model.Kind.UNLIMITED, model.Kind.DYNAMIC, ]
def process(nodes): model.cross_reference(nodes) model.evaluate_kinds(nodes) model.evaluate_sizes(nodes) return nodes
def process(nodes, warn=None): warnings = [] model.cross_reference(nodes) model.evaluate_kinds(nodes) model.evaluate_sizes(nodes, **(warn and {'warn': warn} or {})) return nodes
def process(nodes): model.cross_reference(nodes) model.evaluate_kinds(nodes) model.evaluate_sizes(nodes) _check_nodes(nodes) return nodes