test: add test script to verify config example files
This commit is contained in:
parent
0428d91aa4
commit
a069b351fd
|
@ -24,7 +24,8 @@
|
|||
compact_errors/2,
|
||||
format_error/1,
|
||||
format_error/2,
|
||||
make_schema/1
|
||||
make_schema/1,
|
||||
load_and_check/2
|
||||
]).
|
||||
|
||||
%% @doc Format hocon config field path to dot-separated string in iolist format.
|
||||
|
@ -46,7 +47,8 @@ check(SchemaModule, Conf) ->
|
|||
|
||||
check(SchemaModule, Conf, Opts) when is_map(Conf) ->
|
||||
try
|
||||
{ok, hocon_tconf:check_plain(SchemaModule, Conf, Opts)}
|
||||
RootNames = maps:keys(Conf),
|
||||
{ok, hocon_tconf:check_plain(SchemaModule, Conf, Opts, RootNames)}
|
||||
catch
|
||||
throw:Errors:Stacktrace ->
|
||||
compact_errors(Errors, Stacktrace)
|
||||
|
@ -135,3 +137,26 @@ compact_errors(SchemaModule, Error, Stacktrace) ->
|
|||
exception => Error,
|
||||
stacktrace => Stacktrace
|
||||
}}.
|
||||
|
||||
%% @doc This is only used in static check scripts in the CI.
|
||||
-spec load_and_check(module(), filename:filename_all()) -> {ok, term()} | {error, any()}.
|
||||
load_and_check(SchemaModule, File) ->
|
||||
try
|
||||
do_load_and_check(SchemaModule, File)
|
||||
catch
|
||||
throw:Reason ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
do_load_and_check(SchemaModule, File) ->
|
||||
Conf =
|
||||
case hocon:load(File, #{format => map}) of
|
||||
{ok, Conf0} ->
|
||||
Conf0;
|
||||
{error, {parse_error, Reason}} ->
|
||||
throw(Reason);
|
||||
{error, Reason} ->
|
||||
throw(Reason)
|
||||
end,
|
||||
Opts = #{atom_key => false, required => false},
|
||||
check(SchemaModule, Conf, Opts).
|
||||
|
|
|
@ -3271,7 +3271,19 @@ tombstone() ->
|
|||
tombstone_map(Name, Type) ->
|
||||
%% marked_for_deletion must be the last member of the union
|
||||
%% because we need to first union member to populate the default values
|
||||
map(Name, ?UNION([Type, ?TOMBSTONE_TYPE])).
|
||||
map(
|
||||
Name,
|
||||
hoconsc:union(
|
||||
fun
|
||||
(all_union_members) ->
|
||||
[Type, ?TOMBSTONE_TYPE];
|
||||
({value, V}) when is_map(V) ->
|
||||
[Type];
|
||||
({value, _}) ->
|
||||
[?TOMBSTONE_TYPE]
|
||||
end
|
||||
)
|
||||
).
|
||||
|
||||
%% inverse of mark_del_map
|
||||
get_tombstone_map_value_type(Schema) ->
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqx_conf_schema_tests).
|
||||
|
@ -488,3 +500,60 @@ check(Config) ->
|
|||
atom_key => false, required => false, format => map
|
||||
}),
|
||||
emqx_utils_maps:unsafe_atom_key_map(Conf).
|
||||
|
||||
with_file(Path, Content, F) ->
|
||||
ok = file:write_file(Path, Content),
|
||||
try
|
||||
F()
|
||||
after
|
||||
file:delete(Path)
|
||||
end.
|
||||
|
||||
load_and_check_test_() ->
|
||||
[
|
||||
{"non-existing file", fun() ->
|
||||
File = "/tmp/nonexistingfilename.hocon",
|
||||
?assertEqual(
|
||||
{error, {enoent, File}},
|
||||
emqx_hocon:load_and_check(emqx_conf_schema, File)
|
||||
)
|
||||
end},
|
||||
{"bad syntax", fun() ->
|
||||
%% use abs path to match error return
|
||||
File = "/tmp/emqx-conf-bad-syntax-test.hocon",
|
||||
with_file(
|
||||
File,
|
||||
"{",
|
||||
fun() ->
|
||||
?assertMatch(
|
||||
{error, #{file := File}},
|
||||
emqx_hocon:load_and_check(emqx_conf_schema, File)
|
||||
)
|
||||
end
|
||||
)
|
||||
end},
|
||||
{"type-check failure", fun() ->
|
||||
File = "emqx-conf-type-check-failure.hocon",
|
||||
%% typecheck fail because cookie is required field
|
||||
with_file(
|
||||
File,
|
||||
"node {}",
|
||||
fun() ->
|
||||
?assertMatch(
|
||||
{error, #{
|
||||
kind := validation_error,
|
||||
path := "node.cookie",
|
||||
reason := required_field
|
||||
}},
|
||||
emqx_hocon:load_and_check(emqx_conf_schema, File)
|
||||
)
|
||||
end
|
||||
)
|
||||
end},
|
||||
{"ok load", fun() ->
|
||||
File = "emqx-conf-test-tmp-file-load-ok.hocon",
|
||||
with_file(File, "plugins: {}", fun() ->
|
||||
?assertMatch({ok, _}, emqx_hocon:load_and_check(emqx_conf_schema, File))
|
||||
end)
|
||||
end}
|
||||
].
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
PROJ_DIR="$(git rev-parse --show-toplevel)"
|
||||
|
||||
PROFILE="${PROFILE:-emqx}"
|
||||
DIR_NAME='examples'
|
||||
SCHEMA_MOD='emqx_conf_schema'
|
||||
if [ "${PROFILE}" = 'emqx-enterprise' ]; then
|
||||
DIR_NAME='ee-examples'
|
||||
SCHEMA_MOD='emqx_enterprise_schema'
|
||||
PA=""
|
||||
fi
|
||||
|
||||
IFS=$'\n' read -r -d '' -a FILES < <(find "${PROJ_DIR}/rel/config/${DIR_NAME}" -name "*.example" 2>/dev/null | sort && printf '\0')
|
||||
|
||||
prepare_erl_libs() {
|
||||
local libs_dir="$1"
|
||||
local erl_libs="${ERL_LIBS:-}"
|
||||
local sep=':'
|
||||
for app in "${libs_dir}"/*; do
|
||||
if [ -d "${app}/ebin" ]; then
|
||||
if [ -n "$erl_libs" ]; then
|
||||
erl_libs="${erl_libs}${sep}${app}"
|
||||
else
|
||||
erl_libs="${app}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
export ERL_LIBS="$erl_libs"
|
||||
}
|
||||
|
||||
# This is needed when checking schema
|
||||
export EMQX_ETC_DIR="${PROJ_DIR}/apps/emqx/etc"
|
||||
|
||||
prepare_erl_libs "_build/$PROFILE/lib"
|
||||
|
||||
check_file() {
|
||||
local file="$1"
|
||||
erl -noshell -eval \
|
||||
"File=\"$file\",
|
||||
case emqx_hocon:load_and_check($SCHEMA_MOD, File) of
|
||||
{ok, _} ->
|
||||
io:format(\"check_example_config_ok: ~s~n\", [File]),
|
||||
halt(0);
|
||||
{error, Reason} ->
|
||||
io:format(\"failed_to_check_example_config: ~s~n~p~n\", [File, Reason]),
|
||||
halt(1)
|
||||
end."
|
||||
}
|
||||
|
||||
for file in ${FILES[@]}; do
|
||||
check_file "$file"
|
||||
done
|
Loading…
Reference in New Issue