I'm starting to use common test as my test framework in erlang.
Suppose that I have function I expect to accept only positive numbers and it should blows in any other case.
positive_number(X) when > 0 -> {positive, X}.
and I want to test that
positive_number(-5).
will not complete successfully.
How do I test this behaviour? In other languages I would say that the test case expects some error or exception and fails if it function under test doesn't throws any error for invalid invalid parameter. How to do that with common test?
Update:
I can make it work with
test_credit_invalid_input(_) ->
InvalidArgument = -1,
try mypackage:positive_number(InvalidArgument) of
_ -> ct:fail(not_failing_as_expected)
catch
error:function_clause -> ok
end.
but I think this is too verbose, I would like something like:
assert_error(mypackage:positive_number, [-1], error:function_clause)
I assuming that common test has this in some place and my lack of proper knowledge of the framework that is making me take such a verbose solution.
Update:
Inspired by Michael's response I created the following function:
assert_fail(Fun, Args, ExceptionType, ExceptionValue, Reason) ->
try apply(Fun, Args) of
_ -> ct:fail(Reason)
catch
ExceptionType:ExceptionValue -> ok
end.
and my test became:
test_credit_invalid_input(_) ->
InvalidArgument = -1,
assert_fail(fun mypackage:positive_number/1,
[InvalidArgument],
error,
function_clause,
failed_to_catch_invalid_argument).
but I think it just works because it is a little bit more readable to have the assert_fail call than having the try....catch in every test case.
I still think that some better implementation should exists in Common Test, IMO it is an ugly repetition to have this test pattern repeatedly implemented in every project.
Convert the exception to an expression and match it:
test_credit_invalid_input(_) ->
InvalidArgument = -1,
{'EXIT', {function_clause, _}}
= (catch mypackage:positive_number(InvalidArgument)).
That turns your exception into a non exception and vice versa, in probably about as terse a fashion as you can expect.
You could always use a macro or function too though to hide the verbosity.
Edit (re: comment):
If you use a full try catch construct, as in your question, you lose information about any failure case, because that information is thrown away in favour of the atom 'not_failing_as_expected' or 'failed_to_catch_invalid_argument'.
Trying an expected fail value on the shell:
1> {'EXIT', {function_clause, _}}
= (catch mypackage:positive_number(-4)).
{'EXIT',{function_clause,[{mypackage,positive_number,
[-4],
[{file,"mypackage.erl"},{line,7}]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,661}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,434}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,441}]},
{shell,exprs,7,[{file,"shell.erl"},{line,676}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,631}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,616}]}]}}
Truing an expected success value on the shell:
2> {'EXIT', {function_clause, _}} = (catch mypackage:positive_number(3)).
** exception error: no match of right hand side value {positive,3}
In both cases you get a lot of information, but crucially, from both of them you can tell what parameters were used to call your function under test (albeit in the second case this is only because your function is determinate and one to one).
In a simple case like this these things don't matter so much, but as a matter of principal, it's important, because later with more complex cases where perhaps the value that fails your function is not hard coded as it is here, you may not know what value caused your function to fail, or what return value. This might then the difference between looking at an ugly backtrace for a moment or two and realising exactly what the problem is, or spending 15 minutes setting up a test to really find out what's going on... OR, worse still, if it's a heisenbug you might spend hours looking for it!
Related
I am trying to have a better performance visualization of my software using fprof. However, the default is measured using wall clock but I want to measure it with cpu time. Hence, I run the following command on the shell but I get an error. Could not really find the reason why it fails on the Internet or erlang documentation. Does anybody have any hints?
% fprof:trace([start, {cpu_time, true}]).
{error,not_supported}
fprof's cpu_time flag is translated to trace's cpu_timestamp as showed in the code snippet above:
According to http://erlang.org/doc/man/erlang.html#trace-3:
cpu_timestamp
A global trace flag for the Erlang node that makes all trace timestamps be in CPU time, not wallclock. It is only allowed with PidSpec==all. If the host machine operating system does not support high resolution CPU time measurements, trace/3 exits with badarg.
So, if the call erlang:trace(all, true, [cpu_timestamp]) returns a badarg exception it means that this feature is unsupported on your platform.
The following code is from file fprof.erl, It shows where the error message comes from. But I don't know how to continue find the source code of erlang:trace. It may be written by c. If trace's source code can be found, the secret can be unveiled.
trace_on(Procs, Tracer, {V, CT}) ->
case case CT of
cpu_time ->
try erlang:trace(all, true, [cpu_timestamp]) of _ -> ok
catch
error:badarg -> {error, not_supported} %% above error message is shown here
end;
wallclock -> ok
end
of ok ->
MatchSpec = [{'_', [], [{message, {{cp, {caller}}}}]}],
erlang:trace_pattern(on_load, MatchSpec, [local]),
erlang:trace_pattern({'_', '_', '_'}, MatchSpec, [local]),
lists:foreach(
fun (P) ->
erlang:trace(P, true, [{tracer, Tracer} | trace_flags(V)])
end,
Procs),
ok;
Error ->
Error
end.
Could you tell me when to use throw, exit and error?
1> catch throw ({aaa}).
{aaa}
2> catch exit ({aaa}).
{'EXIT',{aaa}}
3> catch gen_server:call(aaa,{aaa}).
{'EXIT',{noproc,{gen_server,call,[aaa,{aaa}]}}}
4> catch exit("jaj")
{'EXIT',"jaj"}
There are 3 classes which can be caught with a try ... catch: throw, error and exit.
throw is generated using throw/1 and is intended to be used for non-local returns and does not generate an error unless it is not caught (when you get a nocatch error).
error is generated when the system detects an error. You can explicitly generate an error using error/1. The system also includes a stacktrace in the generated error value, for example {badarg,[...]}.
exit is generated using exit/1 and is intended to signal that this process is to die.
The difference between error/1 and exit/1 is not that great, it more about intention which the stacktrace generated by errors enhances.
The difference between them is actually more noticeable when doing catch ...: when throw/1 is used then the catch just returns the thrown value, as is expected from a non-local return; when an error/1 is used then the catch returns {'EXIT',Reason} where Reason contains the stacktrace; while from exit/1 catch also returns {'EXIT',Reason} but Reason only contains the actual exit reason. try ... catch looks like it equates them, but they are/were very different.
[UPDATED]
I glossed over the important difference between throw and error, pointed out by Robert Virding. This edit is just for the record!
throw error is to be used where one would use throw in other languages. An error in a running process has been detected by your code, which signals an exception with error/1. The same process catches it (possibly higher up in the stack), and the error is to be handled within the same process. error always brings with it a stacktrace.
throw is to be used not to signal an error, but just to return a value from a deeply nested function.
Since it unwinds the stack, calling throw returns the thrown value to the place it was caught. As in the case of error, we're catching stuff that was thrown, only what was thrown wasn't an error but rather just a value passed up the stack. This is why throw does not bring with it a stacktrace.
As a contrived example, if we wanted to implement an exists function for lists, (similar to what list:any does) and as an exercise without doing the recursing ourselves, and using just list:foreach, then throw could be used here:
exists(P, List) ->
F = fun(X) ->
case P(X) of
true -> throw(true);
Whatever -> Whatever
end
end,
try lists:foreach(F, List) of
ok -> false
catch
true -> true
end.
A value thrown but not caught is treated as an error: a nocatch exception will be generated.
EXIT is to be signaled by a process when it 'gives up'. The parent process handles the EXIT, while the child process just dies. This is the Erlang let-it-crash philosophy.
So exit/1's EXIT is not to be caught within the same process, but left to the parent. error/1's errors are local to the process - i.e., a matter of what happens and how it is handled by the process itself; throw/1 is used for control flow across the stack.
[UPDATE]
This tutorial explains it well: http://learnyousomeerlang.com/errors-and-exceptions
Note there is also a exit/2 - called with a Pid of a process to send the EXIT to.
exit/1 implies the parent process.
I'm new to Erlang, but here's how I think about what these things are, their differences, what they're used for, etc.:
throw: a condition that should be handled locally (i.e. within the current process). E.g. caller is looking for an element in a collection, but does not know if the collection actually contains such an element; then, the callee could throw if such an element is not present, and the caller detect absence by using try[/of]/catch. If caller neglects to do this, then this gets turned into an nocatch error (explained below).
exit: The current process is done. E.g. it has simply finished (in that case, you'd pass normal, which is treated the the same as the original function returning), or its operation was cancelled (E.g. it normally loops indefinitely but has just received a shut_down message).
error: the process has done something and/or reached a state that the programmer did not take into account (E.g. 1/0), believes is impossible (E.g. case ... of encounters a value that does not match any case), or some precondition is not met (E.g. input is nonempty). In this case, local recovery doesn't make sense. Therefore, neither throw nor exit is appropriate. Since this is unexpected, a stack trace is part of the Reason.
As you can see, the above list is in escalating order:
throw is for sane conditions that the caller is expected to handle. I.e. handling occurs within the current process.
exit is also sane, but should end the current process simply because the process is done.
error is insane. Something happened that can't reasonably be recovered from (usually a bug?), and local recovery would not be appropriate.
vs. other languages:
throw is analogous to the way checked exceptions are used in Java. Whereas, error is used in a manner more analogous to unchecked exceptions. Checked exceptions are exceptions you want the caller to handle. Java requires you to either wrap calls in try/catch or declare that your method throws such exceptions. Whereas, unchecked exceptions generally propagate to the outermost caller.
exit does not have a good analog in more "conventional" languages like Java, C++, Python, JavaScript, Ruby, etc. exit vaguely like an uber-return: instead of returning at the end, you can return from the middle of a function, except you don't just return from the current function, you return from them ALL.
exit Example
serve_good_times() ->
receive
{top_of_the_mornin, Sender} ->
Sender ! and_the_rest_of_the_day_to_yourself;
{you_suck, Sender} ->
Sender ! take_a_chill_pill;
% More cases...
shut_down ->
exit(normal)
end,
serve_good_times()
end
Since serve_good_times calls itself after almost all messages, the programmer has decided that we don't want to repeat that call in every receive case. Therefore, she has put that call after the receive. But then, what if serve_good_times decides to stop calling itself? This is where exit comes to the rescue. Passing normal to exit causes the process to terminate just as though the last function call has returned.
As such, it's generally inappropriate to call exit in a general purpose library, like lists. It's none of the library's business whether the process should end; that should be decided by application code.
What About Abnormal exit?
This matters if another process (the "remote" process) is linked to the "local" process that calls exit (and process_flag(trap_exit, true) was not called): Just like the last function returning, exit(normal) does not cause remote process to exit. But if the local process makes a exit(herp_derp) call, then the remote process also exits with Reason=herp_derp. Of course, if the remote process is linked to yet more processes, they also get exit signal with Reason=herp_derp. Therefore, non-normal exits result in a chain reaction.
Let's take a look at this in action:
1> self().
<0.32.0>
2> spawn_link(fun() -> exit(normal) end).
<0.35.0>
3> self().
<0.32.0>
4>
4>
4> spawn_link(fun() -> exit(abnormal) end).
** exception exit: abnormal
5> self().
<0.39.0>
6>
The first process that we spawned did not cause the shell to exit (we can tell, because self returned the same pid before and after spawn_link). BUT the second process did cause the shell to exit (and the system replaced the shell process with a new one).
Of course, if the remote process uses process_flag(trap_exit, true) then it just gets a message, regardless of whether the local process passes normal or something else to exit. Setting this flag stops the chain reaction.
6> process_flag(trap_exit, true).
false
7> spawn_link(fun() -> exit(normal) end).
<0.43.0>
8> self().
<0.39.0>
9> flush().
Shell got {'EXIT',<0.43.0>,normal}
ok
10>
10>
10> spawn_link(fun() -> exit(abnormal) end).
<0.47.0>
11> self().
<0.39.0>
12> flush().
Shell got {'EXIT',<0.47.0>,abnormal}
Recall that I said that exit(normal) is treated like the original function returning:
13> spawn_link(fun() -> ok end).
<0.51.0>
14> flush().
Shell got {'EXIT',<0.51.0>,normal}
ok
15> self().
<0.39.0>
What do you know: the same thing happened as when exit(normal) was called. Wonderful!
I am trying to make a simple UDP packet decoder.
packet_decoder(Packet)->
<<Opts:8,MobIdLength:8,MobId:64,MobIdType:8,MgeType:8,SeqNum:16,Rest/binary>> = Packet,
io:format("Options:~p~n",Opts),
io:format("MobIdLength:~p~n",MobIdLength),
io:format("MobId:~p~n",MobId),
io:format("MobIdType:~p~n",MobIdType),
io:format("MgeType:~p~n",MgeType),
io:format("SeqNum:~p~n",SeqNum).
Packet is passed by a receive loop:
rcv_loop(Socket) ->
inet:setopts(Socket, [{active, once}, binary]),
io:format("rcvr started:~n"),
receive
{udp, Socket, Host, Port, Bin} ->
packet_decoder(Bin),
rcv_loop(Socket)
end.
I keep getting(following error edited 9/7/12 9:30 EST):
** exception error: no match of right hand side value
<<131,8,53,134,150,4,149,0,80,15,1,2,1,2,0,16,80,71,115,
52,80,71,115,53,24,63,227,197,211,...>>
in function udp_server:packet_decoder/1
called as udp_server:packet_decoder(<<131,8,53,134,150,4,149,0,80,15,
1,2,1,2,0,16,80,71,115,52,80,71,
115,53,24,63,227,197,...>>)
in call from udp_server:rcv_loop/1
in call from udp_server:init/0
If I create the same variable in the Erlang shell as a binary, i.e.
Packet = <<131,8,53,134,150,4,149,0,80,15,1,2,1,2,0,16,80,71,115,52,80,71,115,53,24,63,227,197,211,228,89,72,0,0,0,0,0,0,0,16,0,5,5,32,1,4,255,159,15,18,28,0,34,62,2,0,0,0,0,0,0,0,47,67>>.
<<Opts:8,MobIdLength:8,MobId:64,MobIdType:8,MgeType:8,SeqNum:16,Rest/binary>> = Packet.
It works just fine. Is there some subtlety in passing this to a function that I am missing? I have tried what I think is everything(except the right way). I tried setting the type and size. I also just tried
<<Rest/binary>> = Packet.
To no avail. Any help much appreciated.
The error you are getting when you run your code does not match your code. The error you are getting:
** exception error: no match of right hand side value ...
is a badmatch error and comes from an explicit = match where the pattern does not match the value from the RHS. There is no = in the code for rcv_loop/1. This implies that the loop you are running is not this code. So there are some questions to be asked:
When you have recompiled the module containing rcv_loop/1 have you restarted the loop so you run the new code? This is not done automagically.
Are you sure you are loading/running the code you think you are? I know this question sounds stupid but it is very easy, and not uncommon, to work on one version of the code and load another. You need to get the paths right.
The other things about mentioned about your code would not give this error. The calls to io:format/2 are wrong but would result in errors when you make the actual calls to io:format/2. Using the variable Socket as you do is not an error, it just means that you only want to receive UDP packets from just that socket.
EDIT : the first part of my answer was completely wrong so in order to not mislead, I deleted it.
Like spotted Alexey Kachayev io:format takes as second parameter a list, so :
packet_decoder(Packet)->
<<Opts:8,MobIdLength:8,MobId:64,MobIdType:8,MgeType:8,SeqNum:16,Rest/binary>> = Packet,
io:format("Options:~p~n",[Opts]),
io:format("MobIdLength:~p~n",[MobIdLength]),
io:format("MobId:~p~n",[MobId]),
io:format("MobIdType:~p~n",[MobIdType]),
io:format("MgeType:~p~n",[MgeType]),
io:format("SeqNum:~p~n",[SeqNum]).
I figured it out(kinda). I had been working on this in erlide in eclipse which had worked fine for all of the other parts of the. I tried compiling it from the erl shell and it worked fine. There must be some minor difference in the way eclipse is representing the source or the way it invokes the erlang compiler and shell. I will take it up with erlide.org. Thanks for the help!
Mainly I want to know if I can send a function in a message in a distributed Erlang setup.
On Machine 1:
F1 = Fun()-> hey end,
gen_server:call(on_other_machine,F1)
On Machine 2:
handler_call(Function,From,State) ->
{reply,Function(),State)
Does it make sense?
Here's an interesting article about "passing fun's to other Erlang nodes". To resume it briefly:
[...] As you might know, Erlang distribution
works by sending the binary encoding
of terms; and so sending a fun is also
essentially done by encoding it using
erlang:term_to_binary/1; passing the
resulting binary to another node, and
then decoding it again using
erlang:binary_to_term/1.[...]
This is pretty obvious
for most data types; but how does it
work for function objects?
When you encode a fun, what is encoded
is just a reference to the function,
not the function implementation.
[...]
[...]the definition of the function is not passed along; just exactly enough information to recreate the fun at an other node if the module is there.
[...] If the module containing the fun has not yet been loaded, and the target node is running in interactive mode; then the module is attempted loaded using the regular module loading mechanism (contained in the module error_handler); and then it tries to see if a fun with the given id is available in said module. However, this only happens lazily when you try to apply the function.
[...] If you never attempt to apply the function, then nothing bad happens. The fun can be passed to another node (which has the module/fun in question) and then everybody is happy.
Maybe the target node has a module loaded of said name, but perhaps in a different version; which would then be very likely to have a different MD5 checksum, then you get the error badfun if you try to apply it.
I would suggest you to read the whole article, cause it's extremely interesting.
You can send any valid Erlang term. Although you have to be careful when sending funs. Any fun referencing a function inside a module needs that module to exist on the target node to work:
(first#host)9> rpc:call(second#host, erlang, apply,
[fun io:format/1, ["Hey!~n"]]).
Hey!
ok
(first#host)10> mymodule:func("Hey!~n").
5
(first#host)11> rpc:call(second#host, erlang, apply,
[fun mymodule:func/1, ["Hey!~n"]]).
{badrpc,{'EXIT',{undef,[{mymodule,func,["Hey!~n"]},
{rpc,'-handle_call_call/6-fun-0-',5}]}}}
In this example, io exists on both nodes and it works to send a function from io as a fun. However, mymodule exists only on the first node and the fun generates an undef exception when called on the other node.
As for anonymous functions, it seems they can be sent and work as expected.
t1#localhost:
(t1#localhost)7> register(shell, self()).
true
(t1#localhost)10> A = me, receive Fun when is_function(Fun) -> Fun(A) end.
hello me you
ok
t2#localhost:
(t2#localhost)11> B = you.
you
(t2#localhost)12> Fn2 = fun (A) -> io:format("hello ~p ~p~n", [A, B]) end.
#Fun<erl_eval.6.54118792>
(t2#localhost)13> {shell, 't1#localhost'} ! Fn2.
I am adding coverage logic to an app built on riak-core, and the merge of results gathered can be tricky if anonymous functions cannot be used in messages.
Also check out riak_kv/src/riak_kv_coverage_filter.erl
riak_kv might be using it to filter result, I guess.
I'm trying to use the following F# code to access a Xaml control.
let (?) (source:obj) (s:string) =
match source with
| :? ResourceDictionary as r -> r.[s] :?> 'T
| :? Control as source ->
match source.FindName(s) with
| null -> invalidOp (sprintf "dynamic lookup of Xaml component %s failed" s)
| :? 'T as x -> x
| _ -> invalidOp (sprintf "dynamic lookup of Xaml component %s failed because the component found was of type %A instead of type %A" s (s.GetType()) typeof<'T>)
| _ -> invalidOp (sprintf "dynamic lookup of Xaml component %s failed because the source object was of type %A. It must be a control or a resource dictionary" s (source.GetType()))
This is from Daniel Mohl's excellent F# for Windows Phone template.
I've created a class to basically read the accelerometer and trigger an event when the phone is shaken. The event gets raised as expected but for some reason it's spawned in a second thread--which leads the CLR to throw an "invalid cross-thread access" exception when the event handler attempts to execute this code. The exception is thrown on the source.FindName(s) call. I can see a second thread of execution--which kind of surprises me because I didn't specifically spawn a secondary thread. I mean I didn't explicitly call async or do anything else that I can think of that would cause a secondary thread of execution to start.
So it seems like there are a few approaches I could take:
I could try to figure out why I'm
spawning a secondary thread when I
haven't specifically requested it and modify the code to prevent a secondary thread of
execution from being spawned.
I could try to modify the (?)
function to account for multiple
threads of execution but I'd really
like to understand why I'm getting a
second thread started
I think probably the second approach is best but I'd really like to understand what I'm doing that's causing a secondary thread to spawn. I realize how hard that is to answer without specific code but I don't mind researching this if someone can point me in the right direction. I believe this has something to do with the Windows 7 Phone platform because the code is, as far as I can tell, pretty much the idiomatic way to bind a Xaml control with F# code.
Any thoughts, comments, suggestions would be greatly appreciated.
Cross-posted to HubFS as well
Event handling in WP7 is generally handled on async callbacks. Accessing the accelerometer is no exception.
You'll need to direct any code that results in a UI update to the dispatcher.
In c# this can be done like
Dispatcher.BeginInvoke( () => { /* your UI code */ } );
The approach for sending results to the Dispatcher used in this post may also be helpful for you in f# as it's more of a functional style than imperative as a result of using Rx.
WP7 Code: Using the Accelerometer API - Dragos Manolescu's (work) blog