Beispiel #1
0
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
Beispiel #2
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
Beispiel #3
0
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
Beispiel #4
0
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 '''"
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
    def format_op_mode_decoder_item(
        self, chain: str, t: Type, si: int, fi: int, shift: int, mask: int, r: int
    ) -> str:
        """Implements format_op_mode_encoder_item for Go.
        Generated Go statement like:

                m.Color |= uint16(byte(s[0]>>3) & 31) << 8

        """
        bshift = " << {0}".format(fi * 8) if fi > 0 else ""
        shift_s = self.format_op_mode_smart_shift(shift)

        byte = f"byte(s[{si}] {shift_s}) & {mask}"

        assign = "|="
        type_s = self.format_type(t)
        data = f"{type_s}({byte})"

        # Handle go's annoying type casting
        if isinstance(t, Bool):
            data = f"byte2bool({byte})"
            assign = "="
        elif isinstance(t, Alias):
            alias_t = cast_or_raise(Alias, t)
            if isinstance(alias_t.type, Bool):
                data = f"{type_s}(byte2bool({byte}))"
                assign = "="

        return f"{chain} {assign} {data}{bshift}"
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
 def _get_definition_name_prefix(self, d: Definition) -> str:
     """Gets the configured name prefix for given definition."""
     if isinstance(d, BoundDefinition):
         d_ = cast_or_raise(BoundDefinition, d)
         bound = d_.bound
         option_name = self.definition_name_prefix_option_name()
         if option_name:
             return bound.get_option_as_string_or_raise(option_name)
     return ""
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
    def format_op_mode_encoder_item(
        self, chain: str, t: Type, si: int, fi: int, shift: int, mask: int, r: int
    ) -> str:
        """Implements format_op_mode_encoder_item for Go.
        Generated Go statement like:

                s[0] |= (byte(m.Color >> 8) >> 5) & 7

        """
        bshift = " >> {0}".format(fi * 8) if fi > 0 else ""
        shift_s = self.format_op_mode_smart_shift(shift)

        # Handle go's annoying type casting
        if isinstance(t, Bool):
            chain = f"bool2byte({chain})"
        elif isinstance(t, Alias):
            alias_t = cast_or_raise(Alias, t)
            if isinstance(alias_t.type, Bool):
                chain = f"bool2byte(bool({chain}))"

        return f"s[{si}] |= (byte({chain}{bshift}) {shift_s}) & {mask}"
Beispiel #16
0
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
Beispiel #17
0
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
Beispiel #18
0
 def block(self) -> Block[F]:
     array_type = cast_or_raise(Array, self.d.type)
     return BlockArrayJsonFormatter(array_type, self.d)
Beispiel #19
0
 def block(self) -> Block[F]:
     array_type = cast_or_raise(Array, self.d.type)
     return BlockArrayProcessor(array_type, self.d)
Beispiel #20
0
def test_parse_drone() -> None:
    filepath = bitproto_filepath("drone.bitproto")
    proto = parse(filepath)

    # Test Proto
    assert proto.name == "drone"
    assert proto.is_frozen()
    assert os.path.samefile(proto.filepath, filepath)
    assert proto._bound is None

    # Test scope.get_member()
    message_drone = proto.get_member("Drone")
    assert message_drone is not None
    assert isinstance(message_drone, Message)
    assert message_drone.name == "Drone"
    assert message_drone.bound is proto

    message_drone = cast_or_raise(Message, message_drone)

    # Test message.nfields
    assert message_drone.nfields() == 7

    # Test message.sorted_fields()
    assert tuple(f.number for f in message_drone.sorted_fields()) == tuple(range(1, 8))

    # Test message.number_to_field()
    assert 1 in message_drone.number_to_field()
    assert len(message_drone.number_to_field()) == 7

    # Test message.number_to_field_sorted()
    assert 1 in message_drone.number_to_field()
    assert len(message_drone.number_to_field()) == 7
    assert tuple(message_drone.number_to_field_sorted().keys()) == tuple(range(1, 8))

    # Test field
    field_position = message_drone.number_to_field()[2]
    assert field_position is not None
    assert isinstance(field_position, MessageField)
    assert field_position.name == "position"
    assert field_position is message_drone.get_member("position")
    assert isinstance(field_position.type, Message)

    # Test message nbits.
    message_network = proto.get_member("Network")
    message_network = cast_or_raise(Message, message_network)
    assert message_network.nbits() == 4 + 64

    # Test message options
    assert message_drone.options() == []

    # Test enum
    enum_drone_status = proto.get_member("DroneStatus")
    assert enum_drone_status is not None
    assert isinstance(enum_drone_status, Enum)

    enum_drone_status = cast_or_raise(Enum, enum_drone_status)

    # Test enum nbits
    assert enum_drone_status.nbits() == 3
    assert len(enum_drone_status.fields()) == 5

    # Test enum.name_to_values()
    assert tuple(enum_drone_status.name_to_values().keys()) == (
        "DRONE_STATUS_UNKNOWN",
        "DRONE_STATUS_STANDBY",
        "DRONE_STATUS_RISING",
        "DRONE_STATUS_LANDING",
        "DRONE_STATUS_FLYING",
    )

    # Test enum.value_to_names()
    assert tuple(enum_drone_status.value_to_names()) == (0, 1, 2, 3, 4)

    # Test array.
    field_propellers = message_drone.get_member("propellers")
    assert field_propellers and isinstance(field_propellers, MessageField)
    field_propellers = cast_or_raise(MessageField, field_propellers)
    assert isinstance(field_propellers.type, Array)
    array_of_propellers = cast_or_raise(Array, field_propellers.type)
    assert array_of_propellers.cap == 4
    assert array_of_propellers.nbits() == 4 * array_of_propellers.element_type.nbits()
    assert not array_of_propellers.extensible

    # Test alias
    alias_timestamp = cast_or_raise(Alias, proto.get_member("Timestamp"))
    assert alias_timestamp
    assert isinstance(alias_timestamp.type, Int)
Beispiel #21
0
 def p_close_global_scope(self, p: P) -> None:
     scope = self.pop_scope()
     proto = cast_or_raise(Proto, scope)
     if not proto.name:
         raise ProtoNameUndefined(filepath=self.current_filepath())
     proto.freeze()
Beispiel #22
0
def test_cast_or_raise() -> None:
    assert cast_or_raise(int, 1) == 1
    with pytest.raises(TypeError):
        cast_or_raise(int, "1")