Skip to content

Commit

Permalink
Improve error handling in mnesia API
Browse files Browse the repository at this point in the history
  • Loading branch information
jacekwegr committed Dec 9, 2022
1 parent 2567190 commit af3b39c
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 58 deletions.
31 changes: 27 additions & 4 deletions big_tests/tests/graphql_mnesia_SUITE.erl
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
-module(graphql_mnesia_SUITE).
-include_lib("eunit/include/eunit.hrl").
-include_lib("common_test/include/ct.hrl").

-compile([export_all, nowarn_export_all]).

-import(distributed_helper, [require_rpc_nodes/1, mim/0, mim2/0, rpc/4]).
-import(domain_helper, [host_type/1]).
-import(mongooseimctl_helper, [rpc_call/3]).
-import(graphql_helper, [execute_command/4, execute_user_command/5, user_to_bin/1,
get_ok_value/2, get_err_code/1, get_err_value/2, get_unauthorized/1]).
get_ok_value/2, get_err_code/1, get_err_value/2, get_unauthorized/1,
get_coercion_err_msg/1]).

-record(mnesia_table_test, {key :: integer(), name :: binary()}).
-record(vcard, {us, vcard}).
Expand All @@ -33,17 +33,20 @@ admin_mnesia_tests() ->
backup_wrong_filename_test,
restore_no_file_test,
restore_wrong_file_format_test,
restore_bad_file_test,
load_mnesia_test,
load_mnesia_no_file_test,
load_mnesia_bad_file_test,
load_mnesia_bad_file2_test,
change_nodename_test,
change_nodename_incorrect_name,
change_nodename_no_file_error_test,
change_nodename_bad_file_error_test,
get_info_test,
get_all_info_test,
install_fallback_error_test,
set_master_test].
set_master_test,
set_incorrect_master_test].

