Tag: erlang

nitrogen

i have stumbled upon a very promissing web framwork for erlang. nitrogen, altough very young (first release was around December 2008), it seems exactly what i have looking for. it actually bring the erlang into the web, allowing to develope a true erlang based web app.

nitrogen have several appealing features. the framwork support ajax/comet, which is absolutely a shame how easy it ease to use. it allows defining html templates, with ‘holes’ in it to insert content from the erlang source. but the real benefit is the ability to write those ‘holes’ in erlang modules. those ‘holes’ are filled with elements which are parallel to html structures, and because you are using erlang sytax to describe them, you can use the erlang pattern matching and messaging system in it.

colinux strikes back

because the colinux images are very old, i have decided to build one of my own, based on ubuntu 8.10. so, i followed this post, to create my colinux image. keep in mind installing ubuntu using qemu on windows takes ages (really, few hours, so schedule it to an hour before you go to sleep).

later, i just added another conf file to start this colinux, see more details on me previous post:

kernel=vmlinux
sda1="c:\linux\distro\ubuntu_8.10.ext3.3gb.img"
sda2="c:\linux\distro\ext3_disk_1gb.img"
sdb1="c:\linux\distro\swap_512mb"
root=/dev/sda1 fastboot 3
ro
mem=384
eth0=slirp
eth1=tuntap

moreover, i edited the network and samba, again, as i posted before. afterward i have installed erlang and yaws. finally, few fixes and tweaks i have encountered.

because i want it as a server:

$ sudo apt-get install linux-headers-server linux-image-server linux-server

to solve and odd error message on startup (mmap: Bad address):

$ sudo apt-get remove dmidecode --purge

to prevent yaws, and few other services i don’t need to start after boot:

$ sudo update-rc.d -f bluetooth remove
$ sudo update-rc.d -f gdm remove
$ sudo update-rc.d -f yaws remove

that’s it! if you got so far, you are now officialy an uber-geek ;)

code coverage in erlang

yesterday i found about code coverage under erlang on this nice blog. i wanted to integrate it with my unit testing, so i would be able to see what code of mine is not tested. this can be used to add new tests to cover it, or even remove of unnecessary code.

it took me some time to play with it and come up with a good method of doing that. eventually i have replaced the unit testing makefile line with:

