Thursday, August 2, 2012

Erlang: problems connecting to node

How did you start the nodes, did you use
erl -setcookie my_cookie

Sometimes it is common to write

erl -cookie my_cookie % wrong, use setcooke, not cookie

erl --setcookie my_cookie % wrong, use only 1 dash

erl -setcookie=my_cookie % wrong, do not use an equals sign

What does the shell think the cookie value is ?
Try
1> erlang:get_cookie().

Is the value returned the same as the value as you intended to use for the cookie ?  If not, check the common mistakes above.


net_adm:ping fails:
Did you specify the remote node name as an atom ?
e.g. try 'a@localhost' instead of a@localhost

Thursday, July 5, 2012

eunit truncates terms when outputting diff

Apparently this is not eunit's fault, but rather something to do with the shell. There is a workaround which is to output to file instead of the shell:

Use eunit with surefire:
eunit:test(my_module, [{report,{eunit_surefire,[{dir,"."}]}}]).

this will create a file called TEST-something.xml which will print out the full terms if a test fails

If you are running eunit via dialyzer like this:


$> rebar eunit

Then you can create the xml files by adding this line to your rebar.config:

{eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}.

This will make the tests more verbose (remove the verbose option if you do not want that).
It will also create the xml files in the same directory as the beam files created for the test which is called .eunit.

For example if you have the following structure for your app:
| my_app
|-- src
|-- ebin
| -- .eunt

Compiling Erlang modules for Unit Test

%% When compiling erlang modules for testing, some of the common options are
  debug_info
and
  export_all
e.g. from the shell:
compile:file(my_module, [debug_info, export_all]).

%% or you can use
c(my_module, [debug_info, export_all]).

%% If my_module is not in the current path, you can specify the full path as a string:
c("apps/my_app/src/my_module.erl", [export_all, {outdir, "apps/my_module/ebin"}, {d, 'TEST'}]).

%% OR
c("src/bid_processor", [export_all, {outdir, "ebin"}, {d, 'TEST'}]).

%% If you suspect that your module under test does not behave according to the most recent code changes you can check that the shell has not loaded some stray beam file from another directory:
code:which(my_module).
%% This will return the full path to the module

%% And if you really want to you can unload the module with
code:purge(my_module).
code:delete(my_module).

%% When running eunit test cases it often happens that the diff of 2 terms is truncated. e.g. when you compare 2 large tuples.  You can output the test log to a file and in the file the terms are not truncated.

You can use
code:get_path().
to get a list of paths used in the erlang shell, most likely you will have to wrap that method in the shell command rp, otherwise the shell will truncate the output e.g.
rp(code:get_path()).


It is very useful if you have a directory called e.g. apps and which contains a collection of erlang applications to set the ERL_LIBS environment variable e.g.
export ERL_LIBS=/home/philip/erlang/apps
When you start up the erlang shell, and do code:get_path(), you will see that for each application, erlang has automatically set a path to the ebin directory.

Tuesday, July 3, 2012

erlang registering and monitoring global processes

Please note, the shell command numbers may not be in order as I put this together in a hurry.

% start up an erlang node
 erl -sname a -setcookie qwerty




%% create a new process which echos back anything it receives
(a@philipclarkeirl-desktop)1> Pid = spawn(fun() -> receive {Sender, Msg} -> Sender ! Msg end end).
<0.40.0>



%% test it out
(a@philipclarkeirl-desktop)2> Pid ! {self(), "Hello"}.
{<0.38.0>,"Hello"}


%% globally register the process
 (a@philipclarkeirl-desktop)3> global:register_name(myprocess, Pid).
yes


%% check it is registered
(a@philipclarkeirl-desktop)4> global:registered_names().
[myprocess]



(a@philipclarkeirl-desktop)6> global:whereis_name(myprocess) =:= Pid.
true
 

%% send to myprocess a message
(a@philipclarkeirl-desktop)7> global:send(myprocess, {self(), "Hello from shell"}).
<0.40.0>


%% note the return value is the pid found for myprocess
 

%% check in the shell that we received a response
(a@philipclarkeirl-desktop)8> flush().
Shell got "Hello from shell"
ok



%% start up another node
erl -sname b -setcookie qwerty

%% check that the process is globally registered
(b@philipclarkeirl-desktop)3> global:registered_names().
[myprocess]


%% monitor the process started in node a
(b@philipclarkeirl-desktop)11> MRef = erlang:monitor(process, global:whereis_name(myprocess)).
#Ref<0.0.0.83>



%% in node a, kill the process
(a@philipclarkeirl-desktop)33> exit(Pid, kill).
true


