diff --git a/case-studies/meViolation/trace/trace_result.log b/case-studies/meViolation/trace/trace_result.log index 282ff4d..0955e34 100644 --- a/case-studies/meViolation/trace/trace_result.log +++ b/case-studies/meViolation/trace/trace_result.log @@ -3,5 +3,5 @@ {exec,10016000}. {node,nonode@nohost}. {pid,209}. -{return,{value,<0.216.0>}}. +{return,{value,216}}. {tracing,timeout}. \ No newline at end of file diff --git a/src/cauder_trace.erl b/src/cauder_trace.erl index 379f6d0..7170d32 100644 --- a/src/cauder_trace.erl +++ b/src/cauder_trace.erl @@ -6,8 +6,11 @@ push/3, pop/3, get/2, - peek/2, - reverse_actions/1, + peek/2 +]). +-export([ + reverse/1, + map_pids/1, to_log/1 ]). @@ -86,12 +89,36 @@ peek(Pid, Trace) -> error end. --spec reverse_actions(Trace) -> NewTrace when +%%%============================================================================= + +-spec reverse(Trace) -> NewTrace when Trace :: cauder_trace:trace(), NewTrace :: cauder_trace:trace(). -reverse_actions(Trace) -> - maps:map(fun(_, Actions) -> lists:reverse(Actions) end, Trace). +reverse(Trace) -> + maps:map(fun(_, Actions) -> lists:reverse(map_pids(Actions)) end, Trace). + +-spec map_pids(term()) -> term(). + +map_pids(List) when is_list(List) -> + lists:map(fun map_pids/1, List); +map_pids(Tuple) when is_tuple(Tuple) -> + list_to_tuple(lists:map(fun map_pids/1, tuple_to_list(Tuple))); +map_pids(Map) when is_map(Map) -> + maps:fold( + fun(K, V, Acc) -> + K1 = map_pids(K), + V1 = map_pids(V), + false = maps:is_key(K1, Acc), + Acc#{K1 => V1} + end, + #{}, + Map + ); +map_pids(Pid) when is_pid(Pid) -> + cauder_process:from_pid(Pid); +map_pids(Term) -> + Term. -spec to_log(Trace) -> Log when Trace :: cauder_trace:trace(), diff --git a/src/cauder_tracer.erl b/src/cauder_tracer.erl index 0a59943..063f6bf 100644 --- a/src/cauder_tracer.erl +++ b/src/cauder_tracer.erl @@ -142,10 +142,10 @@ init({MainPid, TracedPid}) -> NewState :: state(). handle_call(get_traces, _From, #state{trace = Trace0} = State) -> - Trace1 = cauder_trace:reverse_actions(Trace0), + Trace1 = cauder_trace:reverse(Trace0), {reply, {ok, Trace1}, State}; handle_call(get_return_value, _From, #state{return = ReturnValue} = State) -> - {reply, ReturnValue, State}; + {reply, cauder_trace:map_pids(ReturnValue), State}; %% ========== 'call' trace messages ========== %% %% Generate message stamp handle_call({trace, Pid, call, {cauder_tracer_erlang, send_centralized, [_, _]}}, _From, State) -> @@ -454,13 +454,13 @@ get_uid(Stamp, #state{ets = Table, stamps = Map} = State) -> -spec write_trace(Dir, TraceInfo) -> ok when Dir :: file:filename(), - TraceInfo :: cauder_tracer:trace_info(). + TraceInfo :: cauder_types:trace_info(). -write_trace(Dir, TraceResult) -> +write_trace(Dir, TraceInfo) -> % This not compile time safe but there is no other way to keep it human-friendly and simple - [trace_info | Values] = tuple_to_list(TraceResult), Fields = record_info(fields, trace_info), - {Traces, ResultInfo} = maps:take(trace, maps:from_list(lists:zip(Fields, Values))), + [trace_info | Values] = tuple_to_list(TraceInfo), + {Trace, ResultInfo} = maps:take(trace, maps:from_list(lists:zip(Fields, Values))), ok = filelib:ensure_dir(Dir), case filelib:is_dir(Dir) of @@ -468,15 +468,23 @@ write_trace(Dir, TraceResult) -> false -> ok = file:make_dir(Dir) end, - ResultFile = filename:join(Dir, "trace_result.log"), - ResultContent = lists:join($\n, lists:map(fun(T) -> io_lib:format("~p.", [T]) end, maps:to_list(ResultInfo))), - ok = file:write_file(ResultFile, ResultContent), + ResultFilename = filename:join(Dir, "trace_result.log"), + write_terms(ResultFilename, maps:to_list(ResultInfo)), maps:foreach( fun(Pid, Actions) -> - File = filename:join(Dir, io_lib:format("trace_~b.log", [Pid])), - Content = lists:join($\n, lists:map(fun(T) -> io_lib:format("~p.", [T]) end, Actions)), - ok = file:write_file(File, Content) + Filename = filename:join(Dir, io_lib:format("trace_~b.log", [Pid])), + write_terms(Filename, Actions) end, - Traces + Trace ). + +-spec write_terms(Filename, Terms) -> ok when + Filename :: file:name_all(), + Terms :: [term()]. + +write_terms(Filename, Terms) -> + Lines = lists:map(fun(Term) -> io_lib:format("~w.", [Term]) end, Terms), + Joined = lists:join($\n, Lines), + Text = unicode:characters_to_binary(Joined), + file:write_file(Filename, Text).