@@ -54,6 +54,7 @@ defmodule ExUnit.Formatter do
54
54
55
55
@ counter_padding " "
56
56
@ mailbox_label_padding @ counter_padding <> " "
57
+ @ formatter_exceptions [ ExUnit.AssertionError , FunctionClauseError ]
57
58
@ no_value ExUnit.AssertionError . no_value ( )
58
59
59
60
@ doc """
@@ -136,10 +137,10 @@ defmodule ExUnit.Formatter do
136
137
137
138
@ doc false
138
139
def format_assertion_error ( % ExUnit.AssertionError { } = struct ) do
139
- format_assertion_error ( % { } , struct , [ ] , :infinity , fn _ , msg -> msg end , "" )
140
+ format_exception ( % { } , struct , [ ] , :infinity , fn _ , msg -> msg end , "" ) |> elem ( 0 )
140
141
end
141
142
142
- defp format_assertion_error ( test , struct , stack , width , formatter , counter_padding ) do
143
+ defp format_exception ( test , % ExUnit.AssertionError { } = struct , stack , width , formatter , pad ) do
143
144
label_padding_size = if has_value? ( struct . right ) , do: 7 , else: 6
144
145
padding_size = label_padding_size + byte_size ( @ counter_padding )
145
146
@@ -148,16 +149,27 @@ defmodule ExUnit.Formatter do
148
149
do: & pad_multiline ( & 1 , padding_size ) ,
149
150
else: & code_multiline ( & 1 , padding_size )
150
151
151
- [
152
- note: if_value ( struct . message , & format_message ( & 1 , formatter ) ) ,
153
- doctest: if_value ( struct . doctest , & pad_multiline ( & 1 , 2 + byte_size ( @ counter_padding ) ) ) ,
154
- code: if_value ( struct . expr , code_multiline ) ,
155
- code: unless_value ( struct . expr , fn -> get_code ( test , stack ) || @ no_value end ) ,
156
- arguments: if_value ( struct . args , & format_args ( & 1 , width ) )
157
- ]
158
- |> Kernel . ++ ( format_context ( struct , formatter , padding_size , width ) )
159
- |> format_meta ( formatter , counter_padding , label_padding_size )
160
- |> IO . iodata_to_binary ( )
152
+ formatted =
153
+ [
154
+ note: if_value ( struct . message , & format_message ( & 1 , formatter ) ) ,
155
+ doctest: if_value ( struct . doctest , & pad_multiline ( & 1 , 2 + byte_size ( @ counter_padding ) ) ) ,
156
+ code: if_value ( struct . expr , code_multiline ) ,
157
+ code: unless_value ( struct . expr , fn -> get_code ( test , stack ) || @ no_value end ) ,
158
+ arguments: if_value ( struct . args , & format_args ( & 1 , width ) )
159
+ ]
160
+ |> Kernel . ++ ( format_context ( struct , formatter , padding_size , width ) )
161
+ |> format_meta ( formatter , pad , label_padding_size )
162
+ |> IO . iodata_to_binary ( )
163
+
164
+ { formatted , stack }
165
+ end
166
+
167
+ defp format_exception ( test , % FunctionClauseError { } = struct , stack , _width , formatter , _pad ) do
168
+ { blamed , stack } = Exception . blame ( :error , struct , stack )
169
+ banner = Exception . format_banner ( :error , struct )
170
+ blamed = FunctionClauseError . blame ( blamed , & inspect / 1 , & blame_match ( & 1 , & 2 , formatter ) )
171
+ message = error_info ( banner , formatter ) <> "\n " <> pad ( String . trim_leading ( blamed , "\n " ) )
172
+ { message <> format_code ( test , stack , formatter ) , stack }
161
173
end
162
174
163
175
@ doc false
@@ -179,30 +191,48 @@ defmodule ExUnit.Formatter do
179
191
end )
180
192
end
181
193
182
- defp format_kind_reason (
183
- test ,
184
- :error ,
185
- % ExUnit.AssertionError { } = struct ,
186
- stack ,
187
- width ,
188
- formatter
189
- ) do
190
- { format_assertion_error ( test , struct , stack , width , formatter , @ counter_padding ) , stack }
194
+ defp format_kind_reason ( test , :error , % mod { } = struct , stack , width , formatter )
195
+ when mod in @ formatter_exceptions do
196
+ format_exception ( test , struct , stack , width , formatter , @ counter_padding )
191
197
end
192
198
193
- defp format_kind_reason ( test , :error , % FunctionClauseError { } = struct , stack , _width , formatter ) do
194
- { blamed , stack } = Exception . blame ( :error , struct , stack )
195
- banner = Exception . format_banner ( :error , struct )
196
- blamed = FunctionClauseError . blame ( blamed , & inspect / 1 , & blame_match ( & 1 , & 2 , formatter ) )
197
- message = error_info ( banner , formatter ) <> "\n " <> pad ( String . trim_leading ( blamed , "\n " ) )
198
- { message <> format_code ( test , stack , formatter ) , stack }
199
+ defp format_kind_reason ( test , kind , reason , stack , width , formatter ) do
200
+ case linked_or_trapped_exit ( kind , reason ) do
201
+ { header , wrapped_reason , wrapped_stack } ->
202
+ struct = Exception . normalize ( :error , wrapped_reason , wrapped_stack )
203
+
204
+ { formatted_reason , _ } =
205
+ format_exception ( test , struct , wrapped_stack , width , formatter , @ counter_padding )
206
+
207
+ formatted_stack = format_stacktrace ( wrapped_stack , test . module , test . name , formatter )
208
+ { error_info ( header , formatter ) <> pad ( formatted_reason <> formatted_stack ) , stack }
209
+
210
+ :error ->
211
+ { reason , stack } = Exception . blame ( kind , reason , stack )
212
+ message = error_info ( Exception . format_banner ( kind , reason ) , formatter )
213
+ { message <> format_code ( test , stack , formatter ) , stack }
214
+ end
199
215
end
200
216
201
- defp format_kind_reason ( test , kind , reason , stack , _width , formatter ) do
202
- message = error_info ( Exception . format_banner ( kind , reason ) , formatter )
203
- { message <> format_code ( test , stack , formatter ) , stack }
217
+ defp linked_or_trapped_exit ( { :EXIT , pid } , { reason , [ _ | _ ] = stack } )
218
+ when :erlang . map_get ( :__struct__ , reason ) in @ formatter_exceptions
219
+ when reason == :function_clause do
220
+ { "** (EXIT from #{ inspect ( pid ) } ) an exception was raised:\n " , reason , stack }
204
221
end
205
222
223
+ defp linked_or_trapped_exit ( :exit , { { reason , [ _ | _ ] = stack } , { mod , fun , args } } )
224
+ when is_atom ( mod ) and is_atom ( fun ) and is_list ( args ) and
225
+ :erlang . map_get ( :__struct__ , reason ) in @ formatter_exceptions
226
+ when is_atom ( mod ) and is_atom ( fun ) and is_list ( args ) and reason == :function_clause do
227
+ {
228
+ "** (exit) exited in: #{ Exception . format_mfa ( mod , fun , args ) } \n ** (EXIT) an exception was raised:" ,
229
+ reason ,
230
+ stack
231
+ }
232
+ end
233
+
234
+ defp linked_or_trapped_exit ( _kind , _reason ) , do: :error
235
+
206
236
defp format_code ( test , stack , formatter ) do
207
237
if snippet = get_code ( test , stack ) do
208
238
" " <> formatter . ( :extra_info , "code: " ) <> snippet <> "\n "
0 commit comments