Reputation: 5251
Disclaimer: The author of this question has mostly theoretical knowledge of Erlang/OTP.
I have a small OTP application which calls some non-Erlang executable inside the myapp/ebin
directory via open_port()
. When I run the application itself everything goes well and the port to the executable is successfully opened.
But when I try to run unit tests for the application, the ones that depend on the open_port()
fail, because when started with EUnit
the application tries to find the executable under myapp/.eunit/ebin
.
How can I change that behaviour without changing the code of the application itself? How can I run EUnit tests with the same current directory as when running the application itself? (I mean it would not be a good idea to change the code which provides the path to the executable just to be able to run EUnit).
Edit: I followed the advice in the Erlang mailing list, but code:priv_dir(myapp_name)
returns {error, bad_name}
.
Edit: I can see that .eunit/
contains modulename.beam
files and ebin/
contains both modulename.beam
files and modulename_tests.beam
files. Now I am completely lost. When I run make test
, rebar
runs eunit
command, which calls each modulename_tests.beam
file in the ebin/
directory which calls a corresponding modulename.beam
file in the .eunit/
directory (filename:absname("")
clearly shows that modulename.beam
files are executed from .eunit/
during test). Why is it so? Why do we need to run modulename.beam
files from the .eunit/
directory instead of ebin/
?
Why do we actually need to have the very same .beam files in myapp/ebin
and myapp/.eunit/ebin
?
P.S. I have read the official documentation and did not find the solution.
Upvotes: 2
Views: 654
Reputation: 4077
To use erlang
start script ".erlang" , and it can solve your problem.
In the .erlang file, to use code:add_pathz/N
to add your necessary path.
Before reading couchdb
source code there is example of how to use priv
directory. Maybe the solution is helpful to you. It wrap open_port
with start_port
function, and set the directory in start_port
function.
In file couch_os_daemon.erl
start_port(Command) ->
PrivDir = couch_util:priv_dir(),
Spawnkiller = filename:join(PrivDir, "couchspawnkillable"),
Port = open_port({spawn, Spawnkiller ++ " " ++ Command}, ?PORT_OPTIONS),
{ok, Port}.
stop_port(#daemon{port=Port, kill=undefined}=D) ->
?LOG_ERROR("Stopping daemon without a kill command: ~p", [D#daemon.name]),
catch port_close(Port);
stop_port(#daemon{port=Port}=D) ->
?LOG_DEBUG("Stopping daemon: ~p", [D#daemon.name]),
os:cmd(D#daemon.kill),
catch port_close(Port).
In file couch_util.erl
priv_dir() ->
case code:priv_dir(couch) of
{error, bad_name} ->
% small hack, in dev mode "app" is couchdb. Fixing requires
% renaming src/couch to src/couch. Not really worth the hassle.
% -Damien
code:priv_dir(couchdb);
Dir -> Dir
end.
start_driver(LibDir) ->
case erl_ddll:load_driver(LibDir, "couch_icu_driver") of
ok ->
ok;
{error, already_loaded} ->
ok = erl_ddll:reload_driver(LibDir, "couch_icu_driver");
{error, Error} ->
exit(erl_ddll:format_error(Error))
end.
You can grep priv
, many example can be found.
Upvotes: 1
Reputation: 10557
EUnit does not do this by itself - the .eunit directory is a convention used by Rebar.
Upvotes: 5