Select the types of activity you want to include in your feed.
fix(ocaml-requests): update tests and fuzz for cstruct→Bytes migration
Test files still referenced Cstruct.t where the API now uses bytes. Fixed all H2 frame, HPACK, client, and connection tests. Fixed fuzz test. 330 tests pass.
···1414(* Generate a valid float string *)
1515let float_str_gen =
1616 map [ float ] (fun f ->
1717- if Float.is_nan f || Float.is_infinite f then "0.0"
1818- else string_of_float f)
1717+ if Float.is_nan f || Float.is_infinite f then "0.0" else string_of_float f)
19182019(* Generate a valid int string *)
2120let int_str_gen = map [ int ] (fun i -> string_of_int i)
22212322(* Generate a valid bool string *)
2424-let bool_str_gen =
2525- map [ bool ] (fun b -> if b then "true" else "false")
2323+let bool_str_gen = map [ bool ] (fun b -> if b then "true" else "false")
26242725(* {1 Test codecs} *)
28262927let int_codec = Csvt.(Row.(obj Fun.id |> col "v" int ~enc:Fun.id |> finish))
3030-3131-let float_codec =
3232- Csvt.(Row.(obj Fun.id |> col "v" float ~enc:Fun.id |> finish))
2828+let float_codec = Csvt.(Row.(obj Fun.id |> col "v" float ~enc:Fun.id |> finish))
33293430let string_codec =
3531 Csvt.(Row.(obj Fun.id |> col "v" string ~enc:Fun.id |> finish))
36323737-let bool_codec =
3838- Csvt.(Row.(obj Fun.id |> col "v" bool ~enc:Fun.id |> finish))
3333+let bool_codec = Csvt.(Row.(obj Fun.id |> col "v" bool ~enc:Fun.id |> finish))
39344035let pair_codec =
4136 Csvt.(
4237 Row.(
4338 obj (fun a b -> (a, b))
4444- |> col "a" int ~enc:fst
4545- |> col "b" string ~enc:snd
4646- |> finish))
3939+ |> col "a" int ~enc:fst |> col "b" string ~enc:snd |> finish))
47404841let triple_codec =
4942 Csvt.(
···5548 |> finish))
56495750let nullable_codec =
5858- Csvt.(
5959- Row.(obj Fun.id |> col "v" nullable_float ~enc:Fun.id |> finish))
5151+ Csvt.(Row.(obj Fun.id |> col "v" nullable_float ~enc:Fun.id |> finish))
60526153let option_codec =
6262- Csvt.(
6363- Row.(obj Fun.id |> col "v" (option int) ~enc:Fun.id |> finish))
5454+ Csvt.(Row.(obj Fun.id |> col "v" (option int) ~enc:Fun.id |> finish))
64556556(* {1 Crash safety: arbitrary bytes never cause a crash} *)
6657···8172 let csv = "v\n" ^ string_of_int i ^ "\n" in
8273 match Csvt.decode_string int_codec csv with
8374 | Error e -> failf "int decode failed: %s" (Csvt.error_to_string e)
8484- | Ok [ v ] ->
8585- if v <> i then failf "int roundtrip: expected %d, got %d" i v
7575+ | Ok [ v ] -> if v <> i then failf "int roundtrip: expected %d, got %d" i v
8676 | Ok vs -> failf "int roundtrip: expected 1 row, got %d" (List.length vs)
87778878(* {1 Float roundtrip} *)
···10797 let csv = "v\n" ^ string_of_bool b ^ "\n" in
10898 match Csvt.decode_string bool_codec csv with
10999 | Error e -> failf "bool decode failed: %s" (Csvt.error_to_string e)
110110- | Ok [ v ] ->
111111- if v <> b then failf "bool roundtrip: expected %b, got %b" b v
100100+ | Ok [ v ] -> if v <> b then failf "bool roundtrip: expected %b, got %b" b v
112101 | Ok vs -> failf "bool roundtrip: expected 1 row, got %d" (List.length vs)
113102114103(* {1 String roundtrip (no commas/newlines)} *)
···119108 |> Seq.filter (fun c -> c <> ',' && c <> '\n' && c <> '\r')
120109 |> String.of_seq
121110 in
122122- if String.length s = 0 then () (* empty lines are skipped *)
111111+ if String.length s = 0 then () (* empty lines are skipped *)
123112 else
124113 let csv = "v\n" ^ s ^ "\n" in
125114 match Csvt.decode_string string_codec csv with
···127116 | Ok [ v ] ->
128117 if not (String.equal v s) then
129118 failf "string roundtrip: expected %S, got %S" s v
130130- | Ok vs ->
131131- failf "string roundtrip: expected 1 row, got %d" (List.length vs)
119119+ | Ok vs -> failf "string roundtrip: expected 1 row, got %d" (List.length vs)
132120133121(* {1 Pair roundtrip} *)
134122···145133 | Error e -> failf "pair decode failed: %s" (Csvt.error_to_string e)
146134 | Ok [ (a, b) ] ->
147135 if a <> i then failf "pair.a: expected %d, got %d" i a;
148148- if not (String.equal b s) then
149149- failf "pair.b: expected %S, got %S" s b
136136+ if not (String.equal b s) then failf "pair.b: expected %S, got %S" s b
150137 | Ok vs -> failf "pair roundtrip: expected 1 row, got %d" (List.length vs)
151138152139(* {1 Column reorder invariance} *)
···161148 else
162149 let csv1 = "a,b\n" ^ string_of_int i ^ "," ^ s ^ "\n" in
163150 let csv2 = "b,a\n" ^ s ^ "," ^ string_of_int i ^ "\n" in
164164- match (Csvt.decode_string pair_codec csv1, Csvt.decode_string pair_codec csv2) with
151151+ match
152152+ (Csvt.decode_string pair_codec csv1, Csvt.decode_string pair_codec csv2)
153153+ with
165154 | Ok [ (a1, b1) ], Ok [ (a2, b2) ] ->
166155 if a1 <> a2 then failf "reorder.a: %d vs %d" a1 a2;
167167- if not (String.equal b1 b2) then
168168- failf "reorder.b: %S vs %S" b1 b2
156156+ if not (String.equal b1 b2) then failf "reorder.b: %S vs %S" b1 b2
169157 | Error e, _ | _, Error e ->
170158 failf "reorder decode failed: %s" (Csvt.error_to_string e)
171159 | _ -> failf "reorder: unexpected row count"
···186174 | Error e -> failf "multi-row decode failed: %s" (Csvt.error_to_string e)
187175 | Ok vs ->
188176 if List.length vs <> List.length is then
189189- failf "multi-row: expected %d rows, got %d"
190190- (List.length is) (List.length vs);
177177+ failf "multi-row: expected %d rows, got %d" (List.length is)
178178+ (List.length vs);
191179 List.iter2
192180 (fun expected got ->
193181 if expected <> got then
···198186199187let test_nullable_roundtrip f =
200188 let s =
201201- if Float.is_nan f || Float.is_infinite f then "NULL"
202202- else string_of_float f
189189+ if Float.is_nan f || Float.is_infinite f then "NULL" else string_of_float f
203190 in
204191 let csv = "v\n" ^ s ^ "\n" in
205192 match Csvt.decode_string nullable_codec csv with
206193 | Error e -> failf "nullable decode failed: %s" (Csvt.error_to_string e)
207194 | Ok [ v ] ->
208195 if String.equal s "NULL" then (
209209- if not (Float.is_nan v) then
210210- failf "nullable: expected nan, got %g" v)
196196+ if not (Float.is_nan v) then failf "nullable: expected nan, got %g" v)
211197 else
212198 let diff = Float.abs (f -. v) in
213199 let scale = Float.max 1.0 (Float.abs f) in
214200 if diff /. scale > 1e-10 then
215201 failf "nullable roundtrip: expected %g, got %g" f v
216216- | Ok vs ->
217217- failf "nullable roundtrip: expected 1 row, got %d" (List.length vs)
202202+ | Ok vs -> failf "nullable roundtrip: expected 1 row, got %d" (List.length vs)
218203219204(* {1 Test suite} *)
220205221206let suite =
222207 ( "csvt",
223208 [
224224- test_case "no crash on arbitrary" [ bytes ] test_no_crash_on_arbitrary_input;
209209+ test_case "no crash on arbitrary" [ bytes ]
210210+ test_no_crash_on_arbitrary_input;
225211 test_case "int roundtrip" [ int ] test_int_roundtrip;
226212 test_case "float roundtrip" [ float ] test_float_roundtrip;
227213 test_case "bool roundtrip" [ bool ] test_bool_roundtrip;
+11-20
lib/csvt.ml
···1818 | Missing_header -> "missing CSV header row"
1919 | Missing_column name -> "missing required column: " ^ name
2020 | Bad_value { row; column; value; msg } ->
2121- Printf.sprintf "row %d, column %s: bad value %S (%s)" row column value
2222- msg
2121+ Printf.sprintf "row %d, column %s: bad value %S (%s)" row column value msg
2322 | Truncated_row { row; expected; got } ->
2423 Printf.sprintf "row %d: expected %d columns, got %d" row expected got
2524 | Encode_error msg -> "encode error: " ^ msg
26252726let pp_error ppf e = Format.pp_print_string ppf (error_to_string e)
2828-2927let ( let* ) = Result.bind
30283129(* {1 Column codecs} *)
···3735}
38363937let col_kind c = c.kind
4040-4138let col_map ?(kind = "custom") ~dec ~enc () = { kind; dec; enc }
4242-4339let string = { kind = "string"; dec = (fun s -> Ok s); enc = Fun.id }
44404541let int =
···108104 {
109105 kind = "option(" ^ c.kind ^ ")";
110106 dec =
111111- (fun s ->
112112- if is_null s then Ok None else Result.map Option.some (c.dec s));
107107+ (fun s -> if is_null s then Ok None else Result.map Option.some (c.dec s));
113108 enc = (fun v -> match v with None -> "NULL" | Some x -> c.enc x);
114109 }
115110···131126 encode : Obj.t -> string;
132127}
133128134134-type 'a t = {
135135- kind : string;
136136- cols : col_entry list;
137137- ctor : Obj.t;
138138-}
129129+type 'a t = { kind : string; cols : col_entry list; ctor : Obj.t }
139130140131(* {1 Row builder} *)
141132···228219 | Ok v -> go (i + 1) (apply f v)
229220 | Error msg ->
230221 Error
231231- (Bad_value
232232- { row = row_num; column = col.name; value = s; msg })
222222+ (Bad_value { row = row_num; column = col.name; value = s; msg })
233223 in
234224 go 0 resolved.rctor
235225236226(* {1 Row encoding} *)
237227238238-let encode_header codec =
239239- Array.of_list (List.map (fun c -> c.name) codec.cols)
228228+let encode_header codec = Array.of_list (List.map (fun c -> c.name) codec.cols)
240229241230let encode_row codec v =
242231 let o = Obj.repr v in
···278267279268let fold_file codec path f acc =
280269 let ic = open_in path in
281281- Fun.protect ~finally:(fun () -> close_in ic) (fun () ->
282282- fold_channel codec ic f acc)
270270+ Fun.protect
271271+ ~finally:(fun () -> close_in ic)
272272+ (fun () -> fold_channel codec ic f acc)
283273284274let decode_file codec path =
285275 let ic = open_in path in
286286- Fun.protect ~finally:(fun () -> close_in ic) (fun () ->
287287- decode_channel codec ic)
276276+ Fun.protect
277277+ ~finally:(fun () -> close_in ic)
278278+ (fun () -> decode_channel codec ic)
288279289280let decode_string codec s =
290281 let lines = String.split_on_char '\n' s in
+11-12
lib/csvt.mli
···5050(** {1:codec Column Codecs} *)
51515252type 'a col_codec
5353-(** The type of column-level codecs. A column codec knows how to convert
5454- between a single CSV field (string) and a typed OCaml value. *)
5353+(** The type of column-level codecs. A column codec knows how to convert between
5454+ a single CSV field (string) and a typed OCaml value. *)
55555656val string : string col_codec
5757(** Codec for string fields (identity). *)
···8080 enc:('a -> string) ->
8181 unit ->
8282 'a col_codec
8383-(** [col_map ~dec ~enc] creates a column codec from raw decode/encode
8484- functions. *)
8383+(** [col_map ~dec ~enc] creates a column codec from raw decode/encode functions.
8484+*)
85858686val col_kind : 'a col_codec -> string
8787(** [col_kind c] returns the kind description of column codec [c]. *)
···8989(** {1:row Row Codecs} *)
90909191type 'a t
9292-(** The type of row-level codecs. A row codec maps between a CSV row
9393- (resolved through header column names) and a typed OCaml record. *)
9292+(** The type of row-level codecs. A row codec maps between a CSV row (resolved
9393+ through header column names) and a typed OCaml record. *)
94949595(** Row codec builder. *)
9696module Row : sig
···141141 performed once, giving O(1) per-row decoding. *)
142142143143val resolve : 'a t -> header -> ('a resolved, error) result
144144-(** [resolve codec header] resolves column names to indices.
145145- Returns an error if a required column is missing. *)
144144+(** [resolve codec header] resolves column names to indices. Returns an error if
145145+ a required column is missing. *)
146146147147val decode_row : 'a resolved -> int -> string array -> ('a, error) result
148148-(** [decode_row resolved row_num fields] decodes a single CSV row.
149149- [row_num] is for error reporting (1-based). *)
148148+(** [decode_row resolved row_num fields] decodes a single CSV row. [row_num] is
149149+ for error reporting (1-based). *)
150150151151val encode_header : 'a t -> header
152152(** [encode_header codec] returns the CSV header for encoding. *)
···167167(** [fold_channel codec ic f acc] folds over rows without building an
168168 intermediate list. Useful for large files. *)
169169170170-val fold_file :
171171- 'a t -> string -> ('b -> 'a -> 'b) -> 'b -> ('b, error) result
170170+val fold_file : 'a t -> string -> ('b -> 'a -> 'b) -> 'b -> ('b, error) result
172171(** [fold_file codec path f acc] folds over rows from a file. *)
173172174173val decode_string : 'a t -> string -> ('a list, error) result
+68-33
test/test_csvt.ml
···102102103103let test_missing_column () =
104104 let csv = "x,label\n1.0,foo\n" in
105105- check_error "missing y" (function Csvt.Missing_column "y" -> true | _ -> false)
105105+ check_error "missing y"
106106+ (function Csvt.Missing_column "y" -> true | _ -> false)
106107 (Csvt.decode_string point_codec csv)
107108108109let test_bad_float () =
109110 let csv = "x,y,label\nnot_a_number,2.0,foo\n" in
110110- check_error "bad float" (function Csvt.Bad_value { column = "x"; _ } -> true | _ -> false)
111111+ check_error "bad float"
112112+ (function Csvt.Bad_value { column = "x"; _ } -> true | _ -> false)
111113 (Csvt.decode_string point_codec csv)
112114113115let test_bad_int () =
114116 let csv = "id,name,score,active\nabc,alice,95.5,true\n" in
115115- check_error "bad int" (function Csvt.Bad_value { column = "id"; _ } -> true | _ -> false)
117117+ check_error "bad int"
118118+ (function Csvt.Bad_value { column = "id"; _ } -> true | _ -> false)
116119 (Csvt.decode_string record_codec csv)
117120118121let test_bad_bool () =
119122 let csv = "id,name,score,active\n1,alice,95.5,maybe\n" in
120120- check_error "bad bool" (function Csvt.Bad_value { column = "active"; _ } -> true | _ -> false)
123123+ check_error "bad bool"
124124+ (function Csvt.Bad_value { column = "active"; _ } -> true | _ -> false)
121125 (Csvt.decode_string record_codec csv)
122126123127let test_empty_csv () =
124124- check_error "empty" (function Csvt.Missing_header -> true | _ -> false)
128128+ check_error "empty"
129129+ (function Csvt.Missing_header -> true | _ -> false)
125130 (Csvt.decode_string point_codec "")
126131127132let test_header_only () =
···254259(* {1 Bool codec edge cases} *)
255260256261let test_bool_variants () =
257257- let codec =
258258- Csvt.(Row.(obj Fun.id |> col "v" bool ~enc:Fun.id |> finish))
259259- in
262262+ let codec = Csvt.(Row.(obj Fun.id |> col "v" bool ~enc:Fun.id |> finish)) in
260263 let check input expected =
261264 match Csvt.decode_string codec ("v\n" ^ input ^ "\n") with
262265 | Error e -> Alcotest.failf "%s: %s" input (Csvt.error_to_string e)
···277280(* {1 Float edge cases} *)
278281279282let test_float_edge_cases () =
280280- let codec =
281281- Csvt.(Row.(obj Fun.id |> col "v" float ~enc:Fun.id |> finish))
282282- in
283283+ let codec = Csvt.(Row.(obj Fun.id |> col "v" float ~enc:Fun.id |> finish)) in
283284 let check input expected =
284285 match Csvt.decode_string codec ("v\n" ^ input ^ "\n") with
285286 | Error e -> Alcotest.failf "%s: %s" input (Csvt.error_to_string e)
···294295 check "-999.999" (-999.999);
295296 check "inf" infinity;
296297 check "-inf" neg_infinity;
297297- check "nan" Float.nan (* OCaml float_of_string handles this *)
298298+ check "nan" Float.nan (* OCaml float_of_string handles this *)
298299299300let test_float_nan_check () =
300300- let codec =
301301- Csvt.(Row.(obj Fun.id |> col "v" float ~enc:Fun.id |> finish))
302302- in
301301+ let codec = Csvt.(Row.(obj Fun.id |> col "v" float ~enc:Fun.id |> finish)) in
303302 match Csvt.decode_string codec "v\nnan\n" with
304303 | Error e -> Alcotest.failf "%s" (Csvt.error_to_string e)
305304 | Ok [ v ] -> Alcotest.(check bool) "is nan" true (Float.is_nan v)
···308307(* {1 Int edge cases} *)
309308310309let test_int_edge_cases () =
311311- let codec =
312312- Csvt.(Row.(obj Fun.id |> col "v" int ~enc:Fun.id |> finish))
313313- in
310310+ let codec = Csvt.(Row.(obj Fun.id |> col "v" int ~enc:Fun.id |> finish)) in
314311 let check input expected =
315312 match Csvt.decode_string codec ("v\n" ^ input ^ "\n") with
316313 | Error e -> Alcotest.failf "%s: %s" input (Csvt.error_to_string e)
···325322(* {1 String edge cases} *)
326323327324let test_string_with_spaces () =
328328- let codec =
329329- Csvt.(Row.(obj Fun.id |> col "v" string ~enc:Fun.id |> finish))
330330- in
325325+ let codec = Csvt.(Row.(obj Fun.id |> col "v" string ~enc:Fun.id |> finish)) in
331326 match Csvt.decode_string codec "v\nhello world\n" with
332327 | Error e -> Alcotest.failf "%s" (Csvt.error_to_string e)
333328 | Ok [ v ] -> Alcotest.(check string) "spaces" "hello world" v
···339334 Csvt.(
340335 Row.(
341336 obj (fun a b -> (a, b))
342342- |> col "a" string ~enc:fst
343343- |> col "b" string ~enc:snd
344344- |> finish))
337337+ |> col "a" string ~enc:fst |> col "b" string ~enc:snd |> finish))
345338 in
346339 match Csvt.decode_string codec "a,b\nhello,\n" with
347340 | Error e -> Alcotest.failf "%s" (Csvt.error_to_string e)
···353346(* {1 Many rows} *)
354347355348let test_many_rows () =
356356- let codec =
357357- Csvt.(Row.(obj Fun.id |> col "v" int ~enc:Fun.id |> finish))
358358- in
349349+ let codec = Csvt.(Row.(obj Fun.id |> col "v" int ~enc:Fun.id |> finish)) in
359350 let buf = Buffer.create 1024 in
360351 Buffer.add_string buf "v\n";
361352 for i = 0 to 999 do
···420411 let codec =
421412 Csvt.(
422413 Row.(
423423- obj (fun c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16
424424- c17 c18 c19 ->
425425- [| c0; c1; c2; c3; c4; c5; c6; c7; c8; c9; c10; c11; c12; c13; c14;
426426- c15; c16; c17; c18; c19 |])
414414+ obj
415415+ (fun
416416+ c0
417417+ c1
418418+ c2
419419+ c3
420420+ c4
421421+ c5
422422+ c6
423423+ c7
424424+ c8
425425+ c9
426426+ c10
427427+ c11
428428+ c12
429429+ c13
430430+ c14
431431+ c15
432432+ c16
433433+ c17
434434+ c18
435435+ c19
436436+ ->
437437+ [|
438438+ c0;
439439+ c1;
440440+ c2;
441441+ c3;
442442+ c4;
443443+ c5;
444444+ c6;
445445+ c7;
446446+ c8;
447447+ c9;
448448+ c10;
449449+ c11;
450450+ c12;
451451+ c13;
452452+ c14;
453453+ c15;
454454+ c16;
455455+ c17;
456456+ c18;
457457+ c19;
458458+ |])
427459 |> col "c0" int ~enc:(fun a -> a.(0))
428460 |> col "c1" int ~enc:(fun a -> a.(1))
429461 |> col "c2" int ~enc:(fun a -> a.(2))
···446478 |> col "c19" int ~enc:(fun a -> a.(19))
447479 |> finish))
448480 in
449449- let header = String.concat "," (List.init 20 (fun i -> "c" ^ string_of_int i)) in
481481+ let header =
482482+ String.concat "," (List.init 20 (fun i -> "c" ^ string_of_int i))
483483+ in
450484 let row = String.concat "," (List.init 20 string_of_int) in
451485 let csv = header ^ "\n" ^ row ^ "\n" in
452486 match Csvt.decode_string codec csv with
···484518 Alcotest.test_case "option string" `Quick test_option_string;
485519 (* Defaults *)
486520 Alcotest.test_case "dec_absent" `Quick test_dec_absent;
487487- Alcotest.test_case "dec_absent all missing" `Quick test_dec_absent_all_missing;
521521+ Alcotest.test_case "dec_absent all missing" `Quick
522522+ test_dec_absent_all_missing;
488523 (* Encoding *)
489524 Alcotest.test_case "encode header" `Quick test_encode_header;
490525 Alcotest.test_case "encode row" `Quick test_encode_row;