diff options
author | Martin Fischer <martin@push-f.com> | 2021-12-05 01:44:45 +0100 |
---|---|---|
committer | Martin Fischer <martin@push-f.com> | 2021-12-05 01:53:28 +0100 |
commit | 799f2d02bea9bb16780bce01d4f3d831954bf9f0 (patch) | |
tree | a9c2d425aee007cf0f16cd2172f5f1a88f31d18b /test | |
parent | c3255c4473dd3976361ac52899c504c7f70c4be9 (diff) |
remove C++ implementation
Diffstat (limited to 'test')
-rw-r--r-- | test/CMakeLists.txt | 29 | ||||
-rw-r--r-- | test/src/CharacterSetTests.cpp | 122 | ||||
-rw-r--r-- | test/src/PercentEncodedCharacterDecoderTests.cpp | 50 | ||||
-rw-r--r-- | test/src/UriTests.cpp | 964 |
4 files changed, 0 insertions, 1165 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index a7f6320..0000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# CMakeLists.txt for UriTests -# -# © 2018 by Richard Walters - -cmake_minimum_required(VERSION 3.8) -set(This UriTests) - -set(Sources - src/UriTests.cpp - src/CharacterSetTests.cpp - src/PercentEncodedCharacterDecoderTests.cpp -) - -add_executable(${This} ${Sources}) -set_target_properties(${This} PROPERTIES - FOLDER Tests -) - -target_include_directories(${This} PRIVATE ..) - -target_link_libraries(${This} PUBLIC - gtest_main - Uri -) - -add_test( - NAME ${This} - COMMAND ${This} -) diff --git a/test/src/CharacterSetTests.cpp b/test/src/CharacterSetTests.cpp deleted file mode 100644 index 3663ee6..0000000 --- a/test/src/CharacterSetTests.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @file CharacterSetTests.cpp - * - * This module contains the unit tests of the Uri::CharacterSet class. - * - * © 2018 by Richard Walters - */ - -#include <gtest/gtest.h> -#include <src/CharacterSet.hpp> -#include <utility> -#include <vector> - -TEST(CharacterSetTests, DefaultConstructor) { - Uri::CharacterSet cs; - for (char c = 0; c < 0x7F; ++c) { - ASSERT_FALSE(cs.Contains(c)); - } -} - -TEST(CharacterSetTests, SingleCharacterConstructor) { - Uri::CharacterSet cs('X'); - for (char c = 0; c < 0x7F; ++c) { - if (c == 'X') { - ASSERT_TRUE(cs.Contains(c)); - } else { - ASSERT_FALSE(cs.Contains(c)); - } - } -} - -TEST(CharacterSetTests, RangeConstructor) { - Uri::CharacterSet cs('A', 'G'); - for (char c = 0; c < 0x7F; ++c) { - if ( - (c >= 'A') - && (c <= 'G') - ) { - ASSERT_TRUE(cs.Contains(c)); - } else { - ASSERT_FALSE(cs.Contains(c)); - } - } -} - -TEST(CharacterSetTests, Range_Constructor_Reversed) { - Uri::CharacterSet cs('G', 'A'); - for (char c = 0; c < 0x7F; ++c) { - if ( - (c >= 'A') - && (c <= 'G') - ) { - ASSERT_TRUE(cs.Contains(c)); - } else { - ASSERT_FALSE(cs.Contains(c)); - } - } -} - -TEST(CharacterSetTests, InitializerListConstructor) { - Uri::CharacterSet cs1{'X'}; - for (char c = 0; c < 0x7F; ++c) { - if (c == 'X') { - ASSERT_TRUE(cs1.Contains(c)); - } else { - ASSERT_FALSE(cs1.Contains(c)); - } - } - Uri::CharacterSet cs2{'A', 'G'}; - for (char c = 0; c < 0x7F; ++c) { - if ( - (c == 'A') - || (c == 'G') - ) { - ASSERT_TRUE(cs2.Contains(c)); - } else { - ASSERT_FALSE(cs2.Contains(c)); - } - } - Uri::CharacterSet cs3{Uri::CharacterSet('f', 'i')}; - for (char c = 0; c < 0x7F; ++c) { - if ( - (c >= 'f') - && (c <= 'i') - ) { - ASSERT_TRUE(cs3.Contains(c)); - } else { - ASSERT_FALSE(cs3.Contains(c)); - } - } - Uri::CharacterSet cs4{Uri::CharacterSet('a', 'c'), Uri::CharacterSet('f', 'i')}; - for (char c = 0; c < 0x7F; ++c) { - if ( - ( - (c >= 'a') - && (c <= 'c') - ) - || ( - (c >= 'f') - && (c <= 'i') - ) - ) { - ASSERT_TRUE(cs4.Contains(c)); - } else { - ASSERT_FALSE(cs4.Contains(c)); - } - } - Uri::CharacterSet cs5{Uri::CharacterSet('a', 'c'), Uri::CharacterSet('x')}; - for (char c = 0; c < 0x7F; ++c) { - if ( - ( - (c >= 'a') - && (c <= 'c') - ) - || (c == 'x') - ) { - ASSERT_TRUE(cs5.Contains(c)); - } else { - ASSERT_FALSE(cs5.Contains(c)); - } - } -} diff --git a/test/src/PercentEncodedCharacterDecoderTests.cpp b/test/src/PercentEncodedCharacterDecoderTests.cpp deleted file mode 100644 index fcc4286..0000000 --- a/test/src/PercentEncodedCharacterDecoderTests.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file PercentEncodedCharacterDecoderTests.cpp - * - * This module contains the unit tests of the Uri::PercentEncodedCharacterDecoder class. - * - * © 2018 by Richard Walters - */ - -#include <gtest/gtest.h> -#include <src/PercentEncodedCharacterDecoder.hpp> -#include <stddef.h> -#include <vector> - -TEST(PercentEncodedCharacterDecoderTests, GoodSequences) { - Uri::PercentEncodedCharacterDecoder pec; - struct TestVector { - char sequence[2]; - char expectedOutput; - }; - const std::vector< TestVector > testVectors{ - {{'4', '1'}, 'A'}, - {{'5', 'A'}, 'Z'}, - {{'6', 'e'}, 'n'}, - {{'e', '1'}, (char)0xe1}, - {{'C', 'A'}, (char)0xca}, - }; - size_t index = 0; - for (auto testVector: testVectors) { - pec = Uri::PercentEncodedCharacterDecoder(); - ASSERT_FALSE(pec.Done()); - ASSERT_TRUE(pec.NextEncodedCharacter(testVector.sequence[0])); - ASSERT_FALSE(pec.Done()); - ASSERT_TRUE(pec.NextEncodedCharacter(testVector.sequence[1])); - ASSERT_TRUE(pec.Done()); - ASSERT_EQ(testVector.expectedOutput, pec.GetDecodedCharacter()) << index; - ++index; - } -} - -TEST(PercentEncodedCharacterDecoderTests, BadSequences) { - Uri::PercentEncodedCharacterDecoder pec; - std::vector< char > testVectors{ - 'G', 'g', '.', 'z', '-', ' ', 'V', - }; - for (auto testVector: testVectors) { - pec = Uri::PercentEncodedCharacterDecoder(); - ASSERT_FALSE(pec.Done()); - ASSERT_FALSE(pec.NextEncodedCharacter(testVector)); - } -} diff --git a/test/src/UriTests.cpp b/test/src/UriTests.cpp deleted file mode 100644 index 4848724..0000000 --- a/test/src/UriTests.cpp +++ /dev/null @@ -1,964 +0,0 @@ -/** - * @file UriTests.cpp - * - * This module contains the unit tests of the Uri::Uri class. - * - * © 2018 by Richard Walters - */ - -#include <gtest/gtest.h> -#include <stddef.h> -#include <Uri/Uri.hpp> - -TEST(UriTests, ParseFromStringNoScheme) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("foo/bar")); - ASSERT_EQ("", uri.GetScheme()); - ASSERT_EQ( - (std::vector< std::string >{ - "foo", - "bar", - }), - uri.GetPath() - ); -} - -TEST(UriTests, ParseFromStringUrl) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("http://www.example.com/foo/bar")); - ASSERT_EQ("http", uri.GetScheme()); - ASSERT_EQ("www.example.com", uri.GetHost()); - ASSERT_EQ( - (std::vector< std::string >{ - "", - "foo", - "bar", - }), - uri.GetPath() - ); -} - -TEST(UriTests, ParseFromStringUrnDefaultPathDelimiter) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("urn:book:fantasy:Hobbit")); - ASSERT_EQ("urn", uri.GetScheme()); - ASSERT_EQ("", uri.GetHost()); - ASSERT_EQ( - (std::vector< std::string >{ - "book:fantasy:Hobbit", - }), - uri.GetPath() - ); -} - -TEST(UriTests, ParseFromStringPathCornerCases) { - struct TestVector { - std::string pathIn; - std::vector< std::string > pathOut; - }; - const std::vector< TestVector > testVectors{ - {"", {}}, - {"/", {""}}, - {"/foo", {"", "foo"} }, - {"foo/", {"foo", ""} }, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.pathIn)) << index; - ASSERT_EQ(testVector.pathOut, uri.GetPath()) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringHasAPortNumber) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("http://www.example.com:8080/foo/bar")); - ASSERT_EQ("www.example.com", uri.GetHost()); - ASSERT_TRUE(uri.HasPort()); - ASSERT_EQ(8080, uri.GetPort()); -} - -TEST(UriTests, ParseFromStringDoesNotHaveAPortNumber) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("http://www.example.com/foo/bar")); - ASSERT_EQ("www.example.com", uri.GetHost()); - ASSERT_FALSE(uri.HasPort()); -} - -TEST(UriTests, ParseFromStringTwiceFirstWithPortNumberThenWithout) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("http://www.example.com:8080/foo/bar")); - ASSERT_TRUE(uri.ParseFromString("http://www.example.com/foo/bar")); - ASSERT_FALSE(uri.HasPort()); -} - -TEST(UriTests, ParseFromStringBadPortNumberPurelyAlphabetic) { - Uri::Uri uri; - ASSERT_FALSE(uri.ParseFromString("http://www.example.com:spam/foo/bar")); -} - -TEST(UriTests, ParseFromStringBadPortNumberStartsNumericEndsAlphabetic) { - Uri::Uri uri; - ASSERT_FALSE(uri.ParseFromString("http://www.example.com:8080spam/foo/bar")); -} - -TEST(UriTests, ParseFromStringLargestValidPortNumber) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("http://www.example.com:65535/foo/bar")); - ASSERT_TRUE(uri.HasPort()); - ASSERT_EQ(65535, uri.GetPort()); -} - -TEST(UriTests, ParseFromStringBadPortNumberTooBig) { - Uri::Uri uri; - ASSERT_FALSE(uri.ParseFromString("http://www.example.com:65536/foo/bar")); -} - -TEST(UriTests, ParseFromStringBadPortNumberNegative) { - Uri::Uri uri; - ASSERT_FALSE(uri.ParseFromString("http://www.example.com:-1234/foo/bar")); -} - -TEST(UriTests, ParseFromStringEndsAfterAuthority) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("http://www.example.com")); -} - -TEST(UriTests, ParseFromStringRelativeVsNonRelativeReferences) { - struct TestVector { - std::string uriString; - bool isRelativeReference; - }; - const std::vector< TestVector > testVectors{ - {"http://www.example.com/", false}, - {"http://www.example.com", false}, - {"/", true}, - {"foo", true}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.isRelativeReference, uri.IsRelativeReference()) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringRelativeVsNonRelativePaths) { - struct TestVector { - std::string uriString; - bool containsRelativePath; - }; - const std::vector< TestVector > testVectors{ - {"http://www.example.com/", false}, - {"http://www.example.com", false}, - {"/", false}, - {"foo", true}, - - /* - * This is only a valid test vector if we understand - * correctly that an empty string IS a valid - * "relative reference" URI with an empty path. - */ - {"", true}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.containsRelativePath, uri.ContainsRelativePath()) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringQueryAndFragmentElements) { - struct TestVector { - std::string uriString; - std::string host; - std::string query; - std::string fragment; - }; - const std::vector< TestVector > testVectors{ - {"http://www.example.com/", "www.example.com", "", ""}, - {"http://example.com?foo", "example.com", "foo", ""}, - {"http://www.example.com#foo", "www.example.com", "", "foo"}, - {"http://www.example.com?foo#bar", "www.example.com", "foo", "bar"}, - {"http://www.example.com?earth?day#bar", "www.example.com", "earth?day", "bar"}, - {"http://www.example.com/spam?foo#bar", "www.example.com", "foo", "bar"}, - - /* - * NOTE: curiously, but we think this is correct, that - * having a trailing question mark is equivalent to not having - * any question mark, because in both cases, the query element - * is empty string. Perhaps research deeper to see if this is right. - */ - {"http://www.example.com/?", "www.example.com", "", ""}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.host, uri.GetHost()) << index; - ASSERT_EQ(testVector.query, uri.GetQuery()) << index; - ASSERT_EQ(testVector.fragment, uri.GetFragment()) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringUserInfo) { - struct TestVector { - std::string uriString; - std::string userInfo; - }; - const std::vector< TestVector > testVectors{ - {"http://www.example.com/", ""}, - {"http://joe@www.example.com", "joe"}, - {"http://pepe:feelsbadman@www.example.com", "pepe:feelsbadman"}, - {"//www.example.com", ""}, - {"//bob@www.example.com", "bob"}, - {"/", ""}, - {"foo", ""}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.userInfo, uri.GetUserInfo()) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringTwiceFirstUserInfoThenWithout) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("http://joe@www.example.com/foo/bar")); - ASSERT_TRUE(uri.ParseFromString("/foo/bar")); - ASSERT_TRUE(uri.GetUserInfo().empty()); -} - -TEST(UriTests, ParseFromStringSchemeIllegalCharacters) { - const std::vector< std::string > testVectors{ - {"://www.example.com/"}, - {"0://www.example.com/"}, - {"+://www.example.com/"}, - {"@://www.example.com/"}, - {".://www.example.com/"}, - {"h@://www.example.com/"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_FALSE(uri.ParseFromString(testVector)) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringSchemeBarelyLegal) { - struct TestVector { - std::string uriString; - std::string scheme; - }; - const std::vector< TestVector > testVectors{ - {"h://www.example.com/", "h"}, - {"x+://www.example.com/", "x+"}, - {"y-://www.example.com/", "y-"}, - {"z.://www.example.com/", "z."}, - {"aa://www.example.com/", "aa"}, - {"a0://www.example.com/", "a0"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.scheme, uri.GetScheme()); - ++index; - } -} - -TEST(UriTests, ParseFromStringSchemeMixedCase) { - const std::vector< std::string > testVectors{ - {"http://www.example.com/"}, - {"hTtp://www.example.com/"}, - {"HTTP://www.example.com/"}, - {"Http://www.example.com/"}, - {"HttP://www.example.com/"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector)) << index; - ASSERT_EQ("http", uri.GetScheme()) << ">>> Failed for test vector element " << index << " <<<"; - ++index; - } -} - -TEST(UriTests, ParseFromStringHostEndsInDot) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("http://example.com./foo")); - ASSERT_EQ("example.com.", uri.GetHost()); -} - -TEST(UriTests, ParseFromStringUserInfoIllegalCharacters) { - const std::vector< std::string > testVectors{ - {"//%X@www.example.com/"}, - {"//{@www.example.com/"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_FALSE(uri.ParseFromString(testVector)) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringUserInfoBarelyLegal) { - struct TestVector { - std::string uriString; - std::string userInfo; - }; - const std::vector< TestVector > testVectors{ - {"//%41@www.example.com/", "A"}, - {"//@www.example.com/", ""}, - {"//!@www.example.com/", "!"}, - {"//'@www.example.com/", "'"}, - {"//(@www.example.com/", "("}, - {"//;@www.example.com/", ";"}, - {"http://:@www.example.com/", ":"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.userInfo, uri.GetUserInfo()); - ++index; - } -} - -TEST(UriTests, ParseFromStringHostIllegalCharacters) { - const std::vector< std::string > testVectors{ - {"//%X@www.example.com/"}, - {"//@www:example.com/"}, - {"//[vX.:]/"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_FALSE(uri.ParseFromString(testVector)) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringHostBarelyLegal) { - struct TestVector { - std::string uriString; - std::string host; - }; - const std::vector< TestVector > testVectors{ - {"//%41/", "a"}, - {"///", ""}, - {"//!/", "!"}, - {"//'/", "'"}, - {"//(/", "("}, - {"//;/", ";"}, - {"//1.2.3.4/", "1.2.3.4"}, - {"//[v7.:]/", "v7.:"}, - {"//[v7.aB]/", "v7.aB"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.host, uri.GetHost()); - ++index; - } -} - -TEST(UriTests, ParseFromStringHostMixedCase) { - const std::vector< std::string > testVectors{ - {"http://www.example.com/"}, - {"http://www.EXAMPLE.com/"}, - {"http://www.exAMple.com/"}, - {"http://www.example.cOM/"}, - {"http://wWw.exampLe.Com/"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector)) << index; - ASSERT_EQ("www.example.com", uri.GetHost()) << ">>> Failed for test vector element " << index << " <<<"; - ++index; - } -} - -TEST(UriTests, ParseFromStringDontMisinterpretColonInOtherPlacesAsSchemeDelimiter) { - const std::vector< std::string > testVectors{ - {"//foo:bar@www.example.com/"}, - {"//www.example.com/a:b"}, - {"//www.example.com/foo?a:b"}, - {"//www.example.com/foo#a:b"}, - {"//[v7.:]/"}, - {"/:/foo"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector)) << index; - ASSERT_TRUE(uri.GetScheme().empty()); - ++index; - } -} - -TEST(UriTests, ParseFromStringPathIllegalCharacters) { - const std::vector< std::string > testVectors{ - {"http://www.example.com/foo[bar"}, - {"http://www.example.com/]bar"}, - {"http://www.example.com/foo]"}, - {"http://www.example.com/["}, - {"http://www.example.com/abc/foo]"}, - {"http://www.example.com/abc/["}, - {"http://www.example.com/foo]/abc"}, - {"http://www.example.com/[/abc"}, - {"http://www.example.com/foo]/"}, - {"http://www.example.com/[/"}, - {"/foo[bar"}, - {"/]bar"}, - {"/foo]"}, - {"/["}, - {"/abc/foo]"}, - {"/abc/["}, - {"/foo]/abc"}, - {"/[/abc"}, - {"/foo]/"}, - {"/[/"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_FALSE(uri.ParseFromString(testVector)) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringPathBarelyLegal) { - struct TestVector { - std::string uriString; - std::vector< std::string > path; - }; - const std::vector< TestVector > testVectors{ - {"/:/foo", {"", ":", "foo"}}, - {"bob@/foo", {"bob@", "foo"}}, - {"hello!", {"hello!"}}, - {"urn:hello,%20w%6Frld", {"hello, world"}}, - {"//example.com/foo/(bar)/", {"", "foo", "(bar)", ""}}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.path, uri.GetPath()); - ++index; - } -} - -TEST(UriTests, ParseFromStringQueryIllegalCharacters) { - const std::vector< std::string > testVectors{ - {"http://www.example.com/?foo[bar"}, - {"http://www.example.com/?]bar"}, - {"http://www.example.com/?foo]"}, - {"http://www.example.com/?["}, - {"http://www.example.com/?abc/foo]"}, - {"http://www.example.com/?abc/["}, - {"http://www.example.com/?foo]/abc"}, - {"http://www.example.com/?[/abc"}, - {"http://www.example.com/?foo]/"}, - {"http://www.example.com/?[/"}, - {"?foo[bar"}, - {"?]bar"}, - {"?foo]"}, - {"?["}, - {"?abc/foo]"}, - {"?abc/["}, - {"?foo]/abc"}, - {"?[/abc"}, - {"?foo]/"}, - {"?[/"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_FALSE(uri.ParseFromString(testVector)) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringQueryBarelyLegal) { - struct TestVector { - std::string uriString; - std::string query; - }; - const std::vector< TestVector > testVectors{ - {"/?:/foo", ":/foo"}, - {"?bob@/foo", "bob@/foo"}, - {"?hello!", "hello!"}, - {"urn:?hello,%20w%6Frld", "hello, world"}, - {"//example.com/foo?(bar)/", "(bar)/"}, - {"http://www.example.com/?foo?bar", "foo?bar" }, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.query, uri.GetQuery()); - ++index; - } -} - -TEST(UriTests, ParseFromStringFragmentIllegalCharacters) { - const std::vector< std::string > testVectors{ - {"http://www.example.com/#foo[bar"}, - {"http://www.example.com/#]bar"}, - {"http://www.example.com/#foo]"}, - {"http://www.example.com/#["}, - {"http://www.example.com/#abc/foo]"}, - {"http://www.example.com/#abc/["}, - {"http://www.example.com/#foo]/abc"}, - {"http://www.example.com/#[/abc"}, - {"http://www.example.com/#foo]/"}, - {"http://www.example.com/#[/"}, - {"#foo[bar"}, - {"#]bar"}, - {"#foo]"}, - {"#["}, - {"#abc/foo]"}, - {"#abc/["}, - {"#foo]/abc"}, - {"#[/abc"}, - {"#foo]/"}, - {"#[/"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_FALSE(uri.ParseFromString(testVector)) << index; - ++index; - } -} - -TEST(UriTests, ParseFromStringFragmentBarelyLegal) { - struct TestVector { - std::string uriString; - std::string fragment; - }; - const std::vector< TestVector > testVectors{ - {"/#:/foo", ":/foo"}, - {"#bob@/foo", "bob@/foo"}, - {"#hello!", "hello!"}, - {"urn:#hello,%20w%6Frld", "hello, world"}, - {"//example.com/foo#(bar)/", "(bar)/"}, - {"http://www.example.com/#foo?bar", "foo?bar" }, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.fragment, uri.GetFragment()); - ++index; - } -} - -TEST(UriTests, ParseFromStringPathsWithPercentEncodedCharacters) { - struct TestVector { - std::string uriString; - std::string pathFirstSegment; - }; - const std::vector< TestVector > testVectors{ - {"%41", "A"}, - {"%4A", "J"}, - {"%4a", "J"}, - {"%bc", "\xbc"}, - {"%Bc", "\xbc"}, - {"%bC", "\xbc"}, - {"%BC", "\xbc"}, - {"%41%42%43", "ABC"}, - {"%41%4A%43%4b", "AJCK"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - ASSERT_EQ(testVector.pathFirstSegment, uri.GetPath()[0]); - ++index; - } -} - -TEST(UriTests, NormalizePath) { - struct TestVector { - std::string uriString; - std::vector< std::string > normalizedPathSegments; - }; - const std::vector< TestVector > testVectors{ - {"/a/b/c/./../../g", {"", "a", "g"}}, - {"mid/content=5/../6", {"mid", "6"}}, - {"http://example.com/a/../b", {"", "b"}}, - {"http://example.com/../b", {"", "b"}}, - {"http://example.com/a/../b/", {"", "b", ""}}, - {"http://example.com/a/../../b", {"", "b"}}, - {"./a/b", {"a", "b"}}, - {"..", {}}, - {"/", {""}}, - {"a/b/..", {"a", ""}}, - {"a/b/.", {"a", "b", ""}}, - {"a/b/./c", {"a", "b", "c"}}, - {"a/b/./c/", {"a", "b", "c", ""}}, - {"/a/b/..", {"", "a", ""}}, - {"/a/b/.", {"", "a", "b", ""}}, - {"/a/b/./c", {"", "a", "b", "c"}}, - {"/a/b/./c/", {"", "a", "b", "c", ""}}, - {"./a/b/..", {"a", ""}}, - {"./a/b/.", {"a", "b", ""}}, - {"./a/b/./c", {"a", "b", "c"}}, - {"./a/b/./c/", {"a", "b", "c", ""}}, - {"../a/b/..", {"a", ""}}, - {"../a/b/.", {"a", "b", ""}}, - {"../a/b/./c", {"a", "b", "c"}}, - {"../a/b/./c/", {"a", "b", "c", ""}}, - {"../a/b/../c", {"a", "c"}}, - {"../a/b/./../c/", {"a", "c", ""}}, - {"../a/b/./../c", {"a", "c"}}, - {"../a/b/./../c/", {"a", "c", ""}}, - {"../a/b/.././c/", {"a", "c", ""}}, - {"../a/b/.././c", {"a", "c"}}, - {"../a/b/.././c/", {"a", "c", ""}}, - {"/./c/d", {"", "c", "d"}}, - {"/../c/d", {"", "c", "d"}}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString(testVector.uriString)) << index; - uri.NormalizePath(); - ASSERT_EQ(testVector.normalizedPathSegments, uri.GetPath()) << index; - ++index; - } -} - -TEST(UriTests, ConstructNormalizeAndCompareEquivalentUris) { - // This was inspired by section 6.2.2 - // of RFC 3986 (https://tools.ietf.org/html/rfc3986). - Uri::Uri uri1, uri2; - ASSERT_TRUE(uri1.ParseFromString("example://a/b/c/%7Bfoo%7D")); - ASSERT_TRUE(uri2.ParseFromString("eXAMPLE://a/./b/../b/%63/%7bfoo%7d")); - ASSERT_NE(uri1, uri2); - uri2.NormalizePath(); - ASSERT_EQ(uri1, uri2); -} - -TEST(UriTests, ReferenceResolution) { - struct TestVector { - std::string baseString; - std::string relativeReferenceString; - std::string targetString; - }; - const std::vector< TestVector > testVectors{ - // These are all taken from section 5.4.1 - // of RFC 3986 (https://tools.ietf.org/html/rfc3986). - {"http://a/b/c/d;p?q", "g:h", "g:h"}, - {"http://a/b/c/d;p?q", "g", "http://a/b/c/g"}, - {"http://a/b/c/d;p?q", "./g", "http://a/b/c/g"}, - {"http://a/b/c/d;p?q", "g/", "http://a/b/c/g/"}, - {"http://a/b/c/d;p?q", "//g", "http://g"}, - {"http://a/b/c/d;p?q", "?y", "http://a/b/c/d;p?y"}, - {"http://a/b/c/d;p?q", "g?y", "http://a/b/c/g?y"}, - {"http://a/b/c/d;p?q", "#s", "http://a/b/c/d;p?q#s"}, - {"http://a/b/c/d;p?q", "g#s", "http://a/b/c/g#s"}, - {"http://a/b/c/d;p?q", "g?y#s", "http://a/b/c/g?y#s"}, - {"http://a/b/c/d;p?q", ";x", "http://a/b/c/;x"}, - {"http://a/b/c/d;p?q", "g;x", "http://a/b/c/g;x"}, - {"http://a/b/c/d;p?q", "g;x?y#s", "http://a/b/c/g;x?y#s"}, - {"http://a/b/c/d;p?q", "", "http://a/b/c/d;p?q"}, - {"http://a/b/c/d;p?q", ".", "http://a/b/c/"}, - {"http://a/b/c/d;p?q", "./", "http://a/b/c/"}, - {"http://a/b/c/d;p?q", "..", "http://a/b/"}, - {"http://a/b/c/d;p?q", "../", "http://a/b/"}, - {"http://a/b/c/d;p?q", "../g", "http://a/b/g"}, - {"http://a/b/c/d;p?q", "../..", "http://a"}, - {"http://a/b/c/d;p?q", "../../", "http://a"}, - {"http://a/b/c/d;p?q", "../../g", "http://a/g"}, - - // Here are some examples of our own. - {"http://example.com", "foo", "http://example.com/foo"}, - {"http://example.com/", "foo", "http://example.com/foo"}, - {"http://example.com", "foo/", "http://example.com/foo/"}, - {"http://example.com/", "foo/", "http://example.com/foo/"}, - {"http://example.com", "/foo", "http://example.com/foo"}, - {"http://example.com/", "/foo", "http://example.com/foo"}, - {"http://example.com", "/foo/", "http://example.com/foo/"}, - {"http://example.com/", "/foo/", "http://example.com/foo/"}, - {"http://example.com/", "?foo", "http://example.com/?foo"}, - {"http://example.com/", "#foo", "http://example.com/#foo"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri baseUri, relativeReferenceUri, expectedTargetUri; - ASSERT_TRUE(baseUri.ParseFromString(testVector.baseString)); - ASSERT_TRUE(relativeReferenceUri.ParseFromString(testVector.relativeReferenceString)) << index; - ASSERT_TRUE(expectedTargetUri.ParseFromString(testVector.targetString)) << index; - const auto actualTargetUri = baseUri.Resolve(relativeReferenceUri); - ASSERT_EQ(expectedTargetUri, actualTargetUri) << index; - ++index; - } -} - -TEST(UriTests, EmptyPathInUriWithAuthorityIsEquivalentToSlashOnlyPath) { - Uri::Uri uri1, uri2; - ASSERT_TRUE(uri1.ParseFromString("http://example.com")); - ASSERT_TRUE(uri2.ParseFromString("http://example.com/")); - ASSERT_EQ(uri1, uri2); - ASSERT_TRUE(uri1.ParseFromString("//example.com")); - ASSERT_TRUE(uri2.ParseFromString("//example.com/")); - ASSERT_EQ(uri1, uri2); -} - -TEST(UriTests, IPv6Address) { - struct TestVector { - std::string uriString; - std::string expectedHost; - bool isValid; - }; - const std::vector< TestVector > testVectors{ - // valid - {"http://[::1]/", "::1", true}, - {"http://[::ffff:1.2.3.4]/", "::ffff:1.2.3.4", true}, - {"http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/", "2001:db8:85a3:8d3:1319:8a2e:370:7348", true}, - {"http://[2001:db8:85a3:8d3:1319:8a2e:370::]/", "2001:db8:85a3:8d3:1319:8a2e:370::", true}, - {"http://[2001:db8:85a3:8d3:1319:8a2e::1]/", "2001:db8:85a3:8d3:1319:8a2e::1", true}, - {"http://[fFfF::1]", "fFfF::1", true}, - {"http://[1234::1]", "1234::1", true}, - {"http://[fFfF:1:2:3:4:5:6:a]", "fFfF:1:2:3:4:5:6:a", true}, - {"http://[2001:db8:85a3::8a2e:0]/", "2001:db8:85a3::8a2e:0", true}, - {"http://[2001:db8:85a3:8a2e::]/", "2001:db8:85a3:8a2e::", true}, - - // invalid - {"http://[::fFfF::1]", "", false}, - {"http://[::ffff:1.2.x.4]/", "", false}, - {"http://[::ffff:1.2.3.4.8]/", "", false}, - {"http://[::ffff:1.2.3]/", "", false}, - {"http://[::ffff:1.2.3.]/", "", false}, - {"http://[::ffff:1.2.3.256]/", "", false}, - {"http://[::fxff:1.2.3.4]/", "", false}, - {"http://[::ffff:1.2.3.-4]/", "", false}, - {"http://[::ffff:1.2.3. 4]/", "", false}, - {"http://[::ffff:1.2.3.4 ]/", "", false}, - {"http://[::ffff:1.2.3.4/", "", false}, - {"http://::ffff:1.2.3.4]/", "", false}, - {"http://::ffff:a.2.3.4]/", "", false}, - {"http://::ffff:1.a.3.4]/", "", false}, - {"http://[2001:db8:85a3:8d3:1319:8a2e:370:7348:0000]/", "", false}, - {"http://[2001:db8:85a3:8d3:1319:8a2e:370:7348::1]/", "", false}, - {"http://[2001:db8:85a3:8d3:1319:8a2e:370::1]/", "", false}, - {"http://[2001:db8:85a3::8a2e:0:]/", "", false}, - {"http://[2001:db8:85a3::8a2e::]/", "", false}, - {"http://[]/", "", false}, - {"http://[:]/", "", false}, - {"http://[v]/", "", false}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - const bool parseResult = uri.ParseFromString(testVector.uriString); - ASSERT_EQ(testVector.isValid, parseResult) << index; - if (parseResult) { - ASSERT_EQ(testVector.expectedHost, uri.GetHost()); - } - ++index; - } -} - -TEST(UriTests, IPvFutureAddress) { - struct TestVector { - std::string uriString; - std::string expectedHost; - bool isValid; - }; - const std::vector< TestVector > testVectors{ - // valid - {"http://[v1.x]/", "v1.x", true}, - {"http://[vf.xy]/", "vf.xy", true}, - {"http://[vf.x:y]/", "vf.x:y", true}, - - // invalid - {"http://[vx]/", "", false}, - {"http://[v12]/", "", false}, - {"http://[v1.?]/", "", false}, - {"http://[v1.x?]/", "", false}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - const bool parseResult = uri.ParseFromString(testVector.uriString); - ASSERT_EQ(testVector.isValid, parseResult) << index; - if (parseResult) { - ASSERT_EQ(testVector.expectedHost, uri.GetHost()); - } - ++index; - } -} - -TEST(UriTests, GenerateString) { - struct TestVector { - std::string scheme; - std::string userinfo; - std::string host; - bool hasPort; - uint16_t port; - std::vector< std::string > path; - bool hasQuery; - std::string query; - bool hasFragment; - std::string fragment; - std::string expectedUriString; - }; - const std::vector< TestVector > testVectors{ - // general test vectors - {"http", "bob", "www.example.com", true, 8080, {"", "abc", "def"}, true, "foobar", true, "ch2", "http://bob@www.example.com:8080/abc/def?foobar#ch2"}, - {"http", "bob", "www.example.com", true, 0, {}, true, "foobar", true, "ch2", "http://bob@www.example.com:0?foobar#ch2"}, - {"http", "bob", "www.example.com", true, 0, {}, true, "foobar", true, "", "http://bob@www.example.com:0?foobar#"}, - {"", "", "example.com", false, 0, {}, true, "bar", false, "", "//example.com?bar"}, - {"", "", "example.com", false, 0, {}, true, "" , false, "", "//example.com?"}, - {"", "", "example.com", false, 0, {}, false, "", false, "", "//example.com"}, - {"", "", "example.com", false, 0, {""}, false, "", false, "", "//example.com/"}, - {"", "", "example.com", false, 0, {"", "xyz"}, false, "", false, "", "//example.com/xyz"}, - {"", "", "example.com", false, 0, {"", "xyz", ""}, false, "", false, "", "//example.com/xyz/"}, - {"", "", "", false, 0, {""}, false, "", false, "", "/"}, - {"", "", "", false, 0, {"", "xyz"}, false, "", false, "", "/xyz"}, - {"", "", "", false, 0, {"", "xyz", ""}, false, "", false, "", "/xyz/"}, - {"", "", "", false, 0, {}, false, "", false, "", ""}, - {"", "", "", false, 0, {"xyz"}, false, "", false, "", "xyz"}, - {"", "", "", false, 0, {"xyz", ""}, false, "", false, "", "xyz/"}, - {"", "", "", false, 0, {}, true, "bar", false, "", "?bar"}, - {"http", "", "", false, 0, {}, true, "bar", false, "", "http:?bar"}, - {"http", "", "", false, 0, {}, false, "", false, "", "http:"}, - {"http", "", "::1", false, 0, {}, false, "", false, "", "http://[::1]"}, - {"http", "", "::1.2.3.4", false, 0, {}, false, "", false, "", "http://[::1.2.3.4]"}, - {"http", "", "1.2.3.4", false, 0, {}, false, "", false, "", "http://1.2.3.4"}, - {"", "", "", false, 0, {}, false, "", false, "", ""}, - {"http", "bob", "", false, 0, {}, true, "foobar", false, "", "http://bob@?foobar"}, - {"", "bob", "", false, 0, {}, true, "foobar", false, "", "//bob@?foobar"}, - {"", "bob", "", false, 0, {}, false, "", false, "", "//bob@"}, - - // percent-encoded character test vectors - {"http", "b b", "www.example.com", true, 8080, {"", "abc", "def"}, true, "foobar", true, "ch2", "http://b%20b@www.example.com:8080/abc/def?foobar#ch2"}, - {"http", "bob", "www.e ample.com", true, 8080, {"", "abc", "def"}, true, "foobar", true, "ch2", "http://bob@www.e%20ample.com:8080/abc/def?foobar#ch2"}, - {"http", "bob", "www.example.com", true, 8080, {"", "a c", "def"}, true, "foobar", true, "ch2", "http://bob@www.example.com:8080/a%20c/def?foobar#ch2"}, - {"http", "bob", "www.example.com", true, 8080, {"", "abc", "def"}, true, "foo ar", true, "ch2", "http://bob@www.example.com:8080/abc/def?foo%20ar#ch2"}, - {"http", "bob", "www.example.com", true, 8080, {"", "abc", "def"}, true, "foobar", true, "c 2", "http://bob@www.example.com:8080/abc/def?foobar#c%202"}, - {"http", "bob", "ሴ.example.com", true, 8080, {"", "abc", "def"}, true, "foobar", false, "", "http://bob@%E1%88%B4.example.com:8080/abc/def?foobar"}, - - // normalization of IPv6 address hex digits - {"http", "bob", "fFfF::1", true, 8080, {"", "abc", "def"}, true, "foobar", true, "c 2", "http://bob@[ffff::1]:8080/abc/def?foobar#c%202"}, - }; - size_t index = 0; - for (const auto& testVector : testVectors) { - Uri::Uri uri; - uri.SetScheme(testVector.scheme); - uri.SetUserInfo(testVector.userinfo); - uri.SetHost(testVector.host); - if (testVector.hasPort) { - uri.SetPort(testVector.port); - } else { - uri.ClearPort(); - } - uri.SetPath(testVector.path); - if (testVector.hasQuery) { - uri.SetQuery(testVector.query); - } else { - uri.ClearQuery(); - } - if (testVector.hasFragment) { - uri.SetFragment(testVector.fragment); - } else { - uri.ClearFragment(); - } - const auto actualUriString = uri.GenerateString(); - ASSERT_EQ(testVector.expectedUriString, actualUriString) << index; - ++index; - } -} - -TEST(UriTests, FragmentEmptyButPresent) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("http://example.com#")); - ASSERT_TRUE(uri.HasFragment()); - ASSERT_EQ("", uri.GetFragment()); - ASSERT_EQ("http://example.com/#", uri.GenerateString()); - uri.ClearFragment(); - ASSERT_EQ("http://example.com/", uri.GenerateString()); - ASSERT_FALSE(uri.HasFragment()); - ASSERT_TRUE(uri.ParseFromString("http://example.com")); - ASSERT_FALSE(uri.HasFragment()); - uri.SetFragment(""); - ASSERT_TRUE(uri.HasFragment()); - ASSERT_EQ("", uri.GetFragment()); - ASSERT_EQ("http://example.com/#", uri.GenerateString()); -} - -TEST(UriTests, QueryEmptyButPresent) { - Uri::Uri uri; - ASSERT_TRUE(uri.ParseFromString("http://example.com?")); - ASSERT_TRUE(uri.HasQuery()); - ASSERT_EQ("", uri.GetQuery()); - ASSERT_EQ("http://example.com/?", uri.GenerateString()); - uri.ClearQuery(); - ASSERT_EQ("http://example.com/", uri.GenerateString()); - ASSERT_FALSE(uri.HasQuery()); - ASSERT_TRUE(uri.ParseFromString("http://example.com")); - ASSERT_FALSE(uri.HasQuery()); - uri.SetQuery(""); - ASSERT_TRUE(uri.HasQuery()); - ASSERT_EQ("", uri.GetQuery()); - ASSERT_EQ("http://example.com/?", uri.GenerateString()); -} - -TEST(UriTests, MakeACopy) { - Uri::Uri uri1; - (void)uri1.ParseFromString("http://www.example.com/foo.txt"); - Uri::Uri uri2(uri1); - uri1.SetQuery("bar"); - uri2.SetFragment("page2"); - uri2.SetHost("example.com"); - EXPECT_EQ("http://www.example.com/foo.txt?bar", uri1.GenerateString()); - EXPECT_EQ("http://example.com/foo.txt#page2", uri2.GenerateString()); -} - -TEST(UriTests, AssignACopy) { - Uri::Uri uri1; - (void)uri1.ParseFromString("http://www.example.com/foo.txt"); - Uri::Uri uri2; - uri2 = uri1; - uri1.SetQuery("bar"); - uri2.SetFragment("page2"); - uri2.SetHost("example.com"); - EXPECT_EQ("http://www.example.com/foo.txt?bar", uri1.GenerateString()); - EXPECT_EQ("http://example.com/foo.txt#page2", uri2.GenerateString()); -} - -TEST(UriTests, ClearQuery) { - Uri::Uri uri; - (void)uri.ParseFromString("http://www.example.com/?foo=bar"); - uri.ClearQuery(); - EXPECT_EQ("http://www.example.com/", uri.GenerateString()); - EXPECT_FALSE(uri.HasQuery()); -} - -TEST(UriTests, PercentEncodePlusInQueries) { - // Although RFC 3986 doesn't say anything about '+', some web services - // treat it the same as ' ' due to how HTML originally defined how - // to encode the query portion of a URL - // (see https://stackoverflow.com/questions/2678551/when-to-encode-space-to-plus-or-20). - // - // To avoid issues with these web services, make sure '+' is - // percent-encoded in a URI when the URI is encoded. - Uri::Uri uri; - uri.SetQuery("foo+bar"); - EXPECT_EQ("?foo%2Bbar", uri.GenerateString()); -} |