Skip to content

Commit

Permalink
Merge pull request #254 from emqx/convert-to-different-type-crash
Browse files Browse the repository at this point in the history
fix: convert to different union type crash
  • Loading branch information
zhongwencool authored May 4, 2023
2 parents b1ccc20 + 946344b commit 1ef1695
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/hocon_tconf.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,7 @@ maybe_mkrich(_, undefined, _Box) ->
maybe_mkrich(#{format := map}, Value, _Box) ->
Value;
maybe_mkrich(#{format := richmap}, Value, Box) ->
hocon_maps:deep_merge(Box, mkrich(Value, Box)).
mkrich(Value, Box).

mkrich(Arr, Box) when is_list(Arr) ->
NewArr = [mkrich(I, Box) || I <- Arr],
Expand Down
78 changes: 77 additions & 1 deletion test/hocon_tconf_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,82 @@ converter_test() ->
hocon_tconf:check_plain(Sc, BadIn)
).

%% converter can be used to convert a value to a different type
%% From ref(bar) to map(name, ref(bar)).
converter_type_test() ->
Sc = #{
roots => [
{f1,
hoconsc:mk(
hoconsc:union([
hoconsc:ref(?MODULE, bar), hoconsc:map(name, hoconsc:ref(?MODULE, bar))
]),
#{
converter => fun(Conf, _Opts) ->
Fields = lists:map(fun({F, _}) -> atom_to_binary(F) end, fields(bar)),
DefaultBar = maps:with(Fields, Conf),
MapBar = maps:without(Fields, Conf),
hocon_maps:deep_merge(MapBar, #{<<"default">> => DefaultBar})
end
}
)}
]
},
Inputs = [
"{f1.field1: \"foo1\"}",
""
"\n"
" {f1 {field1: foo1\n"
" host: \"127.0.0.1\",\n"
" my-test-name: {\n"
" field1: \"test-name\"\n"
" },\n"
" default: {\n"
" field1: \"default-field1\"\n"
" }\n"
" }\n"
" }\n"
" "
""
],
Expects = [
#{
<<"f1">> =>
#{
<<"default">> =>
#{<<"field1">> => "foo1", <<"union_with_default">> => dummy}
}
},
#{
<<"f1">> =>
#{
<<"default">> =>
#{
<<"field1">> => "foo1",
<<"union_with_default">> => dummy,
<<"host">> => "127.0.0.1"
},
<<"my-test-name">> =>
#{
<<"field1">> => "test-name",
<<"union_with_default">> => dummy
}
}
}
],
lists:foreach(
fun({Input, Expect}) ->
{ok, PlainConf} = hocon:binary(Input, #{format => map}),
{ok, RichConf} = hocon:binary(Input, #{format => richmap}),
PlainConverted = hocon_tconf:check_plain(Sc, PlainConf),
RichConverted = richmap_to_map(hocon_tconf:check(Sc, RichConf)),
?assertEqual(PlainConverted, RichConverted),
?assertEqual(Expect, PlainConverted)
end,
lists:zip(Inputs, Expects)
),
ok.

converter_non_primitive_test() ->
Sc = #{
roots => [
Expand Down Expand Up @@ -1125,7 +1201,7 @@ converter_return_undefined_test() ->
]
},
Input = #{<<"f1">> => <<"1">>},
%% assert that converter ruturning 'undefined' has no effect
%% assert that converter returning 'undefined' has no effect
%% this is a limitation of current version:
%% there is no way to 'remove' a config value by converting values to 'undefined'
%% use 'deprecated' instead
Expand Down

0 comments on commit 1ef1695

Please sign in to comment.