%% in node b
(b@philipclarkeirl-desktop)12> flush().
Shell got {'DOWN',#Ref<0.0.0.83>,process,<5799.85.0>,killed}
ok



Saturday, June 30, 2012

Eunit terminology

Eunit Terminology

Based mostly on https://github.com/richcarl/eunit/blob/master/doc/overview.edoc

Simple Test

A function ending in _test and which takes no arguments
The test will always pass unless an exception is raised e.g. 1 =:= 2
You can use assert macros to cause the function to pass or fail
From the doc:
"A drawback of simple test functions is that you must write a separate
function (with a separate name) for each test case."
However you could write a _test() function which contains a list of assert statements ??
eunit:test(someModule) will export all simple tests.

Test

A fun expression that takes no arguments
e.g.
fun () -> ?assert(1 + 1 =:= 2) end.

Test Object

An assert which starts with an underscore 
"You can think of the initial underscore as signalling test object."
A simple test can be converted into a test object:
?_test(assert(BoolExpr)) % this is now a test object

Test Generator

A function ending in _test_
Returns a representation of a set of tests (that is a test set).
e.g.
basic_test_() ->
       fun () -> ?assert(1 + 1 =:= 2) end.
which is the same as
basic_test_() ->
       ?_assert(1 + 1 =:= 2).'''
Test generators cannot return simple tests ?
eunit:test(someModule) will export all test generators.

Simple Test Object (2nd definition)

A nullary functional value (i.e., a fun that takes zero arguments). 
e.g.
fun () -> ... end

Test Set

A list of test objects or a list of other test sets.

Instantiator

Used inside a fixture, takes some state and returns a test set
It behaves like a generator
Is defined by:
((R::any()) -> Tests)
It can be used in a setup fixture like this:
{setup, Setup, Cleanup, Tests | Instantiator}
or used in a foreach fixture like
{foreach, Setup, Cleanup, [Tests | Instantiator]}
 

Fixture

Sets up state for a test set and takes down the state at the end of the test set
By default a separate process is responsible for the setup and teardown and another process is used for the test. Therefore if the test causes a crash, the cleanup will always be done.
A setup fixture works differently to a foreach fixture.
A setup fixture sets up state, runs all test cases and then does a cleanup.
A foreach fixture will setup state for each test case and teardown after each test case.
e.g.
higher_order_test_() ->
    {"Higher Order Tests",
     [
      {"Setup Test",
       {setup,
fun () -> 4711 end,
fun (4711) -> ok end,
fun (X) ->
[{"1st", ?_assert(X =:= 4711)},
{"2nd", ?_assert(X =:= 4711)},
{"3rd", ?_assert(X =:= 4711)}]
end}
      },
      {"Foreach Test",
       {foreach,
fun () -> 4711 end,
fun (4711) -> ok end,
[fun (R) -> {"1st", ?_assert(R =:= 4711)} end,
fun (R) -> {"2nd", ?_assert(R =:= 4711)} end,
fun (R) -> {"3rd", ?_assert(R =:= 4711)} end]
       }
      }.

Tuesday, January 24, 2012

Fun with vim and IPython kernel

#First of all, get the development version of ipython

cd /home/philip/Packages
git clone https://github.com/ipython/ipython.git


# install this into your own virtualenv (I'm assuming at this point that you have created a virtualenv and that you have activated it).

pip install /home/philip/Packages/ipython

# do a 'which ipython' to check that it worked


# you will need development libraries for zeromq
sudo apt-get install libzmq-dev
pip install pyzmq

# check pyzmq was installed into the virtualenv

(py26)philip@desktop:~/git/project$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on desktop
Type "help", "copyright", "credits" or "license" for more information.
>>> import zmq
>>> zmq.__path__
['/home/philip/git/project/py26/lib/python2.6/site-packages/zmq']


# get the vim-ipython plugin
pip install git+https://github.com/ivanov/vim-ipython.git


# start up an IPython kernel.
 ipython kernel

# and you get output like:
(py26)philip@desktop:~/git/project$ ipython kernel
[IPKernelApp] To connect another client to this kernel, use:
[IPKernelApp] --existing kernel-32459.json


# startup vim and connect to the ipython kernel
gvim -c "IPython --existing kernel-32459.json"

or startup gvim and enter
:IPython --existing kernel-32459.json

In vim add this line:
3 + 4
Hit ctrl-s while still on this line and notice that a new window opens up with the result from the ipython kernel

now enter
a = 1

# from another shell
ipython qtconsole --existing kernel-32459.json

# to start up a qtconsole and connect it to the kernel
pip install pyside
ipython qtconsole --existing kernel-32459.json

do:
print a

And notice that the result of a is 1 because that is what we set a to from our vim session.


Dealing with Tuples in Erlang


Say in Python we have a function defined like this:
def foo(**kwargs):
    pass

In languages like Python, we can pass keyword arguments to a function like:
foo(a = 1, b = 2, c = 3, d = 1)



In Erlang the function may look like this:
foo(Args) -> ok.

A call to foo in Erlang would look like:
foo([{a, 1}, {b, 2}, {c, 3}, {d, 1}]).




In Python we could check if 'a' was passed in as a keyword argument with:
return 'a' in kwargs


Whereas in Erlang we need to do:
lists:keyfind('a', 1, Args)

Note that we are looking at the 1st element in our tuple (hence the 1 in the second argument and not a zero).

keyfind returns false if the key was not found, otherwise it returns the tuple




In Python, to find all keys with the value 1 we do:
[k for k, v in kwargs.items() if v == 1]


In Erlang we do:
lists:filter(fun({Key, Value}) -> Value == 1 end, Args).

and just in case you thought that
lists:keyfind(1, 2, Args).
would find all tuples with the second element equal to 1, it only returns the first tuple that it finds.