Skip to content

Commit 76b2594

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 76b2594

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,32 @@
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,<<"Ooooooooooo">>}]},
27+
28+
{xmlel,<<"TEL">>,[],
29+
[{xmlel,<<"HOME">>,[],[]},
30+
{xmlel,<<"VOICE">>,[],[]},
31+
{xmlel,<<"NUMBER">>,[],
32+
[{xmlcdata,<<"+00000000000">>}]}]}]}).
33+
-define(BASE_SEARCH_VCARD, {vcard_search, {<<"migration_user">>, <<"localhost">>}, <<?USERNAME/binary, "@localhost/test">>, ?USERNAME, <<"fn">>, <<"lfn">>, <<"family">>,
34+
<<"lfamily">>, <<"given">>, <<"lgiven">>, <<"middle">>, <<"lmiddle">>, <<"nickname">>, <<"lnickname">>, <<"bday">>, <<"lbday">>,
35+
<<"ctry">>, <<"lctry">>, <<"locality">>, <<"llocality">>, <<"email">>, <<"lemail">>, <<"orgname">>, <<"lorgname">>, <<"orgunit">>,
36+
<<"lorgunit">>}).
1837

1938
%%--------------------------------------------------------------------
2039
%% Suite configuration
2140
%%--------------------------------------------------------------------
2241

2342
all() ->
24-
case (not ct_helper:is_ct_running()) orelse mongoose_helper:is_rdbms_enabled(ct:get_config({hosts, mim, domain})) of
43+
case (not ct_helper:is_ct_running()) orelse mongoose_helper:is_rdbms_enabled(?NODE_HOST) of
2544
true ->
2645
tests();
2746
false ->
@@ -63,9 +82,18 @@ suite() ->
6382
escalus:suite().
6483

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

6894
end_per_suite(Config) ->
95+
ok = mongoose_helper:successful_rpc(ejabberd_auth_internal, stop, [?NODE_HOST]),
96+
_ = mnesia:stop(),
6997
escalus_fresh:clean(),
7098
escalus:end_per_suite(Config).
7199

@@ -82,68 +110,143 @@ end_per_testcase(CaseName, Config) ->
82110
escalus:end_per_testcase(CaseName, Config).
83111

84112
%%% ==================================================================
85-
%%% Test case for migrate pubsub_nodes @TODO
113+
%%% Test case for migrate pubsub_nodes
86114
%%% ==================================================================
87115

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

92129
%%% ==================================================================
93-
%%% Test case for migrate pubsub_subscriptions @TODO
130+
%%% Test case for migrate pubsub_subscriptions
94131
%%% ==================================================================
95132

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

100147
%%% ==================================================================
101-
%%% Test case for migrate pubsub_affiliations @TODO
148+
%%% Test case for migrate pubsub_affiliations
102149
%%% ==================================================================
103150

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

108164
%%% ==================================================================
109-
%%% Test case for migrate pubsub_items @TODO
165+
%%% Test case for migrate pubsub_items
110166
%%% ==================================================================
111167

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

116182
%%% ==================================================================
117-
%%% Test case for migrate users @TODO
183+
%%% Test case for migrate users
118184
%%% ==================================================================
119185

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

124199
%%% ==================================================================
125-
%%% Test case for migrate vcard_search @TODO
200+
%%% Test case for migrate vcard_search
126201
%%% ==================================================================
127202

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

132216
%%% ==================================================================
133-
%%% Test case for migrate vcard @TODO
217+
%%% Test case for migrate vcard
134218
%%% ==================================================================
135219

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

140233
%%% ==================================================================
141-
%%% Test case for migrate event_pusher_push_subscription @TODO
234+
%%% Test case for migrate event_pusher_push_subscription
142235
%%% ==================================================================
143236

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

148251
%%% ==================================================================
149252
%%% Test case for migrate rosterusers @TODO
@@ -208,3 +311,39 @@ migrate_muc_light_rooms(Config) ->
208311
migrate_all(Config) ->
209312
?RPC_MIGRATE(<<"all">>),
210313
ct:comment("TEST CASE ~p", [?FUNCTION_NAME]).
314+
315+
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)