···11+open Fastcgi
22+33+let test_record_types () =
44+ Printf.printf "Testing record type conversions...\n%!";
55+66+ let test_type rt expected_int =
77+ assert (Record.record_to_int rt = expected_int);
88+ assert (Record.record_of_int expected_int = rt)
99+ in
1010+1111+ test_type Begin_request 1;
1212+ test_type Abort_request 2;
1313+ test_type End_request 3;
1414+ test_type Params 4;
1515+ test_type Stdin 5;
1616+ test_type Stdout 6;
1717+ test_type Stderr 7;
1818+ test_type Data 8;
1919+ test_type Get_values 9;
2020+ test_type Get_values_result 10;
2121+ test_type Unknown_type 11;
2222+2323+ (* Test invalid record type *)
2424+ (try
2525+ let _ = Record.record_of_int 99 in
2626+ assert false (* Should not reach here *)
2727+ with Invalid_argument _ -> ());
2828+2929+ Printf.printf "✓ Record type conversion test passed\n%!"
3030+3131+let test_kv_encoding () =
3232+ Printf.printf "Testing key-value encoding...\n%!";
3333+3434+ let kv = Record.KV.empty
3535+ |> Record.KV.add "REQUEST_METHOD" "GET"
3636+ |> Record.KV.add "SERVER_NAME" "localhost"
3737+ |> Record.KV.add "SERVER_PORT" "80"
3838+ in
3939+4040+ let encoded = Record.KV.encode kv in
4141+ let decoded = Record.KV.decode encoded in
4242+4343+ (* Check that all original pairs are present *)
4444+ assert (Record.KV.find "REQUEST_METHOD" decoded = "GET");
4545+ assert (Record.KV.find "SERVER_NAME" decoded = "localhost");
4646+ assert (Record.KV.find "SERVER_PORT" decoded = "80");
4747+4848+ Printf.printf "✓ Key-value encoding test passed\n%!"
4949+5050+let test_long_key_value () =
5151+ Printf.printf "Testing long key-value encoding...\n%!";
5252+5353+ (* Create a long key and value to test 4-byte length encoding *)
5454+ let long_key = String.make 200 'k' in
5555+ let long_value = String.make 300 'v' in
5656+5757+ let kv = Record.KV.empty
5858+ |> Record.KV.add long_key long_value
5959+ |> Record.KV.add "short" "val"
6060+ in
6161+6262+ let encoded = Record.KV.encode kv in
6363+ let decoded = Record.KV.decode encoded in
6464+6565+ assert (Record.KV.find long_key decoded = long_value);
6666+ assert (Record.KV.find "short" decoded = "val");
6767+6868+ Printf.printf "✓ Long key-value encoding test passed\n%!"
6969+7070+let test_with_binary_test_case filename expected_type expected_request_id =
7171+ Printf.printf "Testing with binary test case: %s...\n%!" filename;
7272+7373+ let content =
7474+ let ic = open_in_bin ("test_cases/" ^ filename) in
7575+ let len = in_channel_length ic in
7676+ let content = really_input_string ic len in
7777+ close_in ic;
7878+ content
7979+ in
8080+8181+ let buf_read = Eio.Buf_read.of_string content in
8282+ let parsed = Record.read buf_read in
8383+8484+ assert (parsed.version = 1);
8585+ assert (parsed.record_type = expected_type);
8686+ assert (parsed.request_id = expected_request_id);
8787+8888+ Printf.printf "✓ Binary test case %s passed\n%!" filename
8989+9090+let run_tests () =
9191+ Printf.printf "Running FastCGI Record tests...\n\n%!";
9292+9393+ test_record_types ();
9494+ test_kv_encoding ();
9595+ test_long_key_value ();
9696+9797+ (* Test with some of our binary test cases *)
9898+ test_with_binary_test_case "begin_request_responder.bin" Begin_request 1;
9999+ test_with_binary_test_case "params_empty.bin" Params 1;
100100+ test_with_binary_test_case "end_request_success.bin" End_request 1;
101101+ test_with_binary_test_case "get_values.bin" Get_values 0;
102102+ test_with_binary_test_case "abort_request.bin" Abort_request 1;
103103+104104+ Printf.printf "\n✅ All FastCGI Record tests passed!\n%!"
105105+106106+let () = run_tests ()
+165
test/validate_all_test_cases.ml
···11+open Fastcgi
22+open Record
33+44+let test_cases = [
55+ ("abort_request.bin", Abort_request, 1);
66+ ("begin_request_authorizer.bin", Begin_request, 2);
77+ ("begin_request_filter.bin", Begin_request, 3);
88+ ("begin_request_no_keep.bin", Begin_request, 1);
99+ ("begin_request_responder.bin", Begin_request, 1);
1010+ ("data_empty.bin", Data, 3);
1111+ ("data_filter.bin", Data, 3);
1212+ ("end_request_error.bin", End_request, 1);
1313+ ("end_request_success.bin", End_request, 1);
1414+ ("get_values.bin", Get_values, 0);
1515+ ("get_values_result.bin", Get_values_result, 0);
1616+ ("params_empty.bin", Params, 1);
1717+ ("params_get.bin", Params, 1);
1818+ ("params_post.bin", Params, 1);
1919+ ("stderr_empty.bin", Stderr, 1);
2020+ ("stderr_message.bin", Stderr, 1);
2121+ ("stdin_empty.bin", Stdin, 1);
2222+ ("stdin_form_data.bin", Stdin, 1);
2323+ ("stdout_empty.bin", Stdout, 1);
2424+ ("stdout_response.bin", Stdout, 1);
2525+ ("unknown_type.bin", Unknown_type, 0);
2626+]
2727+2828+let test_binary_file filename expected_type expected_request_id =
2929+ Printf.printf "Testing %s... " filename;
3030+3131+ let content =
3232+ let ic = open_in_bin ("test_cases/" ^ filename) in
3333+ let len = in_channel_length ic in
3434+ let content = really_input_string ic len in
3535+ close_in ic;
3636+ content
3737+ in
3838+3939+ let buf_read = Eio.Buf_read.of_string content in
4040+ let parsed = Record.read buf_read in
4141+4242+ assert (parsed.version = 1);
4343+ assert (parsed.record_type = expected_type);
4444+ assert (parsed.request_id = expected_request_id);
4545+4646+ Printf.printf "✓\n%!"
4747+4848+let test_params_decoding () =
4949+ Printf.printf "Testing params record content decoding... ";
5050+5151+ let content =
5252+ let ic = open_in_bin "test_cases/params_get.bin" in
5353+ let len = in_channel_length ic in
5454+ let content = really_input_string ic len in
5555+ close_in ic;
5656+ content
5757+ in
5858+5959+ let buf_read = Eio.Buf_read.of_string content in
6060+ let parsed = Record.read buf_read in
6161+6262+ (* Decode the params content *)
6363+ let params = Record.KV.decode parsed.content in
6464+6565+ (* Check some expected environment variables *)
6666+ assert (Record.KV.find "REQUEST_METHOD" params = "GET");
6767+ assert (Record.KV.find "SERVER_NAME" params = "localhost");
6868+ assert (Record.KV.find "SERVER_PORT" params = "80");
6969+7070+ Printf.printf "✓\n%!"
7171+7272+let test_large_record () =
7373+ Printf.printf "Testing large record... ";
7474+7575+ let content =
7676+ let ic = open_in_bin "test_cases/large_record.bin" in
7777+ let len = in_channel_length ic in
7878+ let content = really_input_string ic len in
7979+ close_in ic;
8080+ content
8181+ in
8282+8383+ let buf_read = Eio.Buf_read.of_string content in
8484+ let parsed = Record.read buf_read in
8585+8686+ assert (parsed.version = 1);
8787+ assert (parsed.record_type = Stdout);
8888+ assert (parsed.request_id = 1);
8989+ assert (String.length parsed.content = 65000);
9090+9191+ Printf.printf "✓\n%!"
9292+9393+let test_padded_record () =
9494+ Printf.printf "Testing padded record... ";
9595+9696+ let content =
9797+ let ic = open_in_bin "test_cases/padded_record.bin" in
9898+ let len = in_channel_length ic in
9999+ let content = really_input_string ic len in
100100+ close_in ic;
101101+ content
102102+ in
103103+104104+ let buf_read = Eio.Buf_read.of_string content in
105105+ let parsed = Record.read buf_read in
106106+107107+ assert (parsed.version = 1);
108108+ assert (parsed.record_type = Stdout);
109109+ assert (parsed.request_id = 1);
110110+ assert (parsed.content = "Hello");
111111+112112+ Printf.printf "✓\n%!"
113113+114114+let test_multiplexed_records () =
115115+ Printf.printf "Testing multiplexed records... ";
116116+117117+ let content =
118118+ let ic = open_in_bin "test_cases/multiplexed_requests.bin" in
119119+ let len = in_channel_length ic in
120120+ let content = really_input_string ic len in
121121+ close_in ic;
122122+ content
123123+ in
124124+125125+ let buf_read = Eio.Buf_read.of_string content in
126126+ let records = ref [] in
127127+128128+ (* Read all records from the multiplexed stream *)
129129+ (try
130130+ while true do
131131+ let record = Record.read buf_read in
132132+ records := record :: !records
133133+ done
134134+ with End_of_file -> ());
135135+136136+ let records = List.rev !records in
137137+138138+ (* Should have multiple records with different request IDs *)
139139+ assert (List.length records > 5);
140140+141141+ (* Check that we have records for both request ID 1 and 2 *)
142142+ let request_ids = List.map (fun r -> r.Record.request_id) records in
143143+ assert (List.mem 1 request_ids);
144144+ assert (List.mem 2 request_ids);
145145+146146+ Printf.printf "✓\n%!"
147147+148148+let run_all_tests () =
149149+ Printf.printf "Validating all FastCGI test case files...\n\n%!";
150150+151151+ (* Test individual files *)
152152+ List.iter (fun (filename, expected_type, expected_request_id) ->
153153+ test_binary_file filename expected_type expected_request_id
154154+ ) test_cases;
155155+156156+ Printf.printf "\nTesting specific content decoding...\n%!";
157157+ test_params_decoding ();
158158+ test_large_record ();
159159+ test_padded_record ();
160160+ test_multiplexed_records ();
161161+162162+ Printf.printf "\n✅ All %d test case files validated successfully!\n%!" (List.length test_cases);
163163+ Printf.printf "✅ FastCGI Record implementation is working correctly!\n%!"
164164+165165+let () = run_all_tests ()