My aggregated monorepo of OCaml code, automaintained
0
fork

Configure Feed

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

Squashed 'ocaml-yamlt/' changes from bd3ac45..2ce298e

2ce298e Fix tangled.org URLs: remove @ prefix from all projects
5be6625 Merge commit '6b34b48ae94c5f280bec790610cd948a71c98127'
3fc75e6 Fix build errors and update ocamlformat versions
242af37 Fix build errors and update ocamlformat versions
9ec4e59 Update precommit and clean up yamlt test files
aedf4d4 Update precommit and clean up yamlt test files
c337113 Consolidate duplicate hex utilities and crypto functions
4fc7211 Consolidate duplicate hex utilities and crypto functions
d5ada31 yamlt: add decode_string and decode_value convenience functions
12f3911 Remove public installation of test binaries

git-subtree-dir: ocaml-yamlt
git-subtree-split: 2ce298e1a833b73057c21d1f49c39889c5dadb85

+35 -4667
+1 -1
.ocamlformat
··· 1 - version=0.28.1 1 + version = 0.28.1
+2 -2
dune-project
··· 6 6 7 7 (license ISC) 8 8 (authors "Anil Madhavapeddy") 9 - (homepage "https://tangled.org/@anil.recoil.org/ocaml-yamlt") 9 + (homepage "https://tangled.org/anil.recoil.org/ocaml-yamlt") 10 10 (maintainers "Anil Madhavapeddy <anil@recoil.org>") 11 - (bug_reports "https://tangled.org/@anil.recoil.org/ocaml-yamlt/issues") 11 + (bug_reports "https://tangled.org/anil.recoil.org/ocaml-yamlt/issues") 12 12 (maintenance_intent "(latest)") 13 13 14 14 (package
+16 -29
lib/yamlt.ml
··· 71 71 The last_byte is on the previous line, so we need to calculate 72 72 the line start position based on last_byte, not stop. *) 73 73 let last_line = 74 - if stop.Position.column = 1 && stop.Position.line > start.Position.line then 74 + if stop.Position.column = 1 && stop.Position.line > start.Position.line 75 + then 75 76 (* last_byte is on the previous line (stop.line - 1) 76 77 We need to estimate where that line starts. Since we don't have 77 78 the full text, we can't calculate it exactly, but we can use: ··· 91 92 last_byte should be the newline character on the previous line. 92 93 The line likely started much earlier, but we'll estimate conservatively. *) 93 94 (last_line_num, last_byte) 94 - else 95 - (stop.Position.line, stop.Position.index - stop.Position.column + 1) 95 + else (stop.Position.line, stop.Position.index - stop.Position.column + 1) 96 96 in 97 97 let textloc = 98 98 Jsont.Textloc.make ~file:d.file ~first_byte ~last_byte ~first_line ··· 206 206 if is_null_scalar value then 207 207 let end_meta = meta_of_span d ev.Event.span in 208 208 map.dec_finish end_meta 0 (map.dec_empty ()) 209 - else 210 - err_type_mismatch d ev.span t ~fnd:"scalar" 209 + else err_type_mismatch d ev.span t ~fnd:"scalar" 211 210 | Object map -> 212 211 (* Treat null as an empty object for convenience *) 213 212 if is_null_scalar value then ··· 223 222 let dict = String_map.fold add_default map.mem_decs Dict.empty in 224 223 let dict = Dict.add object_meta_arg meta dict in 225 224 apply_dict map.dec dict 226 - else 227 - err_type_mismatch d ev.span t ~fnd:"scalar" 225 + else err_type_mismatch d ev.span t ~fnd:"scalar" 228 226 | Map m -> 229 227 (* Handle Map combinators (e.g., from Jsont.option) *) 230 228 m.dec (decode_scalar_as d ev value style m.dom) ··· 347 345 | None -> 348 346 let meta = meta_of_span d ev.span in 349 347 err_msg meta "Unknown anchor: %s" anchor 350 - | Some json_value -> 348 + | Some json_value -> ( 351 349 (* Decode the stored JSON value through the type *) 352 350 let t' = Jsont.Repr.unsafe_to_t t in 353 351 match Jsont.Json.decode' t' json_value with 354 352 | Ok v -> v 355 - | Error e -> raise (Jsont.Error e) 353 + | Error e -> raise (Jsont.Error e)) 356 354 357 355 and decode_array : type a elt b. 358 356 decoder -> nest:int -> Event.spanned -> (a, elt, b) array_map -> a = ··· 576 574 e) 577 575 | None -> 578 576 (* Unknown member - decode as generic JSON and delay *) 579 - let v = 580 - decode d ~nest:(nest + 1) (Jsont.Repr.of_t Jsont.json) 581 - in 577 + let v = decode d ~nest:(nest + 1) (Jsont.Repr.of_t Jsont.json) in 582 578 let delayed = ((name, name_meta), v) :: delayed in 583 - decode_object_cases d ~nest obj_meta object_map umems cases 584 - mem_miss delayed dict 579 + decode_object_cases d ~nest obj_meta object_map umems cases mem_miss 580 + delayed dict 585 581 end 586 582 | None -> err_msg obj_meta "Unclosed mapping" 587 583 ··· 793 789 | `String s -> Jsont.String (s, meta) 794 790 | `A items -> Jsont.Array (List.map value_to_json items, meta) 795 791 | `O fields -> 796 - let mems = 797 - List.map 798 - (fun (k, v) -> ((k, meta), value_to_json v)) 799 - fields 800 - in 792 + let mems = List.map (fun (k, v) -> ((k, meta), value_to_json v)) fields in 801 793 Jsont.Object (mems, meta) 802 794 803 795 let decode_value' t v = ··· 836 828 (* Helper to create scalar events with common defaults *) 837 829 let scalar_event ?(anchor = None) ?(tag = None) ~value ~style () = 838 830 Event.Scalar 839 - { 840 - anchor; 841 - tag; 842 - value; 843 - plain_implicit = true; 844 - quoted_implicit = true; 845 - style; 846 - } 831 + { anchor; tag; value; plain_implicit = true; quoted_implicit = true; style } 847 832 848 833 (* Helper to emit events *) 849 834 let emit e = Emitter.emit e.emitter ··· 916 901 and encode_object : type o. encoder -> (o, o) object_map -> o -> unit = 917 902 fun e map v -> 918 903 let style = layout_style_of_format e.format in 919 - emit e (Event.Mapping_start { anchor = None; tag = None; implicit = true; style }); 904 + emit e 905 + (Event.Mapping_start { anchor = None; tag = None; implicit = true; style }); 920 906 (* Encode each member *) 921 907 List.iter 922 908 (fun (Mem_enc mem) -> ··· 975 961 let e = make_encoder ?format ?indent ?explicit_doc ?scalar_style emitter in 976 962 try 977 963 emit e (Event.Stream_start { encoding = `Utf8 }); 978 - emit e (Event.Document_start { version = None; implicit = not e.explicit_doc }); 964 + emit e 965 + (Event.Document_start { version = None; implicit = not e.explicit_doc }); 979 966 let t' = Jsont.Repr.of_t t in 980 967 encode e t' v; 981 968 emit e (Event.Document_end { implicit = not e.explicit_doc });
+14 -15
lib/yamlt.mli
··· 31 31 32 32 {2 Related Libraries} 33 33 34 - {ul 35 - {- [Jsont] - JSON codec library whose type descriptions this library interprets} 36 - {- [Yamlrw] - Pure OCaml YAML parser/emitter used for low-level YAML processing} 37 - {- [Bytesrw] - Byte-level I/O abstraction for streaming encode/decode}} 34 + - [Jsont] - JSON codec library whose type descriptions this library 35 + interprets 36 + - [Yamlrw] - Pure OCaml YAML parser/emitter used for low-level YAML 37 + processing 38 + - [Bytesrw] - Byte-level I/O abstraction for streaming encode/decode 38 39 39 40 See notes about {{!yaml_mapping}YAML to JSON mapping}, 40 41 {{!yaml_scalars}YAML scalar resolution}, and ··· 102 103 'a Jsont.t -> 103 104 Bytes.Reader.t -> 104 105 ('a, Jsont.Error.t) result Seq.t 105 - (** [decode_all'] is like {!val-decode_all} but preserves the error structure. *) 106 + (** [decode_all'] is like {!val-decode_all} but preserves the error structure. 107 + *) 106 108 107 109 val decode_string : 108 110 ?layout:bool -> ··· 113 115 'a Jsont.t -> 114 116 string -> 115 117 ('a, string) result 116 - (** [decode_string t s] decodes a value from YAML string [s] according to 117 - type [t]. This is a convenience wrapper around {!val-decode}. *) 118 + (** [decode_string t s] decodes a value from YAML string [s] according to type 119 + [t]. This is a convenience wrapper around {!val-decode}. *) 118 120 119 121 val decode_value : 'a Jsont.t -> Yamlrw.value -> ('a, string) result 120 122 (** [decode_value t v] decodes a value from a pre-parsed {!Yamlrw.value} 121 123 according to type [t]. 122 124 123 125 This is useful when you have already parsed YAML into its JSON-compatible 124 - representation (e.g., when using {!Yamlrw.of_string}) and want to decode 125 - it using a Jsont codec without re-parsing the YAML text. *) 126 + representation (e.g., when using {!Yamlrw.of_string}) and want to decode it 127 + using a Jsont codec without re-parsing the YAML text. *) 126 128 127 129 val decode_value' : 'a Jsont.t -> Yamlrw.value -> ('a, Jsont.Error.t) result 128 130 (** [decode_value'] is like {!val-decode_value} but preserves the error ··· 273 275 {[ 274 276 (* Accepts null, decodes as None *) 275 277 Jsont.Object.mem "count" (Jsont.option Jsont.int) ~dec_absent:None 276 - 277 - (* Rejects null, requires a number *) 278 - Jsont.Object.mem "count" Jsont.int ~dec_absent:0 279 - ]} 280 - 281 - *) 278 + (* Rejects null, requires a number *) 279 + Jsont.Object.mem "count" Jsont.int ~dec_absent:0 280 + ]} *)
-67
tests/bin/dune
··· 1 - (executable 2 - (name test_scalars) 3 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 4 - 5 - (executable 6 - (name test_objects) 7 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 8 - 9 - (executable 10 - (name test_arrays) 11 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 12 - 13 - (executable 14 - (name test_formats) 15 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 16 - 17 - (executable 18 - (name test_roundtrip) 19 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 20 - 21 - (executable 22 - (name test_complex) 23 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 24 - 25 - (executable 26 - (name test_edge) 27 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 28 - 29 - (executable 30 - (name test_null_fix) 31 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 32 - 33 - (executable 34 - (name test_null_complete) 35 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 36 - 37 - (executable 38 - (name test_null_collections) 39 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 40 - 41 - (executable 42 - (name test_opt_array) 43 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 44 - 45 - (executable 46 - (name test_array_variants) 47 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 48 - 49 - (executable 50 - (name test_some_vs_option) 51 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 52 - 53 - (executable 54 - (name test_comprehensive) 55 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 56 - 57 - (executable 58 - (name test_flow_newline) 59 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 60 - 61 - (executable 62 - (name test_locations) 63 - (libraries yamlt jsont jsont.bytesrw bytesrw)) 64 - 65 - (executable 66 - (name test_multidoc) 67 - (libraries yamlt jsont jsont.bytesrw bytesrw))
-32
tests/bin/test_array_variants.ml
··· 1 - open Bytesrw 2 - 3 - let () = 4 - let codec1 = 5 - Jsont.Object.map ~kind:"Test" (fun arr -> arr) 6 - |> Jsont.Object.mem "values" (Jsont.array Jsont.string) ~enc:(fun arr -> 7 - arr) 8 - |> Jsont.Object.finish 9 - in 10 - 11 - let yaml1 = "values: [a, b, c]" in 12 - 13 - Printf.printf "Test 1: Non-optional array:\n"; 14 - (match Yamlt.decode codec1 (Bytes.Reader.of_string yaml1) with 15 - | Ok arr -> Printf.printf "Result: [%d items]\n" (Array.length arr) 16 - | Error e -> Printf.printf "Error: %s\n" e); 17 - 18 - let codec2 = 19 - Jsont.Object.map ~kind:"Test" (fun arr -> arr) 20 - |> Jsont.Object.mem "values" 21 - (Jsont.option (Jsont.array Jsont.string)) 22 - ~enc:(fun arr -> arr) 23 - |> Jsont.Object.finish 24 - in 25 - 26 - Printf.printf "\nTest 2: Jsont.option (Jsont.array):\n"; 27 - match Yamlt.decode codec2 (Bytes.Reader.of_string yaml1) with 28 - | Ok arr -> ( 29 - match arr with 30 - | None -> Printf.printf "Result: None\n" 31 - | Some a -> Printf.printf "Result: Some([%d items])\n" (Array.length a)) 32 - | Error e -> Printf.printf "Error: %s\n" e
-326
tests/bin/test_arrays.ml
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Test array codec functionality with Yamlt *) 7 - 8 - open Bytesrw 9 - 10 - (* Helper to read file *) 11 - let read_file path = 12 - let ic = open_in path in 13 - let len = in_channel_length ic in 14 - let s = really_input_string ic len in 15 - close_in ic; 16 - s 17 - 18 - (* Helper to show results *) 19 - let show_result label = function 20 - | Ok v -> Printf.printf "%s: %s\n" label v 21 - | Error e -> Printf.printf "%s: ERROR: %s\n" label e 22 - 23 - let show_result_both label json_result yaml_result = 24 - Printf.printf "JSON: "; 25 - show_result label json_result; 26 - Printf.printf "YAML: "; 27 - show_result label yaml_result 28 - 29 - (* Test: Simple int array *) 30 - let test_int_array file = 31 - let module M = struct 32 - type numbers = { values : int array } 33 - 34 - let numbers_codec = 35 - Jsont.Object.map ~kind:"Numbers" (fun values -> { values }) 36 - |> Jsont.Object.mem "values" (Jsont.array Jsont.int) ~enc:(fun n -> 37 - n.values) 38 - |> Jsont.Object.finish 39 - 40 - let show n = 41 - Printf.sprintf "[%s]" 42 - (String.concat "; " (Array.to_list (Array.map string_of_int n.values))) 43 - end in 44 - let yaml = read_file file in 45 - let json = read_file (file ^ ".json") in 46 - let json_result = Jsont_bytesrw.decode_string M.numbers_codec json in 47 - let yaml_result = Yamlt.decode M.numbers_codec (Bytes.Reader.of_string yaml) in 48 - 49 - show_result_both "int_array" 50 - (Result.map M.show json_result) 51 - (Result.map M.show yaml_result) 52 - 53 - (* Test: String array *) 54 - let test_string_array file = 55 - let module M = struct 56 - type tags = { items : string array } 57 - 58 - let tags_codec = 59 - Jsont.Object.map ~kind:"Tags" (fun items -> { items }) 60 - |> Jsont.Object.mem "items" (Jsont.array Jsont.string) ~enc:(fun t -> 61 - t.items) 62 - |> Jsont.Object.finish 63 - 64 - let show t = 65 - Printf.sprintf "[%s]" 66 - (String.concat "; " 67 - (Array.to_list (Array.map (Printf.sprintf "%S") t.items))) 68 - end in 69 - let yaml = read_file file in 70 - let json = read_file (file ^ ".json") in 71 - let json_result = Jsont_bytesrw.decode_string M.tags_codec json in 72 - let yaml_result = Yamlt.decode M.tags_codec (Bytes.Reader.of_string yaml) in 73 - 74 - show_result_both "string_array" 75 - (Result.map M.show json_result) 76 - (Result.map M.show yaml_result) 77 - 78 - (* Test: Float/number array *) 79 - let test_float_array file = 80 - let module M = struct 81 - type measurements = { values : float array } 82 - 83 - let measurements_codec = 84 - Jsont.Object.map ~kind:"Measurements" (fun values -> { values }) 85 - |> Jsont.Object.mem "values" (Jsont.array Jsont.number) ~enc:(fun m -> 86 - m.values) 87 - |> Jsont.Object.finish 88 - 89 - let show m = 90 - Printf.sprintf "[%s]" 91 - (String.concat "; " 92 - (Array.to_list (Array.map (Printf.sprintf "%.2f") m.values))) 93 - end in 94 - let yaml = read_file file in 95 - let json = read_file (file ^ ".json") in 96 - let json_result = Jsont_bytesrw.decode_string M.measurements_codec json in 97 - let yaml_result = Yamlt.decode M.measurements_codec (Bytes.Reader.of_string yaml) in 98 - 99 - show_result_both "float_array" 100 - (Result.map M.show json_result) 101 - (Result.map M.show yaml_result) 102 - 103 - (* Test: Empty array *) 104 - let test_empty_array file = 105 - let module M = struct 106 - type empty = { items : int array } 107 - 108 - let empty_codec = 109 - Jsont.Object.map ~kind:"Empty" (fun items -> { items }) 110 - |> Jsont.Object.mem "items" (Jsont.array Jsont.int) ~enc:(fun e -> 111 - e.items) 112 - |> Jsont.Object.finish 113 - 114 - let show e = Printf.sprintf "length=%d" (Stdlib.Array.length e.items) 115 - end in 116 - let yaml = read_file file in 117 - let json = read_file (file ^ ".json") in 118 - let json_result = Jsont_bytesrw.decode_string M.empty_codec json in 119 - let yaml_result = Yamlt.decode M.empty_codec (Bytes.Reader.of_string yaml) in 120 - 121 - show_result_both "empty_array" 122 - (Result.map M.show json_result) 123 - (Result.map M.show yaml_result) 124 - 125 - (* Test: Array of objects *) 126 - let test_object_array file = 127 - let module M = struct 128 - type person = { name : string; age : int } 129 - type people = { persons : person array } 130 - 131 - let person_codec = 132 - Jsont.Object.map ~kind:"Person" (fun name age -> { name; age }) 133 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun p -> p.name) 134 - |> Jsont.Object.mem "age" Jsont.int ~enc:(fun p -> p.age) 135 - |> Jsont.Object.finish 136 - 137 - let people_codec = 138 - Jsont.Object.map ~kind:"People" (fun persons -> { persons }) 139 - |> Jsont.Object.mem "persons" (Jsont.array person_codec) ~enc:(fun p -> 140 - p.persons) 141 - |> Jsont.Object.finish 142 - 143 - let show_person p = Printf.sprintf "{%s,%d}" p.name p.age 144 - 145 - let show ps = 146 - Printf.sprintf "[%s]" 147 - (String.concat "; " (Array.to_list (Array.map show_person ps.persons))) 148 - end in 149 - let yaml = read_file file in 150 - let json = read_file (file ^ ".json") in 151 - let json_result = Jsont_bytesrw.decode_string M.people_codec json in 152 - let yaml_result = Yamlt.decode M.people_codec (Bytes.Reader.of_string yaml) in 153 - 154 - show_result_both "object_array" 155 - (Result.map M.show json_result) 156 - (Result.map M.show yaml_result) 157 - 158 - (* Test: Nested arrays *) 159 - let test_nested_arrays file = 160 - let module M = struct 161 - type matrix = { data : int array array } 162 - 163 - let matrix_codec = 164 - Jsont.Object.map ~kind:"Matrix" (fun data -> { data }) 165 - |> Jsont.Object.mem "data" 166 - (Jsont.array (Jsont.array Jsont.int)) 167 - ~enc:(fun m -> m.data) 168 - |> Jsont.Object.finish 169 - 170 - let show_row row = 171 - Printf.sprintf "[%s]" 172 - (String.concat "; " (Array.to_list (Array.map string_of_int row))) 173 - 174 - let show m = 175 - Printf.sprintf "[%s]" 176 - (String.concat "; " (Array.to_list (Array.map show_row m.data))) 177 - end in 178 - let yaml = read_file file in 179 - let json = read_file (file ^ ".json") in 180 - let json_result = Jsont_bytesrw.decode_string M.matrix_codec json in 181 - let yaml_result = Yamlt.decode M.matrix_codec (Bytes.Reader.of_string yaml) in 182 - 183 - show_result_both "nested_arrays" 184 - (Result.map M.show json_result) 185 - (Result.map M.show yaml_result) 186 - 187 - (* Test: Mixed types in array (should fail with homogeneous codec) *) 188 - let test_type_mismatch file = 189 - let module M = struct 190 - type numbers = { values : int array } 191 - 192 - let numbers_codec = 193 - Jsont.Object.map ~kind:"Numbers" (fun values -> { values }) 194 - |> Jsont.Object.mem "values" (Jsont.array Jsont.int) ~enc:(fun n -> 195 - n.values) 196 - |> Jsont.Object.finish 197 - end in 198 - let yaml = read_file file in 199 - let result = Yamlt.decode M.numbers_codec (Bytes.Reader.of_string yaml) in 200 - match result with 201 - | Ok _ -> Printf.printf "Unexpected success\n" 202 - | Error e -> Printf.printf "Expected error: %s\n" e 203 - 204 - (* Test: Bool array *) 205 - let test_bool_array file = 206 - let module M = struct 207 - type flags = { values : bool array } 208 - 209 - let flags_codec = 210 - Jsont.Object.map ~kind:"Flags" (fun values -> { values }) 211 - |> Jsont.Object.mem "values" (Jsont.array Jsont.bool) ~enc:(fun f -> 212 - f.values) 213 - |> Jsont.Object.finish 214 - 215 - let show f = 216 - Printf.sprintf "[%s]" 217 - (String.concat "; " (Array.to_list (Array.map string_of_bool f.values))) 218 - end in 219 - let yaml = read_file file in 220 - let json = read_file (file ^ ".json") in 221 - let json_result = Jsont_bytesrw.decode_string M.flags_codec json in 222 - let yaml_result = Yamlt.decode M.flags_codec (Bytes.Reader.of_string yaml) in 223 - 224 - show_result_both "bool_array" 225 - (Result.map M.show json_result) 226 - (Result.map M.show yaml_result) 227 - 228 - (* Test: Array with nulls *) 229 - let test_nullable_array file = 230 - let module M = struct 231 - type nullable = { values : string option array } 232 - 233 - let nullable_codec = 234 - Jsont.Object.map ~kind:"Nullable" (fun values -> { values }) 235 - |> Jsont.Object.mem "values" 236 - (Jsont.array (Jsont.some Jsont.string)) 237 - ~enc:(fun n -> n.values) 238 - |> Jsont.Object.finish 239 - 240 - let show_opt = function None -> "null" | Some s -> Printf.sprintf "%S" s 241 - 242 - let show n = 243 - Printf.sprintf "[%s]" 244 - (String.concat "; " (Array.to_list (Array.map show_opt n.values))) 245 - end in 246 - let yaml = read_file file in 247 - let json = read_file (file ^ ".json") in 248 - let json_result = Jsont_bytesrw.decode_string M.nullable_codec json in 249 - let yaml_result = Yamlt.decode M.nullable_codec (Bytes.Reader.of_string yaml) in 250 - 251 - show_result_both "nullable_array" 252 - (Result.map M.show json_result) 253 - (Result.map M.show yaml_result) 254 - 255 - (* Test: Encoding arrays to different formats *) 256 - let test_encode_arrays () = 257 - let module M = struct 258 - type data = { numbers : int array; strings : string array } 259 - 260 - let data_codec = 261 - Jsont.Object.map ~kind:"Data" (fun numbers strings -> 262 - { numbers; strings }) 263 - |> Jsont.Object.mem "numbers" (Jsont.array Jsont.int) ~enc:(fun d -> 264 - d.numbers) 265 - |> Jsont.Object.mem "strings" (Jsont.array Jsont.string) ~enc:(fun d -> 266 - d.strings) 267 - |> Jsont.Object.finish 268 - end in 269 - let data = 270 - { M.numbers = [| 1; 2; 3; 4; 5 |]; strings = [| "hello"; "world" |] } 271 - in 272 - 273 - (* Encode to JSON *) 274 - (match Jsont_bytesrw.encode_string M.data_codec data with 275 - | Ok s -> Printf.printf "JSON: %s\n" (String.trim s) 276 - | Error e -> Printf.printf "JSON ERROR: %s\n" e); 277 - 278 - (* Encode to YAML Block *) 279 - (let b = Buffer.create 256 in 280 - let writer = Bytes.Writer.of_buffer b in 281 - match Yamlt.encode ~format:Yamlt.Block M.data_codec data ~eod:true writer with 282 - | Ok () -> Printf.printf "YAML Block:\n%s" (Buffer.contents b) 283 - | Error e -> Printf.printf "YAML Block ERROR: %s\n" e); 284 - 285 - (* Encode to YAML Flow *) 286 - let b = Buffer.create 256 in 287 - let writer = Bytes.Writer.of_buffer b in 288 - match Yamlt.encode ~format:Yamlt.Flow M.data_codec data ~eod:true writer with 289 - | Ok () -> Printf.printf "YAML Flow: %s" (Buffer.contents b) 290 - | Error e -> Printf.printf "YAML Flow ERROR: %s\n" e 291 - 292 - let () = 293 - let usage = "Usage: test_arrays <command> [args...]" in 294 - 295 - if Array.length Sys.argv < 2 then begin 296 - prerr_endline usage; 297 - exit 1 298 - end; 299 - 300 - match Sys.argv.(1) with 301 - | "int" when Array.length Sys.argv = 3 -> test_int_array Sys.argv.(2) 302 - | "string" when Array.length Sys.argv = 3 -> test_string_array Sys.argv.(2) 303 - | "float" when Array.length Sys.argv = 3 -> test_float_array Sys.argv.(2) 304 - | "empty" when Array.length Sys.argv = 3 -> test_empty_array Sys.argv.(2) 305 - | "objects" when Array.length Sys.argv = 3 -> test_object_array Sys.argv.(2) 306 - | "nested" when Array.length Sys.argv = 3 -> test_nested_arrays Sys.argv.(2) 307 - | "type-mismatch" when Array.length Sys.argv = 3 -> 308 - test_type_mismatch Sys.argv.(2) 309 - | "bool" when Array.length Sys.argv = 3 -> test_bool_array Sys.argv.(2) 310 - | "nullable" when Array.length Sys.argv = 3 -> 311 - test_nullable_array Sys.argv.(2) 312 - | "encode" when Array.length Sys.argv = 2 -> test_encode_arrays () 313 - | _ -> 314 - prerr_endline usage; 315 - prerr_endline "Commands:"; 316 - prerr_endline " int <file> - Test int array"; 317 - prerr_endline " string <file> - Test string array"; 318 - prerr_endline " float <file> - Test float array"; 319 - prerr_endline " empty <file> - Test empty array"; 320 - prerr_endline " objects <file> - Test array of objects"; 321 - prerr_endline " nested <file> - Test nested arrays"; 322 - prerr_endline " type-mismatch <file> - Test type mismatch error"; 323 - prerr_endline " bool <file> - Test bool array"; 324 - prerr_endline " nullable <file> - Test array with nulls"; 325 - prerr_endline " encode - Test encoding arrays"; 326 - exit 1
-206
tests/bin/test_complex.ml
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Test complex nested types with Yamlt *) 7 - 8 - open Bytesrw 9 - 10 - (* Helper to read file *) 11 - let read_file path = 12 - let ic = open_in path in 13 - let len = in_channel_length ic in 14 - let s = really_input_string ic len in 15 - close_in ic; 16 - s 17 - 18 - (* Helper to show results *) 19 - let show_result label = function 20 - | Ok v -> Printf.printf "%s: %s\n" label v 21 - | Error e -> Printf.printf "%s: ERROR: %s\n" label e 22 - 23 - let show_result_both label json_result yaml_result = 24 - Printf.printf "JSON: "; 25 - show_result label json_result; 26 - Printf.printf "YAML: "; 27 - show_result label yaml_result 28 - 29 - (* Test: Deeply nested objects *) 30 - let test_deep_nesting file = 31 - let module M = struct 32 - type level3 = { value : int } 33 - type level2 = { data : level3 } 34 - type level1 = { nested : level2 } 35 - type root = { top : level1 } 36 - 37 - let level3_codec = 38 - Jsont.Object.map ~kind:"Level3" (fun value -> { value }) 39 - |> Jsont.Object.mem "value" Jsont.int ~enc:(fun l -> l.value) 40 - |> Jsont.Object.finish 41 - 42 - let level2_codec = 43 - Jsont.Object.map ~kind:"Level2" (fun data -> { data }) 44 - |> Jsont.Object.mem "data" level3_codec ~enc:(fun l -> l.data) 45 - |> Jsont.Object.finish 46 - 47 - let level1_codec = 48 - Jsont.Object.map ~kind:"Level1" (fun nested -> { nested }) 49 - |> Jsont.Object.mem "nested" level2_codec ~enc:(fun l -> l.nested) 50 - |> Jsont.Object.finish 51 - 52 - let root_codec = 53 - Jsont.Object.map ~kind:"Root" (fun top -> { top }) 54 - |> Jsont.Object.mem "top" level1_codec ~enc:(fun r -> r.top) 55 - |> Jsont.Object.finish 56 - 57 - let show r = Printf.sprintf "depth=4, value=%d" r.top.nested.data.value 58 - end in 59 - let yaml = read_file file in 60 - let json = read_file (file ^ ".json") in 61 - let json_result = Jsont_bytesrw.decode_string M.root_codec json in 62 - let yaml_result = Yamlt.decode M.root_codec (Bytes.Reader.of_string yaml) in 63 - 64 - show_result_both "deep_nesting" 65 - (Result.map M.show json_result) 66 - (Result.map M.show yaml_result) 67 - 68 - (* Test: Array of objects with nested arrays *) 69 - let test_mixed_structure file = 70 - let module M = struct 71 - type item = { id : int; tags : string array } 72 - type collection = { name : string; items : item array } 73 - 74 - let item_codec = 75 - Jsont.Object.map ~kind:"Item" (fun id tags -> { id; tags }) 76 - |> Jsont.Object.mem "id" Jsont.int ~enc:(fun i -> i.id) 77 - |> Jsont.Object.mem "tags" (Jsont.array Jsont.string) ~enc:(fun i -> 78 - i.tags) 79 - |> Jsont.Object.finish 80 - 81 - let collection_codec = 82 - Jsont.Object.map ~kind:"Collection" (fun name items -> { name; items }) 83 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun c -> c.name) 84 - |> Jsont.Object.mem "items" (Jsont.array item_codec) ~enc:(fun c -> 85 - c.items) 86 - |> Jsont.Object.finish 87 - 88 - let show c = 89 - let total_tags = 90 - Stdlib.Array.fold_left 91 - (fun acc item -> acc + Stdlib.Array.length item.tags) 92 - 0 c.items 93 - in 94 - Printf.sprintf "name=%S, items=%d, total_tags=%d" c.name 95 - (Stdlib.Array.length c.items) 96 - total_tags 97 - end in 98 - let yaml = read_file file in 99 - let json = read_file (file ^ ".json") in 100 - let json_result = Jsont_bytesrw.decode_string M.collection_codec json in 101 - let yaml_result = Yamlt.decode M.collection_codec (Bytes.Reader.of_string yaml) in 102 - 103 - show_result_both "mixed_structure" 104 - (Result.map M.show json_result) 105 - (Result.map M.show yaml_result) 106 - 107 - (* Test: Complex optional and nullable combinations *) 108 - let test_complex_optional file = 109 - let module M = struct 110 - type config = { 111 - host : string; 112 - port : int option; 113 - ssl : bool option; 114 - cert_path : string option; 115 - fallback_hosts : string array option; 116 - } 117 - 118 - let config_codec = 119 - Jsont.Object.map ~kind:"Config" 120 - (fun host port ssl cert_path fallback_hosts -> 121 - { host; port; ssl; cert_path; fallback_hosts }) 122 - |> Jsont.Object.mem "host" Jsont.string ~enc:(fun c -> c.host) 123 - |> Jsont.Object.opt_mem "port" Jsont.int ~enc:(fun c -> c.port) 124 - |> Jsont.Object.opt_mem "ssl" Jsont.bool ~enc:(fun c -> c.ssl) 125 - |> Jsont.Object.opt_mem "cert_path" Jsont.string ~enc:(fun c -> 126 - c.cert_path) 127 - |> Jsont.Object.opt_mem "fallback_hosts" (Jsont.array Jsont.string) 128 - ~enc:(fun c -> c.fallback_hosts) 129 - |> Jsont.Object.finish 130 - 131 - let show c = 132 - let port_str = 133 - match c.port with None -> "None" | Some p -> string_of_int p 134 - in 135 - let ssl_str = 136 - match c.ssl with None -> "None" | Some b -> string_of_bool b 137 - in 138 - let fallbacks = 139 - match c.fallback_hosts with 140 - | None -> 0 141 - | Some arr -> Stdlib.Array.length arr 142 - in 143 - Printf.sprintf "host=%S, port=%s, ssl=%s, fallbacks=%d" c.host port_str 144 - ssl_str fallbacks 145 - end in 146 - let yaml = read_file file in 147 - let json = read_file (file ^ ".json") in 148 - let json_result = Jsont_bytesrw.decode_string M.config_codec json in 149 - let yaml_result = Yamlt.decode M.config_codec (Bytes.Reader.of_string yaml) in 150 - 151 - show_result_both "complex_optional" 152 - (Result.map M.show json_result) 153 - (Result.map M.show yaml_result) 154 - 155 - (* Test: Heterogeneous data via any type *) 156 - let test_heterogeneous file = 157 - let module M = struct 158 - type data = { mixed : Jsont.json array } 159 - 160 - let data_codec = 161 - Jsont.Object.map ~kind:"Data" (fun mixed -> { mixed }) 162 - |> Jsont.Object.mem "mixed" 163 - (Jsont.array (Jsont.any ())) 164 - ~enc:(fun d -> d.mixed) 165 - |> Jsont.Object.finish 166 - 167 - let show d = Printf.sprintf "items=%d" (Stdlib.Array.length d.mixed) 168 - end in 169 - let yaml = read_file file in 170 - let json = read_file (file ^ ".json") in 171 - let json_result = Jsont_bytesrw.decode_string M.data_codec json in 172 - let yaml_result = Yamlt.decode M.data_codec (Bytes.Reader.of_string yaml) in 173 - 174 - show_result_both "heterogeneous" 175 - (Result.map M.show json_result) 176 - (Result.map M.show yaml_result) 177 - 178 - let () = 179 - let usage = "Usage: test_complex <command> [args...]" in 180 - 181 - if Stdlib.Array.length Sys.argv < 2 then begin 182 - prerr_endline usage; 183 - exit 1 184 - end; 185 - 186 - match Sys.argv.(1) with 187 - | "deep-nesting" when Stdlib.Array.length Sys.argv = 3 -> 188 - test_deep_nesting Sys.argv.(2) 189 - | "mixed-structure" when Stdlib.Array.length Sys.argv = 3 -> 190 - test_mixed_structure Sys.argv.(2) 191 - | "complex-optional" when Stdlib.Array.length Sys.argv = 3 -> 192 - test_complex_optional Sys.argv.(2) 193 - | "heterogeneous" when Stdlib.Array.length Sys.argv = 3 -> 194 - test_heterogeneous Sys.argv.(2) 195 - | _ -> 196 - prerr_endline usage; 197 - prerr_endline "Commands:"; 198 - prerr_endline " deep-nesting <file> - Test deeply nested objects"; 199 - prerr_endline 200 - " mixed-structure <file> - Test arrays of objects with nested arrays"; 201 - prerr_endline 202 - " complex-optional <file> - Test complex optional/nullable \ 203 - combinations"; 204 - prerr_endline 205 - " heterogeneous <file> - Test heterogeneous data via any type"; 206 - exit 1
-96
tests/bin/test_comprehensive.ml
··· 1 - open Bytesrw 2 - 3 - let () = 4 - (* Test 1: Null handling with option types *) 5 - Printf.printf "=== NULL HANDLING ===\n"; 6 - let opt_codec = 7 - Jsont.Object.map ~kind:"Test" (fun v -> v) 8 - |> Jsont.Object.mem "value" (Jsont.option Jsont.string) ~enc:(fun v -> v) 9 - |> Jsont.Object.finish 10 - in 11 - 12 - (match Yamlt.decode opt_codec (Bytes.Reader.of_string "value: null") with 13 - | Ok None -> Printf.printf "✓ Plain 'null' with option codec: None\n" 14 - | _ -> Printf.printf "✗ FAIL\n"); 15 - 16 - (match Yamlt.decode opt_codec (Bytes.Reader.of_string "value: hello") with 17 - | Ok (Some "hello") -> 18 - Printf.printf "✓ Plain 'hello' with option codec: Some(hello)\n" 19 - | _ -> Printf.printf "✗ FAIL\n"); 20 - 21 - let string_codec = 22 - Jsont.Object.map ~kind:"Test" (fun v -> v) 23 - |> Jsont.Object.mem "value" Jsont.string ~enc:(fun v -> v) 24 - |> Jsont.Object.finish 25 - in 26 - 27 - (match Yamlt.decode string_codec (Bytes.Reader.of_string "value: null") with 28 - | Error _ -> 29 - Printf.printf "✓ Plain 'null' with string codec: ERROR (expected)\n" 30 - | _ -> Printf.printf "✗ FAIL\n"); 31 - 32 - (match Yamlt.decode string_codec (Bytes.Reader.of_string "value: \"\"") with 33 - | Ok "" -> Printf.printf "✓ Quoted empty string: \"\"\n" 34 - | _ -> Printf.printf "✗ FAIL\n"); 35 - 36 - (match Yamlt.decode string_codec (Bytes.Reader.of_string "value: \"null\"") with 37 - | Ok "null" -> Printf.printf "✓ Quoted 'null': \"null\"\n" 38 - | _ -> Printf.printf "✗ FAIL\n"); 39 - 40 - (* Test 2: Number formats *) 41 - Printf.printf "\n=== NUMBER FORMATS ===\n"; 42 - let num_codec = 43 - Jsont.Object.map ~kind:"Test" (fun v -> v) 44 - |> Jsont.Object.mem "value" Jsont.number ~enc:(fun v -> v) 45 - |> Jsont.Object.finish 46 - in 47 - 48 - (match Yamlt.decode num_codec (Bytes.Reader.of_string "value: 0xFF") with 49 - | Ok 255. -> Printf.printf "✓ Hex 0xFF: 255\n" 50 - | _ -> Printf.printf "✗ FAIL\n"); 51 - 52 - (match Yamlt.decode num_codec (Bytes.Reader.of_string "value: 0o77") with 53 - | Ok 63. -> Printf.printf "✓ Octal 0o77: 63\n" 54 - | _ -> Printf.printf "✗ FAIL\n"); 55 - 56 - (match Yamlt.decode num_codec (Bytes.Reader.of_string "value: 0b1010") with 57 - | Ok 10. -> Printf.printf "✓ Binary 0b1010: 10\n" 58 - | _ -> Printf.printf "✗ FAIL\n"); 59 - 60 - (* Test 3: Optional arrays *) 61 - Printf.printf "\n=== OPTIONAL ARRAYS ===\n"; 62 - let opt_array_codec = 63 - Jsont.Object.map ~kind:"Test" (fun v -> v) 64 - |> Jsont.Object.opt_mem "values" (Jsont.array Jsont.string) ~enc:(fun v -> 65 - v) 66 - |> Jsont.Object.finish 67 - in 68 - 69 - (match Yamlt.decode opt_array_codec (Bytes.Reader.of_string "values: [a, b, c]") with 70 - | Ok (Some arr) when Array.length arr = 3 -> 71 - Printf.printf "✓ Optional array [a, b, c]: Some([3 items])\n" 72 - | _ -> Printf.printf "✗ FAIL\n"); 73 - 74 - (match Yamlt.decode opt_array_codec (Bytes.Reader.of_string "{}") with 75 - | Ok None -> Printf.printf "✓ Missing optional array: None\n" 76 - | _ -> Printf.printf "✗ FAIL\n"); 77 - 78 - (* Test 4: Flow encoding *) 79 - Printf.printf "\n=== FLOW ENCODING ===\n"; 80 - let encode_codec = 81 - Jsont.Object.map ~kind:"Test" (fun name values -> (name, values)) 82 - |> Jsont.Object.mem "name" Jsont.string ~enc:fst 83 - |> Jsont.Object.mem "values" (Jsont.array Jsont.number) ~enc:snd 84 - |> Jsont.Object.finish 85 - in 86 - 87 - let b = Buffer.create 256 in 88 - let writer = Bytes.Writer.of_buffer b in 89 - match 90 - Yamlt.encode ~format:Flow encode_codec ("test", [| 1.; 2.; 3. |]) ~eod:true writer 91 - with 92 - | Ok () 93 - when String.equal (Buffer.contents b) "{name: test, values: [1.0, 2.0, 3.0]}\n" -> 94 - Printf.printf "✓ Flow encoding with comma separator\n" 95 - | Ok () -> Printf.printf "✗ FAIL: %S\n" (Buffer.contents b) 96 - | Error e -> Printf.printf "✗ ERROR: %s\n" e
-214
tests/bin/test_edge.ml
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Test edge cases with Yamlt *) 7 - 8 - open Bytesrw 9 - 10 - (* Helper to read file *) 11 - let read_file path = 12 - let ic = open_in path in 13 - let len = in_channel_length ic in 14 - let s = really_input_string ic len in 15 - close_in ic; 16 - s 17 - 18 - (* Helper to show results *) 19 - let show_result label = function 20 - | Ok v -> Printf.printf "%s: %s\n" label v 21 - | Error e -> Printf.printf "%s: ERROR: %s\n" label e 22 - 23 - let show_result_both label json_result yaml_result = 24 - Printf.printf "JSON: "; 25 - show_result label json_result; 26 - Printf.printf "YAML: "; 27 - show_result label yaml_result 28 - 29 - (* Test: Very large numbers *) 30 - let test_large_numbers file = 31 - let module M = struct 32 - type numbers = { 33 - large_int : float; 34 - large_float : float; 35 - small_float : float; 36 - } 37 - 38 - let numbers_codec = 39 - Jsont.Object.map ~kind:"Numbers" (fun large_int large_float small_float -> 40 - { large_int; large_float; small_float }) 41 - |> Jsont.Object.mem "large_int" Jsont.number ~enc:(fun n -> n.large_int) 42 - |> Jsont.Object.mem "large_float" Jsont.number ~enc:(fun n -> 43 - n.large_float) 44 - |> Jsont.Object.mem "small_float" Jsont.number ~enc:(fun n -> 45 - n.small_float) 46 - |> Jsont.Object.finish 47 - 48 - let show n = 49 - Printf.sprintf "large_int=%.0f, large_float=%e, small_float=%e" 50 - n.large_int n.large_float n.small_float 51 - end in 52 - let yaml = read_file file in 53 - let json = read_file (file ^ ".json") in 54 - let json_result = Jsont_bytesrw.decode_string M.numbers_codec json in 55 - let yaml_result = Yamlt.decode M.numbers_codec (Bytes.Reader.of_string yaml) in 56 - 57 - show_result_both "large_numbers" 58 - (Result.map M.show json_result) 59 - (Result.map M.show yaml_result) 60 - 61 - (* Test: Special characters in strings *) 62 - let test_special_chars file = 63 - let module M = struct 64 - type text = { content : string } 65 - 66 - let text_codec = 67 - Jsont.Object.map ~kind:"Text" (fun content -> { content }) 68 - |> Jsont.Object.mem "content" Jsont.string ~enc:(fun t -> t.content) 69 - |> Jsont.Object.finish 70 - 71 - let show t = 72 - Printf.sprintf "length=%d, contains_newline=%b, contains_tab=%b" 73 - (String.length t.content) 74 - (String.contains t.content '\n') 75 - (String.contains t.content '\t') 76 - end in 77 - let yaml = read_file file in 78 - let json = read_file (file ^ ".json") in 79 - let json_result = Jsont_bytesrw.decode_string M.text_codec json in 80 - let yaml_result = Yamlt.decode M.text_codec (Bytes.Reader.of_string yaml) in 81 - 82 - show_result_both "special_chars" 83 - (Result.map M.show json_result) 84 - (Result.map M.show yaml_result) 85 - 86 - (* Test: Unicode strings *) 87 - let test_unicode file = 88 - let module M = struct 89 - type text = { emoji : string; chinese : string; rtl : string } 90 - 91 - let text_codec = 92 - Jsont.Object.map ~kind:"Text" (fun emoji chinese rtl -> 93 - { emoji; chinese; rtl }) 94 - |> Jsont.Object.mem "emoji" Jsont.string ~enc:(fun t -> t.emoji) 95 - |> Jsont.Object.mem "chinese" Jsont.string ~enc:(fun t -> t.chinese) 96 - |> Jsont.Object.mem "rtl" Jsont.string ~enc:(fun t -> t.rtl) 97 - |> Jsont.Object.finish 98 - 99 - let show t = 100 - Printf.sprintf "emoji=%S, chinese=%S, rtl=%S" t.emoji t.chinese t.rtl 101 - end in 102 - let yaml = read_file file in 103 - let json = read_file (file ^ ".json") in 104 - let json_result = Jsont_bytesrw.decode_string M.text_codec json in 105 - let yaml_result = Yamlt.decode M.text_codec (Bytes.Reader.of_string yaml) in 106 - 107 - show_result_both "unicode" 108 - (Result.map M.show json_result) 109 - (Result.map M.show yaml_result) 110 - 111 - (* Test: Empty collections *) 112 - let test_empty_collections file = 113 - let module M = struct 114 - type data = { empty_array : int array; empty_object_array : unit array } 115 - 116 - let data_codec = 117 - Jsont.Object.map ~kind:"Data" (fun empty_array empty_object_array -> 118 - { empty_array; empty_object_array }) 119 - |> Jsont.Object.mem "empty_array" (Jsont.array Jsont.int) ~enc:(fun d -> 120 - d.empty_array) 121 - |> Jsont.Object.mem "empty_object_array" 122 - (Jsont.array (Jsont.null ())) 123 - ~enc:(fun d -> d.empty_object_array) 124 - |> Jsont.Object.finish 125 - 126 - let show d = 127 - Printf.sprintf "empty_array_len=%d, empty_object_array_len=%d" 128 - (Stdlib.Array.length d.empty_array) 129 - (Stdlib.Array.length d.empty_object_array) 130 - end in 131 - let yaml = read_file file in 132 - let json = read_file (file ^ ".json") in 133 - let json_result = Jsont_bytesrw.decode_string M.data_codec json in 134 - let yaml_result = Yamlt.decode M.data_codec (Bytes.Reader.of_string yaml) in 135 - 136 - show_result_both "empty_collections" 137 - (Result.map M.show json_result) 138 - (Result.map M.show yaml_result) 139 - 140 - (* Test: Key names with special characters *) 141 - let test_special_keys file = 142 - let module M = struct 143 - let show j = 144 - match Jsont.Json.decode (Jsont.any ()) j with 145 - | Ok (Jsont.Object _) -> "valid_object" 146 - | Ok _ -> "not_object" 147 - | Error _ -> "decode_error" 148 - end in 149 - let yaml = read_file file in 150 - let json = read_file (file ^ ".json") in 151 - let json_result = Jsont_bytesrw.decode_string (Jsont.any ()) json in 152 - let yaml_result = Yamlt.decode (Jsont.any ()) (Bytes.Reader.of_string yaml) in 153 - 154 - show_result_both "special_keys" 155 - (Result.map M.show json_result) 156 - (Result.map M.show yaml_result) 157 - 158 - (* Test: Single-element arrays *) 159 - let test_single_element file = 160 - let module M = struct 161 - type data = { single : int array } 162 - 163 - let data_codec = 164 - Jsont.Object.map ~kind:"Data" (fun single -> { single }) 165 - |> Jsont.Object.mem "single" (Jsont.array Jsont.int) ~enc:(fun d -> 166 - d.single) 167 - |> Jsont.Object.finish 168 - 169 - let show d = 170 - Printf.sprintf "length=%d, value=%d" 171 - (Stdlib.Array.length d.single) 172 - (if Stdlib.Array.length d.single > 0 then d.single.(0) else 0) 173 - end in 174 - let yaml = read_file file in 175 - let json = read_file (file ^ ".json") in 176 - let json_result = Jsont_bytesrw.decode_string M.data_codec json in 177 - let yaml_result = Yamlt.decode M.data_codec (Bytes.Reader.of_string yaml) in 178 - 179 - show_result_both "single_element" 180 - (Result.map M.show json_result) 181 - (Result.map M.show yaml_result) 182 - 183 - let () = 184 - let usage = "Usage: test_edge <command> [args...]" in 185 - 186 - if Stdlib.Array.length Sys.argv < 2 then begin 187 - prerr_endline usage; 188 - exit 1 189 - end; 190 - 191 - match Sys.argv.(1) with 192 - | "large-numbers" when Stdlib.Array.length Sys.argv = 3 -> 193 - test_large_numbers Sys.argv.(2) 194 - | "special-chars" when Stdlib.Array.length Sys.argv = 3 -> 195 - test_special_chars Sys.argv.(2) 196 - | "unicode" when Stdlib.Array.length Sys.argv = 3 -> test_unicode Sys.argv.(2) 197 - | "empty-collections" when Stdlib.Array.length Sys.argv = 3 -> 198 - test_empty_collections Sys.argv.(2) 199 - | "special-keys" when Stdlib.Array.length Sys.argv = 3 -> 200 - test_special_keys Sys.argv.(2) 201 - | "single-element" when Stdlib.Array.length Sys.argv = 3 -> 202 - test_single_element Sys.argv.(2) 203 - | _ -> 204 - prerr_endline usage; 205 - prerr_endline "Commands:"; 206 - prerr_endline " large-numbers <file> - Test very large numbers"; 207 - prerr_endline 208 - " special-chars <file> - Test special characters in strings"; 209 - prerr_endline " unicode <file> - Test Unicode strings"; 210 - prerr_endline " empty-collections <file> - Test empty collections"; 211 - prerr_endline 212 - " special-keys <file> - Test special characters in keys"; 213 - prerr_endline " single-element <file> - Test single-element arrays"; 214 - exit 1
-21
tests/bin/test_flow_newline.ml
··· 1 - open Bytesrw 2 - 3 - let () = 4 - let encode_codec = 5 - Jsont.Object.map ~kind:"Test" (fun name values -> (name, values)) 6 - |> Jsont.Object.mem "name" Jsont.string ~enc:fst 7 - |> Jsont.Object.mem "values" (Jsont.array Jsont.number) ~enc:snd 8 - |> Jsont.Object.finish 9 - in 10 - 11 - let b = Buffer.create 256 in 12 - let writer = Bytes.Writer.of_buffer b in 13 - match 14 - Yamlt.encode ~format:Flow encode_codec ("test", [| 1.; 2.; 3. |]) ~eod:true writer 15 - with 16 - | Ok () -> 17 - let yaml_flow = Buffer.contents b in 18 - Printf.printf "Length: %d\n" (String.length yaml_flow); 19 - Printf.printf "Repr: %S\n" yaml_flow; 20 - Printf.printf "Output:\n%s" yaml_flow 21 - | Error e -> Printf.printf "Error: %s\n" e
-248
tests/bin/test_formats.ml
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Test format-specific features with Yamlt *) 7 - 8 - open Bytesrw 9 - 10 - (* Helper to read file *) 11 - let read_file path = 12 - let ic = open_in path in 13 - let len = in_channel_length ic in 14 - let s = really_input_string ic len in 15 - close_in ic; 16 - s 17 - 18 - (* Helper to show results *) 19 - let show_result label = function 20 - | Ok v -> Printf.printf "%s: %s\n" label v 21 - | Error e -> Printf.printf "%s: ERROR: %s\n" label e 22 - 23 - let show_result_both label json_result yaml_result = 24 - Printf.printf "JSON: "; 25 - show_result label json_result; 26 - Printf.printf "YAML: "; 27 - show_result label yaml_result 28 - 29 - (* Test: Multi-line strings - literal style *) 30 - let test_literal_string file = 31 - let module M = struct 32 - type text = { content : string } 33 - 34 - let text_codec = 35 - Jsont.Object.map ~kind:"Text" (fun content -> { content }) 36 - |> Jsont.Object.mem "content" Jsont.string ~enc:(fun t -> t.content) 37 - |> Jsont.Object.finish 38 - 39 - let show t = 40 - Printf.sprintf "lines=%d, length=%d" 41 - (List.length (String.split_on_char '\n' t.content)) 42 - (String.length t.content) 43 - end in 44 - let yaml = read_file file in 45 - let json = read_file (file ^ ".json") in 46 - let json_result = Jsont_bytesrw.decode_string M.text_codec json in 47 - let yaml_result = Yamlt.decode M.text_codec (Bytes.Reader.of_string yaml) in 48 - 49 - show_result_both "literal_string" 50 - (Result.map M.show json_result) 51 - (Result.map M.show yaml_result) 52 - 53 - (* Test: Multi-line strings - folded style *) 54 - let test_folded_string file = 55 - let module M = struct 56 - type text = { content : string } 57 - 58 - let text_codec = 59 - Jsont.Object.map ~kind:"Text" (fun content -> { content }) 60 - |> Jsont.Object.mem "content" Jsont.string ~enc:(fun t -> t.content) 61 - |> Jsont.Object.finish 62 - 63 - let show t = 64 - Printf.sprintf "length=%d, newlines=%d" (String.length t.content) 65 - (List.length 66 - (List.filter 67 - (fun c -> c = '\n') 68 - (List.init (String.length t.content) (String.get t.content)))) 69 - end in 70 - let yaml = read_file file in 71 - let json = read_file (file ^ ".json") in 72 - let json_result = Jsont_bytesrw.decode_string M.text_codec json in 73 - let yaml_result = Yamlt.decode M.text_codec (Bytes.Reader.of_string yaml) in 74 - 75 - show_result_both "folded_string" 76 - (Result.map M.show json_result) 77 - (Result.map M.show yaml_result) 78 - 79 - (* Test: Number formats - hex, octal, binary *) 80 - let test_number_formats file = 81 - let module M = struct 82 - type numbers = { hex : float; octal : float; binary : float } 83 - 84 - let numbers_codec = 85 - Jsont.Object.map ~kind:"Numbers" (fun hex octal binary -> 86 - { hex; octal; binary }) 87 - |> Jsont.Object.mem "hex" Jsont.number ~enc:(fun n -> n.hex) 88 - |> Jsont.Object.mem "octal" Jsont.number ~enc:(fun n -> n.octal) 89 - |> Jsont.Object.mem "binary" Jsont.number ~enc:(fun n -> n.binary) 90 - |> Jsont.Object.finish 91 - 92 - let show n = 93 - Printf.sprintf "hex=%.0f, octal=%.0f, binary=%.0f" n.hex n.octal n.binary 94 - end in 95 - let yaml = read_file file in 96 - let json = read_file (file ^ ".json") in 97 - let json_result = Jsont_bytesrw.decode_string M.numbers_codec json in 98 - let yaml_result = Yamlt.decode M.numbers_codec (Bytes.Reader.of_string yaml) in 99 - 100 - show_result_both "number_formats" 101 - (Result.map M.show json_result) 102 - (Result.map M.show yaml_result) 103 - 104 - (* Test: Block vs Flow style encoding *) 105 - let test_encode_styles () = 106 - let module M = struct 107 - type data = { name : string; values : int array; nested : nested_data } 108 - and nested_data = { enabled : bool; count : int } 109 - 110 - let nested_codec = 111 - Jsont.Object.map ~kind:"Nested" (fun enabled count -> { enabled; count }) 112 - |> Jsont.Object.mem "enabled" Jsont.bool ~enc:(fun n -> n.enabled) 113 - |> Jsont.Object.mem "count" Jsont.int ~enc:(fun n -> n.count) 114 - |> Jsont.Object.finish 115 - 116 - let data_codec = 117 - Jsont.Object.map ~kind:"Data" (fun name values nested -> 118 - { name; values; nested }) 119 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun d -> d.name) 120 - |> Jsont.Object.mem "values" (Jsont.array Jsont.int) ~enc:(fun d -> 121 - d.values) 122 - |> Jsont.Object.mem "nested" nested_codec ~enc:(fun d -> d.nested) 123 - |> Jsont.Object.finish 124 - end in 125 - let data = 126 - { 127 - M.name = "test"; 128 - values = [| 1; 2; 3 |]; 129 - nested = { enabled = true; count = 5 }; 130 - } 131 - in 132 - 133 - (* Encode to YAML Block style *) 134 - (let b = Buffer.create 256 in 135 - let writer = Bytes.Writer.of_buffer b in 136 - match Yamlt.encode ~format:Yamlt.Block M.data_codec data ~eod:true writer with 137 - | Ok () -> Printf.printf "YAML Block:\n%s\n" (Buffer.contents b) 138 - | Error e -> Printf.printf "YAML Block ERROR: %s\n" e); 139 - 140 - (* Encode to YAML Flow style *) 141 - let b = Buffer.create 256 in 142 - let writer = Bytes.Writer.of_buffer b in 143 - match Yamlt.encode ~format:Yamlt.Flow M.data_codec data ~eod:true writer with 144 - | Ok () -> Printf.printf "YAML Flow:\n%s\n" (Buffer.contents b) 145 - | Error e -> Printf.printf "YAML Flow ERROR: %s\n" e 146 - 147 - (* Test: Comments in YAML (should be ignored) *) 148 - let test_comments file = 149 - let module M = struct 150 - type config = { host : string; port : int; debug : bool } 151 - 152 - let config_codec = 153 - Jsont.Object.map ~kind:"Config" (fun host port debug -> 154 - { host; port; debug }) 155 - |> Jsont.Object.mem "host" Jsont.string ~enc:(fun c -> c.host) 156 - |> Jsont.Object.mem "port" Jsont.int ~enc:(fun c -> c.port) 157 - |> Jsont.Object.mem "debug" Jsont.bool ~enc:(fun c -> c.debug) 158 - |> Jsont.Object.finish 159 - 160 - let show c = 161 - Printf.sprintf "host=%S, port=%d, debug=%b" c.host c.port c.debug 162 - end in 163 - let yaml = read_file file in 164 - let yaml_result = Yamlt.decode M.config_codec (Bytes.Reader.of_string yaml) in 165 - 166 - match yaml_result with 167 - | Ok v -> Printf.printf "YAML (with comments): %s\n" (M.show v) 168 - | Error e -> Printf.printf "YAML ERROR: %s\n" e 169 - 170 - (* Test: Empty documents and null documents *) 171 - let test_empty_document file = 172 - let module M = struct 173 - type wrapper = { value : string option } 174 - 175 - let wrapper_codec = 176 - Jsont.Object.map ~kind:"Wrapper" (fun value -> { value }) 177 - |> Jsont.Object.mem "value" (Jsont.some Jsont.string) ~enc:(fun w -> 178 - w.value) 179 - |> Jsont.Object.finish 180 - 181 - let show w = 182 - match w.value with 183 - | None -> "value=None" 184 - | Some s -> Printf.sprintf "value=Some(%S)" s 185 - end in 186 - let yaml = read_file file in 187 - let json = read_file (file ^ ".json") in 188 - let json_result = Jsont_bytesrw.decode_string M.wrapper_codec json in 189 - let yaml_result = Yamlt.decode M.wrapper_codec (Bytes.Reader.of_string yaml) in 190 - 191 - show_result_both "empty_document" 192 - (Result.map M.show json_result) 193 - (Result.map M.show yaml_result) 194 - 195 - (* Test: Explicit typing with tags (if supported) *) 196 - let test_explicit_tags file = 197 - let module M = struct 198 - type value_holder = { data : string } 199 - 200 - let value_codec = 201 - Jsont.Object.map ~kind:"ValueHolder" (fun data -> { data }) 202 - |> Jsont.Object.mem "data" Jsont.string ~enc:(fun v -> v.data) 203 - |> Jsont.Object.finish 204 - 205 - let show v = Printf.sprintf "data=%S" v.data 206 - end in 207 - let yaml = read_file file in 208 - let yaml_result = Yamlt.decode M.value_codec (Bytes.Reader.of_string yaml) in 209 - 210 - match yaml_result with 211 - | Ok v -> Printf.printf "YAML (with tags): %s\n" (M.show v) 212 - | Error e -> Printf.printf "YAML ERROR: %s\n" e 213 - 214 - let () = 215 - let usage = "Usage: test_formats <command> [args...]" in 216 - 217 - if Stdlib.Array.length Sys.argv < 2 then begin 218 - prerr_endline usage; 219 - exit 1 220 - end; 221 - 222 - match Sys.argv.(1) with 223 - | "literal" when Stdlib.Array.length Sys.argv = 3 -> 224 - test_literal_string Sys.argv.(2) 225 - | "folded" when Stdlib.Array.length Sys.argv = 3 -> 226 - test_folded_string Sys.argv.(2) 227 - | "number-formats" when Stdlib.Array.length Sys.argv = 3 -> 228 - test_number_formats Sys.argv.(2) 229 - | "encode-styles" when Stdlib.Array.length Sys.argv = 2 -> 230 - test_encode_styles () 231 - | "comments" when Stdlib.Array.length Sys.argv = 3 -> 232 - test_comments Sys.argv.(2) 233 - | "empty-doc" when Stdlib.Array.length Sys.argv = 3 -> 234 - test_empty_document Sys.argv.(2) 235 - | "explicit-tags" when Stdlib.Array.length Sys.argv = 3 -> 236 - test_explicit_tags Sys.argv.(2) 237 - | _ -> 238 - prerr_endline usage; 239 - prerr_endline "Commands:"; 240 - prerr_endline " literal <file> - Test literal multi-line strings"; 241 - prerr_endline " folded <file> - Test folded multi-line strings"; 242 - prerr_endline 243 - " number-formats <file> - Test hex/octal/binary number formats"; 244 - prerr_endline " encode-styles - Test block vs flow encoding"; 245 - prerr_endline " comments <file> - Test YAML with comments"; 246 - prerr_endline " empty-doc <file> - Test empty documents"; 247 - prerr_endline " explicit-tags <file> - Test explicit type tags"; 248 - exit 1
-270
tests/bin/test_locations.ml
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Test location and layout preservation options with Yamlt codec *) 7 - 8 - (* Helper to read file *) 9 - open Bytesrw 10 - 11 - let read_file path = 12 - let ic = open_in path in 13 - let len = in_channel_length ic in 14 - let s = really_input_string ic len in 15 - close_in ic; 16 - s 17 - 18 - (* Helper to show results *) 19 - let show_result label = function 20 - | Ok _ -> Printf.printf "%s: OK\n" label 21 - | Error e -> Printf.printf "%s:\n%s\n" label e 22 - 23 - (* Test: Compare error messages with and without locs *) 24 - let test_error_precision file = 25 - let yaml = read_file file in 26 - 27 - (* Define a codec that will fail on type mismatch *) 28 - let codec = 29 - Jsont.Object.map ~kind:"Person" (fun name age -> (name, age)) 30 - |> Jsont.Object.mem "name" Jsont.string ~enc:fst 31 - |> Jsont.Object.mem "age" Jsont.int ~enc:snd 32 - |> Jsont.Object.finish 33 - in 34 - 35 - Printf.printf "=== Without locs (default) ===\n"; 36 - let result_no_locs = Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:false in 37 - show_result "Error message" result_no_locs; 38 - 39 - Printf.printf "\n=== With locs=true ===\n"; 40 - let result_with_locs = Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:true in 41 - show_result "Error message" result_with_locs 42 - 43 - (* Test: Show error locations for nested structures *) 44 - let test_nested_error file = 45 - let yaml = read_file file in 46 - 47 - (* Nested object codec *) 48 - let address_codec = 49 - Jsont.Object.map ~kind:"Address" (fun street city zip -> 50 - (street, city, zip)) 51 - |> Jsont.Object.mem "street" Jsont.string ~enc:(fun (s, _, _) -> s) 52 - |> Jsont.Object.mem "city" Jsont.string ~enc:(fun (_, c, _) -> c) 53 - |> Jsont.Object.mem "zip" Jsont.int ~enc:(fun (_, _, z) -> z) 54 - |> Jsont.Object.finish 55 - in 56 - 57 - let codec = 58 - Jsont.Object.map ~kind:"Employee" (fun name address -> (name, address)) 59 - |> Jsont.Object.mem "name" Jsont.string ~enc:fst 60 - |> Jsont.Object.mem "address" address_codec ~enc:snd 61 - |> Jsont.Object.finish 62 - in 63 - 64 - Printf.printf "=== Without locs (default) ===\n"; 65 - let result_no_locs = Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:false in 66 - show_result "Nested error" result_no_locs; 67 - 68 - Printf.printf "\n=== With locs=true ===\n"; 69 - let result_with_locs = Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:true in 70 - show_result "Nested error" result_with_locs 71 - 72 - (* Test: Array element error locations *) 73 - let test_array_error file = 74 - let yaml = read_file file in 75 - 76 - (* Array codec *) 77 - let codec = 78 - Jsont.Object.map ~kind:"Numbers" (fun nums -> nums) 79 - |> Jsont.Object.mem "values" (Jsont.array Jsont.int) ~enc:(fun n -> n) 80 - |> Jsont.Object.finish 81 - in 82 - 83 - Printf.printf "=== Without locs (default) ===\n"; 84 - let result_no_locs = Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:false in 85 - show_result "Array error" result_no_locs; 86 - 87 - Printf.printf "\n=== With locs=true ===\n"; 88 - let result_with_locs = Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:true in 89 - show_result "Array error" result_with_locs 90 - 91 - (* Test: Layout preservation - check if we can decode with layout info *) 92 - let test_layout_preservation file = 93 - let yaml = read_file file in 94 - 95 - let codec = 96 - Jsont.Object.map ~kind:"Config" (fun host port -> (host, port)) 97 - |> Jsont.Object.mem "host" Jsont.string ~enc:fst 98 - |> Jsont.Object.mem "port" Jsont.int ~enc:snd 99 - |> Jsont.Object.finish 100 - in 101 - 102 - Printf.printf "=== Without layout (default) ===\n"; 103 - (match Yamlt.decode codec (Bytes.Reader.of_string yaml) ~layout:false with 104 - | Ok (host, port) -> 105 - Printf.printf "Decoded: host=%s, port=%d\n" host port; 106 - Printf.printf "Meta preserved: no\n" 107 - | Error e -> Printf.printf "Error: %s\n" e); 108 - 109 - Printf.printf "\n=== With layout=true ===\n"; 110 - match Yamlt.decode codec (Bytes.Reader.of_string yaml) ~layout:true with 111 - | Ok (host, port) -> 112 - Printf.printf "Decoded: host=%s, port=%d\n" host port; 113 - Printf.printf 114 - "Meta preserved: yes (style info available for round-tripping)\n" 115 - | Error e -> Printf.printf "Error: %s\n" e 116 - 117 - (* Test: Round-trip with layout preservation *) 118 - let test_roundtrip_layout file = 119 - let yaml = read_file file in 120 - 121 - let codec = 122 - Jsont.Object.map ~kind:"Data" (fun items -> items) 123 - |> Jsont.Object.mem "items" (Jsont.array Jsont.string) ~enc:(fun x -> x) 124 - |> Jsont.Object.finish 125 - in 126 - 127 - Printf.printf "=== Original YAML ===\n"; 128 - Printf.printf "%s\n" (String.trim yaml); 129 - 130 - Printf.printf "\n=== Decode without layout, re-encode ===\n"; 131 - (match Yamlt.decode codec (Bytes.Reader.of_string yaml) ~layout:false with 132 - | Ok items -> ( 133 - let b = Buffer.create 256 in 134 - let writer = Bytes.Writer.of_buffer b in 135 - match Yamlt.encode ~format:Yamlt.Block codec items ~eod:true writer with 136 - | Ok () -> Printf.printf "%s" (Buffer.contents b) 137 - | Error e -> Printf.printf "Encode error: %s\n" e) 138 - | Error e -> Printf.printf "Decode error: %s\n" e); 139 - 140 - Printf.printf 141 - "\n=== Decode with layout=true, re-encode with Layout format ===\n"; 142 - match Yamlt.decode codec (Bytes.Reader.of_string yaml) ~layout:true with 143 - | Ok items -> ( 144 - let b = Buffer.create 256 in 145 - let writer = Bytes.Writer.of_buffer b in 146 - match Yamlt.encode ~format:Yamlt.Layout codec items ~eod:true writer with 147 - | Ok () -> Printf.printf "%s" (Buffer.contents b) 148 - | Error e -> Printf.printf "Encode error: %s\n" e) 149 - | Error e -> Printf.printf "Decode error: %s\n" e 150 - 151 - (* Test: File path in error messages *) 152 - let test_file_path () = 153 - let yaml = "name: Alice\nage: not-a-number\n" in 154 - 155 - let codec = 156 - Jsont.Object.map ~kind:"Person" (fun name age -> (name, age)) 157 - |> Jsont.Object.mem "name" Jsont.string ~enc:fst 158 - |> Jsont.Object.mem "age" Jsont.int ~enc:snd 159 - |> Jsont.Object.finish 160 - in 161 - 162 - Printf.printf "=== Without file path ===\n"; 163 - let result1 = Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:true in 164 - show_result "Error" result1; 165 - 166 - Printf.printf "\n=== With file path ===\n"; 167 - let result2 = Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:true ~file:"test.yml" in 168 - show_result "Error" result2 169 - 170 - (* Test: Missing field error with locs *) 171 - let test_missing_field file = 172 - let yaml = read_file file in 173 - 174 - let codec = 175 - Jsont.Object.map ~kind:"Complete" (fun a b c -> (a, b, c)) 176 - |> Jsont.Object.mem "field_a" Jsont.string ~enc:(fun (a, _, _) -> a) 177 - |> Jsont.Object.mem "field_b" Jsont.int ~enc:(fun (_, b, _) -> b) 178 - |> Jsont.Object.mem "field_c" Jsont.bool ~enc:(fun (_, _, c) -> c) 179 - |> Jsont.Object.finish 180 - in 181 - 182 - Printf.printf "=== Without locs ===\n"; 183 - let result_no_locs = Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:false in 184 - show_result "Missing field" result_no_locs; 185 - 186 - Printf.printf "\n=== With locs=true ===\n"; 187 - let result_with_locs = Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:true in 188 - show_result "Missing field" result_with_locs 189 - 190 - (* Test: Both locs and layout together *) 191 - let test_combined_options file = 192 - let yaml = read_file file in 193 - 194 - let codec = 195 - Jsont.Object.map ~kind:"Settings" (fun timeout retries -> 196 - (timeout, retries)) 197 - |> Jsont.Object.mem "timeout" Jsont.int ~enc:fst 198 - |> Jsont.Object.mem "retries" Jsont.int ~enc:snd 199 - |> Jsont.Object.finish 200 - in 201 - 202 - Printf.printf "=== locs=false, layout=false (defaults) ===\n"; 203 - (match Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:false ~layout:false with 204 - | Ok (timeout, retries) -> 205 - Printf.printf "OK: timeout=%d, retries=%d\n" timeout retries 206 - | Error e -> Printf.printf "Error: %s\n" e); 207 - 208 - Printf.printf "\n=== locs=true, layout=false ===\n"; 209 - (match Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:true ~layout:false with 210 - | Ok (timeout, retries) -> 211 - Printf.printf "OK: timeout=%d, retries=%d (with precise locations)\n" 212 - timeout retries 213 - | Error e -> Printf.printf "Error: %s\n" e); 214 - 215 - Printf.printf "\n=== locs=false, layout=true ===\n"; 216 - (match Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:false ~layout:true with 217 - | Ok (timeout, retries) -> 218 - Printf.printf "OK: timeout=%d, retries=%d (with layout metadata)\n" 219 - timeout retries 220 - | Error e -> Printf.printf "Error: %s\n" e); 221 - 222 - Printf.printf "\n=== locs=true, layout=true (both enabled) ===\n"; 223 - match Yamlt.decode codec (Bytes.Reader.of_string yaml) ~locs:true ~layout:true with 224 - | Ok (timeout, retries) -> 225 - Printf.printf "OK: timeout=%d, retries=%d (with locations and layout)\n" 226 - timeout retries 227 - | Error e -> Printf.printf "Error: %s\n" e 228 - 229 - let () = 230 - let usage = "Usage: test_locations <command> [args...]" in 231 - 232 - if Stdlib.Array.length Sys.argv < 2 then begin 233 - prerr_endline usage; 234 - exit 1 235 - end; 236 - 237 - match Sys.argv.(1) with 238 - | "error-precision" when Array.length Sys.argv = 3 -> 239 - test_error_precision Sys.argv.(2) 240 - | "nested-error" when Array.length Sys.argv = 3 -> 241 - test_nested_error Sys.argv.(2) 242 - | "array-error" when Array.length Sys.argv = 3 -> 243 - test_array_error Sys.argv.(2) 244 - | "layout" when Array.length Sys.argv = 3 -> 245 - test_layout_preservation Sys.argv.(2) 246 - | "roundtrip" when Array.length Sys.argv = 3 -> 247 - test_roundtrip_layout Sys.argv.(2) 248 - | "file-path" -> test_file_path () 249 - | "missing-field" when Array.length Sys.argv = 3 -> 250 - test_missing_field Sys.argv.(2) 251 - | "combined" when Array.length Sys.argv = 3 -> 252 - test_combined_options Sys.argv.(2) 253 - | _ -> 254 - prerr_endline usage; 255 - prerr_endline "Commands:"; 256 - prerr_endline 257 - " error-precision <file> - Compare error messages with/without locs"; 258 - prerr_endline 259 - " nested-error <file> - Test error locations in nested objects"; 260 - prerr_endline 261 - " array-error <file> - Test error locations in arrays"; 262 - prerr_endline " layout <file> - Test layout preservation"; 263 - prerr_endline 264 - " roundtrip <file> - Test round-tripping with layout"; 265 - prerr_endline 266 - " file-path - Test file path in error messages"; 267 - prerr_endline 268 - " missing-field <file> - Test missing field errors with locs"; 269 - prerr_endline " combined <file> - Test locs and layout together"; 270 - exit 1
-240
tests/bin/test_multidoc.ml
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Test multi-document YAML streams with decode_all *) 7 - 8 - open Bytesrw 9 - 10 - (* Helper to read file *) 11 - let read_file path = 12 - let ic = open_in path in 13 - let len = in_channel_length ic in 14 - let s = really_input_string ic len in 15 - close_in ic; 16 - s 17 - 18 - (* Helper to show results *) 19 - let show_result label = function 20 - | Ok v -> Printf.printf "%s: %s\n" label v 21 - | Error e -> Printf.printf "%s: ERROR: %s\n" label e 22 - 23 - (* Test: Simple multi-document stream *) 24 - let test_simple file = 25 - let module M = struct 26 - type person = { name : string; age : int } 27 - 28 - let person_codec = 29 - Jsont.Object.map ~kind:"Person" (fun name age -> { name; age }) 30 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun p -> p.name) 31 - |> Jsont.Object.mem "age" Jsont.int ~enc:(fun p -> p.age) 32 - |> Jsont.Object.finish 33 - 34 - let show p = Printf.sprintf "%s (age %d)" p.name p.age 35 - end in 36 - let yaml = read_file file in 37 - let reader = Bytes.Reader.of_string yaml in 38 - let seq = Yamlt.decode_all M.person_codec reader in 39 - Printf.printf "Documents:\n"; 40 - seq |> Seq.iteri (fun i result -> 41 - Printf.printf " [%d] " i; 42 - show_result "" (Result.map M.show result) 43 - ) 44 - 45 - (* Test: Count documents *) 46 - let test_count file = 47 - let yaml = read_file file in 48 - let reader = Bytes.Reader.of_string yaml in 49 - let seq = Yamlt.decode_all Jsont.json reader in 50 - let count = Seq.fold_left (fun acc _ -> acc + 1) 0 seq in 51 - Printf.printf "Document count: %d\n" count 52 - 53 - (* Test: Error tracking - show which documents succeed and which fail *) 54 - let test_errors file = 55 - let module M = struct 56 - type person = { name : string; age : int } 57 - 58 - let person_codec = 59 - Jsont.Object.map ~kind:"Person" (fun name age -> { name; age }) 60 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun p -> p.name) 61 - |> Jsont.Object.mem "age" Jsont.int ~enc:(fun p -> p.age) 62 - |> Jsont.Object.finish 63 - 64 - let show p = Printf.sprintf "%s (age %d)" p.name p.age 65 - end in 66 - let yaml = read_file file in 67 - let reader = Bytes.Reader.of_string yaml in 68 - let seq = Yamlt.decode_all M.person_codec reader in 69 - Printf.printf "Document results:\n"; 70 - seq |> Seq.iteri (fun i result -> 71 - match result with 72 - | Ok p -> Printf.printf " [%d] OK: %s\n" i (M.show p) 73 - | Error e -> Printf.printf " [%d] ERROR: %s\n" i (String.trim e) 74 - ) 75 - 76 - (* Test: Location tracking with locs=true *) 77 - let test_locations file = 78 - let module M = struct 79 - type person = { name : string; age : int } 80 - 81 - let person_codec = 82 - Jsont.Object.map ~kind:"Person" (fun name age -> { name; age }) 83 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun p -> p.name) 84 - |> Jsont.Object.mem "age" Jsont.int ~enc:(fun p -> p.age) 85 - |> Jsont.Object.finish 86 - end in 87 - let yaml = read_file file in 88 - 89 - Printf.printf "=== Without locs (default) ===\n"; 90 - let reader = Bytes.Reader.of_string yaml in 91 - let seq = Yamlt.decode_all ~locs:false M.person_codec reader in 92 - seq |> Seq.iteri (fun i result -> 93 - match result with 94 - | Ok _ -> Printf.printf " [%d] OK\n" i 95 - | Error e -> Printf.printf " [%d] ERROR:\n%s\n" i (String.trim e) 96 - ); 97 - 98 - Printf.printf "\n=== With locs=true ===\n"; 99 - let reader = Bytes.Reader.of_string yaml in 100 - let seq = Yamlt.decode_all ~locs:true ~file:"test.yml" M.person_codec reader in 101 - seq |> Seq.iteri (fun i result -> 102 - match result with 103 - | Ok _ -> Printf.printf " [%d] OK\n" i 104 - | Error e -> Printf.printf " [%d] ERROR:\n%s\n" i (String.trim e) 105 - ) 106 - 107 - (* Test: Roundtrip to JSON - decode YAML multidoc, encode each to JSON *) 108 - let test_json_roundtrip file = 109 - let yaml = read_file file in 110 - let reader = Bytes.Reader.of_string yaml in 111 - let seq = Yamlt.decode_all Jsont.json reader in 112 - Printf.printf "JSON outputs:\n"; 113 - seq |> Seq.iteri (fun i result -> 114 - match result with 115 - | Ok json_val -> 116 - (match Jsont_bytesrw.encode_string Jsont.json json_val with 117 - | Ok json_str -> Printf.printf " [%d] %s\n" i (String.trim json_str) 118 - | Error e -> Printf.printf " [%d] ENCODE ERROR: %s\n" i e) 119 - | Error e -> Printf.printf " [%d] DECODE ERROR: %s\n" i (String.trim e) 120 - ) 121 - 122 - (* Test: Nested objects in multidoc *) 123 - let test_nested file = 124 - let module M = struct 125 - type address = { street : string; city : string } 126 - type person = { name : string; age : int; address : address } 127 - 128 - let address_codec = 129 - Jsont.Object.map ~kind:"Address" (fun street city -> { street; city }) 130 - |> Jsont.Object.mem "street" Jsont.string ~enc:(fun a -> a.street) 131 - |> Jsont.Object.mem "city" Jsont.string ~enc:(fun a -> a.city) 132 - |> Jsont.Object.finish 133 - 134 - let person_codec = 135 - Jsont.Object.map ~kind:"Person" (fun name age address -> 136 - { name; age; address }) 137 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun p -> p.name) 138 - |> Jsont.Object.mem "age" Jsont.int ~enc:(fun p -> p.age) 139 - |> Jsont.Object.mem "address" address_codec ~enc:(fun p -> p.address) 140 - |> Jsont.Object.finish 141 - 142 - let show p = 143 - Printf.sprintf "%s (age %d) from %s, %s" p.name p.age p.address.street 144 - p.address.city 145 - end in 146 - let yaml = read_file file in 147 - let reader = Bytes.Reader.of_string yaml in 148 - let seq = Yamlt.decode_all M.person_codec reader in 149 - Printf.printf "Nested documents:\n"; 150 - seq |> Seq.iteri (fun i result -> 151 - Printf.printf " [%d] " i; 152 - show_result "" (Result.map M.show result) 153 - ) 154 - 155 - (* Test: Arrays in multidoc *) 156 - let test_arrays file = 157 - let yaml = read_file file in 158 - let reader = Bytes.Reader.of_string yaml in 159 - let seq = Yamlt.decode_all Jsont.json reader in 160 - Printf.printf "Array documents:\n"; 161 - seq |> Seq.iteri (fun i result -> 162 - match result with 163 - | Ok json_val -> 164 - (match Jsont_bytesrw.encode_string Jsont.json json_val with 165 - | Ok json_str -> Printf.printf " [%d] %s\n" i (String.trim json_str) 166 - | Error e -> Printf.printf " [%d] ERROR: %s\n" i e) 167 - | Error e -> Printf.printf " [%d] ERROR: %s\n" i (String.trim e) 168 - ) 169 - 170 - (* Test: Scalars in multidoc *) 171 - let test_scalars file = 172 - let yaml = read_file file in 173 - let reader = Bytes.Reader.of_string yaml in 174 - let seq = Yamlt.decode_all Jsont.json reader in 175 - Printf.printf "Scalar documents:\n"; 176 - seq |> Seq.iteri (fun i result -> 177 - match result with 178 - | Ok json_val -> 179 - (match Jsont_bytesrw.encode_string Jsont.json json_val with 180 - | Ok json_str -> Printf.printf " [%d] %s\n" i (String.trim json_str) 181 - | Error e -> Printf.printf " [%d] ERROR: %s\n" i e) 182 - | Error e -> Printf.printf " [%d] ERROR: %s\n" i (String.trim e) 183 - ) 184 - 185 - (* Test: Summary stats - count successes vs failures *) 186 - let test_summary file = 187 - let module M = struct 188 - type person = { name : string; age : int } 189 - 190 - let person_codec = 191 - Jsont.Object.map ~kind:"Person" (fun name age -> { name; age }) 192 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun p -> p.name) 193 - |> Jsont.Object.mem "age" Jsont.int ~enc:(fun p -> p.age) 194 - |> Jsont.Object.finish 195 - end in 196 - let yaml = read_file file in 197 - let reader = Bytes.Reader.of_string yaml in 198 - let seq = Yamlt.decode_all M.person_codec reader in 199 - let success = ref 0 in 200 - let failure = ref 0 in 201 - seq |> Seq.iter (fun result -> 202 - match result with 203 - | Ok _ -> incr success 204 - | Error _ -> incr failure 205 - ); 206 - Printf.printf "Summary: %d documents (%d ok, %d error)\n" 207 - (!success + !failure) !success !failure 208 - 209 - let () = 210 - let usage = "Usage: test_multidoc <command> <file>" in 211 - if Array.length Sys.argv < 3 then begin 212 - prerr_endline usage; 213 - exit 1 214 - end; 215 - 216 - let test = Sys.argv.(1) in 217 - let file = Sys.argv.(2) in 218 - match test with 219 - | "simple" -> test_simple file 220 - | "count" -> test_count file 221 - | "errors" -> test_errors file 222 - | "locations" -> test_locations file 223 - | "json" -> test_json_roundtrip file 224 - | "nested" -> test_nested file 225 - | "arrays" -> test_arrays file 226 - | "scalars" -> test_scalars file 227 - | "summary" -> test_summary file 228 - | _ -> 229 - prerr_endline usage; 230 - prerr_endline "Commands:"; 231 - prerr_endline " simple <file> - Decode person documents"; 232 - prerr_endline " count <file> - Count documents"; 233 - prerr_endline " errors <file> - Show success/error for each document"; 234 - prerr_endline " locations <file> - Test location tracking with locs=true"; 235 - prerr_endline " json <file> - Roundtrip to JSON"; 236 - prerr_endline " nested <file> - Decode nested objects"; 237 - prerr_endline " arrays <file> - Decode arrays"; 238 - prerr_endline " scalars <file> - Decode scalars"; 239 - prerr_endline " summary <file> - Show success/failure summary"; 240 - exit 1
-89
tests/bin/test_null_collections.ml
··· 1 - open Bytesrw 2 - 3 - let () = 4 - Printf.printf "=== Test 1: Explicit null as empty array ===\n"; 5 - let yaml1 = "values: null" in 6 - let codec1 = 7 - let open Jsont in 8 - Object.map ~kind:"Test" (fun v -> v) 9 - |> Object.mem "values" (list int) ~dec_absent:[] ~enc:(fun v -> v) 10 - |> Object.finish 11 - in 12 - (match Yamlt.decode codec1 (Bytes.Reader.of_string yaml1) with 13 - | Ok v -> 14 - Printf.printf "Result: [%s]\n" 15 - (String.concat "; " (List.map string_of_int v)) 16 - | Error e -> Printf.printf "Error: %s\n" e); 17 - 18 - Printf.printf "\n=== Test 2: Tilde as empty array ===\n"; 19 - let yaml2 = "values: ~" in 20 - (match Yamlt.decode codec1 (Bytes.Reader.of_string yaml2) with 21 - | Ok v -> 22 - Printf.printf "Result: [%s]\n" 23 - (String.concat "; " (List.map string_of_int v)) 24 - | Error e -> Printf.printf "Error: %s\n" e); 25 - 26 - Printf.printf "\n=== Test 3: Empty array syntax ===\n"; 27 - let yaml3 = "values: []" in 28 - (match Yamlt.decode codec1 (Bytes.Reader.of_string yaml3) with 29 - | Ok v -> 30 - Printf.printf "Result: [%s]\n" 31 - (String.concat "; " (List.map string_of_int v)) 32 - | Error e -> Printf.printf "Error: %s\n" e); 33 - 34 - Printf.printf "\n=== Test 4: Array with values ===\n"; 35 - let yaml4 = "values: [1, 2, 3]" in 36 - (match Yamlt.decode codec1 (Bytes.Reader.of_string yaml4) with 37 - | Ok v -> 38 - Printf.printf "Result: [%s]\n" 39 - (String.concat "; " (List.map string_of_int v)) 40 - | Error e -> Printf.printf "Error: %s\n" e); 41 - 42 - Printf.printf "\n=== Test 5: Explicit null as empty object ===\n"; 43 - let yaml5 = "config: null" in 44 - let codec2 = 45 - let open Jsont in 46 - let config_codec = 47 - Object.map ~kind:"Config" (fun timeout retries -> (timeout, retries)) 48 - |> Object.mem "timeout" int ~dec_absent:30 ~enc:fst 49 - |> Object.mem "retries" int ~dec_absent:3 ~enc:snd 50 - |> Object.finish 51 - in 52 - Object.map ~kind:"Test" (fun c -> c) 53 - |> Object.mem "config" config_codec ~dec_absent:(30, 3) ~enc:(fun c -> c) 54 - |> Object.finish 55 - in 56 - (match Yamlt.decode codec2 (Bytes.Reader.of_string yaml5) with 57 - | Ok (timeout, retries) -> 58 - Printf.printf "Result: {timeout=%d; retries=%d}\n" timeout retries 59 - | Error e -> Printf.printf "Error: %s\n" e); 60 - 61 - Printf.printf "\n=== Test 6: Empty object syntax ===\n"; 62 - let yaml6 = "config: {}" in 63 - (match Yamlt.decode codec2 (Bytes.Reader.of_string yaml6) with 64 - | Ok (timeout, retries) -> 65 - Printf.printf "Result: {timeout=%d; retries=%d}\n" timeout retries 66 - | Error e -> Printf.printf "Error: %s\n" e); 67 - 68 - Printf.printf "\n=== Test 7: Object with values ===\n"; 69 - let yaml7 = "config:\n timeout: 60\n retries: 5" in 70 - (match Yamlt.decode codec2 (Bytes.Reader.of_string yaml7) with 71 - | Ok (timeout, retries) -> 72 - Printf.printf "Result: {timeout=%d; retries=%d}\n" timeout retries 73 - | Error e -> Printf.printf "Error: %s\n" e); 74 - 75 - Printf.printf "\n=== Test 8: Nested null arrays ===\n"; 76 - let yaml8 = "name: test\nitems: null\ntags: ~" in 77 - let codec3 = 78 - let open Jsont in 79 - Object.map ~kind:"Nested" (fun name items tags -> (name, items, tags)) 80 - |> Object.mem "name" string ~enc:(fun (n, _, _) -> n) 81 - |> Object.mem "items" (list int) ~dec_absent:[] ~enc:(fun (_, i, _) -> i) 82 - |> Object.mem "tags" (list string) ~dec_absent:[] ~enc:(fun (_, _, t) -> t) 83 - |> Object.finish 84 - in 85 - match Yamlt.decode codec3 (Bytes.Reader.of_string yaml8) with 86 - | Ok (name, items, tags) -> 87 - Printf.printf "Result: {name=%s; items_count=%d; tags_count=%d}\n" 88 - name (List.length items) (List.length tags) 89 - | Error e -> Printf.printf "Error: %s\n" e
-39
tests/bin/test_null_complete.ml
··· 1 - open Bytesrw 2 - 3 - let () = 4 - Printf.printf "=== Test 1: Jsont.option with YAML null ===\n"; 5 - let yaml1 = "value: null" in 6 - let codec1 = 7 - let open Jsont in 8 - Object.map ~kind:"Test" (fun v -> v) 9 - |> Object.mem "value" (option string) ~enc:(fun v -> v) 10 - |> Object.finish 11 - in 12 - (match Yamlt.decode codec1 (Bytes.Reader.of_string yaml1) with 13 - | Ok v -> 14 - Printf.printf "Result: %s\n" 15 - (match v with None -> "None" | Some s -> "Some(" ^ s ^ ")") 16 - | Error e -> Printf.printf "Error: %s\n" e); 17 - 18 - Printf.printf "\n=== Test 2: Jsont.option with YAML string ===\n"; 19 - (match Yamlt.decode codec1 (Bytes.Reader.of_string "value: hello") with 20 - | Ok v -> 21 - Printf.printf "Result: %s\n" 22 - (match v with None -> "None" | Some s -> "Some(" ^ s ^ ")") 23 - | Error e -> Printf.printf "Error: %s\n" e); 24 - 25 - Printf.printf "\n=== Test 3: Jsont.string with YAML null (should error) ===\n"; 26 - let codec2 = 27 - let open Jsont in 28 - Object.map ~kind:"Test" (fun v -> v) 29 - |> Object.mem "value" string ~enc:(fun v -> v) 30 - |> Object.finish 31 - in 32 - (match Yamlt.decode codec2 (Bytes.Reader.of_string "value: null") with 33 - | Ok v -> Printf.printf "Result: %s\n" v 34 - | Error e -> Printf.printf "Error (expected): %s\n" e); 35 - 36 - Printf.printf "\n=== Test 4: Jsont.string with YAML string ===\n"; 37 - match Yamlt.decode codec2 (Bytes.Reader.of_string "value: hello") with 38 - | Ok v -> Printf.printf "Result: %s\n" v 39 - | Error e -> Printf.printf "Error: %s\n" e
-31
tests/bin/test_null_fix.ml
··· 1 - open Bytesrw 2 - 3 - let () = 4 - let module M = struct 5 - type data = { value : string option } 6 - 7 - let data_codec = 8 - Jsont.Object.map ~kind:"Data" (fun value -> { value }) 9 - |> Jsont.Object.mem "value" (Jsont.option Jsont.string) ~enc:(fun d -> 10 - d.value) 11 - |> Jsont.Object.finish 12 - end in 13 - let yaml_null = "value: null" in 14 - 15 - Printf.printf "Testing YAML null handling with Jsont.option Jsont.string:\n\n"; 16 - 17 - match Yamlt.decode M.data_codec (Bytes.Reader.of_string yaml_null) with 18 - | Ok data -> ( 19 - match data.M.value with 20 - | None -> Printf.printf "YAML: value=None (CORRECT)\n" 21 - | Some s -> Printf.printf "YAML: value=Some(%S) (BUG!)\n" s) 22 - | Error e -> ( 23 - Printf.printf "YAML ERROR: %s\n" e; 24 - 25 - let json_null = "{\"value\": null}" in 26 - match Jsont_bytesrw.decode_string M.data_codec json_null with 27 - | Ok data -> ( 28 - match data.M.value with 29 - | None -> Printf.printf "JSON: value=None (CORRECT)\n" 30 - | Some s -> Printf.printf "JSON: value=Some(%S) (BUG!)\n" s) 31 - | Error e -> Printf.printf "JSON ERROR: %s\n" e)
-347
tests/bin/test_objects.ml
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Test object codec functionality with Yamlt *) 7 - 8 - open Bytesrw 9 - 10 - (* Helper to read file *) 11 - let read_file path = 12 - let ic = open_in path in 13 - let len = in_channel_length ic in 14 - let s = really_input_string ic len in 15 - close_in ic; 16 - s 17 - 18 - (* Helper to show results *) 19 - let show_result label = function 20 - | Ok v -> Printf.printf "%s: %s\n" label v 21 - | Error e -> Printf.printf "%s: ERROR: %s\n" label e 22 - 23 - let show_result_both label json_result yaml_result = 24 - Printf.printf "JSON: "; 25 - show_result label json_result; 26 - Printf.printf "YAML: "; 27 - show_result label yaml_result 28 - 29 - (* Test: Simple object with required fields *) 30 - let test_simple_object file = 31 - let module M = struct 32 - type person = { name : string; age : int } 33 - 34 - let person_codec = 35 - Jsont.Object.map ~kind:"Person" (fun name age -> { name; age }) 36 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun p -> p.name) 37 - |> Jsont.Object.mem "age" Jsont.int ~enc:(fun p -> p.age) 38 - |> Jsont.Object.finish 39 - 40 - let show p = Printf.sprintf "{name=%S; age=%d}" p.name p.age 41 - end in 42 - let yaml = read_file file in 43 - let json = read_file (file ^ ".json") in 44 - let json_result = Jsont_bytesrw.decode_string M.person_codec json in 45 - let yaml_result = Yamlt.decode M.person_codec (Bytes.Reader.of_string yaml) in 46 - 47 - show_result_both "person" 48 - (Result.map M.show json_result) 49 - (Result.map M.show yaml_result) 50 - 51 - (* Test: Object with optional fields *) 52 - let test_optional_fields file = 53 - let module M = struct 54 - type config = { host : string; port : int option; debug : bool option } 55 - 56 - let config_codec = 57 - Jsont.Object.map ~kind:"Config" (fun host port debug -> 58 - { host; port; debug }) 59 - |> Jsont.Object.mem "host" Jsont.string ~enc:(fun c -> c.host) 60 - |> Jsont.Object.opt_mem "port" Jsont.int ~enc:(fun c -> c.port) 61 - |> Jsont.Object.opt_mem "debug" Jsont.bool ~enc:(fun c -> c.debug) 62 - |> Jsont.Object.finish 63 - 64 - let show c = 65 - Printf.sprintf "{host=%S; port=%s; debug=%s}" c.host 66 - (match c.port with 67 - | None -> "None" 68 - | Some p -> Printf.sprintf "Some %d" p) 69 - (match c.debug with 70 - | None -> "None" 71 - | Some b -> Printf.sprintf "Some %b" b) 72 - end in 73 - let yaml = read_file file in 74 - let json = read_file (file ^ ".json") in 75 - let json_result = Jsont_bytesrw.decode_string M.config_codec json in 76 - let yaml_result = Yamlt.decode M.config_codec (Bytes.Reader.of_string yaml) in 77 - 78 - show_result_both "config" 79 - (Result.map M.show json_result) 80 - (Result.map M.show yaml_result) 81 - 82 - (* Test: Object with default values *) 83 - let test_default_values file = 84 - let module M = struct 85 - type settings = { timeout : int; retries : int; verbose : bool } 86 - 87 - let settings_codec = 88 - Jsont.Object.map ~kind:"Settings" (fun timeout retries verbose -> 89 - { timeout; retries; verbose }) 90 - |> Jsont.Object.mem "timeout" Jsont.int 91 - ~enc:(fun s -> s.timeout) 92 - ~dec_absent:30 93 - |> Jsont.Object.mem "retries" Jsont.int 94 - ~enc:(fun s -> s.retries) 95 - ~dec_absent:3 96 - |> Jsont.Object.mem "verbose" Jsont.bool 97 - ~enc:(fun s -> s.verbose) 98 - ~dec_absent:false 99 - |> Jsont.Object.finish 100 - 101 - let show s = 102 - Printf.sprintf "{timeout=%d; retries=%d; verbose=%b}" s.timeout s.retries 103 - s.verbose 104 - end in 105 - let yaml = read_file file in 106 - let json = read_file (file ^ ".json") in 107 - let json_result = Jsont_bytesrw.decode_string M.settings_codec json in 108 - let yaml_result = Yamlt.decode M.settings_codec (Bytes.Reader.of_string yaml) in 109 - 110 - show_result_both "settings" 111 - (Result.map M.show json_result) 112 - (Result.map M.show yaml_result) 113 - 114 - (* Test: Nested objects *) 115 - let test_nested_objects file = 116 - let module M = struct 117 - type address = { street : string; city : string; zip : string } 118 - type employee = { name : string; address : address } 119 - 120 - let address_codec = 121 - Jsont.Object.map ~kind:"Address" (fun street city zip -> 122 - { street; city; zip }) 123 - |> Jsont.Object.mem "street" Jsont.string ~enc:(fun a -> a.street) 124 - |> Jsont.Object.mem "city" Jsont.string ~enc:(fun a -> a.city) 125 - |> Jsont.Object.mem "zip" Jsont.string ~enc:(fun a -> a.zip) 126 - |> Jsont.Object.finish 127 - 128 - let employee_codec = 129 - Jsont.Object.map ~kind:"Employee" (fun name address -> { name; address }) 130 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun e -> e.name) 131 - |> Jsont.Object.mem "address" address_codec ~enc:(fun e -> e.address) 132 - |> Jsont.Object.finish 133 - 134 - let show e = 135 - Printf.sprintf "{name=%S; address={street=%S; city=%S; zip=%S}}" e.name 136 - e.address.street e.address.city e.address.zip 137 - end in 138 - let yaml = read_file file in 139 - let json = read_file (file ^ ".json") in 140 - let json_result = Jsont_bytesrw.decode_string M.employee_codec json in 141 - let yaml_result = Yamlt.decode M.employee_codec (Bytes.Reader.of_string yaml) in 142 - 143 - show_result_both "employee" 144 - (Result.map M.show json_result) 145 - (Result.map M.show yaml_result) 146 - 147 - (* Test: Unknown member handling - error *) 148 - let test_unknown_members_error file = 149 - let module M = struct 150 - type strict = { name : string } 151 - 152 - let strict_codec = 153 - Jsont.Object.map ~kind:"Strict" (fun name -> { name }) 154 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun s -> s.name) 155 - |> Jsont.Object.finish 156 - end in 157 - let yaml = read_file file in 158 - let result = Yamlt.decode M.strict_codec (Bytes.Reader.of_string yaml) in 159 - match result with 160 - | Ok _ -> Printf.printf "Unexpected success\n" 161 - | Error e -> Printf.printf "Expected error: %s\n" e 162 - 163 - (* Test: Unknown member handling - keep *) 164 - let test_unknown_members_keep file = 165 - let module M = struct 166 - type flexible = { name : string; extra : Jsont.json } 167 - 168 - let flexible_codec = 169 - Jsont.Object.map ~kind:"Flexible" (fun name extra -> { name; extra }) 170 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun f -> f.name) 171 - |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:(fun f -> f.extra) 172 - |> Jsont.Object.finish 173 - 174 - let show f = Printf.sprintf "{name=%S; has_extra=true}" f.name 175 - end in 176 - let yaml = read_file file in 177 - let json = read_file (file ^ ".json") in 178 - let json_result = Jsont_bytesrw.decode_string M.flexible_codec json in 179 - let yaml_result = Yamlt.decode M.flexible_codec (Bytes.Reader.of_string yaml) in 180 - 181 - show_result_both "flexible" 182 - (Result.map M.show json_result) 183 - (Result.map M.show yaml_result) 184 - 185 - (* Test: Object cases (discriminated unions) - simplified version *) 186 - let test_object_cases file = 187 - let module M = struct 188 - type circle = { type_ : string; radius : float } 189 - 190 - let circle_codec = 191 - Jsont.Object.map ~kind:"Circle" (fun type_ radius -> { type_; radius }) 192 - |> Jsont.Object.mem "type" Jsont.string ~enc:(fun c -> c.type_) 193 - |> Jsont.Object.mem "radius" Jsont.number ~enc:(fun c -> c.radius) 194 - |> Jsont.Object.finish 195 - 196 - let show c = Printf.sprintf "Circle{radius=%.2f}" c.radius 197 - end in 198 - let yaml = read_file file in 199 - let json = read_file (file ^ ".json") in 200 - let json_result = Jsont_bytesrw.decode_string M.circle_codec json in 201 - let yaml_result = Yamlt.decode M.circle_codec (Bytes.Reader.of_string yaml) in 202 - 203 - show_result_both "shape" 204 - (Result.map M.show json_result) 205 - (Result.map M.show yaml_result) 206 - 207 - (* Test: Missing required field error *) 208 - let test_missing_required file = 209 - let module M = struct 210 - type required = { name : string; age : int } 211 - 212 - let required_codec = 213 - Jsont.Object.map ~kind:"Required" (fun name age -> { name; age }) 214 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun r -> r.name) 215 - |> Jsont.Object.mem "age" Jsont.int ~enc:(fun r -> r.age) 216 - |> Jsont.Object.finish 217 - end in 218 - let yaml = read_file file in 219 - let result = Yamlt.decode M.required_codec (Bytes.Reader.of_string yaml) in 220 - match result with 221 - | Ok _ -> Printf.printf "Unexpected success\n" 222 - | Error e -> Printf.printf "Expected error: %s\n" e 223 - 224 - (* Test: Encoding objects to different formats *) 225 - let test_encode_object () = 226 - let module M = struct 227 - type person = { name : string; age : int; active : bool } 228 - 229 - let person_codec = 230 - Jsont.Object.map ~kind:"Person" (fun name age active -> 231 - { name; age; active }) 232 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun p -> p.name) 233 - |> Jsont.Object.mem "age" Jsont.int ~enc:(fun p -> p.age) 234 - |> Jsont.Object.mem "active" Jsont.bool ~enc:(fun p -> p.active) 235 - |> Jsont.Object.finish 236 - end in 237 - let person = M.{ name = "Alice"; age = 30; active = true } in 238 - 239 - (* Encode to JSON *) 240 - (match Jsont_bytesrw.encode_string M.person_codec person with 241 - | Ok s -> Printf.printf "JSON: %s\n" (String.trim s) 242 - | Error e -> Printf.printf "JSON ERROR: %s\n" e); 243 - 244 - (* Encode to YAML Block *) 245 - (let b = Buffer.create 256 in 246 - let writer = Bytes.Writer.of_buffer b in 247 - match Yamlt.encode ~format:Yamlt.Block M.person_codec person ~eod:true writer with 248 - | Ok () -> Printf.printf "YAML Block:\n%s" (Buffer.contents b) 249 - | Error e -> Printf.printf "YAML Block ERROR: %s\n" e); 250 - 251 - (* Encode to YAML Flow *) 252 - let b = Buffer.create 256 in 253 - let writer = Bytes.Writer.of_buffer b in 254 - match Yamlt.encode ~format:Yamlt.Flow M.person_codec person ~eod:true writer with 255 - | Ok () -> Printf.printf "YAML Flow: %s" (Buffer.contents b) 256 - | Error e -> Printf.printf "YAML Flow ERROR: %s\n" e 257 - 258 - (* Test: Roundtrip encoding of objects with unknown members *) 259 - let test_unknown_keep_roundtrip file = 260 - let module M = struct 261 - type flexible = { name : string; extra : Jsont.json } 262 - 263 - let flexible_codec = 264 - Jsont.Object.map ~kind:"Flexible" (fun name extra -> { name; extra }) 265 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun f -> f.name) 266 - |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:(fun f -> f.extra) 267 - |> Jsont.Object.finish 268 - 269 - let show_json json = 270 - match Jsont_bytesrw.encode_string Jsont.json json with 271 - | Ok s -> String.trim s 272 - | Error e -> Printf.sprintf "ERROR: %s" e 273 - end in 274 - let yaml = read_file file in 275 - 276 - (* Decode from YAML *) 277 - match Yamlt.decode M.flexible_codec (Bytes.Reader.of_string yaml) with 278 - | Error e -> Printf.printf "Decode error: %s\n" e 279 - | Ok v -> 280 - Printf.printf "Decoded: name=%S, extra=%s\n" v.M.name (M.show_json v.M.extra); 281 - 282 - (* Encode to YAML Block *) 283 - let b = Buffer.create 256 in 284 - let writer = Bytes.Writer.of_buffer b in 285 - (match 286 - Yamlt.encode ~format:Yamlt.Block M.flexible_codec v ~eod:true writer 287 - with 288 - | Ok () -> Printf.printf "Encoded Block:\n%s" (Buffer.contents b) 289 - | Error e -> Printf.printf "Encode Block ERROR: %s\n" e); 290 - 291 - (* Re-decode the encoded YAML to verify roundtrip *) 292 - let encoded = Buffer.contents b in 293 - (match 294 - Yamlt.decode M.flexible_codec (Bytes.Reader.of_string encoded) 295 - with 296 - | Error e -> Printf.printf "Re-decode error: %s\n" e 297 - | Ok v2 -> 298 - Printf.printf "Re-decoded: name=%S, extra=%s\n" v2.M.name 299 - (M.show_json v2.M.extra); 300 - if M.show_json v.M.extra = M.show_json v2.M.extra then 301 - Printf.printf "Roundtrip: OK (extra members preserved)\n" 302 - else Printf.printf "Roundtrip: FAILED (extra members lost)\n") 303 - 304 - let () = 305 - let usage = "Usage: test_objects <command> [args...]" in 306 - 307 - if Stdlib.Array.length Sys.argv < 2 then begin 308 - prerr_endline usage; 309 - exit 1 310 - end; 311 - 312 - match Sys.argv.(1) with 313 - | "simple" when Stdlib.Array.length Sys.argv = 3 -> 314 - test_simple_object Sys.argv.(2) 315 - | "optional" when Stdlib.Array.length Sys.argv = 3 -> 316 - test_optional_fields Sys.argv.(2) 317 - | "defaults" when Stdlib.Array.length Sys.argv = 3 -> 318 - test_default_values Sys.argv.(2) 319 - | "nested" when Stdlib.Array.length Sys.argv = 3 -> 320 - test_nested_objects Sys.argv.(2) 321 - | "unknown-error" when Stdlib.Array.length Sys.argv = 3 -> 322 - test_unknown_members_error Sys.argv.(2) 323 - | "unknown-keep" when Stdlib.Array.length Sys.argv = 3 -> 324 - test_unknown_members_keep Sys.argv.(2) 325 - | "unknown-keep-roundtrip" when Stdlib.Array.length Sys.argv = 3 -> 326 - test_unknown_keep_roundtrip Sys.argv.(2) 327 - | "cases" when Stdlib.Array.length Sys.argv = 3 -> 328 - test_object_cases Sys.argv.(2) 329 - | "missing-required" when Stdlib.Array.length Sys.argv = 3 -> 330 - test_missing_required Sys.argv.(2) 331 - | "encode" when Stdlib.Array.length Sys.argv = 2 -> test_encode_object () 332 - | _ -> 333 - prerr_endline usage; 334 - prerr_endline "Commands:"; 335 - prerr_endline " simple <file> - Test simple object"; 336 - prerr_endline " optional <file> - Test optional fields"; 337 - prerr_endline " defaults <file> - Test default values"; 338 - prerr_endline " nested <file> - Test nested objects"; 339 - prerr_endline " unknown-error <file> - Test unknown member error"; 340 - prerr_endline " unknown-keep <file> - Test keeping unknown members"; 341 - prerr_endline 342 - " unknown-keep-roundtrip <file> - Test roundtrip of unknown members"; 343 - prerr_endline " cases <file> - Test object cases (unions)"; 344 - prerr_endline 345 - " missing-required <file> - Test missing required field error"; 346 - prerr_endline " encode - Test encoding objects"; 347 - exit 1
-19
tests/bin/test_opt_array.ml
··· 1 - open Bytesrw 2 - 3 - let () = 4 - let codec = 5 - Jsont.Object.map ~kind:"Test" (fun arr -> arr) 6 - |> Jsont.Object.opt_mem "values" (Jsont.array Jsont.string) ~enc:(fun arr -> 7 - arr) 8 - |> Jsont.Object.finish 9 - in 10 - 11 - let yaml = "values: [a, b, c]" in 12 - 13 - Printf.printf "Testing optional array field:\n"; 14 - match Yamlt.decode codec (Bytes.Reader.of_string yaml) with 15 - | Ok arr -> ( 16 - match arr with 17 - | None -> Printf.printf "Result: None\n" 18 - | Some a -> Printf.printf "Result: Some([%d items])\n" (Array.length a)) 19 - | Error e -> Printf.printf "Error: %s\n" e
-267
tests/bin/test_roundtrip.ml
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Test roundtrip encoding/decoding with Yamlt *) 7 - 8 - open Bytesrw 9 - 10 - (* Test: Roundtrip scalars *) 11 - let test_scalar_roundtrip () = 12 - let module M = struct 13 - type data = { s : string; n : float; b : bool; nul : unit } 14 - 15 - let data_codec = 16 - Jsont.Object.map ~kind:"Data" (fun s n b nul -> { s; n; b; nul }) 17 - |> Jsont.Object.mem "s" Jsont.string ~enc:(fun d -> d.s) 18 - |> Jsont.Object.mem "n" Jsont.number ~enc:(fun d -> d.n) 19 - |> Jsont.Object.mem "b" Jsont.bool ~enc:(fun d -> d.b) 20 - |> Jsont.Object.mem "nul" (Jsont.null ()) ~enc:(fun d -> d.nul) 21 - |> Jsont.Object.finish 22 - 23 - let equal d1 d2 = 24 - d1.s = d2.s && d1.n = d2.n && d1.b = d2.b && d1.nul = d2.nul 25 - end in 26 - let original = { M.s = "hello"; n = 42.5; b = true; nul = () } in 27 - 28 - (* JSON roundtrip *) 29 - let json_encoded = Jsont_bytesrw.encode_string M.data_codec original in 30 - let json_decoded = 31 - Result.bind json_encoded (Jsont_bytesrw.decode_string M.data_codec) 32 - in 33 - (match json_decoded with 34 - | Ok decoded when M.equal original decoded -> 35 - Printf.printf "JSON roundtrip: PASS\n" 36 - | Ok _ -> Printf.printf "JSON roundtrip: FAIL (data mismatch)\n" 37 - | Error e -> Printf.printf "JSON roundtrip: FAIL (%s)\n" e); 38 - 39 - (* YAML Block roundtrip *) 40 - let yaml_block_encoded = 41 - let b = Buffer.create 256 in 42 - let writer = Bytes.Writer.of_buffer b in 43 - match Yamlt.encode ~format:Yamlt.Block M.data_codec original ~eod:true writer with 44 - | Ok () -> Ok (Buffer.contents b) 45 - | Error e -> Error e 46 - in 47 - let yaml_block_decoded = 48 - Result.bind yaml_block_encoded (fun yaml -> 49 - Yamlt.decode M.data_codec (Bytes.Reader.of_string yaml)) 50 - in 51 - (match yaml_block_decoded with 52 - | Ok decoded when M.equal original decoded -> 53 - Printf.printf "YAML Block roundtrip: PASS\n" 54 - | Ok _ -> Printf.printf "YAML Block roundtrip: FAIL (data mismatch)\n" 55 - | Error e -> Printf.printf "YAML Block roundtrip: FAIL (%s)\n" e); 56 - 57 - (* YAML Flow roundtrip *) 58 - let yaml_flow_encoded = 59 - let b = Buffer.create 256 in 60 - let writer = Bytes.Writer.of_buffer b in 61 - match Yamlt.encode ~format:Yamlt.Flow M.data_codec original ~eod:true writer with 62 - | Ok () -> Ok (Buffer.contents b) 63 - | Error e -> Error e 64 - in 65 - let yaml_flow_decoded = 66 - Result.bind yaml_flow_encoded (fun yaml -> 67 - Yamlt.decode M.data_codec (Bytes.Reader.of_string yaml)) 68 - in 69 - match yaml_flow_decoded with 70 - | Ok decoded when M.equal original decoded -> 71 - Printf.printf "YAML Flow roundtrip: PASS\n" 72 - | Ok _ -> Printf.printf "YAML Flow roundtrip: FAIL (data mismatch)\n" 73 - | Error e -> Printf.printf "YAML Flow roundtrip: FAIL (%s)\n" e 74 - 75 - (* Test: Roundtrip arrays *) 76 - let test_array_roundtrip () = 77 - let module M = struct 78 - type data = { items : int array; nested : float array array } 79 - 80 - let data_codec = 81 - Jsont.Object.map ~kind:"Data" (fun items nested -> { items; nested }) 82 - |> Jsont.Object.mem "items" (Jsont.array Jsont.int) ~enc:(fun d -> 83 - d.items) 84 - |> Jsont.Object.mem "nested" 85 - (Jsont.array (Jsont.array Jsont.number)) 86 - ~enc:(fun d -> d.nested) 87 - |> Jsont.Object.finish 88 - 89 - let equal d1 d2 = d1.items = d2.items && d1.nested = d2.nested 90 - end in 91 - let original = 92 - { 93 - M.items = [| 1; 2; 3; 4; 5 |]; 94 - nested = [| [| 1.0; 2.0 |]; [| 3.0; 4.0 |] |]; 95 - } 96 - in 97 - 98 - (* JSON roundtrip *) 99 - let json_result = 100 - Result.bind 101 - (Jsont_bytesrw.encode_string M.data_codec original) 102 - (Jsont_bytesrw.decode_string M.data_codec) 103 - in 104 - (match json_result with 105 - | Ok decoded when M.equal original decoded -> 106 - Printf.printf "JSON array roundtrip: PASS\n" 107 - | Ok _ -> Printf.printf "JSON array roundtrip: FAIL (data mismatch)\n" 108 - | Error e -> Printf.printf "JSON array roundtrip: FAIL (%s)\n" e); 109 - 110 - (* YAML roundtrip *) 111 - let yaml_result = 112 - let b = Buffer.create 256 in 113 - let writer = Bytes.Writer.of_buffer b in 114 - match Yamlt.encode M.data_codec original ~eod:true writer with 115 - | Ok () -> 116 - let yaml = Buffer.contents b in 117 - Yamlt.decode M.data_codec (Bytes.Reader.of_string yaml) 118 - | Error e -> Error e 119 - in 120 - match yaml_result with 121 - | Ok decoded when M.equal original decoded -> 122 - Printf.printf "YAML array roundtrip: PASS\n" 123 - | Ok _ -> Printf.printf "YAML array roundtrip: FAIL (data mismatch)\n" 124 - | Error e -> Printf.printf "YAML array roundtrip: FAIL (%s)\n" e 125 - 126 - (* Test: Roundtrip objects *) 127 - let test_object_roundtrip () = 128 - let module M = struct 129 - type person = { p_name : string; age : int; active : bool } 130 - type company = { c_name : string; employees : person array } 131 - 132 - let person_codec = 133 - Jsont.Object.map ~kind:"Person" (fun p_name age active -> 134 - { p_name; age; active }) 135 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun p -> p.p_name) 136 - |> Jsont.Object.mem "age" Jsont.int ~enc:(fun p -> p.age) 137 - |> Jsont.Object.mem "active" Jsont.bool ~enc:(fun p -> p.active) 138 - |> Jsont.Object.finish 139 - 140 - let company_codec = 141 - Jsont.Object.map ~kind:"Company" (fun c_name employees -> 142 - { c_name; employees }) 143 - |> Jsont.Object.mem "name" Jsont.string ~enc:(fun c -> c.c_name) 144 - |> Jsont.Object.mem "employees" (Jsont.array person_codec) ~enc:(fun c -> 145 - c.employees) 146 - |> Jsont.Object.finish 147 - 148 - let person_equal p1 p2 = 149 - p1.p_name = p2.p_name && p1.age = p2.age && p1.active = p2.active 150 - 151 - let equal c1 c2 = 152 - c1.c_name = c2.c_name 153 - && Stdlib.Array.length c1.employees = Stdlib.Array.length c2.employees 154 - && Stdlib.Array.for_all2 person_equal c1.employees c2.employees 155 - end in 156 - let original = 157 - { 158 - M.c_name = "Acme Corp"; 159 - employees = 160 - [| 161 - { p_name = "Alice"; age = 30; active = true }; 162 - { p_name = "Bob"; age = 25; active = false }; 163 - |]; 164 - } 165 - in 166 - 167 - (* JSON roundtrip *) 168 - let json_result = 169 - Result.bind 170 - (Jsont_bytesrw.encode_string M.company_codec original) 171 - (Jsont_bytesrw.decode_string M.company_codec) 172 - in 173 - (match json_result with 174 - | Ok decoded when M.equal original decoded -> 175 - Printf.printf "JSON object roundtrip: PASS\n" 176 - | Ok _ -> Printf.printf "JSON object roundtrip: FAIL (data mismatch)\n" 177 - | Error e -> Printf.printf "JSON object roundtrip: FAIL (%s)\n" e); 178 - 179 - (* YAML roundtrip *) 180 - let yaml_result = 181 - let b = Buffer.create 256 in 182 - let writer = Bytes.Writer.of_buffer b in 183 - match Yamlt.encode M.company_codec original ~eod:true writer with 184 - | Ok () -> 185 - let yaml = Buffer.contents b in 186 - Yamlt.decode M.company_codec (Bytes.Reader.of_string yaml) 187 - | Error e -> Error e 188 - in 189 - match yaml_result with 190 - | Ok decoded when M.equal original decoded -> 191 - Printf.printf "YAML object roundtrip: PASS\n" 192 - | Ok _ -> Printf.printf "YAML object roundtrip: FAIL (data mismatch)\n" 193 - | Error e -> Printf.printf "YAML object roundtrip: FAIL (%s)\n" e 194 - 195 - (* Test: Roundtrip with optionals *) 196 - let test_optional_roundtrip () = 197 - let module M = struct 198 - type data = { 199 - required : string; 200 - optional : int option; 201 - nullable : string option; 202 - } 203 - 204 - let data_codec = 205 - Jsont.Object.map ~kind:"Data" (fun required optional nullable -> 206 - { required; optional; nullable }) 207 - |> Jsont.Object.mem "required" Jsont.string ~enc:(fun d -> d.required) 208 - |> Jsont.Object.opt_mem "optional" Jsont.int ~enc:(fun d -> d.optional) 209 - |> Jsont.Object.mem "nullable" (Jsont.some Jsont.string) ~enc:(fun d -> 210 - d.nullable) 211 - |> Jsont.Object.finish 212 - 213 - let equal d1 d2 = 214 - d1.required = d2.required && d1.optional = d2.optional 215 - && d1.nullable = d2.nullable 216 - end in 217 - let original = { M.required = "test"; optional = Some 42; nullable = None } in 218 - 219 - (* JSON roundtrip *) 220 - let json_result = 221 - Result.bind 222 - (Jsont_bytesrw.encode_string M.data_codec original) 223 - (Jsont_bytesrw.decode_string M.data_codec) 224 - in 225 - (match json_result with 226 - | Ok decoded when M.equal original decoded -> 227 - Printf.printf "JSON optional roundtrip: PASS\n" 228 - | Ok _ -> Printf.printf "JSON optional roundtrip: FAIL (data mismatch)\n" 229 - | Error e -> Printf.printf "JSON optional roundtrip: FAIL (%s)\n" e); 230 - 231 - (* YAML roundtrip *) 232 - let yaml_result = 233 - let b = Buffer.create 256 in 234 - let writer = Bytes.Writer.of_buffer b in 235 - match Yamlt.encode M.data_codec original ~eod:true writer with 236 - | Ok () -> 237 - let yaml = Buffer.contents b in 238 - Yamlt.decode M.data_codec (Bytes.Reader.of_string yaml) 239 - | Error e -> Error e 240 - in 241 - match yaml_result with 242 - | Ok decoded when M.equal original decoded -> 243 - Printf.printf "YAML optional roundtrip: PASS\n" 244 - | Ok _ -> Printf.printf "YAML optional roundtrip: FAIL (data mismatch)\n" 245 - | Error e -> Printf.printf "YAML optional roundtrip: FAIL (%s)\n" e 246 - 247 - let () = 248 - let usage = "Usage: test_roundtrip <command>" in 249 - 250 - if Stdlib.Array.length Sys.argv < 2 then begin 251 - prerr_endline usage; 252 - exit 1 253 - end; 254 - 255 - match Sys.argv.(1) with 256 - | "scalar" -> test_scalar_roundtrip () 257 - | "array" -> test_array_roundtrip () 258 - | "object" -> test_object_roundtrip () 259 - | "optional" -> test_optional_roundtrip () 260 - | _ -> 261 - prerr_endline usage; 262 - prerr_endline "Commands:"; 263 - prerr_endline " scalar - Test scalar roundtrip"; 264 - prerr_endline " array - Test array roundtrip"; 265 - prerr_endline " object - Test object roundtrip"; 266 - prerr_endline " optional - Test optional fields roundtrip"; 267 - exit 1
-309
tests/bin/test_scalars.ml
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Test scalar type resolution with Yamlt codec *) 7 - 8 - open Bytesrw 9 - 10 - (* Helper to read file *) 11 - let read_file path = 12 - let ic = open_in path in 13 - let len = in_channel_length ic in 14 - let s = really_input_string ic len in 15 - close_in ic; 16 - s 17 - 18 - (* Helper to show results *) 19 - let show_result label = function 20 - | Ok v -> Printf.printf "%s: %s\n" label v 21 - | Error e -> Printf.printf "%s: ERROR: %s\n" label e 22 - 23 - let show_result_json label json_result yaml_result = 24 - Printf.printf "JSON %s\n" label; 25 - show_result " decode" json_result; 26 - Printf.printf "YAML %s\n" label; 27 - show_result " decode" yaml_result 28 - 29 - (* Test: Decode null values with different type expectations *) 30 - let test_null_resolution file = 31 - let yaml = read_file file in 32 - 33 - (* Define a simple object codec with nullable field *) 34 - let null_codec = 35 - Jsont.Object.map ~kind:"NullTest" (fun n -> n) 36 - |> Jsont.Object.mem "value" (Jsont.null ()) ~enc:(fun n -> n) 37 - |> Jsont.Object.finish 38 - in 39 - 40 - (* Try decoding as null *) 41 - let result = Yamlt.decode null_codec (Bytes.Reader.of_string yaml) in 42 - show_result "null_codec" (Result.map (fun () -> "null") result) 43 - 44 - (* Test: Boolean type-directed resolution *) 45 - let test_bool_resolution file = 46 - let yaml = read_file file in 47 - let json = read_file (file ^ ".json") in 48 - 49 - (* Codec expecting bool *) 50 - let bool_codec = 51 - Jsont.Object.map ~kind:"BoolTest" (fun b -> b) 52 - |> Jsont.Object.mem "value" Jsont.bool ~enc:(fun b -> b) 53 - |> Jsont.Object.finish 54 - in 55 - 56 - (* Codec expecting string *) 57 - let string_codec = 58 - Jsont.Object.map ~kind:"StringTest" (fun s -> s) 59 - |> Jsont.Object.mem "value" Jsont.string ~enc:(fun s -> s) 60 - |> Jsont.Object.finish 61 - in 62 - 63 - Printf.printf "=== Bool Codec ===\n"; 64 - let json_result = Jsont_bytesrw.decode_string bool_codec json in 65 - let yaml_result = Yamlt.decode bool_codec (Bytes.Reader.of_string yaml) in 66 - show_result_json "bool_codec" 67 - (Result.map (Printf.sprintf "%b") json_result) 68 - (Result.map (Printf.sprintf "%b") yaml_result); 69 - 70 - Printf.printf "\n=== String Codec ===\n"; 71 - let json_result = Jsont_bytesrw.decode_string string_codec json in 72 - let yaml_result = Yamlt.decode string_codec (Bytes.Reader.of_string yaml) in 73 - show_result_json "string_codec" 74 - (Result.map (Printf.sprintf "%S") json_result) 75 - (Result.map (Printf.sprintf "%S") yaml_result) 76 - 77 - (* Test: Number resolution *) 78 - let test_number_resolution file = 79 - let yaml = read_file file in 80 - let json = read_file (file ^ ".json") in 81 - 82 - let number_codec = 83 - Jsont.Object.map ~kind:"NumberTest" (fun n -> n) 84 - |> Jsont.Object.mem "value" Jsont.number ~enc:(fun n -> n) 85 - |> Jsont.Object.finish 86 - in 87 - 88 - let json_result = Jsont_bytesrw.decode_string number_codec json in 89 - let yaml_result = Yamlt.decode number_codec (Bytes.Reader.of_string yaml) in 90 - 91 - show_result_json "number_codec" 92 - (Result.map (Printf.sprintf "%.17g") json_result) 93 - (Result.map (Printf.sprintf "%.17g") yaml_result) 94 - 95 - (* Test: String resolution preserves everything *) 96 - let test_string_resolution file = 97 - let yaml = read_file file in 98 - let json = read_file (file ^ ".json") in 99 - 100 - let string_codec = 101 - Jsont.Object.map ~kind:"StringTest" (fun s -> s) 102 - |> Jsont.Object.mem "value" Jsont.string ~enc:(fun s -> s) 103 - |> Jsont.Object.finish 104 - in 105 - 106 - let json_result = Jsont_bytesrw.decode_string string_codec json in 107 - let yaml_result = Yamlt.decode string_codec (Bytes.Reader.of_string yaml) in 108 - 109 - show_result_json "string_codec" 110 - (Result.map (Printf.sprintf "%S") json_result) 111 - (Result.map (Printf.sprintf "%S") yaml_result) 112 - 113 - (* Test: Special float values *) 114 - let test_special_floats file = 115 - let yaml = read_file file in 116 - 117 - let number_codec = 118 - Jsont.Object.map ~kind:"SpecialFloat" (fun n -> n) 119 - |> Jsont.Object.mem "value" Jsont.number ~enc:(fun n -> n) 120 - |> Jsont.Object.finish 121 - in 122 - 123 - let result = Yamlt.decode number_codec (Bytes.Reader.of_string yaml) in 124 - match result with 125 - | Ok f -> 126 - if Float.is_nan f then Printf.printf "value: NaN\n" 127 - else if f = Float.infinity then Printf.printf "value: +Infinity\n" 128 - else if f = Float.neg_infinity then Printf.printf "value: -Infinity\n" 129 - else Printf.printf "value: %.17g\n" f 130 - | Error e -> Printf.printf "ERROR: %s\n" e 131 - 132 - (* Test: Type mismatch errors *) 133 - let test_type_mismatch file expected_type = 134 - let yaml = read_file file in 135 - 136 - match expected_type with 137 - | "bool" -> ( 138 - let codec = 139 - Jsont.Object.map ~kind:"BoolTest" (fun b -> b) 140 - |> Jsont.Object.mem "value" Jsont.bool ~enc:(fun b -> b) 141 - |> Jsont.Object.finish 142 - in 143 - let result = Yamlt.decode codec (Bytes.Reader.of_string yaml) in 144 - match result with 145 - | Ok _ -> Printf.printf "Unexpected success\n" 146 - | Error e -> Printf.printf "Expected error: %s\n" e) 147 - | "number" -> ( 148 - let codec = 149 - Jsont.Object.map ~kind:"NumberTest" (fun n -> n) 150 - |> Jsont.Object.mem "value" Jsont.number ~enc:(fun n -> n) 151 - |> Jsont.Object.finish 152 - in 153 - let result = Yamlt.decode codec (Bytes.Reader.of_string yaml) in 154 - match result with 155 - | Ok _ -> Printf.printf "Unexpected success\n" 156 - | Error e -> Printf.printf "Expected error: %s\n" e) 157 - | "null" -> ( 158 - let codec = 159 - Jsont.Object.map ~kind:"NullTest" (fun n -> n) 160 - |> Jsont.Object.mem "value" (Jsont.null ()) ~enc:(fun n -> n) 161 - |> Jsont.Object.finish 162 - in 163 - let result = Yamlt.decode codec (Bytes.Reader.of_string yaml) in 164 - match result with 165 - | Ok _ -> Printf.printf "Unexpected success\n" 166 - | Error e -> Printf.printf "Expected error: %s\n" e) 167 - | _ -> failwith "unknown type" 168 - 169 - (* Test: Decode with Jsont.json to see auto-resolution *) 170 - let test_any_resolution file = 171 - let yaml = read_file file in 172 - let json = read_file (file ^ ".json") in 173 - 174 - let any_codec = 175 - Jsont.Object.map ~kind:"AnyTest" (fun v -> v) 176 - |> Jsont.Object.mem "value" Jsont.json ~enc:(fun v -> v) 177 - |> Jsont.Object.finish 178 - in 179 - 180 - let json_result = Jsont_bytesrw.decode_string any_codec json in 181 - let yaml_result = Yamlt.decode any_codec (Bytes.Reader.of_string yaml) in 182 - 183 - (* Just show that it decoded successfully *) 184 - show_result_json "any_codec" 185 - (Result.map (fun _ -> "decoded") json_result) 186 - (Result.map (fun _ -> "decoded") yaml_result) 187 - 188 - (* Test: Encoding to different formats *) 189 - let test_encode_formats value_type value = 190 - match value_type with 191 - | "bool" -> ( 192 - let codec = 193 - Jsont.Object.map ~kind:"BoolTest" (fun b -> b) 194 - |> Jsont.Object.mem "value" Jsont.bool ~enc:(fun b -> b) 195 - |> Jsont.Object.finish 196 - in 197 - let v = bool_of_string value in 198 - (match Jsont_bytesrw.encode_string codec v with 199 - | Ok s -> Printf.printf "JSON: %s\n" (String.trim s) 200 - | Error e -> Printf.printf "JSON ERROR: %s\n" e); 201 - (let b = Buffer.create 256 in 202 - let writer = Bytes.Writer.of_buffer b in 203 - match Yamlt.encode ~format:Yamlt.Block codec v ~eod:true writer with 204 - | Ok () -> Printf.printf "YAML Block:\n%s" (Buffer.contents b) 205 - | Error e -> Printf.printf "YAML Block ERROR: %s\n" e); 206 - let b = Buffer.create 256 in 207 - let writer = Bytes.Writer.of_buffer b in 208 - match Yamlt.encode ~format:Yamlt.Flow codec v ~eod:true writer with 209 - | Ok () -> Printf.printf "YAML Flow: %s" (Buffer.contents b) 210 - | Error e -> Printf.printf "YAML Flow ERROR: %s\n" e) 211 - | "number" -> ( 212 - let codec = 213 - Jsont.Object.map ~kind:"NumberTest" (fun n -> n) 214 - |> Jsont.Object.mem "value" Jsont.number ~enc:(fun n -> n) 215 - |> Jsont.Object.finish 216 - in 217 - let v = float_of_string value in 218 - (match Jsont_bytesrw.encode_string codec v with 219 - | Ok s -> Printf.printf "JSON: %s\n" (String.trim s) 220 - | Error e -> Printf.printf "JSON ERROR: %s\n" e); 221 - (let b = Buffer.create 256 in 222 - let writer = Bytes.Writer.of_buffer b in 223 - match Yamlt.encode ~format:Yamlt.Block codec v ~eod:true writer with 224 - | Ok () -> Printf.printf "YAML Block:\n%s" (Buffer.contents b) 225 - | Error e -> Printf.printf "YAML Block ERROR: %s\n" e); 226 - let b = Buffer.create 256 in 227 - let writer = Bytes.Writer.of_buffer b in 228 - match Yamlt.encode ~format:Yamlt.Flow codec v ~eod:true writer with 229 - | Ok () -> Printf.printf "YAML Flow: %s" (Buffer.contents b) 230 - | Error e -> Printf.printf "YAML Flow ERROR: %s\n" e) 231 - | "string" -> ( 232 - let codec = 233 - Jsont.Object.map ~kind:"StringTest" (fun s -> s) 234 - |> Jsont.Object.mem "value" Jsont.string ~enc:(fun s -> s) 235 - |> Jsont.Object.finish 236 - in 237 - let v = value in 238 - (match Jsont_bytesrw.encode_string codec v with 239 - | Ok s -> Printf.printf "JSON: %s\n" (String.trim s) 240 - | Error e -> Printf.printf "JSON ERROR: %s\n" e); 241 - (let b = Buffer.create 256 in 242 - let writer = Bytes.Writer.of_buffer b in 243 - match Yamlt.encode ~format:Yamlt.Block codec v ~eod:true writer with 244 - | Ok () -> Printf.printf "YAML Block:\n%s" (Buffer.contents b) 245 - | Error e -> Printf.printf "YAML Block ERROR: %s\n" e); 246 - let b = Buffer.create 256 in 247 - let writer = Bytes.Writer.of_buffer b in 248 - match Yamlt.encode ~format:Yamlt.Flow codec v ~eod:true writer with 249 - | Ok () -> Printf.printf "YAML Flow: %s" (Buffer.contents b) 250 - | Error e -> Printf.printf "YAML Flow ERROR: %s\n" e) 251 - | "null" -> ( 252 - let codec = 253 - Jsont.Object.map ~kind:"NullTest" (fun n -> n) 254 - |> Jsont.Object.mem "value" (Jsont.null ()) ~enc:(fun n -> n) 255 - |> Jsont.Object.finish 256 - in 257 - let v = () in 258 - (match Jsont_bytesrw.encode_string codec v with 259 - | Ok s -> Printf.printf "JSON: %s\n" (String.trim s) 260 - | Error e -> Printf.printf "JSON ERROR: %s\n" e); 261 - (let b = Buffer.create 256 in 262 - let writer = Bytes.Writer.of_buffer b in 263 - match Yamlt.encode ~format:Yamlt.Block codec v ~eod:true writer with 264 - | Ok () -> Printf.printf "YAML Block:\n%s" (Buffer.contents b) 265 - | Error e -> Printf.printf "YAML Block ERROR: %s\n" e); 266 - let b = Buffer.create 256 in 267 - let writer = Bytes.Writer.of_buffer b in 268 - match Yamlt.encode ~format:Yamlt.Flow codec v ~eod:true writer with 269 - | Ok () -> Printf.printf "YAML Flow: %s" (Buffer.contents b) 270 - | Error e -> Printf.printf "YAML Flow ERROR: %s\n" e) 271 - | _ -> failwith "unknown type" 272 - 273 - let () = 274 - let usage = "Usage: test_scalars <command> [args...]" in 275 - 276 - if Stdlib.Array.length Sys.argv < 2 then begin 277 - prerr_endline usage; 278 - exit 1 279 - end; 280 - 281 - match Sys.argv.(1) with 282 - | "null" when Array.length Sys.argv = 3 -> test_null_resolution Sys.argv.(2) 283 - | "bool" when Array.length Sys.argv = 3 -> test_bool_resolution Sys.argv.(2) 284 - | "number" when Array.length Sys.argv = 3 -> 285 - test_number_resolution Sys.argv.(2) 286 - | "string" when Array.length Sys.argv = 3 -> 287 - test_string_resolution Sys.argv.(2) 288 - | "special-float" when Array.length Sys.argv = 3 -> 289 - test_special_floats Sys.argv.(2) 290 - | "type-mismatch" when Array.length Sys.argv = 4 -> 291 - test_type_mismatch Sys.argv.(2) Sys.argv.(3) 292 - | "any" when Array.length Sys.argv = 3 -> test_any_resolution Sys.argv.(2) 293 - | "encode" when Array.length Sys.argv = 4 -> 294 - test_encode_formats Sys.argv.(2) Sys.argv.(3) 295 - | _ -> 296 - prerr_endline usage; 297 - prerr_endline "Commands:"; 298 - prerr_endline " null <file> - Test null resolution"; 299 - prerr_endline 300 - " bool <file> - Test bool vs string resolution"; 301 - prerr_endline " number <file> - Test number resolution"; 302 - prerr_endline " string <file> - Test string resolution"; 303 - prerr_endline " special-float <file> - Test .inf, .nan, etc."; 304 - prerr_endline 305 - " type-mismatch <file> <type> - Test error on type mismatch"; 306 - prerr_endline 307 - " any <file> - Test Jsont.any auto-resolution"; 308 - prerr_endline " encode <type> <value> - Test encoding to JSON/YAML"; 309 - exit 1
-38
tests/bin/test_some_vs_option.ml
··· 1 - open Bytesrw 2 - 3 - let () = 4 - (* Using Jsont.some like opt_mem does *) 5 - let codec1 = 6 - Jsont.Object.map ~kind:"Test" (fun arr -> arr) 7 - |> Jsont.Object.mem "values" 8 - (Jsont.some (Jsont.array Jsont.string)) 9 - ~enc:(fun arr -> arr) 10 - |> Jsont.Object.finish 11 - in 12 - 13 - let yaml = "values: [a, b, c]" in 14 - 15 - Printf.printf "Test 1: Jsont.some (Jsont.array) - like opt_mem:\n"; 16 - (match Yamlt.decode codec1 (Bytes.Reader.of_string yaml) with 17 - | Ok arr -> ( 18 - match arr with 19 - | None -> Printf.printf "Result: None\n" 20 - | Some a -> Printf.printf "Result: Some([%d items])\n" (Array.length a)) 21 - | Error e -> Printf.printf "Error: %s\n" e); 22 - 23 - (* Using Jsont.option *) 24 - let codec2 = 25 - Jsont.Object.map ~kind:"Test" (fun arr -> arr) 26 - |> Jsont.Object.mem "values" 27 - (Jsont.option (Jsont.array Jsont.string)) 28 - ~enc:(fun arr -> arr) 29 - |> Jsont.Object.finish 30 - in 31 - 32 - Printf.printf "\nTest 2: Jsont.option (Jsont.array):\n"; 33 - match Yamlt.decode codec2 (Bytes.Reader.of_string yaml) with 34 - | Ok arr -> ( 35 - match arr with 36 - | None -> Printf.printf "Result: None\n" 37 - | Some a -> Printf.printf "Result: Some([%d items])\n" (Array.length a)) 38 - | Error e -> Printf.printf "Error: %s\n" e
-148
tests/cram/arrays_codec.t
··· 1 - Array Codec Tests with Yamlt 2 - =============================== 3 - 4 - This test suite validates array encoding/decoding with Jsont codecs in YAML, 5 - including homogeneous type checking and nested structures. 6 - 7 - Setup 8 - ----- 9 - 10 - ================================================================================ 11 - HOMOGENEOUS ARRAYS 12 - ================================================================================ 13 - 14 - Integer arrays 15 - 16 - $ test_arrays int ../data/arrays/int_array.yml 17 - JSON: int_array: [1; 2; 3; 4; 5] 18 - YAML: int_array: [1; 2; 3; 4; 5] 19 - 20 - String arrays 21 - 22 - $ test_arrays string ../data/arrays/string_array.yml 23 - JSON: string_array: ["apple"; "banana"; "cherry"] 24 - YAML: string_array: ["apple"; "banana"; "cherry"] 25 - 26 - Float/Number arrays 27 - 28 - $ test_arrays float ../data/arrays/float_array.yml 29 - JSON: float_array: [1.50; 2.70; 3.14; 0.50] 30 - YAML: float_array: [1.50; 2.70; 3.14; 0.50] 31 - 32 - Boolean arrays 33 - 34 - $ test_arrays bool ../data/arrays/bool_array.yml 35 - JSON: bool_array: [true; false; true; true; false] 36 - YAML: bool_array: [true; false; true; true; false] 37 - 38 - ================================================================================ 39 - EMPTY ARRAYS 40 - ================================================================================ 41 - 42 - Empty arrays work correctly 43 - 44 - $ test_arrays empty ../data/arrays/empty_array.yml 45 - JSON: empty_array: length=0 46 - YAML: empty_array: length=0 47 - 48 - ================================================================================ 49 - ARRAYS OF OBJECTS 50 - ================================================================================ 51 - 52 - Arrays containing objects 53 - 54 - $ test_arrays objects ../data/arrays/object_array.yml 55 - JSON: object_array: [{Alice,30}; {Bob,25}; {Charlie,35}] 56 - YAML: object_array: [{Alice,30}; {Bob,25}; {Charlie,35}] 57 - 58 - ================================================================================ 59 - NESTED ARRAYS 60 - ================================================================================ 61 - 62 - Arrays containing arrays (matrices) 63 - 64 - $ test_arrays nested ../data/arrays/nested_array.yml 65 - JSON: nested_arrays: [[1; 2; 3]; [4; 5; 6]; [7; 8; 9]] 66 - YAML: nested_arrays: [[1; 2; 3]; [4; 5; 6]; [7; 8; 9]] 67 - 68 - ================================================================================ 69 - NULLABLE ARRAYS 70 - ================================================================================ 71 - 72 - Arrays with null elements 73 - 74 - $ test_arrays nullable ../data/arrays/nullable_array.yml 75 - JSON: nullable_array: ERROR: Expected string but found null 76 - File "-", line 1, characters 21-22: 77 - File "-", line 1, characters 21-22: at index 1 of 78 - File "-", line 1, characters 11-22: array<string> 79 - File "-": in member values of 80 - File "-", line 1, characters 0-22: Nullable object 81 - YAML: nullable_array: ERROR: Expected string but found null 82 - File "-": 83 - at index 1 of 84 - File "-": array<string> 85 - File "-": in member values of 86 - File "-": Nullable object 87 - 88 - ================================================================================ 89 - ERROR HANDLING 90 - ================================================================================ 91 - 92 - Type mismatch in array element 93 - 94 - $ test_arrays type-mismatch ../data/arrays/type_mismatch.yml 95 - Expected error: String "not-a-number" does not parse to OCaml int value 96 - File "-": 97 - at index 2 of 98 - File "-": array<OCaml int> 99 - File "-": in member values of 100 - File "-": Numbers object 101 - 102 - ================================================================================ 103 - ENCODING ARRAYS 104 - ================================================================================ 105 - 106 - Encode arrays to JSON and YAML formats 107 - 108 - $ test_arrays encode 109 - JSON: {"numbers":[1,2,3,4,5],"strings":["hello","world"]} 110 - YAML Block: 111 - numbers: 112 - - 1 113 - - 2 114 - - 3 115 - - 4 116 - - 5 117 - strings: 118 - - hello 119 - - world 120 - YAML Flow: {numbers: [1, 2, 3, 4, 5], strings: [hello, world]} 121 - 122 - ================================================================================ 123 - NEGATIVE TESTS - Wrong File Types 124 - ================================================================================ 125 - 126 - Attempting to decode an object file with an array codec should fail 127 - 128 - $ test_arrays int ../data/objects/simple.yml 129 - JSON: int_array: ERROR: Missing member values in Numbers object 130 - File "-", line 1, characters 0-28: 131 - YAML: int_array: ERROR: Missing member values in Numbers object 132 - File "-": 133 - 134 - Attempting to decode a scalar file with an array codec should fail 135 - 136 - $ test_arrays string ../data/scalars/string_plain.yml 137 - JSON: string_array: ERROR: Missing member items in Tags object 138 - File "-", line 1, characters 0-24: 139 - YAML: string_array: ERROR: Missing member items in Tags object 140 - File "-": 141 - 142 - Attempting to decode int array with string array codec should fail 143 - 144 - $ test_arrays string ../data/arrays/int_array.yml 145 - JSON: string_array: ERROR: Missing member items in Tags object 146 - File "-", line 1, characters 0-27: 147 - YAML: string_array: ERROR: Missing member items in Tags object 148 - File "-":
-71
tests/cram/complex_codec.t
··· 1 - Complex Nested Types Tests with Yamlt 2 - ====================================== 3 - 4 - This test suite validates complex nested structures combining objects, arrays, 5 - and various levels of nesting. 6 - 7 - ================================================================================ 8 - DEEPLY NESTED OBJECTS 9 - ================================================================================ 10 - 11 - Handle deeply nested object structures 12 - 13 - $ test_complex deep-nesting ../data/complex/deep_nesting.yml 14 - JSON: deep_nesting: depth=4, value=42 15 - YAML: deep_nesting: depth=4, value=42 16 - 17 - ================================================================================ 18 - MIXED STRUCTURES 19 - ================================================================================ 20 - 21 - Arrays of objects containing arrays 22 - 23 - $ test_complex mixed-structure ../data/complex/mixed_structure.yml 24 - JSON: mixed_structure: name="products", items=3, total_tags=6 25 - YAML: mixed_structure: name="products", items=3, total_tags=6 26 - 27 - ================================================================================ 28 - COMPLEX OPTIONAL COMBINATIONS 29 - ================================================================================ 30 - 31 - Multiple optional fields with different combinations 32 - 33 - $ test_complex complex-optional ../data/complex/complex_optional.yml 34 - JSON: complex_optional: host="example.com", port=443, ssl=true, fallbacks=2 35 - YAML: complex_optional: host="example.com", port=443, ssl=true, fallbacks=2 36 - 37 - ================================================================================ 38 - HETEROGENEOUS DATA 39 - ================================================================================ 40 - 41 - Mixed types in arrays using any type 42 - 43 - $ test_complex heterogeneous ../data/complex/heterogeneous.yml 44 - JSON: heterogeneous: ERROR: Expected one of but found number 45 - File "-", line 1, characters 11-12: 46 - File "-", line 1, characters 11-12: at index 0 of 47 - File "-", line 1, characters 10-12: array<one of > 48 - File "-": in member mixed of 49 - File "-", line 1, characters 0-12: Data object 50 - YAML: heterogeneous: ERROR: Expected one of but found number 51 - File "-": 52 - at index 0 of 53 - File "-": array<one of > 54 - File "-": in member mixed of 55 - File "-": Data object 56 - 57 - ================================================================================ 58 - NEGATIVE TESTS - Structure Mismatch 59 - ================================================================================ 60 - 61 - Using deeply nested data with flat codec should fail 62 - 63 - $ test_complex mixed-structure ../data/complex/deep_nesting.yml 64 - JSON: mixed_structure: ERROR: Missing members in Collection object: 65 - items 66 - name 67 - File "-", line 1, characters 0-44: 68 - YAML: mixed_structure: ERROR: Missing members in Collection object: 69 - items 70 - name 71 - File "-":
-17
tests/cram/dune
··· 1 - (cram 2 - (deps 3 - (package yamlt) 4 - (glob_files ../data/scalars/*.yml) 5 - (glob_files ../data/scalars/*.json) 6 - (glob_files ../data/objects/*.yml) 7 - (glob_files ../data/objects/*.json) 8 - (glob_files ../data/arrays/*.yml) 9 - (glob_files ../data/arrays/*.json) 10 - (glob_files ../data/formats/*.yml) 11 - (glob_files ../data/formats/*.json) 12 - (glob_files ../data/complex/*.yml) 13 - (glob_files ../data/complex/*.json) 14 - (glob_files ../data/edge/*.yml) 15 - (glob_files ../data/edge/*.json) 16 - (glob_files ../data/multidoc/*.yml) 17 - (glob_files ../data/locations/*.yml)))
-85
tests/cram/edge_codec.t
··· 1 - Edge Cases Tests with Yamlt 2 - ============================ 3 - 4 - This test suite validates edge cases including large numbers, special characters, 5 - unicode, and boundary conditions. 6 - 7 - ================================================================================ 8 - LARGE NUMBERS 9 - ================================================================================ 10 - 11 - Very large and very small floating point numbers 12 - 13 - $ test_edge large-numbers ../data/edge/large_numbers.yml 14 - JSON: large_numbers: large_int=9007199254740991, large_float=1.797693e+308, small_float=2.225074e-308 15 - YAML: large_numbers: large_int=9007199254740991, large_float=1.797693e+308, small_float=2.225074e-308 16 - 17 - ================================================================================ 18 - SPECIAL CHARACTERS 19 - ================================================================================ 20 - 21 - Strings containing newlines, tabs, and other special characters 22 - 23 - $ test_edge special-chars ../data/edge/special_chars.yml 24 - JSON: special_chars: length=34, contains_newline=true, contains_tab=true 25 - YAML: special_chars: length=34, contains_newline=true, contains_tab=true 26 - 27 - ================================================================================ 28 - UNICODE STRINGS 29 - ================================================================================ 30 - 31 - Emoji, Chinese, and RTL text 32 - 33 - $ test_edge unicode ../data/edge/unicode.yml 34 - JSON: unicode: emoji="\240\159\142\137\240\159\154\128\226\156\168", chinese="\228\189\160\229\165\189\228\184\150\231\149\140", rtl="\217\133\216\177\216\173\216\168\216\167" 35 - YAML: unicode: emoji="\240\159\142\137\240\159\154\128\226\156\168", chinese="\228\189\160\229\165\189\228\184\150\231\149\140", rtl="\217\133\216\177\216\173\216\168\216\167" 36 - 37 - ================================================================================ 38 - EMPTY COLLECTIONS 39 - ================================================================================ 40 - 41 - Empty arrays and objects 42 - 43 - $ test_edge empty-collections ../data/edge/empty_collections.yml 44 - JSON: empty_collections: empty_array_len=0, empty_object_array_len=0 45 - YAML: empty_collections: empty_array_len=0, empty_object_array_len=0 46 - 47 - ================================================================================ 48 - SPECIAL KEY NAMES 49 - ================================================================================ 50 - 51 - Keys with dots, dashes, colons 52 - 53 - $ test_edge special-keys ../data/edge/special_keys.yml 54 - JSON: special_keys: ERROR: Expected one of but found object 55 - File "-", line 1, characters 0-1: 56 - YAML: special_keys: ERROR: Expected one of but found object 57 - File "-": 58 - 59 - ================================================================================ 60 - SINGLE-ELEMENT ARRAYS 61 - ================================================================================ 62 - 63 - Arrays with exactly one element 64 - 65 - $ test_edge single-element ../data/edge/single_element.yml 66 - JSON: single_element: length=1, value=42 67 - YAML: single_element: length=1, value=42 68 - 69 - ================================================================================ 70 - NEGATIVE TESTS - Boundary Violations 71 - ================================================================================ 72 - 73 - Using unicode data with number codec should fail 74 - 75 - $ test_edge large-numbers ../data/edge/unicode.yml 76 - JSON: large_numbers: ERROR: Missing members in Numbers object: 77 - large_float 78 - large_int 79 - small_float 80 - File "-", line 1, characters 0-72: 81 - YAML: large_numbers: ERROR: Missing members in Numbers object: 82 - large_float 83 - large_int 84 - small_float 85 - File "-":
-107
tests/cram/formats_codec.t
··· 1 - Format-Specific Features Tests with Yamlt 2 - ========================================== 3 - 4 - This test suite validates YAML-specific format features and compares with JSON behavior. 5 - 6 - ================================================================================ 7 - MULTI-LINE STRINGS - LITERAL STYLE 8 - ================================================================================ 9 - 10 - Literal style (|) preserves newlines 11 - 12 - $ test_formats literal ../data/formats/literal_string.yml 13 - JSON: literal_string: lines=5, length=81 14 - YAML: literal_string: lines=5, length=81 15 - 16 - ================================================================================ 17 - MULTI-LINE STRINGS - FOLDED STYLE 18 - ================================================================================ 19 - 20 - Folded style (>) folds lines into single line 21 - 22 - $ test_formats folded ../data/formats/folded_string.yml 23 - JSON: folded_string: length=114, newlines=1 24 - YAML: folded_string: length=114, newlines=1 25 - 26 - ================================================================================ 27 - NUMBER FORMATS 28 - ================================================================================ 29 - 30 - YAML supports hex, octal, and binary number formats 31 - 32 - $ test_formats number-formats ../data/formats/number_formats.yml 33 - JSON: number_formats: hex=255, octal=63, binary=10 34 - YAML: number_formats: hex=255, octal=63, binary=10 35 - 36 - ================================================================================ 37 - COMMENTS 38 - ================================================================================ 39 - 40 - YAML comments are ignored during parsing 41 - 42 - $ test_formats comments ../data/formats/comments.yml 43 - YAML (with comments): host="localhost", port=8080, debug=true 44 - 45 - ================================================================================ 46 - EMPTY DOCUMENTS 47 - ================================================================================ 48 - 49 - Empty or null documents handled correctly 50 - 51 - $ test_formats empty-doc ../data/formats/empty_doc.yml 52 - JSON: empty_document: ERROR: Expected string but found null 53 - File "-", line 1, characters 10-11: 54 - File "-": in member value of 55 - File "-", line 1, characters 0-11: Wrapper object 56 - YAML: empty_document: ERROR: Expected string but found null 57 - File "-": 58 - File "-": in member value of 59 - File "-": Wrapper object 60 - 61 - ================================================================================ 62 - EXPLICIT TYPE TAGS 63 - ================================================================================ 64 - 65 - Explicit YAML type tags (!!str, !!int, etc.) 66 - 67 - $ test_formats explicit-tags ../data/formats/explicit_tags.yml 68 - YAML (with tags): data="123" 69 - 70 - ================================================================================ 71 - ENCODING STYLES 72 - ================================================================================ 73 - 74 - Compare Block vs Flow encoding styles 75 - 76 - $ test_formats encode-styles 77 - YAML Block: 78 - name: test 79 - values: 80 - - 1 81 - - 2 82 - - 3 83 - nested: 84 - enabled: true 85 - count: 5 86 - 87 - YAML Flow: 88 - {name: test, values: [1, 2, 3], nested: {enabled: true, count: 5}} 89 - 90 - 91 - ================================================================================ 92 - NEGATIVE TESTS - Format Compatibility 93 - ================================================================================ 94 - 95 - Using literal string test with number codec should fail 96 - 97 - $ test_formats number-formats ../data/formats/literal_string.yml 98 - JSON: number_formats: ERROR: Missing members in Numbers object: 99 - binary 100 - hex 101 - octal 102 - File "-", line 1, characters 0-100: 103 - YAML: number_formats: ERROR: Missing members in Numbers object: 104 - binary 105 - hex 106 - octal 107 - File "-":
-217
tests/cram/locations.t
··· 1 - Location and Layout Preservation Tests with Yamlt 2 - ================================================== 3 - 4 - This test suite validates the `locs` and `layout` options in the Yamlt decoder, 5 - demonstrating how they affect error messages and metadata preservation. 6 - 7 - ================================================================================ 8 - ERROR MESSAGE PRECISION - locs option 9 - ================================================================================ 10 - 11 - The `locs` option controls whether source locations are preserved in error messages. 12 - When `locs=false` (default), errors show basic location info. 13 - When `locs=true`, errors show precise character positions. 14 - 15 - Basic type error with and without locs 16 - 17 - $ test_locations error-precision ../data/locations/type_error.yml 18 - === Without locs (default) === 19 - Error message: 20 - String "not-a-number" does not parse to OCaml int value 21 - File "-": 22 - File "-": in member age of 23 - File "-": Person object 24 - 25 - === With locs=true === 26 - Error message: 27 - String "not-a-number" does not parse to OCaml int value 28 - File "-", line 2, characters 5-18: 29 - File "-", line 2, characters 0-3: in member age of 30 - File "-", line 1, characters 0-1: Person object 31 - 32 - ================================================================================ 33 - NESTED ERROR LOCATIONS 34 - ================================================================================ 35 - 36 - The `locs` option is especially useful for nested structures, 37 - showing exactly where deep errors occur. 38 - 39 - Error in nested object field 40 - 41 - $ test_locations nested-error ../data/locations/nested_error.yml 42 - === Without locs (default) === 43 - Nested error: 44 - String "invalid-zip" does not parse to OCaml int value 45 - File "-": 46 - File "-": in member zip of 47 - File "-": Address object 48 - File "-": in member address of 49 - File "-": Employee object 50 - 51 - === With locs=true === 52 - Nested error: 53 - String "invalid-zip" does not parse to OCaml int value 54 - File "-", line 5, characters 7-19: 55 - File "-", line 5, characters 2-5: in member zip of 56 - File "-", line 3, characters 2-3: Address object 57 - File "-", line 2, characters 0-7: in member address of 58 - File "-", line 1, characters 0-1: Employee object 59 - 60 - ================================================================================ 61 - ARRAY ELEMENT ERROR LOCATIONS 62 - ================================================================================ 63 - 64 - The `locs` option pinpoints which array element caused an error. 65 - 66 - Error at specific array index 67 - 68 - $ test_locations array-error ../data/locations/array_error.yml 69 - === Without locs (default) === 70 - Array error: 71 - String "not-a-number" does not parse to OCaml int value 72 - File "-": 73 - at index 2 of 74 - File "-": array<OCaml int> 75 - File "-": in member values of 76 - File "-": Numbers object 77 - 78 - === With locs=true === 79 - Array error: 80 - String "not-a-number" does not parse to OCaml int value 81 - File "-", lines 4-5, characters 4-2: 82 - at index 2 of 83 - File "-", line 2, characters 2-3: array<OCaml int> 84 - File "-", line 1, characters 0-6: in member values of 85 - File "-", line 1, characters 0-1: Numbers object 86 - 87 - ================================================================================ 88 - FILE PATH IN ERROR MESSAGES 89 - ================================================================================ 90 - 91 - The `file` parameter sets the file path shown in error messages. 92 - 93 - $ test_locations file-path 94 - === Without file path === 95 - Error: 96 - String "not-a-number" does not parse to OCaml int value 97 - File "-", line 2, characters 5-18: 98 - File "-", line 2, characters 0-3: in member age of 99 - File "-", line 1, characters 0-1: Person object 100 - 101 - === With file path === 102 - Error: 103 - String "not-a-number" does not parse to OCaml int value 104 - File "test.yml", line 2, characters 5-18: 105 - File "test.yml", line 2, characters 0-3: in member age of 106 - File "test.yml", line 1, characters 0-1: Person object 107 - 108 - ================================================================================ 109 - MISSING FIELD ERROR LOCATIONS 110 - ================================================================================ 111 - 112 - The `locs` option helps identify where fields are missing. 113 - 114 - $ test_locations missing-field ../data/locations/missing_field.yml 115 - === Without locs === 116 - Missing field: 117 - Missing member field_c in Complete object 118 - File "-": 119 - 120 - === With locs=true === 121 - Missing field: 122 - Missing member field_c in Complete object 123 - File "-", line 1, characters 0-1: 124 - 125 - ================================================================================ 126 - LAYOUT PRESERVATION - layout option 127 - ================================================================================ 128 - 129 - The `layout` option controls whether style information (block vs flow) 130 - is preserved in metadata for potential round-tripping. 131 - 132 - Basic layout preservation 133 - 134 - $ test_locations layout ../data/locations/simple.yml 135 - === Without layout (default) === 136 - Decoded: host=localhost, port=8080 137 - Meta preserved: no 138 - 139 - === With layout=true === 140 - Decoded: host=localhost, port=8080 141 - Meta preserved: yes (style info available for round-tripping) 142 - 143 - ================================================================================ 144 - ROUND-TRIPPING WITH LAYOUT 145 - ================================================================================ 146 - 147 - With `layout=true` during decode and `format:Layout` during encode, 148 - the original YAML style can be preserved. 149 - 150 - Flow style preservation 151 - 152 - $ test_locations roundtrip ../data/locations/flow_style.yml 153 - === Original YAML === 154 - items: [apple, banana, cherry] 155 - 156 - === Decode without layout, re-encode === 157 - items: 158 - - apple 159 - - banana 160 - - cherry 161 - 162 - === Decode with layout=true, re-encode with Layout format === 163 - items: 164 - - apple 165 - - banana 166 - - cherry 167 - 168 - Block style preservation 169 - 170 - $ test_locations roundtrip ../data/locations/block_style.yml 171 - === Original YAML === 172 - items: 173 - - apple 174 - - banana 175 - - cherry 176 - 177 - === Decode without layout, re-encode === 178 - items: 179 - - apple 180 - - banana 181 - - cherry 182 - 183 - === Decode with layout=true, re-encode with Layout format === 184 - items: 185 - - apple 186 - - banana 187 - - cherry 188 - 189 - ================================================================================ 190 - COMBINED OPTIONS - locs and layout together 191 - ================================================================================ 192 - 193 - Both options can be used simultaneously for maximum information. 194 - 195 - $ test_locations combined ../data/locations/valid_settings.yml 196 - === locs=false, layout=false (defaults) === 197 - OK: timeout=30, retries=3 198 - 199 - === locs=true, layout=false === 200 - OK: timeout=30, retries=3 (with precise locations) 201 - 202 - === locs=false, layout=true === 203 - OK: timeout=30, retries=3 (with layout metadata) 204 - 205 - === locs=true, layout=true (both enabled) === 206 - OK: timeout=30, retries=3 (with locations and layout) 207 - 208 - ================================================================================ 209 - SUMMARY OF OPTIONS 210 - ================================================================================ 211 - 212 - locs option: 213 - 214 - layout option: 215 - 216 - Both options add metadata overhead, so only enable when needed. 217 - For production parsing where you only need the data, use defaults (both false).
-220
tests/cram/multidoc.t
··· 1 - Multi-Document YAML Streams with Yamlt 2 - ======================================== 3 - 4 - This test suite validates multi-document YAML stream decoding using decode_all, 5 - including error handling, location tracking, and JSON roundtripping. 6 - 7 - ================================================================================ 8 - BASIC MULTIDOC DECODING 9 - ================================================================================ 10 - 11 - Simple multi-document stream with person objects 12 - 13 - $ test_multidoc simple ../data/multidoc/simple.yml 14 - Documents: 15 - [0] : Alice (age 30) 16 - [1] : Bob (age 25) 17 - [2] : Charlie (age 35) 18 - 19 - Count documents in a stream 20 - 21 - $ test_multidoc count ../data/multidoc/simple.yml 22 - Document count: 3 23 - 24 - ================================================================================ 25 - ERROR HANDLING - MIXED VALID AND INVALID DOCUMENTS 26 - ================================================================================ 27 - 28 - When some documents succeed and others fail, decode_all continues processing 29 - and returns results for each document individually. 30 - 31 - Stream with one error in the middle 32 - 33 - $ test_multidoc errors ../data/multidoc/mixed_errors.yml 34 - Document results: 35 - [0] OK: Alice (age 30) 36 - [1] ERROR: String "not-a-number" does not parse to OCaml int value 37 - File "-": 38 - File "-": in member age of 39 - File "-": Person object 40 - [2] OK: Charlie (age 35) 41 - 42 - Summary statistics for mixed documents 43 - 44 - $ test_multidoc summary ../data/multidoc/mixed_errors.yml 45 - Summary: 3 documents (2 ok, 1 error) 46 - 47 - Stream where all documents fail 48 - 49 - $ test_multidoc errors ../data/multidoc/all_errors.yml 50 - Document results: 51 - [0] ERROR: String "invalid1" does not parse to OCaml int value 52 - File "-": 53 - File "-": in member age of 54 - File "-": Person object 55 - [1] ERROR: String "invalid2" does not parse to OCaml int value 56 - File "-": 57 - File "-": in member age of 58 - File "-": Person object 59 - [2] ERROR: String "invalid3" does not parse to OCaml int value 60 - File "-": 61 - File "-": in member age of 62 - File "-": Person object 63 - 64 - Summary for all-error stream 65 - 66 - $ test_multidoc summary ../data/multidoc/all_errors.yml 67 - Summary: 3 documents (0 ok, 3 error) 68 - 69 - ================================================================================ 70 - LOCATION TRACKING WITH locs=true 71 - ================================================================================ 72 - 73 - Location tracking helps identify exactly where errors occur in each document 74 - of a multi-document stream. 75 - 76 - Without locs (default) - basic error information 77 - 78 - $ test_multidoc locations ../data/multidoc/mixed_errors.yml 79 - === Without locs (default) === 80 - [0] OK 81 - [1] ERROR: 82 - String "not-a-number" does not parse to OCaml int value 83 - File "-": 84 - File "-": in member age of 85 - File "-": Person object 86 - [2] OK 87 - 88 - === With locs=true === 89 - [0] OK 90 - [1] ERROR: 91 - String "not-a-number" does not parse to OCaml int value 92 - File "test.yml", line 6, characters 5-18: 93 - File "test.yml", line 6, characters 0-3: in member age of 94 - File "test.yml", line 5, characters 0-1: Person object 95 - [2] OK 96 - 97 - ================================================================================ 98 - MISSING FIELDS IN MULTIDOC 99 - ================================================================================ 100 - 101 - Documents with missing required fields generate errors but don't stop 102 - processing of subsequent documents. 103 - 104 - $ test_multidoc errors ../data/multidoc/missing_fields.yml 105 - Document results: 106 - [0] OK: Alice (age 30) 107 - [1] ERROR: Missing member age in Person object 108 - File "-": 109 - [2] OK: Charlie (age 35) 110 - 111 - Summary of missing fields test 112 - 113 - $ test_multidoc summary ../data/multidoc/missing_fields.yml 114 - Summary: 3 documents (2 ok, 1 error) 115 - 116 - ================================================================================ 117 - JSON ROUNDTRIPPING 118 - ================================================================================ 119 - 120 - Decode YAML multi-document streams and encode each document as JSON. 121 - This validates that the data model conversion is correct. 122 - 123 - Simple documents to JSON 124 - 125 - $ test_multidoc json ../data/multidoc/simple.yml 126 - JSON outputs: 127 - [0] {"name":"Alice","age":30} 128 - [1] {"name":"Bob","age":25} 129 - [2] {"name":"Charlie","age":35} 130 - 131 - Nested objects to JSON 132 - 133 - $ test_multidoc json ../data/multidoc/nested.yml 134 - JSON outputs: 135 - [0] {"name":"Alice","age":30,"address":{"street":"123 Main St","city":"Boston"}} 136 - [1] {"name":"Bob","age":25,"address":{"street":"456 Oak Ave","city":"Seattle"}} 137 - [2] {"name":"Charlie","age":35,"address":{"street":"789 Pine Rd","city":"Portland"}} 138 - 139 - Arrays to JSON 140 - 141 - $ test_multidoc json ../data/multidoc/arrays.yml 142 - JSON outputs: 143 - [0] [1,2,3] 144 - [1] ["apple","banana","cherry"] 145 - [2] [true,false,true] 146 - 147 - Scalar values to JSON 148 - 149 - $ test_multidoc json ../data/multidoc/scalars.yml 150 - JSON outputs: 151 - [0] "hello world" 152 - [1] 42 153 - [2] true 154 - [3] null 155 - 156 - ================================================================================ 157 - NESTED OBJECTS IN MULTIDOC 158 - ================================================================================ 159 - 160 - Test decoding complex nested structures across multiple documents. 161 - 162 - $ test_multidoc nested ../data/multidoc/nested.yml 163 - Nested documents: 164 - [0] : Alice (age 30) from 123 Main St, Boston 165 - [1] : Bob (age 25) from 456 Oak Ave, Seattle 166 - [2] : Charlie (age 35) from 789 Pine Rd, Portland 167 - 168 - ================================================================================ 169 - ARRAYS IN MULTIDOC 170 - ================================================================================ 171 - 172 - Test decoding different array types across documents. 173 - 174 - $ test_multidoc arrays ../data/multidoc/arrays.yml 175 - Array documents: 176 - [0] [1,2,3] 177 - [1] ["apple","banana","cherry"] 178 - [2] [true,false,true] 179 - 180 - ================================================================================ 181 - SCALARS IN MULTIDOC 182 - ================================================================================ 183 - 184 - Test decoding bare scalar values as documents. 185 - 186 - $ test_multidoc scalars ../data/multidoc/scalars.yml 187 - Scalar documents: 188 - [0] "hello world" 189 - [1] 42 190 - [2] true 191 - [3] null 192 - 193 - ================================================================================ 194 - EMPTY DOCUMENTS 195 - ================================================================================ 196 - 197 - Empty or null documents in a stream are handled correctly. 198 - 199 - $ test_multidoc json ../data/multidoc/empty_docs.yml 200 - JSON outputs: 201 - [0] {"name":"Alice","age":30} 202 - [1] null 203 - [2] {"name":"Charlie","age":35} 204 - 205 - Count including empty documents 206 - 207 - $ test_multidoc count ../data/multidoc/empty_docs.yml 208 - Document count: 3 209 - 210 - ================================================================================ 211 - SUMMARY 212 - ================================================================================ 213 - 214 - The decode_all function: 215 - - Processes all documents in a stream, not stopping on errors 216 - - Returns a sequence of Result values (Ok/Error for each document) 217 - - Supports all decode options: locs, layout, file, max_depth, max_nodes 218 - - Correctly handles document boundaries even when errors occur 219 - - Works with any Jsont codec (objects, arrays, scalars, etc.) 220 - - Can be used for JSON roundtripping and format conversion
-37
tests/cram/null_collections.t
··· 1 - Null to Empty Collection Tests 2 - ================================ 3 - 4 - This test suite validates that yamlt treats null values as empty collections 5 - when decoding into Array or Object types, providing a more user-friendly 6 - YAML experience. 7 - 8 - ================================================================================ 9 - NULL AS EMPTY COLLECTION 10 - ================================================================================ 11 - 12 - Test various forms of null decoding as empty arrays and objects 13 - 14 - $ test_null_collections 15 - === Test 1: Explicit null as empty array === 16 - Result: [] 17 - 18 - === Test 2: Tilde as empty array === 19 - Result: [] 20 - 21 - === Test 3: Empty array syntax === 22 - Result: [] 23 - 24 - === Test 4: Array with values === 25 - Result: [1; 2; 3] 26 - 27 - === Test 5: Explicit null as empty object === 28 - Result: {timeout=30; retries=3} 29 - 30 - === Test 6: Empty object syntax === 31 - Result: {timeout=30; retries=3} 32 - 33 - === Test 7: Object with values === 34 - Result: {timeout=60; retries=5} 35 - 36 - === Test 8: Nested null arrays === 37 - Result: {name=test; items_count=0; tags_count=0}
-171
tests/cram/objects_codec.t
··· 1 - Object Codec Tests with Yamlt 2 - ================================ 3 - 4 - This test suite validates object encoding/decoding with Jsont codecs in YAML, 5 - and compares behavior with JSON. 6 - 7 - Setup 8 - ----- 9 - 10 - 11 - ================================================================================ 12 - SIMPLE OBJECTS 13 - ================================================================================ 14 - 15 - Decode simple object with required fields 16 - 17 - $ test_objects simple ../data/objects/simple.yml 18 - JSON: person: {name="Alice"; age=30} 19 - YAML: person: {name="Alice"; age=30} 20 - 21 - ================================================================================ 22 - OPTIONAL FIELDS 23 - ================================================================================ 24 - 25 - Object with all optional fields present 26 - 27 - $ test_objects optional ../data/objects/optional_all.yml 28 - JSON: config: {host="localhost"; port=Some 8080; debug=Some true} 29 - YAML: config: {host="localhost"; port=Some 8080; debug=Some true} 30 - 31 - Object with some optional fields missing 32 - 33 - $ test_objects optional ../data/objects/optional_partial.yml 34 - JSON: config: {host="example.com"; port=Some 3000; debug=None} 35 - YAML: config: {host="example.com"; port=Some 3000; debug=None} 36 - 37 - Object with only required field 38 - 39 - $ test_objects optional ../data/objects/optional_minimal.yml 40 - JSON: config: {host="minimal.com"; port=None; debug=None} 41 - YAML: config: {host="minimal.com"; port=None; debug=None} 42 - 43 - ================================================================================ 44 - DEFAULT VALUES 45 - ================================================================================ 46 - 47 - Empty object uses all defaults 48 - 49 - $ test_objects defaults ../data/objects/defaults_empty.yml 50 - JSON: settings: {timeout=30; retries=3; verbose=false} 51 - YAML: settings: {timeout=30; retries=3; verbose=false} 52 - 53 - Object with partial fields uses defaults for missing ones 54 - 55 - $ test_objects defaults ../data/objects/defaults_partial.yml 56 - JSON: settings: {timeout=60; retries=3; verbose=false} 57 - YAML: settings: {timeout=60; retries=3; verbose=false} 58 - 59 - ================================================================================ 60 - NESTED OBJECTS 61 - ================================================================================ 62 - 63 - Objects containing other objects 64 - 65 - $ test_objects nested ../data/objects/nested.yml 66 - JSON: employee: {name="Bob"; address={street="123 Main St"; city="Springfield"; zip="12345"}} 67 - YAML: employee: {name="Bob"; address={street="123 Main St"; city="Springfield"; zip="12345"}} 68 - 69 - ================================================================================ 70 - UNKNOWN MEMBER HANDLING 71 - ================================================================================ 72 - 73 - Unknown members cause error by default 74 - 75 - $ test_objects unknown-error ../data/objects/unknown_members.yml 76 - Unexpected success 77 - 78 - Unknown members can be kept 79 - 80 - $ test_objects unknown-keep ../data/objects/unknown_keep.yml 81 - JSON: flexible: {name="Charlie"; has_extra=true} 82 - YAML: flexible: {name="Charlie"; has_extra=true} 83 - 84 - Unknown members are preserved during encoding roundtrip 85 - 86 - $ test_objects unknown-keep-roundtrip ../data/objects/unknown_keep.yml 87 - Decoded: name="Charlie", extra={"extra1":"value1","extra2":"value2"} 88 - Encoded Block: 89 - name: Charlie 90 - extra1: value1 91 - extra2: value2 92 - Re-decoded: name="Charlie", extra={"extra1":"value1","extra2":"value2"} 93 - Roundtrip: OK (extra members preserved) 94 - 95 - ================================================================================ 96 - OBJECT CASES (DISCRIMINATED UNIONS) 97 - ================================================================================ 98 - 99 - Decode circle variant 100 - 101 - $ test_objects cases ../data/objects/case_circle.yml 102 - JSON: shape: Circle{radius=5.50} 103 - YAML: shape: Circle{radius=5.50} 104 - 105 - Decode rectangle variant 106 - 107 - $ test_objects cases ../data/objects/case_rectangle.yml 108 - JSON: shape: ERROR: Missing member radius in Circle object 109 - File "-", line 1, characters 0-52: 110 - YAML: shape: ERROR: Missing member radius in Circle object 111 - File "-": 112 - 113 - ================================================================================ 114 - ERROR HANDLING 115 - ================================================================================ 116 - 117 - Missing required field produces error 118 - 119 - $ test_objects missing-required ../data/objects/missing_required.yml 120 - Expected error: Missing member age in Required object 121 - File "-": 122 - 123 - ================================================================================ 124 - ENCODING OBJECTS 125 - ================================================================================ 126 - 127 - Encode objects to JSON and YAML formats 128 - 129 - $ test_objects encode 130 - JSON: {"name":"Alice","age":30,"active":true} 131 - YAML Block: 132 - name: Alice 133 - age: 30 134 - active: true 135 - YAML Flow: {name: Alice, age: 30, active: true} 136 - 137 - ================================================================================ 138 - NEGATIVE TESTS - Wrong File Types 139 - ================================================================================ 140 - 141 - Attempting to decode an array file with an object codec should fail 142 - 143 - $ test_objects simple ../data/arrays/int_array.yml 144 - JSON: person: ERROR: Missing members in Person object: 145 - age 146 - name 147 - File "-", line 1, characters 0-27: 148 - YAML: person: ERROR: Missing members in Person object: 149 - age 150 - name 151 - File "-": 152 - 153 - Attempting to decode a scalar file with an object codec should fail 154 - 155 - $ test_objects simple ../data/scalars/string_plain.yml 156 - JSON: person: ERROR: Missing members in Person object: 157 - age 158 - name 159 - File "-", line 1, characters 0-24: 160 - YAML: person: ERROR: Missing members in Person object: 161 - age 162 - name 163 - File "-": 164 - 165 - Attempting to decode wrong object type (nested when expecting simple) should fail 166 - 167 - $ test_objects simple ../data/objects/nested.yml 168 - JSON: person: ERROR: Missing member age in Person object 169 - File "-", line 1, characters 0-92: 170 - YAML: person: ERROR: Missing member age in Person object 171 - File "-":
-46
tests/cram/roundtrip_codec.t
··· 1 - Roundtrip Encoding/Decoding Tests with Yamlt 2 - ============================================= 3 - 4 - This test suite validates that data can be encoded and then decoded back 5 - to the original value, ensuring no data loss in the roundtrip process. 6 - 7 - ================================================================================ 8 - SCALAR ROUNDTRIP 9 - ================================================================================ 10 - 11 - Encode and decode scalar types 12 - 13 - $ test_roundtrip scalar 14 - JSON roundtrip: PASS 15 - YAML Block roundtrip: PASS 16 - YAML Flow roundtrip: PASS 17 - 18 - ================================================================================ 19 - ARRAY ROUNDTRIP 20 - ================================================================================ 21 - 22 - Encode and decode arrays including nested arrays 23 - 24 - $ test_roundtrip array 25 - JSON array roundtrip: PASS 26 - YAML array roundtrip: PASS 27 - 28 - ================================================================================ 29 - OBJECT ROUNDTRIP 30 - ================================================================================ 31 - 32 - Encode and decode complex objects with nested structures 33 - 34 - $ test_roundtrip object 35 - JSON object roundtrip: PASS 36 - YAML object roundtrip: PASS 37 - 38 - ================================================================================ 39 - OPTIONAL FIELDS ROUNDTRIP 40 - ================================================================================ 41 - 42 - Encode and decode optional and nullable fields 43 - 44 - $ test_roundtrip optional 45 - Fatal error: exception Invalid_argument("option is None") 46 - [2]
-339
tests/cram/scalars_codec.t
··· 1 - Scalar Type Resolution Tests with Yamlt Codec 2 - ================================================== 3 - 4 - This test suite validates how YAML scalars are resolved based on the expected 5 - Jsont type codec, and compares behavior with JSON decoding. 6 - 7 - ================================================================================ 8 - NULL RESOLUTION 9 - ================================================================================ 10 - 11 - Explicit null value 12 - 13 - $ test_scalars null ../data/scalars/null_explicit.yml 14 - null_codec: null 15 - 16 - Tilde as null 17 - 18 - $ test_scalars null ../data/scalars/null_tilde.yml 19 - null_codec: null 20 - 21 - Empty value as null 22 - 23 - $ test_scalars null ../data/scalars/null_empty.yml 24 - null_codec: null 25 - 26 - ================================================================================ 27 - BOOLEAN TYPE-DIRECTED RESOLUTION 28 - ================================================================================ 29 - 30 - Plain "true" resolves to bool(true) with bool codec, but string "true" with string codec 31 - 32 - $ test_scalars bool ../data/scalars/bool_true_plain.yml 33 - === Bool Codec === 34 - JSON bool_codec 35 - decode: true 36 - YAML bool_codec 37 - decode: true 38 - 39 - === String Codec === 40 - JSON string_codec 41 - decode: ERROR: Expected string but found bool 42 - File "-", line 1, characters 10-11: 43 - File "-": in member value of 44 - File "-", line 1, characters 0-11: StringTest object 45 - YAML string_codec 46 - decode: "true" 47 - 48 - Quoted "true" always resolves to string, even with bool codec 49 - 50 - $ test_scalars bool ../data/scalars/bool_true_quoted.yml 51 - === Bool Codec === 52 - JSON bool_codec 53 - decode: ERROR: Expected bool but found string 54 - File "-", line 1, characters 10-11: 55 - File "-": in member value of 56 - File "-", line 1, characters 0-11: BoolTest object 57 - YAML bool_codec 58 - decode: true 59 - 60 - === String Codec === 61 - JSON string_codec 62 - decode: "true" 63 - YAML string_codec 64 - decode: "true" 65 - 66 - YAML-specific bool: "yes" resolves to bool(true) 67 - 68 - $ test_scalars bool ../data/scalars/bool_yes.yml 69 - === Bool Codec === 70 - JSON bool_codec 71 - decode: true 72 - YAML bool_codec 73 - decode: true 74 - 75 - === String Codec === 76 - JSON string_codec 77 - decode: ERROR: Expected string but found bool 78 - File "-", line 1, characters 10-11: 79 - File "-": in member value of 80 - File "-", line 1, characters 0-11: StringTest object 81 - YAML string_codec 82 - decode: "yes" 83 - 84 - Plain "false" and "no" work similarly 85 - 86 - $ test_scalars bool ../data/scalars/bool_false.yml 87 - === Bool Codec === 88 - JSON bool_codec 89 - decode: false 90 - YAML bool_codec 91 - decode: false 92 - 93 - === String Codec === 94 - JSON string_codec 95 - decode: ERROR: Expected string but found bool 96 - File "-", line 1, characters 10-11: 97 - File "-": in member value of 98 - File "-", line 1, characters 0-11: StringTest object 99 - YAML string_codec 100 - decode: "false" 101 - 102 - $ test_scalars bool ../data/scalars/bool_no.yml 103 - === Bool Codec === 104 - JSON bool_codec 105 - decode: false 106 - YAML bool_codec 107 - decode: false 108 - 109 - === String Codec === 110 - JSON string_codec 111 - decode: ERROR: Expected string but found bool 112 - File "-", line 1, characters 10-11: 113 - File "-": in member value of 114 - File "-", line 1, characters 0-11: StringTest object 115 - YAML string_codec 116 - decode: "no" 117 - 118 - ================================================================================ 119 - NUMBER RESOLUTION 120 - ================================================================================ 121 - 122 - Integer values 123 - 124 - $ test_scalars number ../data/scalars/number_int.yml 125 - JSON number_codec 126 - decode: 42 127 - YAML number_codec 128 - decode: 42 129 - 130 - Float values 131 - 132 - $ test_scalars number ../data/scalars/number_float.yml 133 - JSON number_codec 134 - decode: 3.1415899999999999 135 - YAML number_codec 136 - decode: 3.1415899999999999 137 - 138 - Hexadecimal notation (YAML-specific) 139 - 140 - $ test_scalars number ../data/scalars/number_hex.yml 141 - JSON number_codec 142 - decode: 42 143 - YAML number_codec 144 - decode: 42 145 - 146 - Octal notation (YAML-specific) 147 - 148 - $ test_scalars number ../data/scalars/number_octal.yml 149 - JSON number_codec 150 - decode: 42 151 - YAML number_codec 152 - decode: 42 153 - 154 - Negative numbers 155 - 156 - $ test_scalars number ../data/scalars/number_negative.yml 157 - JSON number_codec 158 - decode: -273.14999999999998 159 - YAML number_codec 160 - decode: -273.14999999999998 161 - 162 - ================================================================================ 163 - SPECIAL FLOAT VALUES (YAML-specific) 164 - ================================================================================ 165 - 166 - Positive infinity 167 - 168 - $ test_scalars special-float ../data/scalars/special_inf.yml 169 - value: +Infinity 170 - 171 - Negative infinity 172 - 173 - $ test_scalars special-float ../data/scalars/special_neg_inf.yml 174 - value: -Infinity 175 - 176 - Not-a-Number (NaN) 177 - 178 - $ test_scalars special-float ../data/scalars/special_nan.yml 179 - value: NaN 180 - 181 - ================================================================================ 182 - STRING RESOLUTION 183 - ================================================================================ 184 - 185 - Plain strings 186 - 187 - $ test_scalars string ../data/scalars/string_plain.yml 188 - JSON string_codec 189 - decode: "hello world" 190 - YAML string_codec 191 - decode: "hello world" 192 - 193 - Quoted numeric strings stay as strings 194 - 195 - $ test_scalars string ../data/scalars/string_quoted.yml 196 - JSON string_codec 197 - decode: "42" 198 - YAML string_codec 199 - decode: "42" 200 - 201 - Empty strings 202 - 203 - $ test_scalars string ../data/scalars/string_empty.yml 204 - JSON string_codec 205 - decode: "" 206 - YAML string_codec 207 - decode: "" 208 - 209 - ================================================================================ 210 - TYPE MISMATCH ERRORS 211 - ================================================================================ 212 - 213 - String when bool expected 214 - 215 - $ test_scalars type-mismatch ../data/scalars/mismatch_string_as_bool.yml bool 216 - Expected error: Expected bool but found scalar hello 217 - File "-": 218 - File "-": in member value of 219 - File "-": BoolTest object 220 - 221 - String when number expected 222 - 223 - $ test_scalars type-mismatch ../data/scalars/mismatch_string_as_number.yml number 224 - Expected error: Expected number but found scalar not-a-number 225 - File "-": 226 - File "-": in member value of 227 - File "-": NumberTest object 228 - 229 - Number when null expected 230 - 231 - $ test_scalars type-mismatch ../data/scalars/mismatch_number_as_null.yml null 232 - Expected error: Expected null but found scalar 42 233 - File "-": 234 - File "-": in member value of 235 - File "-": NullTest object 236 - 237 - ================================================================================ 238 - JSONT.ANY AUTO-RESOLUTION 239 - ================================================================================ 240 - 241 - With Jsont.any, scalars are auto-resolved based on their content 242 - 243 - Null auto-resolves to null 244 - 245 - $ test_scalars any ../data/scalars/any_null.yml 246 - JSON any_codec 247 - decode: decoded 248 - YAML any_codec 249 - decode: decoded 250 - 251 - Plain bool auto-resolves to bool 252 - 253 - $ test_scalars any ../data/scalars/any_bool.yml 254 - JSON any_codec 255 - decode: decoded 256 - YAML any_codec 257 - decode: decoded 258 - 259 - Number auto-resolves to number 260 - 261 - $ test_scalars any ../data/scalars/any_number.yml 262 - JSON any_codec 263 - decode: decoded 264 - YAML any_codec 265 - decode: decoded 266 - 267 - Plain string auto-resolves to string 268 - 269 - $ test_scalars any ../data/scalars/any_string.yml 270 - JSON any_codec 271 - decode: decoded 272 - YAML any_codec 273 - decode: decoded 274 - 275 - ================================================================================ 276 - ENCODING SCALARS 277 - ================================================================================ 278 - 279 - Encoding bool values 280 - 281 - $ test_scalars encode bool true 282 - JSON: {"value":true} 283 - YAML Block: 284 - value: true 285 - YAML Flow: {value: true} 286 - 287 - $ test_scalars encode bool false 288 - JSON: {"value":false} 289 - YAML Block: 290 - value: false 291 - YAML Flow: {value: false} 292 - 293 - Encoding numbers 294 - 295 - $ test_scalars encode number 42.5 296 - JSON: {"value":42.5} 297 - YAML Block: 298 - value: 42.5 299 - YAML Flow: {value: 42.5} 300 - 301 - Encoding strings 302 - 303 - $ test_scalars encode string "hello world" 304 - JSON: {"value":"hello world"} 305 - YAML Block: 306 - value: hello world 307 - YAML Flow: {value: hello world} 308 - 309 - Encoding null 310 - 311 - $ test_scalars encode null "" 312 - JSON: {"value":null} 313 - YAML Block: 314 - value: null 315 - YAML Flow: {value: null} 316 - 317 - ================================================================================ 318 - NEGATIVE TESTS - Wrong File Types 319 - ================================================================================ 320 - 321 - Attempting to decode an object file with a scalar codec should fail 322 - 323 - $ test_scalars string ../data/objects/simple.yml 324 - JSON string_codec 325 - decode: ERROR: Missing member value in StringTest object 326 - File "-", line 1, characters 0-28: 327 - YAML string_codec 328 - decode: ERROR: Missing member value in StringTest object 329 - File "-": 330 - 331 - Attempting to decode an array file with a scalar codec should fail 332 - 333 - $ test_scalars number ../data/arrays/int_array.yml 334 - JSON number_codec 335 - decode: ERROR: Missing member value in NumberTest object 336 - File "-", line 1, characters 0-27: 337 - YAML number_codec 338 - decode: ERROR: Missing member value in NumberTest object 339 - File "-":
-6
tests/data/arrays/bool_array.yml
··· 1 - values: 2 - - true 3 - - false 4 - - true 5 - - true 6 - - false
-1
tests/data/arrays/bool_array.yml.json
··· 1 - {"values": [true, false, true, true, false]}
-1
tests/data/arrays/empty_array.yml
··· 1 - items: []
-1
tests/data/arrays/empty_array.yml.json
··· 1 - {"items": []}
-5
tests/data/arrays/float_array.yml
··· 1 - values: 2 - - 1.5 3 - - 2.7 4 - - 3.14 5 - - 0.5
-1
tests/data/arrays/float_array.yml.json
··· 1 - {"values": [1.5, 2.7, 3.14, 0.5]}
-6
tests/data/arrays/int_array.yml
··· 1 - values: 2 - - 1 3 - - 2 4 - - 3 5 - - 4 6 - - 5
-1
tests/data/arrays/int_array.yml.json
··· 1 - {"values": [1, 2, 3, 4, 5]}
-4
tests/data/arrays/nested_array.yml
··· 1 - data: 2 - - [1, 2, 3] 3 - - [4, 5, 6] 4 - - [7, 8, 9]
-1
tests/data/arrays/nested_array.yml.json
··· 1 - {"data": [[1, 2, 3], [4, 5, 6], [7, 8, 9]]}
-6
tests/data/arrays/nullable_array.yml
··· 1 - values: 2 - - hello 3 - - null 4 - - world 5 - - null 6 - - test
-1
tests/data/arrays/nullable_array.yml.json
··· 1 - {"values": ["hello", null, "world", null, "test"]}
-7
tests/data/arrays/object_array.yml
··· 1 - persons: 2 - - name: Alice 3 - age: 30 4 - - name: Bob 5 - age: 25 6 - - name: Charlie 7 - age: 35
-1
tests/data/arrays/object_array.yml.json
··· 1 - {"persons": [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}, {"name": "Charlie", "age": 35}]}
-4
tests/data/arrays/string_array.yml
··· 1 - items: 2 - - apple 3 - - banana 4 - - cherry
-1
tests/data/arrays/string_array.yml.json
··· 1 - {"items": ["apple", "banana", "cherry"]}
-5
tests/data/arrays/type_mismatch.yml
··· 1 - values: 2 - - 1 3 - - 2 4 - - not-a-number 5 - - 4
-4
tests/data/complex/complex_optional.yml
··· 1 - host: example.com 2 - port: 443 3 - ssl: true 4 - fallback_hosts: [backup1.example.com, backup2.example.com]
-1
tests/data/complex/complex_optional.yml.json
··· 1 - {"host": "example.com", "port": 443, "ssl": true, "fallback_hosts": ["backup1.example.com", "backup2.example.com"]}
-4
tests/data/complex/deep_nesting.yml
··· 1 - top: 2 - nested: 3 - data: 4 - value: 42
-1
tests/data/complex/deep_nesting.yml.json
··· 1 - {"top": {"nested": {"data": {"value": 42}}}}
-1
tests/data/complex/heterogeneous.yml
··· 1 - mixed: [42, "hello", true, null, 3.14]
-1
tests/data/complex/heterogeneous.yml.json
··· 1 - {"mixed": [42, "hello", true, null, 3.14]}
-8
tests/data/complex/mixed_structure.yml
··· 1 - name: products 2 - items: 3 - - id: 1 4 - tags: [new, sale, featured] 5 - - id: 2 6 - tags: [clearance] 7 - - id: 3 8 - tags: [premium, exclusive]
-1
tests/data/complex/mixed_structure.yml.json
··· 1 - {"name": "products", "items": [{"id": 1, "tags": ["new", "sale", "featured"]}, {"id": 2, "tags": ["clearance"]}, {"id": 3, "tags": ["premium", "exclusive"]}]}
-2
tests/data/edge/empty_collections.yml
··· 1 - empty_array: [] 2 - empty_object_array: []
-1
tests/data/edge/empty_collections.yml.json
··· 1 - {"empty_array": [], "empty_object_array": []}
-3
tests/data/edge/large_numbers.yml
··· 1 - large_int: 9007199254740991 2 - large_float: 1.7976931348623157e+308 3 - small_float: 2.2250738585072014e-308
-1
tests/data/edge/large_numbers.yml.json
··· 1 - {"large_int": 9007199254740991, "large_float": 1.7976931348623157e+308, "small_float": 2.2250738585072014e-308}
-1
tests/data/edge/single_element.yml
··· 1 - single: [42]
-1
tests/data/edge/single_element.yml.json
··· 1 - {"single": [42]}
-1
tests/data/edge/special_chars.yml
··· 1 - content: "Line 1\nLine 2\tTabbed\r\nWindows line"
-1
tests/data/edge/special_chars.yml.json
··· 1 - {"content": "Line 1\nLine 2\tTabbed\r\nWindows line"}
-3
tests/data/edge/special_keys.yml
··· 1 - "key.with.dots": value1 2 - "key-with-dashes": value2 3 - "key:with:colons": value3
-1
tests/data/edge/special_keys.yml.json
··· 1 - {"key.with.dots": "value1", "key-with-dashes": "value2", "key:with:colons": "value3"}
-3
tests/data/edge/unicode.yml
··· 1 - emoji: "🎉🚀✨" 2 - chinese: "你好世界" 3 - rtl: "مرحبا"
-1
tests/data/edge/unicode.yml.json
··· 1 - {"emoji": "🎉🚀✨", "chinese": "你好世界", "rtl": "مرحبا"}
-5
tests/data/formats/comments.yml
··· 1 - # Configuration file with comments 2 - host: localhost # The server host 3 - port: 8080 # The server port 4 - # Enable debug mode for development 5 - debug: true
-1
tests/data/formats/empty_doc.yml
··· 1 - value: null
-1
tests/data/formats/empty_doc.yml.json
··· 1 - {"value": null}
-1
tests/data/formats/explicit_tags.yml
··· 1 - data: !!str 123
-5
tests/data/formats/folded_string.yml
··· 1 - content: > 2 - This is a folded string that 3 - spans multiple lines but will 4 - be folded into a single line 5 - with spaces between words
-1
tests/data/formats/folded_string.yml.json
··· 1 - {"content": "This is a folded string that spans multiple lines but will be folded into a single line with spaces between words\n"}
-5
tests/data/formats/literal_string.yml
··· 1 - content: | 2 - This is a literal string 3 - with multiple lines 4 - preserving newlines 5 - and indentation
-1
tests/data/formats/literal_string.yml.json
··· 1 - {"content": "This is a literal string\nwith multiple lines\npreserving newlines\nand indentation\n"}
-3
tests/data/formats/number_formats.yml
··· 1 - hex: 0xFF 2 - octal: 0o77 3 - binary: 0b1010
-1
tests/data/formats/number_formats.yml.json
··· 1 - {"hex": 255, "octal": 63, "binary": 10}
-6
tests/data/locations/array_error.yml
··· 1 - values: 2 - - 1 3 - - 2 4 - - not-a-number 5 - - 4 6 - - 5
-4
tests/data/locations/block_style.yml
··· 1 - items: 2 - - apple 3 - - banana 4 - - cherry
-1
tests/data/locations/flow_style.yml
··· 1 - items: [apple, banana, cherry]
-2
tests/data/locations/missing_field.yml
··· 1 - field_a: hello 2 - field_b: 42
-5
tests/data/locations/nested_error.yml
··· 1 - name: Bob 2 - address: 3 - street: 123 Main St 4 - city: Springfield 5 - zip: invalid-zip
-2
tests/data/locations/simple.yml
··· 1 - host: localhost 2 - port: 8080
-2
tests/data/locations/type_error.yml
··· 1 - name: Alice 2 - age: not-a-number
-2
tests/data/locations/valid_settings.yml
··· 1 - timeout: 30 2 - retries: 3
-9
tests/data/multidoc/all_errors.yml
··· 1 - --- 2 - name: Alice 3 - age: invalid1 4 - --- 5 - name: Bob 6 - age: invalid2 7 - --- 8 - name: Charlie 9 - age: invalid3
-12
tests/data/multidoc/arrays.yml
··· 1 - --- 2 - - 1 3 - - 2 4 - - 3 5 - --- 6 - - apple 7 - - banana 8 - - cherry 9 - --- 10 - - true 11 - - false 12 - - true
-7
tests/data/multidoc/empty_docs.yml
··· 1 - --- 2 - name: Alice 3 - age: 30 4 - --- 5 - --- 6 - name: Charlie 7 - age: 35
-9
tests/data/multidoc/missing_fields.yml
··· 1 - --- 2 - name: Alice 3 - age: 30 4 - --- 5 - name: Bob 6 - --- 7 - name: Charlie 8 - age: 35 9 - city: Springfield
-9
tests/data/multidoc/mixed_errors.yml
··· 1 - --- 2 - name: Alice 3 - age: 30 4 - --- 5 - name: Bob 6 - age: not-a-number 7 - --- 8 - name: Charlie 9 - age: 35
-18
tests/data/multidoc/nested.yml
··· 1 - --- 2 - name: Alice 3 - age: 30 4 - address: 5 - street: 123 Main St 6 - city: Boston 7 - --- 8 - name: Bob 9 - age: 25 10 - address: 11 - street: 456 Oak Ave 12 - city: Seattle 13 - --- 14 - name: Charlie 15 - age: 35 16 - address: 17 - street: 789 Pine Rd 18 - city: Portland
-8
tests/data/multidoc/scalars.yml
··· 1 - --- 2 - hello world 3 - --- 4 - 42 5 - --- 6 - true 7 - --- 8 - null
-9
tests/data/multidoc/simple.yml
··· 1 - --- 2 - name: Alice 3 - age: 30 4 - --- 5 - name: Bob 6 - age: 25 7 - --- 8 - name: Charlie 9 - age: 35
-2
tests/data/objects/case_circle.yml
··· 1 - type: circle 2 - radius: 5.5
-1
tests/data/objects/case_circle.yml.json
··· 1 - {"type": "circle", "radius": 5.5}
-3
tests/data/objects/case_rectangle.yml
··· 1 - type: rectangle 2 - width: 10.0 3 - height: 20.0
-1
tests/data/objects/case_rectangle.yml.json
··· 1 - {"type": "rectangle", "width": 10.0, "height": 20.0}
-1
tests/data/objects/defaults_empty.yml
··· 1 - {}
-1
tests/data/objects/defaults_empty.yml.json
··· 1 - {}
-1
tests/data/objects/defaults_partial.yml
··· 1 - timeout: 60
-1
tests/data/objects/defaults_partial.yml.json
··· 1 - {"timeout": 60}
-1
tests/data/objects/missing_required.yml
··· 1 - name: Incomplete
-5
tests/data/objects/nested.yml
··· 1 - name: Bob 2 - address: 3 - street: 123 Main St 4 - city: Springfield 5 - zip: "12345"
-1
tests/data/objects/nested.yml.json
··· 1 - {"name": "Bob", "address": {"street": "123 Main St", "city": "Springfield", "zip": "12345"}}
-3
tests/data/objects/optional_all.yml
··· 1 - host: localhost 2 - port: 8080 3 - debug: true
-1
tests/data/objects/optional_all.yml.json
··· 1 - {"host": "localhost", "port": 8080, "debug": true}
-1
tests/data/objects/optional_minimal.yml
··· 1 - host: minimal.com
-1
tests/data/objects/optional_minimal.yml.json
··· 1 - {"host": "minimal.com"}
-2
tests/data/objects/optional_partial.yml
··· 1 - host: example.com 2 - port: 3000
-1
tests/data/objects/optional_partial.yml.json
··· 1 - {"host": "example.com", "port": 3000}
-2
tests/data/objects/simple.yml
··· 1 - name: Alice 2 - age: 30
-1
tests/data/objects/simple.yml.json
··· 1 - {"name": "Alice", "age": 30}
-3
tests/data/objects/unknown_keep.yml
··· 1 - name: Charlie 2 - extra1: value1 3 - extra2: value2
-1
tests/data/objects/unknown_keep.yml.json
··· 1 - {"name": "Charlie", "extra1": "value1", "extra2": "value2"}
-3
tests/data/objects/unknown_members.yml
··· 1 - name: Alice 2 - age: 30 3 - extra: not_expected
-1
tests/data/scalars/any_bool.yml
··· 1 - value: true
-1
tests/data/scalars/any_bool.yml.json
··· 1 - {"value": true}
-1
tests/data/scalars/any_null.yml
··· 1 - value: null
-1
tests/data/scalars/any_null.yml.json
··· 1 - {"value": null}
-1
tests/data/scalars/any_number.yml
··· 1 - value: 123.45
-1
tests/data/scalars/any_number.yml.json
··· 1 - {"value": 123.45}
-1
tests/data/scalars/any_string.yml
··· 1 - value: hello
-1
tests/data/scalars/any_string.yml.json
··· 1 - {"value": "hello"}
-1
tests/data/scalars/bool_false.yml
··· 1 - value: false
-1
tests/data/scalars/bool_false.yml.json
··· 1 - {"value": false}
-1
tests/data/scalars/bool_no.yml
··· 1 - value: no
-1
tests/data/scalars/bool_no.yml.json
··· 1 - {"value": false}
-1
tests/data/scalars/bool_true_plain.yml
··· 1 - value: true
-1
tests/data/scalars/bool_true_plain.yml.json
··· 1 - {"value": true}
-1
tests/data/scalars/bool_true_quoted.yml
··· 1 - value: "true"
-1
tests/data/scalars/bool_true_quoted.yml.json
··· 1 - {"value": "true"}
-1
tests/data/scalars/bool_yes.yml
··· 1 - value: yes
-1
tests/data/scalars/bool_yes.yml.json
··· 1 - {"value": true}
-1
tests/data/scalars/mismatch_number_as_null.yml
··· 1 - value: 42
-1
tests/data/scalars/mismatch_string_as_bool.yml
··· 1 - value: hello
-1
tests/data/scalars/mismatch_string_as_number.yml
··· 1 - value: not-a-number
-1
tests/data/scalars/null_empty.yml
··· 1 - value:
-1
tests/data/scalars/null_explicit.yml
··· 1 - value: null
-1
tests/data/scalars/null_tilde.yml
··· 1 - value: ~
-1
tests/data/scalars/number_float.yml
··· 1 - value: 3.14159
-1
tests/data/scalars/number_float.yml.json
··· 1 - {"value": 3.14159}
-1
tests/data/scalars/number_hex.yml
··· 1 - value: 0x2A
-1
tests/data/scalars/number_hex.yml.json
··· 1 - {"value": 42}
-1
tests/data/scalars/number_int.yml
··· 1 - value: 42
-1
tests/data/scalars/number_int.yml.json
··· 1 - {"value": 42}
-1
tests/data/scalars/number_negative.yml
··· 1 - value: -273.15
-1
tests/data/scalars/number_negative.yml.json
··· 1 - {"value": -273.15}
-1
tests/data/scalars/number_octal.yml
··· 1 - value: 0o52
-1
tests/data/scalars/number_octal.yml.json
··· 1 - {"value": 42}
-1
tests/data/scalars/special_inf.yml
··· 1 - value: .inf
-1
tests/data/scalars/special_nan.yml
··· 1 - value: .nan
-1
tests/data/scalars/special_neg_inf.yml
··· 1 - value: -.inf
-1
tests/data/scalars/string_empty.yml
··· 1 - value: ""
-1
tests/data/scalars/string_empty.yml.json
··· 1 - {"value": ""}
-1
tests/data/scalars/string_plain.yml
··· 1 - value: hello world
-1
tests/data/scalars/string_plain.yml.json
··· 1 - {"value": "hello world"}
-1
tests/data/scalars/string_quoted.yml
··· 1 - value: "42"
-1
tests/data/scalars/string_quoted.yml.json
··· 1 - {"value": "42"}
+2 -2
yamlt.opam
··· 6 6 maintainer: ["Anil Madhavapeddy <anil@recoil.org>"] 7 7 authors: ["Anil Madhavapeddy"] 8 8 license: "ISC" 9 - homepage: "https://tangled.org/@anil.recoil.org/ocaml-yamlt" 10 - bug-reports: "https://tangled.org/@anil.recoil.org/ocaml-yamlt/issues" 9 + homepage: "https://tangled.org/anil.recoil.org/ocaml-yamlt" 10 + bug-reports: "https://tangled.org/anil.recoil.org/ocaml-yamlt/issues" 11 11 depends: [ 12 12 "dune" {>= "3.18"} 13 13 "ocaml" {>= "4.14.0"}