def test_should_return_field_part_value_when_giving_correct_name( self, size, format_): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) assert 4 == field.get_field_part_value('version')
def test_should_return_correct_value_when_calling_value_as_tuple_property( self): field = BitsField( parts=[FieldPart('version', 4, 4), FieldPart('IHL', 5, 4)], format='B') assert (4, 5) == field.value_as_tuple
def test_should_return_byte_value_when_calling_raw_property( self, size, format_): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) assert struct.pack(f'!{format_}', field.value) == field.raw()
def test_should_set_bits_field_value_when_giving_correct_name_and_value(self, given_value, expected_value): fields = [ShortBitsField([FieldPart('flags', 0b010, 3, Flags), FieldPart('offset', 0, 13)])] bit_class = create_packet_class('Bits', fields) instance = bit_class() instance.flags = given_value assert instance.flags == expected_value
def test_should_return_a_correct_copy_of_field_part_when_calling_clone_method( self): part = FieldPart('part', 2, 3) cloned_part = part.clone() assert cloned_part == part assert cloned_part is not part
def test_should_correctly_represent_field_part(self, enumeration, representation, hexadecimal): part = FieldPart('flags', 20, 6, enumeration, hex=hexadecimal) part.value = 17 assert representation == repr(part)
def test_should_return_field_part_given_its_name(self, size, format_): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) field_part = field['IHL'] assert field_part.name == 'IHL'
def test_should_raise_error_when_giving_incorrect_value_to_hex_property( self, value): part = FieldPart('flags', 0b010, 3) with pytest.raises(TypeError) as exc_info: part.hex = value assert f'hex value must be a boolean but you provided {value}' == str( exc_info.value)
def test_should_raise_error_when_value_is_not_valid_boundaries( self, value): part = FieldPart('banana', 2, 3) with pytest.raises(ValueError) as exc_info: part.value = value assert f'{part.name} value must be between 0 and 7 but you provided {value}' == str( exc_info.value)
def test_should_raise_error_when_given_value_is_not_of_correct_type( self, value): part = FieldPart('banana', 2, 3) with pytest.raises(TypeError) as exc_info: part.value = value assert f'{part.name} value must be a positive integer but you provided {value}' == str( exc_info.value)
def mini_ip_fields() -> List[Field]: """Returns list of fields used in various packet tests.""" return [ ByteBitsField([FieldPart('version', 4, 4), FieldPart('ihl', 5, 4)]), ShortField('length', 20), ShortEnumField('identification', 1, Identification), ShortBitsField([FieldPart('flags', 0b010, 3, Flags), FieldPart('offset', 0, 13)], hex=True), ]
def test_should_raise_error_when_tuple_is_empty(self): field = BitsField( parts=[FieldPart('version', 4, 4), FieldPart('IHL', 5, 4)], format='B') with pytest.raises(ValueError) as exc_info: field.value = () assert 'value must not be an empty tuple' == str(exc_info.value)
def test_should_set_field_part_value_when_giving_correct_name_and_value( self, size, format_): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) field.set_field_part_value('version', 6) assert (6, 5) == field.value_as_tuple
def test_should_raise_error_when_all_items_in_tuple_are_not_integers(self): field = BitsField( parts=[FieldPart('version', 4, 4), FieldPart('IHL', 5, 4)], format='B') with pytest.raises(ValueError) as exc_info: field.value = (2, 3.4) assert 'all items in tuple must be integers' == str(exc_info.value)
def test_should_correctly_instantiate_bits_field(self): field_parts = [FieldPart('version', 4, 4), FieldPart('IHL', 5, 4)] field = BitsField(parts=field_parts, format='B') assert field_parts == field.parts assert 1 == field.size assert '!B' == field.struct_format assert self.get_int_from_tuple(4, (4, 5)) == field.default assert not field.hex
def test_should_correctly_represent_bits_field(self, value_1, value_2, hexadecimal): field_parts = [FieldPart('version', 4, 4), FieldPart('IHL', 5, 4)] field = BitsField(parts=field_parts, format='B', hex=hexadecimal) assert ( f'BitsField(FieldPart(name=version, default={value_1}, value={value_1}),' f' FieldPart(name=IHL, default={value_2}, value={value_2}))' ) == repr(field)
def test_should_call_randint_function_with_correct_values( self, mocker, size, format_, right_value): randint_mock = mocker.patch('random.randint', return_value=2) field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) assert 2 == field.random_value() randint_mock.assert_called_once_with(0, right_value)
def test_should_return_empty_byte_when_not_enough_data_to_compute( self, size, format_): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) remaining_bytes = field.compute_value(b'bbb') assert remaining_bytes == b'' assert field.value_was_computed is False
def test_should_raise_error_when_value_is_not_integer_or_tuple( self, value): field = BitsField( parts=[FieldPart('version', 4, 4), FieldPart('IHL', 5, 4)], format='B') with pytest.raises(TypeError) as exc_info: field.value = value assert 'value must be an integer or a tuple of integers' == str( exc_info.value)
def test_should_raise_error_when_trying_to_access_field_part_giving_a_wrong_name( self, size, format_): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) with pytest.raises(KeyError) as exc_info: assert field['foo'] assert f"'no field part was found with name foo'" == str( exc_info.value)
def test_should_raise_error_when_tuple_length_is_different_field_parts_length( self): field = BitsField( parts=[FieldPart('version', 4, 4), FieldPart('IHL', 5, 4)], format='B') with pytest.raises(ValueError) as exc_info: field.value = (2, 3, 4) assert 'tuple length is different from field parts length' == str( exc_info.value)
def test_should_raise_error_when_items_dont_have_a_correct_value( self, size, format_, value_1, value_2): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) for value in [value_1, value_2]: with pytest.raises(ValueError) as exc_info: field.value = (value, 4) message = f'item version must be between 0 and {2 ** size - 1} according to the field part size' assert message == str(exc_info.value)
def test_should_raise_error_when_int_value_is_not_in_valid_boundaries( self, size, format_, value_1, value_2): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) for value in [value_1, value_2]: with pytest.raises(ValueError) as exc_info: field.value = value assert f'integer value must be between 0 and {value_2 - 1}' == str( exc_info.value)
class MiniIP(Packet): # noinspection PyArgumentList __fields__ = [ ByteBitsField([FieldPart('version', 4, 4), FieldPart('ihl', 5, 4)]), ShortField('length', 20), ShortEnumField('identification', 1, Identification), ShortBitsField( [FieldPart('flags', 0b010, 3, Flags), FieldPart('offset', 0, 13)], hex=True), ]
def test_should_raise_error_if_name_is_not_present_in_field_parts_when_setting_value( self, size, format_): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) name = 'hello' with pytest.raises(KeyError) as exc_info: field.set_field_part_value(name, 6) assert f"'no field part was found with name {name}'" == str( exc_info.value)
def test_should_not_raise_error_when_setting_a_correct_tuple_value( self, size, format_): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) value = (5, 6) try: field.value = value except ValueError: pytest.fail(f'unexpected error when setting value with {value}') assert value == field.value_as_tuple
def test_should_return_a_copy_of_the_object_when_calling_clone_method( self): field = BitsField( parts=[FieldPart('version', 4, 4), FieldPart('IHL', 5, 4)], format='B') cloned_field = field.clone() assert cloned_field == field assert cloned_field is not field # check the parts attribute of cloned field is not a shallow copy for i, part in enumerate(cloned_field.parts): assert part is not field.parts[i]
def test_should_raise_error_when_parts_size_is_not_correct( self, size_1, size_2): with pytest.raises(ValueError) as exc_info: BitsField( parts=[ FieldPart('version', 4, size_1), FieldPart('IHL', 5, size_2) ], format='B' # 1 byte (8 bits) ) size = size_1 + size_2 assert (f'the sum in bits of the different FieldPart ({size})' f' is different from the field size (8)') == str( exc_info.value)
def test_should_correctly_instantiate_object(self, bit_class, size, format_): field_parts = [ FieldPart('version', 4, size), FieldPart('IHL', 5, size) ] # Pycharm 2020.3 has an issue related to overriding attributes on a "attrs" class # noinspection PyArgumentList field = bit_class(field_parts) assert size * 2 == field.size * 8 assert field_parts == field.parts assert f'!{format_}' == field.struct_format assert (4, 5) == field.value_as_tuple assert field.default == field.value
def test_should_compute_internal_field_part_value_when_calling_compute_value_method( self, size, format_): field = BitsField( parts=[FieldPart('version', 4, size), FieldPart('IHL', 5, size)], format=format_) assert field.value_was_computed is False value = (8, 11) data = struct.pack(f'!{format_}5s', self.get_int_from_tuple(size, value), b'hello') remaining_data = field.compute_value(data) assert remaining_data == b'hello' assert field.value_as_tuple == (8, 11) assert field.value_was_computed is True