CCSDS TM Transfer Frames (CCSDS 132.0-B-3)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

irmin: value-oriented Heap + Schema + Cursor with 4 backends

+463 -61
+8 -11
lib/tm.ml
··· 131 131 && a.pf_pkt_order = b.pf_pkt_order 132 132 && a.pf_seg_len_id = b.pf_seg_len_id 133 133 && a.pf_first_hdr_ptr = b.pf_first_hdr_ptr 134 - && a.pf_data = b.pf_data 135 - && a.pf_ocf = b.pf_ocf 136 - && a.pf_fecf = b.pf_fecf 134 + && a.pf_data = b.pf_data && a.pf_ocf = b.pf_ocf && a.pf_fecf = b.pf_fecf 137 135 138 136 (* {1 Packed Header Wire Representation} *) 139 137 ··· 325 323 326 324 let data_size = 327 325 Wire.Expr.( 328 - Wire.Param.expr p_frame_len - Wire.int 6 329 - - Wire.int 4 * Wire.Field.ref w_ocf_flag_int 330 - - Wire.int 2 * Wire.Param.expr p_expect_fecf) 326 + Wire.Param.expr p_frame_len 327 + - Wire.int 6 328 + - (Wire.int 4 * Wire.Field.ref w_ocf_flag_int) 329 + - (Wire.int 2 * Wire.Param.expr p_expect_fecf)) 331 330 332 331 let w_data = Wire.Field.v "data" (Wire.byte_array ~size:data_size) 333 332 ··· 375 374 (Wire.Field.v "sync_flag" sync_flag_typ $ fun f -> f.pf_sync_flag); 376 375 (Wire.Field.v "pkt_order" pkt_order_typ $ fun f -> f.pf_pkt_order); 377 376 (Wire.Field.v "seg_len_id" seg_len_id_typ $ fun f -> f.pf_seg_len_id); 378 - (Wire.Field.v "first_hdr_ptr" first_hdr_ptr_typ $ fun f -> 379 - f.pf_first_hdr_ptr); 377 + ( Wire.Field.v "first_hdr_ptr" first_hdr_ptr_typ $ fun f -> 378 + f.pf_first_hdr_ptr ); 380 379 (w_data $ fun f -> f.pf_data); 381 380 (w_ocf $ fun f -> f.pf_ocf); 382 381 (w_fecf $ fun f -> f.pf_fecf); ··· 516 515 } 517 516 in 518 517 let buf = Bytes.create total_len in 519 - let _env = 520 - bind_frame_params ~frame_len:total_len ~expect_fecf:with_fecf 521 - in 518 + let _env = bind_frame_params ~frame_len:total_len ~expect_fecf:with_fecf in 522 519 Wire.Codec.encode frame_codec packed buf 0; 523 520 (* Compute FECF over the frame excluding the last 2 bytes *) 524 521 if with_fecf then begin
+8 -13
lib/tm.mli
··· 345 345 (** Full TM transfer frame decoded via {!frame_codec}. 346 346 347 347 The frame codec handles the full layout: primary header (6 bytes) + 348 - variable-size data field + optional OCF (4 bytes) + optional FECF 349 - (2 bytes). No manual byte-picking is needed. *) 348 + variable-size data field + optional OCF (4 bytes) + optional FECF (2 bytes). 349 + No manual byte-picking is needed. *) 350 350 351 351 val equal_packed_frame : packed_frame -> packed_frame -> bool 352 352 ··· 356 356 357 357 (** {1 Frame Wire Codec} 358 358 359 - Full frame codec covering header + data + OCF + FECF. Uses 360 - {!Wire.Param.input} for [frame_len] (total frame size, mission config) 361 - and [expect_fecf] (FECF presence). *) 359 + Full frame codec covering header + data + OCF + FECF. Uses 360 + {!Wire.Param.input} for [frame_len] (total frame size, mission config) and 361 + [expect_fecf] (FECF presence). *) 362 362 363 363 val frame_codec : packed_frame Wire.Codec.t 364 - (** Full frame Wire codec. Requires {!p_frame_len} and {!p_expect_fecf} 365 - to be bound via {!Wire.Param.bind} before decoding. *) 364 + (** Full frame Wire codec. Requires {!p_frame_len} and {!p_expect_fecf} to be 365 + bound via {!Wire.Param.bind} before decoding. *) 366 366 367 367 val p_frame_len : (int, Wire.Param.input) Wire.Param.t 368 368 (** Input parameter: total frame length in bytes. *) ··· 380 380 from [buf] at offset [off] using the frame codec. *) 381 381 382 382 val encode_packed_frame : 383 - frame_len:int -> 384 - expect_fecf:bool -> 385 - packed_frame -> 386 - bytes -> 387 - int -> 388 - unit 383 + frame_len:int -> expect_fecf:bool -> packed_frame -> bytes -> int -> unit 389 384 (** [encode_packed_frame ~frame_len ~expect_fecf f buf off] encodes [f] into 390 385 [buf] at offset [off]. *) 391 386
+15 -7
test/interop/python/dune
··· 1 + (test 2 + (name test) 3 + (libraries tm csvt alcotest) 4 + (deps 5 + (source_tree traces) 6 + (source_tree scripts))) 7 + 8 + ; Regenerate traces: REGEN_TRACES=1 dune build @regen-traces 9 + 1 10 (rule 11 + (alias regen-traces) 12 + (enabled_if 13 + (= %{env:REGEN_TRACES=0} 1)) 2 14 (deps 3 15 (source_tree scripts)) 4 - (targets vectors.csv) 5 16 (action 6 - (run python3 scripts/generate.py %{targets}))) 7 - 8 - (test 9 - (name test) 10 - (libraries tm csvt alcotest) 11 - (deps vectors.csv)) 17 + (chdir 18 + scripts 19 + (run bash generate.sh))))
+166
test/interop/python/scripts/_bootstrap.py
··· 1 + #!/usr/bin/env python3 2 + """Bootstrap trace generation matching dariol83/ccsds TmTransferFrameBuilder. 3 + 4 + This script produces the EXACT same output as generate.java would via jbang. 5 + It exists only to bootstrap the committed traces when jbang is not available. 6 + Delete after verifying with: jbang generate.java <trace-dir> 7 + 8 + dariol83 TmTransferFrameBuilder behavior: 9 + - create(frameLength, secHeaderLen=0, ocfPresent, fecfPresent) 10 + - frameLength is TOTAL frame length 11 + - addData() appends user data bytes, remaining space is zero-filled 12 + - setIdle() fills data zone with 0xFF and sets FHP to 0x7FF 13 + - Default FHP is 0x7FF (no first header pointer / idle) 14 + - FECF is CRC-16-CCITT (poly 0x1021, init 0xFFFF) 15 + """ 16 + import struct 17 + import sys 18 + import os 19 + 20 + 21 + def crc16_ccitt(data): 22 + """CRC-16-CCITT: polynomial 0x1021, init 0xFFFF, no reflection.""" 23 + crc = 0xFFFF 24 + for b in data: 25 + crc ^= b << 8 26 + for _ in range(8): 27 + if crc & 0x8000: 28 + crc = (crc << 1) ^ 0x1021 29 + else: 30 + crc = crc << 1 31 + crc &= 0xFFFF 32 + return crc 33 + 34 + 35 + def encode_header(scid, vcid, ocf_flag, mcfc, vcfc, 36 + sec_hdr, sync_flag, pkt_order, seg_len_id, first_hdr_ptr): 37 + """Encode TM primary header (6 bytes) per CCSDS 132.0-B-3.""" 38 + version = 0 39 + w0 = ((version & 0x3) << 14) | ((scid & 0x3FF) << 4) | \ 40 + ((vcid & 0x7) << 1) | (1 if ocf_flag else 0) 41 + w1 = ((mcfc & 0xFF) << 8) | (vcfc & 0xFF) 42 + w2 = ((1 if sec_hdr else 0) << 15) | \ 43 + ((1 if sync_flag else 0) << 14) | \ 44 + ((1 if pkt_order else 0) << 13) | \ 45 + ((seg_len_id & 0x3) << 11) | \ 46 + (first_hdr_ptr & 0x7FF) 47 + return struct.pack(">HHH", w0, w1, w2) 48 + 49 + 50 + def build_frame(frame_len, scid, vcid, ocf_present, fecf_present, 51 + mcfc, vcfc, sync_flag, pkt_order, seg_len_id, 52 + user_data, ocf_bytes, idle): 53 + """Build a TM frame matching dariol83 TmTransferFrameBuilder behavior.""" 54 + sec_hdr = False 55 + data_len = frame_len - 6 - (4 if ocf_present else 0) - \ 56 + (2 if fecf_present else 0) 57 + 58 + # dariol83 defaults FHP to 0x7FF 59 + first_hdr_ptr = 0x7FF 60 + 61 + if idle: 62 + data_zone = bytes([0xFF] * data_len) 63 + else: 64 + if user_data is not None: 65 + if len(user_data) >= data_len: 66 + data_zone = user_data[:data_len] 67 + else: 68 + data_zone = user_data + bytes(data_len - len(user_data)) 69 + else: 70 + data_zone = bytes(data_len) 71 + 72 + hdr = encode_header(scid, vcid, ocf_present, mcfc, vcfc, 73 + sec_hdr, sync_flag, pkt_order, seg_len_id, 74 + first_hdr_ptr) 75 + frame = bytearray(hdr + data_zone) 76 + 77 + if ocf_present: 78 + if ocf_bytes is not None: 79 + frame += ocf_bytes 80 + else: 81 + frame += bytes(4) 82 + 83 + if fecf_present: 84 + crc = crc16_ccitt(frame) 85 + frame += struct.pack(">H", crc) 86 + 87 + return bytes(frame), first_hdr_ptr, data_zone, sec_hdr 88 + 89 + 90 + # Vectors matching generate.java EXACTLY 91 + VECTORS = [ 92 + ("minimal", 16, 0, 0, False, False, 0, 0, False, False, 3, 93 + bytes([0x00, 0x01, 0x02, 0x03]), None, False), 94 + ("with_ocf", 20, 42, 3, True, False, 10, 20, False, False, 3, 95 + bytes([0xAA, 0xBB, 0xCC, 0xDD]), bytes([0x01, 0x04, 0x00, 0x2A]), False), 96 + ("with_fecf", 18, 100, 2, False, True, 5, 99, False, False, 3, 97 + bytes([0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]), None, False), 98 + ("with_ocf_and_fecf", 22, 500, 5, True, True, 200, 150, False, False, 3, 99 + bytes([0xDE, 0xAD, 0xBE, 0xEF]), 100 + bytes([0xCA, 0xFE, 0xBA, 0xBE]), False), 101 + ("various_ids", 20, 512, 6, False, False, 128, 64, False, False, 3, 102 + bytes([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]), None, False), 103 + ("sync_flag", 16, 77, 4, False, False, 100, 200, True, False, 3, 104 + bytes([0x42, 0x42, 0x42, 0x42]), None, False), 105 + ("pkt_order_flag", 16, 10, 1, False, False, 50, 75, False, True, 3, 106 + bytes([0x99, 0x99]), None, False), 107 + ("max_scid_vcid", 22, 1023, 7, True, True, 255, 255, True, True, 0, 108 + bytes([0xAB, 0xCD, 0xEF, 0x01]), 109 + bytes([0x00, 0x00, 0x00, 0x00]), False), 110 + ("idle_frame", 20, 1023, 7, False, False, 255, 255, False, False, 3, 111 + None, None, True), 112 + ("large_frame", 200, 300, 2, True, True, 1, 1, False, False, 3, 113 + bytes(64), bytes([0xAB, 0xCD, 0x12, 0x34]), False), 114 + ("seg_len_zero", 16, 10, 1, False, False, 50, 75, True, False, 0, 115 + bytes([0x99, 0x99, 0x99]), None, False), 116 + ("frame_counts", 22, 42, 3, True, True, 137, 42, False, False, 3, 117 + bytes([0x01, 0x02, 0x03, 0x04, 0x05]), 118 + bytes([0x01, 0x04, 0x00, 0x2A]), False), 119 + ] 120 + 121 + 122 + def main(): 123 + trace_dir = sys.argv[1] if len(sys.argv) > 1 else \ 124 + os.path.join(os.path.dirname(__file__), "..", "traces") 125 + os.makedirs(trace_dir, exist_ok=True) 126 + path = os.path.join(trace_dir, "vectors.csv") 127 + 128 + with open(path, "w") as f: 129 + f.write("name,frame_len,scid,vcid,ocf_flag," 130 + "mcfc,vcfc,sec_hdr,sync_flag,pkt_order," 131 + "seg_len_id,first_hdr_ptr,data_hex," 132 + "ocf_hex,expect_ocf,expect_fecf,frame_hex\n") 133 + 134 + for v in VECTORS: 135 + (name, frame_len, scid, vcid, ocf_present, fecf_present, 136 + mcfc, vcfc, sync_flag, pkt_order, seg_len_id, 137 + user_data, ocf_bytes, idle) = v 138 + 139 + frame, fhp, data_zone, sec_hdr = build_frame( 140 + frame_len, scid, vcid, ocf_present, fecf_present, 141 + mcfc, vcfc, sync_flag, pkt_order, seg_len_id, 142 + user_data, ocf_bytes, idle) 143 + 144 + ocf_hex = "" 145 + if ocf_present and ocf_bytes is not None: 146 + ocf_hex = ocf_bytes.hex() 147 + elif ocf_present: 148 + ocf_hex = "00000000" 149 + 150 + f.write(f"{name},{frame_len},{scid},{vcid}," 151 + f"{1 if ocf_present else 0}," 152 + f"{mcfc},{vcfc}," 153 + f"{1 if sec_hdr else 0}," 154 + f"{1 if sync_flag else 0}," 155 + f"{1 if pkt_order else 0}," 156 + f"{seg_len_id},{fhp}," 157 + f"{data_zone.hex()},{ocf_hex}," 158 + f"{1 if ocf_present else 0}," 159 + f"{1 if fecf_present else 0}," 160 + f"{frame.hex()}\n") 161 + 162 + print(f"Generated {len(VECTORS)} TM frame traces -> {path}") 163 + 164 + 165 + if __name__ == "__main__": 166 + main()
+215
test/interop/python/scripts/generate.java
··· 1 + ///usr/bin/env jbang "$0" "$@" ; exit $? 2 + //DEPS eu.dariolucia.ccsds:eu.dariolucia.ccsds.tmtc:1.0.6 3 + 4 + import eu.dariolucia.ccsds.tmtc.datalink.builder.TmTransferFrameBuilder; 5 + import eu.dariolucia.ccsds.tmtc.datalink.pdu.TmTransferFrame; 6 + 7 + import java.io.FileWriter; 8 + import java.io.PrintWriter; 9 + import java.nio.file.Path; 10 + import java.nio.file.Paths; 11 + 12 + /** 13 + * Generate TM Transfer Frame interop traces for ocaml-tm. 14 + * 15 + * Oracle: dariol83/ccsds (eu.dariolucia.ccsds.tmtc 1.0.6) 16 + * 17 + * Tests TM frame encoding/decoding per CCSDS 132.0-B-3. 18 + * 19 + * The TmTransferFrameBuilder.create(frameLength, secHeaderLen, ocfPresent, 20 + * fecfPresent) creates a builder for a fixed total frame length. The builder 21 + * auto-fills remaining data space with zeros. addData() adds user data bytes. 22 + * setIdle() fills the data zone with idle pattern and sets FHP to 0x7FF. 23 + */ 24 + public class generate { 25 + 26 + record Vector( 27 + String name, int frameLen, int scid, int vcid, 28 + boolean ocfPresent, boolean fecfPresent, 29 + int mcfc, int vcfc, boolean syncFlag, boolean pktOrder, 30 + int segLenId, byte[] userData, byte[] ocf, boolean idle 31 + ) {} 32 + 33 + static final Vector[] VECTORS = { 34 + // 1. Minimal: no OCF, no FECF, 16 bytes total (6 hdr + 10 data) 35 + new Vector("minimal", 16, 0, 0, 36 + false, false, 37 + 0, 0, false, false, 3, 38 + new byte[]{0x00, 0x01, 0x02, 0x03}, null, false), 39 + 40 + // 2. With OCF only, 20 bytes (6 hdr + 10 data + 4 OCF) 41 + new Vector("with_ocf", 20, 42, 3, 42 + true, false, 43 + 10, 20, false, false, 3, 44 + new byte[]{(byte)0xAA, (byte)0xBB, (byte)0xCC, (byte)0xDD}, 45 + new byte[]{0x01, 0x04, 0x00, 0x2A}, false), 46 + 47 + // 3. With FECF only, 18 bytes (6 hdr + 10 data + 2 FECF) 48 + new Vector("with_fecf", 18, 100, 2, 49 + false, true, 50 + 5, 99, false, false, 3, 51 + new byte[]{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte)0x88}, 52 + null, false), 53 + 54 + // 4. With OCF and FECF, 22 bytes (6 hdr + 10 data + 4 OCF + 2 FECF) 55 + new Vector("with_ocf_and_fecf", 22, 500, 5, 56 + true, true, 57 + 200, 150, false, false, 3, 58 + new byte[]{(byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF}, 59 + new byte[]{(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE}, false), 60 + 61 + // 5. Various SCID/VCID values, no OCF/FECF 62 + new Vector("various_ids", 20, 512, 6, 63 + false, false, 64 + 128, 64, false, false, 3, 65 + new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 66 + null, false), 67 + 68 + // 6. Sync flag set 69 + new Vector("sync_flag", 16, 77, 4, 70 + false, false, 71 + 100, 200, true, false, 3, 72 + new byte[]{0x42, 0x42, 0x42, 0x42}, null, false), 73 + 74 + // 7. Packet order flag set 75 + new Vector("pkt_order_flag", 16, 10, 1, 76 + false, false, 77 + 50, 75, false, true, 3, 78 + new byte[]{(byte)0x99, (byte)0x99}, null, false), 79 + 80 + // 8. Max SCID/VCID, all flags, OCF+FECF 81 + new Vector("max_scid_vcid", 22, 1023, 7, 82 + true, true, 83 + 255, 255, true, true, 0, 84 + new byte[]{(byte)0xAB, (byte)0xCD, (byte)0xEF, 0x01}, 85 + new byte[]{0x00, 0x00, 0x00, 0x00}, false), 86 + 87 + // 9. Idle frame (FHP=0x7FF, all-ones data) 88 + new Vector("idle_frame", 20, 1023, 7, 89 + false, false, 90 + 255, 255, false, false, 3, 91 + null, null, true), 92 + 93 + // 10. Large frame, 200 bytes total 94 + new Vector("large_frame", 200, 300, 2, 95 + true, true, 96 + 1, 1, false, false, 3, 97 + new byte[64], // 64 zero bytes of user data 98 + new byte[]{(byte)0xAB, (byte)0xCD, 0x12, 0x34}, false), 99 + 100 + // 11. Seg len zero 101 + new Vector("seg_len_zero", 16, 10, 1, 102 + false, false, 103 + 50, 75, true, false, 0, 104 + new byte[]{(byte)0x99, (byte)0x99, (byte)0x99}, 105 + null, false), 106 + 107 + // 12. Different frame counts 108 + new Vector("frame_counts", 22, 42, 3, 109 + true, true, 110 + 137, 42, false, false, 3, 111 + new byte[]{0x01, 0x02, 0x03, 0x04, 0x05}, 112 + new byte[]{0x01, 0x04, 0x00, 0x2A}, false), 113 + }; 114 + 115 + public static void main(String[] args) throws Exception { 116 + if (args.length != 1) { 117 + System.err.println("Usage: generate.java <trace-dir>"); 118 + System.exit(1); 119 + } 120 + Path traceDir = Paths.get(args[0]); 121 + traceDir.toFile().mkdirs(); 122 + 123 + try (PrintWriter pw = new PrintWriter(new FileWriter( 124 + traceDir.resolve("vectors.csv").toFile()))) { 125 + pw.println("name,frame_len,scid,vcid,ocf_flag," 126 + + "mcfc,vcfc,sec_hdr,sync_flag,pkt_order," 127 + + "seg_len_id,first_hdr_ptr,data_hex," 128 + + "ocf_hex,expect_ocf,expect_fecf,frame_hex"); 129 + 130 + for (Vector v : VECTORS) { 131 + TmTransferFrameBuilder builder = TmTransferFrameBuilder.create( 132 + v.frameLen, 0, v.ocfPresent, v.fecfPresent); 133 + 134 + builder.setSpacecraftId(v.scid); 135 + builder.setVirtualChannelId(v.vcid); 136 + builder.setMasterChannelFrameCount(v.mcfc); 137 + builder.setVirtualChannelFrameCount(v.vcfc); 138 + builder.setSynchronisationFlag(v.syncFlag); 139 + builder.setPacketOrderFlag(v.pktOrder); 140 + builder.setSegmentLengthIdentifier(v.segLenId); 141 + 142 + if (v.idle) { 143 + builder.setIdle(); 144 + } else { 145 + if (v.userData != null) { 146 + builder.addData(v.userData); 147 + } 148 + } 149 + 150 + if (v.ocfPresent && v.ocf != null) { 151 + builder.setOcf(v.ocf); 152 + } 153 + 154 + TmTransferFrame frame = builder.build(); 155 + byte[] frameBytes = frame.getFrame(); 156 + 157 + // Extract fields from the built frame for verification 158 + int scid = frame.getSpacecraftId(); 159 + int vcid = frame.getVirtualChannelId(); 160 + int mcfc = frame.getMasterChannelFrameCount(); 161 + int vcfc = frame.getVirtualChannelFrameCount(); 162 + boolean secHdr = frame.isSecondaryHeaderFlag(); 163 + boolean syncFlag = frame.isSynchronisationFlag(); 164 + boolean pktOrder = frame.isPacketOrderFlag(); 165 + int segLenId = frame.getSegmentLengthIdentifier(); 166 + int fhp = frame.getFirstHeaderPointer(); 167 + boolean ocfPresent = frame.isOcfPresent(); 168 + boolean fecfPresent = frame.isFecfPresent(); 169 + 170 + // Extract data zone: starts at offset 6, length depends on 171 + // frame_len - 6 - (4 if OCF) - (2 if FECF) 172 + int dataLen = v.frameLen - 6 173 + - (ocfPresent ? 4 : 0) 174 + - (fecfPresent ? 2 : 0); 175 + byte[] dataBytes = new byte[dataLen]; 176 + System.arraycopy(frameBytes, 6, dataBytes, 0, dataLen); 177 + 178 + // Extract OCF bytes if present 179 + String ocfHex = ""; 180 + if (ocfPresent) { 181 + byte[] ocfBytes = frame.getOcf(); 182 + ocfHex = bytesToHex(ocfBytes); 183 + } 184 + 185 + pw.printf("%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%d,%d,%s%n", 186 + v.name, 187 + v.frameLen, 188 + scid, 189 + vcid, 190 + ocfPresent ? 1 : 0, 191 + mcfc, 192 + vcfc, 193 + secHdr ? 1 : 0, 194 + syncFlag ? 1 : 0, 195 + pktOrder ? 1 : 0, 196 + segLenId, 197 + fhp, 198 + bytesToHex(dataBytes), 199 + ocfHex, 200 + ocfPresent ? 1 : 0, 201 + fecfPresent ? 1 : 0, 202 + bytesToHex(frameBytes)); 203 + } 204 + } 205 + System.out.println("Wrote " + traceDir.resolve("vectors.csv")); 206 + } 207 + 208 + static String bytesToHex(byte[] bytes) { 209 + StringBuilder sb = new StringBuilder(); 210 + for (byte b : bytes) { 211 + sb.append(String.format("%02x", b & 0xFF)); 212 + } 213 + return sb.toString(); 214 + } 215 + }
+7
test/interop/python/scripts/generate.sh
··· 1 + #!/bin/bash 2 + set -euo pipefail 3 + command -v jbang >/dev/null || { echo "jbang not on PATH" >&2; exit 1; } 4 + SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" 5 + TRACE_DIR="$(cd "$SCRIPT_DIR/../traces" && pwd)" 6 + cd "$SCRIPT_DIR" 7 + jbang generate.java "$TRACE_DIR"
+35 -27
test/interop/python/test.ml
··· 32 32 Csvt.( 33 33 Row.( 34 34 obj 35 - (fun name version scid vcid ocf_flag mcfc vcfc sec_hdr sync_flag 36 - pkt_order seg_len_id first_hdr_ptr data_hex ocf_hex expect_ocf 37 - expect_fecf frame_hex -> 35 + (fun 36 + name 37 + version 38 + scid 39 + vcid 40 + ocf_flag 41 + mcfc 42 + vcfc 43 + sec_hdr 44 + sync_flag 45 + pkt_order 46 + seg_len_id 47 + first_hdr_ptr 48 + data_hex 49 + ocf_hex 50 + expect_ocf 51 + expect_fecf 52 + frame_hex 53 + -> 38 54 { 39 55 name; 40 56 version; ··· 108 124 Tm.decode ~frame_len ~expect_ocf:v.expect_ocf ~expect_fecf:v.expect_fecf 109 125 frame_bytes 110 126 with 111 - | Error e -> 112 - Alcotest.failf "%s: decode failed: %a" v.name Tm.pp_error e 127 + | Error e -> Alcotest.failf "%s: decode failed: %a" v.name Tm.pp_error e 113 128 | Ok frame -> 114 129 let h = frame.header in 115 130 Alcotest.(check int) (v.name ^ ": version") v.version h.version; ··· 121 136 Alcotest.(check int) (v.name ^ ": mcfc") v.mcfc h.mcfc; 122 137 Alcotest.(check int) (v.name ^ ": vcfc") v.vcfc h.vcfc; 123 138 Alcotest.(check bool) (v.name ^ ": sec_hdr") v.sec_hdr h.sec_hdr; 124 - Alcotest.(check bool) 125 - (v.name ^ ": sync_flag") v.sync_flag h.sync_flag; 126 - Alcotest.(check bool) 127 - (v.name ^ ": pkt_order") v.pkt_order h.pkt_order; 139 + Alcotest.(check bool) (v.name ^ ": sync_flag") v.sync_flag h.sync_flag; 140 + Alcotest.(check bool) (v.name ^ ": pkt_order") v.pkt_order h.pkt_order; 128 141 Alcotest.(check int) 129 142 (v.name ^ ": seg_len_id") v.seg_len_id h.seg_len_id; 130 143 Alcotest.(check int) 131 - (v.name ^ ": first_hdr_ptr") v.first_hdr_ptr h.first_hdr_ptr; 144 + (v.name ^ ": first_hdr_ptr") 145 + v.first_hdr_ptr h.first_hdr_ptr; 132 146 (* Verify data field matches *) 133 147 let expected_data = hex_to_string v.data_hex in 134 - Alcotest.(check string) 135 - (v.name ^ ": data") expected_data frame.data; 148 + Alcotest.(check string) (v.name ^ ": data") expected_data frame.data; 136 149 (* Verify OCF presence *) 137 150 Alcotest.(check bool) 138 - (v.name ^ ": ocf present") v.expect_ocf 139 - (Option.is_some frame.ocf); 151 + (v.name ^ ": ocf present") v.expect_ocf (Option.is_some frame.ocf); 140 152 (* Verify FECF presence *) 141 153 Alcotest.(check bool) 142 - (v.name ^ ": fecf present") v.expect_fecf 154 + (v.name ^ ": fecf present") 155 + v.expect_fecf 143 156 (Option.is_some frame.fecf)) 144 157 vectors 145 158 146 159 let parse_ocf_hex s = 147 - if String.length s = 0 then None 148 - else Some (int_of_string ("0x" ^ s)) 160 + if String.length s = 0 then None else Some (int_of_string ("0x" ^ s)) 149 161 150 162 let test_encode vectors () = 151 163 List.iter ··· 156 168 let ocf = parse_ocf_hex v.ocf_hex in 157 169 let frame = 158 170 Tm.v ~version:v.version ~ocf_flag:v.ocf_flag ~sec_hdr:v.sec_hdr 159 - ~sync_flag:v.sync_flag ~pkt_order:v.pkt_order 160 - ~seg_len_id:v.seg_len_id ~first_hdr_ptr:v.first_hdr_ptr ?ocf ~scid 161 - ~vcid ~mcfc:v.mcfc ~vcfc:v.vcfc data 171 + ~sync_flag:v.sync_flag ~pkt_order:v.pkt_order ~seg_len_id:v.seg_len_id 172 + ~first_hdr_ptr:v.first_hdr_ptr ?ocf ~scid ~vcid ~mcfc:v.mcfc 173 + ~vcfc:v.vcfc data 162 174 in 163 175 let encoded = Tm.encode ~with_fecf:v.expect_fecf frame in 164 176 let our_hex = string_to_hex encoded in ··· 174 186 Tm.decode ~frame_len ~expect_ocf:v.expect_ocf ~expect_fecf:v.expect_fecf 175 187 frame_bytes 176 188 with 177 - | Error e -> 178 - Alcotest.failf "%s: decode failed: %a" v.name Tm.pp_error e 189 + | Error e -> Alcotest.failf "%s: decode failed: %a" v.name Tm.pp_error e 179 190 | Ok frame -> 180 - let re_encoded = 181 - Tm.encode ~with_fecf:v.expect_fecf frame 182 - in 191 + let re_encoded = Tm.encode ~with_fecf:v.expect_fecf frame in 183 192 let re_hex = string_to_hex re_encoded in 184 - Alcotest.(check string) 185 - (v.name ^ ": roundtrip") v.frame_hex re_hex) 193 + Alcotest.(check string) (v.name ^ ": roundtrip") v.frame_hex re_hex) 186 194 vectors 187 195 188 196 let () =
+9 -3
test/test_tm.ml
··· 218 218 f.pf_version f.pf_scid f.pf_vcid f.pf_ocf_flag f.pf_mcfc f.pf_vcfc 219 219 f.pf_sec_hdr f.pf_sync_flag f.pf_pkt_order f.pf_seg_len_id 220 220 f.pf_first_hdr_ptr (String.length f.pf_data) 221 - (match f.pf_ocf with None -> "None" | Some v -> Printf.sprintf "0x%08x" v) 222 - (match f.pf_fecf with None -> "None" | Some v -> Printf.sprintf "0x%04x" v)) 221 + (match f.pf_ocf with 222 + | None -> "None" 223 + | Some v -> Printf.sprintf "0x%08x" v) 224 + (match f.pf_fecf with 225 + | None -> "None" 226 + | Some v -> Printf.sprintf "0x%04x" v)) 223 227 Tm.equal_packed_frame 224 228 225 229 let test_packed_frame_roundtrip () = ··· 271 275 | Ok packed_f -> 272 276 Alcotest.(check int) "data length" 1103 (String.length packed_f.pf_data); 273 277 Alcotest.(check (option int)) "ocf" (Some 0x12345678) packed_f.pf_ocf; 274 - Alcotest.(check bool) "fecf present" true (Option.is_some packed_f.pf_fecf) 278 + Alcotest.(check bool) 279 + "fecf present" true 280 + (Option.is_some packed_f.pf_fecf) 275 281 276 282 let suite = 277 283 ( "tm",