check:
	@for f in $(MODULES); do \
	echo $$f; \
	erl $(FLAGS) -noshell -eval "
	cover:compile($$f, [{i,\"$(INCLUDE)\"}]),\
	$$f:test(),
	cover:analyse_to_file($$f, \"$(DOC)/$${f}_coverage.html\", [html])."\
	-s init stop; \

This actually do 3 things in a raw:

  1. compile each module using cover:compile.
  2. run the test, using the eunit test() function.
  3. dump analysis into html files on doc directory

enjoy!

edit: i found out, that you compile the whole directory for covearge, so the result you get is thecombined  coverage for all the specified modules and tests.

OBJECTS := $(patsubst %.erl,$(BIN)/%.$(EMULATOR),$(wildcard *.erl))
MODULES := $(patsubst %.erl,%,$(wildcard *.erl))
SKIP_FILES := $(patsubst %.erl,%,$(wildcard *_tests.erl))
MODULES := $(filter-out $(SKIP_FILES), $(MODULES))
MODULES := [$(subst $(space),$(comma),$(MODULES))]
 
check:
	@echo Testing units...
	@$(TIME) erl $(ERL_LIB_FLAGS) \
	-mnesia dir '"$(DATA_DIR)"' -mnesia debug $(MNESIA) -noshell \
	-eval "\
	cover:compile_directory(\".\", [{i,\"$(INCLUDE)\"},{d,'NODEBUG'}]), \
	T = fun(X) -> io:format(user, \"~-20.s\", [X]), X:test() end, \
	[T(X) || X <- "$(MODULES)"], \
	F = fun(X) -> cover:analyse_to_file(X, \"$(LOG)/\" ++ \
	    atom_to_list(X) ++ \"_coverage.html\", [html]) end, \
	[F(X) || X <- "$(MODULES)"]. \
	" -s init stop;

more on eunit

the use of eunit is very easy and intuitive. in principle every function which ends with _test of arity 0 (i.e. no input arguments) will be automaticly exported by eunit. eunit will also create a function called test() which will call all tests functions which have been defined. this mechanism leaves the programmer with only the actual test writing, and saves him/her the tedious wrappers and procedures. writing a test on a new module become something which take few seconds.

for example, the next function has its own testing function:

flip_sides(Side) ->
	case Side of
		x -> o;
		o -> x
	end.
 
flip_sides_test() ->
	?assert(flip_sides(x) == o),
	?assert(flip_sides(o) == x).

the testing function is invoked automatically by calling the test function of this module, e.g. mymodule:test(). the test function is supplied by the eunit framework, which takes every function that ends with _test() and add it to the testing list of that module.

a more advanced testing method is needed for testing the always loops that keep the state on the erlang module. few problems need to be solved in order to properly test those kind of loops:

  • initial state loading.
  • external function calls.
  • check of the new state, after each event.
  • the first problem can be solved by adding a new start function for debug use, which takes all the state variables of the always loop as parameters. this allows you to start the always loop in any state you want.

    % original start of arity/0
    start() -> start([], start).
     
    % new function for debug of arity/2
    start(State, Status) ->  register(?MODULE, spawn(fun() -> always(State, Status) end)).
     
    % the state loop
    always(State, Status) ->
    	receive
    		{From, stop} -> From ! stopped;
    		{From, reset} -> always([], start);
    		{From, {add, N}} -> always(module2:add(N, State), continue)
    	end.

    the next problem is the call for external function, shown here as call for module2:add/2, i solved this by adding another parameter to the loop’s state in order to keep a reference to the called function. i have also added it to the start function.

    % original start of arity/0
    start() -> start([], start, fun module2:add/2).
     
    % new function for debug of arity/2
    start(State, Status, Func) ->
    	register(?MODULE, spawn(fun() -> always(State, Status, Func) end)).
     
    % the state loop
    always(State, Status, Func) ->
    	receive
    		{From, stop} -> From ! stopped;
    		{From, reset} -> always([], start, Func);
    		{From, {add, N}} -> always(Func(N, State), continue, Func)
    	end.

    adding a reference to the external function allows me to switch to a mocking function as desired. for the new state checking i have added a dump command to the always loop which return me the current state, so i can test it on my testing functions.

    % the state loop
    always(State, Status, Func) ->
    	receive
    		{From, stop} -> From ! stopped;
    		{From, reset} -> From ! reset, always([], start, Func);
    		{From, {add, N}} -> always(Func(N, State), continue, Func);
    		{From, dump} -> {State, dump, Func}
    	end.

    last i’ll show the test function:

    always_reset_test() ->
    	Fun = fun callback_check_reset_mockup/2,
    	start([x, o], continue, Fun),
    	rpc(reset),
    	?assert(rpc(dump) == {[], start, Fun}),
    	stop().

    callback_check_reset_mockup(N, State) -> void. % you can check match if applicable

    that’s it!

lots of ‘e’s…

i have started off a new project, mostly based on erlang, and i have decided to post few of my observations and experiences which i pick along the way. i will start with edoc and eunit, both i have added to my project with zero effort, and got remarkable results.

edoc produces automatic documentation for the project. i have just added the right code to my project makefile, and voula – instance documentation for my functions api. the code itself is:

docs:
erl -noshell -eval "edoc:application($(APPNAME), \".\", [$(DOC_OPTS)])" -s init stop

where:

APPNAME = myappVSN = 0.1
DOC_OPTS = {def, {version, \"$(VSN)\"}}, no_packages

eunit gives an easy way to add unit testing to the project, again, i have added few lines to my makefile:

MODULES = $(patsubst %.erl,%,$(wildcard *.erl))
check:
@for f in $(MODULES); do \
echo $$f; \
erl $(ERL_LIB_FLAGS) -noshell -s $$f test -s init stop; \
done

those few lines takes all the erl files on the current directory and run the test function for each module.

that’s it for the first time.

Powered by WordPress & Theme by Anders Norén