···
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
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;
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 " "
21
+
(* Pad remaining space *)
22
+
for _ = end_ to start + bytes_per_line - 1 do
24
+
if end_ <= start + 7 then Printf.printf " "
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
38
+
Printf.printf "|\n%!"
41
+
if len > max_bytes then
42
+
Printf.printf " ... (%d more bytes truncated)\n%!" (len - max_bytes)
("abort_request.bin", Abort_request, 1);
("begin_request_authorizer.bin", Begin_request, 2);
···
let test_binary_file ~fs filename expected_type expected_request_id =
29
-
Printf.printf "Testing %s... " filename;
70
+
Printf.printf "Testing %s...\n" filename;
72
+
let (raw_content, parsed) =
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)
82
+
Printf.printf "\nRaw file contents (%d bytes):\n" (String.length raw_content);
83
+
hex_dump raw_content;
85
+
Printf.printf "\nParsed record:\n";
86
+
Format.printf "%a\n" (fun ppf -> Record.pp ppf) parsed;
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
assert (parsed.version = 1);
assert (parsed.record_type = expected_type);
assert (parsed.request_id = expected_request_id);
41
-
Printf.printf "✓\n%!"
99
+
Printf.printf "✓ %s passed\n\n%!" filename
let test_params_decoding ~fs =
44
-
Printf.printf "Testing params record content decoding... ";
102
+
Printf.printf "Testing params record content decoding...\n";
Eio.Path.with_open_in (fs, "test_cases/params_get.bin") @@ fun flow ->
···
110
+
Printf.printf "\nParsed params record:\n";
111
+
Format.printf "%a\n" (fun ppf -> Record.pp ppf) parsed;
(* Decode the params content *)
let params = Record.KV.decode parsed.content in
116
+
Printf.printf "\nDecoded parameters:\n";
117
+
Format.printf "%a\n" Record.KV.pp params;
(* Check some expected environment variables *)
assert (Record.KV.find "REQUEST_METHOD" params = "GET");
assert (Record.KV.find "SERVER_NAME" params = "localhost");
assert (Record.KV.find "SERVER_PORT" params = "80");
60
-
Printf.printf "✓\n%!"
124
+
Printf.printf "✓ params decoding passed\n\n%!"
let test_large_record ~fs =
63
-
Printf.printf "Testing large record... ";
127
+
Printf.printf "Testing large record...\n";
Eio.Path.with_open_in (fs, "test_cases/large_record.bin") @@ fun flow ->
···
135
+
Printf.printf "\nParsed large record:\n";
136
+
Format.printf "%a\n" (fun ppf -> Record.pp ppf) parsed;
assert (parsed.version = 1);
assert (parsed.record_type = Stdout);
assert (parsed.request_id = 1);
assert (String.length parsed.content = 65000);
76
-
Printf.printf "✓\n%!"
143
+
Printf.printf "✓ large record test passed\n\n%!"
let test_padded_record ~fs =
79
-
Printf.printf "Testing padded record... ";
146
+
Printf.printf "Testing padded record...\n";
Eio.Path.with_open_in (fs, "test_cases/padded_record.bin") @@ fun flow ->
let buf_read = Eio.Buf_read.of_flow flow ~max_size:1000000 in
154
+
Printf.printf "\nParsed padded record:\n";
155
+
Format.printf "%a\n" (fun ppf -> Record.pp ppf) parsed;
assert (parsed.version = 1);
assert (parsed.record_type = Stdout);
assert (parsed.request_id = 1);
assert (parsed.content = "Hello");
92
-
Printf.printf "✓\n%!"
162
+
Printf.printf "✓ padded record test passed\n\n%!"
let test_multiplexed_records ~fs =
95
-
Printf.printf "Testing multiplexed records... ";
165
+
Printf.printf "Testing multiplexed records...\n";
Eio.Path.with_open_in (fs, "test_cases/multiplexed_requests.bin") @@ fun flow ->
···
let records = List.rev records in
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
(* Should have multiple records with different request IDs *)
assert (List.length records > 5);
···
assert (List.mem 1 request_ids);
assert (List.mem 2 request_ids);
122
-
Printf.printf "✓\n%!"
198
+
Printf.printf "✓ multiplexed records test passed\n\n%!"
Printf.printf "Validating all FastCGI test case files...\n\n%!";