DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
WIBEth_binding_test.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2
3import sys
4from fddetdataformats import WIBEthFrame, WIBEthHeader
5
6
7NUM_CHANNELS = 64
8NUM_SAMPLES = 64
9ADC_MAX = (1 << 14) - 1 # 14-bit ADC
10
11
13 frame = WIBEthFrame()
14 if frame is None:
15 print("FAIL: WIBEthFrame default construction returned None")
16 return 1
17 size = WIBEthFrame.sizeof()
18 if size <= 0:
19 print(f"FAIL: WIBEthFrame.sizeof() returned {size}, expected > 0")
20 return 1
21 print(f"PASS: WIBEthFrame construction and sizeof={size}")
22 return 0
23
24
26 if WIBEthFrame.s_bits_per_adc != 14:
27 print(f"FAIL: WIBEthFrame.s_bits_per_adc expected 14, got {WIBEthFrame.s_bits_per_adc}")
28 return 1
29 if WIBEthFrame.s_num_channels != NUM_CHANNELS:
30 print(f"FAIL: WIBEthFrame.s_num_channels expected {NUM_CHANNELS}, got {WIBEthFrame.s_num_channels}")
31 return 1
32 if WIBEthFrame.s_time_samples_per_frame != NUM_SAMPLES:
33 print(f"FAIL: WIBEthFrame.s_time_samples_per_frame expected {NUM_SAMPLES}, got {WIBEthFrame.s_time_samples_per_frame}")
34 return 1
35 if WIBEthFrame.s_expected_bytes != WIBEthFrame.sizeof():
36 print(f"FAIL: WIBEthFrame.s_expected_bytes {WIBEthFrame.s_expected_bytes} != sizeof {WIBEthFrame.sizeof()}")
37 return 1
38 if WIBEthHeader.s_expected_bytes <= 0:
39 print(f"FAIL: WIBEthHeader.s_expected_bytes invalid: {WIBEthHeader.s_expected_bytes}")
40 return 1
41 print("PASS: WIBEthFrame/WIBEthHeader static members")
42 return 0
43
44
46 frame = WIBEthFrame()
47 frame.set_timestamp(0xABCDEF012345)
48 frame.set_channel(12)
49 raw = frame.get_bytes()
50 if len(raw) != WIBEthFrame.sizeof():
51 print(f"FAIL: get_bytes() length {len(raw)} != sizeof() {WIBEthFrame.sizeof()}")
52 return 1
53 clone = WIBEthFrame(raw)
54 if clone.get_timestamp() != 0xABCDEF012345:
55 print(f"FAIL: bytes round-trip timestamp mismatch: got {clone.get_timestamp():#x}")
56 return 1
57 if clone.get_channel() != 12:
58 print(f"FAIL: bytes round-trip channel mismatch: got {clone.get_channel()}")
59 return 1
60 print("PASS: WIBEthFrame bytes constructor roundtrip")
61 return 0
62
63
65 earlier = WIBEthFrame()
66 later = WIBEthFrame()
67 earlier.set_timestamp(100)
68 later.set_timestamp(200)
69 if not (earlier < later):
70 print("FAIL: __lt__ expected earlier < later")
71 return 1
72 if later < earlier:
73 print("FAIL: __lt__ expected later !< earlier")
74 return 1
75 print("PASS: __lt__ ordering by timestamp")
76 return 0
77
78
79def test_timestamp() -> int:
80 frame = WIBEthFrame()
81 test_ts = 0x123456789ABC
82 frame.set_timestamp(test_ts)
83 got = frame.get_timestamp()
84 if got != test_ts:
85 print(f"FAIL: set/get_timestamp: set {test_ts:#x}, got {got:#x}")
86 return 1
87 print("PASS: set_timestamp / get_timestamp")
88 return 0
89
90
91def test_channel() -> int:
92 frame = WIBEthFrame()
93 for val in (0, 1, 127, 255):
94 frame.set_channel(val)
95 got = frame.get_channel()
96 if got != val:
97 print(f"FAIL: set_channel({val}), get_channel() returned {got}")
98 return 1
99 print("PASS: set_channel / get_channel")
100 return 0
101
102
104 frame = WIBEthFrame()
105 hdr = frame.daq_header
106 if hdr is None:
107 print("FAIL: daq_header returned None")
108 return 1
109 hdr_alias = frame.get_daqheader()
110 if hdr_alias is None:
111 print("FAIL: get_daqheader() returned None")
112 return 1
113 print("PASS: daq_header accessible")
114 return 0
115
116
117def test_set_geoid() -> int:
118 frame = WIBEthFrame()
119 crate_id = 9
120 slot_id = 7
121 stream_id = 42
122 hdr = frame.daq_header
123 hdr.crate_id = crate_id
124 hdr.slot_id = slot_id
125 hdr.stream_id = stream_id
126 if hdr.crate_id != crate_id:
127 print(f"FAIL: crate_id mismatch, got {hdr.crate_id}")
128 return 1
129 if hdr.slot_id != slot_id:
130 print(f"FAIL: slot_id mismatch, got {hdr.slot_id}")
131 return 1
132 if hdr.stream_id != stream_id:
133 print(f"FAIL: stream_id mismatch, got {hdr.stream_id}")
134 return 1
135 print("PASS: DAQEthHeader geoid fields can be set directly")
136 return 0
137
138
140 frame = WIBEthFrame()
141 hdr = frame.header
142 hdr_alias = frame.get_wibheader()
143
144 if hdr_alias is None:
145 print("FAIL: get_wibheader() returned None")
146 return 1
147
148 hdr.channel = 4
149 hdr.version = 2
150 hdr.cd = 1
151 hdr.context = 3
152 hdr.ready = 1
153 hdr.calibration = 1
154 hdr.pulser = 1
155 hdr.femb_sync = 2
156 hdr.wib_sync = 1
157 hdr.lol = 1
158 hdr.link_valid = 2
159 hdr.crc_err = 1
160 hdr.colddata_timestamp_1 = 99
161 hdr.colddata_timestamp_0 = 77
162 hdr.extra_data = 0x1122334455667788
163
164 if hdr.channel != 4:
165 print(f"FAIL: WIBEthHeader.channel mismatch, got {hdr.channel}")
166 return 1
167 if hdr.version != 2:
168 print(f"FAIL: WIBEthHeader.version mismatch, got {hdr.version}")
169 return 1
170 if hdr.cd != 1:
171 print(f"FAIL: WIBEthHeader.cd mismatch, got {hdr.cd}")
172 return 1
173 if hdr.context != 3:
174 print(f"FAIL: WIBEthHeader.context mismatch, got {hdr.context}")
175 return 1
176 if hdr.ready != 1 or hdr.calibration != 1 or hdr.pulser != 1:
177 print("FAIL: WIBEthHeader ready/calibration/pulser mismatch")
178 return 1
179 if hdr.femb_sync != 2 or hdr.wib_sync != 1:
180 print("FAIL: WIBEthHeader femb_sync/wib_sync mismatch")
181 return 1
182 if hdr.lol != 1:
183 print(f"FAIL: WIBEthHeader.lol mismatch, got {hdr.lol}")
184 return 1
185 if hdr.link_valid != 2 or hdr.crc_err != 1:
186 print("FAIL: WIBEthHeader link_valid/crc_err mismatch")
187 return 1
188 if hdr.colddata_timestamp_1 != 99:
189 print(f"FAIL: WIBEthHeader.colddata_timestamp_1 mismatch, got {hdr.colddata_timestamp_1}")
190 return 1
191 if hdr.colddata_timestamp_0 != 77:
192 print(f"FAIL: WIBEthHeader.colddata_timestamp_0 mismatch, got {hdr.colddata_timestamp_0}")
193 return 1
194 if hdr.extra_data != 0x1122334455667788:
195 print(f"FAIL: WIBEthHeader.extra_data mismatch, got {hdr.extra_data:#x}")
196 return 1
197 if hdr_alias.extra_data != 0x1122334455667788:
198 print(f"FAIL: get_wibheader alias mismatch, got {hdr_alias.extra_data:#x}")
199 return 1
200
201 print("PASS: WIBEthHeader property read/write and get_wibheader alias")
202 return 0
203
204
205def test_adc_single() -> int:
206 frame = WIBEthFrame()
207 frame.set_adc(0, 0, 1234)
208 got = frame.get_adc(0, 0)
209 if got != 1234:
210 print(f"FAIL: set_adc(0,0,1234) -> get_adc(0,0) returned {got}")
211 return 1
212 print("PASS: single ADC set/get (channel 0, sample 0)")
213 return 0
214
215
217 frame = WIBEthFrame()
218 frame.set_adc(0, 0, ADC_MAX)
219 got = frame.get_adc(0, 0)
220 if got != ADC_MAX:
221 print(f"FAIL: max ADC value {ADC_MAX}: got {got}")
222 return 1
223 print(f"PASS: max ADC value ({ADC_MAX}) preserved")
224 return 0
225
226
228 """Verify that writing to one (channel, sample) cell does not corrupt its neighbours."""
229 frame = WIBEthFrame()
230 test_cases = [
231 (0, 0, 100),
232 (0, 1, 200),
233 (1, 0, 300),
234 (NUM_CHANNELS - 1, NUM_SAMPLES - 1, 9999),
235 ]
236 for ch, samp, val in test_cases:
237 frame.set_adc(ch, samp, val)
238 for ch, samp, expected in test_cases:
239 got = frame.get_adc(ch, samp)
240 if got != expected:
241 print(f"FAIL: ADC independence: channel={ch}, sample={samp}: expected {expected}, got {got}")
242 return 1
243 print("PASS: ADC cell independence across multiple (channel, sample) pairs")
244 return 0
245
246
248 """Write a unique value to every channel in sample 0 and verify all read back correctly."""
249 frame = WIBEthFrame()
250 for ch in range(NUM_CHANNELS):
251 frame.set_adc(ch, 0, ch * 100 % (ADC_MAX + 1))
252 for ch in range(NUM_CHANNELS):
253 expected = ch * 100 % (ADC_MAX + 1)
254 got = frame.get_adc(ch, 0)
255 if got != expected:
256 print(f"FAIL: all-channels test: channel {ch}: expected {expected}, got {got}")
257 return 1
258 print(f"PASS: all {NUM_CHANNELS} channels read back correctly for sample 0")
259 return 0
260
261
263 """get_adc / set_adc should raise when indices are out of range."""
264 frame = WIBEthFrame()
265 try:
266 frame.get_adc(NUM_CHANNELS, 0)
267 print("FAIL: get_adc with out-of-range channel should have raised an exception")
268 return 1
269 except Exception:
270 pass
271 try:
272 frame.get_adc(0, NUM_SAMPLES)
273 print("FAIL: get_adc with out-of-range sample should have raised an exception")
274 return 1
275 except Exception:
276 pass
277 print("PASS: out-of-range ADC indices raise exceptions as expected")
278 return 0
279
280
281def main() -> int:
282 tests = [
283 test_construction_and_size,
284 test_static_members,
285 test_bytes_roundtrip,
286 test_less_than_operator,
287 test_timestamp,
288 test_channel,
289 test_daqheader_accessible,
290 test_set_geoid,
291 test_header_properties,
292 test_adc_single,
293 test_adc_max_value,
294 test_adc_independence,
295 test_adc_all_channels_one_sample,
296 test_adc_out_of_range,
297 ]
298
299 failures = 0
300 for test in tests:
301 failures += test()
302
303 print()
304 if failures == 0:
305 print("All WIBEthFrame Python binding tests passed")
306 else:
307 print(f"{failures} WIBEthFrame Python binding test(s) FAILED")
308 return failures
309
310
311if __name__ == "__main__":
312 sys.exit(main())