Question

I have some issue with distributed tests under rebar. Rebar starts node with name nonode@nohost. After it I call help function make_distrib which provide normal node name and starts distribution work.
After starting the slave node I couldn't sent to it any lambda. I had error:

    =ERROR REPORT==== 27-Jul-2013::22:48:02 ===
    Error in process  on node 'test1@just' with exit value: {{badfun,#Fun<msg_proxy_tests.2.117197241>},[{error_handler,undefined_lambda,3,[{file,"error_handler.erl"},{line,64}]}]}

But! If I run it test with simple way - all works good:

    $erl
    1> c(msg_proxy_tests).
    {ok,msg_proxy_tests}
    2> eunit:test({module, msg_proxy_tests},[verbose]).
    ======================== EUnit ========================
    module 'msg_proxy_tests'msg_proxy_tests: distrib_mode_test_ (distribute mode test for nodes)...
    msg_proxy_tests.erl:14:<0.48.0>: nodes ( ) = [test1@just]
    msg_proxy_tests.erl:15:<9999.39.0>: node ( ) = test1@just
    msg_proxy_tests.erl:17:<0.48.0>: nodes ( ) = [test1@just]
    [0.238 s] ok

How can I fix this?


Module source:

    -module(msg_proxy_tests).

    -include_lib("eunit/include/eunit.hrl").

    distrib_mode_test_()->
    {"distribute mode test for nodes", timeout, 60, 
        fun() ->
            {ok, Host} = inet:gethostname(),
            make_distrib("tests@"++Host, shortnames),
            slave:start(Host, test1),
            ?debugVal(nodes()),
            spawn(list_to_atom("test1@"++Host), fun()-> ?debugVal(node())  end),
            timer:sleep(100), 
            ?debugVal(nodes()),
            stop_distrib(),
            ok
        end}.

    -spec make_distrib( NodeName::string()|atom(), NodeType::shortnames | longnames) ->
        {ok, ActualNodeName::atom} | {error, Reason::term()}.
    make_distrib(NodeName, NodeType) when is_list(NodeName) ->
        make_distrib(erlang:list_to_atom(NodeName), NodeType);
    make_distrib(NodeName, NodeType) ->
        case node() of
            'nonode@nohost' -> 
                [] = os:cmd("epmd -daemon"),
                case net_kernel:start([NodeName, NodeType]) of 
                    {ok, _Pid} -> node() 
                end;
            CurrNode -> CurrNode
        end.

    stop_distrib()->
        net_kernel:stop().

Was it helpful?

Solution

That is because of module hash on both nodes is different. That happens because eunit compiles code before it run and module contains -ifdef(TEST) macroses, which will definitely change it's hash.

Thats why anonymous function #Fun<msg_proxy_tests.2.117197241 could not be called and error occurred. (look at function name and you will notice funny numbers, this is module hash, it will be different on both nodes).

If you want to avoid this, you should call funs by it fully qualified name: module:fun_name/arity.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top