diff --git a/test/test_dev.ml b/test/test_dev.ml index 6b62062..0488551 100644 --- a/test/test_dev.ml +++ b/test/test_dev.ml @@ -2829,7 +2829,22 @@ let () = outlive a sequence with several cold clang drivers in it, which is what programs/dev-robust.flan is for. *) let rsock = tmp "robust.sock" and rout = tmp "robust.out" in + (* This daemon gets a stderr of its own, which none of the others needs. + [Build.run] shells out with [Sys.command], so a clang driver's own words + go to whatever stderr it inherited — and the two failures below are + deliberate, so on a *passing* run the suite was printing + "cannot open output file ... Permission denied" and "linker command + failed" straight to the terminal. Four lines of what reads like a broken + toolchain, on every run, for years of handoffs. Noise that is always + there stops being read, and a real linker failure in this spot would + have been invisible behind it. So it goes to a file, and the file is + reprinted below only if a step in this block actually failed. *) + let rerr = tmp "robust.err" in let rcache = tmp "robust.cache" in + (* Counted from here, not from zero: [failures] is the whole file's, and a + failure in an earlier block is not a reason to reprint this daemon's + expected complaints. *) + let rfailures = !failures in let rec rm_rf path = match Sys.is_directory path with | true -> @@ -2853,12 +2868,23 @@ let () = @ [ "FLAN_CACHE_DIR=" ^ rcache ]) in let rfd = Unix.openfile rout [ Unix.O_WRONLY; Unix.O_CREAT; Unix.O_TRUNC ] 0o600 in + let refd = Unix.openfile rerr [ Unix.O_WRONLY; Unix.O_CREAT; Unix.O_TRUNC ] 0o600 in + (* Said out loud, because the alternative is a reader deciding for + themselves what a linker complaint in a test run means. Deliberately no + "error" or "FAIL" in the wording: the reader this line is for is + scanning for exactly those words. *) + print_endline + "dev: two builds below are made to fail on purpose — the robustness \ + fixture holds its own cache directory read-only, so the linker cannot \ + write its output there. The compiler's complaints go to a log and are \ + reprinted only if a step actually goes wrong."; let rpid = Unix.create_process_env flan [| flan; "dev"; "programs/dev-robust.flan"; "-s"; rsock |] - renv Unix.stdin rfd Unix.stderr + renv Unix.stdin rfd refd in Unix.close rfd; + Unix.close refd; if not (listening ~pid:rpid rsock) then begin fail "the robustness daemon %s" !listen_why; (try Unix.kill rpid Sys.sigkill with Unix.Unix_error _ -> ()) @@ -3026,8 +3052,23 @@ let () = (try ignore (Unix.waitpid [] rpid) with Unix.Unix_error _ -> ()); (try Unix.chmod rcache 0o700 with Unix.Unix_error _ -> ()); rm_rf rcache; + (* Its contents rather than its name: [rerr] is under dune's per-run + TMPDIR, which is gone by the time anyone reads the run. *) + if !failures > rfailures then begin + print_endline + "dev: the robustness daemon's stderr follows. Two of the linker \ + failures in it are the deliberate ones described above; anything \ + else is not."; + match open_in_bin rerr with + | ic -> + let n = in_channel_length ic in + print_string (really_input_string ic n); + flush stdout; + close_in ic + | exception Sys_error e -> Printf.printf " (unreadable: %s)\n" e + end; List.iter (fun f -> try Sys.remove f with Sys_error _ -> ()) - [ rsock; rout ]; + [ rsock; rout; rerr ]; List.iter (fun f -> try Sys.remove f with Sys_error _ -> ()) [ sock; out; bsock; bout ];