Merge pull request #13 from basho/adt-fix-term-printing

Fix term printing in errors to properly show embedded lists
diff --git a/src/error_logger_lager_h.erl b/src/error_logger_lager_h.erl
index 5983bdb..30fa1bb 100644
--- a/src/error_logger_lager_h.erl
+++ b/src/error_logger_lager_h.erl
@@ -109,8 +109,8 @@
             Details = lists:sort(D),
             case Details of
                 [{application, App}, {exited, Reason}, {type, _Type}] ->
-                    ?LOG(info, Pid, "Application ~w exited with reason: ~w",
-                        [App, Reason]);
+                    ?LOG(info, Pid, "Application ~w exited with reason: ~s",
+                        [App, format_reason(Reason)]);
                 _ ->
                     ?LOG(info, Pid, print_silly_list(D))
             end;
@@ -171,19 +171,21 @@
 format_reason({undef, [MFA|_]}) ->
     ["call to undefined function ", format_mfa(MFA)];
 format_reason({bad_return_value, Val}) ->
-    io_lib:format("bad return value: ~w", [Val]);
+    ["bad return value: ", print_val(Val)];
+format_reason({{bad_return_value, Val}, MFA}) ->
+    ["bad return value: ", print_val(Val), " in ", format_mfa(MFA)];
 format_reason({{case_clause, Val}, [MFA|_]}) ->
-    [io_lib:format("no case clause matching ~w in ", [Val]), format_mfa(MFA)];
+    ["no case clause matching ", print_val(Val), " in ", format_mfa(MFA)];
 format_reason({function_clause, [MFA|_]}) ->
     ["no function clause matching ", format_mfa(MFA)];
 format_reason({if_clause, [MFA|_]}) ->
     ["no true branch found while evaluating if expression in ", format_mfa(MFA)];
 format_reason({{try_clause, Val}, [MFA|_]}) ->
-    [io_lib:format("no try clause matching ~w in ", [Val]), format_mfa(MFA)]; 
+    ["no try clause matching ", print_val(Val), " in ", format_mfa(MFA)]; 
 format_reason({badarith, [MFA|_]}) ->
     ["bad arithmetic expression in ", format_mfa(MFA)];
 format_reason({{badmatch, Val}, [MFA|_]}) ->
-    [io_lib:format("no match of right hand value ~w in ", [Val]), format_mfa(MFA)];
+    ["no match of right hand value ", print_val(Val), " in ", format_mfa(MFA)];
 format_reason({emfile, _Trace}) ->
     "maximum number of file descriptors exhausted, check ulimit -n";
 format_reason({system_limit, [{M, F, _}|_] = Trace}) ->
@@ -218,29 +220,24 @@
 format_reason({noproc, MFA}) ->
     ["no such process or port in call to ", format_mfa(MFA)];
 format_reason({{badfun, Term}, [MFA|_]}) ->
-    [io_lib:format("bad function ~w in ", [Term]), format_mfa(MFA)];
+    ["bad function ", print_val(Term), " in ", format_mfa(MFA)];
 format_reason(Reason) ->
     {Str, _} = lager_trunc_io:print(Reason, 500),
     Str.
 
 format_mfa({M, F, A}) when is_list(A) ->
-    io_lib:format("~w:~w("++format_args(A, [])++")", [M, F | A]);
+    {FmtStr, Args} = format_args(A, [], []),
+    io_lib:format("~w:~w("++FmtStr++")", [M, F | Args]);
 format_mfa({M, F, A}) when is_integer(A) ->
     io_lib:format("~w:~w/~w", [M, F, A]);
 format_mfa(Other) ->
     io_lib:format("~w", [Other]).
 
-format_args([], Acc) ->
-    string:join(lists:reverse(Acc), ", ");
-format_args([H|T], Acc) when is_list(H) ->
-    case lager_stdlib:string_p(H) of
-        true ->
-            format_args(T, ["\"~s\""|Acc]);
-        _ ->
-            format_args(T, ["~w"|Acc])
-    end;
-format_args([_|T], Acc) ->
-    format_args(T, ["~w"|Acc]).
+format_args([], FmtAcc, ArgsAcc) ->
+    {string:join(lists:reverse(FmtAcc), ", "), lists:reverse(ArgsAcc)};
+format_args([H|T], FmtAcc, ArgsAcc) ->
+    {Str, _} = lager_trunc_io:print(H, 100),
+    format_args(T, ["~s"|FmtAcc], [Str|ArgsAcc]).
 
 print_silly_list(L) when is_list(L) ->
     case lager_stdlib:string_p(L) of
