def test_parse_array_of_message() -> None: proto = parse(bitproto_filepath("array_of_message.bitproto")) message_a = cast_or_raise(Message, proto.get_member("A")) message_b = cast_or_raise(Message, proto.get_member("B")) alias_c = cast_or_raise(Alias, proto.get_member("C")) assert message_a.nbits() == 1 assert isinstance(alias_c.type, Array) array_of_a = cast_or_raise(Array, alias_c.type) field_b_a = message_b.fields()[0] field_b_c = message_b.fields()[1] field_b_d = message_b.fields()[2] assert array_of_a.cap == 3 assert array_of_a.element_type is message_a assert field_b_d.type is alias_c assert isinstance(field_b_a.type, Array) assert isinstance(field_b_c.type, Array) array_of_field_b_a = cast_or_raise(Array, field_b_a.type) array_of_field_b_c = cast_or_raise(Array, field_b_c.type) assert array_of_field_b_a.element_type is message_a assert array_of_field_b_c.element_type is alias_c assert alias_c.nbits() == 3 * 1 assert message_b.nbits() == 2 * 1 + 3 * 1 * 3 + 3 * 1
def test_parse_nested_import() -> None: proto = parse(bitproto_filepath("nested_import.bitproto")) proto_shared_3 = cast_or_raise(Proto, proto.get_member("shared_3")) proto_shared_4 = cast_or_raise(Proto, proto.get_member("shared_4")) message_a = cast_or_raise(Message, proto.get_member("A")) message_c = cast_or_raise(Message, proto_shared_3.get_member("B", "C")) alias_timestamp = cast_or_raise(Alias, proto.get_member("shared_4", "Timestamp")) assert alias_timestamp is proto_shared_4.get_member("Timestamp") assert alias_timestamp.bound is proto_shared_4 assert len(alias_timestamp.scope_stack) == 2 message_record = cast_or_raise(Message, proto.get_member("shared_3", "Record")) assert message_record is proto_shared_3.get_member("Record") assert message_record.bound is proto_shared_3 assert len(message_record.scope_stack) == 2 enum_color = cast_or_raise(Enum, proto.get_member("shared_3", "Color")) assert enum_color is proto_shared_3.get_member("Color") assert enum_color.bound is proto_shared_3 assert len(enum_color.scope_stack) == 2 assert message_a.bound is proto field_a_color = message_a.fields()[0] field_a_record = message_a.fields()[1] field_a_created_at = message_a.fields()[2] field_a_c = message_a.fields()[3] assert field_a_color.type is enum_color assert field_a_record.type is message_record assert field_a_created_at.type is alias_timestamp assert field_a_c.type is message_c
def test_parse_extensible() -> None: proto = parse(bitproto_filepath("extensible.bitproto")) enum_c = cast_or_raise(Enum, proto.get_member("C")) enum_f = cast_or_raise(Enum, proto.get_member("F")) message_a = cast_or_raise(Message, proto.get_member("A")) message_b = cast_or_raise(Message, proto.get_member("B")) message_d = cast_or_raise(Message, proto.get_member("D")) message_e = cast_or_raise(Message, proto.get_member("E")) message_m = cast_or_raise(Message, proto.get_member("M")) alias_h = cast_or_raise(Alias, proto.get_member("H")) array_h = cast_or_raise(Array, alias_h.type) assert message_a.extensible assert not message_b.extensible assert not message_d.extensible assert not message_e.extensible assert array_h.extensible assert message_m.extensible assert enum_c.nbits() == 3 assert enum_f.nbits() == 3 assert message_a.nbits() == 1 + 16 assert message_b.nbits() == 1 assert message_d.nbits() == enum_c.nbits() assert message_e.nbits() == message_a.nbits() assert message_m.nbits() == message_e.nbits() + 16 assert array_h.nbits() == 3 * 8 + 16
def test_parse_reference_message() -> None: proto = parse(bitproto_filepath("reference_message.bitproto")) message_a = cast_or_raise(Message, proto.get_member("A")) message_b = cast_or_raise(Message, proto.get_member("A", "B")) message_c = cast_or_raise(Message, proto.get_member("A", "B", "C")) message_d = cast_or_raise(Message, proto.get_member("D")) message_e = cast_or_raise(Message, proto.get_member("E")) message_f = cast_or_raise(Message, proto.get_member("E", "F")) field_a_b = message_a.sorted_fields()[0] field_a_c = message_a.sorted_fields()[1] field_b_c = message_b.sorted_fields()[0] field_c_is_ok = message_c.sorted_fields()[0] field_d_a = message_d.sorted_fields()[0] field_d_b = message_d.sorted_fields()[1] field_d_c = message_d.sorted_fields()[2] field_f_c = message_f.sorted_fields()[0] assert field_a_b.type is message_b assert field_a_c.type is message_c assert field_b_c.type is message_c assert isinstance(field_c_is_ok.type, Bool) assert field_d_a.type is message_a assert field_d_b.type is message_b assert field_d_c.type is message_c assert field_f_c.type is message_c assert message_c.nbits() == 1 assert message_b.nbits() == 1 assert message_a.nbits() == 1 + 1 assert message_d.nbits() == (1 + 1) + 1 + 1 assert message_f.nbits() == 1
def test_parse_empty_message() -> None: proto = parse(bitproto_filepath("empty_message.bitproto")) message_empty = cast_or_raise(Message, proto.get_member("Empty")) message_a = cast_or_raise(Message, proto.get_member("A")) assert message_empty.nbits() == 0 assert message_a.nbits() == 0
def test_parse_hex_value() -> None: proto = parse(bitproto_filepath("hex_value.bitproto")) constant_a = cast_or_raise(IntegerConstant, proto.get_member("A")) constant_c = cast_or_raise(IntegerConstant, proto.get_member("C")) enum_b = cast_or_raise(Enum, proto.get_member("B")) assert constant_a.value == 0xF assert constant_c.value == 0x40 assert enum_b.fields()[0].value == 0xF
def test_parse_escaping_char() -> None: proto = parse(bitproto_filepath("escaping_char.bitproto")) constant_a = cast_or_raise(StringConstant, proto.get_member("A")) constant_b = cast_or_raise(StringConstant, proto.get_member("B")) constant_c = cast_or_raise(StringConstant, proto.get_member("C")) constant_d = cast_or_raise(StringConstant, proto.get_member("D")) assert constant_a.value == "simple char \t" assert constant_b.value == 'simple char "V"' assert constant_c.value == "simple char \\" assert constant_d.value == "simple char '''"
def test_parse_2d_array() -> None: proto = parse(bitproto_filepath("_2d_array.bitproto")) alias_slice = cast_or_raise(Alias, proto.get_member("Slice")) alias_matrix = cast_or_raise(Alias, proto.get_member("Matrix")) message_a = cast_or_raise(Message, proto.get_member("A")) assert alias_slice.nbits() == 4 * 8 assert alias_matrix.nbits() == 4 * 4 * 8 assert message_a.nbits() == alias_matrix.nbits() assert message_a.fields()[0].type is alias_matrix
def test_parse_reference_type_undefined() -> None: with pytest.raises(GrammarError): parse(bitproto_filepath("reference_type_undefined_1.bitproto")) with pytest.raises(GrammarError): parse(bitproto_filepath("reference_type_undefined_2.bitproto")) with pytest.raises(GrammarError): parse(bitproto_filepath("reference_type_undefined_3.bitproto"))
def test_parse_option() -> None: proto = parse(bitproto_filepath("option_.bitproto")) option = proto.get_option_or_raise("c.struct_packing_alignment") assert option is not None option_c_alignment = proto.get_option_as_int_or_raise("c.struct_packing_alignment") assert option_c_alignment and option_c_alignment == 1 message_a = cast_or_raise(Message, proto.get_member("A")) option_max_bytes = message_a.get_option_as_int_or_raise("max_bytes") assert option_max_bytes and option_max_bytes == 3
def test_constants() -> None: proto = parse(bitproto_filepath("constants.bitproto")) constant_a = cast_or_raise(IntegerConstant, proto.get_member("A")) constant_b = cast_or_raise(StringConstant, proto.get_member("B")) constant_c = cast_or_raise(BooleanConstant, proto.get_member("C")) constant_d = cast_or_raise(BooleanConstant, proto.get_member("D")) constant_e = cast_or_raise(BooleanConstant, proto.get_member("E")) assert constant_a.value == 1 assert constant_b.value == "B" assert constant_c.value is False assert constant_d.value is True assert constant_e.value is False
def main( filepath: str, lang: str = "", outdir: str = "", disable_linter: bool = False, check: bool = False, enable_optimize: bool = False, filter_messages: Optional[List[str]] = None, ) -> None: # Parse try: traditional_mode = enable_optimize and not check proto = parse(filepath, traditional_mode=traditional_mode) except ParserError as error: fatal(error.colored()) except IOError as error: fatal(str(error)) # Lint if not disable_linter: lint_warnings = lint(proto) if check: if lint_warnings > 0: fatal() return # Render if not lang: fatal(str(NoLanguageArgument())) if not enable_optimize: if filter_messages: fatal("-F not available in non-optimization mode.") try: render( proto, lang, outdir=outdir, optimization_mode=enable_optimize, optimization_mode_filter_messages=filter_messages, ) except RendererError as error: fatal(error.colored()) except IOError as error: fatal(str(error))
def test_parse_nested_enum() -> None: proto = parse(bitproto_filepath("nested_enum.bitproto")) message_a = cast_or_raise(Message, proto.get_member("A")) message_b = cast_or_raise(Message, proto.get_member("A", "B")) enum_c = cast_or_raise(Enum, proto.get_member("A", "B", "C")) message_d = cast_or_raise(Message, proto.get_member("D")) field_a_c = message_a.sorted_fields()[0] field_b_c = message_b.sorted_fields()[0] field_d_c = message_d.sorted_fields()[0] assert field_a_c.type is enum_c assert field_b_c.type is enum_c assert field_d_c.type is enum_c assert len(enum_c.fields()) == 3
def test_parse_reference_constant() -> None: proto = parse(bitproto_filepath("reference_constant.bitproto")) constant_a = cast_or_raise(IntegerConstant, proto.get_member("A")) constant_b = cast_or_raise(IntegerConstant, proto.get_member("B")) message_c = cast_or_raise(Message, proto.get_member("C")) constant_d = cast_or_raise(StringConstant, proto.get_member("D")) constant_e = cast_or_raise(StringConstant, proto.get_member("E")) assert constant_a.value == 2 assert constant_b.value == 2 * 3 assert constant_d.value == "abcde" assert constant_e.value == "abcde" field_c_b = message_c.fields()[0] assert isinstance(field_c_b.type, Array) array_type = cast_or_raise(Array, field_c_b.type) assert array_type.cap == constant_b.value
def test_parse_nested_message() -> None: proto = parse(bitproto_filepath("nested_message.bitproto")) message_a = cast_or_raise(Message, proto.get_member("A")) message_b = cast_or_raise(Message, proto.get_member("A", "B")) message_c = cast_or_raise(Message, proto.get_member("A", "B", "C")) field_a_b = message_a.sorted_fields()[0] field_a_c = message_a.sorted_fields()[1] field_b_c = message_b.sorted_fields()[0] field_c_is_ok = message_c.sorted_fields()[0] assert field_a_b.type is message_b assert field_a_c.type is message_c assert field_b_c.type is message_c assert isinstance(field_c_is_ok.type, Bool) assert message_c.nbits() == 1 assert message_b.nbits() == 1 assert message_a.nbits() == 1 + 1
def test_parse_import() -> None: proto = parse(bitproto_filepath("import_.bitproto")) message_a = cast_or_raise(Message, proto.get_member("A")) constant_pi = cast_or_raise(IntegerConstant, proto.get_member("Pi")) proto_shared = cast_or_raise(Proto, proto.get_member("base")) proto_color = cast_or_raise(Proto, proto.get_member("color")) alias_slice = cast_or_raise(Alias, proto.get_member("base", "Slice")) enum_color = cast_or_raise(Enum, proto.get_member("color", "Color")) message_container = cast_or_raise(Message, proto.get_member("base", "Container")) assert proto_shared.name == "shared" assert constant_pi.value == 314 field_container = message_a.fields()[0] field_slice = message_a.fields()[1] field_color = message_a.fields()[2] assert field_container.type is message_container assert field_slice.type is alias_slice assert field_color.type is enum_color
def test_parse_cycle_import() -> None: with pytest.raises(GrammarError): parse(bitproto_filepath("cycle_import.bitproto"))
def test_lint_message_field_naming_style() -> None: assert lint(parse(bitproto_filepath("message_field_naming_style.bitproto"))) > 0
def test_lint_enum_contains_0() -> None: assert lint(parse(bitproto_filepath("enum_contains_0.bitproto"))) > 0
def test_lint_enum_naming_style() -> None: assert lint(parse(bitproto_filepath("enum_naming_style.bitproto"))) > 0
def test_lint_constant_naming_style() -> None: assert lint(parse(bitproto_filepath("constant_naming_style.bitproto"))) > 0
def test_lint_definition_indent() -> None: assert lint(parse(bitproto_filepath("definition_indent.bitproto"))) > 0
def test_lint_drone() -> None: assert lint(parse(bitproto_filepath("drone.bitproto"))) == 0
def test_parse_duplicate_definition() -> None: with pytest.raises(GrammarError): parse(bitproto_filepath("duplicate_definition_1.bitproto")) with pytest.raises(GrammarError): parse(bitproto_filepath("duplicate_definition_2.bitproto")) with pytest.raises(GrammarError): parse(bitproto_filepath("duplicate_definition_3.bitproto")) with pytest.raises(GrammarError): parse(bitproto_filepath("duplicate_definition_4.bitproto")) with pytest.raises(GrammarError): parse(bitproto_filepath("duplicate_definition_5.bitproto")) with pytest.raises(GrammarError): parse(bitproto_filepath("duplicate_definition_6.bitproto")) with pytest.raises(GrammarError): parse(bitproto_filepath("duplicate_definition_7.bitproto"))
def test_option_wrong_type() -> None: with pytest.raises(GrammarError): parse(bitproto_filepath("option_wrong_type.bitproto"))
def test_parse_dupliate_enum_field_value() -> None: with pytest.raises(GrammarError): parse(bitproto_filepath("duplicate_enum_field_value.bitproto"))
def test_parse_duplicate_message_field_number() -> None: with pytest.raises(GrammarError): parse(bitproto_filepath("duplicate_message_field_number.bitproto"))
def test_parse_message_field_number_constraint() -> None: with pytest.raises(GrammarError): parse(bitproto_filepath("message_field_number_constraint.bitproto"))
def test_parse_reference_not_type() -> None: with pytest.raises(GrammarError): parse(bitproto_filepath("reference_not_type_1.bitproto")) with pytest.raises(GrammarError): parse(bitproto_filepath("reference_not_type_2.bitproto"))
def test_parse_alias_named_definition() -> None: with pytest.raises(GrammarError): parse(bitproto_filepath("alias_named_definition_1.bitproto")) with pytest.raises(GrammarError): parse(bitproto_filepath("alias_named_definition_2.bitproto"))