package ppx_expect
Cram like framework for OCaml
Install
Dune Dependency
Authors
Maintainers
Sources
v0.17.0.tar.gz
sha256=6cb403d7d59f7451f1d5a94838ca46902991fc7bb43e5342b620fc73ab99bd94
doc/src/ppx_expect.runtime/write_corrected_file.ml.html
Source file write_corrected_file.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
open! Base open Types module Patch_with_file_contents = struct type 'a t = original_file_contents:string -> 'a -> (Compact_loc.t * string) list end let rewrite_corrections ~original_file_contents ~corrections = (* Ensure that we encounter the corrections in order as we build up the file. *) let corrections = List.sort ~compare:(Comparable.lift Compact_loc.compare_character_range ~f:fst) corrections in let l_pos, strs = List.fold_map corrections ~init:0 ~f:(fun l_pos ({ start_pos; end_pos; start_bol = _ }, correction) -> let code_chunk = String.sub original_file_contents ~pos:l_pos ~len:(start_pos - l_pos) in end_pos, [ code_chunk; correction ]) in let result = List.concat strs |> String.concat in let rest = String.subo original_file_contents ~pos:l_pos in result ^ rest ;; let f ~use_color ~in_place ~diff_command ~diff_path_prefix ~filename ~with_ corrections : Ppx_inline_test_lib.Test_result.t = let dot_corrected = filename ^ ".corrected" in let original_file_contents = let in_channel = Stdlib.open_in filename in let contents = Stdlib.really_input_string in_channel (Stdlib.in_channel_length in_channel) in Stdlib.close_in in_channel; contents in let remove file = if Stdlib.Sys.file_exists file then Stdlib.Sys.remove file in let corrections = with_ ~original_file_contents corrections in let next_contents = rewrite_corrections ~original_file_contents ~corrections in match in_place with | true -> if not (String.equal original_file_contents next_contents) then Stdio.Out_channel.write_all filename ~data:next_contents; remove dot_corrected; Success | false -> (match diff_command with | Some "-" (* Just write the .corrected file - do not output a diff. *) -> Stdio.Out_channel.write_all dot_corrected ~data:next_contents; Success | _ -> (* By invoking [Make_corrected_file.f] with a fresh temporary file, we avoid the following possible race between inline_test_runners A and B: 1. A runs test T1 and generates next contents C1. 2. B runs test T2 and generates next contents C2. 3. A writes C1 to the .corrected file. 4. B writes C2 to the .corrected file. 5. A diffs the .corrected file against the original file and reports the result. It thinks it is reporting the diff produced by T1, but is in fact reporting the diff produced by T2. The key aspect of using temporary files is that even if in the above scenario the final contents of the .corrected file are C2, the diff reported by A comes from its tmp file and will still be the diff produced by T1. *) let tmp_corrected = Stdlib.Filename.temp_file (Stdlib.Filename.basename filename) ".corrected.tmp" ~temp_dir:(Stdlib.Filename.dirname filename) in (match Make_corrected_file.f ~use_color ?diff_command ?diff_path_prefix ~corrected_path:tmp_corrected ~next_contents ~path:filename () with | Ok _ -> (* Even though this execution of the expect test ran without making corrections, we should delete any old [.corrected] files that are left over from previous builds. In particular, hydra relies on this behavior for flaky tests; if the test fails the first time and passes the second, the second run should make sure the [.corrected] file is not lingering in the sandbox. *) remove dot_corrected; remove tmp_corrected; Success | Error _ -> Stdlib.Sys.rename tmp_corrected dot_corrected; Failure)) ;;
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>