@@ -260,3 +257,7 @@
     print_silly_list(T, ["~w: ~w" | Fmt], [V, K | Acc]);
 print_silly_list([H|T], Fmt, Acc) ->
     print_silly_list(T, ["~w" | Fmt], [H | Acc]).
+
+print_val(Val) ->
+    {Str, _} = lager_trunc_io:print(Val, 500),
+    Str.
diff --git a/test/crash.erl b/test/crash.erl
index ab66612..7037379 100644
--- a/test/crash.erl
+++ b/test/crash.erl
@@ -22,11 +22,19 @@
 	{reply, M(), State};
 handle_call(bad_return, _, _) ->
 	bleh;
+handle_call(bad_return_string, _, _) ->
+	{tuple, {tuple, "string"}};
 handle_call(case_clause, _, State) ->
-		case State of
-			goober ->
-				{reply, ok, State}
-		end;
+	case State of
+		goober ->
+			{reply, ok, State}
+	end;
+handle_call(case_clause_string, _, State) ->
+	Foo = atom_to_list(?MODULE),
+	case Foo of
+		State ->
+			{reply, ok, State}
+	end;
 handle_call(if_clause, _, State) ->
 	if State == 1 ->
 			{reply, ok, State}
@@ -56,12 +64,12 @@
 	Res = list_to_atom(lists:flatten(lists:duplicate(256, "a"))),
 	{reply, Res, State};
 handle_call(process_limit, _, State) ->
-    %% run with +P 300 to make this crash
-    [erlang:spawn(fun() -> timer:sleep(5000) end) || _ <- lists:seq(0, 500)],
-    {reply, ok, State};
+	%% run with +P 300 to make this crash
+	[erlang:spawn(fun() -> timer:sleep(5000) end) || _ <- lists:seq(0, 500)],
+	{reply, ok, State};
 handle_call(port_limit, _, State) ->
-    [erlang:open_port({spawn, "ls"}, []) || _ <- lists:seq(0, 1024)],
-    {reply, ok, State};
+	[erlang:open_port({spawn, "ls"}, []) || _ <- lists:seq(0, 1024)],
+	{reply, ok, State};
 handle_call(noproc, _, State) ->
 	Res = gen_event:call(foo, bar, baz),
 	{reply, Res, State};
diff --git a/test/lager_test_backend.erl b/test/lager_test_backend.erl
index 01c1ec1..c216d44 100644
--- a/test/lager_test_backend.erl
+++ b/test/lager_test_backend.erl
@@ -237,6 +237,15 @@
                         ?assertEqual(Expected, lists:flatten(Msg))
                 end
             },
+            {"bad return value with string",
+                fun() ->
+                        Pid = whereis(crash),
+                        crash(bad_return_string),
+                        {_, _, Msg} = pop(),
+                        Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad return value: {tuple,{tuple,\"string\"}}", [Pid])),
+                        ?assertEqual(Expected, lists:flatten(Msg))
+                end
+            },
             {"case clause",
                 fun() ->
                         Pid = whereis(crash),
@@ -246,6 +255,15 @@
                         ?assertEqual(Expected, lists:flatten(Msg))
                 end
             },
+            {"case clause string",
+                fun() ->
+                        Pid = whereis(crash),
+                        crash(case_clause_string),
+                        {_, _, Msg} = pop(),
+                        Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no case clause matching \"crash\" in crash:handle_call/3", [Pid])),
+                        ?assertEqual(Expected, lists:flatten(Msg))
+                end
+            },
             {"function clause",
                 fun() ->
                         Pid = whereis(crash),
@@ -323,7 +341,7 @@
                         Pid = whereis(crash),
                         crash(badarg2),
                         {_, _, Msg} = pop(),
-                        Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad argument in call to erlang:iolist_to_binary([[102,111,111],bar]) in crash:handle_call/3", [Pid])),
+                        Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad argument in call to erlang:iolist_to_binary([\"foo\",bar]) in crash:handle_call/3", [Pid])),
                         ?assertEqual(Expected, lists:flatten(Msg))
                 end
             },