@@ -42,8 +42,9 @@ module FileCheck
42
42
import LLVM_jll
43
43
import IOCapture
44
44
using InteractiveUtils
45
+ using Test
45
46
46
- export filecheck
47
+ export filecheck, @filecheck , @check_str
47
48
48
49
global filecheck_path:: String
49
50
function __init__ ()
@@ -77,33 +78,76 @@ module FileCheck
77
78
78
79
function filecheck (f, input)
79
80
# 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 )
83
84
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 )
91
92
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)
94
96
end
95
97
96
- # Determine some useful prefixes for FileCheck
98
+ # determine some useful prefixes for FileCheck
97
99
prefixes = [" CHECK" ]
98
100
if julia_typed_pointers
99
101
push! (prefixes, " OPAQUE" )
100
102
else
101
103
push! (prefixes, " TYPED" )
102
104
end
103
105
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" )
107
143
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 )
108
152
end
109
153
end
0 commit comments