mirror of
https://github.com/boostorg/url.git
synced 2026-01-19 16:52:14 +00:00
847 lines
28 KiB
C++
847 lines
28 KiB
C++
//
|
|
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
|
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
// Official repository: https://github.com/boostorg/url
|
|
//
|
|
|
|
// Test that header file is self-contained.
|
|
#include <boost/url/segments_encoded_ref.hpp>
|
|
|
|
#include <boost/url/parse.hpp>
|
|
#include <boost/url/url.hpp>
|
|
#include <boost/core/detail/static_assert.hpp>
|
|
#include <boost/core/ignore_unused.hpp>
|
|
|
|
#include "test_suite.hpp"
|
|
|
|
#ifdef BOOST_TEST_CSTR_EQ
|
|
#undef BOOST_TEST_CSTR_EQ
|
|
#define BOOST_TEST_CSTR_EQ(expr1,expr2) \
|
|
BOOST_TEST_EQ( boost::urls::detail::to_sv(expr1), boost::urls::detail::to_sv(expr2) )
|
|
#endif
|
|
|
|
namespace boost {
|
|
namespace urls {
|
|
|
|
#ifdef assert
|
|
#undef assert
|
|
#endif
|
|
#define assert BOOST_TEST
|
|
|
|
BOOST_CORE_STATIC_ASSERT(
|
|
! std::is_default_constructible<
|
|
segments_encoded_ref>::value);
|
|
|
|
BOOST_CORE_STATIC_ASSERT(
|
|
std::is_copy_constructible<
|
|
segments_encoded_ref>::value);
|
|
|
|
BOOST_CORE_STATIC_ASSERT(
|
|
std::is_copy_assignable<
|
|
segments_encoded_ref>::value);
|
|
|
|
BOOST_CORE_STATIC_ASSERT(
|
|
std::is_default_constructible<
|
|
segments_encoded_ref::iterator>::value);
|
|
|
|
struct segments_encoded_ref_test
|
|
{
|
|
// check that modification produces
|
|
// the string and correct sequence
|
|
static
|
|
void
|
|
check(
|
|
void(*f)(segments_encoded_ref),
|
|
core::string_view s0,
|
|
core::string_view s1,
|
|
std::initializer_list<
|
|
core::string_view> init)
|
|
{
|
|
auto rv = parse_uri_reference(s0);
|
|
if(! BOOST_TEST(rv.has_value()))
|
|
return;
|
|
url u = *rv;
|
|
segments_encoded_ref ps(u.encoded_segments());
|
|
f(ps);
|
|
BOOST_TEST_EQ(u.encoded_path(), s1);
|
|
if(! BOOST_TEST_EQ(
|
|
ps.size(), init.size()))
|
|
return;
|
|
auto it0 = ps.begin();
|
|
auto it1 = init.begin();
|
|
auto const end = ps.end();
|
|
while(it0 != end)
|
|
{
|
|
BOOST_TEST_EQ(*it0, *it1);
|
|
++it0;
|
|
++it1;
|
|
}
|
|
}
|
|
|
|
static
|
|
void
|
|
check(
|
|
void(*f1)(segments_encoded_ref),
|
|
void(*f2)(segments_encoded_ref),
|
|
core::string_view s0, core::string_view s1,
|
|
std::initializer_list<
|
|
core::string_view> init)
|
|
{
|
|
check(f1, s0, s1, init);
|
|
check(f2, s0, s1, init);
|
|
}
|
|
|
|
static
|
|
void
|
|
assign(
|
|
segments_encoded_ref& ps,
|
|
std::initializer_list<
|
|
core::string_view> init)
|
|
{
|
|
ps.assign(init.begin(), init.end());
|
|
}
|
|
|
|
static
|
|
auto
|
|
insert(
|
|
segments_encoded_ref& ps,
|
|
segments_encoded_ref::iterator before,
|
|
std::initializer_list<
|
|
core::string_view> init) ->
|
|
segments_encoded_ref::iterator
|
|
{
|
|
return ps.insert(before,
|
|
init.begin(), init.end());
|
|
}
|
|
|
|
static
|
|
auto
|
|
replace(
|
|
segments_encoded_ref& ps,
|
|
segments_encoded_ref::iterator from,
|
|
segments_encoded_ref::iterator to,
|
|
std::initializer_list<
|
|
core::string_view> init) ->
|
|
segments_encoded_ref::iterator
|
|
{
|
|
return ps.replace(from, to,
|
|
init.begin(), init.end());
|
|
}
|
|
|
|
//--------------------------------------------
|
|
|
|
void
|
|
testSpecial()
|
|
{
|
|
// segments_encoded_ref(segments_encoded_ref)
|
|
{
|
|
url u("/index.htm");
|
|
segments_encoded_ref ps0 = u.encoded_segments();
|
|
segments_encoded_ref ps1(ps0);
|
|
BOOST_TEST_EQ(&ps0.url(), &ps1.url());
|
|
BOOST_TEST_EQ(
|
|
ps0.url().buffer().data(),
|
|
ps1.url().buffer().data());
|
|
}
|
|
|
|
// operator=(segments_encoded_ref)
|
|
{
|
|
url u1("/index.htm");
|
|
url u2("/path/to/file.txt");
|
|
segments_encoded_ref ps1 = u1.encoded_segments();
|
|
segments_encoded_ref ps2 = u2.encoded_segments();
|
|
BOOST_TEST_NE(
|
|
ps1.buffer().data(),
|
|
ps2.buffer().data());
|
|
ps1 = ps2;
|
|
BOOST_TEST_EQ(
|
|
u1.encoded_path(),
|
|
u2.encoded_path());
|
|
BOOST_TEST_NE(
|
|
ps1.buffer().data(),
|
|
ps2.buffer().data());
|
|
}
|
|
|
|
// operator=(segments_encoded_view)
|
|
{
|
|
url u1("/index.htm");
|
|
url_view u2("/path/to/file.txt");
|
|
segments_encoded_ref ps1 =
|
|
u1.encoded_segments();
|
|
segments_encoded_view ps2 =
|
|
u2.encoded_segments();
|
|
BOOST_TEST_NE(
|
|
ps1.buffer().data(),
|
|
ps2.buffer().data());
|
|
ps1 = ps2;
|
|
BOOST_TEST_EQ(
|
|
u1.encoded_path(),
|
|
u2.encoded_path());
|
|
BOOST_TEST_NE(
|
|
ps1.buffer().data(),
|
|
ps2.buffer().data());
|
|
}
|
|
|
|
// operator=(initializer_list)
|
|
{
|
|
url u;
|
|
u.encoded_segments() = { "path", "to%3F", "file#" };
|
|
BOOST_TEST_EQ(
|
|
u.encoded_path(), "path/to%3F/file%23");
|
|
}
|
|
|
|
// operator segments_encoded_view()
|
|
{
|
|
url u;
|
|
u.encoded_segments() = { "path", "to%3F", "file#" };
|
|
segments_encoded_view ps = u.encoded_segments();
|
|
auto it = ps.begin();
|
|
BOOST_TEST_EQ(*it++, "path");
|
|
BOOST_TEST_EQ(*it++, "to%3F");
|
|
BOOST_TEST_EQ(*it++, "file%23");
|
|
}
|
|
|
|
// operator segments_encoded_view()
|
|
{
|
|
url u;
|
|
u.encoded_segments() = { "x:y", "a:b" };
|
|
segments_encoded_view ps = u.encoded_segments();
|
|
auto it = ps.begin();
|
|
BOOST_TEST_CSTR_EQ(*it++, "x%3Ay");
|
|
BOOST_TEST_CSTR_EQ(*it++, "a:b");
|
|
}
|
|
}
|
|
|
|
void
|
|
testObservers()
|
|
{
|
|
// url()
|
|
{
|
|
url u0( "/" );
|
|
url u1( "/" );
|
|
BOOST_TEST_EQ(
|
|
&u0.encoded_segments().url(), &u0);
|
|
BOOST_TEST_EQ(
|
|
&u1.encoded_segments().url(), &u1);
|
|
BOOST_TEST_NE(
|
|
&u0.encoded_segments().url(),
|
|
&u1.encoded_segments().url());
|
|
}
|
|
}
|
|
|
|
void
|
|
testModifiers()
|
|
{
|
|
//
|
|
// clear()
|
|
//
|
|
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
ps.clear();
|
|
};
|
|
check(f, "", "", {} );
|
|
check(f, "/", "/", {});
|
|
check(f, "/index.htm", "/", {});
|
|
check(f, "index.htm", "", {});
|
|
check(f, "/path/to/file.txt", "/", {});
|
|
check(f, "Program%20Files", "", {});
|
|
check(f, "x://y/", "", {});
|
|
}
|
|
|
|
//
|
|
// assign(initializer_list)
|
|
// assign(FwdIt, FwdIt)
|
|
//
|
|
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
ps.assign({ "path", "to%23", "file.txt?" });
|
|
|
|
// invalid percent-escape
|
|
BOOST_TEST_THROWS(ps.assign({ "%" }), system::system_error);
|
|
};
|
|
auto const g = [](segments_encoded_ref ps)
|
|
{
|
|
assign(ps, { "path", "to%23", "file.txt?" });
|
|
|
|
// invalid percent-escape
|
|
BOOST_TEST_THROWS(assign(ps, { "%" }), system::system_error);
|
|
};
|
|
check(f, g, "", "path/to%23/file.txt%3F", {"path", "to%23", "file.txt%3F"});
|
|
check(f, g, "/", "/path/to%23/file.txt%3F", {"path", "to%23", "file.txt%3F"});
|
|
check(f, g, "/index.htm", "/path/to%23/file.txt%3F", {"path", "to%23", "file.txt%3F"});
|
|
check(f, g, "index.htm", "path/to%23/file.txt%3F", {"path", "to%23", "file.txt%3F"});
|
|
check(f, g, "/path/to/file.txt", "/path/to%23/file.txt%3F", {"path", "to%23", "file.txt%3F"});
|
|
check(f, g, "Program%20Files", "path/to%23/file.txt%3F", {"path", "to%23", "file.txt%3F"});
|
|
}
|
|
|
|
//
|
|
// insert(iterator, pct_string_view)
|
|
//
|
|
|
|
// inserting extra "" as first segment
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.insert(ps.begin(), "");
|
|
BOOST_TEST_EQ(*it, "");
|
|
|
|
// invalid percent-escape
|
|
BOOST_TEST_THROWS(ps.insert(ps.begin(),
|
|
"%%"), system::system_error);
|
|
};
|
|
check(f, "", "./", {""});
|
|
// path "/" represents empty segment range: {}
|
|
BOOST_TEST(url_view("/").encoded_segments().empty());
|
|
// path "/./" represents segment range: {""}
|
|
check(f, "/", "/./", {""});
|
|
check(f, "/index.htm", "/.//index.htm", {"", "index.htm"});
|
|
check(f, "index.htm", ".//index.htm", {"", "index.htm"});
|
|
check(f, "path/to/file.txt", ".//path/to/file.txt", {"", "path", "to", "file.txt"});
|
|
check(f, "/path/to/file.txt", "/.//path/to/file.txt", {"", "path", "to", "file.txt"});
|
|
check(f, "Program%20Files", ".//Program%20Files", {"", "Program%20Files"});
|
|
check(f, "x:", "./", {""});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.insert(ps.begin(), "my seg%23");
|
|
BOOST_TEST_EQ(*it, "my%20seg%23");
|
|
};
|
|
check(f, "", "my%20seg%23", {"my%20seg%23"});
|
|
check(f, "/", "/my%20seg%23", {"my%20seg%23"});
|
|
check(f, "/index.htm", "/my%20seg%23/index.htm", {"my%20seg%23", "index.htm"});
|
|
check(f, "index.htm", "my%20seg%23/index.htm", {"my%20seg%23", "index.htm"});
|
|
check(f, "path/to/file.txt", "my%20seg%23/path/to/file.txt", {"my%20seg%23", "path", "to", "file.txt"});
|
|
check(f, "/path/to/file.txt", "/my%20seg%23/path/to/file.txt", {"my%20seg%23", "path", "to", "file.txt"});
|
|
check(f, "Program%20Files", "my%20seg%23/Program%20Files", {"my%20seg%23", "Program%20Files"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.insert(std::next(ps.begin(), 1), "my%20seg?");
|
|
BOOST_TEST_EQ(*it, "my%20seg%3F");
|
|
};
|
|
check(f, "path/to/file.txt", "path/my%20seg%3F/to/file.txt", {"path", "my%20seg%3F", "to", "file.txt"});
|
|
check(f, "/path/to/file.txt", "/path/my%20seg%3F/to/file.txt", {"path", "my%20seg%3F", "to", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.insert(ps.end(), "my%20seg[");
|
|
BOOST_TEST_EQ(*it, "my%20seg%5B");
|
|
};
|
|
check(f, "", "my%20seg%5B", {"my%20seg%5B"});
|
|
check(f, "/", "/my%20seg%5B", {"my%20seg%5B"});
|
|
check(f, "/index.htm", "/index.htm/my%20seg%5B", {"index.htm", "my%20seg%5B"});
|
|
check(f, "index.htm", "index.htm/my%20seg%5B", {"index.htm", "my%20seg%5B"});
|
|
check(f, "path/to/file.txt", "path/to/file.txt/my%20seg%5B", {"path", "to", "file.txt", "my%20seg%5B"});
|
|
check(f, "/path/to/file.txt", "/path/to/file.txt/my%20seg%5B", {"path", "to", "file.txt", "my%20seg%5B"});
|
|
check(f, "Program%20Files", "Program%20Files/my%20seg%5B", {"Program%20Files", "my%20seg%5B"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.insert(ps.end(), "");
|
|
BOOST_TEST_EQ(*it, "");
|
|
};
|
|
check(f, "", "./", {""});
|
|
check(f, "/", "/./", {""});
|
|
check(f, "/index.htm", "/index.htm/", {"index.htm", ""});
|
|
check(f, "index.htm", "index.htm/", {"index.htm", ""});
|
|
check(f, "path/to/file.txt", "path/to/file.txt/", {"path", "to", "file.txt", ""});
|
|
check(f, "/path/to/file.txt", "/path/to/file.txt/", {"path", "to", "file.txt", ""});
|
|
}
|
|
|
|
//
|
|
// insert(iterator, initializer_list)
|
|
// insert(iterator, FwdIt, FwdIt)
|
|
//
|
|
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.insert(ps.begin(), { "u#", "v%20" });
|
|
BOOST_TEST_EQ(*it, "u%23");
|
|
|
|
// invalid percent-escape
|
|
BOOST_TEST_THROWS(ps.insert(ps.begin(),
|
|
{ "%F" }), system::system_error);
|
|
};
|
|
auto const g = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = insert(ps, ps.begin(), { "u#", "v%20" });
|
|
BOOST_TEST_EQ(*it, "u%23");
|
|
|
|
// invalid percent-escape
|
|
BOOST_TEST_THROWS(insert(ps, ps.begin(),
|
|
{ "%F" }), system::system_error);
|
|
};
|
|
check(f, g, "", "u%23/v%20", {"u%23", "v%20"});
|
|
check(f, g, "/", "/u%23/v%20", {"u%23", "v%20"});
|
|
check(f, g, "/index.htm", "/u%23/v%20/index.htm", {"u%23", "v%20", "index.htm"});
|
|
check(f, g, "index.htm", "u%23/v%20/index.htm", {"u%23", "v%20", "index.htm"});
|
|
check(f, g, "path/to/file.txt", "u%23/v%20/path/to/file.txt", {"u%23", "v%20", "path", "to", "file.txt"});
|
|
check(f, g, "/path/to/file.txt", "/u%23/v%20/path/to/file.txt", {"u%23", "v%20", "path", "to", "file.txt"});
|
|
check(f, g, "Program%20Files", "u%23/v%20/Program%20Files", {"u%23", "v%20", "Program%20Files"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.insert(ps.begin(), { "", "" });
|
|
BOOST_TEST_EQ(*it, "");
|
|
};
|
|
auto const g = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = insert(ps, ps.begin(), { "", "" });
|
|
BOOST_TEST_EQ(*it, "");
|
|
};
|
|
check(f, g, "", ".//", {"", ""});
|
|
check(f, g, "/", "/.//", {"", ""});
|
|
check(f, g, "/index.htm", "/.///index.htm", {"", "", "index.htm"});
|
|
check(f, g, "index.htm", ".///index.htm", {"", "", "index.htm"});
|
|
check(f, g, "path/to/file.txt", ".///path/to/file.txt", {"", "", "path", "to", "file.txt"});
|
|
check(f, g, "/path/to/file.txt", "/.///path/to/file.txt", {"", "", "path", "to", "file.txt"});
|
|
check(f, g, "x", ".///x", {"", "", "x"});
|
|
}
|
|
|
|
//
|
|
// erase(iterator)
|
|
//
|
|
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.erase(std::next(ps.begin(), 0));
|
|
BOOST_TEST_EQ(*it, ps.front());
|
|
};
|
|
check(f, "path/to/file.txt", "to/file.txt", {"to", "file.txt"});
|
|
check(f, "/path/to/file.txt", "/to/file.txt", {"to", "file.txt"});
|
|
check(f, "//x/y/", "/./", {""});
|
|
check(f, "/x/", "/./", {""});
|
|
check(f, "x/", "./", {""});
|
|
check(f, "x:.//", "./", {""});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.erase(std::next(ps.begin(), 1));
|
|
BOOST_TEST_EQ(*it, "file.txt");
|
|
};
|
|
check(f, "path/to/file.txt", "path/file.txt", {"path", "file.txt"});
|
|
check(f, "/path/to/file.txt", "/path/file.txt", {"path", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.erase(std::next(ps.begin(), 2));
|
|
BOOST_TEST_EQ(it, ps.end());
|
|
};
|
|
check(f, "path/to/file.txt", "path/to", {"path", "to"});
|
|
check(f, "/path/to/file.txt", "/path/to", {"path", "to"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.erase(std::next(ps.begin(), 1));
|
|
BOOST_TEST_EQ(*it, "");
|
|
};
|
|
check(f, "x://y///", "//", {"", ""});
|
|
check(f, ".///", ".//", {"", ""});
|
|
}
|
|
|
|
//
|
|
// erase(iterator, iterator)
|
|
//
|
|
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.erase(
|
|
std::next(ps.begin(), 0),
|
|
std::next(ps.begin(), 2));
|
|
BOOST_TEST_EQ(*it, "the");
|
|
};
|
|
check(f, "path/to/the/file.txt", "the/file.txt", {"the", "file.txt"});
|
|
check(f, "/path/to/the/file.txt", "/the/file.txt", {"the", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.erase(
|
|
std::next(ps.begin(), 1),
|
|
std::next(ps.begin(), 3));
|
|
BOOST_TEST_EQ(*it, ps.back());
|
|
};
|
|
check(f, "path/to/the/file.txt", "path/file.txt", {"path", "file.txt"});
|
|
check(f, "/path/to/the/file.txt", "/path/file.txt", {"path", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.erase(
|
|
std::next(ps.begin(), 2),
|
|
std::next(ps.begin(), 4));
|
|
BOOST_TEST_EQ(it, ps.end());
|
|
};
|
|
check(f, "path/to/the/file.txt", "path/to", {"path", "to"});
|
|
check(f, "/path/to/the/file.txt", "/path/to", {"path", "to"});
|
|
}
|
|
|
|
//
|
|
// replace(iterator, pct_string_view)
|
|
//
|
|
|
|
// replace first with empty segment
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(ps.begin(), "");
|
|
BOOST_TEST_EQ(*it, "");
|
|
|
|
// invalid percent escape
|
|
BOOST_TEST_THROWS(ps.replace(
|
|
ps.begin(), "00%"), system::system_error);
|
|
};
|
|
check(f, "path/to/file.txt", ".//to/file.txt", {"", "to", "file.txt"});
|
|
check(f, "/path/to/file.txt", "/.//to/file.txt", {"", "to", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(std::next(ps.begin(), 1), "");
|
|
BOOST_TEST_EQ(*it, "");
|
|
};
|
|
check(f, "path/to/file.txt", "path//file.txt", {"path", "", "file.txt"});
|
|
check(f, "/path/to/file.txt", "/path//file.txt", {"path", "", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(std::next(ps.begin(), 0), "te%20[");
|
|
BOOST_TEST_EQ(*it, "te%20%5B");
|
|
};
|
|
check(f, "path/to/file.txt", "te%20%5B/to/file.txt", {"te%20%5B", "to", "file.txt"});
|
|
check(f, "/path/to/file.txt", "/te%20%5B/to/file.txt", {"te%20%5B", "to", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(std::next(ps.begin(), 1), "test");
|
|
BOOST_TEST_EQ(*it, "test");
|
|
};
|
|
check(f, "path/to/file.txt", "path/test/file.txt", {"path", "test", "file.txt"});
|
|
check(f, "/path/to/file.txt", "/path/test/file.txt", {"path", "test", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(std::next(ps.begin(), 2), "test");
|
|
BOOST_TEST_EQ(*it, "test");
|
|
};
|
|
check(f, "path/to/file.txt", "path/to/test", {"path", "to", "test"});
|
|
check(f, "/path/to/file.txt", "/path/to/test", {"path", "to", "test"});
|
|
}
|
|
|
|
//
|
|
// replace(iterator, iterator, pct_string_view)
|
|
//
|
|
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(
|
|
std::next(ps.begin(), 0),
|
|
std::next(ps.begin(), 2),
|
|
"");
|
|
BOOST_TEST_EQ(*it, "");
|
|
|
|
// invalid percent escape
|
|
BOOST_TEST_THROWS(ps.replace(
|
|
std::next(ps.begin(), 0), std::next(ps.begin(), 2),
|
|
"0%"), system::system_error);
|
|
};
|
|
check(f, "path/to/the/file.txt", ".//the/file.txt", {"", "the", "file.txt"});
|
|
check(f, "/path/to/the/file.txt", "/.//the/file.txt", {"", "the", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(
|
|
std::next(ps.begin(), 1),
|
|
std::next(ps.begin(), 3),
|
|
"");
|
|
BOOST_TEST_EQ(*it, "");
|
|
};
|
|
check(f, "path/to/the/file.txt", "path//file.txt", {"path", "", "file.txt"});
|
|
check(f, "/path/to/the/file.txt", "/path//file.txt", {"path", "", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(
|
|
std::next(ps.begin(), 2),
|
|
std::next(ps.begin(), 4),
|
|
"");
|
|
BOOST_TEST_EQ(*it, "");
|
|
};
|
|
check(f, "path/to/the/file.txt", "path/to/", {"path", "to", ""});
|
|
check(f, "/path/to/the/file.txt", "/path/to/", {"path", "to", ""});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(
|
|
std::next(ps.begin(), 0),
|
|
std::next(ps.begin(), 2),
|
|
"test");
|
|
BOOST_TEST_EQ(*it, "test");
|
|
};
|
|
check(f, "path/to/the/file.txt", "test/the/file.txt", {"test", "the", "file.txt"});
|
|
check(f, "/path/to/the/file.txt", "/test/the/file.txt", {"test", "the", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(
|
|
std::next(ps.begin(), 1),
|
|
std::next(ps.begin(), 3),
|
|
"test");
|
|
BOOST_TEST_EQ(*it, "test");
|
|
};
|
|
check(f, "path/to/the/file.txt", "path/test/file.txt", {"path", "test", "file.txt"});
|
|
check(f, "/path/to/the/file.txt", "/path/test/file.txt", {"path", "test", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(
|
|
std::next(ps.begin(), 2),
|
|
std::next(ps.begin(), 4),
|
|
"test");
|
|
BOOST_TEST_EQ(*it, "test");
|
|
};
|
|
check(f, "path/to/the/file.txt", "path/to/test", {"path", "to", "test"});
|
|
check(f, "/path/to/the/file.txt", "/path/to/test", {"path", "to", "test"});
|
|
}
|
|
|
|
//
|
|
// replace(iterator, iterator. initializer_list)
|
|
// replace(iterator, iterator. FwdIt, FwdIt)
|
|
//
|
|
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(
|
|
std::next(ps.begin(), 0),
|
|
std::next(ps.begin(), 2),
|
|
{ "t", "u %3F", "v" });
|
|
BOOST_TEST_EQ(*it, "t");
|
|
|
|
// invalid percent escape
|
|
BOOST_TEST_THROWS(ps.replace(
|
|
std::next(ps.begin(), 0),
|
|
std::next(ps.begin(), 2),
|
|
{ "x", "%FG" }), system::system_error);
|
|
};
|
|
auto const g = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = replace(ps,
|
|
std::next(ps.begin(), 0),
|
|
std::next(ps.begin(), 2),
|
|
{ "t", "u %3F", "v" });
|
|
BOOST_TEST_EQ(*it, "t");
|
|
|
|
// invalid percent escape
|
|
BOOST_TEST_THROWS(replace(ps,
|
|
std::next(ps.begin(), 0),
|
|
std::next(ps.begin(), 2),
|
|
{ "x", "%" }), system::system_error);
|
|
};
|
|
check(f, g, "path/to/the/file.txt", "t/u%20%3F/v/the/file.txt", {"t", "u%20%3F", "v", "the", "file.txt"});
|
|
check(f, g, "/path/to/the/file.txt", "/t/u%20%3F/v/the/file.txt", {"t", "u%20%3F", "v", "the", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(
|
|
std::next(ps.begin(), 1),
|
|
std::next(ps.begin(), 3),
|
|
{ "t", "u", "v" });
|
|
BOOST_TEST_EQ(*it, "t");
|
|
};
|
|
auto const g = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = replace(ps,
|
|
std::next(ps.begin(), 1),
|
|
std::next(ps.begin(), 3),
|
|
{ "t", "u", "v" });
|
|
BOOST_TEST_EQ(*it, "t");
|
|
};
|
|
check(f, g, "path/to/the/file.txt", "path/t/u/v/file.txt", {"path", "t", "u", "v", "file.txt"});
|
|
check(f, g, "/path/to/the/file.txt", "/path/t/u/v/file.txt", {"path", "t", "u", "v", "file.txt"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = ps.replace(
|
|
std::next(ps.begin(), 2),
|
|
std::next(ps.begin(), 4),
|
|
{ "t", "u", "v" });
|
|
BOOST_TEST_EQ(*it, "t");
|
|
};
|
|
auto const g = [](segments_encoded_ref ps)
|
|
{
|
|
auto it = replace(ps,
|
|
std::next(ps.begin(), 2),
|
|
std::next(ps.begin(), 4),
|
|
{ "t", "u", "v" });
|
|
BOOST_TEST_EQ(*it, "t");
|
|
};
|
|
check(f, g, "path/to/the/file.txt", "path/to/t/u/v", {"path", "to", "t", "u", "v"});
|
|
check(f, g, "/path/to/the/file.txt", "/path/to/t/u/v", {"path", "to", "t", "u", "v"});
|
|
}
|
|
|
|
//
|
|
// push_back
|
|
//
|
|
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
ps.push_back("");
|
|
|
|
// invalid percent-escape
|
|
BOOST_TEST_THROWS(ps.push_back("%"), system::system_error);
|
|
};
|
|
check(f, "", "./", {""});
|
|
check(f, "/", "/./", {""});
|
|
check(f, "./", ".//", {"", ""});
|
|
check(f, "/./", "/.//", {"", ""});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
ps.push_back("/");
|
|
};
|
|
check(f, "", "%2F", {"%2F"});
|
|
check(f, "/", "/%2F", {"%2F"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
ps.push_back(":");
|
|
};
|
|
check(f, "", "%3A", {"%3A"});
|
|
check(f, "/", "/:", {":"});
|
|
}
|
|
|
|
//
|
|
// pop_back
|
|
//
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
ps.pop_back();
|
|
};
|
|
check(f, "/path/to/file.txt", "/path/to", {"path", "to"});
|
|
check(f, "/path/to/", "/path/to", {"path", "to"});
|
|
check(f, ".//", "./", {""});
|
|
check(f, "/.//", "/./", {""});
|
|
check(f, "x://y//", "/", {""});
|
|
check(f, "x://y/.//", "/./", {""});
|
|
check(f, "x://y/.///", "/.//", {"", ""});
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
testEditSegments()
|
|
{
|
|
/* Legend
|
|
|
|
'#' 0x23 '/' 0x2f
|
|
'%' 0x25 ':' 0x3a
|
|
'.' 0x2e '?' 0x3f
|
|
*/
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
ps.push_back("");
|
|
};
|
|
check(f, "", "./", {""});
|
|
check(f, "/", "/./", {""});
|
|
check(f, "./", ".//", {"", ""});
|
|
check(f, "/./", "/.//", {"", ""});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
ps.push_back("/");
|
|
};
|
|
check(f, "", "%2F", {"%2F"});
|
|
check(f, "/", "/%2F", {"%2F"});
|
|
}
|
|
{
|
|
auto const f = [](segments_encoded_ref ps)
|
|
{
|
|
ps.push_back(":");
|
|
};
|
|
check(f, "", "%3A", {"%3A"});
|
|
check(f, "/", "/:", {":"});
|
|
}
|
|
}
|
|
|
|
void
|
|
testJavadocs()
|
|
{
|
|
// {class}
|
|
{
|
|
url u( "/path/to/file.txt" );
|
|
|
|
segments_encoded_ref ps = u.encoded_segments();
|
|
|
|
ignore_unused(ps);
|
|
}
|
|
|
|
// operator=(initializer_list)
|
|
{
|
|
url u;
|
|
|
|
u.encoded_segments() = {"path", "to", "file.txt"};
|
|
}
|
|
|
|
// url()
|
|
{
|
|
url u( "?key=value" );
|
|
|
|
assert( &u.encoded_segments().url() == &u );
|
|
}
|
|
}
|
|
|
|
void
|
|
run()
|
|
{
|
|
testSpecial();
|
|
testObservers();
|
|
testModifiers();
|
|
testEditSegments();
|
|
testJavadocs();
|
|
}
|
|
};
|
|
|
|
TEST_SUITE(
|
|
segments_encoded_ref_test,
|
|
"boost.url.segments_encoded_ref");
|
|
|
|
} // urls
|
|
} // boost
|