| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- %%--------------------------------------------------------------------
- %% Copyright (c) 2020-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
- %%
- %% Licensed under the Apache License, Version 2.0 (the "License");
- %% you may not use this file except in compliance with the License.
- %% You may obtain a copy of the License at
- %%
- %% http://www.apache.org/licenses/LICENSE-2.0
- %%
- %% Unless required by applicable law or agreed to in writing, software
- %% distributed under the License is distributed on an "AS IS" BASIS,
- %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- %% See the License for the specific language governing permissions and
- %% limitations under the License.
- %%--------------------------------------------------------------------
- -module(prop_emqx_rpc).
- -include_lib("proper/include/proper.hrl").
- -include_lib("eunit/include/eunit.hrl").
- -define(NODENAME, 'test@127.0.0.1').
- -define(ALL(Vars, Types, Exprs),
- ?SETUP(
- fun() ->
- State = do_setup(),
- fun() -> do_teardown(State) end
- end,
- ?FORALL(Vars, Types, Exprs)
- )
- ).
- %%--------------------------------------------------------------------
- %% Properties
- %%--------------------------------------------------------------------
- prop_node() ->
- ?ALL(
- Node0,
- nodename(),
- begin
- Node = punch(Node0),
- ?assert(emqx_rpc:cast(Node, erlang, system_time, [])),
- case emqx_rpc:call(Node, erlang, system_time, []) of
- {badrpc, _Reason} -> true;
- Delivery when is_integer(Delivery) -> true;
- _Other -> false
- end
- end
- ).
- prop_node_with_key() ->
- ?ALL(
- {Node0, Key},
- nodename_with_key(),
- begin
- Node = punch(Node0),
- ?assert(emqx_rpc:cast(Key, Node, erlang, system_time, [])),
- case emqx_rpc:call(Key, Node, erlang, system_time, []) of
- {badrpc, _Reason} -> true;
- Delivery when is_integer(Delivery) -> true;
- _Other -> false
- end
- end
- ).
- prop_nodes() ->
- ?ALL(
- Nodes0,
- nodesname(),
- begin
- Nodes = punch(Nodes0),
- case emqx_rpc:multicall(Nodes, erlang, system_time, []) of
- {RealResults, RealBadNodes} when
- is_list(RealResults);
- is_list(RealBadNodes)
- ->
- true;
- _Other ->
- false
- end
- end
- ).
- prop_nodes_with_key() ->
- ?ALL(
- {Nodes0, Key},
- nodesname_with_key(),
- begin
- Nodes = punch(Nodes0),
- case emqx_rpc:multicall(Key, Nodes, erlang, system_time, []) of
- {RealResults, RealBadNodes} when
- is_list(RealResults);
- is_list(RealBadNodes)
- ->
- true;
- _Other ->
- false
- end
- end
- ).
- %%--------------------------------------------------------------------
- %% Helper
- %%--------------------------------------------------------------------
- do_setup() ->
- ensure_distributed_nodename(),
- ok = logger:set_primary_config(#{level => warning}),
- {ok, _Apps} = application:ensure_all_started(gen_rpc),
- ok = application:set_env(gen_rpc, call_receive_timeout, 100),
- ok = meck:new(gen_rpc, [passthrough, no_history]),
- ok = meck:expect(
- gen_rpc,
- multicall,
- fun(Nodes, Mod, Fun, Args) ->
- gen_rpc:multicall(Nodes, Mod, Fun, Args, 100)
- end
- ).
- do_teardown(_) ->
- ok = net_kernel:stop(),
- ok = application:stop(gen_rpc),
- ok = meck:unload(gen_rpc),
- %% wait for tcp close
- timer:sleep(2500).
- ensure_distributed_nodename() ->
- case net_kernel:start([?NODENAME]) of
- {ok, _} ->
- ok;
- {error, {already_started, _}} ->
- net_kernel:stop(),
- net_kernel:start([?NODENAME]);
- {error, {{shutdown, {_, _, {'EXIT', nodistribution}}}, _}} ->
- %% start epmd first
- spawn_link(fun() -> os:cmd("epmd") end),
- timer:sleep(100),
- net_kernel:start([?NODENAME])
- end.
- %%--------------------------------------------------------------------
- %% Generator
- %%--------------------------------------------------------------------
- nodename() ->
- ?LET(
- {NodePrefix, HostName},
- {node_prefix(), hostname()},
- begin
- Node = NodePrefix ++ "@" ++ HostName,
- list_to_atom(Node)
- end
- ).
- nodename_with_key() ->
- ?LET(
- {NodePrefix, HostName, Key},
- {node_prefix(), hostname(), choose(0, 10)},
- begin
- Node = NodePrefix ++ "@" ++ HostName,
- {list_to_atom(Node), Key}
- end
- ).
- nodesname() ->
- oneof([list(nodename()), [node()]]).
- nodesname_with_key() ->
- oneof([{list(nodename()), choose(0, 10)}, {[node()], 1}]).
- node_prefix() ->
- oneof(["emqxct", text_like()]).
- text_like() ->
- ?SUCHTHAT(Text, list(range($a, $z)), (length(Text) =< 100 andalso length(Text) > 0)).
- hostname() ->
- oneof(["127.0.0.1", "localhost"]).
- %%--------------------------------------------------------------------
- %% Utils
- %%--------------------------------------------------------------------
- %% After running the props, the `node()` () is only able to return an
- %% incorrect node name - `nonode@nohost`, But we want a distributed nodename
- %% So, just translate the `nonode@nohost` to ?NODENAME
- punch(Nodes) when is_list(Nodes) ->
- lists:map(fun punch/1, Nodes);
- punch('nonode@nohost') ->
- %% Equal to ?NODENAME
- node();
- punch(GoodBoy) ->
- GoodBoy.
|