Skip to content

Commit

Permalink
test: Test interoparability with the old releases
Browse files Browse the repository at this point in the history
Signed-off-by: ieQu1 <99872536+ieQu1@users.noreply.github.com>
  • Loading branch information
ieQu1 committed Mar 6, 2023
1 parent e238a83 commit 5d5116b
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 67 deletions.
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@ test: smoke-test ct-consistency ct-fault-tolerance cover

.PHONY: smoke-test
smoke-test:
$(REBAR) do eunit, ct -v --readable=$(CT_READABLE)
$(REBAR) do eunit, ct -v --cover --readable=$(CT_READABLE)
$(REBAR) ct --readable=$(CT_READABLE) -v --suite mria_compatibility_suite

.PHONY: ct-consistency
ct-consistency:
$(REBAR) ct -v --readable=$(CT_READABLE) --suite mria_proper_suite,mria_proper_mixed_cluster_suite
$(REBAR) ct --cover -v --readable=$(CT_READABLE) --suite mria_proper_suite,mria_proper_mixed_cluster_suite

.PHONY: ct-fault-tolerance
ct-fault-tolerance:
$(REBAR) ct -v --readable=$(CT_READABLE) --suite mria_fault_tolerance_suite
$(REBAR) ct --cover -v --readable=$(CT_READABLE) --suite mria_fault_tolerance_suite

.PHONY: ct-suite
ct-suite: compile
Expand Down
4 changes: 2 additions & 2 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "3.0.1"}}},
{replayq, {git, "https://github.com/emqx/replayq", {tag, "0.3.6"}}},
{mnesia_rocksdb, {git, "https://github.com/emqx/mnesia_rocksdb", {tag, "0.1.11"}}},
{optvar, {git, "https://github.com/emqx/optvar", {tag, "1.0.1"}}}
{optvar, {git, "https://github.com/emqx/optvar", {tag, "1.0.2"}}}
]}.

{erl_opts,
Expand All @@ -33,7 +33,7 @@
{report,{eunit_surefire,[{dir,"."}]}}
]}.

{cover_enabled, true}.
%% {cover_enabled, false}. % Note: it's important to enable it per test-suite only. Otherwise it will mess up the compatibility suite
{cover_opts, [verbose]}.
{cover_export_enabled, true}.

Expand Down
18 changes: 18 additions & 0 deletions scripts/build-old-rel
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash
set -euxo pipefail

echo "Building "${tag}""
[ -d "${tmp_dir}" ] ||
git clone "${root_dir}" "${tmp_dir}"
cd "${tmp_dir}"
git checkout "${tag}"

# Avoid rebuilding rocksdb:
mkdir -p "_checkouts"
pushd "_checkouts"
[ -L rocksdb ] ||
ln -s "${root_dir}/_build/default/lib/rocksdb" rocksdb
popd

[ ! -z $(find . -name mria.app) ] ||
rebar3 as test compile
2 changes: 1 addition & 1 deletion src/mria_status.erl
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ wait_for_shards(Shards, Timeout) ->
Result = optvar:wait_vars( [?optvar({?upstream_pid, I})
|| I <- Shards,
I =/= ?LOCAL_CONTENT_SHARD]
, Timeout
, Timeout
),
Ret = case Result of
ok ->
Expand Down
145 changes: 145 additions & 0 deletions test/mria_compatibility_suite.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
%%--------------------------------------------------------------------
%% Copyright (c) 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.
%%--------------------------------------------------------------------

%% @doc Test interoperability of different mria releases
-module(mria_compatibility_suite).

-compile(export_all).
-compile(nowarn_export_all).
-compile(nowarn_underscore_match).

