2026-06-16 06:41:37 +02:00
|
|
|
%% 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">> =>
|
|
|
|
|
<<"fluxer_gateway_websocket_1@127.0.0.1, fluxer_gateway_sessions_1@127.0.0.1">>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
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("fluxer_gateway_websocket_1@127.0.0.1"),
|
|
|
|
|
list_to_atom("fluxer_gateway_sessions_1@127.0.0.1")
|
|
|
|
|
],
|
|
|
|
|
maps:get(cluster_static_peers, Config)
|
|
|
|
|
).
|
|
|
|
|
|
|
|
|
|
cluster_static_peers_filters_invalid_node_names_test() ->
|
|
|
|
|
LongPeer = list_to_binary(lists:duplicate(260, $a)),
|
|
|
|
|
RawConfig = #{
|
|
|
|
|
<<"services">> => #{
|
|
|
|
|
<<"gateway">> => #{
|
|
|
|
|
<<"cluster_static_peers">> => <<
|
|
|
|
|
"valid_peer@127.0.0.1,",
|
|
|
|
|
"invalid peer@127.0.0.2,",
|
|
|
|
|
"missing-host@,",
|
|
|
|
|
LongPeer/binary,
|
|
|
|
|
",other-valid@node.local"
|
|
|
|
|
>>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
Config = fluxer_gateway_config:build_config(RawConfig),
|
|
|
|
|
?assertEqual(
|
|
|
|
|
[list_to_atom("valid_peer@127.0.0.1"), list_to_atom("other-valid@node.local")],
|
|
|
|
|
maps:get(cluster_static_peers, Config)
|
|
|
|
|
).
|
|
|
|
|
|
|
|
|
|
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_push_and_http_runtime_config_test() ->
|
|
|
|
|
ApnsAppsJson =
|
|
|
|
|
"[{\"app_id\":\"ios-stable\",\"topic\":\"app.fluxer\",\"environment\":\"production\"}]",
|
|
|
|
|
FcmAppsJson = "[{\"app_id\":\"android-stable\",\"project_id\":\"fluxer-fcm\"}]",
|
|
|
|
|
with_envs(
|
|
|
|
|
[
|
|
|
|
|
{"FLUXER_GATEWAY_SHUTDOWN_DRAIN_WAIT_MS", "1234"},
|
|
|
|
|
{"FLUXER_GATEWAY_HTTP_RPC_MAX_CONCURRENCY", "42"},
|
|
|
|
|
{"FLUXER_GATEWAY_HTTP_FAILURE_THRESHOLD", "9"},
|
|
|
|
|
{"FLUXER_GATEWAY_HTTP_RECOVERY_TIMEOUT_MS", "6000"},
|
|
|
|
|
{"FLUXER_PUSH_APNS_ENABLED", "true"},
|
|
|
|
|
{"FLUXER_PUSH_APNS_TEAM_ID", "TEAMID"},
|
|
|
|
|
{"FLUXER_PUSH_APNS_KEY_ID", "KEYID"},
|
|
|
|
|
{"FLUXER_PUSH_APNS_PRIVATE_KEY_PATH", "/etc/fluxer/apns.p8"},
|
|
|
|
|
{"FLUXER_PUSH_APNS_DEFAULT_ENVIRONMENT", "development"},
|
|
|
|
|
{"FLUXER_PUSH_APNS_APPS", ApnsAppsJson},
|
|
|
|
|
{"FLUXER_PUSH_FCM_ENABLED", "true"},
|
|
|
|
|
{"FLUXER_PUSH_FCM_PROJECT_ID", "fluxer-fcm"},
|
|
|
|
|
{"FLUXER_PUSH_FCM_SERVICE_ACCOUNT_JSON_PATH", "/etc/fluxer/fcm.json"},
|
|
|
|
|
{"FLUXER_PUSH_FCM_TOKEN_URI", "https://oauth2.example/token"},
|
|
|
|
|
{"FLUXER_PUSH_FCM_APPS", FcmAppsJson}
|
|
|
|
|
],
|
|
|
|
|
fun() ->
|
|
|
|
|
Config = fluxer_gateway_config:load(),
|
|
|
|
|
?assertEqual(1234, maps:get(shutdown_drain_wait_ms, Config)),
|
|
|
|
|
?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)),
|
|
|
|
|
?assertEqual(true, maps:get(apns_enabled, Config)),
|
|
|
|
|
?assertEqual(<<"TEAMID">>, maps:get(apns_team_id, Config)),
|
|
|
|
|
?assertEqual(<<"KEYID">>, maps:get(apns_key_id, Config)),
|
|
|
|
|
?assertEqual(<<"development">>, maps:get(apns_default_environment, Config)),
|
|
|
|
|
?assertEqual(
|
|
|
|
|
[
|
|
|
|
|
#{
|
|
|
|
|
<<"app_id">> => <<"ios-stable">>,
|
|
|
|
|
<<"topic">> => <<"app.fluxer">>,
|
|
|
|
|
<<"environment">> => <<"production">>
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
maps:get(apns_apps, Config)
|
|
|
|
|
),
|
|
|
|
|
?assertEqual(true, maps:get(fcm_enabled, Config)),
|
|
|
|
|
?assertEqual(<<"fluxer-fcm">>, maps:get(fcm_project_id, Config)),
|
|
|
|
|
?assertEqual(<<"https://oauth2.example/token">>, maps:get(fcm_token_uri, Config)),
|
|
|
|
|
?assertEqual(
|
|
|
|
|
[#{<<"app_id">> => <<"android-stable">>, <<"project_id">> => <<"fluxer-fcm">>}],
|
|
|
|
|
maps:get(fcm_apps, Config)
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
).
|
|
|
|
|
|
2026-08-30 23:16:53 +02:00
|
|
|
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
|
|
|
|
|
).
|
|
|
|
|
|
|
|
|
|
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)).
|
|
|
|
|
|
2026-06-16 06:41:37 +02:00
|
|
|
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(<<>>)).
|
|
|
|
|
|
2026-09-01 20:47:18 +02:00
|
|
|
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)).
|
|
|
|
|
|
2026-06-16 06:41:37 +02:00
|
|
|
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).
|