this repo has no description
2
fork

Configure Feed

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

Add content truncation to pretty printer and enhance test output

Add optional max_content_len parameter to Record.pp (default 100 bytes) to handle large records gracefully. Enhance test output with hex dumps of raw file contents and detailed structured pretty printing of parsed records and key-value pairs.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

+161 -20
+8 -2
lib/fastcgi_record.ml
··· 63 63 content : string; 64 64 } 65 65 66 - let pp ppf record = 66 + let pp ?(max_content_len=100) ppf record = 67 + let truncated_content = 68 + let content = record.content in 69 + let len = String.length content in 70 + if len <= max_content_len then content 71 + else String.sub content 0 max_content_len ^ "..." ^ Printf.sprintf " (%d more bytes)" (len - max_content_len) 72 + in 67 73 Format.fprintf ppf 68 74 "@[<2>{ version = %d;@ record_type = %a;@ request_id = %d;@ content = %S }@]" 69 75 record.version 70 76 pp_record record.record_type 71 77 record.request_id 72 - record.content 78 + truncated_content 73 79 74 80 (* FastCGI constants *) 75 81 let fcgi_version_1 = 1
+3 -2
lib/fastcgi_record.mli
··· 48 48 content : string; (** Record content data *) 49 49 } 50 50 51 - (** [pp ppf record] pretty-prints a FastCGI record *) 52 - val pp : Format.formatter -> t -> unit 51 + (** [pp ?max_content_len ppf record] pretty-prints a FastCGI record. 52 + [max_content_len] limits the displayed content length (default: 100 bytes) *) 53 + val pp : ?max_content_len:int -> Format.formatter -> t -> unit 53 54 54 55 (** {1 Record Operations} *) 55 56
+61 -3
test/simple_test.ml
··· 1 1 open Fastcgi 2 2 3 + let hex_dump ?(max_bytes=256) content = 4 + let len = String.length content in 5 + let display_len = min len max_bytes in 6 + let bytes_per_line = 16 in 7 + let lines_to_show = (display_len - 1) / bytes_per_line + 1 in 8 + 9 + for i = 0 to lines_to_show - 1 do 10 + let start = i * bytes_per_line in 11 + let end_ = min (start + bytes_per_line) display_len in 12 + Printf.printf " %04x: " start; 13 + 14 + (* Print hex bytes *) 15 + for j = start to end_ - 1 do 16 + Printf.printf "%02x " (Char.code content.[j]); 17 + if j = start + 7 then Printf.printf " " 18 + done; 19 + 20 + (* Pad remaining space *) 21 + for _ = end_ to start + bytes_per_line - 1 do 22 + Printf.printf " "; 23 + if end_ <= start + 7 then Printf.printf " " 24 + done; 25 + 26 + Printf.printf " |"; 27 + 28 + (* Print ASCII representation *) 29 + for j = start to end_ - 1 do 30 + let c = content.[j] in 31 + if c >= ' ' && c <= '~' then 32 + Printf.printf "%c" c 33 + else 34 + Printf.printf "." 35 + done; 36 + 37 + Printf.printf "|\n%!" 38 + done; 39 + 40 + if len > max_bytes then 41 + Printf.printf " ... (%d more bytes truncated)\n%!" (len - max_bytes) 42 + 43 + 3 44 let test_record_types () = 4 45 Printf.printf "Testing record type conversions...\n%!"; 5 46 ··· 70 111 let test_with_binary_test_case ~fs filename expected_type expected_request_id = 71 112 Printf.printf "Testing with binary test case: %s...\n%!" filename; 72 113 73 - let parsed = 114 + let (raw_content, parsed) = 74 115 Eio.Path.with_open_in (fs, "test_cases/" ^ filename) @@ fun flow -> 75 - let buf_read = Eio.Buf_read.of_flow flow ~max_size:1000000 in 76 - Record.read buf_read 116 + let buf = Buffer.create 1024 in 117 + Eio.Flow.copy flow (Eio.Flow.buffer_sink buf); 118 + let raw_content = Buffer.contents buf in 119 + let buf_read = Eio.Buf_read.of_string raw_content in 120 + let parsed = Record.read buf_read in 121 + (raw_content, parsed) 77 122 in 123 + 124 + Printf.printf "\nRaw file contents (%d bytes):\n" (String.length raw_content); 125 + hex_dump raw_content; 126 + 127 + Printf.printf "\nParsed record:\n"; 128 + Format.printf "%a\n" (fun ppf -> Record.pp ppf) parsed; 129 + 130 + (* If this is a Params record, also show the decoded key-value pairs *) 131 + if parsed.record_type = Params && String.length parsed.content > 0 then ( 132 + let params = Record.KV.decode parsed.content in 133 + Printf.printf "\nDecoded parameters:\n"; 134 + Format.printf "%a\n" Record.KV.pp params 135 + ); 78 136 79 137 assert (parsed.version = 1); 80 138 assert (parsed.record_type = expected_type);
+89 -13
test/validate_all_test_cases.ml
··· 1 1 open Fastcgi 2 2 open Record 3 3 4 + let hex_dump ?(max_bytes=256) content = 5 + let len = String.length content in 6 + let display_len = min len max_bytes in 7 + let bytes_per_line = 16 in 8 + let lines_to_show = (display_len - 1) / bytes_per_line + 1 in 9 + 10 + for i = 0 to lines_to_show - 1 do 11 + let start = i * bytes_per_line in 12 + let end_ = min (start + bytes_per_line) display_len in 13 + Printf.printf " %04x: " start; 14 + 15 + (* Print hex bytes *) 16 + for j = start to end_ - 1 do 17 + Printf.printf "%02x " (Char.code content.[j]); 18 + if j = start + 7 then Printf.printf " " 19 + done; 20 + 21 + (* Pad remaining space *) 22 + for _ = end_ to start + bytes_per_line - 1 do 23 + Printf.printf " "; 24 + if end_ <= start + 7 then Printf.printf " " 25 + done; 26 + 27 + Printf.printf " |"; 28 + 29 + (* Print ASCII representation *) 30 + for j = start to end_ - 1 do 31 + let c = content.[j] in 32 + if c >= ' ' && c <= '~' then 33 + Printf.printf "%c" c 34 + else 35 + Printf.printf "." 36 + done; 37 + 38 + Printf.printf "|\n%!" 39 + done; 40 + 41 + if len > max_bytes then 42 + Printf.printf " ... (%d more bytes truncated)\n%!" (len - max_bytes) 43 + 44 + 4 45 let test_cases = [ 5 46 ("abort_request.bin", Abort_request, 1); 6 47 ("begin_request_authorizer.bin", Begin_request, 2); ··· 26 67 ] 27 68 28 69 let test_binary_file ~fs filename expected_type expected_request_id = 29 - Printf.printf "Testing %s... " filename; 70 + Printf.printf "Testing %s...\n" filename; 30 71 31 - let parsed = 72 + let (raw_content, parsed) = 32 73 Eio.Path.with_open_in (fs, "test_cases/" ^ filename) @@ fun flow -> 33 - let buf_read = Eio.Buf_read.of_flow flow ~max_size:1000000 in 34 - Record.read buf_read 74 + let buf = Buffer.create 1024 in 75 + Eio.Flow.copy flow (Eio.Flow.buffer_sink buf); 76 + let raw_content = Buffer.contents buf in 77 + let buf_read = Eio.Buf_read.of_string raw_content in 78 + let parsed = Record.read buf_read in 79 + (raw_content, parsed) 35 80 in 36 81 82 + Printf.printf "\nRaw file contents (%d bytes):\n" (String.length raw_content); 83 + hex_dump raw_content; 84 + 85 + Printf.printf "\nParsed record:\n"; 86 + Format.printf "%a\n" (fun ppf -> Record.pp ppf) parsed; 87 + 88 + (* If this is a Params record, also show the decoded key-value pairs *) 89 + if parsed.record_type = Params && String.length parsed.content > 0 then ( 90 + let params = Record.KV.decode parsed.content in 91 + Printf.printf "\nDecoded parameters:\n"; 92 + Format.printf "%a\n" Record.KV.pp params 93 + ); 94 + 37 95 assert (parsed.version = 1); 38 96 assert (parsed.record_type = expected_type); 39 97 assert (parsed.request_id = expected_request_id); 40 98 41 - Printf.printf "✓\n%!" 99 + Printf.printf "✓ %s passed\n\n%!" filename 42 100 43 101 let test_params_decoding ~fs = 44 - Printf.printf "Testing params record content decoding... "; 102 + Printf.printf "Testing params record content decoding...\n"; 45 103 46 104 let parsed = 47 105 Eio.Path.with_open_in (fs, "test_cases/params_get.bin") @@ fun flow -> ··· 49 107 Record.read buf_read 50 108 in 51 109 110 + Printf.printf "\nParsed params record:\n"; 111 + Format.printf "%a\n" (fun ppf -> Record.pp ppf) parsed; 112 + 52 113 (* Decode the params content *) 53 114 let params = Record.KV.decode parsed.content in 54 115 116 + Printf.printf "\nDecoded parameters:\n"; 117 + Format.printf "%a\n" Record.KV.pp params; 118 + 55 119 (* Check some expected environment variables *) 56 120 assert (Record.KV.find "REQUEST_METHOD" params = "GET"); 57 121 assert (Record.KV.find "SERVER_NAME" params = "localhost"); 58 122 assert (Record.KV.find "SERVER_PORT" params = "80"); 59 123 60 - Printf.printf "✓\n%!" 124 + Printf.printf "✓ params decoding passed\n\n%!" 61 125 62 126 let test_large_record ~fs = 63 - Printf.printf "Testing large record... "; 127 + Printf.printf "Testing large record...\n"; 64 128 65 129 let parsed = 66 130 Eio.Path.with_open_in (fs, "test_cases/large_record.bin") @@ fun flow -> ··· 68 132 Record.read buf_read 69 133 in 70 134 135 + Printf.printf "\nParsed large record:\n"; 136 + Format.printf "%a\n" (fun ppf -> Record.pp ppf) parsed; 137 + 71 138 assert (parsed.version = 1); 72 139 assert (parsed.record_type = Stdout); 73 140 assert (parsed.request_id = 1); 74 141 assert (String.length parsed.content = 65000); 75 142 76 - Printf.printf "✓\n%!" 143 + Printf.printf "✓ large record test passed\n\n%!" 77 144 78 145 let test_padded_record ~fs = 79 - Printf.printf "Testing padded record... "; 146 + Printf.printf "Testing padded record...\n"; 80 147 81 148 let parsed = 82 149 Eio.Path.with_open_in (fs, "test_cases/padded_record.bin") @@ fun flow -> 83 150 let buf_read = Eio.Buf_read.of_flow flow ~max_size:1000000 in 84 151 Record.read buf_read 85 152 in 153 + 154 + Printf.printf "\nParsed padded record:\n"; 155 + Format.printf "%a\n" (fun ppf -> Record.pp ppf) parsed; 86 156 87 157 assert (parsed.version = 1); 88 158 assert (parsed.record_type = Stdout); 89 159 assert (parsed.request_id = 1); 90 160 assert (parsed.content = "Hello"); 91 161 92 - Printf.printf "✓\n%!" 162 + Printf.printf "✓ padded record test passed\n\n%!" 93 163 94 164 let test_multiplexed_records ~fs = 95 - Printf.printf "Testing multiplexed records... "; 165 + Printf.printf "Testing multiplexed records...\n"; 96 166 97 167 let records = 98 168 Eio.Path.with_open_in (fs, "test_cases/multiplexed_requests.bin") @@ fun flow -> ··· 111 181 112 182 let records = List.rev records in 113 183 184 + Printf.printf "\nParsed %d multiplexed records:\n" (List.length records); 185 + List.iteri (fun i record -> 186 + Printf.printf "\nRecord %d:\n" (i + 1); 187 + Format.printf "%a\n" (fun ppf -> Record.pp ppf) record 188 + ) records; 189 + 114 190 (* Should have multiple records with different request IDs *) 115 191 assert (List.length records > 5); 116 192 ··· 119 195 assert (List.mem 1 request_ids); 120 196 assert (List.mem 2 request_ids); 121 197 122 - Printf.printf "✓\n%!" 198 + Printf.printf "✓ multiplexed records test passed\n\n%!" 123 199 124 200 let run_all_tests ~fs = 125 201 Printf.printf "Validating all FastCGI test case files...\n\n%!";