-include_lib("eunit/include/eunit.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-include("mria_rlog.hrl").

releases() ->
string:lexemes(os:cmd("git tag -l 0.3.*"), "\n").

matrix() ->
Testcases = [t_core_core], %% TODO: add core_replicant test
[{A, B, TC} || OldRel <- releases(),
{A, B} <- [{"master", OldRel}, {OldRel, "master"}],
TC <- Testcases,
supported(A, B, TC)].

supported(_Rel1, _Rel2, _TC) ->
true.

t_core_core(Config, Rel1, Rel2) ->
Cluster = mria_ct:cluster([ #{role => core, code_paths => code_paths(Config, Rel1)}
, #{role => core, code_paths => code_paths(Config, Rel2)}
], []),
?check_trace(
#{timetrap => 30_000},
try
[N1, N2] = mria_ct:start_cluster(mria, Cluster),
verify_version(Rel1, N1),
verify_version(Rel2, N2),
%% Check clustering:
?assertMatch([N1, N2], lists:sort(mria_ct:rpc(N1, mria_mnesia, db_nodes, []))),
?assertMatch([N1, N2], lists:sort(mria_ct:rpc(N2, mria_mnesia, db_nodes, [])))
after
mria_ct:teardown_cluster(Cluster),
mria_ct:cleanup(?FUNCTION_NAME)
end,
common_checks()).

verify_version("master", _Node) ->
ok;
verify_version(Rel, Node) ->
%% Paranoid check: make sure that the code running on the remote
%% node does indeed match the expected release. There are too many
%% things that can break this assumption, for example cover
%% compilation:
?assertEqual({ok, Rel}, mria_ct:rpc(Node, application, get_key, [mria, vsn])),
Src = proplists:get_value(source, mria_ct:rpc(Node, mria, module_info, [compile])),
?assertMatch({match, _}, re:run(Src, "oldrel/" ++ Rel)),
ok.

common_checks() ->
[ fun mria_rlog_props:replicant_no_restarts/1
, fun mria_rlog_props:no_unexpected_events/1
, fun mria_rlog_props:no_split_brain/1
].

all() ->
[t_run_all].

init_per_suite(Config) ->
mria_ct:start_dist(),
snabbkaffe:fix_ct_logging(),
RootDir = root_dir(),
Releases = [{Rel, prep_release(RootDir, Rel)} || Rel <- releases()],
[{releases, Releases} | Config].

init_per_testcase(_, Config) ->
Config.

end_per_testcase(TestCase, Config) ->
mria_ct:cleanup(TestCase),
snabbkaffe:stop(),
Config.

end_per_suite(_Config) ->
ok.

t_run_all(Config) ->
Matrix = matrix(),
Results =
lists:map(
fun({Rel1, Rel2, TC}) ->
try
?MODULE:TC(Config, Rel1, Rel2),
logger:notice(asciiart:visible($%, "~p: ~p -> ~p: OK", [TC, Rel1, Rel2]))
catch
_:_ ->
logger:error(asciiart:visible($!, "~p: ~p -> ~p: FAIL", [TC, Rel1, Rel2])),
false
end
end,
Matrix),
?assert(true, lists:all(fun(A) -> A end, Results)).

code_paths(_Config, "master") ->
mria_ct:master_code_paths();
code_paths(Config, Rel) ->
RelDir = proplists:get_value(Rel, proplists:get_value(releases, Config)),
Rocksdb = filename:join(root_dir(), "_build/test/lib/rocksdb/ebin"),
CodePaths = filelib:wildcard(filename:join(RelDir, "_build/test/lib/*/ebin")),
[Rocksdb|CodePaths].

prep_release(RootDir, Tag) ->
TmpDir = filename:join([RootDir, "_build", "oldrel", Tag]),
ok = filelib:ensure_dir(TmpDir),
0 = cmd( filename:join(RootDir, "scripts/build-old-rel")
, [ {env, [ {"tag", Tag}
, {"tmp_dir", TmpDir}
, {"root_dir", RootDir}
]}
]
),
TmpDir.

cmd(Cmd, Opts) ->
Port = open_port({spawn_executable, Cmd}, [exit_status, nouse_stdio|Opts]),
receive
{Port, {exit_status, Status}} ->
Status
end.

root_dir() ->
[RootDir] = string:lexemes(os:cmd("git rev-parse --show-toplevel"), "\n"),
RootDir.

0 comments on commit 5d5116b

Please sign in to comment.