Skip to content

Commit edaddc0

Browse files
committed
Mnesia migration: Added CT for migrate_pubsub_nodes, migrate_pubsub_subscriptions, migrate_pubsub_affiliations, migrate_pubsub_items, migrate_users, migrate_vcard_search, migrate_vcard, migrate_event_pusher_push_subscription
1 parent 036bcd7 commit edaddc0

File tree

3 files changed

+185
-33
lines changed

3 files changed

+185
-33
lines changed

big_tests/tests/mnesia_migration_SUITE.erl

+170-31
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,31 @@
1515
%%% ==================================================================
1616

1717
-define(RPC_MIGRATE(Act), mongoose_helper:successful_rpc(service_admin_extra_migration, migrate, [<<"mnesia">>, <<"rdbms">>, Act])).
18+
-define(JID, jid:binary_to_bare(<<"migration_user@localhost/test">>)).
19+
-define(NODE_NAME, <<"migration_node">>).
20+
-define(USERNAME, <<"migration_user">>).
21+
-define(NODE_HOST, ct:get_config({hosts, mim, domain})).
22+
-define(BASE_NODE, {pubsub_node, {?NODE_HOST, ?NODE_NAME}, undefined, [], <<"flat">>, [?JID], []}).
23+
-define(BASE_ITEM(Nidx), {pubsub_item, {?NODE_NAME, Nidx}, {erlang:timestamp(), ?JID}, {erlang:timestamp(),?JID}, ?JID, [{xmlcdata, []}]}).
24+
-define(BASE_VCARD, {xmlel,<<"vCard">>,
25+
[{<<"xmlns">>,<<"vcard-temp">>}],
26+
[{xmlel,<<"NICKNAME">>,[],[{xmlcdata, ?USERNAME}]},
27+
{xmlel,<<"TEL">>,[],
28+
[{xmlel,<<"HOME">>,[],[]},
29+
{xmlel,<<"VOICE">>,[],[]},
30+
{xmlel,<<"NUMBER">>,[],
31+
[{xmlcdata,<<"+00000000000">>}]}]}]}).
32+
-define(BASE_SEARCH_VCARD, {vcard_search, {<<"migration_user">>, <<"localhost">>}, <<?USERNAME/binary, "@localhost/test">>, ?USERNAME, <<"fn">>, <<"lfn">>, <<"family">>,
33+
<<"lfamily">>, <<"given">>, <<"lgiven">>, <<"middle">>, <<"lmiddle">>, <<"nickname">>, <<"lnickname">>, <<"bday">>, <<"lbday">>,
34+
<<"ctry">>, <<"lctry">>, <<"locality">>, <<"llocality">>, <<"email">>, <<"lemail">>, <<"orgname">>, <<"lorgname">>, <<"orgunit">>,
35+
<<"lorgunit">>}).
1836

1937
%%--------------------------------------------------------------------
2038
%% Suite configuration
2139
%%--------------------------------------------------------------------
2240

2341
all() ->
24-
case (not ct_helper:is_ct_running()) orelse mongoose_helper:is_rdbms_enabled(ct:get_config({hosts, mim, domain})) of
42+
case (not ct_helper:is_ct_running()) orelse mongoose_helper:is_rdbms_enabled(?NODE_HOST) of
2543
true ->
2644
tests();
2745
false ->
@@ -63,9 +81,18 @@ suite() ->
6381
escalus:suite().
6482

6583
init_per_suite(Config) ->
84+
ok = mnesia:create_schema([node()]),
85+
ok = mnesia:start(),
86+
ok = mongoose_helper:successful_rpc(mod_pubsub_db_mnesia, start, []),
87+
ok = mongoose_helper:successful_rpc(ejabberd_auth_internal, start, [?NODE_HOST]),
88+
ok = mongoose_helper:successful_rpc(mod_vcard_mnesia, init, [<<>>, <<>>]),
89+
ok = mongoose_helper:successful_rpc(mod_event_pusher_push_mnesia, init, [<<>>, <<>>]),
90+
{ok, _} = application:ensure_all_started(jid),
6691
escalus:init_per_suite(Config).
6792

