Changeset 5809
- Timestamp:
- 08/16/10 20:17:58 (3 years ago)
- Location:
- umpa/branches/protocols
- Files:
-
- 2 modified
-
tests/a_unit/test_protocols/test__fields.py (modified) (5 diffs)
-
umit/umpa/protocols/_fields.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
umpa/branches/protocols/tests/a_unit/test_protocols/test__fields.py
r5808 r5809 741 741 py.test.raises(UMPAException, f.fillout) 742 742 743 class TestOptionsField(TestField): 744 cls_field = OptionsField 745 746 def test_init(self): 747 f = self.cls_field('options') 748 assert f.bits == 0 749 750 def test_set(self): 751 f = self.cls_field('options') 752 753 f.set(None) 754 assert f._value == None 755 756 f.set('payload') 757 assert len(f._value) == 1 758 assert f._value[0].get() == 'payload' 759 760 f.set( [ 'payload' ] ) 761 assert len(f._value) == 1 762 assert f._value[0].get() == 'payload' 763 764 f.set( [ (1, ), (2, ''), (3, 'foo'), 'bar', None ] ) 765 assert len(f._value) == 5 766 assert f._value[0].get() == (1, '') 767 assert f._value[1].get() == (2, '') 768 assert f._value[2].get() == (3, 'foo') 769 assert f._value[3].get() == 'bar' 770 assert f._value[4].get() == None 771 772 def test_get(self): 773 f = self.cls_field('options') 774 assert f.get() is None 775 776 f = self.cls_field('options', 'payload') 777 assert f.get() == [ 'payload' ] 778 779 f = self.cls_field('options', [ 'payload' ]) 780 assert f.get() == [ 'payload' ] 781 782 f = self.cls_field('options', [ (1,), (2, ), (3, ''), (4, 'foo'), 'bar', None ] ) 783 assert f.get() == [ (1, ''), (2, ''), (3, ''), (4, 'foo'), 'bar', None ] 784 785 def test_clear(self): 786 f = self.cls_field('options', 'payload') 787 assert f._value is not None 788 assert f.get() is not None 789 f.clear() 790 assert f._value is None 791 assert f.get() is None 792 793 def test_raw_value(self): 794 f = self.cls_field('foobar') 795 796 f.set('test') 797 assert f._raw_value() == 0x74657374 798 assert f.bits == 32 799 800 f.set([ (1,) ]) 801 assert f._raw_value() == 0x01 802 assert f.bits == 8 803 804 f.set([ (5, 'test') ]) 805 assert f._raw_value() == 0x050674657374 806 assert f.bits == 48 807 808 def test_fillout(self): 809 f = self.cls_field('options') 810 assert f.fillout() == 0 811 assert f.bits == 0 812 743 813 class TestOptionField(TestField): 744 814 cls_field = OptionField … … 746 816 def test_init(self): 747 817 f = self.cls_field('foobar') 748 assert f.auto is False818 assert f.auto is True 749 819 750 820 f = self.cls_field('foobar', 'xxx') 751 821 assert f.get() == 'xxx' 752 822 823 def test_set(self): 824 f = self.cls_field('foobar') 825 826 f.set((1,)) 827 assert f._value == (1, '') 828 f.set((1, '')) 829 assert f._value == (1, '') 830 f.set((1, 'foo')) 831 assert f._value == (1, 'foo') 832 833 f.set((2, )) 834 assert f._value == (2, '') 835 f.set((2, '')) 836 assert f._value == (2, '') 837 f.set((2, 'bar')) 838 assert f._value == (2, 'bar') 839 753 840 def test_get(self): 754 841 f = self.cls_field('foobar') … … 758 845 assert f.get() == 'text' 759 846 760 f = self.cls_field('foobar', (0,)) 761 assert f.get() == (0,) 762 763 def test_set(self): 764 f = self.cls_field('foobar') 765 766 f.set((1,)) 767 assert f.get() == (1,) 768 f.set((2, 'x')) 769 assert f.get() == (2, 'x') 847 f = self.cls_field('foobar', (4, 'test')) 848 assert f.get() == (4, 'test') 770 849 771 850 def test_clear(self): … … 773 852 f.set('foobarfoobar') 774 853 assert f.get() == 'foobarfoobar' 775 assert f.bits == 96776 854 f.clear() 777 855 assert f.get() is None 778 assert f.bits == 0779 856 780 857 def test_raw_value(self): 781 858 f = self.cls_field('foobar') 782 859 783 860 f.set('test') 784 861 assert f._raw_value() == 0x74657374 … … 798 875 799 876 f = self.cls_field('foobar') 800 py.test.raises(UMPAException, f.fillout)877 assert f.fillout() == 0x01 -
umpa/branches/protocols/umit/umpa/protocols/_fields.py
r5808 r5809 950 950 return str_to_bits(self._value) 951 951 952 class OptionsField(Field): 953 """ 954 A field holding IP/TCP options. This field contains a list of zero or more 955 Fields in a format understood by the OptionField class. Example: 956 957 [ (4, 'foo'), '\4\5bar', (5, ), (0, ) ] 958 """ 959 960 bits = 0 # dynamic, changes depending on the content 961 962 def _is_valid(self, value): 963 """ 964 Validate each value independently; return True only if all pass. 965 """ 966 967 if value is None: 968 return True 969 of = OptionField('option') 970 for opt in value: 971 if not of._is_valid(opt): 972 return False 973 return True 974 975 def set(self, value): 976 """ 977 Set the field value. 978 """ 979 980 # allow the user to set a single raw string value 981 if isinstance(value, str): 982 value = [value] 983 984 super(OptionsField, self).set(value) 985 986 if self._value is None or len(value) == 0: 987 self.clear() 988 return 989 990 # the above sets _value to the user-supplied list; convert it to 991 # a list of OptionField objects 992 fields = [] 993 for opt in value: 994 fields.append(OptionField('option', opt)) 995 self._value = fields 996 997 def get(self): 998 """ 999 Get the field value. 1000 """ 1001 1002 if self._value is None: 1003 return None 1004 1005 # build a list of values and return it to the user 1006 values = [] 1007 for field in self._value: 1008 values.append(field.get()) 1009 return values 1010 1011 def _generate_value(self): 1012 """ 1013 No options are included by default. 1014 """ 1015 1016 return [] 1017 1018 def _raw_value(self): 1019 """ 1020 Convert the value to the raw mode and update bits field. 1021 """ 1022 1023 raw = 0 1024 bits = 0 1025 1026 for field in self._value: 1027 field_raw = field.fillout() 1028 raw <<= field.bits 1029 raw |= field_raw 1030 bits += field.bits 1031 1032 self.bits = bits 1033 return raw 1034 952 1035 class OptionField(Field): 953 1036 """ … … 955 1038 956 1039 1. A (option-kind, option-value) tuple. The option-length octet will be 957 generated automatically. The option-value should be a raw string value .958 Options 0 and 1 don't have option-value.1040 generated automatically. The option-value should be a raw string value; 1041 if it's not supplied, an empty value will be used. 959 1042 2. A string value which will be inserted as-is without any validation. 960 1043 """ 961 1044 962 1045 bits = 0 # dynamic, changes depending on the content 1046 auto = True 963 1047 964 1048 def _is_valid(self, value): 965 1049 """ 966 Ensure that the value is either a string or a valid tuple.1050 Ensure that the value is either a string or a non-empty sequence. 967 1051 """ 968 1052 … … 971 1055 if len(value) == 0: 972 1056 return False 973 if value[0] in (0, 1):974 return True975 if len(value) == 1:976 return False977 if not isinstance(value[1], str):978 return False979 1057 return True 980 1058 981 1059 def set(self, value): 982 1060 """ 983 Calculate the bit length after setting the value. 984 """ 985 1061 Canonicalize the field value and recalculate bit length. 1062 """ 1063 1064 # validate and set value 986 1065 super(OptionField, self).set(value) 987 if value is None: 988 self.bits = 0 989 elif isinstance(value, str): 990 # use a raw value as-is 991 self.bits = BYTE * len(value) 992 else: 993 if value[0] in (0, 1): 994 # options 0 and 1 have no option-length field 995 self.bits = BYTE 996 else: 997 self.bits = BYTE * (2 + len(value[1])) 1066 1067 # canonicalize value field: always store as ( kind, value ) pair 1068 if self._value is not None and len(self._value) < 2: 1069 self._value = ( self._value[0], '' ) 998 1070 999 1071 def clear(self): 1000 1072 """ 1073 Clear the field. 1074 1001 1075 Reset the bit length after clearing the value. 1002 1076 """ … … 1007 1081 def _raw_value(self): 1008 1082 """ 1009 Convert the value to the raw mode. 1010 """ 1011 1083 Convert the value to the raw mode and update bits field. 1084 """ 1085 1086 # generate raw value 1012 1087 if isinstance(self._value, str): 1013 1088 data = self._value … … 1017 1092 else: 1018 1093 data = "%c%c%s" % ( self._value[0], len(self._value[1]) + 2, 1019 self._value[1] ) 1094 self._value[1] ) 1095 1096 # update field length 1097 self.bits = BYTE * len(data) 1020 1098 1021 1099 return str_to_bits(data) 1100 1101 def _generate_value(self): 1102 """ 1103 Return a NOP option by default. 1104 """ 1105 1106 return (1, '')
