%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2008-2017. 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.
%%
%% %CopyrightEnd%
%%
-module(uri_string_SUITE).
-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,
parse_binary_fragment/1, parse_binary_host/1, parse_binary_host_ipv4/1,
parse_binary_host_ipv6/1,
parse_binary_path/1, parse_binary_pct_encoded_fragment/1, parse_binary_pct_encoded_query/1,
parse_binary_pct_encoded_userinfo/1, parse_binary_port/1,
parse_binary_query/1, parse_binary_scheme/1, parse_binary_userinfo/1,
parse_fragment/1, parse_host/1, parse_host_ipv4/1, parse_host_ipv6/1,
parse_path/1, parse_pct_encoded_fragment/1, parse_pct_encoded_query/1,
parse_pct_encoded_userinfo/1, parse_port/1,
parse_query/1, parse_scheme/1, parse_userinfo/1,
parse_list/1, parse_binary/1, parse_mixed/1, parse_relative/1,
parse_special/1, parse_special2/1,
recompose_fragment/1, recompose_parse_fragment/1,
recompose_query/1, recompose_parse_query/1,
recompose_path/1, recompose_parse_path/1,
recompose_autogen/1, parse_recompose_autogen/1
]).
-define(SCHEME, "foo").
-define(USERINFO, "åsa").
-define(USERINFO_ENC, "%C3%A5sa").
-define(HOST, "älvsjö").
-define(HOST_ENC, "%C3%A4lvsj%C3%B6").
-define(IPV6, "::127.0.0.1").
-define(IPV6_ENC, "[::127.0.0.1]").
-define(PORT, 8042).
-define(PORT_ENC, ":8042").
-define(PATH, "/där").
-define(PATH_ENC, "/d%C3%A4r").
-define(QUERY, "?name=örn").
-define(QUERY_ENC, "?name=%C3%B6rn").
-define(FRAGMENT, "näsa").
-define(FRAGMENT_ENC, "#n%C3%A4sa").
suite() ->
[{timetrap,{minutes,1}}].
all() ->
[
parse_binary_scheme,
parse_binary_userinfo,
parse_binary_pct_encoded_userinfo,
parse_binary_host,
parse_binary_host_ipv4,
parse_binary_host_ipv6,
parse_binary_port,
parse_binary_path,
parse_binary_query,
parse_binary_pct_encoded_query,
parse_binary_fragment,
parse_binary_pct_encoded_fragment,
parse_scheme,
parse_userinfo,
parse_pct_encoded_userinfo,
parse_host,
parse_host_ipv4,
parse_host_ipv6,
parse_port,
parse_path,
parse_query,
parse_pct_encoded_query,
parse_fragment,
parse_pct_encoded_fragment,
parse_list,
parse_binary,
parse_mixed,
parse_relative,
parse_special,
parse_special2,
recompose_fragment,
recompose_parse_fragment,
recompose_query,
recompose_parse_query,
recompose_path,
recompose_parse_path,
recompose_autogen,
parse_recompose_autogen
].
groups() ->
[].
%%-------------------------------------------------------------------------
%% Helper functions
%%-------------------------------------------------------------------------
uri_combinations() ->
[[Sch,Usr,Hst,Prt,Pat,Qry,Frg] ||
Sch <- [fun update_scheme/1, fun update_scheme_binary/1, none],
Usr <- [fun update_userinfo/1, fun update_userinfo_binary/1, none],
Hst <- [fun update_host/1, fun update_host_binary/1,
fun update_ipv6/1, fun update_ipv6_binary/1, none],
Prt <- [fun update_port/1, none],
Pat <- [fun update_path/1, fun update_path_binary/1],
Qry <- [fun update_query/1,fun update_query_binary/1, none],
Frg <- [fun update_fragment/1, fun update_fragment_binary/1, none],
not (Usr =:= none andalso Hst =:= none andalso Prt =/= none),
not (Usr =/= none andalso Hst =:= none andalso Prt =:= none),
not (Usr =/= none andalso Hst =:= none andalso Prt =/= none)].
generate_test_vector(Comb) ->
Fun = fun (F, {Map, URI}) when is_function(F) -> F({Map, URI});
(_, Map) -> Map
end,
lists:foldl(Fun, {#{}, empty}, Comb).
generate_test_vectors(L) ->
lists:map(fun generate_test_vector/1, L).
update_fragment({In, empty}) ->
{In#{fragment => ?FRAGMENT}, ?FRAGMENT_ENC};
update_fragment({In, Out}) when is_list(Out) ->
{In#{fragment => ?FRAGMENT}, Out ++ ?FRAGMENT_ENC};
update_fragment({In, Out}) when is_binary(Out) ->
{In#{fragment => ?FRAGMENT}, binary_to_list(Out) ++ ?FRAGMENT_ENC}.
update_fragment_binary({In, empty}) ->
{In#{fragment => <<?FRAGMENT/utf8>>}, <<?FRAGMENT_ENC>>};
update_fragment_binary({In, Out}) when is_list(Out) ->
{In#{fragment => <<?FRAGMENT/utf8>>}, Out ++ ?FRAGMENT_ENC};
update_fragment_binary({In, Out}) when is_binary(Out) ->
{In#{fragment => <<?FRAGMENT/utf8>>}, <<Out/binary,?FRAGMENT_ENC>>}.
update_query({In, empty}) ->
{In#{query => ?QUERY}, ?QUERY_ENC};
update_query({In, Out}) when is_list(Out) ->
{In#{query => ?QUERY}, Out ++ ?QUERY_ENC};
update_query({In, Out}) when is_binary(Out) ->
{In#{query => ?QUERY}, binary_to_list(Out) ++ ?QUERY_ENC}.
update_query_binary({In, empty}) ->
{In#{query => <<?QUERY/utf8>>}, <<?QUERY_ENC>>};
update_query_binary({In, Out}) when is_list(Out) ->
{In#{query => <<?QUERY/utf8>>}, Out ++ ?QUERY_ENC};
update_query_binary({In, Out}) when is_binary(Out) ->
{In#{query => <<?QUERY/utf8>>}, <<Out/binary,?QUERY_ENC>>}.
update_path({In, empty}) ->
{In#{path => ?PATH}, ?PATH_ENC};
update_path({In, Out}) when is_list(Out) ->
{In#{path => ?PATH}, Out ++ ?PATH_ENC};
update_path({In, Out}) when is_binary(Out) ->
{In#{path => ?PATH}, binary_to_list(Out) ++ ?PATH_ENC}.
update_path_binary({In, empty}) ->
{In#{path => <<?PATH/utf8>>}, <<?PATH_ENC>>};
update_path_binary({In, Out}) when is_list(Out) ->
{In#{path => <<?PATH/utf8>>}, Out ++ ?PATH_ENC};
update_path_binary({In, Out}) when is_binary(Out) ->
{In#{path => <<?PATH/utf8>>}, <<Out/binary,?PATH_ENC>>}.
update_port({In, Out}) when is_list(Out) ->
{In#{port => ?PORT}, Out ++ ?PORT_ENC};
update_port({In, Out}) when is_binary(Out) ->
{In#{port => ?PORT}, <<Out/binary,?PORT_ENC>>}.
update_host({In, empty}) ->
{In#{host => ?HOST}, "//" ++ ?HOST_ENC};
update_host({In, Out}) when is_list(Out) ->
case maps:is_key(userinfo, In) of
true -> {In#{host => ?HOST}, Out ++ [$@|?HOST_ENC]};
false -> {In#{host => ?HOST}, Out ++ [$/,$/|?HOST_ENC]}
end;
update_host({In, Out}) when is_binary(Out) ->
case maps:is_key(userinfo, In) of
true -> {In#{host => ?HOST}, binary_to_list(Out) ++ [$@|?HOST_ENC]};
false -> {In#{host => ?HOST}, binary_to_list(Out) ++ [$/,$/|?HOST_ENC]}
end.
update_host_binary({In, empty}) ->
{In#{host => <<?HOST/utf8>>}, <<"//",?HOST_ENC>>};
update_host_binary({In, Out}) when is_list(Out) ->
case maps:is_key(userinfo, In) of
true -> {In#{host => <<?HOST/utf8>>}, Out ++ [$@|?HOST_ENC]};
false -> {In#{host => <<?HOST/utf8>>}, Out ++ [$/,$/|?HOST_ENC]}
end;
update_host_binary({In, Out}) when is_binary(Out) ->
case maps:is_key(userinfo, In) of
true -> {In#{host => <<?HOST/utf8>>}, <<Out/binary,$@,?HOST_ENC>>};
false-> {In#{host => <<?HOST/utf8>>}, <<Out/binary,"//",?HOST_ENC>>}
end.
update_ipv6({In, empty}) ->
{In#{host => ?IPV6}, "//" ++ ?IPV6_ENC};
update_ipv6({In, Out}) when is_list(Out) ->
case maps:is_key(userinfo, In) of
true -> {In#{host => ?IPV6}, Out ++ [$@|?IPV6_ENC]};
false -> {In#{host => ?IPV6}, Out ++ [$/,$/|?IPV6_ENC]}
end;
update_ipv6({In, Out}) when is_binary(Out) ->
case maps:is_key(userinfo, In) of
true -> {In#{host => ?IPV6}, binary_to_list(Out) ++ [$@|?IPV6_ENC]};
false -> {In#{host => ?IPV6}, binary_to_list(Out) ++ [$/,$/|?IPV6_ENC]}
end.
update_ipv6_binary({In, empty}) ->
{In#{host => <<?IPV6/utf8>>}, <<"//",?IPV6_ENC>>};
update_ipv6_binary({In, Out}) when is_list(Out) ->
case maps:is_key(userinfo, In) of
true -> {In#{host => <<?IPV6/utf8>>}, Out ++ [$@|?IPV6_ENC]};
false -> {In#{host => <<?IPV6/utf8>>}, Out ++ [$/,$/|?IPV6_ENC]}
end;
update_ipv6_binary({In, Out}) when is_binary(Out) ->
case maps:is_key(userinfo, In) of
true -> {In#{host => <<?IPV6/utf8>>}, <<Out/binary,$@,?IPV6_ENC>>};
false-> {In#{host => <<?IPV6/utf8>>}, <<Out/binary,"//",?IPV6_ENC>>}
end.
update_userinfo({In, empty}) ->
{In#{userinfo => ?USERINFO}, "//" ++ ?USERINFO_ENC};
update_userinfo({In, Out}) when is_list(Out) ->
{In#{userinfo => ?USERINFO}, Out ++ "//" ++ ?USERINFO_ENC};
update_userinfo({In, Out}) when is_binary(Out) ->
{In#{userinfo => ?USERINFO}, binary_to_list(Out) ++ "//" ++ ?USERINFO_ENC}.
update_userinfo_binary({In, empty}) ->
{In#{userinfo => <<?USERINFO/utf8>>}, <<"//",?USERINFO_ENC>>};
update_userinfo_binary({In, Out}) when is_list(Out) ->
{In#{userinfo => <<?USERINFO/utf8>>}, Out ++ "//" ++ ?USERINFO_ENC};
update_userinfo_binary({In, Out}) when is_binary(Out) ->
{In#{userinfo => <<?USERINFO/utf8>>}, <<Out/binary,"//",?USERINFO_ENC>>}.
update_scheme({In, empty}) ->
{In#{scheme => ?SCHEME}, ?SCHEME ++ ":"}.
update_scheme_binary({In, empty}) ->
{In#{scheme => <<?SCHEME/utf8>>}, <<?SCHEME,$:>>}.
%% Test recompose on a generated test vector
run_test_recompose({#{}, empty}) ->
try "" = uri_string:recompose(#{}) of
_ -> ok
catch
_:_ -> error({test_failed, #{}, ""})
end;
run_test_recompose({Map, URI}) ->
try URI = uri_string:recompose(Map) of
URI -> ok
catch
_:_ -> error({test_failed, Map, URI})
end.
%% Test parse - recompose on a generated test vector
run_test_parse_recompose({#{}, empty}) ->
try "" = uri_string:recompose(uri_string:parse("")) of
_ -> ok
catch
_:_ -> error({test_failed, #{}, ""})
end;
run_test_parse_recompose({Map, URI}) ->
try URI = uri_string:recompose(uri_string:parse(URI)) of
URI -> ok
catch
_:_ -> error({test_failed, Map, URI})
end.
%%-------------------------------------------------------------------------
%% Parse tests
%%-------------------------------------------------------------------------
parse_binary_scheme(_Config) ->
#{} = uri_string:parse(<<>>),
#{path := <<"foo">>} = uri_string:parse(<<"foo">>),
#{scheme := <<"foo">>} = uri_string:parse(<<"foo:">>),
#{scheme := <<"foo">>, path := <<"bar:nisse">>} = uri_string:parse(<<"foo:bar:nisse">>),
#{scheme := <<"foo">>, host := <<"">>} = uri_string:parse(<<"foo://">>),
#{scheme := <<"foo">>, host := <<"">>, path := <<"/">>} = uri_string:parse(<<"foo:///">>),
#{scheme := <<"foo">>, host := <<"">>, path := <<"//">>} = uri_string:parse(<<"foo:////">>),
#{path := <<"/">>} = uri_string:parse(<<"/">>),
#{host := <<>>} = uri_string:parse(<<"//">>),
#{host := <<>>, path := <<"/">>} = uri_string:parse(<<"///">>).
parse_binary_userinfo(_Config) ->
#{scheme := <<"user">>, path := <<"password@localhost">>} =
uri_string:parse(<<"user:password@localhost">>),
#{path := <<"user@">>} = uri_string:parse(<<"user@">>),
#{path := <<"/user@">>} = uri_string:parse(<<"/user@">>),
#{path := <<"user@localhost">>} = uri_string:parse(<<"user@localhost">>),
#{userinfo := <<"user">>, host := <<"localhost">>} = uri_string:parse(<<"//user@localhost">>),
#{userinfo := <<"user:password">>, host := <<"localhost">>} =
uri_string:parse(<<"//user:password@localhost">>),
#{scheme := <<"foo">>, path := <<"/user@">>} =
uri_string:parse(<<"foo:/user@">>),
#{scheme := <<"foo">>, userinfo := <<"user">>, host := <<"localhost">>} =
uri_string:parse(<<"foo://user@localhost">>),
#{scheme := <<"foo">>, userinfo := <<"user:password">>, host := <<"localhost">>} =
uri_string:parse(<<"foo://user:password@localhost">>).
parse_binary_pct_encoded_userinfo(_Config) ->
#{scheme := <<"user">>, path := <<"合@気道"/utf8>>} =
uri_string:parse(<<"user:%E5%90%88@%E6%B0%97%E9%81%93">>),
#{path := <<"合気道@"/utf8>>} = uri_string:parse(<<"%E5%90%88%E6%B0%97%E9%81%93@">>),
#{path := <<"/合気道@"/utf8>>} = uri_string:parse(<<"/%E5%90%88%E6%B0%97%E9%81%93@">>),
#{path := <<"合@気道"/utf8>>} = uri_string:parse(<<"%E5%90%88@%E6%B0%97%E9%81%93">>),
#{userinfo := <<"合"/utf8>>, host := <<"気道"/utf8>>} =
uri_string:parse(<<"//%E5%90%88@%E6%B0%97%E9%81%93">>),
#{userinfo := <<"合:気"/utf8>>, host := <<"道"/utf8>>} =
uri_string:parse(<<"//%E5%90%88:%E6%B0%97@%E9%81%93">>),
#{scheme := <<"foo">>, path := <<"/合気道@"/utf8>>} =
uri_string:parse(<<"foo:/%E5%90%88%E6%B0%97%E9%81%93@">>),
#{scheme := <<"foo">>, userinfo := <<"合"/utf8>>, host := <<"気道"/utf8>>} =
uri_string:parse(<<"foo://%E5%90%88@%E6%B0%97%E9%81%93">>),
#{scheme := <<"foo">>, userinfo := <<"合:気"/utf8>>, host := <<"道"/utf8>>} =
uri_string:parse(<<"foo://%E5%90%88:%E6%B0%97@%E9%81%93">>),
uri_parse_error =(catch uri_string:parse(<<"//%E5%90%88@%E6%B0%97%E9%81%93@">>)),
uri_parse_error = (catch uri_string:parse(<<"foo://%E5%90%88@%E6%B0%97%E9%81%93@">>)).
parse_binary_host(_Config) ->
#{host := <<"hostname">>} = uri_string:parse(<<"//hostname">>),
#{host := <<"hostname">>,scheme := <<"foo">>} = uri_string:parse(<<"foo://hostname">>),
#{host := <<"hostname">>,scheme := <<"foo">>, userinfo := <<"user">>} =
uri_string:parse(<<"foo://user@hostname">>).
parse_binary_host_ipv4(_Config) ->
#{host := <<"127.0.0.1">>} = uri_string:parse(<<"//127.0.0.1">>),
#{host := <<"127.0.0.1">>, path := <<"/over/there">>} =
uri_string:parse(<<"//127.0.0.1/over/there">>),
#{host := <<"127.0.0.1">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"//127.0.0.1?name=ferret">>),
#{host := <<"127.0.0.1">>, fragment := <<"nose">>} = uri_string:parse(<<"//127.0.0.1#nose">>),
uri_parse_error = (catch uri_string:parse(<<"//127.0.0.x">>)),
uri_parse_error = (catch uri_string:parse(<<"//1227.0.0.1">>)).
parse_binary_host_ipv6(_Config) ->
#{host := <<"::127.0.0.1">>} = uri_string:parse(<<"//[::127.0.0.1]">>),
#{host := <<"2001:0db8:0000:0000:0000:0000:1428:07ab">>} =
uri_string:parse(<<"//[2001:0db8:0000:0000:0000:0000:1428:07ab]">>),
#{host := <<"::127.0.0.1">>, path := <<"/over/there">>} =
uri_string:parse(<<"//[::127.0.0.1]/over/there">>),
#{host := <<"::127.0.0.1">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"//[::127.0.0.1]?name=ferret">>),
#{host := <<"::127.0.0.1">>, fragment := <<"nose">>} =
uri_string:parse(<<"//[::127.0.0.1]#nose">>),
uri_parse_error = (catch uri_string:parse(<<"//[::127.0.0.x]">>)),
uri_parse_error = (catch uri_string:parse(<<"//[::1227.0.0.1]">>)),
uri_parse_error = (catch uri_string:parse(<<"//[2001:0db8:0000:0000:0000:0000:1428:G7ab]">>)).
parse_binary_port(_Config) ->
#{path:= <<"/:8042">>} =
uri_string:parse(<<"/:8042">>),
#{host:= <<>>, port := 8042} =
uri_string:parse(<<"//:8042">>),
#{host := <<"example.com">>, port:= 8042} =
uri_string:parse(<<"//example.com:8042">>),
#{scheme := <<"foo">>, path := <<"/:8042">>} =
uri_string:parse(<<"foo:/:8042">>),
#{scheme := <<"foo">>, host := <<>>, port := 8042} =
uri_string:parse(<<"foo://:8042">>),
#{scheme := <<"foo">>, host := <<"example.com">>, port := 8042} =
uri_string:parse(<<"foo://example.com:8042">>),
uri_parse_error = (catch uri_string:parse(":600")),
uri_parse_error = (catch uri_string:parse("//:8042x")).
parse_binary_path(_Config) ->
#{path := <<"over/there">>} = uri_string:parse(<<"over/there">>),
#{path := <<"/over/there">>} = uri_string:parse(<<"/over/there">>),
#{scheme := <<"foo">>, path := <<"/over/there">>} =
uri_string:parse(<<"foo:/over/there">>),
#{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/over/there">>} =
uri_string:parse(<<"foo://example.com/over/there">>),
#{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/over/there">>, port := 8042} =
uri_string:parse(<<"foo://example.com:8042/over/there">>).
parse_binary_query(_Config) ->
#{scheme := <<"foo">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"foo:?name=ferret">>),
#{scheme := <<"foo">>, path:= <<"over/there">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"foo:over/there?name=ferret">>),
#{scheme := <<"foo">>, path:= <<"/over/there">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"foo:/over/there?name=ferret">>),
#{scheme := <<"foo">>, host := <<"example.com">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"foo://example.com?name=ferret">>),
#{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"foo://example.com/?name=ferret">>),
#{query := <<"?name=ferret">>} =
uri_string:parse(<<"?name=ferret">>),
#{path := <<"over/there">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"over/there?name=ferret">>),
#{path := <<"/">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"/?name=ferret">>),
#{path := <<"/over/there">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"/over/there?name=ferret">>),
#{host := <<"example.com">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"//example.com?name=ferret">>),
#{host := <<"example.com">>, path := <<"/">>, query := <<"?name=ferret">>} =
uri_string:parse(<<"//example.com/?name=ferret">>).
parse_binary_pct_encoded_query(_Config) ->
#{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/">>,
query := <<"?name=合気道"/utf8>>} =
uri_string:parse(<<"foo://example.com/?name=%E5%90%88%E6%B0%97%E9%81%93">>),
#{host := <<"example.com">>, path := <<"/">>, query := <<"?name=合気道"/utf8>>} =
uri_string:parse(<<"//example.com/?name=%E5%90%88%E6%B0%97%E9%81%93">>).
parse_binary_fragment(_Config) ->
#{scheme := <<"foo">>, fragment := <<"nose">>} =
uri_string:parse(<<"foo:#nose">>),
#{scheme := <<"foo">>, path:= <<"over/there">>, fragment := <<"nose">>} =
uri_string:parse(<<"foo:over/there#nose">>),
#{scheme := <<"foo">>, path:= <<"/over/there">>, fragment := <<"nose">>} =
uri_string:parse(<<"foo:/over/there#nose">>),
#{scheme := <<"foo">>, host := <<"example.com">>, fragment := <<"nose">>} =
uri_string:parse(<<"foo://example.com#nose">>),
#{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/">>, fragment := <<"nose">>} =
uri_string:parse(<<"foo://example.com/#nose">>),
#{scheme := <<"foo">>, host := <<"example.com">>, fragment := <<"nose">>} =
uri_string:parse(<<"foo://example.com#nose">>),
#{fragment := <<"nose">>} =
uri_string:parse(<<"#nose">>),
#{path := <<"over/there">>, fragment := <<"nose">>} =
uri_string:parse(<<"over/there#nose">>),
#{path := <<"/">>, fragment := <<"nose">>} =
uri_string:parse(<<"/#nose">>),
#{path := <<"/over/there">>, fragment := <<"nose">>} =
uri_string:parse(<<"/over/there#nose">>),
#{host := <<"example.com">>, fragment := <<"nose">>} =
uri_string:parse(<<"//example.com#nose">>),
#{host := <<"example.com">>, path := <<"/">>, fragment := <<"nose">>} =
uri_string:parse(<<"//example.com/#nose">>).
parse_binary_pct_encoded_fragment(_Config) ->
#{scheme := <<"foo">>, host := <<"example.com">>, fragment := <<"合気道"/utf8>>} =
uri_string:parse(<<"foo://example.com#%E5%90%88%E6%B0%97%E9%81%93">>),
#{host := <<"example.com">>, path := <<"/">>, fragment := <<"合気道"/utf8>>} =
uri_string:parse(<<"//example.com/#%E5%90%88%E6%B0%97%E9%81%93">>).
parse_scheme(_Config) ->
#{} = uri_string:parse(""),
#{path := "foo"} = uri_string:parse("foo"),
#{scheme := "foo"} = uri_string:parse("foo:"),
#{scheme := "foo", path := "bar:nisse"} = uri_string:parse("foo:bar:nisse"),
#{scheme := "foo", host := ""} = uri_string:parse("foo://"),
#{scheme := "foo", host := "", path := "/"} = uri_string:parse("foo:///"),
#{scheme := "foo", host := "", path := "//"} = uri_string:parse("foo:////"),
#{path := "/"} = uri_string:parse("/"),
#{host := ""} = uri_string:parse("//"),
#{host := "", path := "/"} = uri_string:parse("///").
parse_userinfo(_Config) ->
#{scheme := "user", path := "password@localhost"} = uri_string:parse("user:password@localhost"),
#{path := "user@"} = uri_string:parse("user@"),
#{path := "/user@"} = uri_string:parse("/user@"),
#{path := "user@localhost"} = uri_string:parse("user@localhost"),
#{userinfo := "user", host := "localhost"} = uri_string:parse("//user@localhost"),
#{userinfo := "user:password", host := "localhost"} =
uri_string:parse("//user:password@localhost"),
#{scheme := "foo", path := "/user@"} =
uri_string:parse("foo:/user@"),
#{scheme := "foo", userinfo := "user", host := "localhost"} =
uri_string:parse("foo://user@localhost"),
#{scheme := "foo", userinfo := "user:password", host := "localhost"} =
uri_string:parse("foo://user:password@localhost").
parse_pct_encoded_userinfo(_Config) ->
#{scheme := "user", path := "合@気道"} =
uri_string:parse("user:%E5%90%88@%E6%B0%97%E9%81%93"),
#{path := "合気道@"} = uri_string:parse("%E5%90%88%E6%B0%97%E9%81%93@"),
#{path := "/合気道@"} = uri_string:parse("/%E5%90%88%E6%B0%97%E9%81%93@"),
#{path := "合@気道"} = uri_string:parse("%E5%90%88@%E6%B0%97%E9%81%93"),
#{userinfo := "合", host := "気道"} =
uri_string:parse("//%E5%90%88@%E6%B0%97%E9%81%93"),
#{userinfo := "合:気", host := "道"} =
uri_string:parse("//%E5%90%88:%E6%B0%97@%E9%81%93"),
#{scheme := "foo", path := "/合気道@"} =
uri_string:parse("foo:/%E5%90%88%E6%B0%97%E9%81%93@"),
#{scheme := "foo", userinfo := "合", host := "気道"} =
uri_string:parse("foo://%E5%90%88@%E6%B0%97%E9%81%93"),
#{scheme := "foo", userinfo := "合:気", host := "道"} =
uri_string:parse("foo://%E5%90%88:%E6%B0%97@%E9%81%93"),
uri_parse_error =(catch uri_string:parse("//%E5%90%88@%E6%B0%97%E9%81%93@")),
uri_parse_error = (catch uri_string:parse("foo://%E5%90%88@%E6%B0%97%E9%81%93@")).
parse_host(_Config) ->
#{host := "hostname"} = uri_string:parse("//hostname"),
#{host := "hostname",scheme := "foo"} = uri_string:parse("foo://hostname"),
#{host := "hostname",scheme := "foo", userinfo := "user"} =
uri_string:parse("foo://user@hostname").
parse_host_ipv4(_Config) ->
#{host := "127.0.0.1"} = uri_string:parse("//127.0.0.1"),
#{host := "2001:0db8:0000:0000:0000:0000:1428:07ab"} =
uri_string:parse("//[2001:0db8:0000:0000:0000:0000:1428:07ab]"),
#{host := "127.0.0.1", path := "/over/there"} = uri_string:parse("//127.0.0.1/over/there"),
#{host := "127.0.0.1", query := "?name=ferret"} = uri_string:parse("//127.0.0.1?name=ferret"),
#{host := "127.0.0.1", fragment := "nose"} = uri_string:parse("//127.0.0.1#nose"),
uri_parse_error = (catch uri_string:parse("//127.0.0.x")),
uri_parse_error = (catch uri_string:parse("//1227.0.0.1")).
parse_host_ipv6(_Config) ->
#{host := "::127.0.0.1"} = uri_string:parse("//[::127.0.0.1]"),
#{host := "::127.0.0.1", path := "/over/there"} = uri_string:parse("//[::127.0.0.1]/over/there"),
#{host := "::127.0.0.1", query := "?name=ferret"} =
uri_string:parse("//[::127.0.0.1]?name=ferret"),
#{host := "::127.0.0.1", fragment := "nose"} = uri_string:parse("//[::127.0.0.1]#nose"),
uri_parse_error = (catch uri_string:parse("//[::127.0.0.x]")),
uri_parse_error = (catch uri_string:parse("//[::1227.0.0.1]")),
uri_parse_error = (catch uri_string:parse("//[2001:0db8:0000:0000:0000:0000:1428:G7ab]")).
parse_port(_Config) ->
#{path:= "/:8042"} =
uri_string:parse("/:8042"),
#{host:= "", port := 8042} =
uri_string:parse("//:8042"),
#{host := "example.com", port:= 8042} =
uri_string:parse("//example.com:8042"),
#{scheme := "foo", path := "/:8042"} =
uri_string:parse("foo:/:8042"),
#{scheme := "foo", host := "", port := 8042} =
uri_string:parse("foo://:8042"),
#{scheme := "foo", host := "example.com", port := 8042} =
uri_string:parse("foo://example.com:8042").
parse_path(_Config) ->
#{path := "over/there"} = uri_string:parse("over/there"),
#{path := "/over/there"} = uri_string:parse("/over/there"),
#{scheme := "foo", path := "/over/there"} =
uri_string:parse("foo:/over/there"),
#{scheme := "foo", host := "example.com", path := "/over/there"} =
uri_string:parse("foo://example.com/over/there"),
#{scheme := "foo", host := "example.com", path := "/over/there", port := 8042} =
uri_string:parse("foo://example.com:8042/over/there").
parse_query(_Config) ->
#{scheme := "foo", query := "?name=ferret"} =
uri_string:parse("foo:?name=ferret"),
#{scheme := "foo", path:= "over/there", query := "?name=ferret"} =
uri_string:parse("foo:over/there?name=ferret"),
#{scheme := "foo", path:= "/over/there", query := "?name=ferret"} =
uri_string:parse("foo:/over/there?name=ferret"),
#{scheme := "foo", host := "example.com", query := "?name=ferret"} =
uri_string:parse("foo://example.com?name=ferret"),
#{scheme := "foo", host := "example.com", path := "/", query := "?name=ferret"} =
uri_string:parse("foo://example.com/?name=ferret"),
#{query := "?name=ferret"} =
uri_string:parse("?name=ferret"),
#{path := "over/there", query := "?name=ferret"} =
uri_string:parse("over/there?name=ferret"),
#{path := "/", query := "?name=ferret"} =
uri_string:parse("/?name=ferret"),
#{path := "/over/there", query := "?name=ferret"} =
uri_string:parse("/over/there?name=ferret"),
#{host := "example.com", query := "?name=ferret"} =
uri_string:parse("//example.com?name=ferret"),
#{host := "example.com", path := "/", query := "?name=ferret"} =
uri_string:parse("//example.com/?name=ferret").
parse_pct_encoded_query(_Config) ->
#{scheme := "foo", host := "example.com", path := "/",
query := "?name=合気道"} =
uri_string:parse("foo://example.com/?name=%E5%90%88%E6%B0%97%E9%81%93"),
#{host := "example.com", path := "/", query := "?name=合気道"} =
uri_string:parse("//example.com/?name=%E5%90%88%E6%B0%97%E9%81%93").
parse_fragment(_Config) ->
#{scheme := "foo", fragment := "nose"} =
uri_string:parse("foo:#nose"),
#{scheme := "foo", path:= "over/there", fragment := "nose"} =
uri_string:parse("foo:over/there#nose"),
#{scheme := "foo", path:= "/over/there", fragment := "nose"} =
uri_string:parse("foo:/over/there#nose"),
#{scheme := "foo", host := "example.com", fragment := "nose"} =
uri_string:parse("foo://example.com#nose"),
#{scheme := "foo", host := "example.com", path := "/", fragment := "nose"} =
uri_string:parse("foo://example.com/#nose"),
#{scheme := "foo", host := "example.com", fragment := "nose"} =
uri_string:parse("foo://example.com#nose"),
#{fragment := "nose"} =
uri_string:parse("#nose"),
#{path := "over/there", fragment := "nose"} =
uri_string:parse("over/there#nose"),
#{path := "/", fragment := "nose"} =
uri_string:parse("/#nose"),
#{path := "/over/there", fragment := "nose"} =
uri_string:parse("/over/there#nose"),
#{host := "example.com", fragment := "nose"} =
uri_string:parse("//example.com#nose"),
#{host := "example.com", path := "/", fragment := "nose"} =
uri_string:parse("//example.com/#nose").
parse_pct_encoded_fragment(_Config) ->
#{scheme := "foo", host := "example.com", fragment := "合気道"} =
uri_string:parse("foo://example.com#%E5%90%88%E6%B0%97%E9%81%93"),
#{host := "example.com", path := "/", fragment := "合気道"} =
uri_string:parse("//example.com/#%E5%90%88%E6%B0%97%E9%81%93").
parse_list(_Config) ->
#{scheme := "foo", path := "bar:nisse"} = uri_string:parse("foo:bar:nisse"),
#{scheme := "foo", host := "example.com", port := 8042,
path := "/over/there", query := "?name=ferret", fragment := "nose"} =
uri_string:parse("foo://example.com:8042/over/there?name=ferret#nose"),
#{scheme := "foo", userinfo := "admin:admin", host := "example.com", port := 8042,
path := "/over/there", query := "?name=ferret", fragment := "nose"} =
uri_string:parse("foo://admin:[email protected]:8042/over/there?name=ferret#nose").
parse_binary(_Config) ->
#{scheme := <<"foo">>, path := <<"bar:nisse">>} = uri_string:parse(<<"foo:bar:nisse">>),
#{scheme := <<"foo">>, host := <<"example.com">>, port := 8042,
path := <<"/over/there">>, query := <<"?name=ferret">>, fragment := <<"nose">>} =
uri_string:parse(<<"foo://example.com:8042/over/there?name=ferret#nose">>),
#{scheme := <<"foo">>, userinfo := <<"admin:admin">>, host := <<"example.com">>, port := 8042,
path := <<"/over/there">>, query := <<"?name=ferret">>, fragment := <<"nose">>} =
uri_string:parse(<<"foo://admin:[email protected]:8042/over/there?name=ferret#nose">>).
parse_mixed(_Config) ->
#{scheme := "foo", path := "bar"} =
uri_string:parse(lists:append("fo",<<"o:bar">>)),
#{scheme := "foo", path := "bar"} =
uri_string:parse(lists:append("foo:b",<<"ar">>)),
#{scheme := "foo", path := "bar:bar"} =
uri_string:parse([[102],[111,111],<<":bar">>,58,98,97,114]).
parse_relative(_Config) ->
#{path := "/path"} =
uri_string:parse(lists:append("/pa",<<"th">>)),
#{path := "foo"} =
uri_string:parse(lists:append("fo",<<"o">>)).
parse_special(_Config) ->
#{host := [],query := "?"} = uri_string:parse("//?"),
#{fragment := [],host := []} = uri_string:parse("//#"),
#{host := [],query := "?",scheme := "foo"} = uri_string:parse("foo://?"),
#{fragment := [],host := [],scheme := "foo"} = uri_string:parse("foo://#"),
#{host := <<>>, path := <<"/">>} = uri_string:parse(<<"///">>),
#{host := <<"hostname">>} = uri_string:parse(<<"//hostname">>),
#{host := <<>>, path := <<"/hostname">>} = uri_string:parse(<<"///hostname">>),
#{host := [],path := "/",query := "?"} = uri_string:parse("///?"),
#{fragment := [],host := [],path := "/"} = uri_string:parse("///#"),
#{host := "foo",query := "?"} = uri_string:parse("//foo?"),
#{fragment := [],host := "foo"} = uri_string:parse("//foo#"),
#{host := "foo",path := "/"} = uri_string:parse("//foo/"),
#{host := "foo",query := "?",scheme := "http"} = uri_string:parse("http://foo?"),
#{fragment := [],host := "foo",scheme := "http"} = uri_string:parse("http://foo#"),
#{host := "foo",path := "/",scheme := "http"} = uri_string:parse("http://foo/"),
#{fragment := [],host := "host",port := 80,scheme := "http"} = uri_string:parse("http://host:80#"),
#{host := "host",port := 80,query := "?",scheme := "http"} = uri_string:parse("http://host:80?").
parse_special2(_Config) ->
#{host := [],path := "/",port := 1,scheme := "a"} = uri_string:parse("a://:1/"),
#{path := "/a/",scheme := "a"} = uri_string:parse("a:/a/"),
#{host := [],path := [],userinfo := []} = uri_string:parse("//@"),
#{host := [],path := [],scheme := "foo",userinfo := []} = uri_string:parse("foo://@"),
#{host := [],path := "/",userinfo := []} = uri_string:parse("//@/"),
#{host := [],path := "/",scheme := "foo",userinfo := []} = uri_string:parse("foo://@/").
%%-------------------------------------------------------------------------
%% Recompose tests
%%-------------------------------------------------------------------------
recompose_fragment(_Config) ->
<<?FRAGMENT_ENC>> = uri_string:recompose(#{fragment => <<?FRAGMENT/utf8>>, path => <<>>}),
?FRAGMENT_ENC = uri_string:recompose(#{fragment => ?FRAGMENT, path => ""}).
recompose_parse_fragment(_Config) ->
<<?FRAGMENT_ENC>> = uri_string:recompose(uri_string:parse(<<?FRAGMENT_ENC>>)),
?FRAGMENT_ENC = uri_string:recompose(uri_string:parse(?FRAGMENT_ENC)).
recompose_query(_Config) ->
<<?QUERY_ENC>> =
uri_string:recompose(#{query => <<?QUERY/utf8>>, path => <<>>}),
<<?QUERY_ENC?FRAGMENT_ENC>> =
uri_string:recompose(#{query => <<?QUERY/utf8>>,
fragment => <<?FRAGMENT/utf8>>,
path => <<>>}),
"?name=%C3%B6rn" =
uri_string:recompose(#{query => "?name=örn", path => ""}),
"?name=%C3%B6rn#n%C3%A4sa" =
uri_string:recompose(#{query => "?name=örn",
fragment => "näsa",
path => ""}).
recompose_parse_query(_Config) ->
<<"?name=%C3%B6rn">> = uri_string:recompose(uri_string:parse(<<"?name=%C3%B6rn">>)),
<<"?name=%C3%B6rn#n%C3%A4sa">> =
uri_string:recompose(uri_string:parse(<<"?name=%C3%B6rn#n%C3%A4sa">>)),
"?name=%C3%B6rn" = uri_string:recompose(uri_string:parse("?name=%C3%B6rn")),
"?name=%C3%B6rn#n%C3%A4sa" = uri_string:recompose(uri_string:parse("?name=%C3%B6rn#n%C3%A4sa")).
recompose_path(_Config) ->
<<"/d%C3%A4r">> =
uri_string:recompose(#{path => <<"/där"/utf8>>}),
<<"/d%C3%A4r#n%C3%A4sa">> =
uri_string:recompose(#{path => <<"/där"/utf8>>,
fragment => <<"näsa"/utf8>>}),
<<"/d%C3%A4r?name=%C3%B6rn">> =
uri_string:recompose(#{path => <<"/där"/utf8>>,
query => <<"?name=örn"/utf8>>}),
<<"/d%C3%A4r?name=%C3%B6rn#n%C3%A4sa">> =
uri_string:recompose(#{path => <<"/där"/utf8>>,
query => <<"?name=örn"/utf8>>,
fragment => <<"näsa"/utf8>>}),
"/d%C3%A4r" =
uri_string:recompose(#{path => "/där"}),
"/d%C3%A4r#n%C3%A4sa" =
uri_string:recompose(#{path => "/där",
fragment => "näsa"}),
"/d%C3%A4r?name=%C3%B6rn" =
uri_string:recompose(#{path => "/där",
query => "?name=örn"}),
"/d%C3%A4r?name=%C3%B6rn#n%C3%A4sa" =
uri_string:recompose(#{path => "/där",
query => "?name=örn",
fragment => "näsa"}).
recompose_parse_path(_Config) ->
<<"/d%C3%A4r">> =
uri_string:recompose(uri_string:parse(<<"/d%C3%A4r">>)),
<<"/d%C3%A4r#n%C3%A4sa">> =
uri_string:recompose(uri_string:parse(<<"/d%C3%A4r#n%C3%A4sa">>)),
<<"/d%C3%A4r?name=%C3%B6rn">> =
uri_string:recompose(uri_string:parse(<<"/d%C3%A4r?name=%C3%B6rn">>)),
"/d%C3%A4r" =
uri_string:recompose(uri_string:parse("/d%C3%A4r")),
"/d%C3%A4r#n%C3%A4sa" =
uri_string:recompose(uri_string:parse("/d%C3%A4r#n%C3%A4sa")),
"/d%C3%A4r?name=%C3%B6rn" =
uri_string:recompose(uri_string:parse("/d%C3%A4r?name=%C3%B6rn")).
recompose_autogen(_Config) ->
Tests = generate_test_vectors(uri_combinations()),
lists:map(fun run_test_recompose/1, Tests).
parse_recompose_autogen(_Config) ->
Tests = generate_test_vectors(uri_combinations()),
lists:map(fun run_test_parse_recompose/1, Tests).