Skip to content

Commit

Permalink
Added a function to normalize the URI path and used it to better test…
Browse files Browse the repository at this point in the history
… URI equality.
  • Loading branch information
glynos committed Jul 29, 2012
1 parent a127593 commit 275ed5d
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 15 deletions.
32 changes: 32 additions & 0 deletions include/network/uri/normalize.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) Glyn Matthews 2012.
// 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)


#ifndef __BOOST_NETWORK_URI_NORMALIZE_INC__
# define __BOOST_NETWORK_URI_NORMALIZE_INC__

# include <network/uri/uri.hpp>

namespace network {
uri::string_type normalize_path(const uri::const_range_type &path);

//uri normalize(const uri &uri_);
//
//uri::string_type normalize_scheme(const uri &uri_);
//
//uri::string_type normalize_user_info(const uri &uri_);
//
//uri::string_type normalize_host(const uri &uri_);
//
//uri::string_type normalize_port(const uri &uri_);
//
//uri::string_type normalize_path(const uri &uri_);
//
//uri::string_type normalize_fragment(const uri &uri_);
//
//uri::string_type normalize_query(const uri &uri_);
} // namespace network

#endif // __BOOST_NETWORK_URI_NORMALIZE_INC__
2 changes: 1 addition & 1 deletion libs/network/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU)
endif()
endif()

set(CPP-NETLIB_URI_SRCS uri/uri.cpp uri/schemes.cpp)
set(CPP-NETLIB_URI_SRCS uri/uri.cpp uri/schemes.cpp uri/normalize.cpp)
add_library(cppnetlib-uri ${CPP-NETLIB_URI_SRCS})
foreach (src_file ${CPP-NETLIB_URI_SRCS})
if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU)
Expand Down
56 changes: 56 additions & 0 deletions libs/network/src/uri/normalize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) Glyn Matthews 2012.
// 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)


# include <network/uri/normalize.hpp>
# include <vector>
# include <stack>
# include <boost/algorithm/string/split.hpp>
# include <boost/algorithm/string/join.hpp>
# include <boost/algorithm/string/predicate.hpp>
# include <boost/algorithm/string/classification.hpp>
# include <boost/range/as_literal.hpp>
# include <boost/range/algorithm_ext/erase.hpp>
# include <boost/range/algorithm/for_each.hpp>

namespace network {
uri::string_type normalize_path(const uri::const_range_type &path) {
using namespace boost;
using namespace boost::algorithm;

// add trailing /
if (empty(path)) {
return uri::string_type("/");
}

std::vector<uri::string_type> path_segments;
split(path_segments, path, is_any_of("/"));

// remove single dot segments
remove_erase_if(path_segments, [] (const uri::string_type &s) {
return equal(s, as_literal("."));
});

// remove double dot segments
std::vector<std::string> normalized_segments;
auto depth = 0;
for_each(path_segments, [&normalized_segments, &depth] (const uri::string_type &s) {
assert(depth >= 0);
if (equal(s, as_literal(".."))) {
normalized_segments.pop_back();
}
else {
normalized_segments.push_back(s);
}
});

if (!empty(normalized_segments.back()) &&
!contains(normalized_segments.back(), as_literal("."))) {
normalized_segments.push_back(uri::string_type());
}

return join(normalized_segments, "/");
}
} // namespace network
3 changes: 2 additions & 1 deletion libs/network/src/uri/uri.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <network/uri/uri.ipp>
#include <network/uri/uri.hpp>
#include <network/uri/normalize.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <map>

