/src/mochiweb_cover.erl
Erlang | 93 lines | 56 code | 12 blank | 25 comment | 2 complexity | b644d567d0890c60f4ad4d8c4a2cc53a MD5 | raw file
1%% @author Bob Ippolito <bob@mochimedia.com> 2%% @copyright 2010 Mochi Media, Inc. 3%% 4%% Permission is hereby granted, free of charge, to any person obtaining a 5%% copy of this software and associated documentation files (the "Software"), 6%% to deal in the Software without restriction, including without limitation 7%% the rights to use, copy, modify, merge, publish, distribute, sublicense, 8%% and/or sell copies of the Software, and to permit persons to whom the 9%% Software is furnished to do so, subject to the following conditions: 10%% 11%% The above copyright notice and this permission notice shall be included in 12%% all copies or substantial portions of the Software. 13%% 14%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17%% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19%% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20%% DEALINGS IN THE SOFTWARE. 21 22%% @doc Workarounds for various cover deficiencies. 23-module(mochiweb_cover). 24-export([get_beam/1, get_abstract_code/1, 25 get_clauses/2, clause_lookup_table/1]). 26-export([clause_lookup_table/2]). 27 28%% Internal 29 30get_beam(Module) -> 31 {Module, Beam, _Path} = code:get_object_code(Module), 32 Beam. 33 34get_abstract_code(Beam) -> 35 {ok, {_Module, 36 [{abstract_code, 37 {raw_abstract_v1, L}}]}} = beam_lib:chunks(Beam, [abstract_code]), 38 L. 39 40get_clauses(Function, Code) -> 41 [L] = [Clauses || {function, _, FName, _, Clauses} 42 <- Code, FName =:= Function], 43 L. 44 45clause_lookup_table(Module, Function) -> 46 clause_lookup_table( 47 get_clauses(Function, 48 get_abstract_code(get_beam(Module)))). 49 50clause_lookup_table(Clauses) -> 51 lists:foldr(fun clause_fold/2, [], Clauses). 52 53clause_fold({clause, _, 54 [InTerm], 55 _Guards=[], 56 [OutTerm]}, 57 Acc) -> 58 try [{erl_parse:normalise(InTerm), erl_parse:normalise(OutTerm)} | Acc] 59 catch error:_ -> Acc 60 end; 61clause_fold(_, Acc) -> 62 Acc. 63 64%% 65%% Tests 66%% 67-ifdef(TEST). 68-include_lib("eunit/include/eunit.hrl"). 69foo_table(a) -> b; 70foo_table("a") -> <<"b">>; 71foo_table(123) -> {4, 3, 2}; 72foo_table([list]) -> []; 73foo_table([list1, list2]) -> [list1, list2, list3]; 74foo_table(ignored) -> some, code, ignored; 75foo_table(Var) -> Var. 76 77foo_table_test() -> 78 T = clause_lookup_table(?MODULE, foo_table), 79 [?assertEqual(V, foo_table(K)) || {K, V} <- T]. 80 81clause_lookup_table_test() -> 82 ?assertEqual(b, foo_table(a)), 83 ?assertEqual(ignored, foo_table(ignored)), 84 ?assertEqual('Var', foo_table('Var')), 85 ?assertEqual( 86 [{a, b}, 87 {"a", <<"b">>}, 88 {123, {4, 3, 2}}, 89 {[list], []}, 90 {[list1, list2], [list1, list2, list3]}], 91 clause_lookup_table(?MODULE, foo_table)). 92 93-endif.