6893
end_per_suite(Config) ->
94+
ok = mongoose_helper:successful_rpc(ejabberd_auth_internal, stop, [?NODE_HOST]),
95+
_ = mnesia:stop(),
6996
escalus_fresh:clean(),
7097
escalus:end_per_suite(Config).
7198

@@ -82,68 +109,143 @@ end_per_testcase(CaseName, Config) ->
82109
escalus:end_per_testcase(CaseName, Config).
83110

84111
%%% ==================================================================
85-
%%% Test case for migrate pubsub_nodes @TODO
112+
%%% Test case for migrate pubsub_nodes
86113
%%% ==================================================================
87114

88-
migrate_pubsub_nodes(Config) ->
89-
R = ?RPC_MIGRATE(<<"pubsub_nodes">>),
90-
ct:comment("TEST CASE ~p", [{?FUNCTION_NAME, R}]).
115+
migrate_pubsub_nodes(_Config) ->
116+
Nidx = create_migration_node(),
117+
{ok, _} = ?RPC_MIGRATE(<<"pubsub_nodes">>),
118+
SqlData = #{table => <<"pubsub_nodes">>, where => <<"name='", ?NODE_NAME/binary, "'">>},
119+
case sql_to_rdbms(SqlData#{act => <<"SELECT">>, column => <<"nidx">>}) of
120+
{selected, [{Nidx}]} ->
121+
{updated, 1} = sql_to_rdbms(SqlData#{act => <<"DELETE">>, column => <<"">>}),
122+
_ = clear_tables(),
123+
ct:comment("Migration of 'pubsub_nodes' is successful for Nidx: ~p", [Nidx]);
124+
Any ->
125+
ct:fail("Unexpected result of 'pubsub_nodes' migration ~p~n", [Any])
126+
end.
91127

92128
%%% ==================================================================
93-
%%% Test case for migrate pubsub_subscriptions @TODO
129+
%%% Test case for migrate pubsub_subscriptions
94130
%%% ==================================================================
95131

96-
migrate_pubsub_subscriptions(Config) ->
97-
?RPC_MIGRATE(<<"pubsub_subscriptions">>),
98-
ct:comment("TEST CASE ~p", [?FUNCTION_NAME]).
132+
migrate_pubsub_subscriptions(_Config) ->
133+
Nidx = create_migration_node(),
134+
ok = mongoose_helper:successful_rpc(mod_pubsub_db_mnesia, transaction, [#{name => add_subscription, args => [Nidx, ?JID, 'subscribed', <<"0000-0000-0000000">>, []]}]),
135+
{ok, _} = ?RPC_MIGRATE(<<"pubsub_subscriptions">>),
136+
SqlData = #{table => <<"pubsub_subscriptions">>, where => <<"nidx=", (list_to_binary(integer_to_list(Nidx)))/binary>>},
137+
case sql_to_rdbms(SqlData#{act => <<"SELECT">>, column => <<"nidx">>}) of
138+
{selected, [{Nidx}]} ->
139+
{updated, 1} = sql_to_rdbms(SqlData#{act => <<"DELETE">>, column => <<"">>}),
140+
_ = clear_tables(),
141+
ct:comment("Migration of 'pubsub_subscriptions' is successful for Nidx: ~p", [Nidx]);
142+
Any ->
143+
ct:fail("Unexpected result of 'pubsub_subscriptions' migration ~p~n", [Any])
144+
end.
99145

100146
%%% ==================================================================
101-
%%% Test case for migrate pubsub_affiliations @TODO
147+
%%% Test case for migrate pubsub_affiliations
102148
%%% ==================================================================
103149

104-
migrate_pubsub_affiliations(Config) ->
105-
?RPC_MIGRATE(<<"pubsub_affiliations">>),
106-
ct:comment("TEST CASE ~p", [?FUNCTION_NAME]).
150+
migrate_pubsub_affiliations(_Config) ->
151+
Nidx = create_migration_node(),
152+
{ok, _} = ?RPC_MIGRATE(<<"pubsub_affiliations">>),
153+
SqlData = #{table => <<"pubsub_affiliations">>, where => <<"nidx=", (list_to_binary(integer_to_list(Nidx)))/binary>>},
154+
case sql_to_rdbms(SqlData#{act => <<"SELECT">>, column => <<"nidx">>}) of
155+
{selected, [{Nidx}]} ->
156+
{updated, 1} = sql_to_rdbms(SqlData#{act => <<"DELETE">>, column => <<"">>}),
157+
_ = clear_tables(),
158+
ct:comment("Migration of 'pubsub_affiliations' is successful for Nidx: ~p", [Nidx]);
159+
Any ->
160+
ct:fail("Unexpected result of 'pubsub_affiliations' migration ~p~n", [Any])
161+
end.
107162

108163
%%% ==================================================================
109-
%%% Test case for migrate pubsub_items @TODO
164+
%%% Test case for migrate pubsub_items
110165
%%% ==================================================================
111166

112-
migrate_pubsub_items(Config) ->
113-
?RPC_MIGRATE(<<"pubsub_items">>),
114-
ct:comment("TEST CASE ~p", [?FUNCTION_NAME]).
167+
migrate_pubsub_items(_Config) ->
168+
Nidx = create_migration_node(),
169+
ok = mongoose_helper:successful_rpc(mod_pubsub_db_mnesia, transaction, [#{name => add_item, args => [Nidx, ?JID, ?BASE_ITEM(Nidx)]}]),
170+
{ok, _} = ?RPC_MIGRATE(<<"pubsub_items">>),
171+
SqlData = #{table => <<"pubsub_items">>, where => <<"nidx=", (list_to_binary(integer_to_list(Nidx)))/binary>>},
172+
case sql_to_rdbms(SqlData#{act => <<"SELECT">>, column => <<"nidx">>}) of
173+
{selected, [{Nidx}]} ->
174+
{updated, 1} = sql_to_rdbms(SqlData#{act => <<"DELETE">>, column => <<"">>}),
175+
_ = clear_tables(),
176+
ct:comment("Migration of 'pubsub_items' is successful for Nidx: ~p", [Nidx]);
177+
Any ->
178+
ct:fail("Unexpected result of 'pubsub_items' migration ~p~n", [Any])
179+
end.
115180

116181
%%% ==================================================================
117-
%%% Test case for migrate users @TODO
182+
%%% Test case for migrate users
118183
%%% ==================================================================
119184

120-
migrate_users(Config) ->
121-
?RPC_MIGRATE(<<"users">>),
122-
ct:comment("TEST CASE ~p", [?FUNCTION_NAME]).
185+
migrate_users(_Config) ->
186+
ok = mongoose_helper:successful_rpc(ejabberd_auth_internal, set_password, [?USERNAME, <<"localhost">>, <<"migration_pass">>]),
187+
{ok, _} = ?RPC_MIGRATE(<<"users">>),
188+
SqlData = #{table => <<"users">>, where => <<"username='", ?USERNAME/binary, "'">>},
189+
case sql_to_rdbms(SqlData#{act => <<"SELECT">>, column => <<"username">>}) of
190+
{selected, [{?USERNAME}]} ->
191+
{updated, 1} = sql_to_rdbms(SqlData#{act => <<"DELETE">>, column => <<"">>}),
192+
_ = clear_tables(),
193+
ct:comment("Migration of 'users' is successful for Username: ~p", [?USERNAME]);
194+
Any ->
195+
ct:fail("Unexpected result of 'users' migration ~p~n", [Any])
196+
end.
123197

124198
%%% ==================================================================
125-
%%% Test case for migrate vcard_search @TODO
199+
%%% Test case for migrate vcard_search
126200
%%% ==================================================================
127201

128-
migrate_vcard_search(Config) ->
129-
?RPC_MIGRATE(<<"vcard_search">>),
130-
ct:comment("TEST CASE ~p", [?FUNCTION_NAME]).
202+
migrate_vcard_search(_Config) ->
203+
ok = set_vcard(),
204+
{ok, _} = ?RPC_MIGRATE(<<"vcard_search">>),
205+
SqlData = #{table => <<"vcard_search">>, where => <<"username='", ?USERNAME/binary, "'">>},
206+
case sql_to_rdbms(SqlData#{act => <<"SELECT">>, column => <<"username">>}) of
207+
{selected, [{?USERNAME}]} ->
208+
{updated, 1} = sql_to_rdbms(SqlData#{act => <<"DELETE">>, column => <<"">>}),
209+
_ = clear_tables(),
210+
ct:comment("Migration of 'vcard_search' is successful for Username: ~p", [?USERNAME]);
211+
Any ->
212+
ct:fail("Unexpected result of 'vcard_search' migration ~p~n", [Any])
213+
end.
131214

132215
%%% ==================================================================
133-
%%% Test case for migrate vcard @TODO
216+
%%% Test case for migrate vcard
134217
%%% ==================================================================
135218

136219
migrate_vcard(Config) ->
137-
?RPC_MIGRATE(<<"vcard">>),
138-
ct:comment("TEST CASE ~p", [?FUNCTION_NAME]).
220+
ok = set_vcard(),
221+
{ok, _} = ?RPC_MIGRATE(<<"vcard">>),
222+
SqlData = #{table => <<"vcard">>, where => <<"username='", ?USERNAME/binary, "'">>},
223+
case sql_to_rdbms(SqlData#{act => <<"SELECT">>, column => <<"username">>}) of
224+
{selected, [{?USERNAME}]} ->
225+
{updated, 1} = sql_to_rdbms(SqlData#{act => <<"DELETE">>, column => <<"">>}),
226+
_ = clear_tables(),
227+
ct:comment("Migration of 'vcard' is successful for Username: ~p", [?USERNAME]);
228+
Any ->
229+
ct:fail("Unexpected result of 'vcard' migration ~p~n", [Any])
230+
end.
139231

140232
%%% ==================================================================
141-
%%% Test case for migrate event_pusher_push_subscription @TODO
233+
%%% Test case for migrate event_pusher_push_subscription
142234
%%% ==================================================================
143235

144236
migrate_event_pusher_push_subscription(Config) ->
145-
?RPC_MIGRATE(<<"event_pusher_push_subscription">>),
146-
ct:comment("TEST CASE ~p", [?FUNCTION_NAME]).
237+
PubsubNode = <<"migration_pub_sub_node">>,
238+
ok = mongoose_helper:successful_rpc(mod_event_pusher_push_mnesia, enable, [?JID, ?JID, PubsubNode, [{<<"name">>, <<"value">>}]]),
239+
{ok, _} = ?RPC_MIGRATE(<<"event_pusher_push_subscription">>),
240+
SqlData = #{table => <<"event_pusher_push_subscription">>, where => <<"node='", PubsubNode/binary, "'">>},
241+
case sql_to_rdbms(SqlData#{act => <<"SELECT">>, column => <<"node">>}) of
242+
{selected, [{PubsubNode}]} ->
243+
{updated, 1} = sql_to_rdbms(SqlData#{act => <<"DELETE">>, column => <<"">>}),
244+
_ = clear_tables(),
245+
ct:comment("Migration of 'event_pusher_push_subscription' is successful for Node: ~p", [PubsubNode]);
246+
Any ->
247+
ct:fail("Unexpected result of 'event_pusher_push_subscription' migration ~p~n", [Any])
248+
end.
147249

148250
%%% ==================================================================
149251
%%% Test case for migrate rosterusers @TODO
@@ -208,3 +310,40 @@ migrate_muc_light_rooms(Config) ->
208310
migrate_all(Config) ->
209311
?RPC_MIGRATE(<<"all">>),
210312
ct:comment("TEST CASE ~p", [?FUNCTION_NAME]).
313+
314+
%%% ==================================================================
315+
%%% Internal functions
316+
%%% ==================================================================
317+
318+
sql_query(Query) ->
319+
slow_rpc(mongoose_rdbms, sql_query, [?NODE_HOST, Query]).
320+
321+
slow_rpc(M, F, A) ->
322+
Node = ct:get_config({hosts, mim, node}),
323+
Cookie = escalus_ct:get_config(ejabberd_cookie),
324+
Res = escalus_rpc:call(Node, M, F, A, timer:seconds(30), Cookie),
325+
case Res of
326+
{badrpc, timeout} ->
327+
{badrpc, {timeout, M, F}};
328+
_ ->
329+
Res
330+
end.
331+
332+
sql_to_rdbms(#{act := Act, column := Column, table := Table, where := Where}) ->
333+
SelectQuery = <<Act/binary, " ", Column/binary, " FROM ", Table/binary, " WHERE ", Where/binary>>,
334+
SelectResult = sql_query(SelectQuery).
335+
336+
clear_tables() ->
337+
Tables = [pubsub_state, pubsub_item, pubsub_node,
338+
pubsub_subscription, pubsub_subnode,
339+
passwd, reg_users_counter,
340+
vcard, vcard_search, push_subscription],
341+
_ = [mongoose_helper:successful_rpc(mod_pubsub_db_mnesia, clear_table, [T]) || T <- Tables].
342+
343+
create_migration_node() ->
344+
{ok, Nidx} = mongoose_helper:successful_rpc(mod_pubsub_db_mnesia, transaction,[#{name => set_node, args => [?BASE_NODE]}]),
345+
ok = mongoose_helper:successful_rpc(mod_pubsub_db_mnesia, transaction,[#{name => create_node, args => [Nidx, ?JID]}]),
346+
Nidx.
347+
348+
set_vcard() ->
349+
mongoose_helper:successful_rpc(mod_vcard_mnesia, set_vcard, [?USERNAME, <<"localhost">>, ?BASE_VCARD, ?BASE_SEARCH_VCARD]).

src/admin_extra/service_admin_extra_migration.erl

+4-1
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ try_migrate({Act, Table}) when is_atom(Table) ->
157157

158158
try_migrate({Act, Table, TableData}) ->
159159
case TableData of
160+
{ok, [_] = Data, '$end_of_table'} ->
161+
?MODULE:(list_to_existing_atom("migrate_" ++ binary_to_list(Act)))(Data),
162+
{ok, io_lib:format("Completed the migration of the table: '~s'", [Act])};
160163
{ok, _, '$end_of_table'} ->
161164
{ok, io_lib:format("Completed the migration of the table: '~s'", [Act])};
162165
{ok, Data, NextKey} ->
@@ -276,7 +279,7 @@ migrate_pubsub_items([H|_]) ->
276279
Cols = ["nidx", "itemid", "created_luser", "created_lserver", "created_at",
277280
"modified_luser", "modified_lserver", "modified_lresource", "modified_at", "payload"],
278281
Vals = [NodeIdx, IID, JID#jid.luser, JID#jid.lserver, CT, JID#jid.lserver,
279-
JID#jid.lserver, JID#jid.lresource, CT, XMLB],
282+
JID#jid.lserver, JID#jid.lresource, CT, XMLB],
280283
Q = ["INSERT INTO pubsub_items ", expand_sql_vals(Cols, Vals), ";"],
281284
case mongoose_rdbms:sql_query(?MYNAME, Q) of
282285
{error, Reason} ->

src/pubsub/mod_pubsub_db_mnesia.erl

+11-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
-export([start/0, stop/0]).
1919
% Funs execution
20-
-export([transaction/2, dirty/2]).
20+
-export([clear_table/1, transaction/1, transaction/2, dirty/2]).
2121
% Direct #pubsub_state access
2222
-export([del_node/1, get_state/2,
2323
get_states/1, get_states_by_lus/1, get_states_by_bare/1,
@@ -134,6 +134,16 @@ maybe_fill_subnode_table(_Other) ->
134134

135135
%% ------------------------ Fun execution ------------------------
136136

137+
-spec clear_table(atom()) ->
138+
{atomic, ok} | {aborted, term()}.
139+
clear_table(Tab) ->
140+
mnesia:clear_table(Tab).
141+
142+
-spec transaction(map()) ->
143+
{result | error, any()}.
144+
transaction(#{name := Name, args := Args}) ->
145+
transaction(fun() -> apply(?MODULE, Name, Args) end, #{}).
146+
137147
-spec transaction(Fun :: fun(() -> {result | error, any()}),
138148
ErrorDebug :: map()) ->
139149
{result | error, any()}.

0 commit comments

Comments
 (0)