@@ -42,8 +42,9 @@ module FileCheck
4242 import LLVM_jll
4343 import IOCapture
4444 using InteractiveUtils
45+ using Test
4546
46- export filecheck
47+ export filecheck, @filecheck , @check_str
4748
4849 global filecheck_path:: String
4950 function __init__ ()
@@ -77,33 +78,76 @@ module FileCheck
7778
7879 function filecheck (f, input)
7980 # FileCheck assumes that the input is available as a file
80- mktemp () do path, io
81- write (io , input)
82- close (io )
81+ mktemp () do path, input_io
82+ write (input_io , input)
83+ close (input_io )
8384
84- # Now execute `f` with IOCapture
85- # XXX : See if Suppressor is a better fit
86- value, output, error, backtrace = IOCapture . capture (() -> f (input); rethrow = Union{} )
87-
88- io = IOBuffer ()
89- write (io, output)
90- println (io )
85+ # capture the output of `f` and write it into a temporary buffer
86+ result = IOCapture . capture (rethrow = Union{}) do
87+ f (input)
88+ end
89+ output_io = IOBuffer ()
90+ write (output_io, result . output)
91+ println (output_io )
9192
92- if error
93- showerror (io, value, backtrace)
93+ # if the function errored, also render the exception and backtrace
94+ if result. error
95+ showerror (output_io, result. value, result. backtrace)
9496 end
9597
96- # Determine some useful prefixes for FileCheck
98+ # determine some useful prefixes for FileCheck
9799 prefixes = [" CHECK" ]
98100 if julia_typed_pointers
99101 push! (prefixes, " OPAQUE" )
100102 else
101103 push! (prefixes, " TYPED" )
102104 end
103105
104- seekstart (io)
105- cmd = ` $(filecheck_exe ()) --allow-unused-prefixes --check-prefixes $(join (prefixes, ' ,' )) $path `
106- value, success (pipeline (cmd; stdin = io, stdout , stderr ))
106+ # now pass the collected output to FileCheck
107+ seekstart (output_io)
108+ filecheck_io = Pipe ()
109+ cmd = ``` $(filecheck_exe ())
110+ --color
111+ --dump-input never
112+ --allow-unused-prefixes
113+ --check-prefixes $(join (prefixes, ' ,' ))
114+ $path ```
115+ proc = run (pipeline (ignorestatus (cmd); stdin = output_io, stdout = filecheck_io, stderr = filecheck_io); wait= false )
116+ close (filecheck_io. in)
117+
118+ # collect the output of FileCheck
119+ reader = Threads. @spawn String (read (filecheck_io))
120+ Base. wait (proc)
121+ log = strip (fetch (reader))
122+
123+ # error out if FileCheck did not succeed.
124+ # otherwise, return true so that `@test @filecheck` works as expected.
125+ if ! success (proc)
126+ error (log)
127+ end
128+ return true
129+ end
130+ end
131+
132+ # collect checks used in the @filecheck block by piggybacking on macro expansion
133+ const checks = String[]
134+ macro check_str (str)
135+ push! (checks, str)
136+ nothing
137+ end
138+
139+ macro filecheck (ex)
140+ ex = Base. macroexpand (__module__, ex)
141+ if isempty (checks)
142+ error (" No checks provided within the @filecheck macro block" )
107143 end
144+ check_str = join (checks, " \n " )
145+ empty! (checks)
146+
147+ esc (quote
148+ filecheck ($ check_str) do _
149+ $ ex
150+ end
151+ end )
108152 end
109153end
0 commit comments