coverモジュールとsmerlモジュールを併用するためのパッチ
Erlang。
デフォルトでは、coverモジュールとsmerlモジュールの併用が不可能(おそらく)なので、その問題を解消するためのパッチを作成。
- cover:
- コードカバレッジ計測用モジュール
- smerl:
使用したバージョンはErlangがR14B01、erlwebが0.7.1。
問題点
末尾のパッチが対象としている問題:
普通にErlangを使っている分には、あまり関係ないかもしれない。
今回は、Erlang製のO/Rマッパー(?)であるerlydbを使用しているソースに対してカバレッジ計測を行うという要件があり、erlydbが内部的にsmerlを利用していたために上記問題が発生した。
以下、修正の概要:
- coverモジュール:
- smerlモジュール:
この修正がベストかどうかは分からないけど、応急処置の一つとしてメモしておく。
パッチ
パッチ適用方法。
# cover.erl $ cd ${解凍ディレクトリ}/otp_src_R14B01/lib/tools/src/ $ patch cover.erl < cover.patch
# smerl.erl $ cd ${解凍ディレクトリ}/erlyweb-0.7.1/src/smerl/ $ patch smerl.erl < smerl.patch
cover.patch:
*** cover.erl 2010-12-17 01:41:28.972951213 +0900 --- cover.erl.patched 2010-12-17 01:03:41.042983354 +0900 *************** *** 65,70 **** --- 65,71 ---- modules/0, imported/0, imported_modules/0, which_nodes/0, is_compiled/1, reset/1, reset/0, stop/0, stop/1]). + -export([get_compiled_beam/1]). -export([remote_start/1]). %-export([bump/5]). -export([transform/4]). % for test purposes *************** *** 150,155 **** --- 151,163 ---- start(Nodes) -> call({start_nodes,remove_myself(Nodes,[])}). + %% get_compiled_beam(Module) -> Result + %% Module = atom() + %% Result = {ok,binary()} | {error, Reason} + %% Reason = term() + get_compiled_beam(Module) -> + call({get_compiled_beam, Module}). + %% compile(ModFile) -> %% compile(ModFile, Options) -> %% compile_module(ModFile) -> Result *************** *** 548,554 **** compiled = Compiled}, reply(From, {ok,StartedNodes}), main_process_loop(State1); ! {From, {compile, File, Options}} -> case do_compile(File, Options) of {ok, Module} -> --- 556,569 ---- compiled = Compiled}, reply(From, {ok,StartedNodes}), main_process_loop(State1); ! {From, {get_compiled_beam, Module}} -> ! case ets:lookup(?BINARY_TABLE,Module) of ! [{Module,Beam}] -> ! reply(From, {ok, Beam}); ! _ -> ! reply(From, {error, not_cover_compiled}) ! end, ! main_process_loop(State); {From, {compile, File, Options}} -> case do_compile(File, Options) of {ok, Module} -> *************** *** 1253,1259 **** %% Compile and load the result %% It's necessary to check the result of loading since it may %% fail, for example if Module resides in a sticky directory ! {ok, Module, Binary} = compile:forms(Forms, []), case code:load_binary(Module, ?TAG, Binary) of {module, Module} -> --- 1268,1274 ---- %% Compile and load the result %% It's necessary to check the result of loading since it may %% fail, for example if Module resides in a sticky directory ! {ok, Module, Binary} = compile:forms(Forms, [debug_info]), case code:load_binary(Module, ?TAG, Binary) of {module, Module} ->
smerl.patch:
*** smerl.erl 2010-12-17 01:42:04.302955178 +0900 --- smerl.erl.patched 2010-12-17 01:42:20.942951890 +0900 *************** *** 166,171 **** --- 166,179 ---- _Other -> {error, {invalid_module, ModuleName}} end; + cover_compiled -> + {ok, BeamBinary} = cover:get_compiled_beam(ModuleName), + case get_forms(ModuleName, BeamBinary) of + {ok, Forms} -> + mod_for_forms(Forms); + _Other -> + {error, {invalid_module, ModuleName}} + end; _Err -> {error, {invalid_module, ModuleName}} end *************** *** 594,603 **** end, case Res of ok -> code:purge(Module), ! case code:load_binary( ! Module, ! atom_to_list(Module) ++ ".erl", Bin) of {module, _Module} -> ok; Err -> --- 602,613 ---- end, case Res of ok -> + Tag = case code:which(Module) of + cover_compiled -> cover_compiled; + _ -> atom_to_list(Module) ++ ".erl" + end, code:purge(Module), ! case code:load_binary(Module, Tag, Bin) of {module, _Module} -> ok; Err ->