我想使用EUnit测试一些第三方Erlang代码.
代码功能的输出使用显示在标准输出上io:format/2.我想捕获该输出并对?assert将要打印的字符串执行测试.我无法修改第三方代码.
这是用Erlang做到这一点的方法吗?(例如,在Java中,我可以简单地将System.setOut()用于输出流).
更新:
在group_leader/2似乎是在正确的轨道上.
但是,我仍然没有看到它如何允许我捕获打印的字符串,io:format所以我可以测试我的断言.一个非常简单的代码示例是:
result(Value) ->
io:format("Result: ~w~n", [Value]).
test_result() ->
?assertMatch("Result: 5~n", result(5)).
Run Code Online (Sandbox Code Playgroud)
显然,函数的返回result/1是原子ok,但实际上我想测试输出到控制台的字符串(即"Result: 5~n").
这种方法我错了,因为似乎没有其他人这样做(根据我缺乏搜索结果判断)?
背景:第三方代码是一个交互式控制台应用程序,因此所有功能仅用于io:format显示结果.
请Haskell的任何专家在那里为我澄清一些事情:
给出一个函数的简化示例,match它应该从列表返回一个匹配的值,这是使用Maybe或返回的"更好"的函数定义[](空列表)?
那是:
match :: String -> [String] -> Maybe String
Run Code Online (Sandbox Code Playgroud)
要么
match :: String -> [String] -> [String] {- possibly empty, if no match -}
Run Code Online (Sandbox Code Playgroud)
出于清晰的原因,我更喜欢第一个版本,但我很想知道这种事情是否有约定.
在我的OS X应用程序中,我允许用户打开Finder窗口.我想在我的"打开Finder"按钮上使用Finder的图标.我的应用程序将进入App Store,但我宁愿预先防止任何违反Apple使用其图标的政策.
那么,Apple会允许重复使用吗?并且,任何人都可以提供相应的Apple文档参考吗?(我以为我读过它是不允许的,但我现在找不到它.)
UPDATE:办案人感兴趣的应用程序没有运行,我用前一个问题的superfell的回答12166532,如下所示:
// Return an application's icon using its bundle identifier
- (NSImage *) applicationIconWithBundleIdentifier: (NSString *) bundleIdentifier
{
NSImage *image = [NSImage imageNamed:NSImageNameComputer]; // fallback icon
NSString *path = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:bundleIdentifier];
if (path) {
image = [[NSWorkspace sharedWorkspace] iconForFile:path];
}
return image;
}
Run Code Online (Sandbox Code Playgroud)
但是,我非常感谢Rob的回答让我走上正轨.
有人可以向我解释为什么Pid从全局返回:whereis_name()在不同的终端(在OSX下,至少)完成时是不同的.
下面是一个简单的演示.
demo.erl
-module(demo).
-export([start/0, loop/0, echo/1]).
start() ->
Pid = spawn(?MODULE, loop, []),
yes = global:register_name('demo', Pid).
echo(Msg) ->
global:send('demo', Msg).
loop() ->
receive
Msg ->
io:format("demo: ~w~n", [Msg]),
loop()
end.
Run Code Online (Sandbox Code Playgroud)
航站楼A:
erl -sname A -setcookie demo
(A@local)1> demo:start().
yes
(A@local)2> global:whereis_name(demo).
<0.39.0>
(A@local)3> demo:echo(aaa).
<0.39.0>
demo: aaa
demo: bbb
demo: ccc
(A@local)4>
Run Code Online (Sandbox Code Playgroud)
B航站楼:
erl -sname B -setcookie demo
(B@local)1> net_kernel:connect_node('A@local').
true
(B@local)2> demo:echo(bbb).
<6572.39.0>
(B@local)3> global:whereis_name(demo).
<6572.39.0>
Run Code Online (Sandbox Code Playgroud)
终端C:
erl -sname C -setcookie demo
(C@local)1> net_kernel:connect_node('A@local').
true
(C@local)2> demo:echo(ccc). …Run Code Online (Sandbox Code Playgroud) 以下代码片段由Francesco Cesarini和Erlang编程的Simon Thompson撰写,作为Erlang中可能的竞争条件的一个例子.
start() ->
case whereis(db_server) of
undefined ->
Pid = spawn(db_server, init, []),
register(db_server, Pid),
{ok, Pid};
Pid when is_pid(Pid) ->
{error, already_started}
end.
Run Code Online (Sandbox Code Playgroud)
在没有逐字复制细节的情况下,作者解释说如果两个进程同时执行start(),那么运行"undefined"部分的进程1可能无法完成,因为进程2会导致它被抢占.然后,进程2将运行"未定义"部分以完成.现在,当进程1恢复时,进程2已经注册了db_server,导致其对register()的调用抛出运行时错误.我希望你能理解我的意思,因为我不想翻阅这本书的文字.
我的问题是,当两个进程同时执行start()时,如何编码上述确切的功能以避免潜在的竞争条件?
随着“最近”对 C 和 C++ 添加内存模型的更改(类似于 Java 和 C#),我想知道 Ada83 或 Ada95 对并发的内置支持是否也定义了内存模型。
有谁知道有关 Ada 是否定义了内存模型的任何参考资料?
额外问题:Ada83 是第一个为共享状态并发提供 INBUILT 支持的通用编程语言吗?
我需要向全局注册的进程发送一条消息,当它被替换为备份进程(即故障转移)时,可能在短时间内不可用.
以下片段是好的Erlang代码:
% send message to globally registered process, with possibility to retry once
send_message(To, Message, Retry) ->
try global:send(To, Message)
catch
% registered process To is unavailable
exit: {badarg, {To, Message}} ->
io:format("catch: exit: {badarg,{~w, ~w}}~n", [To, Message]), % dbg only
case Retry of
true ->
% retry sending message, after 1 second
sleep(1000),
send_message(To, Message, false);
false ->
% re-throw caught exit, including stack trace
erlang:raise(exit, {badarg, {To, Message}},
erlang:get_stacktrace())
end
end.
Run Code Online (Sandbox Code Playgroud)
Retry参数为true或false,表示如果出现问题,应重试一次消息.如果仍然无法发送消息,我希望引发相同的异常,就像在try-catch块之外调用global:send(To,Message)一样.
我知道上面的工作,但我担心我的case块的错误部分是否是好的erlang(例如使用erlang:raise()和rlang:get_stacktrace()).
有什么想法或建议使代码"更好"?