domain_admin_tests() ->
[domain_admin_dump_mnesia_table_test,
Expand Down Expand Up @@ -136,6 +139,10 @@ restore_no_file_test(Config) ->
Res = restore_mnesia(<<>>, Config),
?assertEqual(<<"file_not_found">>, get_err_code(Res)).

restore_bad_file_test(Config) ->
Res = restore_mnesia(<<"NON_EXISTING">>, Config),
?assertEqual(<<"file_not_found">>, get_err_code(Res)).

restore_wrong_file_format_test(Config) ->
Filename = <<"restore_error">>,
FileFullPath = create_full_filename(Filename),
Expand Down Expand Up @@ -185,6 +192,14 @@ change_nodename_test(Config) ->
check_if_response_contains(Value,
<<"Name of the node in the backup was successfully changed">>).

change_nodename_incorrect_name(Config) ->
Filename1 = <<"change_incorrect_nodename_mnesia_test">>,
Filename2 = <<"change_incorrect_nodename2_mnesia_test">>,
ChangeFrom = <<"mongooseim@localhost">>,
ChangeTo = <<"incorrect_format">>,
Value = change_nodename(ChangeFrom, ChangeTo, Filename1, Filename2, Config),
get_coercion_err_msg(Value).

change_nodename_no_file_error_test(Config) ->
Filename1 = <<"non_existing">>,
Filename2 = <<"change_nodename2_mnesia_test">>,
Expand Down Expand Up @@ -232,6 +247,10 @@ set_master_test(Config) ->
ParsedRes = get_ok_value([data, mnesia, setMaster], set_master(mim(), Config)),
?assertEqual(<<"Master node set">>, ParsedRes).

set_incorrect_master_test(Config) ->
Res = set_master(#{node => incorrect_name}, Config),
get_coercion_err_msg(Res).

% Domain admin tests

domain_admin_dump_mnesia_table_test(Config) ->
Expand All @@ -250,7 +269,11 @@ domain_admin_load_mnesia_test(Config) ->
get_unauthorized(load_mnesia(<<"Path">>, Config)).

domain_admin_change_nodename_test(Config) ->
get_unauthorized(change_nodename(<<"From">>, <<"To">>, <<"file1">>, <<"file2">>, Config)).
Filename1 = <<"change_nodename_mnesia_test">>,
Filename2 = <<"change_nodename2_mnesia_test">>,
ChangeFrom = <<"mongooseim@localhost">>,
ChangeTo = <<"change_nodename_test@localhost">>,
get_unauthorized(change_nodename(ChangeFrom, ChangeTo, Filename1, Filename2, Config)).

domain_admin_install_fallback_test(Config) ->
get_unauthorized(install_fallback(<<"Path">>, Config)).
Expand Down
4 changes: 2 additions & 2 deletions priv/graphql/schemas/admin/mnesia.gql
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ Allow admin to backup, dump, load, restore and modify mnesia database
"""
type MnesiaAdminMutation @protected{
"Set mnesia's master node"
setMaster(node: String!): String
setMaster(node: NodeName!): String
@protected(type: GLOBAL)
"Change nodename from 'fromString' to 'toString' in 'source' backup file and create new 'target' backup file"
changeNodename(fromString: String!, toString: String!,
changeNodename(fromString: NodeName!, toString: NodeName!,
source: String!, target: String!): String
@protected(type: GLOBAL)
"Save mnesia backup to file 'path'"
Expand Down
2 changes: 2 additions & 0 deletions priv/graphql/schemas/global/scalar_types.gql
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ scalar RoomName @spectaql(options: [{ key: "example", value: "my-chat-room" }])
scalar DomainName @spectaql(options: [{ key: "example", value: "localhost" }])
"XMPP resource name (resource part of a JID)"
scalar ResourceName @spectaql(options: [{ key: "example", value: "res1" }])
"Name of the Erlang node"
scalar NodeName @spectaql(options: [{key: "example", value: "mynode@localhost"}])
"String that contains at least one character"
scalar NonEmptyString @spectaql(options: [{ key: "example", value: "xyz789" }])
"Integer that has a value above zero"
Expand Down
20 changes: 9 additions & 11 deletions src/graphql/admin/mongoose_graphql_mnesia_admin_mutation.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,49 @@

-export([execute/4]).

-import(mongoose_graphql_helper, [make_error/2]).
-import(mongoose_graphql_helper, [make_error/2, make_error/3]).

-ignore_xref([execute/4]).

-include("../mongoose_graphql_types.hrl").
-include("mongoose.hrl").
-include("jlib.hrl").

execute(_Ctx, mnesia, <<"setMaster">>, #{<<"node">> := Node}) ->
case mnesia_api:set_master(binary_to_list(Node)) of
{ok, _} -> {ok, "Master node set"};
{error, Reason} -> make_error({error, Reason}, #{node => Node})
Error -> make_error(Error, #{node => Node})
end;
execute(_Ctx, mnesia, <<"backup">>, #{<<"path">> := Path}) ->
case mnesia_api:backup_mnesia(binary_to_list(Path)) of
{ok, _} -> {ok, "Mnesia backup was successfully created"};
{error, Error} -> make_error(Error, #{path => Path})
Error -> make_error(Error, #{path => Path})
end;
execute(_Ctx, mnesia, <<"changeNodename">>, #{<<"fromString">> := FromString,
<<"toString">> := ToString, <<"source">> := Source, <<"target">> := Target}) ->
case mnesia_api:mnesia_change_nodename(binary_to_list(FromString), binary_to_list(ToString),
binary_to_list(Source), binary_to_list(Target)) of
{ok, _} -> {ok, "Name of the node in the backup was successfully changed"};
{error, Error} -> make_error(Error, #{fromString => FromString, toString => ToString,
source => Source, target => Target})
Error -> make_error(Error, #{fromString => FromString, toString => ToString,
source => Source, target => Target})
end;
execute(_Ctx, mnesia, <<"restore">>, #{<<"path">> := Path}) ->
case mnesia_api:restore_mnesia(binary_to_list(Path)) of
{ok, _} -> {ok, "Mnesia was successfully restored"};
{error, Error} -> make_error(Error, #{path => Path})
Error -> make_error(Error, #{path => Path})
end;
execute(_Ctx, mnesia, <<"dump">>, #{<<"path">> := Path}) ->
case mnesia_api:dump_mnesia(binary_to_list(Path)) of
{ok, _} -> {ok, "Mnesia successfully dumped"};
{error, Error} -> make_error(Error, #{path => Path})
Error -> make_error(Error, #{path => Path})
end;
execute(_Ctx, mnesia, <<"dumpTable">>, #{<<"path">> := Path, <<"table">> := Table}) ->
case mnesia_api:dump_table(binary_to_list(Path), binary_to_list(Table)) of
{ok, _} -> {ok, "Mnesia table successfully dumped"};
{error, Error} -> make_error(Error, #{path => Path, table => Table})
Error -> make_error(Error, #{path => Path, table => Table})
end;
execute(_Ctx, mnesia, <<"load">>, #{<<"path">> := Path}) ->
case mnesia_api:load_mnesia(binary_to_list(Path)) of
{ok, _} -> {ok, "Mnesia was successfully loaded"};
{error, Error} -> make_error(Error, #{path => Path})
Error -> make_error(Error, #{path => Path})
end;
execute(_Ctx, mnesia, <<"installFallback">>, #{<<"path">> := Path}) ->
case mnesia_api:install_fallback_mnesia(binary_to_list(Path)) of
Expand Down
4 changes: 1 addition & 3 deletions src/graphql/admin/mongoose_graphql_mnesia_admin_query.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
-ignore_xref([execute/4]).

-include("../mongoose_graphql_types.hrl").
-include("mongoose.hrl").
-include("jlib.hrl").

execute(_Ctx, mnesia, <<"systemInfo">>, #{<<"keys">> := Keys}) ->
ResultList = mnesia_api:mnesia_info(Keys),
{ok, ResultList} = mnesia_api:mnesia_info(Keys),
{ok, lists:map(fun process_result/1, ResultList)}.

process_result({ok, _} = Result) -> Result;
Expand Down
11 changes: 11 additions & 0 deletions src/graphql/mongoose_graphql_scalar.erl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ input(<<"UserName">>, User) -> user_from_binary(User);
input(<<"RoomName">>, Room) -> room_from_binary(Room);
input(<<"DomainName">>, Domain) -> domain_from_binary(Domain);
input(<<"ResourceName">>, Res) -> resource_from_binary(Res);
input(<<"NodeName">>, Node) -> node_from_binary(Node);
input(<<"NonEmptyString">>, Value) -> non_empty_string_to_binary(Value);
input(<<"PosInt">>, Value) -> validate_pos_integer(Value);
input(<<"NonNegInt">>, Value) -> validate_non_neg_integer(Value);
Expand Down Expand Up @@ -119,6 +120,16 @@ resource_from_binary(Value) ->
{ok, Res}
end.

node_from_binary(<<>>) ->
{error, empty_node_name};
node_from_binary(NodeName) ->
case string:lexemes(binary_to_list(NodeName), "@") of
[_Name, _Host] ->
{ok, NodeName};
_ ->
{error, incorrect_node_name}
end.

binary_to_microseconds(DT) ->
case mod_mam_utils:maybe_microseconds(DT) of
undefined ->
Expand Down
Loading

0 comments on commit af3b39c

Please sign in to comment.