Expand Down Expand Up @@ -46,7 +47,7 @@ bool operator == (const uri &lhs, const uri &rhs) {

if (equal) {
// TODO: test normalized paths
equal = boost::iequals(lhs.path_range(), rhs.path_range());
equal = boost::iequals(normalize_path(lhs.path_range()), normalize_path(rhs.path_range()));
}

if (equal) {
Expand Down
57 changes: 44 additions & 13 deletions libs/network/test/uri/uri_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,19 +336,19 @@ BOOST_AUTO_TEST_CASE(swap_test) {
BOOST_AUTO_TEST_CASE(equality_test) {
network::uri uri_1("http://www.example.com/");
network::uri uri_2("http://www.example.com/");
BOOST_CHECK(uri_1 == uri_2);
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_1) {
network::uri uri_1("http://www.example.com/");
std::string uri_2("http://www.example.com/");
BOOST_CHECK(uri_1 == uri_2);
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_2) {
std::string uri_1("http://www.example.com/");
network::uri uri_2("http://www.example.com/");
BOOST_CHECK(uri_1 == uri_2);
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_3) {
Expand All @@ -366,62 +366,93 @@ BOOST_AUTO_TEST_CASE(equality_test_4) {
BOOST_AUTO_TEST_CASE(equality_test_reordered_query) {
network::uri uri_1("http://www.example.com/?a=1&b=2");
network::uri uri_2("http://www.example.com/?b=2&a=1");
BOOST_CHECK(uri_1 == uri_2);
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_capitalized_scheme) {
network::uri uri_1("http://www.example.com/");
network::uri uri_2("HTTP://www.example.com/");
BOOST_CHECK(uri_1 == uri_2);
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_capitalized_host) {
network::uri uri_1("http://www.example.com/");
network::uri uri_2("http://WWW.EXAMPLE.COM/");
BOOST_CHECK(uri_1 == uri_2);
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_user_info) {
network::uri uri_1("ftp://john.doe@ftp.example.com/");
network::uri uri_2("ftp://JOHN.DOE@ftp.example.com/");
BOOST_CHECK(uri_1 != uri_2);
BOOST_CHECK_PREDICATE(std::not_equal_to<network::uri>(), (uri_1)(uri_2));
}

BOOST_AUTO_TEST_CASE(equality_test_default_http_port) {
network::uri uri_1("http://www.example.com/");
network::uri uri_2("http://www.example.com:80/");
BOOST_CHECK(uri_1 == uri_2);
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_default_http_port_2) {
network::uri uri_1("http://www.example.com:80/");
network::uri uri_2("http://www.example.com/");
BOOST_CHECK(uri_1 == uri_2);
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_default_https_port) {
network::uri uri_1("https://www.example.com/");
network::uri uri_2("https://www.example.com:443/");
BOOST_CHECK(uri_1 == uri_2);
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_default_https_port_2) {
network::uri uri_1("https://www.example.com:443/");
network::uri uri_2("https://www.example.com/");
BOOST_CHECK(uri_1 == uri_2);
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_empty_path_with_trailing_slash) {
network::uri uri_1("http://www.example.com/");
network::uri uri_2("http://www.example.com");
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_with_single_dot_segment) {
network::uri uri_1("http://www.example.com/./path");
network::uri uri_2("http://www.example.com/path");
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_with_double_dot_segment) {
network::uri uri_1("http://www.example.com/1/../2/");
network::uri uri_2("http://www.example.com/2/");
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_with_trailing_slash) {
network::uri uri_1("http://www.example.com/path/");
network::uri uri_2("http://www.example.com/path");
BOOST_CHECK_EQUAL(uri_1, uri_2);
}

BOOST_AUTO_TEST_CASE(equality_test_with_file_ext) {
network::uri uri_1("http://www.example.com/filename.txt");
network::uri uri_2("http://www.example.com/filename.txt/");
BOOST_CHECK_PREDICATE(std::not_equal_to<network::uri>(), (uri_1)(uri_2));
}

BOOST_AUTO_TEST_CASE(inequality_test) {
network::uri uri_1("http://www.example.com/");
network::uri uri_2("http://www.example.com/");
BOOST_CHECK(!(uri_1 != uri_2));
BOOST_CHECK(!(uri_1 != uri_2));
}

BOOST_AUTO_TEST_CASE(less_than_test) {
// uri_1 is lexicographically less than uri_2
network::uri uri_1("http://www.example.com/");
network::uri uri_2("http://www.example.org/");
BOOST_CHECK(uri_1 < uri_2);
BOOST_CHECK_PREDICATE(std::less<network::uri>(), (uri_1)(uri_2));
//BOOST_CHECK(uri_1 < uri_2);
}

BOOST_AUTO_TEST_CASE(username_test) {
Expand Down

0 comments on commit 275ed5d

Please sign in to comment.