【发布时间】:2019-09-13 03:35:47
【问题描述】:
我有一个数据包,如果它包含一个特定的标签(比如 testtag),那么我需要等待一段时间才能使用数据包标签中的参数值(比如 valuetag)实现一个特定的功能(比如 testfunction),但是如果在此期间超时该数据包再次出现但具有不同的值标签,然后使用更新的值实现测试功能。 如何实现?
【问题讨论】:
标签: erlang
我有一个数据包,如果它包含一个特定的标签(比如 testtag),那么我需要等待一段时间才能使用数据包标签中的参数值(比如 valuetag)实现一个特定的功能(比如 testfunction),但是如果在此期间超时该数据包再次出现但具有不同的值标签,然后使用更新的值实现测试功能。 如何实现?
【问题讨论】:
标签: erlang
通常,它需要显示您到目前为止尝试过的内容。但我发现这个问题很酷,所以我建议你一个解决方案。 cmets很少,但我认为它相对容易阅读。 (我让你找到如何从数据包中提取函数测试名称和参数并调用用户接口)
-module (test_tag).
-export ([start/0,activate/3,modify/2,remove/1,stop/0]).
-export ([test_server/1,proc_server/3]).
-export ([test1/2,test2/3]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% User Interface
% start the test with an empty map of pending test process
start() ->
Pid = spawn(?MODULE, test_server, [#{}]),
register(test_server, Pid).
activate(TestName,ParamList,Timeout) when
is_atom(TestName), is_list(ParamList), is_number(Timeout) ->
test_server ! {activate,TestName,ParamList,Timeout}.
modify(TestName,ParamList) when is_atom(TestName), is_list(ParamList) ->
test_server ! {modify,TestName,ParamList}.
remove(TestName) when is_atom(TestName) ->
test_server ! {remove,TestName}.
stop() ->
test_server ! stop.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% internal interface
completed(TestName) ->
test_server ! {completed,TestName,self()}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Sever loop (receive user request and organize the job)
% test_server(stop | map())
test_server(stop) ->
io:format("stopped by user~n");
test_server(Pending) ->
NewPending = receive
{activate,TestName,ParamList,Timeout} ->
activate_test(TestName,ParamList,Timeout,Pending);
{modify,TestName,ParamList} ->
modify_test(TestName,ParamList,Pending);
{remove,TestName} ->
remove_test(TestName,Pending);
{completed,TestName,Pid} ->
test_complete(TestName,Pid,Pending);
stop -> stop_test(Pending)
end,
test_server(NewPending).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% helper functions (in charge to do the server job)
activate_test(TestName,ParamList,Timeout,Pending) ->
case maps:is_key(TestName, Pending) of
true ->
io:format("test ~p already started~n",[TestName]),
Pending; %do nothing
false ->
Pid = spawn(?MODULE,proc_server,[TestName,ParamList,Timeout]),
maps:put(TestName, Pid, Pending)
end.
modify_test(TestName,ParamList,Pending) ->
case maps:get(TestName, Pending,undefined) of
undefined ->
io:format("test ~p not started~n",[TestName]);
Pid ->
Pid ! {new_param,TestName,ParamList}
end,
Pending. % Map unchanged.
remove_test(TestName,Pending) ->
case maps:get(TestName, Pending,undefined) of
undefined ->
io:format("test ~p not started~n",[TestName]),
Pending;
Pid ->
Pid ! {stop,TestName},
maps:remove(TestName, Pending)
end.
test_complete(TestName,Pid,Pending) ->
case maps:get(TestName, Pending,undefined) of
undefined ->
Pending; % already removed, presumably by user
Pid ->
Pid ! {stop,TestName},
maps:remove(TestName, Pending)
end.
stop_test(Pending) ->
maps:map(fun(TestName,Pid) -> Pid ! {stop,TestName} end, Pending),
stop. % return stop to end the test server loop
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% init the process in charge to execute a test after a while
proc_server(TestName,ParamList,Timeout) ->
timer:send_after(Timeout, self(), {execute,TestName}),
proc_server(TestName,ParamList).
% listening loop
proc_server(TestName,ParamList) ->
receive
{execute,TestName} ->
catch(apply(?MODULE,TestName, ParamList)),
completed(TestName);
{new_param,TestName,NewParamList} ->
proc_server(TestName,NewParamList);
{stop,TestName} ->
io:format("test ~p stopped\n",[TestName]),
stop
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% User tests
test1(Param1,Param2) ->
io:format("executing test1 with params ~p and ~p ~n",[Param1,Param2]).
test2(Param1,Param2,Param3) ->
io:format("executing test2 with params ~p, ~p and ~p~n",[Param1,Param2,Param3]).
在shell中执行
1> c(test_tag).
{ok,test_tag}
test_tag:start().
true
2> test_tag:activate(test1,[hello,"hello"],20000).
{activate,test1,[hello,"hello"],20000}
3> test_tag:modify(test1,[hello,"hello guys"]).
{modify,test1,[hello,"hello guys"]}
executing test1 with params hello and "hello guys"
4> test_tag:activate(test1,[hello,"hello"],20000).
{activate,test1,[hello,"hello"],20000}
5> test_tag:activate(test1,[hello,"hello"],20000).
test test1 already started
{activate,test1,[hello,"hello"],20000}
executing test1 with params hello and "hello"
6> test_tag:remove(test1).
test test1 not started
{remove,test1}
7> test_tag:activate(test1,[hello,"hello"],20000).
{activate,test1,[hello,"hello"],20000}
8> test_tag:remove(test1).
test test1 stopped
{remove,test1}
9> test_tag:activate(test2,[hello,"hello",12],20).
{activate,test2,[hello,"hello",12],20}
executing test2 with params hello, "hello" and 12
10> test_tag:activate(test2,[hello,"hello"],20).
{activate,test2,[hello,"hello"],20}
11> test_tag:activate(test2,[hello,"hello"],20000).
{activate,test2,[hello,"hello"],20000}
12> test_tag:activate(test2,[hello,"hello"],20000).
test test2 already started
{activate,test2,[hello,"hello"],20000}
13> test_tag:remove(test2).
test test2 stopped
{remove,test2}
14> test_tag:activate(test3,[hello,"hello"],20000).
{activate,test3,[hello,"hello"],20000}
15> %wait 20 sec
15> test_tag:remove(test3).
test test3 not started
{remove,test3}
16>
【讨论】: