mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
351 lines
13 KiB
Erlang
351 lines
13 KiB
Erlang
%% SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
-module(fluxer_gateway_config_tests).
|
|
-typing([eqwalizer]).
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
|
|
cluster_defaults_test() ->
|
|
Config = fluxer_gateway_config:build_config(#{}),
|
|
?assertEqual(false, maps:get(cluster_enabled, Config)),
|
|
?assertEqual(undefined, maps:get(cluster_discovery_dns_name, Config)),
|
|
?assertEqual(undefined, maps:get(cluster_discovery_node_basename, Config)),
|
|
?assertEqual(5000, maps:get(cluster_discovery_poll_interval_ms, Config)),
|
|
?assertEqual([], maps:get(cluster_static_peers, Config)).
|
|
|
|
cluster_overrides_test() ->
|
|
RawConfig = #{
|
|
<<"services">> => #{
|
|
<<"gateway">> => #{
|
|
<<"cluster_enabled">> => true,
|
|
<<"cluster_discovery_dns_name">> =>
|
|
<<"fluxer-gateway-headless.fluxer.svc.cluster.local">>,
|
|
<<"cluster_discovery_node_basename">> => <<"fluxer_gateway">>,
|
|
<<"cluster_discovery_poll_interval_ms">> => 2500,
|
|
<<"cluster_static_peers">> =>
|
|
<<"[email protected], [email protected]">>
|
|
}
|
|
}
|
|
},
|
|
Config = fluxer_gateway_config:build_config(RawConfig),
|
|
?assertEqual(true, maps:get(cluster_enabled, Config)),
|
|
?assertEqual(
|
|
"fluxer-gateway-headless.fluxer.svc.cluster.local",
|
|
maps:get(cluster_discovery_dns_name, Config)
|
|
),
|
|
?assertEqual(
|
|
"fluxer_gateway",
|
|
maps:get(cluster_discovery_node_basename, Config)
|
|
),
|
|
?assertEqual(2500, maps:get(cluster_discovery_poll_interval_ms, Config)),
|
|
?assertEqual(
|
|
[
|
|
list_to_atom("[email protected]"),
|
|
list_to_atom("[email protected]")
|
|
],
|
|
maps:get(cluster_static_peers, Config)
|
|
).
|
|
|
|
cluster_static_peers_rejects_invalid_node_names_test() ->
|
|
LongPeer = list_to_binary(lists:duplicate(260, $a)),
|
|
RawConfig = #{
|
|
<<"services">> => #{
|
|
<<"gateway">> => #{
|
|
<<"cluster_static_peers">> => <<
|
|
"[email protected],",
|
|
"invalid [email protected],",
|
|
"missing-host@,",
|
|
LongPeer/binary,
|
|
",[email protected]"
|
|
>>
|
|
}
|
|
}
|
|
},
|
|
?assertError(
|
|
{invalid_cluster_static_peer, "invalid [email protected]"},
|
|
fluxer_gateway_config:build_config(RawConfig)
|
|
).
|
|
|
|
cluster_static_peers_accepts_valid_node_names_test() ->
|
|
RawConfig = #{
|
|
<<"services">> => #{
|
|
<<"gateway">> => #{
|
|
<<"cluster_static_peers">> =>
|
|
<<"[email protected],[email protected]">>
|
|
}
|
|
}
|
|
},
|
|
Config = fluxer_gateway_config:build_config(RawConfig),
|
|
?assertEqual(
|
|
[list_to_atom("[email protected]"), list_to_atom("[email protected]")],
|
|
maps:get(cluster_static_peers, Config)
|
|
).
|
|
|
|
push_clear_switch_reads_the_enrolled_env_name_test() ->
|
|
?assertEqual(
|
|
true, maps:get(push_enrolled_clear_notifications_enabled, fluxer_gateway_config:load())
|
|
),
|
|
with_env("FLUXER_GATEWAY_PUSH_ENROLLED_CLEAR_NOTIFICATIONS_ENABLED", "false", fun() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
?assertEqual(false, maps:get(push_enrolled_clear_notifications_enabled, Config))
|
|
end).
|
|
|
|
gateway_config_holds_no_direct_push_delivery_keys_test() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
lists:foreach(
|
|
fun(Key) -> ?assertNot(maps:is_key(Key, Config)) end,
|
|
[
|
|
push_clear_notifications_enabled,
|
|
push_endpoint_guard_enabled,
|
|
push_managed_relay_hosts,
|
|
push_relay_consent_accepted,
|
|
vapid_public_key,
|
|
apns_enabled,
|
|
fcm_enabled,
|
|
gateway_http_push_max_concurrency
|
|
]
|
|
).
|
|
|
|
presence_push_buffer_env_defaults_test() ->
|
|
with_env("FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_ENTRIES", "7", fun() ->
|
|
with_env("FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_BYTES", "4096", fun() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
?assertEqual(7, maps:get(presence_push_buffer_max_entries, Config)),
|
|
?assertEqual(4096, maps:get(presence_push_buffer_max_bytes, Config))
|
|
end)
|
|
end).
|
|
|
|
env_only_http_runtime_config_test() ->
|
|
with_envs(
|
|
[
|
|
{"FLUXER_GATEWAY_HTTP_RPC_MAX_CONCURRENCY", "42"},
|
|
{"FLUXER_GATEWAY_HTTP_FAILURE_THRESHOLD", "9"},
|
|
{"FLUXER_GATEWAY_HTTP_RECOVERY_TIMEOUT_MS", "6000"}
|
|
],
|
|
fun() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
?assertEqual(42, maps:get(gateway_http_rpc_max_concurrency, Config)),
|
|
?assertEqual(9, maps:get(gateway_http_failure_threshold, Config)),
|
|
?assertEqual(6000, maps:get(gateway_http_recovery_timeout_ms, Config))
|
|
end
|
|
).
|
|
|
|
rpc_concurrency_keys_are_independent_test() ->
|
|
with_envs(
|
|
[
|
|
{"FLUXER_GATEWAY_HTTP_RPC_MAX_CONCURRENCY", "128"},
|
|
{"FLUXER_GATEWAY_NATS_RPC_MAX_HANDLERS", "2048"}
|
|
],
|
|
fun() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
?assertEqual(128, maps:get(gateway_http_rpc_max_concurrency, Config)),
|
|
?assertEqual(2048, maps:get(gateway_nats_rpc_max_handlers, Config))
|
|
end
|
|
).
|
|
|
|
env_int_rejects_a_non_integer_value_test() ->
|
|
with_env("FLUXER_GATEWAY_HTTP_RPC_MAX_CONCURRENCY", "abc", fun() ->
|
|
?assertError(
|
|
{invalid_integer_env, "FLUXER_GATEWAY_HTTP_RPC_MAX_CONCURRENCY", "abc"},
|
|
fluxer_gateway_config:load()
|
|
)
|
|
end).
|
|
|
|
env_int_falls_back_to_the_default_for_an_empty_value_test() ->
|
|
with_env("FLUXER_GATEWAY_HTTP_RPC_MAX_CONCURRENCY", "", fun() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
?assertEqual(512, maps:get(gateway_http_rpc_max_concurrency, Config))
|
|
end).
|
|
|
|
blank_env_values_fall_back_to_the_defaults_test() ->
|
|
with_envs(
|
|
[
|
|
{"FLUXER_GATEWAY_HTTP_RPC_MAX_CONCURRENCY", " "},
|
|
{"FLUXER_CLIENT_IP_HEADER_NAME", " "},
|
|
{"FLUXER_NATS_URL", "\t"},
|
|
{"FLUXER_GATEWAY_API_RPC_ENDPOINT", " "},
|
|
{"FLUXER_GATEWAY_LOGGER_LEVEL", " "},
|
|
{"FLUXER_GATEWAY_PUSH_ENABLED", " "}
|
|
],
|
|
fun() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
?assertEqual(512, maps:get(gateway_http_rpc_max_concurrency, Config)),
|
|
?assertEqual(<<"x-forwarded-for">>, maps:get(client_ip_header, Config)),
|
|
?assertEqual("nats://nats:4222", maps:get(nats_core_url, Config)),
|
|
?assertEqual(undefined, maps:get(api_rpc_endpoint, Config)),
|
|
?assertEqual(info, maps:get(logger_level, Config)),
|
|
?assertEqual(true, maps:get(push_enabled, Config))
|
|
end
|
|
).
|
|
|
|
logger_level_env_test() ->
|
|
with_env("FLUXER_GATEWAY_LOGGER_LEVEL", "Debug", fun() ->
|
|
?assertEqual(debug, maps:get(logger_level, fluxer_gateway_config:load()))
|
|
end).
|
|
|
|
rpc_concurrency_key_defaults_test() ->
|
|
Config = fluxer_gateway_config:build_config(#{}),
|
|
?assertEqual(512, maps:get(gateway_nats_rpc_max_handlers, Config)),
|
|
?assertEqual(512, maps:get(gateway_http_rpc_max_concurrency, Config)).
|
|
|
|
pinned_node_defaults_keep_release_behaviour_test() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
?assertEqual(true, maps:get(nats_rpc_enabled, Config)),
|
|
?assertEqual([], maps:get(pinned_guild_ids, Config)),
|
|
?assertEqual(undefined, maps:get(guild_pin_keeper_beam, Config)).
|
|
|
|
pinned_node_env_test() ->
|
|
with_envs(
|
|
[
|
|
{"FLUXER_GATEWAY_NATS_RPC_ENABLED", "false"},
|
|
{"FLUXER_GATEWAY_PINNED_GUILD_IDS", "1100000000000000001, 42"},
|
|
{"FLUXER_GATEWAY_GUILD_PIN_KEEPER_BEAM", "/etc/fluxer/gw/gateway_node_router.beam"},
|
|
{"FLUXER_GATEWAY_GUILD_PIN_KEEPER_BEAM_MD5", "D5E42B1D6D85C4CDEE93AA0CCA18A420"}
|
|
],
|
|
fun() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
?assertEqual(false, maps:get(nats_rpc_enabled, Config)),
|
|
?assertEqual([42, 1100000000000000001], maps:get(pinned_guild_ids, Config)),
|
|
?assertEqual(
|
|
"/etc/fluxer/gw/gateway_node_router.beam",
|
|
maps:get(guild_pin_keeper_beam, Config)
|
|
),
|
|
?assertEqual(
|
|
<<"D5E42B1D6D85C4CDEE93AA0CCA18A420">>,
|
|
maps:get(guild_pin_keeper_beam_md5, Config)
|
|
)
|
|
end
|
|
).
|
|
|
|
pinned_guild_ids_reject_non_snowflakes_test() ->
|
|
with_env("FLUXER_GATEWAY_PINNED_GUILD_IDS", "1100000000000000001,ab", fun() ->
|
|
?assertError({invalid_pinned_guild_id, "ab"}, fluxer_gateway_config:load())
|
|
end).
|
|
|
|
optional_string_test() ->
|
|
?assertEqual(undefined, fluxer_gateway_config:optional_string(undefined)),
|
|
?assertEqual("hello", fluxer_gateway_config:optional_string(<<"hello">>)),
|
|
?assertEqual("", fluxer_gateway_config:optional_string(<<>>)).
|
|
|
|
public_endpoints_env_non_default_port_test() ->
|
|
with_envs(
|
|
[
|
|
{"FLUXER_BASE_DOMAIN", "fluxer.example"},
|
|
{"FLUXER_PUBLIC_SCHEME", "https"},
|
|
{"FLUXER_PUBLIC_PORT", "8443"},
|
|
{"FLUXER_GATEWAY_MEDIA_PROXY_ENDPOINT", "https://fluxer.example/media"},
|
|
{"FLUXER_GATEWAY_STATIC_CDN_ENDPOINT", "https://fluxer.example"}
|
|
],
|
|
fun() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
?assertEqual(
|
|
<<"https://fluxer.example:8443/media">>,
|
|
maps:get(media_proxy_endpoint, Config)
|
|
),
|
|
?assertEqual(
|
|
<<"https://fluxer.example:8443">>, maps:get(static_cdn_endpoint, Config)
|
|
)
|
|
end
|
|
).
|
|
|
|
public_endpoints_env_default_port_test() ->
|
|
with_envs(
|
|
[
|
|
{"FLUXER_BASE_DOMAIN", "fluxer.example"},
|
|
{"FLUXER_PUBLIC_SCHEME", "https"},
|
|
{"FLUXER_PUBLIC_PORT", "443"},
|
|
{"FLUXER_GATEWAY_MEDIA_PROXY_ENDPOINT", "https://fluxer.example/media"},
|
|
{"FLUXER_GATEWAY_STATIC_CDN_ENDPOINT", "https://cdn.othercdn.net"}
|
|
],
|
|
fun() ->
|
|
Config = fluxer_gateway_config:load(),
|
|
?assertEqual(
|
|
<<"https://fluxer.example/media">>, maps:get(media_proxy_endpoint, Config)
|
|
),
|
|
?assertEqual(
|
|
<<"https://cdn.othercdn.net">>, maps:get(static_cdn_endpoint, Config)
|
|
)
|
|
end
|
|
).
|
|
|
|
public_endpoints_defaults_test() ->
|
|
Config = fluxer_gateway_config:build_config(#{}),
|
|
?assertEqual(undefined, maps:get(media_proxy_endpoint, Config)),
|
|
?assertEqual(<<"http://localhost:8088">>, maps:get(static_cdn_endpoint, Config)).
|
|
|
|
env_value_reads_name_file_test() ->
|
|
with_env_file(<<"from-file\r\n">>, fun(Path) ->
|
|
with_envs(
|
|
[{"FLUXER_GATEWAY_TEST_SECRET", ""}, {"FLUXER_GATEWAY_TEST_SECRET_FILE", Path}],
|
|
fun() ->
|
|
?assertEqual(
|
|
"from-file", fluxer_gateway_config:env_value("FLUXER_GATEWAY_TEST_SECRET")
|
|
)
|
|
end
|
|
)
|
|
end).
|
|
|
|
env_value_trims_only_one_newline_test() ->
|
|
with_env_file(<<"line1\nline2\n\n">>, fun(Path) ->
|
|
with_env("FLUXER_GATEWAY_TEST_SECRET_FILE", Path, fun() ->
|
|
?assertEqual(
|
|
"line1\nline2\n", fluxer_gateway_config:env_value("FLUXER_GATEWAY_TEST_SECRET")
|
|
)
|
|
end)
|
|
end).
|
|
|
|
env_value_rejects_name_and_name_file_test() ->
|
|
with_envs(
|
|
[
|
|
{"FLUXER_GATEWAY_TEST_SECRET", "direct"},
|
|
{"FLUXER_GATEWAY_TEST_SECRET_FILE", "/run/secrets/x"}
|
|
],
|
|
fun() ->
|
|
?assertError(
|
|
{ambiguous_env, "FLUXER_GATEWAY_TEST_SECRET",
|
|
"FLUXER_GATEWAY_TEST_SECRET_FILE"},
|
|
fluxer_gateway_config:env_value("FLUXER_GATEWAY_TEST_SECRET")
|
|
)
|
|
end
|
|
).
|
|
|
|
env_value_rejects_missing_name_file_test() ->
|
|
Path = "/nonexistent/fluxer-gateway-test-secret",
|
|
with_env("FLUXER_GATEWAY_TEST_SECRET_FILE", Path, fun() ->
|
|
?assertError(
|
|
{unreadable_env_file, "FLUXER_GATEWAY_TEST_SECRET_FILE", Path, enoent},
|
|
fluxer_gateway_config:env_value("FLUXER_GATEWAY_TEST_SECRET")
|
|
)
|
|
end).
|
|
|
|
with_env_file(Contents, Fun) ->
|
|
Path = filename:join(
|
|
filename:basedir(user_cache, "fluxer_gateway_tests"),
|
|
integer_to_list(erlang:unique_integer([positive]))
|
|
),
|
|
ok = filelib:ensure_dir(Path),
|
|
ok = file:write_file(Path, Contents),
|
|
try
|
|
Fun(Path)
|
|
after
|
|
file:delete(Path)
|
|
end.
|
|
|
|
with_envs([], Fun) ->
|
|
Fun();
|
|
with_envs([{Name, Value} | Rest], Fun) ->
|
|
with_env(Name, Value, fun() -> with_envs(Rest, Fun) end).
|
|
|
|
with_env(Name, Value, Fun) ->
|
|
Previous = os:getenv(Name),
|
|
os:putenv(Name, Value),
|
|
try
|
|
Fun()
|
|
after
|
|
restore_env(Name, Previous)
|
|
end.
|
|
|
|
restore_env(Name, false) ->
|
|
os:unsetenv(Name);
|
|
restore_env(Name, Previous) ->
|
|
os:putenv(Name, Previous).
|