Skip to content

Commit 177370c

Browse files
committed
add robustness tests for ARINC 717/767 bit extraction and decoding
1 parent 7c3e007 commit 177370c

2 files changed

Lines changed: 198 additions & 0 deletions

File tree

‎tests/test_arinc717_parameter.py‎

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,102 @@ def test_arinc717_cob():
9191
cob_formula="raw * 0.00390625",
9292
)
9393
assert abs(p.decode(256) - 1.0) < 1e-6
94+
95+
96+
def test_signed_cross_byte_extraction():
97+
# 0b0111_1111_1111_1111 = +32767
98+
# 0b1000_0000_0000_0001 = -32767 (two's complement)
99+
data_pos = b"\x7F\xFF"
100+
data_neg = b"\x80\x01"
101+
102+
p = Parameter("X", start_bit=0, bit_length=16, data_type="BNR", signed=True)
103+
104+
assert p.decode_raw_from_bytes(data_pos) == 32767
105+
assert p.decode_raw_from_bytes(data_neg) == -32767
106+
107+
108+
def test_char_with_embedded_nulls():
109+
raw = int.from_bytes(b"A\x00C", "big")
110+
p = Parameter("CH", start_bit=0, bit_length=24, data_type="CHAR")
111+
assert p.decode(raw) == "A\x00C"
112+
113+
114+
def test_utc_leading_zero():
115+
p = Parameter("UTC", start_bit=0, bit_length=24, data_type="UTC")
116+
assert p.decode(0x012305) == "01:23:05"
117+
118+
119+
def test_cob_formula_failure_falls_back_to_raw():
120+
p = Parameter(
121+
"BAD",
122+
start_bit=0,
123+
bit_length=8,
124+
data_type="COB",
125+
cob_formula="raw / 0", # division by zero
126+
)
127+
assert p.decode(10) == 10
128+
129+
130+
def test_717_decode_from_frame_uses_word_fields():
131+
frame = bytes([0x12, 0x34, 0x56])
132+
p = Parameter(
133+
"ALT",
134+
bit_length=8,
135+
data_type="BNR",
136+
start_bit=None,
137+
subframe=0,
138+
word=1,
139+
bit_offset=0,
140+
)
141+
# word=1 → second byte → 0x34
142+
val, valid = p.decode_from_frame(frame, words_per_subframe=4, word_bits=8)
143+
assert valid
144+
assert val == 0x34
145+
146+
147+
def test_767_decode_raw_requires_start_bit():
148+
p = Parameter("X", bit_length=8, data_type="BNR", start_bit=None)
149+
with pytest.raises(ValueError):
150+
p.decode_raw_from_bytes(b"\x00")
151+
152+
153+
def test_717_absolute_bit_start_multi_subframe():
154+
p = Parameter(
155+
"ALT",
156+
bit_length=8,
157+
data_type="BNR",
158+
start_bit=None,
159+
subframe=3,
160+
word=2,
161+
bit_offset=5,
162+
)
163+
# subframe 3 → 3 * (4 words * 12 bits) = 144
164+
assert p.compute_absolute_bit_start(4, 12) == 144 + 24 + 5
165+
166+
167+
def test_767_extract_non_byte_aligned():
168+
data = b"\xAA\xBB\xCC" # 10101010 10111011 11001100
169+
p = Parameter("X", start_bit=5, bit_length=10, data_type="DISCRETE")
170+
assert p.extract_bits_767(data, 5, 10) == 0b0101011101
171+
172+
173+
def test_717_out_of_bounds():
174+
frame = b"\x00\x00"
175+
p = Parameter(
176+
"ALT",
177+
bit_length=16,
178+
data_type="BNR",
179+
start_bit=None,
180+
subframe=0,
181+
word=1,
182+
bit_offset=0,
183+
)
184+
val, valid = p.decode_from_frame(frame, 4, 12)
185+
assert not valid
186+
assert val is None
187+
188+
189+
def test_767_partial_data_rejected():
190+
p = Parameter("X", start_bit=8, bit_length=16, data_type="BNR")
191+
with pytest.raises(ValueError):
192+
p.decode_raw_from_bytes(b"\x12") # only 8 bits available

