diff options
author | Micah Anderson <micah@leap.se> | 2014-01-15 18:13:16 +0000 |
---|---|---|
committer | drebs <drebs@leap.se> | 2014-01-17 08:48:11 -0200 |
commit | 510c6d763fba74f95ae8f894408c3658bcef4f83 (patch) | |
tree | d4dd0930b902cb1e5d46bea621ec83f801ea8ed6 /deps/meck/src/meck_cover.erl | |
parent | 8bd863936ead4243f58fb99e11d1221e1af0a71e (diff) |
embed dependencies that were previously pulled in by git during rebar build
Diffstat (limited to 'deps/meck/src/meck_cover.erl')
-rw-r--r-- | deps/meck/src/meck_cover.erl | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/deps/meck/src/meck_cover.erl b/deps/meck/src/meck_cover.erl new file mode 100644 index 00000000..da8888c8 --- /dev/null +++ b/deps/meck/src/meck_cover.erl @@ -0,0 +1,110 @@ +%%============================================================================== +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%============================================================================== + +%% @doc Module containing functions needed by meck to integrate with cover. + +-module(meck_cover). + +%% Interface exports +-export([compile_beam/2]). +-export([rename_module/2]). + +%%============================================================================== +%% Interface exports +%%============================================================================== + +%% @doc Enabled cover on `<name>_meck_original'. +compile_beam(OriginalMod, Bin) -> + alter_cover(), + {ok, _} = cover:compile_beam(OriginalMod, Bin). + +%% @doc Given a cover file `File' exported by `cover:export' overwrite +%% the module name with `Name'. +rename_module(File, Name) -> + NewTerms = change_cover_mod_name(read_cover_file(File), Name), + write_terms(File, NewTerms), + ok. + +%%============================================================================== +%% Internal functions +%%============================================================================== + +%% @private +%% +%% @doc Alter the cover BEAM module to export some of it's private +%% functions. This is done for two reasons: +%% +%% 1. Meck needs to alter the export analysis data on disk and +%% therefore needs to understand this format. This is why `get_term' +%% and `write' are exposed. +%% +%% 2. In order to avoid creating temporary files meck needs direct +%% access to `compile_beam/2' which allows passing a binary. +alter_cover() -> + case lists:member({compile_beam,2}, cover:module_info(exports)) of + true -> + ok; + false -> + Beam = meck_mod:beam_file(cover), + AbsCode = meck_mod:abstract_code(Beam), + Exports = [{compile_beam, 2}, {get_term, 1}, {write, 2}], + AbsCode2 = meck_mod:add_exports(Exports, AbsCode), + _Bin = meck_mod:compile_and_load_forms(AbsCode2), + ok + end. + +change_cover_mod_name(CoverTerms, Name) -> + {_, Terms} = lists:foldl(fun change_name_in_term/2, {Name,[]}, CoverTerms), + Terms. + +change_name_in_term({file, Mod, File}, {Name, Terms}) -> + Term2 = {file, Name, replace_string(File, Mod, Name)}, + {Name, [Term2|Terms]}; +change_name_in_term({Bump={bump,_,_,_,_,_},_}=Term, {Name, Terms}) -> + Bump2 = setelement(2, Bump, Name), + Term2 = setelement(1, Term, Bump2), + {Name, [Term2|Terms]}; +change_name_in_term({_Mod,Clauses}, {Name, Terms}) -> + Clauses2 = lists:foldl(fun change_name_in_clause/2, {Name, []}, Clauses), + Term2 = {Name, Clauses2}, + {Name, [Term2|Terms]}. + +change_name_in_clause(Clause, {Name, NewClauses}) -> + {Name, [setelement(1, Clause, Name)|NewClauses]}. + +replace_string(File, Old, New) -> + Old2 = atom_to_list(Old), + New2 = atom_to_list(New), + re:replace(File, Old2, New2, [{return, list}]). + +read_cover_file(File) -> + {ok, Fd} = file:open(File, [read, binary, raw]), + Terms = get_terms(Fd, []), + ok = file:close(Fd), + Terms. + +get_terms(Fd, Terms) -> + case cover:get_term(Fd) of + eof -> Terms; + Term -> get_terms(Fd, [Term|Terms]) + end. + +write_terms(File, Terms) -> + {ok, Fd} = file:open(File, [write, binary, raw]), + lists:foreach(write_term(Fd), Terms), + ok. + +write_term(Fd) -> + fun(Term) -> cover:write(Term, Fd) end. + |