EUnit – Spawn on Node – Missing Name Problem


This post is actually a prequel without the first one being posted yet (it’s in draft mode), anyway, if you try doing a spawn with node control, things seem to get a bit out of hand

Erlang R13B04 (erts-5.7.5) [source] [64-bit] [smp:4:4] [rq:4]
[async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.5  (abort with ^G)
(t@zen)1>
=ERROR REPORT==== 1-Sep-2010::09:06:20 ===
Error in process <0.56.0> on node 't@zen' with exit value: 
{badarg,[{erlang,atom_to_list,[[]]},
        {eunit_lib,fun_parent,1},
        {eunit_data,parse_function,1},
        {eunit_data,next,1},
        {eunit_data,iter_next,1},
        {eunit_proc,get_next_item,1},
        {eunit_proc,tests_inorder,3},{eunit_proc,with_timeout...

So, what is the cause for this error?

According to the error message, there is a bad usage with the erlang BIF atom_to_list, from the module eunit_lib, in the function fun_parent

{eunit_lib,fun_parent,1}

Now, if you go and read the source (eunit_lib),

%% This library is free software; you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as
%% published by the Free Software Foundation; either version 2 of the
%% License, or (at your option) any later version.
%%
%% This library is distributed in the hope that it will be useful, but
%% WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%% Lesser General Public License for more details.
%%
%% You should have received a copy of the GNU Lesser General Public
%% License along with this library; if not, write to the Free Software
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
%% $Id: eunit_lib.erl 339 2009-04-05 14:10:47Z rcarlsson $
%%
%% @copyright 2004-2007 Mickaël Rémond, Richard Carlsson
%% @author Mickaël Rémond <mickael.remond@process-one.net>
%%   [http://www.process-one.net/]
%% @author Richard Carlsson <richardc@it.uu.se>
%%   [http://user.it.uu.se/~richardc/]
%% @private
%% @see eunit
%% @doc Utility functions for eunit
%% ---------------------------------------------------------------------
%% Get the name of the containing function for a fun. (This is encoded
%% in the name of the generated function that implements the fun.)
fun_parent(F) ->
    {module, M} = erlang:fun_info(F, module),
    {name, N} = erlang:fun_info(F, name),
    case erlang:fun_info(F, type) of
        {type, external} ->
            {arity, A} = erlang:fun_info(F, arity),
            {M, N, A};
        {type, local} ->
            [$-|S] = atom_to_list(N),
            C1 = string:chr(S, $/),
            C2 = string:chr(S, $-),
            {M, list_to_atom(string:sub_string(S, 1, C1 - 1)),
             list_to_integer(string:sub_string(S, C1 + 1, C2 - 1))}
    end.

Where the second line fun_info(F, name) is the culprit. It seems as if the fun does not retain the name for some reason, but fortunately, after discussing this with my senior friend Nicolas, it turns out this is a problem caused by the module from where the fun is sent code not being loaded on the other node where the tests are to be evaluated.

Thus, the simple solution is to make sure the remote node has loaded the code from the tests a priori. This can be achieved with a module_info() or code:load_file/1.

Leave a comment

3 Comments

  1. Pedro

     /  January 9, 2012

    I found your posts really useful and easy to understand, thanks for them!

    I have a question about this problem, though: How can I start testing in different nodes without having to manually start them and load the code? Or better yet, how do I use the {node, NodeName, Tests} fixture?

    Thanks!

    Reply
  1. Erlang EUnit – continuation 3 – Test Control | Practical Eunit Examples and TDD.

Leave a reply to gianfrancoalongi Cancel reply