1: -module(graphql_mnesia_SUITE).
    2: -include_lib("eunit/include/eunit.hrl").
    3: 
    4: -compile([export_all, nowarn_export_all]).
    5: 
    6: -import(distributed_helper, [require_rpc_nodes/1, mim/0, mim2/0, rpc/4]).
    7: -import(domain_helper, [host_type/1]).
    8: -import(mongooseimctl_helper, [rpc_call/3]).
    9: -import(graphql_helper, [execute_command/4, execute_user_command/5, user_to_bin/1,
   10:                          get_ok_value/2, get_err_code/1, get_err_value/2, get_unauthorized/1,
   11:                          get_coercion_err_msg/1, get_not_loaded/1]).
   12: 
   13: -record(mnesia_table_test, {key :: integer(), name :: binary()}).
   14: -record(vcard, {us, vcard}).
   15: 
   16: all() ->
   17:     [{group, admin_mnesia_cli},
   18:      {group, admin_mnesia_http},
   19:      {group, domain_admin_mnesia},
   20:      {group, mnesia_not_configured}].
   21: 
   22: groups() ->
   23:     [{admin_mnesia_http, [sequence], admin_mnesia_tests()},
   24:      {admin_mnesia_cli, [sequence], admin_mnesia_tests()},
   25:      {domain_admin_mnesia, [], domain_admin_tests()},
   26:      {mnesia_not_configured, [parallel], mnesia_not_configured_tests()}].
   27: 
   28: admin_mnesia_tests() ->
   29:     [dump_mnesia_table_test,
   30:      dump_mnesia_table_file_error_test,
   31:      dump_mnesia_table_no_table_error_test,
   32:      dump_mnesia_test,
   33:      dump_mnesia_file_error_test,
   34:      backup_and_restore_test,
   35:      backup_wrong_filename_test,
   36:      backup_wrong_path_test,
   37:      restore_no_file_test,
   38:      restore_wrong_file_format_test,
   39:      restore_bad_file_test,
   40:      restore_bad_path_test,
   41:      load_mnesia_test,
   42:      load_mnesia_no_file_test,
   43:      load_mnesia_bad_file_test,
   44:      load_mnesia_bad_file2_test,
   45:      change_nodename_test,
   46:      change_nodename_bad_name,
   47:      change_nodename_empty_name,
   48:      change_nodename_no_file_error_test,
   49:      change_nodename_bad_file_error_test,
   50:      get_info_test,
   51:      get_all_info_test,
   52:      install_fallback_error_test,
   53:      set_master_test,
   54:      set_master_self_test,
   55:      set_master_bad_name_test,
   56:      set_master_empty_name_test].
   57: 
   58: domain_admin_tests() ->
   59:     [domain_admin_dump_mnesia_table_test,
   60:      domain_admin_dump_mnesia_test,
   61:      domain_admin_backup_test,
   62:      domain_admin_restore_test,
   63:      domain_admin_load_mnesia_test,
   64:      domain_admin_change_nodename_test,
   65:      domain_admin_install_fallback_test,
   66:      domain_admin_set_master_test,
   67:      domain_admin_get_info_test].
   68: 
   69: mnesia_not_configured_tests() ->
   70:     [backup_not_configured_test,
   71:      change_nodename_not_configured_test,
   72:      dump_not_configured_test,
   73:      dump_table_not_configured_test,
   74:      install_fallback_not_configured_test,
   75:      load_not_configured_test,
   76:      restore_not_configured_test,
   77:      set_master_not_configured_test,
   78:      system_info_not_configured_test
   79:     ].
   80: 
   81: init_per_suite(Config) ->
   82:     application:ensure_all_started(jid),
   83:     ok = mnesia:create_schema([node()]),
   84:     ok = mnesia:start(),
   85:     Config1 = escalus:init_per_suite(Config),
   86:     ejabberd_node_utils:init(mim(), Config1).
   87: 
   88: end_per_suite(_C) ->
   89:     mnesia:stop(),
   90:     mnesia:delete_schema([node()]).
   91: 
   92: init_per_group(admin_mnesia_http, Config) ->
   93:     Config1 = graphql_helper:init_admin_handler(Config),
   94:     skip_if_mnesia_not_configured(Config1);
   95: init_per_group(admin_mnesia_cli, Config) ->
   96:     Config1 = graphql_helper:init_admin_cli(Config),
   97:     skip_if_mnesia_not_configured(Config1);
   98: init_per_group(domain_admin_mnesia, Config) ->
   99:     Config1 = graphql_helper:init_domain_admin_handler(Config),
  100:     skip_if_mnesia_not_configured(Config1);
  101: init_per_group(mnesia_not_configured, Config) ->
  102:     case rpc_call(mongoose_config, lookup_opt, [[internal_databases, mnesia]]) of
  103:         {error, not_found} ->
  104:             graphql_helper:init_admin_handler(Config);
  105:         {ok, _} ->
  106:             {skip, "Mnesia is configured"}
  107:     end.
  108: end_per_group(_, _Config) ->
  109:     graphql_helper:clean(),
  110:     escalus_fresh:clean().
  111: 
  112: skip_if_mnesia_not_configured(Config) ->
  113:     case rpc_call(mongoose_config, lookup_opt, [[internal_databases, mnesia]]) of
  114:         {error, not_found} ->
  115:             {skip, "Mnesia is not configured"};
  116:         {ok, _} ->
  117:             Config
  118:     end.
  119: 
  120: % Admin tests
  121: 
  122: dump_mnesia_table_test(Config) ->
  123:     Filename = <<"dump_mnesia_table_test">>,
  124:     create_mnesia_table_and_write([{attributes, record_info(fields, mnesia_table_test)}]),
  125:     Res = dump_mnesia_table(Filename, <<"mnesia_table_test">>, Config),
  126:     ParsedRes = get_ok_value([data, mnesia, dumpTable], Res),
  127:     ?assertEqual(<<"Mnesia table successfully dumped">>, ParsedRes),
  128:     delete_mnesia_table(),
  129:     check_created_file(create_full_filename(Filename), <<"{mnesia_table_test,1,<<\"TEST\">>}">>).
  130: 
  131: dump_mnesia_table_file_error_test(Config) ->
  132:     Res = dump_mnesia_table(<<>>, <<"vcard">>, Config),
  133:     ?assertEqual(<<"file_error">>, get_err_code(Res)).
  134: 
  135: dump_mnesia_table_no_table_error_test(Config) ->
  136:     Res = dump_mnesia_table(<<"AA">>, <<"NON_EXISTING">>, Config),
  137:     ?assertEqual(<<"table_does_not_exist">>, get_err_code(Res)).
  138: 
  139: dump_mnesia_test(Config) ->
  140:     Filename = <<"dump_mnesia_test">>,
  141:     create_mnesia_table_and_write([{disc_copies, [maps:get(node, mim())]},
  142:                                    {attributes, record_info(fields, mnesia_table_test)}]),
  143:     Res = dump_mnesia(Filename, Config),
  144:     ParsedRes = get_ok_value([data, mnesia, dump], Res),
  145:     ?assertEqual(<<"Mnesia successfully dumped">>, ParsedRes),
  146:     delete_mnesia_table(),
  147:     check_created_file(create_full_filename(Filename), <<"{mnesia_table_test,1,<<\"TEST\">>}">>).
  148: 
  149: dump_mnesia_file_error_test(Config) ->
  150:     Res = dump_mnesia(<<>>, Config),
  151:     ?assertEqual(<<"file_error">>, get_err_code(Res)).
  152: 
  153: backup_and_restore_test(Config) ->
  154:     Filename = <<"backup_restore_mnesia_test">>,
  155:     create_vcard_table(),
  156:     write_to_vcard(),
  157:     ?assert(is_record_in_vcard_table()),
  158:     Res = backup_mnesia(Filename, Config),
  159:     ParsedRes = get_ok_value([data, mnesia, backup], Res),
  160:     ?assertEqual(<<"Mnesia backup was successfully created">>, ParsedRes),
  161:     delete_record_from_table(),
  162:     ?assertEqual(false, is_record_in_vcard_table()),
  163:     Res2 = restore_mnesia(Filename, Config),
  164:     ParsedRes2 = get_ok_value([data, mnesia, restore], Res2),
  165:     ?assertEqual(<<"Mnesia was successfully restored">>, ParsedRes2),
  166:     ?assert(is_record_in_vcard_table()),
  167:     delete_record_from_table(),
  168:     delete_file(create_full_filename(Filename)).
  169: 
  170: backup_wrong_filename_test(Config) ->
  171:     Res = backup_mnesia(<<>>, Config),
  172:     ?assertEqual(<<"wrong_filename">>, get_err_code(Res)).
  173: 
  174: backup_wrong_path_test(Config) ->
  175:     Res = backup_mnesia(<<"/etc/">>, Config),
  176:     ?assertEqual(<<"cannot_backup">>, get_err_code(Res)).
  177: 
  178: restore_no_file_test(Config) ->
  179:     Res = restore_mnesia(<<>>, Config),
  180:     ?assertEqual(<<"file_not_found">>, get_err_code(Res)).
  181: 
  182: restore_bad_file_test(Config) ->
  183:     Res = restore_mnesia(<<"NON_EXISTING">>, Config),
  184:     ?assertEqual(<<"file_not_found">>, get_err_code(Res)).
  185: 
  186: restore_bad_path_test(Config) ->
  187:     Res = restore_mnesia(<<"/etc/">>, Config),
  188:     ?assertEqual(<<"cannot_restore">>, get_err_code(Res)).
  189: 
  190: restore_wrong_file_format_test(Config) ->
  191:     Filename = <<"restore_error">>,
  192:     FileFullPath = create_full_filename(Filename),
  193:     create_file(FileFullPath),
  194:     Res = restore_mnesia(Filename, Config),
  195:     delete_file(Filename),
  196:     ?assertEqual(<<"not_a_log_file_error">>, get_err_code(Res)).
  197: 
  198: load_mnesia_test(Config) ->
  199:     Filename = <<"load_mnesia_test">>,
  200:     create_mnesia_table_and_write([{disc_copies, [maps:get(node, mim())]},
  201:                                    {attributes, record_info(fields, mnesia_table_test)}]),
  202:     Res = dump_mnesia(Filename, Config),
  203:     ParsedRes = get_ok_value([data, mnesia, dump], Res),
  204:     ?assertEqual(<<"Mnesia successfully dumped">>, ParsedRes),
  205:     delete_mnesia_table(),
  206:     check_if_response_contains(load_mnesia(Filename, Config), <<"Mnesia was successfully loaded">>),
  207:     ?assert(is_record_in_table()),
  208:     delete_mnesia_table().
  209: 
  210: load_mnesia_bad_file_test(Config) ->
  211:     Filename = <<"EXISTING_BUT_EMPTY">>,
  212:     create_file(create_full_filename(Filename)),
  213:     check_if_response_contains(load_mnesia(Filename, Config), <<"bad_file_format">>).
  214: 
  215: load_mnesia_bad_file2_test(Config) ->
  216:     Filename = <<"EXISTING_FILE">>,
  217:     create_and_write_file(create_full_filename(Filename)),
  218:     check_if_response_contains(load_mnesia(Filename, Config), <<"bad_file_format">>).
  219: 
  220: load_mnesia_no_file_test(Config) ->
  221:     Filename = <<"NON_EXISTING">>,
  222:     check_if_response_contains(load_mnesia(Filename, Config), <<"file_not_found">>).
  223: 
  224: change_nodename_test(Config) ->
  225:     Filename1 = <<"change_nodename_mnesia_test">>,
  226:     Filename2 = <<"change_nodename2_mnesia_test">>,
  227:     create_vcard_table(),
  228:     write_to_vcard(),
  229:     ?assert(is_record_in_vcard_table()),
  230:     Res = backup_mnesia(Filename1, Config),
  231:     ParsedRes = get_ok_value([data, mnesia, backup], Res),
  232:     ?assertEqual(<<"Mnesia backup was successfully created">>, ParsedRes),
  233:     ChangeFrom = <<"mongooseim@localhost">>,
  234:     ChangeTo = <<"change_nodename_test@localhost">>,
  235:     Value = change_nodename(ChangeFrom, ChangeTo, Filename1, Filename2, Config),
  236:     check_if_response_contains(Value,
  237:         <<"Name of the node in the backup was successfully changed">>).
  238: 
  239: change_nodename_bad_name(Config) ->
  240:     Filename1 = <<"change_incorrect_nodename_mnesia_test">>,
  241:     Filename2 = <<"change_incorrect_nodename2_mnesia_test">>,
  242:     ChangeFrom = <<"mongooseim@localhost">>,
  243:     ChangeTo = <<"incorrect_format">>,
  244:     Value = change_nodename(ChangeFrom, ChangeTo, Filename1, Filename2, Config),
  245:     get_coercion_err_msg(Value).
  246: 
  247: change_nodename_empty_name(Config) ->
  248:     Filename1 = <<"change_incorrect_nodename_mnesia_test">>,
  249:     Filename2 = <<"change_incorrect_nodename2_mnesia_test">>,
  250:     ChangeFrom = <<"mongooseim@localhost">>,
  251:     ChangeTo = <<>>,
  252:     Value = change_nodename(ChangeFrom, ChangeTo, Filename1, Filename2, Config),
  253:     get_coercion_err_msg(Value).
  254: 
  255: change_nodename_no_file_error_test(Config) ->
  256:     Filename1 = <<"non_existing">>,
  257:     Filename2 = <<"change_nodename2_mnesia_test">>,
  258:     ChangeFrom = <<"mongooseim@localhost">>,
  259:     ChangeTo = <<"change_nodename_test@localhost">>,
  260:     Value = change_nodename(ChangeFrom, ChangeTo, Filename1, Filename2, Config),
  261:     ?assertEqual(<<"file_not_found">>, get_err_code(Value)).
  262: 
  263: change_nodename_bad_file_error_test(Config) ->
  264:     Filename1 = <<"existing_but_having_wrong_structure">>,
  265:     Filename2 = <<"change_nodename2_mnesia_test">>,
  266:     create_and_write_file(create_full_filename(Filename1)),
  267:     ChangeFrom = <<"mongooseim@localhost">>,
  268:     ChangeTo = <<"change_nodename_test@localhost">>,
  269:     Value = change_nodename(ChangeFrom, ChangeTo, Filename1, Filename2, Config),
  270:     ?assertEqual(<<"bad_file_format">>, get_err_code(Value)).
  271: 
  272: get_info_test(Config) ->
  273:     Res = get_info(maps:keys(mnesia_info_check()) ++ [<<"AAA">>], Config),
  274:     ?assertEqual(<<"bad_key_error">>, get_err_code(Res)),
  275:     ParsedRes = get_err_value([data, mnesia, systemInfo], Res),
  276:     Map = mnesia_info_check(),
  277:     lists:foreach(fun
  278:         (#{<<"result">> := Element, <<"key">> := Key}) ->
  279:             Fun = maps:get(Key, Map),
  280:             ?assertEqual({true, Element, Key, Fun}, {?MODULE:Fun(Element), Element, Key, Fun});
  281:         (null) ->
  282:             ok
  283:     end, ParsedRes).
  284: 
  285: get_all_info_test(Config) ->
  286:     Res = get_info(null, Config),
  287:     ParsedRes = get_ok_value([data, mnesia, systemInfo], Res),
  288:     Map = mnesia_info_check(),
  289:     lists:foreach(fun (#{<<"result">> := Element, <<"key">> := Key}) ->
  290:         Fun = maps:get(Key, Map),
  291:         ?assertEqual({true, Element, Key, Fun}, {?MODULE:Fun(Element), Element, Key, Fun})
  292:     end, ParsedRes).
  293: 
  294: install_fallback_error_test(Config) ->
  295:     Res = install_fallback(<<"AAAA">>, Config),
  296:     ?assertEqual(<<"cannot_fallback">>, get_err_code(Res)).
  297: 
  298: set_master_test(Config) ->
  299:     ParsedRes = get_ok_value([data, mnesia, setMaster], set_master(mim(), Config)),
  300:     ?assertEqual(<<"Master node set">>, ParsedRes).
  301: 
  302: set_master_self_test(Config) ->
  303:     ParsedRes = get_ok_value([data, mnesia, setMaster], set_master(#{node => self}, Config)),
  304:     ?assertEqual(<<"Master node set">>, ParsedRes).
  305: 
  306: set_master_bad_name_test(Config) ->
  307:     Res = set_master(#{node => incorrect_name}, Config),
  308:     get_coercion_err_msg(Res).
  309: 
  310: set_master_empty_name_test(Config) ->
  311:     Res = set_master(#{node => ''}, Config),
  312:     get_coercion_err_msg(Res).
  313: 
  314: % Domain admin tests
  315: 
  316: domain_admin_dump_mnesia_table_test(Config) ->
  317:     get_unauthorized(dump_mnesia_table(<<"File">>, <<"mnesia_table_test">>, Config)).
  318: 
  319: domain_admin_dump_mnesia_test(Config) ->
  320:     get_unauthorized(dump_mnesia(<<"File">>, Config)).
  321: 
  322: domain_admin_backup_test(Config) ->
  323:     get_unauthorized(backup_mnesia(<<"Path">>, Config)).
  324: 
  325: domain_admin_restore_test(Config) ->
  326:     get_unauthorized(restore_mnesia(<<"Path">>, Config)).
  327: 
  328: domain_admin_load_mnesia_test(Config) ->
  329:     get_unauthorized(load_mnesia(<<"Path">>, Config)).
  330: 
  331: domain_admin_change_nodename_test(Config) ->
  332:     Filename1 = <<"change_nodename_mnesia_test">>,
  333:     Filename2 = <<"change_nodename2_mnesia_test">>,
  334:     ChangeFrom = <<"mongooseim@localhost">>,
  335:     ChangeTo = <<"change_nodename_test@localhost">>,
  336:     get_unauthorized(change_nodename(ChangeFrom, ChangeTo, Filename1, Filename2, Config)).
  337: 
  338: domain_admin_install_fallback_test(Config) ->
  339:     get_unauthorized(install_fallback(<<"Path">>, Config)).
  340: 
  341: domain_admin_set_master_test(Config) ->
  342:     get_unauthorized(set_master(mim(), Config)).
  343: 
  344: domain_admin_get_info_test(Config) ->
  345:     get_unauthorized(get_info([<<"running_db_nodes">>], Config)).
  346: 
  347: backup_not_configured_test(Config) ->
  348:     Filename = <<"backup_not_configured_test">>,
  349:     get_not_loaded(backup_mnesia(Filename, Config)).
  350: 
  351: change_nodename_not_configured_test(Config) ->
  352:     Filename1 = <<"change_nodename_not_configured_test">>,
  353:     Filename2 = <<"change_nodename2_not_configured_test">>,
  354:     ChangeFrom = <<"mongooseim@localhost">>,
  355:     ChangeTo = <<"change_nodename_not_configured_test@localhost">>,
  356:     get_not_loaded(change_nodename(ChangeFrom, ChangeTo, Filename1, Filename2, Config)).
  357: 
  358: dump_not_configured_test(Config) ->
  359:     get_not_loaded(dump_mnesia(<<"File">>, Config)).
  360: 
  361: dump_table_not_configured_test(Config) ->
  362:     get_not_loaded(dump_mnesia_table(<<"File">>, <<"mnesia_table_test">>, Config)).
  363: 
  364: install_fallback_not_configured_test(Config) ->
  365:     get_not_loaded(install_fallback(<<"Path">>, Config)).
  366: 
  367: load_not_configured_test(Config) ->
  368:     get_not_loaded(load_mnesia(<<"Path">>, Config)).
  369: 
  370: restore_not_configured_test(Config) ->
  371:     get_not_loaded(restore_mnesia(<<"Path">>, Config)).
  372: 
  373: set_master_not_configured_test(Config) ->
  374:     get_not_loaded(set_master(mim(), Config)).
  375: 
  376: system_info_not_configured_test(Config) ->
  377:     get_not_loaded(get_info([<<"running_db_nodes">>], Config)).
  378: 
  379: %--------------------------------------------------------------------------------------------------
  380: %                                         Helpers
  381: %--------------------------------------------------------------------------------------------------
  382: 
  383: create_mnesia_table_and_write(Attrs) ->
  384:     rpc_call(mnesia, delete_table, [mnesia_table_test]),
  385:     {atomic, ok} = rpc_call(mnesia, create_table, [mnesia_table_test, Attrs]),
  386:     rpc_call(mnesia, dirty_write,
  387:         [mnesia_table_test, #mnesia_table_test{key = 1, name = <<"TEST">>}]).
  388: 
  389: create_vcard_table() ->
  390:     rpc_call(mnesia, delete_table, [vcard]),
  391:     rpc_call(mnesia, create_table, [vcard, [{disc_copies, [maps:get(node, mim())]},
  392:                                             {attributes, record_info(fields, vcard)}]]).
  393: 
  394: write_to_vcard() ->
  395:     rpc_call(mnesia, dirty_write, [vcard, #vcard{us = 1, vcard = <<"TEST">>}]).
  396: 
  397: is_record_in_table() ->
  398:     Expected = [#mnesia_table_test{key = 1, name = <<"TEST">>}],
  399:     Record = rpc_call(mnesia, dirty_read, [mnesia_table_test, 1]),
  400:     Expected == Record.
  401: 
  402: is_record_in_vcard_table() ->
  403:     Expected = [#vcard{us = 1, vcard = <<"TEST">>}],
  404:     Record = rpc_call(mnesia, dirty_read, [vcard, 1]),
  405:     Expected == Record.
  406: 
  407: delete_record_from_table() ->
  408:     ok = rpc_call(mnesia, dirty_delete, [vcard, 1]).
  409: 
  410: create_full_filename(Filename) ->
  411:     Path  = list_to_binary(get_mim_cwd() ++ "/"),
  412:     <<Path/binary, Filename/binary>>.
  413: 
  414: delete_mnesia_table() ->
  415:     {atomic, ok} = rpc_call(mnesia, delete_table, [mnesia_table_test]).
  416: 
  417: check_created_file(FullPath, ExpectedContent) ->
  418:     {ok, FileInsides} = file:read_file(FullPath),
  419:     ?assertMatch({_,_}, binary:match(FileInsides, ExpectedContent)),
  420:     delete_file(FullPath).
  421: 
  422: create_file(FullPath) ->
  423:     file:open(FullPath, [write]),
  424:     file:close(FullPath).
  425: 
  426: create_and_write_file(FullPath) ->
  427:     {ok, File} = file:open(FullPath, [write]),
  428:     io:format(File, "~s~n", ["TEST"]),
  429:     file:close(FullPath).
  430: 
  431: check_if_response_contains(Response, String) ->
  432:     ParsedLoadRes = io_lib:format("~p", [Response]),
  433:     ?assertMatch({_,_}, binary:match(list_to_binary(ParsedLoadRes), String)).
  434: 
  435: delete_file(FullPath) ->
  436:     file:delete(FullPath).
  437: 
  438: get_info(null, Config) ->
  439:     execute_command(<<"mnesia">>, <<"systemInfo">>, #{}, Config);
  440: get_info(Keys, Config) ->
  441:     execute_command(<<"mnesia">>, <<"systemInfo">>, #{keys => Keys}, Config).
  442: 
  443: install_fallback(Path, Config) ->
  444:     execute_command(<<"mnesia">>, <<"installFallback">>, #{path => Path}, Config).
  445: 
  446: dump_mnesia(Path, Config) ->
  447:     execute_command(<<"mnesia">>, <<"dump">>, #{path => Path}, Config).
  448: 
  449: backup_mnesia(Path, Config) ->
  450:     execute_command(<<"mnesia">>, <<"backup">>, #{path => Path}, Config).
  451: 
  452: restore_mnesia(Path, Config) ->
  453:     execute_command(<<"mnesia">>, <<"restore">>, #{path => Path}, Config).
  454: 
  455: dump_mnesia_table(Path, Table, Config) ->
  456:     execute_command(<<"mnesia">>, <<"dumpTable">>, #{path => Path, table => Table}, Config).
  457: 
  458: load_mnesia(Path, Config) ->
  459:     execute_command(<<"mnesia">>, <<"load">>, #{path => Path}, Config).
  460: 
  461: change_nodename(ChangeFrom, ChangeTo, Source, Target, Config) ->
  462:     Vars = #{<<"fromString">> => ChangeFrom, <<"toString">> => ChangeTo,
  463:              <<"source">> => Source, <<"target">> => Target},
  464:     execute_command(<<"mnesia">>, <<"changeNodename">>, Vars, Config).
  465: 
  466: set_master(Node, Config) ->
  467:     execute_command(<<"mnesia">>, <<"setMaster">>, Node, Config).
  468: 
  469: mnesia_info_check() ->
  470:     #{<<"access_module">> => check_binary,
  471:       <<"auto_repair">> => check_binary,
  472:       <<"backend_types">> => check_list,
  473:       <<"backup_module">> => check_binary,
  474:       <<"checkpoints">> => check_list,
  475:       <<"db_nodes">> => check_list,
  476:       <<"debug">> => check_binary,
  477:       <<"directory">> => check_binary,
  478:       <<"dump_log_load_regulation">> => check_binary,
  479:       <<"dump_log_time_threshold">> => check_integer,
  480:       <<"dump_log_update_in_place">> => check_binary,
  481:       <<"dump_log_write_threshold">> => check_integer,
  482:       <<"event_module">> => check_binary,
  483:       <<"extra_db_nodes">> => check_list,
  484:       <<"fallback_activated">> => check_binary,
  485:       <<"held_locks">> => check_list,
  486:       <<"ignore_fallback_at_startup">> => check_binary,
  487:       <<"fallback_error_function">> => check_binary,
  488:       <<"is_running">> => check_binary,
  489:       <<"local_tables">> => check_list,
  490:       <<"lock_queue">> => check_list,
  491:       <<"log_version">> => check_binary,
  492:       <<"master_node_tables">> => check_list,
  493:       <<"max_wait_for_decision">> => check_binary,
  494:       <<"protocol_version">> => check_binary,
  495:       <<"running_db_nodes">> => check_list,
  496:       <<"schema_location">> => check_binary,
  497:       <<"schema_version">> => check_binary,
  498:       <<"subscribers">> => check_list,
  499:       <<"tables">> => check_list,
  500:       <<"transaction_commits">> => check_integer,
  501:       <<"transaction_failures">> => check_integer,
  502:       <<"transaction_log_writes">> => check_integer,
  503:       <<"transaction_restarts">> => check_integer,
  504:       <<"transactions">> => check_list,
  505:       <<"use_dir">> => check_binary,
  506:       <<"core_dir">> => check_binary,
  507:       <<"no_table_loaders">> => check_integer,
  508:       <<"dc_dump_limit">> => check_integer,
  509:       <<"send_compressed">> => check_integer,
  510:       <<"max_transfer_size">> => check_integer,
  511:       <<"version">> => check_binary,
  512:       <<"db_nodes">> => check_list,
  513:       <<"running_db_nodes">> => check_list}.
  514: 
  515: check_list(L) ->
  516:     lists:all(fun(Item) -> is_binary(Item) end, L).
  517: 
  518: check_binary(Value) -> is_binary(Value).
  519: 
  520: check_integer(Value) -> is_integer(Value).
  521: 
  522: get_mim_cwd() ->
  523:     {ok, Cwd} = rpc(mim(), file, get_cwd, []),
  524:     Cwd.