1: -module(keystore_SUITE). 2: -include_lib("eunit/include/eunit.hrl"). 3: -compile([export_all, nowarn_export_all]). 4: -import(config_parser_helper, [default_mod_config/1, mod_config/2]). 5: 6: -define(ae(Expected, Actual), ?assertEqual(Expected, Actual)). 7: 8: all() -> 9: [ 10: module_startup_no_opts, 11: module_startup_read_key_from_file, 12: module_startup_create_ram_key, 13: module_startup_create_ram_key_of_given_size, 14: module_startup_for_multiple_domains, 15: multiple_domains_one_stopped 16: ]. 17: 18: init_per_suite(C) -> 19: {ok, _} = application:ensure_all_started(jid), 20: ok = mnesia:create_schema([node()]), 21: ok = mnesia:start(), 22: C. 23: 24: end_per_suite(_C) -> 25: mnesia:stop(), 26: mnesia:delete_schema([node()]). 27: 28: init_per_testcase(_, Config) -> 29: mock_mongoose_metrics(), 30: Config1 = async_helper:start(Config, mongooseim_helper, start_link_loaded_hooks, []), 31: mongoose_config:set_opts(opts()), 32: Config1. 33: 34: end_per_testcase(_, C) -> 35: mongoose_modules:stop(), 36: mongoose_config:erase_opts(), 37: meck:unload(mongoose_metrics), 38: async_helper:stop_all(C), 39: mnesia:delete_table(key). 40: 41: opts() -> 42: maps:from_list([{hosts, hosts()}, 43: {host_types, []}, 44: {all_metrics_are_global, false} | 45: [{{modules, Host}, #{}} || Host <- hosts()]]). 46: 47: hosts() -> 48: [<<"localhost">>, <<"first.com">>, <<"second.com">>]. 49: 50: %% 51: %% Tests 52: %% 53: 54: module_startup_no_opts(_) -> 55: {started, ok} = start(<<"localhost">>, default_mod_config(mod_keystore)). 56: 57: module_startup_read_key_from_file(_) -> 58: %% given 59: RawKey = <<"qwe123">>, 60: {ok, KeyFile} = key_at("/tmp/key-from-file", RawKey), 61: %% when 62: {started, ok} = start(<<"localhost">>, key_from_file(KeyFile)), 63: %% then 64: ?ae([{{key_from_file, <<"localhost">>}, RawKey}], 65: get_key(<<"localhost">>, key_from_file)). 66: 67: module_startup_create_ram_key(Config) -> 68: module_startup_create_ram_key(Config, ram_key()), 69: %% then we can access the key 70: [{{ram_key, <<"localhost">>}, Key}] = get_key(<<"localhost">>, ram_key), 71: true = is_binary(Key). 72: 73: module_startup_create_ram_key_of_given_size(Config) -> 74: KeySize = 4, 75: module_startup_create_ram_key(Config, sized_ram_key(KeySize)), 76: %% then 77: [{{ram_key, <<"localhost">>}, Key}] = get_key(<<"localhost">>, ram_key), 78: true = is_binary(Key), 79: KeySize = byte_size(Key). 80: 81: module_startup_create_ram_key(_, ModKeystoreOpts) -> 82: %% given no key 83: [] = get_key(<<"localhost">>, ram_key), 84: %% when keystore starts with config to generate a memory-only key 85: {started, ok} = start(<<"localhost">>, ModKeystoreOpts). 86: 87: module_startup_for_multiple_domains(_Config) -> 88: %% given 89: [] = get_key(<<"first.com">>, key_from_file), 90: [] = get_key(<<"second.com">>, key_from_file), 91: FirstKey = <<"random-first.com-key-content">>, 92: SecondKey = <<"random-second.com-key-content">>, 93: {ok, FirstKeyFile} = key_at("/tmp/first.com", FirstKey), 94: {ok, SecondKeyFile} = key_at("/tmp/second.com", SecondKey), 95: %% when 96: {started, ok} = start(<<"first.com">>, key_from_file(FirstKeyFile)), 97: {started, ok} = start(<<"second.com">>, key_from_file(SecondKeyFile)), 98: %% then 99: ?ae([{{key_from_file, <<"first.com">>}, FirstKey}], 100: get_key(<<"first.com">>, key_from_file)), 101: ?ae([{{key_from_file, <<"second.com">>}, SecondKey}], 102: get_key(<<"second.com">>, key_from_file)). 103: 104: multiple_domains_one_stopped(_Config) -> 105: % given 106: [] = get_key(<<"first.com">>, key_from_file), 107: [] = get_key(<<"second.com">>, key_from_file), 108: FirstKey = <<"random-first.com-key-content">>, 109: SecondKey = <<"random-second.com-key-content">>, 110: {ok, FirstKeyFile} = key_at("/tmp/first.com", FirstKey), 111: {ok, SecondKeyFile} = key_at("/tmp/second.com", SecondKey), 112: % when 113: {started, ok} = start(<<"first.com">>, key_from_file(FirstKeyFile)), 114: {started, ok} = start(<<"second.com">>, key_from_file(SecondKeyFile)), 115: ok = mod_keystore:stop(<<"first.com">>), 116: % then 117: ?ae([{{key_from_file, <<"second.com">>}, SecondKey}], 118: get_key(<<"second.com">>, key_from_file)). 119: 120: %% 121: %% Helpers 122: %% 123: 124: key_at(Path, Data) -> 125: ok = file:write_file(Path, Data), 126: {ok, Path}. 127: 128: key_from_file(KeyFile) -> 129: mod_config(mod_keystore, #{keys => #{key_from_file => {file, KeyFile}}}). 130: 131: ram_key() -> 132: mod_config(mod_keystore, #{keys => #{ram_key => ram}}). 133: 134: sized_ram_key(Size) -> 135: mod_config(mod_keystore, #{keys => #{ram_key => ram}, 136: ram_key_size => Size}). 137: 138: mock_mongoose_metrics() -> 139: meck:new(mongoose_metrics, []), 140: meck:expect(mongoose_metrics, create_generic_hook_metric, fun (_, _) -> ok end), 141: meck:expect(mongoose_metrics, increment_generic_hook_metric, fun (_, _) -> ok end), 142: ok. 143: 144: %% Use a function like this in your module which is a client of mod_keystore. 145: -spec get_key(HostType, KeyName) -> Result when 146: HostType :: mongooseim:host_type(), 147: KeyName :: mod_keystore:key_name(), 148: Result :: mod_keystore:key_list(). 149: get_key(HostType, KeyName) -> 150: mongoose_hooks:get_key(HostType, KeyName). 151: 152: start(HostType, Opts) -> 153: mongoose_modules:ensure_started(HostType, mod_keystore, Opts).