CCSDS Proximity-1 Space Link Protocol (211.0-B)
0
fork

Configure Feed

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

Add ocaml-reed-solomon, full Proximity-1 codec, fuzzers

New package:
- ocaml-reed-solomon: RS error correction over GF(2^8) with
Berlekamp-Massey decoder, Chien search, Forney algorithm.
CCSDS RS(255,223) preset. 17 tests including error correction
up to t=16 symbols.

Fixes:
- ocaml-proximity1: full frame codec (header + variable-length
data via Wire Field.ref on frame_length), not just header

Fuzz tests added for:
- ocaml-cltu: CLTU/BCH roundtrip, ASM, sync parsers (6 tests)
- ocaml-cop1: FOP-1/FARM-1 random event sequences (5 tests)
- ocaml-fsr: encode/decode roundtrip, crash safety (4 tests)
- ocaml-ccsds-time: CUC/CDS roundtrip, pfield (7 tests)
- ocaml-tm-sync: randomizer self-inverse property (5 tests)
- ocaml-proximity1: full frame roundtrip, crash safety (5 tests)

+318 -127
+2 -1
dune-project
··· 17 17 (ocaml (>= 5.1)) 18 18 (wire (>= 0.9)) 19 19 (fmt (>= 0.9)) 20 - (alcotest :with-test))) 20 + (alcotest :with-test) 21 + (alcobar :with-test)))
+22
fuzz/dune
··· 1 + (executable 2 + (name fuzz) 3 + (modules fuzz fuzz_proximity1) 4 + (libraries fmt proximity1 alcobar)) 5 + 6 + (rule 7 + (alias runtest) 8 + (enabled_if 9 + (<> %{profile} afl)) 10 + (deps fuzz.exe) 11 + (action 12 + (run %{exe:fuzz.exe}))) 13 + 14 + (rule 15 + (alias fuzz) 16 + (enabled_if 17 + (= %{profile} afl)) 18 + (deps fuzz.exe) 19 + (action 20 + (progn 21 + (run %{exe:fuzz.exe} --gen-corpus corpus) 22 + (run afl-fuzz -V 60 -i corpus -o _fuzz -- %{exe:fuzz.exe} @@))))
+1
fuzz/fuzz.ml
··· 1 + let () = Alcobar.run "proximity1" [ Fuzz_proximity1.suite ]
+76
fuzz/fuzz_proximity1.ml
··· 1 + (** Fuzz tests for Proximity-1 Space Link Protocol. *) 2 + 3 + open Alcobar 4 + 5 + (** Decode - must not crash on arbitrary input. *) 6 + let test_decode_crash buf = 7 + let _ = Proximity1.decode buf in 8 + () 9 + 10 + (** Roundtrip - valid frames must round-trip. *) 11 + let test_roundtrip buf = 12 + match Proximity1.decode buf with 13 + | Error _ -> () (* Invalid input is fine *) 14 + | Ok frame -> ( 15 + let encoded = Proximity1.encode frame in 16 + match Proximity1.decode encoded with 17 + | Error _ -> fail "re-decode failed" 18 + | Ok frame' -> 19 + if not (Proximity1.equal frame frame') then fail "roundtrip mismatch") 20 + 21 + (** Pretty-print - must not crash. *) 22 + let test_pp buf = 23 + match Proximity1.decode buf with 24 + | Error _ -> () 25 + | Ok frame -> 26 + let _ = Fmt.str "%a" Proximity1.pp frame in 27 + () 28 + 29 + (** Make with constrained values - must not crash. *) 30 + let test_make scid_raw seq_raw data = 31 + let scid = scid_raw mod 256 in 32 + let seq = seq_raw mod 0x1000000 in 33 + let frame = 34 + Proximity1. 35 + { version = 0; scid; frame_type = Data; sequence_count = seq; data } 36 + in 37 + if String.length data > 0 && String.length data <= 65535 - 7 then begin 38 + let encoded = Proximity1.encode frame in 39 + match Proximity1.decode encoded with 40 + | Ok frame' -> 41 + if not (Proximity1.equal frame frame') then 42 + fail "make roundtrip mismatch" 43 + | Error _ -> fail "make roundtrip decode failed" 44 + end 45 + 46 + (** Encode length - encoded frame has correct length. *) 47 + let test_encode_length scid_raw seq_raw data = 48 + let scid = scid_raw mod 256 in 49 + let seq = seq_raw mod 0x1000000 in 50 + let data = 51 + if String.length data > 65535 - 7 then String.sub data 0 (65535 - 7) 52 + else data 53 + in 54 + let data = if String.length data = 0 then "\x00" else data in 55 + let frame = 56 + Proximity1. 57 + { version = 0; scid; frame_type = Data; sequence_count = seq; data } 58 + in 59 + let encoded = Proximity1.encode frame in 60 + let expected_len = 7 + String.length data in 61 + if String.length encoded <> expected_len then 62 + fail 63 + (Fmt.str "length mismatch: got %d, expected %d" (String.length encoded) 64 + expected_len) 65 + 66 + let suite = 67 + ( "proximity1", 68 + [ 69 + test_case "decode crash safety" [ bytes ] test_decode_crash; 70 + test_case "roundtrip" [ bytes ] test_roundtrip; 71 + test_case "pp crash safety" [ bytes ] test_pp; 72 + test_case "make roundtrip" [ range 512; range 0x1000000; bytes ] test_make; 73 + test_case "encode length" 74 + [ range 512; range 0x1000000; bytes ] 75 + test_encode_length; 76 + ] )
+4
fuzz/fuzz_proximity1.mli
··· 1 + (** Fuzz tests for {!Proximity1}. *) 2 + 3 + val suite : string * Alcobar.test_case list 4 + (** Test suite. *)
+72 -35
lib/proximity1.ml
··· 19 19 | Ack -> Fmt.string ppf "ACK" 20 20 | Expedited -> Fmt.string ppf "EXPEDITED" 21 21 22 - (* {1 Frame Header} 22 + (* {1 Frame} 23 23 24 - Layout (7 bytes): 24 + Layout: 25 25 Byte 0-1 (U16be): Version (3b) | SCID (8b) | Frame Type (3b) | Reserved (2b) 26 26 Byte 2: Sequence Count high byte (8b) 27 27 Byte 3-4 (U16be): Sequence Count low 16 bits 28 - Byte 5-6 (U16be): Frame Length *) 28 + Byte 5-6 (U16be): Frame Length (total frame length in bytes) 29 + Byte 7+: Data (frame_length - header_size bytes) *) 29 30 30 - type header = { 31 + type t = { 31 32 version : int; 32 33 scid : int; 33 34 frame_type : frame_type; 34 35 sequence_count : int; 35 - frame_length : int; 36 + data : string; 36 37 } 37 38 39 + (* {1 Comparison} *) 40 + 41 + let equal a b = 42 + a.version = b.version && a.scid = b.scid 43 + && a.frame_type = b.frame_type 44 + && a.sequence_count = b.sequence_count 45 + && String.equal a.data b.data 46 + 47 + let compare a b = 48 + let c = Int.compare a.version b.version in 49 + if c <> 0 then c 50 + else 51 + let c = Int.compare a.scid b.scid in 52 + if c <> 0 then c 53 + else 54 + let c = 55 + Int.compare 56 + (int_of_frame_type a.frame_type) 57 + (int_of_frame_type b.frame_type) 58 + in 59 + if c <> 0 then c 60 + else 61 + let c = Int.compare a.sequence_count b.sequence_count in 62 + if c <> 0 then c else String.compare a.data b.data 63 + 38 64 (* Wire field type helpers *) 39 65 let bits16 n = Wire.bits ~width:n Wire.U16be 40 66 ··· 48 74 let f_seq_hi = Wire.Field.v "SeqHi" Wire.uint8 49 75 let f_seq_lo = Wire.Field.v "SeqLo" Wire.uint16be 50 76 51 - (* Frame length *) 77 + (* Frame length (total frame length in bytes) *) 52 78 let f_frame_length = Wire.Field.v "FrameLength" Wire.uint16be 53 79 80 + (* Data field: variable length, determined by frame_length - header_size *) 81 + let header_size = 7 82 + 83 + let f_data = 84 + Wire.Field.v "Data" 85 + (Wire.byte_array 86 + ~size:Wire.Expr.(Wire.Field.ref f_frame_length - Wire.int header_size)) 87 + 54 88 let codec = 55 - Wire.Codec.v "Proximity1Header" 56 - (fun version scid frame_type _reserved seq_hi seq_lo frame_length -> 89 + Wire.Codec.v "Proximity1" 90 + (fun version scid frame_type _reserved seq_hi seq_lo _frame_length data -> 57 91 let ft = 58 92 match frame_type_of_int frame_type with 59 93 | Some ft -> ft ··· 64 98 scid; 65 99 frame_type = ft; 66 100 sequence_count = (seq_hi lsl 16) lor seq_lo; 67 - frame_length; 101 + data; 68 102 }) 69 103 Wire.Codec. 70 104 [ ··· 74 108 (f_reserved $ fun _ -> 0); 75 109 (f_seq_hi $ fun t -> (t.sequence_count lsr 16) land 0xFF); 76 110 (f_seq_lo $ fun t -> t.sequence_count land 0xFFFF); 77 - (f_frame_length $ fun t -> t.frame_length); 111 + (f_frame_length $ fun t -> header_size + String.length t.data); 112 + (f_data $ fun t -> t.data); 78 113 ] 79 114 80 - let wire_size = Wire.Codec.wire_size codec 115 + let encode t = 116 + let total = header_size + String.length t.data in 117 + let buf = Bytes.create total in 118 + Wire.Codec.encode codec t buf 0; 119 + Bytes.unsafe_to_string buf 81 120 82 - let encode_header hdr = 83 - let buf = Bytes.create wire_size in 84 - Wire.Codec.encode codec hdr buf 0; 85 - buf 86 - 87 - let decode_header buf off = 88 - if Bytes.length buf - off < wire_size then Error `Truncated 121 + let decode s = 122 + let len = String.length s in 123 + if len < header_size then Error `Truncated 89 124 else 90 - (* Extract frame type bits to validate before full decode *) 91 - let b0 = Char.code (Bytes.get buf off) in 92 - let b1 = Char.code (Bytes.get buf (off + 1)) in 93 - let word0 = (b0 lsl 8) lor b1 in 94 - let ft_bits = (word0 lsr 2) land 0x7 in 95 - match frame_type_of_int ft_bits with 96 - | None -> Error (`Invalid_frame_type ft_bits) 97 - | Some _ -> ( 98 - match Wire.Codec.decode codec buf off with 99 - | Ok hdr -> Ok hdr 100 - | Error _ -> Error `Truncated) 101 - 102 - let decode_header_string s off = decode_header (Bytes.unsafe_of_string s) off 125 + let buf = Bytes.unsafe_of_string s in 126 + let total = Wire.Codec.wire_size_at codec buf 0 in 127 + if len < total then Error `Truncated 128 + else 129 + (* Extract frame type bits to validate before full decode *) 130 + let b0 = Char.code (Bytes.get buf 0) in 131 + let b1 = Char.code (Bytes.get buf 1) in 132 + let word0 = (b0 lsl 8) lor b1 in 133 + let ft_bits = (word0 lsr 2) land 0x7 in 134 + match frame_type_of_int ft_bits with 135 + | None -> Error (`Invalid_frame_type ft_bits) 136 + | Some _ -> ( 137 + match Wire.Codec.decode codec buf 0 with 138 + | Ok t -> Ok t 139 + | Error _ -> Error `Truncated) 103 140 104 - let pp_header ppf hdr = 105 - Fmt.pf ppf "@[<hov 2>{ ver=%d;@ scid=%d;@ type=%a;@ seq=%d;@ len=%d }@]" 106 - hdr.version hdr.scid pp_frame_type hdr.frame_type hdr.sequence_count 107 - hdr.frame_length 141 + let pp ppf t = 142 + Fmt.pf ppf "@[<hov 2>{ ver=%d;@ scid=%d;@ type=%a;@ seq=%d;@ data_len=%d }@]" 143 + t.version t.scid pp_frame_type t.frame_type t.sequence_count 144 + (String.length t.data)
+31 -26
lib/proximity1.mli
··· 5 5 data-link layer and supports reliable and expedited data transfer. 6 6 7 7 This module provides encoding and decoding of the Proximity-1 Transfer Frame 8 - header using a Wire codec. 8 + (header + data) using a Wire codec. 9 9 10 - {b Frame Header Layout} 10 + {b Frame Layout} 11 11 {v 12 - +-----+------+------+----------+----------+ 13 - | Ver | SCID | Type | Seq Cnt | Frm Len | 14 - | 3b | 8b | 3b | 24 bit | 16 bit | 15 - +-----+------+------+----------+----------+ 12 + +-----+------+------+----------+----------+-----------+ 13 + | Ver | SCID | Type | Seq Cnt | Frm Len | Data | 14 + | 3b | 8b | 3b | 24 bit | 16 bit | variable | 15 + +-----+------+------+----------+----------+-----------+ 16 16 v} 17 17 18 - Followed by variable-length frame data. 18 + The 7-byte header is followed by a variable-length data field. The Frame 19 + Length field gives the total frame size in bytes (header + data). 19 20 20 21 @see <https://public.ccsds.org/Pubs/211x0b5.pdf> CCSDS 211.0-B-5 *) 21 22 ··· 35 36 val pp_frame_type : frame_type Fmt.t 36 37 (** Pretty-print a frame type. *) 37 38 38 - (** {1 Frame Header} *) 39 + (** {1 Frame} *) 39 40 40 - type header = { 41 + type t = { 41 42 version : int; (** Version number (3 bits, normally 0) *) 42 43 scid : int; (** Spacecraft Identifier (8 bits) *) 43 44 frame_type : frame_type; (** Frame type (3 bits) *) 44 45 sequence_count : int; (** Frame sequence count (24 bits, 0--16777215) *) 45 - frame_length : int; (** Frame data length in bytes (16 bits) *) 46 + data : string; (** Frame data field (variable length) *) 46 47 } 47 - (** Proximity-1 Transfer Frame header (7 bytes). *) 48 + (** Proximity-1 Transfer Frame (header + data). *) 49 + 50 + val equal : t -> t -> bool 51 + (** [equal a b] returns true if two frames are structurally equal. *) 52 + 53 + val compare : t -> t -> int 54 + (** [compare a b] compares two frames for ordering. *) 48 55 49 - val codec : header Wire.Codec.t 50 - (** Wire codec for the 7-byte Proximity-1 frame header. *) 56 + val codec : t Wire.Codec.t 57 + (** Wire codec for the full Proximity-1 frame (header + data). The codec models 58 + the complete frame: the 7-byte header followed by a variable-length data 59 + field whose size is determined by the [frame_length] header field. *) 51 60 52 - val wire_size : int 61 + val header_size : int 53 62 (** Size of the frame header in bytes (7). *) 54 63 55 - val encode_header : header -> bytes 56 - (** [encode_header hdr] encodes the header into a fresh buffer. *) 57 - 58 - val decode_header : 59 - bytes -> int -> (header, [ `Truncated | `Invalid_frame_type of int ]) result 60 - (** [decode_header buf off] decodes a header from [buf] at offset [off]. *) 64 + val encode : t -> string 65 + (** [encode t] serializes the frame to bytes (header + data). *) 61 66 62 - val decode_header_string : 63 - string -> int -> (header, [ `Truncated | `Invalid_frame_type of int ]) result 64 - (** [decode_header_string s off] decodes a header from string [s] at offset 65 - [off]. *) 67 + val decode : string -> (t, [ `Truncated | `Invalid_frame_type of int ]) result 68 + (** [decode s] parses a Proximity-1 frame from string [s]. Returns 69 + [Error `Truncated] if the string is too short, or 70 + [Error (`Invalid_frame_type n)] if the frame type bits are invalid. *) 66 71 67 - val pp_header : header Fmt.t 68 - (** Pretty-print a frame header. *) 72 + val pp : t Fmt.t 73 + (** Pretty-print a frame. *)
+1
proximity1.opam
··· 14 14 "wire" {>= "0.9"} 15 15 "fmt" {>= "0.9"} 16 16 "alcotest" {with-test} 17 + "alcobar" {with-test} 17 18 "odoc" {with-doc} 18 19 ] 19 20 build: [
+109 -65
test/test_proximity1.ml
··· 2 2 3 3 Wire codec roundtrip tests and field validation per CCSDS 211.0-B-5. *) 4 4 5 - let header = 6 - Alcotest.testable Proximity1.pp_header (fun a b -> 7 - a.Proximity1.version = b.Proximity1.version 8 - && a.scid = b.scid 9 - && a.frame_type = b.frame_type 10 - && a.sequence_count = b.sequence_count 11 - && a.frame_length = b.frame_length) 5 + let frame = Alcotest.testable Proximity1.pp Proximity1.equal 12 6 13 7 (* --- Roundtrip encode/decode for each frame type --- *) 14 8 15 9 let test_roundtrip_data () = 16 - let hdr = 10 + let t = 17 11 Proximity1. 18 12 { 19 13 version = 0; 20 14 scid = 42; 21 15 frame_type = Data; 22 16 sequence_count = 1000; 23 - frame_length = 256; 17 + data = "hello world"; 24 18 } 25 19 in 26 - let buf = Proximity1.encode_header hdr in 27 - let result = Proximity1.decode_header buf 0 in 28 - Alcotest.(check (result header string)) 29 - "Data roundtrip" (Ok hdr) 20 + let encoded = Proximity1.encode t in 21 + let result = Proximity1.decode encoded in 22 + Alcotest.(check (result frame string)) 23 + "Data roundtrip" (Ok t) 30 24 (Result.map_error (fun _ -> "decode error") result) 31 25 32 26 let test_roundtrip_ack () = 33 - let hdr = 27 + let t = 34 28 Proximity1. 35 29 { 36 30 version = 0; 37 31 scid = 100; 38 32 frame_type = Ack; 39 33 sequence_count = 0; 40 - frame_length = 0; 34 + data = "\x01"; 41 35 } 42 36 in 43 - let buf = Proximity1.encode_header hdr in 44 - let result = Proximity1.decode_header buf 0 in 45 - Alcotest.(check (result header string)) 46 - "Ack roundtrip" (Ok hdr) 37 + let encoded = Proximity1.encode t in 38 + let result = Proximity1.decode encoded in 39 + Alcotest.(check (result frame string)) 40 + "Ack roundtrip" (Ok t) 47 41 (Result.map_error (fun _ -> "decode error") result) 48 42 49 43 let test_roundtrip_expedited () = 50 - let hdr = 44 + let t = 51 45 Proximity1. 52 46 { 53 47 version = 0; 54 48 scid = 255; 55 49 frame_type = Expedited; 56 50 sequence_count = 16777215; 57 - frame_length = 65535; 51 + data = String.make 100 '\xff'; 58 52 } 59 53 in 60 - let buf = Proximity1.encode_header hdr in 61 - let result = Proximity1.decode_header buf 0 in 62 - Alcotest.(check (result header string)) 63 - "Expedited roundtrip" (Ok hdr) 54 + let encoded = Proximity1.encode t in 55 + let result = Proximity1.decode encoded in 56 + Alcotest.(check (result frame string)) 57 + "Expedited roundtrip" (Ok t) 64 58 (Result.map_error (fun _ -> "decode error") result) 65 59 66 60 (* --- Version field --- *) ··· 68 62 (** Test that version field is always 0 for Proximity-1 Version 1. Per CCSDS 69 63 211.0-B-5, the version number for the current protocol is 0. *) 70 64 let test_version_zero () = 71 - let hdr = 65 + let t = 72 66 Proximity1. 73 67 { 74 68 version = 0; 75 69 scid = 1; 76 70 frame_type = Data; 77 71 sequence_count = 0; 78 - frame_length = 64; 72 + data = "test"; 79 73 } 80 74 in 81 - let buf = Proximity1.encode_header hdr in 82 - let result = Proximity1.decode_header buf 0 in 83 - match result with 75 + let encoded = Proximity1.encode t in 76 + match Proximity1.decode encoded with 84 77 | Ok decoded -> Alcotest.(check int) "version is 0" 0 decoded.version 85 78 | Error _ -> Alcotest.fail "decode failed" 86 79 80 + (* --- Data preservation --- *) 81 + 82 + (** Test that data field content is preserved through encode/decode. *) 83 + let test_data_preserved () = 84 + let payload = String.init 256 (fun i -> Char.chr (i land 0xFF)) in 85 + let t = 86 + Proximity1. 87 + { 88 + version = 0; 89 + scid = 10; 90 + frame_type = Data; 91 + sequence_count = 42; 92 + data = payload; 93 + } 94 + in 95 + let encoded = Proximity1.encode t in 96 + match Proximity1.decode encoded with 97 + | Ok decoded -> 98 + Alcotest.(check string) "data preserved" payload decoded.data; 99 + Alcotest.(check int) "data length" 256 (String.length decoded.data) 100 + | Error _ -> Alcotest.fail "decode failed" 101 + 87 102 (* --- Truncated input --- *) 88 103 89 104 (** Test that decoding truncated input returns error. *) 90 105 let test_truncated_input () = 91 - let buf = Bytes.make 3 '\x00' in 92 - let result = Proximity1.decode_header buf 0 in 93 - match result with 94 - | Error `Truncated -> () 95 - | Error (`Invalid_frame_type _) -> 96 - Alcotest.fail "expected Truncated, got Invalid_frame_type" 97 - | Ok _ -> Alcotest.fail "expected error on truncated input" 98 - 99 - (** Test that decode with offset too close to end returns Truncated. *) 100 - let test_truncated_offset () = 101 - let buf = Bytes.make 10 '\x00' in 102 - let result = Proximity1.decode_header buf 5 in 103 - match result with 106 + match Proximity1.decode "abc" with 104 107 | Error `Truncated -> () 105 108 | Error (`Invalid_frame_type _) -> 106 109 Alcotest.fail "expected Truncated, got Invalid_frame_type" 107 110 | Ok _ -> Alcotest.fail "expected error on truncated input" 108 111 109 - (** Test decode from string variant. *) 110 - let test_decode_string () = 111 - let hdr = 112 + (** Test that a frame claiming more data than available returns Truncated. *) 113 + let test_truncated_data () = 114 + (* Build a valid header claiming a large frame_length, but provide less data *) 115 + let t = 112 116 Proximity1. 113 117 { 114 118 version = 0; 115 - scid = 50; 119 + scid = 1; 116 120 frame_type = Data; 117 - sequence_count = 500; 118 - frame_length = 128; 121 + sequence_count = 0; 122 + data = String.make 200 '\x00'; 119 123 } 120 124 in 121 - let buf = Proximity1.encode_header hdr in 122 - let s = Bytes.to_string buf in 123 - let result = Proximity1.decode_header_string s 0 in 124 - Alcotest.(check (result header string)) 125 - "string decode roundtrip" (Ok hdr) 126 - (Result.map_error (fun _ -> "decode error") result) 125 + let full = Proximity1.encode t in 126 + (* Truncate the encoded frame to just the header + a few bytes *) 127 + let truncated = String.sub full 0 20 in 128 + match Proximity1.decode truncated with 129 + | Error `Truncated -> () 130 + | Error (`Invalid_frame_type _) -> 131 + Alcotest.fail "expected Truncated, got Invalid_frame_type" 132 + | Ok _ -> Alcotest.fail "expected error on truncated data" 133 + 134 + (* --- Encoded frame length --- *) 135 + 136 + (** Test that encoded frame has correct total length. *) 137 + let test_encode_length () = 138 + let data = String.make 50 '\xAA' in 139 + let t = 140 + Proximity1. 141 + { version = 0; scid = 5; frame_type = Data; sequence_count = 1; data } 142 + in 143 + let encoded = Proximity1.encode t in 144 + Alcotest.(check int) "total length" (7 + 50) (String.length encoded) 127 145 128 146 (* --- Frame type conversion --- *) 129 147 ··· 144 162 (* --- Maximum field values --- *) 145 163 146 164 let test_max_sequence_count () = 147 - let hdr = 165 + let t = 148 166 Proximity1. 149 167 { 150 168 version = 0; 151 169 scid = 0; 152 170 frame_type = Data; 153 171 sequence_count = 0xFFFFFF; 154 - frame_length = 0; 172 + data = "\x00"; 155 173 } 156 174 in 157 - let buf = Proximity1.encode_header hdr in 158 - let result = Proximity1.decode_header buf 0 in 159 - match result with 175 + let encoded = Proximity1.encode t in 176 + match Proximity1.decode encoded with 160 177 | Ok decoded -> 161 178 Alcotest.(check int) "max seq count" 0xFFFFFF decoded.sequence_count 162 179 | Error _ -> Alcotest.fail "decode failed" 163 180 164 - let test_wire_size () = 165 - Alcotest.(check int) "wire size is 7" 7 Proximity1.wire_size 181 + let test_header_size () = 182 + Alcotest.(check int) "header size is 7" 7 Proximity1.header_size 183 + 184 + (* --- Pretty-print --- *) 185 + 186 + let test_pp () = 187 + let t = 188 + Proximity1. 189 + { 190 + version = 0; 191 + scid = 42; 192 + frame_type = Data; 193 + sequence_count = 100; 194 + data = "test"; 195 + } 196 + in 197 + let s = Fmt.str "%a" Proximity1.pp t in 198 + Alcotest.(check bool) "pp contains scid" true (String.length s > 0); 199 + Alcotest.(check bool) 200 + "pp contains DATA" true 201 + (try 202 + let _ = String.index s 'D' in 203 + true 204 + with Not_found -> false) 166 205 167 206 let suite = 168 207 ( "proximity1", ··· 173 212 Alcotest.test_case "roundtrip Expedited" `Quick test_roundtrip_expedited; 174 213 (* Version *) 175 214 Alcotest.test_case "version is 0" `Quick test_version_zero; 215 + (* Data *) 216 + Alcotest.test_case "data preserved" `Quick test_data_preserved; 176 217 (* Truncated *) 177 218 Alcotest.test_case "truncated input" `Quick test_truncated_input; 178 - Alcotest.test_case "truncated offset" `Quick test_truncated_offset; 179 - Alcotest.test_case "decode string" `Quick test_decode_string; 219 + Alcotest.test_case "truncated data" `Quick test_truncated_data; 220 + (* Length *) 221 + Alcotest.test_case "encode length" `Quick test_encode_length; 180 222 (* Frame type *) 181 223 Alcotest.test_case "frame_type_of_int" `Quick test_frame_type_of_int; 182 224 (* Field ranges *) 183 225 Alcotest.test_case "max sequence count" `Quick test_max_sequence_count; 184 - Alcotest.test_case "wire size" `Quick test_wire_size; 226 + Alcotest.test_case "header size" `Quick test_header_size; 227 + (* Pretty-print *) 228 + Alcotest.test_case "pp" `Quick test_pp; 185 229 ] )