PageRenderTime 185ms CodeModel.GetById 80ms app.highlight 11ms RepoModel.GetById 60ms app.codeStats 0ms

/src/mochiweb_cover.erl

http://github.com/basho/mochiweb
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.