‎tests/test_arinc767_parameter.py‎

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,102 @@ def test_arinc767_extract_out_of_bounds_raises() -> None:
9797
p = Parameter("X", start_bit=32, bit_length=8, data_type="BNR")
9898
with pytest.raises(ValueError):
9999
_ = p.decode_raw_from_bytes(b"\x00\x00\x00\x00")
100+
101+
102+
def test_signed_cross_byte_extraction():
103+
# 0b0111_1111_1111_1111 = +32767
104+
# 0b1000_0000_0000_0001 = -32767 (two's complement)
105+
data_pos = b"\x7F\xFF"
106+
data_neg = b"\x80\x01"
107+
108+
p = Parameter("X", start_bit=0, bit_length=16, data_type="BNR", signed=True)
109+
110+
assert p.decode_raw_from_bytes(data_pos) == 32767
111+
assert p.decode_raw_from_bytes(data_neg) == -32767
112+
113+
114+
def test_char_with_embedded_nulls():
115+
raw = int.from_bytes(b"A\x00C", "big")
116+
p = Parameter("CH", start_bit=0, bit_length=24, data_type="CHAR")
117+
assert p.decode(raw) == "A\x00C"
118+
119+
120+
def test_utc_leading_zero():
121+
p = Parameter("UTC", start_bit=0, bit_length=24, data_type="UTC")
122+
assert p.decode(0x012305) == "01:23:05"
123+
124+
125+
def test_cob_formula_failure_falls_back_to_raw():
126+
p = Parameter(
127+
"BAD",
128+
start_bit=0,
129+
bit_length=8,
130+
data_type="COB",
131+
cob_formula="raw / 0", # division by zero
132+
)
133+
assert p.decode(10) == 10
134+
135+
136+
def test_717_decode_from_frame_uses_word_fields():
137+
frame = bytes([0x12, 0x34, 0x56])
138+
p = Parameter(
139+
"ALT",
140+
bit_length=8,
141+
data_type="BNR",
142+
start_bit=None,
143+
subframe=0,
144+
word=1,
145+
bit_offset=0,
146+
)
147+
# word=1 → second byte → 0x34
148+
val, valid = p.decode_from_frame(frame, words_per_subframe=4, word_bits=8)
149+
assert valid
150+
assert val == 0x34
151+
152+
153+
def test_767_decode_raw_requires_start_bit():
154+
p = Parameter("X", bit_length=8, data_type="BNR", start_bit=None)
155+
with pytest.raises(ValueError):
156+
p.decode_raw_from_bytes(b"\x00")
157+
158+
159+
def test_717_absolute_bit_start_multi_subframe():
160+
p = Parameter(
161+
"ALT",
162+
bit_length=8,
163+
data_type="BNR",
164+
start_bit=None,
165+
subframe=3,
166+
word=2,
167+
bit_offset=5,
168+
)
169+
# subframe 3 → 3 * (4 words * 12 bits) = 144
170+
assert p.compute_absolute_bit_start(4, 12) == 144 + 24 + 5
171+
172+
173+
def test_767_extract_non_byte_aligned():
174+
data = b"\xAA\xBB\xCC" # 10101010 10111011 11001100
175+
p = Parameter("X", start_bit=5, bit_length=10, data_type="DISCRETE")
176+
assert p.extract_bits_767(data, 5, 10) == 0b0101011101
177+
178+
179+
def test_717_out_of_bounds():
180+
frame = b"\x00\x00"
181+
p = Parameter(
182+
"ALT",
183+
bit_length=16,
184+
data_type="BNR",
185+
start_bit=None,
186+
subframe=0,
187+
word=1,
188+
bit_offset=0,
189+
)
190+
val, valid = p.decode_from_frame(frame, 4, 12)
191+
assert not valid
192+
assert val is None
193+
194+
195+
def test_767_partial_data_rejected():
196+
p = Parameter("X", start_bit=8, bit_length=16, data_type="BNR")
197+
with pytest.raises(ValueError):
198+
p.decode_raw_from_bytes(b"\x12") # only 8 bits available

0 commit comments

Comments
 (0)