Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/network/uri/detail/uri_parts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,17 @@ class uri_part {
};

struct hierarchical_part {
hierarchical_part() = default;

optional<uri_part> user_info;
optional<uri_part> host;
optional<uri_part> port;
optional<uri_part> path;
};

struct uri_parts {
uri_parts() = default;

optional<uri_part> scheme;
hierarchical_part hier_part;
optional<uri_part> query;
Expand Down
8 changes: 3 additions & 5 deletions src/detail/uri_advance_parts.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016 Glyn Matthews.
// Copyright 2016-2017 Glyn Matthews.
// 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)
Expand All @@ -24,7 +24,7 @@ uri_part copy_part(const std::string &uri, string_view::const_iterator &it) {
return copy_part(std::begin(uri), std::end(uri), it);
}

void advance_parts(string_view &uri_view, uri_parts &parts,
void advance_parts(string_view uri_view, uri_parts &parts,
const uri_parts &existing_parts) {
auto first = std::begin(uri_view);

Expand All @@ -39,9 +39,7 @@ void advance_parts(string_view &uri_view, uri_parts &parts,

// ignore // for hierarchical URIs
if (existing_parts.hier_part.host) {
while (*it == '/') {
++it;
}
std::advance(it, 2);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/detail/uri_advance_parts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace detail {
uri_part copy_part(const std::string &part,
string_view::const_iterator &it);

void advance_parts(string_view &uri_view, uri_parts &parts,
void advance_parts(string_view uri_view, uri_parts &parts,
const uri_parts &existing_parts);
} // namespace detail
} // namespace network
Expand Down
2 changes: 1 addition & 1 deletion src/detail/uri_parse.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016 Glyn Matthews.
// Copyright 2016-2017 Glyn Matthews.
// 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)
Expand Down
7 changes: 4 additions & 3 deletions src/uri.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ void uri::initialize(optional<string_type> scheme,
}

if (path) {
// if the URI is hierarchical and the path is not already
// prefixed with a '/', add one.
// if the URI is not opaque and the path is not already prefixed
// with a '/', add one.
if (host && (!path->empty() && path->front() != '/')) {
path = "/" + *path;
}
Expand Down Expand Up @@ -194,10 +194,11 @@ uri &uri::operator=(uri other) {
}

void uri::swap(uri &other) noexcept {
auto parts = uri_parts_;
advance_parts(other.uri_view_, uri_parts_, other.uri_parts_);
uri_.swap(other.uri_);
uri_view_.swap(other.uri_view_);
advance_parts(other.uri_view_, other.uri_parts_, uri_parts_);
advance_parts(other.uri_view_, other.uri_parts_, parts);
}

uri::const_iterator uri::begin() const noexcept { return uri_view_.begin(); }
Expand Down
44 changes: 41 additions & 3 deletions test/uri_parse_test.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016 Glyn Matthews.
// Copyright 2016-2017 Glyn Matthews.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt of copy at
// http://www.boost.org/LICENSE_1_0.txt)
Expand Down Expand Up @@ -485,14 +485,52 @@ TEST(uri_parse_test, test_pct_encoded_user_info) {
EXPECT_EQ("/", uri.path());
}

TEST(uri_parse_test, test_file_uri_bug_98) {
test::uri uri("file:///bin/bash");
EXPECT_TRUE(uri.parse_uri());
ASSERT_FALSE(uri.has_user_info());
ASSERT_TRUE(uri.has_host());
EXPECT_EQ("", uri.host());
ASSERT_TRUE(uri.has_path());
EXPECT_EQ("/bin/bash", uri.path());
}

TEST(uri_parse_test, test_file_uri_bug_98_2) {
test::uri uri("file://localhost/bin");
EXPECT_TRUE(uri.parse_uri());
ASSERT_FALSE(uri.has_user_info());
ASSERT_TRUE(uri.has_host());
EXPECT_EQ("localhost", uri.host());
ASSERT_TRUE(uri.has_path());
EXPECT_EQ("/bin", uri.path());
}

TEST(uri_parse_test, test_file_uri_bug_98_3) {
test::uri uri("file://localhost/bin/bash");
EXPECT_TRUE(uri.parse_uri());
ASSERT_FALSE(uri.has_user_info());
ASSERT_TRUE(uri.has_host());
EXPECT_EQ("localhost", uri.host());
ASSERT_TRUE(uri.has_path());
EXPECT_EQ("/bin/bash", uri.path());
}

TEST(uri_parse_test, test_file_uri_bug_98_4) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something wrong here. This test duplicates test_file_uri_bug_98_2

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, copy and paste error. I'll fix it in the next PR. Thanks.

test::uri uri("file://localhost/bin");
EXPECT_TRUE(uri.parse_uri());
ASSERT_FALSE(uri.has_user_info());
ASSERT_TRUE(uri.has_host());
EXPECT_EQ("localhost", uri.host());
ASSERT_TRUE(uri.has_path());
EXPECT_EQ("/bin", uri.path());
}

// http://formvalidation.io/validators/uri/

std::vector<std::string> create_urls(const std::string &filename) {
std::vector<std::string> urls;
std::ifstream ifs(filename);
std::cout << filename << std::endl;
if (!ifs) {
std::cout << "Shit." << std::endl;
throw std::runtime_error("Unable to open file: " + filename);
}
for (std::string url; std::getline(ifs, url);) {
Expand Down
136 changes: 126 additions & 10 deletions test/uri_test.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright 2010 Jeroen Habraken.
// Copyright 2009-2016 Dean Michael Berris, Glyn Matthews.
// Copyright 2009-2017 Dean Michael Berris, Glyn Matthews.
// Copyright 2012 Google, Inc.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt of copy at
Expand Down Expand Up @@ -223,6 +223,17 @@ TEST(uri_test, file_test) {
EXPECT_EQ("/bin/bash", instance.path());
}

TEST(uri_test, file_path_has_host_bug_98) {
network::uri instance("file:///bin/bash");
EXPECT_TRUE(instance.has_scheme());
EXPECT_FALSE(instance.has_user_info());
EXPECT_TRUE(instance.has_host());
EXPECT_FALSE(instance.has_port());
EXPECT_TRUE(instance.has_path());
EXPECT_FALSE(instance.has_query());
EXPECT_FALSE(instance.has_fragment());
}

TEST(uri_test, xmpp_test) {
network::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World");
EXPECT_EQ("xmpp", instance.scheme());
Expand Down Expand Up @@ -418,11 +429,23 @@ TEST(uri_test, assignment_test) {
}

TEST(uri_test, swap_test) {
network::uri instance("http://www.example.com/");
network::uri copy("http://www.example.org/");
network::swap(instance, copy);
EXPECT_EQ("http://www.example.org/", instance);
EXPECT_EQ("http://www.example.com/", copy);
network::uri original("http://example.com/path/to/file.txt");
network::uri instance("file:///something/different/");
original.swap(instance);

ASSERT_TRUE(original.has_scheme());
ASSERT_TRUE(original.has_host());
ASSERT_TRUE(original.has_path());
EXPECT_EQ("file", original.scheme());
EXPECT_EQ("", original.host());
EXPECT_EQ("/something/different", original.path());

ASSERT_TRUE(instance.has_scheme());
ASSERT_TRUE(instance.has_host());
ASSERT_TRUE(instance.has_path());
EXPECT_EQ("http", instance.scheme());
EXPECT_EQ("example.com", instance.host());
EXPECT_EQ("/path/to/file.txt", instance.path());
}

TEST(uri_test, authority_test) {
Expand Down Expand Up @@ -531,14 +554,14 @@ TEST(uri_test, mailto_has_no_authority) {
EXPECT_FALSE(instance.has_authority());
}

TEST(uri_test, http_is_hierarchical) {
TEST(uri_test, http_is_not_opaque) {
network::uri instance("http://www.example.com/");
EXPECT_TRUE(!instance.is_opaque());
EXPECT_FALSE(instance.is_opaque());
}

TEST(uri_test, file_is_hierarchical) {
TEST(uri_test, file_is_not_opaque) {
network::uri instance("file:///bin/bash");
EXPECT_TRUE(!instance.is_opaque());
EXPECT_FALSE(instance.is_opaque());
}

TEST(uri_test, mailto_is_absolute) {
Expand Down Expand Up @@ -884,3 +907,96 @@ TEST(uri_test, query_iterator_with_fragment) {
EXPECT_EQ("c", query_it->first);
EXPECT_EQ("d", query_it->second);
}

TEST(uri_test, copy_assignment_bug_98) {
network::uri original("file:///path/to/file.txt");

ASSERT_TRUE(original.has_scheme());
ASSERT_FALSE(original.is_opaque());
ASSERT_TRUE(original.has_host());
ASSERT_TRUE(original.has_path());

network::uri instance;
instance = original;

ASSERT_TRUE(instance.has_scheme());
ASSERT_TRUE(instance.has_host());
ASSERT_TRUE(instance.has_path());
EXPECT_EQ("file", instance.scheme());
EXPECT_EQ("", instance.host());
EXPECT_EQ("/path/to/file.txt", instance.path());
}

TEST(uri_test, copy_assignment_bug_98_2) {
network::uri original("file:///path/to/file.txt?query=value#foo");

network::uri instance;
instance = original;

ASSERT_TRUE(instance.has_scheme());
ASSERT_TRUE(instance.has_path());
ASSERT_TRUE(instance.has_query());
ASSERT_TRUE(instance.has_fragment());
EXPECT_EQ("file", instance.scheme());
EXPECT_EQ("/path/to/file.txt", instance.path());
EXPECT_EQ("query=value", instance.query());
EXPECT_EQ("foo", instance.fragment());
}

TEST(uri_test, copy_constructor_bug_98) {
network::uri original("file:///path/to/file.txt?query=value#foo");

network::uri instance(original);

ASSERT_TRUE(instance.has_scheme());
ASSERT_TRUE(instance.has_path());
ASSERT_TRUE(instance.has_query());
ASSERT_TRUE(instance.has_fragment());
EXPECT_EQ("file", instance.scheme());
EXPECT_EQ("/path/to/file.txt", instance.path());
EXPECT_EQ("query=value", instance.query());
EXPECT_EQ("foo", instance.fragment());
}

TEST(uri_test, move_assignment_bug_98) {
network::uri original("file:///path/to/file.txt?query=value#foo");

network::uri instance;
instance = std::move(original);

ASSERT_TRUE(instance.has_scheme());
ASSERT_TRUE(instance.has_path());
ASSERT_TRUE(instance.has_query());
ASSERT_TRUE(instance.has_fragment());
EXPECT_EQ("file", instance.scheme());
EXPECT_EQ("/path/to/file.txt", instance.path());
EXPECT_EQ("query=value", instance.query());
EXPECT_EQ("foo", instance.fragment());
}

TEST(uri_test, move_constructor_bug_98) {
network::uri original("file:///path/to/file.txt?query=value#foo");

network::uri instance(std::move(original));

ASSERT_TRUE(instance.has_scheme());
ASSERT_TRUE(instance.has_path());
ASSERT_TRUE(instance.has_query());
ASSERT_TRUE(instance.has_fragment());
EXPECT_EQ("file", instance.scheme());
EXPECT_EQ("/path/to/file.txt", instance.path());
EXPECT_EQ("query=value", instance.query());
EXPECT_EQ("foo", instance.fragment());
}

TEST(uri_test, http_copy_assignment_bug_98) {
network::uri original("http://example.com/path/to/file.txt");

network::uri instance;
instance = original;

ASSERT_TRUE(instance.has_scheme());
ASSERT_TRUE(instance.has_path());
EXPECT_EQ("http", instance.scheme());
EXPECT_EQ("/path/to/file.txt", instance.path());
}