@@ -54,6 +54,7 @@ defmodule ExUnit.Formatter do
5454
5555 @ counter_padding " "
5656 @ mailbox_label_padding @ counter_padding <> " "
57+ @ formatter_exceptions [ ExUnit.AssertionError , FunctionClauseError ]
5758 @ no_value ExUnit.AssertionError . no_value ( )
5859
5960 @ doc """
@@ -136,10 +137,10 @@ defmodule ExUnit.Formatter do
136137
137138 @ doc false
138139 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 )
140141 end
141142
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
143144 label_padding_size = if has_value? ( struct . right ) , do: 7 , else: 6
144145 padding_size = label_padding_size + byte_size ( @ counter_padding )
145146
@@ -148,16 +149,27 @@ defmodule ExUnit.Formatter do
148149 do: & pad_multiline ( & 1 , padding_size ) ,
149150 else: & code_multiline ( & 1 , padding_size )
150151
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 }
161173 end
162174
163175 @ doc false
@@ -179,30 +191,48 @@ defmodule ExUnit.Formatter do
179191 end )
180192 end
181193
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 )
191197 end
192198
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
199215 end
200216
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 }
204221 end
205222
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+
206236 defp format_code ( test , stack , formatter ) do
207237 if snippet = get_code ( test , stack ) do
208238 " " <> formatter . ( :extra_info , "code: " ) <> snippet <> "\n "
0 commit comments