"Fossies" - the Fresh Open Source Software Archive

Member "uriparser-0.9.5/test/test.cpp" (18 Mar 2021, 84476 Bytes) of package /linux/www/uriparser-0.9.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "test.cpp": 0.9.4_vs_0.9.5.

    1 /*
    2  * uriparser - RFC 3986 URI parsing library
    3  *
    4  * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
    5  * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
    6  *
    7  * This library is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU Lesser General Public
    9  * License as published by the Free Software Foundation; either
   10  * version 2.1 of the License, or (at your option) any later version.
   11  *
   12  * This library is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15  * Lesser General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU Lesser General Public
   18  * License along with this library; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   20  */
   21 
   22 #include <uriparser/Uri.h>
   23 #include <uriparser/UriIp4.h>
   24 #include <gtest/gtest.h>
   25 #include <memory>
   26 #include <cstdio>
   27 #include <cstdlib>
   28 #include <cwchar>
   29 
   30 using namespace std;
   31 
   32 
   33 
   34 extern "C" {
   35 UriBool uri_TESTING_ONLY_ParseIpSixA(const char * text);
   36 UriBool uri_TESTING_ONLY_ParseIpFourA(const char * text);
   37 int uriCompareRangeA(const UriTextRangeA * a, const UriTextRangeA * b);
   38 }
   39 
   40 
   41 
   42 #define URI_TEST_IP_FOUR_FAIL(x) ASSERT_TRUE(URI_FALSE == uri_TESTING_ONLY_ParseIpFourA(x))
   43 #define URI_TEST_IP_FOUR_PASS(x) ASSERT_TRUE(URI_TRUE == uri_TESTING_ONLY_ParseIpFourA(x))
   44 
   45 // Note the closing brackets! TODO
   46 #define URI_TEST_IP_SIX_FAIL(x) ASSERT_TRUE(URI_FALSE == uri_TESTING_ONLY_ParseIpSixA(x "]"))
   47 #define URI_TEST_IP_SIX_PASS(x) ASSERT_TRUE(URI_TRUE == uri_TESTING_ONLY_ParseIpSixA(x "]"))
   48 
   49 #define URI_EXPECT_BETWEEN(candidate, first, afterLast)  \
   50     EXPECT_TRUE((candidate >= first) && (candidate <= afterLast))
   51 
   52 #define URI_EXPECT_OUTSIDE(candidate, first, afterLast)  \
   53     EXPECT_TRUE((candidate < first) || (candidate > afterLast))
   54 
   55 #define URI_EXPECT_RANGE_BETWEEN(range, uriFirst, uriAfterLast)  \
   56     URI_EXPECT_BETWEEN(range.first, uriFirst, uriAfterLast);  \
   57     URI_EXPECT_BETWEEN(range.afterLast, uriFirst, uriAfterLast)
   58 
   59 #define URI_EXPECT_RANGE_OUTSIDE(range, uriFirst, uriAfterLast)  \
   60     URI_EXPECT_OUTSIDE(range.first, uriFirst, uriAfterLast);  \
   61     URI_EXPECT_OUTSIDE(range.afterLast, uriFirst, uriAfterLast)
   62 
   63 #define URI_EXPECT_RANGE_EMPTY(range)  \
   64     EXPECT_TRUE((range.first != NULL)  \
   65             && (range.afterLast != NULL)  \
   66             && (range.first == range.afterLast))
   67 
   68 namespace {
   69     bool testDistinctionHelper(const char * uriText, bool expectedHostSet,
   70             bool expectedAbsPath, bool expectedEmptyTailSegment) {
   71         UriParserStateA state;
   72         UriUriA uri;
   73         state.uri = &uri;
   74 
   75         int res = uriParseUriA(&state, uriText);
   76         if (res != URI_SUCCESS) {
   77             uriFreeUriMembersA(&uri);
   78             return false;
   79         }
   80 
   81         if (expectedHostSet != (uri.hostText.first != NULL)) {
   82             uriFreeUriMembersA(&uri);
   83             return false;
   84         }
   85 
   86         if (expectedAbsPath != (uri.absolutePath == URI_TRUE)) {
   87             uriFreeUriMembersA(&uri);
   88             return false;
   89         }
   90 
   91         if (expectedEmptyTailSegment != ((uri.pathTail != NULL)
   92                 && (uri.pathTail->text.first == uri.pathTail->text.afterLast))) {
   93             uriFreeUriMembersA(&uri);
   94             return false;
   95         }
   96 
   97         uriFreeUriMembersA(&uri);
   98         return true;
   99     }
  100 }  // namespace
  101 
  102 
  103 TEST(UriSuite, TestDistinction) {
  104         /*
  105 ============================================================================
  106 Rule                                | Example | hostSet | absPath | emptySeg
  107 ------------------------------------|---------|---------|---------|---------
  108 1) URI = scheme ":" hier-part ...   |         |         |         |
  109    1) "//" authority path-abempty   | "s://"  | true    |   false |   false
  110                                     | "s:///" | true    |   false | true
  111                                     | "s://a" | true    |   false |   false
  112                                     | "s://a/"| true    |   false | true
  113    2) path-absolute                 | "s:/"   |   false | true    |   false
  114    3) path-rootless                 | "s:a"   |   false |   false |   false
  115                                     | "s:a/"  |   false |   false | true
  116    4) path-empty                    | "s:"    |   false |   false |   false
  117 ------------------------------------|---------|---------|---------|---------
  118 2) relative-ref = relative-part ... |         |         |         |
  119    1) "//" authority path-abempty   | "//"    | true    |   false |   false
  120                                     | "///"   | true    |   false | true
  121    2) path-absolute                 | "/"     |   false | true    |   false
  122    3) path-noscheme                 | "a"     |   false |   false |   false
  123                                     | "a/"    |   false |   false | true
  124    4) path-empty                    | ""      |   false |   false |   false
  125 ============================================================================
  126         */
  127         ASSERT_TRUE(testDistinctionHelper("s://", true, false, false));
  128         ASSERT_TRUE(testDistinctionHelper("s:///", true, false, true));
  129         ASSERT_TRUE(testDistinctionHelper("s://a", true, false, false));
  130         ASSERT_TRUE(testDistinctionHelper("s://a/", true, false, true));
  131         ASSERT_TRUE(testDistinctionHelper("s:/", false, true, false));
  132         ASSERT_TRUE(testDistinctionHelper("s:a", false, false, false));
  133         ASSERT_TRUE(testDistinctionHelper("s:a/", false, false, true));
  134         ASSERT_TRUE(testDistinctionHelper("s:", false, false, false));
  135 
  136         ASSERT_TRUE(testDistinctionHelper("//", true, false, false));
  137         ASSERT_TRUE(testDistinctionHelper("///", true, false, true));
  138         ASSERT_TRUE(testDistinctionHelper("/", false, true, false));
  139         ASSERT_TRUE(testDistinctionHelper("a", false, false, false));
  140         ASSERT_TRUE(testDistinctionHelper("a/", false, false, true));
  141         ASSERT_TRUE(testDistinctionHelper("", false, false, false));
  142 }
  143 
  144 TEST(UriSuite, TestIpFour) {
  145         URI_TEST_IP_FOUR_FAIL("01.0.0.0");
  146         URI_TEST_IP_FOUR_FAIL("001.0.0.0");
  147         URI_TEST_IP_FOUR_FAIL("00.0.0.0");
  148         URI_TEST_IP_FOUR_FAIL("000.0.0.0");
  149         URI_TEST_IP_FOUR_FAIL("256.0.0.0");
  150         URI_TEST_IP_FOUR_FAIL("300.0.0.0");
  151         URI_TEST_IP_FOUR_FAIL("1111.0.0.0");
  152         URI_TEST_IP_FOUR_FAIL("-1.0.0.0");
  153         URI_TEST_IP_FOUR_FAIL("0.0.0");
  154         URI_TEST_IP_FOUR_FAIL("0.0.0.");
  155         URI_TEST_IP_FOUR_FAIL("0.0.0.0.");
  156         URI_TEST_IP_FOUR_FAIL("0.0.0.0.0");
  157         URI_TEST_IP_FOUR_FAIL("0.0..0");
  158         URI_TEST_IP_FOUR_FAIL(".0.0.0");
  159 
  160         URI_TEST_IP_FOUR_PASS("255.0.0.0");
  161         URI_TEST_IP_FOUR_PASS("0.0.0.0");
  162         URI_TEST_IP_FOUR_PASS("1.0.0.0");
  163         URI_TEST_IP_FOUR_PASS("2.0.0.0");
  164         URI_TEST_IP_FOUR_PASS("3.0.0.0");
  165         URI_TEST_IP_FOUR_PASS("30.0.0.0");
  166 }
  167 
  168 TEST(UriSuite, TestIpSixPass) {
  169         // Quad length
  170         URI_TEST_IP_SIX_PASS("abcd::");
  171 
  172         URI_TEST_IP_SIX_PASS("abcd::1");
  173         URI_TEST_IP_SIX_PASS("abcd::12");
  174         URI_TEST_IP_SIX_PASS("abcd::123");
  175         URI_TEST_IP_SIX_PASS("abcd::1234");
  176 
  177         // Full length
  178         URI_TEST_IP_SIX_PASS("2001:0db8:0100:f101:0210:a4ff:fee3:9566"); // lower hex
  179         URI_TEST_IP_SIX_PASS("2001:0DB8:0100:F101:0210:A4FF:FEE3:9566"); // Upper hex
  180         URI_TEST_IP_SIX_PASS("2001:db8:100:f101:210:a4ff:fee3:9566");
  181         URI_TEST_IP_SIX_PASS("2001:0db8:100:f101:0:0:0:1");
  182         URI_TEST_IP_SIX_PASS("1:2:3:4:5:6:255.255.255.255");
  183 
  184         // Legal IPv4
  185         URI_TEST_IP_SIX_PASS("::1.2.3.4");
  186         URI_TEST_IP_SIX_PASS("3:4::5:1.2.3.4");
  187         URI_TEST_IP_SIX_PASS("::ffff:1.2.3.4");
  188         URI_TEST_IP_SIX_PASS("::0.0.0.0"); // Min IPv4
  189         URI_TEST_IP_SIX_PASS("::255.255.255.255"); // Max IPv4
  190 
  191         // Zipper position
  192         URI_TEST_IP_SIX_PASS("::1:2:3:4:5:6:7");
  193         URI_TEST_IP_SIX_PASS("1::1:2:3:4:5:6");
  194         URI_TEST_IP_SIX_PASS("1:2::1:2:3:4:5");
  195         URI_TEST_IP_SIX_PASS("1:2:3::1:2:3:4");
  196         URI_TEST_IP_SIX_PASS("1:2:3:4::1:2:3");
  197         URI_TEST_IP_SIX_PASS("1:2:3:4:5::1:2");
  198         URI_TEST_IP_SIX_PASS("1:2:3:4:5:6::1");
  199         URI_TEST_IP_SIX_PASS("1:2:3:4:5:6:7::");
  200 
  201         // Zipper length
  202         URI_TEST_IP_SIX_PASS("1:1:1::1:1:1:1");
  203         URI_TEST_IP_SIX_PASS("1:1:1::1:1:1");
  204         URI_TEST_IP_SIX_PASS("1:1:1::1:1");
  205         URI_TEST_IP_SIX_PASS("1:1::1:1");
  206         URI_TEST_IP_SIX_PASS("1:1::1");
  207         URI_TEST_IP_SIX_PASS("1::1");
  208         URI_TEST_IP_SIX_PASS("::1"); // == localhost
  209         URI_TEST_IP_SIX_PASS("::"); // == all addresses
  210 
  211         // A few more variations
  212         URI_TEST_IP_SIX_PASS("21ff:abcd::1");
  213         URI_TEST_IP_SIX_PASS("2001:db8:100:f101::1");
  214         URI_TEST_IP_SIX_PASS("a:b:c::12:1");
  215         URI_TEST_IP_SIX_PASS("a:b::0:1:2:3");
  216 }
  217 
  218 TEST(UriSuite, TestIpSixFail) {
  219         // 5 char quad
  220         URI_TEST_IP_SIX_FAIL("::12345");
  221 
  222         // Two zippers
  223         URI_TEST_IP_SIX_FAIL("abcd::abcd::abcd");
  224 
  225         // Triple-colon zipper
  226         URI_TEST_IP_SIX_FAIL(":::1234");
  227         URI_TEST_IP_SIX_FAIL("1234:::1234:1234");
  228         URI_TEST_IP_SIX_FAIL("1234:1234:::1234");
  229         URI_TEST_IP_SIX_FAIL("1234:::");
  230 
  231         // No quads, just IPv4
  232         URI_TEST_IP_SIX_FAIL("1.2.3.4");
  233         URI_TEST_IP_SIX_FAIL("0001.0002.0003.0004");
  234 
  235         // Five quads
  236         URI_TEST_IP_SIX_FAIL("0000:0000:0000:0000:0000:1.2.3.4");
  237 
  238         // Seven quads
  239         URI_TEST_IP_SIX_FAIL("0:0:0:0:0:0:0");
  240         URI_TEST_IP_SIX_FAIL("0:0:0:0:0:0:0:");
  241         URI_TEST_IP_SIX_FAIL("0:0:0:0:0:0:0:1.2.3.4");
  242 
  243         // Nine quads (or more)
  244         URI_TEST_IP_SIX_FAIL("1:2:3:4:5:6:7:8:9");
  245         URI_TEST_IP_SIX_FAIL("::2:3:4:5:6:7:8:9");
  246         URI_TEST_IP_SIX_FAIL("1:2:3:4::6:7:8:9");
  247         URI_TEST_IP_SIX_FAIL("1:2:3:4:5:6:7:8::");
  248 
  249         // Invalid IPv4 part
  250         URI_TEST_IP_SIX_FAIL("::ffff:001.02.03.004"); // Leading zeros
  251         URI_TEST_IP_SIX_FAIL("::ffff:1.2.3.1111"); // Four char octet
  252         URI_TEST_IP_SIX_FAIL("::ffff:1.2.3.256"); // > 255
  253         URI_TEST_IP_SIX_FAIL("::ffff:311.2.3.4"); // > 155
  254         URI_TEST_IP_SIX_FAIL("::ffff:1.2.3:4"); // Not a dot
  255         URI_TEST_IP_SIX_FAIL("::ffff:1.2.3"); // Missing octet
  256         URI_TEST_IP_SIX_FAIL("::ffff:1.2.3."); // Missing octet
  257         URI_TEST_IP_SIX_FAIL("::ffff:1.2.3a.4"); // Hex in octet
  258         URI_TEST_IP_SIX_FAIL("::ffff:1.2.3.4:123"); // Crap input
  259 
  260         // Nonhex
  261         URI_TEST_IP_SIX_FAIL("g:0:0:0:0:0:0");
  262 }
  263 
  264 TEST(UriSuite, TestIpSixOverread) {
  265         UriUriA uri;
  266         const char * errorPos;
  267 
  268         // NOTE: This string is designed to not have a terminator
  269         char uriText[2 + 3 + 2 + 1 + 1];
  270         strncpy(uriText, "//[::44.1", sizeof(uriText));
  271 
  272         EXPECT_EQ(uriParseSingleUriExA(&uri, uriText,
  273                 uriText + sizeof(uriText), &errorPos), URI_ERROR_SYNTAX);
  274         EXPECT_EQ(errorPos, uriText + sizeof(uriText));
  275 }
  276 
  277 TEST(UriSuite, TestUri) {
  278         UriParserStateA stateA;
  279         UriParserStateW stateW;
  280         UriUriA uriA;
  281         UriUriW uriW;
  282 
  283         stateA.uri = &uriA;
  284         stateW.uri = &uriW;
  285 
  286         // On/off for each
  287         ASSERT_TRUE(0 == uriParseUriA(&stateA, "//user:pass@[::1]:80/segment/index.html?query#frag"));
  288         uriFreeUriMembersA(&uriA);
  289         ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://[::1]:80/segment/index.html?query#frag"));
  290         uriFreeUriMembersA(&uriA);
  291         ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://user:pass@[::1]/segment/index.html?query#frag"));
  292         uriFreeUriMembersA(&uriA);
  293         ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://user:pass@[::1]:80?query#frag"));
  294         uriFreeUriMembersA(&uriA);
  295         ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://user:pass@[::1]:80/segment/index.html#frag"));
  296         uriFreeUriMembersA(&uriA);
  297         ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://user:pass@[::1]:80/segment/index.html?query"));
  298         uriFreeUriMembersA(&uriA);
  299 
  300         // Schema, port, one segment
  301         ASSERT_TRUE(0 == uriParseUriA(&stateA, "ftp://host:21/gnu/"));
  302         uriFreeUriMembersA(&uriA);
  303 
  304         // Relative
  305         ASSERT_TRUE(0 == uriParseUriA(&stateA, "one/two/three"));
  306         ASSERT_TRUE(!uriA.absolutePath);
  307         uriFreeUriMembersA(&uriA);
  308         ASSERT_TRUE(0 == uriParseUriA(&stateA, "/one/two/three"));
  309         ASSERT_TRUE(uriA.absolutePath);
  310         uriFreeUriMembersA(&uriA);
  311         ASSERT_TRUE(0 == uriParseUriA(&stateA, "//user:pass@localhost/one/two/three"));
  312         uriFreeUriMembersA(&uriA);
  313 
  314         // Both narrow and wide string version
  315         ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://www.example.com/"));
  316         uriFreeUriMembersA(&uriA);
  317         ASSERT_TRUE(0 == uriParseUriW(&stateW, L"http://www.example.com/"));
  318         uriFreeUriMembersW(&uriW);
  319 
  320         // Real life examples
  321         ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://sourceforge.net/projects/uriparser/"));
  322         uriFreeUriMembersA(&uriA);
  323         ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://sourceforge.net/project/platformdownload.php?group_id=182840"));
  324         uriFreeUriMembersA(&uriA);
  325         ASSERT_TRUE(0 == uriParseUriA(&stateA, "mailto:test@example.com"));
  326         uriFreeUriMembersA(&uriA);
  327         ASSERT_TRUE(0 == uriParseUriA(&stateA, "../../"));
  328         uriFreeUriMembersA(&uriA);
  329         ASSERT_TRUE(0 == uriParseUriA(&stateA, "/"));
  330         ASSERT_TRUE(uriA.absolutePath);
  331         uriFreeUriMembersA(&uriA);
  332         ASSERT_TRUE(0 == uriParseUriA(&stateA, ""));
  333         ASSERT_TRUE(!uriA.absolutePath);
  334         uriFreeUriMembersA(&uriA);
  335         ASSERT_TRUE(0 == uriParseUriA(&stateA, "file:///bin/bash"));
  336         uriFreeUriMembersA(&uriA);
  337 
  338         // Percent encoding
  339         ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://www.example.com/name%20with%20spaces/"));
  340         uriFreeUriMembersA(&uriA);
  341         ASSERT_TRUE(0 != uriParseUriA(&stateA, "http://www.example.com/name with spaces/"));
  342         uriFreeUriMembersA(&uriA);
  343 }
  344 
  345 TEST(UriSuite, TestUriComponents) {
  346         UriParserStateA stateA;
  347         UriUriA uriA;
  348         stateA.uri = &uriA;
  349         //                          0   4  0  3  0              15 01  0      7  01
  350         const char * const input = "http" "://" "sourceforge.net" "/" "project" "/"
  351         //       0                   20 01  0              15
  352                 "platformdownload.php" "?" "group_id=182840";
  353         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  354 
  355         ASSERT_TRUE(uriA.scheme.first == input);
  356         ASSERT_TRUE(uriA.scheme.afterLast == input + 4);
  357         ASSERT_TRUE(uriA.userInfo.first == NULL);
  358         ASSERT_TRUE(uriA.userInfo.afterLast == NULL);
  359         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3);
  360         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 15);
  361         ASSERT_TRUE(uriA.hostData.ipFuture.first == NULL);
  362         ASSERT_TRUE(uriA.hostData.ipFuture.afterLast == NULL);
  363         ASSERT_TRUE(uriA.portText.first == NULL);
  364         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  365 
  366         ASSERT_TRUE(uriA.pathHead->text.first == input + 4 + 3 + 15 + 1);
  367         ASSERT_TRUE(uriA.pathHead->text.afterLast == input + 4 + 3 + 15 + 1 + 7);
  368         ASSERT_TRUE(uriA.pathHead->next->text.first == input + 4 + 3 + 15 + 1 + 7 + 1);
  369         ASSERT_TRUE(uriA.pathHead->next->text.afterLast == input + 4 + 3 + 15 + 1 + 7 + 1 + 20);
  370         ASSERT_TRUE(uriA.pathHead->next->next == NULL);
  371         ASSERT_TRUE(uriA.pathTail == uriA.pathHead->next);
  372 
  373         ASSERT_TRUE(uriA.query.first == input + 4 + 3 + 15 + 1 + 7 + 1 + 20 + 1);
  374         ASSERT_TRUE(uriA.query.afterLast == input + 4 + 3 + 15 + 1 + 7 + 1 + 20 + 1 + 15);
  375         ASSERT_TRUE(uriA.fragment.first == NULL);
  376         ASSERT_TRUE(uriA.fragment.afterLast == NULL);
  377         uriFreeUriMembersA(&uriA);
  378 }
  379 
  380 TEST(UriSuite, TestUriComponentsBug20070701) {
  381         UriParserStateA stateA;
  382         UriUriA uriA;
  383         stateA.uri = &uriA;
  384         //                          01  01  01
  385         const char * const input = "a" ":" "b";
  386         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  387 
  388         ASSERT_TRUE(uriA.scheme.first == input);
  389         ASSERT_TRUE(uriA.scheme.afterLast == input + 1);
  390         ASSERT_TRUE(uriA.userInfo.first == NULL);
  391         ASSERT_TRUE(uriA.userInfo.afterLast == NULL);
  392         ASSERT_TRUE(uriA.hostText.first == NULL);
  393         ASSERT_TRUE(uriA.hostText.afterLast == NULL);
  394         ASSERT_TRUE(uriA.hostData.ipFuture.first == NULL);
  395         ASSERT_TRUE(uriA.hostData.ipFuture.afterLast == NULL);
  396         ASSERT_TRUE(uriA.portText.first == NULL);
  397         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  398 
  399         ASSERT_TRUE(uriA.pathHead->text.first == input + 1 + 1);
  400         ASSERT_TRUE(uriA.pathHead->text.afterLast == input + 1 + 1 + 1);
  401         ASSERT_TRUE(uriA.pathHead->next == NULL);
  402         ASSERT_TRUE(uriA.pathTail == uriA.pathHead);
  403 
  404         ASSERT_TRUE(uriA.query.first == NULL);
  405         ASSERT_TRUE(uriA.query.afterLast == NULL);
  406         ASSERT_TRUE(uriA.fragment.first == NULL);
  407         ASSERT_TRUE(uriA.fragment.afterLast == NULL);
  408 
  409         ASSERT_TRUE(!uriA.absolutePath);
  410         uriFreeUriMembersA(&uriA);
  411 }
  412 
  413 TEST(UriSuite, TestUriUserInfoHostPort1) {
  414         // User info with ":", no port
  415         UriParserStateA stateA;
  416         UriUriA uriA;
  417         stateA.uri = &uriA;
  418         //                          0   4  0  3  0      7  01  0        9
  419         const char * const input = "http" "://" "abc:def" "@" "localhost";
  420         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  421 
  422         ASSERT_TRUE(uriA.userInfo.first == input + 4 + 3);
  423         ASSERT_TRUE(uriA.userInfo.afterLast == input + 4 + 3 + 7);
  424         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3 + 7 + 1);
  425         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 7 + 1 + 9);
  426         ASSERT_TRUE(uriA.portText.first == NULL);
  427         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  428         uriFreeUriMembersA(&uriA);
  429 }
  430 
  431 TEST(UriSuite, TestUriUserInfoHostPort2) {
  432         // User info with ":", with port
  433         UriParserStateA stateA;
  434         UriUriA uriA;
  435         stateA.uri = &uriA;
  436         //                          0   4  0  3  0      7  01  0        9
  437         const char * const input = "http" "://" "abc:def" "@" "localhost"
  438         //      01   0  3
  439                 ":" "123";
  440         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  441 
  442         ASSERT_TRUE(uriA.userInfo.first == input + 4 + 3);
  443         ASSERT_TRUE(uriA.userInfo.afterLast == input + 4 + 3 + 7);
  444         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3 + 7 + 1);
  445         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 7 + 1 + 9);
  446         ASSERT_TRUE(uriA.portText.first == input + 4 + 3 + 7 + 1 + 9 + 1);
  447         ASSERT_TRUE(uriA.portText.afterLast == input + 4 + 3 + 7 + 1 + 9 + 1 + 3);
  448         uriFreeUriMembersA(&uriA);
  449 }
  450 
  451 TEST(UriSuite, TestUriUserInfoHostPort22Bug1948038) {
  452         UriParserStateA stateA;
  453         UriUriA uriA;
  454         stateA.uri = &uriA;
  455 
  456         int res;
  457 
  458         res = uriParseUriA(&stateA, "http://user:21@host/");
  459         ASSERT_TRUE(URI_SUCCESS == res);
  460         ASSERT_TRUE(!memcmp(uriA.userInfo.first, "user:21", 7 * sizeof(char)));
  461         ASSERT_TRUE(uriA.userInfo.afterLast - uriA.userInfo.first == 7);
  462         ASSERT_TRUE(!memcmp(uriA.hostText.first, "host", 4 * sizeof(char)));
  463         ASSERT_TRUE(uriA.hostText.afterLast - uriA.hostText.first == 4);
  464         ASSERT_TRUE(uriA.portText.first == NULL);
  465         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  466         uriFreeUriMembersA(&uriA);
  467 
  468         res = uriParseUriA(&stateA, "http://user:1234@192.168.0.1:1234/foo.com");
  469         ASSERT_TRUE(URI_SUCCESS == res);
  470         uriFreeUriMembersA(&uriA);
  471 
  472         res = uriParseUriA(&stateA, "http://moo:21@moo:21@moo/");
  473         ASSERT_TRUE(URI_ERROR_SYNTAX == res);
  474         uriFreeUriMembersA(&uriA);
  475 
  476         res = uriParseUriA(&stateA, "http://moo:21@moo:21@moo:21/");
  477         ASSERT_TRUE(URI_ERROR_SYNTAX == res);
  478         uriFreeUriMembersA(&uriA);
  479 }
  480 
  481 TEST(UriSuite, TestUriUserInfoHostPort23Bug3510198One) {
  482         // User info with ":", with port, with escaped chars in password
  483         UriParserStateA stateA;
  484         UriUriA uriA;
  485         stateA.uri = &uriA;
  486 
  487         int res;
  488         //                           0   4  0  3  0         10 01  0   4  01
  489         res = uriParseUriA(&stateA, "http" "://" "user:%2F21" "@" "host" "/");
  490         ASSERT_TRUE(URI_SUCCESS == res);
  491         ASSERT_TRUE(!memcmp(uriA.userInfo.first, "user:%2F21", 10 * sizeof(char)));
  492         ASSERT_TRUE(uriA.userInfo.afterLast - uriA.userInfo.first == 10);
  493         ASSERT_TRUE(!memcmp(uriA.hostText.first, "host", 4 * sizeof(char)));
  494         ASSERT_TRUE(uriA.hostText.afterLast - uriA.hostText.first == 4);
  495         ASSERT_TRUE(uriA.portText.first == NULL);
  496         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  497         uriFreeUriMembersA(&uriA);
  498 }
  499 
  500 TEST(UriSuite, TestUriUserInfoHostPort23Bug3510198Two) {
  501         // User info with ":", with port, with escaped chars in user name and password
  502         UriParserStateA stateA;
  503         UriUriA uriA;
  504         stateA.uri = &uriA;
  505 
  506         int res;
  507         //                           0   4  0  3  0            13 01  0   4  01
  508         res = uriParseUriA(&stateA, "http" "://" "%2Fuser:%2F21" "@" "host" "/");
  509         ASSERT_TRUE(URI_SUCCESS == res);
  510         ASSERT_TRUE(!memcmp(uriA.userInfo.first, "%2Fuser:%2F21", 13 * sizeof(char)));
  511         ASSERT_TRUE(uriA.userInfo.afterLast - uriA.userInfo.first == 13);
  512         ASSERT_TRUE(!memcmp(uriA.hostText.first, "host", 4 * sizeof(char)));
  513         ASSERT_TRUE(uriA.hostText.afterLast - uriA.hostText.first == 4);
  514         ASSERT_TRUE(uriA.portText.first == NULL);
  515         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  516         uriFreeUriMembersA(&uriA);
  517 }
  518 
  519 TEST(UriSuite, TestUriUserInfoHostPort23Bug3510198Three) {
  520         // User info with ":", with port, with escaped chars in password
  521         UriParserStateA stateA;
  522         UriUriA uriA;
  523         stateA.uri = &uriA;
  524 
  525         int res;
  526         //                           0   4  0  3  0               16 01  0   4  01
  527         res = uriParseUriA(&stateA, "http" "://" "user:!$&'()*+,;=" "@" "host" "/");
  528         ASSERT_TRUE(URI_SUCCESS == res);
  529         ASSERT_TRUE(!memcmp(uriA.userInfo.first, "user:!$&'()*+,;=", 16 * sizeof(char)));
  530         ASSERT_TRUE(uriA.userInfo.afterLast - uriA.userInfo.first == 16);
  531         ASSERT_TRUE(!memcmp(uriA.hostText.first, "host", 4 * sizeof(char)));
  532         ASSERT_TRUE(uriA.hostText.afterLast - uriA.hostText.first == 4);
  533         ASSERT_TRUE(uriA.portText.first == NULL);
  534         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  535         uriFreeUriMembersA(&uriA);
  536 }
  537 
  538 TEST(UriSuite, TestUriUserInfoHostPort23Bug3510198Four) {
  539         // User info with ":", with port, with escaped chars in user name and password
  540         UriParserStateA stateA;
  541         UriUriA uriA;
  542         stateA.uri = &uriA;
  543 
  544         int res;
  545         //                           0   4  0  3  0                   20 01  0   4  01
  546         res = uriParseUriA(&stateA, "http" "://" "!$&'()*+,;=:password" "@" "host" "/");
  547         ASSERT_TRUE(URI_SUCCESS == res);
  548         ASSERT_TRUE(!memcmp(uriA.userInfo.first, "!$&'()*+,;=:password", 20 * sizeof(char)));
  549         ASSERT_TRUE(uriA.userInfo.afterLast - uriA.userInfo.first == 20);
  550         ASSERT_TRUE(!memcmp(uriA.hostText.first, "host", 4 * sizeof(char)));
  551         ASSERT_TRUE(uriA.hostText.afterLast - uriA.hostText.first == 4);
  552         ASSERT_TRUE(uriA.portText.first == NULL);
  553         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  554         uriFreeUriMembersA(&uriA);
  555 }
  556 
  557 TEST(UriSuite, TestUriUserInfoHostPort23Bug3510198RelatedOne) {
  558         // Empty user info
  559         UriParserStateA stateA;
  560         UriUriA uriA;
  561         stateA.uri = &uriA;
  562 
  563         int res;
  564         //                           0   4  0  3  01  0   4  01
  565         res = uriParseUriA(&stateA, "http" "://" "@" "host" "/");
  566         ASSERT_TRUE(URI_SUCCESS == res);
  567         ASSERT_TRUE(uriA.userInfo.afterLast != NULL);
  568         ASSERT_TRUE(uriA.userInfo.first != NULL);
  569         ASSERT_TRUE(uriA.userInfo.afterLast - uriA.userInfo.first == 0);
  570         ASSERT_TRUE(!memcmp(uriA.hostText.first, "host", 4 * sizeof(char)));
  571         ASSERT_TRUE(uriA.hostText.afterLast - uriA.hostText.first == 4);
  572         ASSERT_TRUE(uriA.portText.first == NULL);
  573         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  574         uriFreeUriMembersA(&uriA);
  575 }
  576 
  577 TEST(UriSuite, TestUriUserInfoHostPort23Bug3510198RelatedOneTwo) {
  578         // Empty user info
  579         UriParserStateA stateA;
  580         UriUriA uriA;
  581         stateA.uri = &uriA;
  582 
  583         int res;
  584         //                           0   4  0  3  0      7  01
  585         res = uriParseUriA(&stateA, "http" "://" "%2Fhost" "/");
  586         ASSERT_TRUE(URI_SUCCESS == res);
  587         ASSERT_TRUE(uriA.userInfo.afterLast == NULL);
  588         ASSERT_TRUE(uriA.userInfo.first == NULL);
  589         ASSERT_TRUE(!memcmp(uriA.hostText.first, "%2Fhost", 7 * sizeof(char)));
  590         ASSERT_TRUE(uriA.hostText.afterLast - uriA.hostText.first == 7);
  591         ASSERT_TRUE(uriA.portText.first == NULL);
  592         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  593         uriFreeUriMembersA(&uriA);
  594 }
  595 
  596 TEST(UriSuite, TestUriUserInfoHostPort23Bug3510198RelatedTwo) {
  597         // Several colons in userinfo
  598         UriParserStateA stateA;
  599         UriUriA uriA;
  600         stateA.uri = &uriA;
  601 
  602         int res;
  603         //                           0   4  0  3  0 2  01  0   4  01
  604         res = uriParseUriA(&stateA, "http" "://" "::" "@" "host" "/");
  605         ASSERT_TRUE(URI_SUCCESS == res);
  606         ASSERT_TRUE(!memcmp(uriA.userInfo.first, "::", 2 * sizeof(char)));
  607         ASSERT_TRUE(uriA.userInfo.afterLast - uriA.userInfo.first == 2);
  608         ASSERT_TRUE(!memcmp(uriA.hostText.first, "host", 4 * sizeof(char)));
  609         ASSERT_TRUE(uriA.hostText.afterLast - uriA.hostText.first == 4);
  610         ASSERT_TRUE(uriA.portText.first == NULL);
  611         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  612         uriFreeUriMembersA(&uriA);
  613 }
  614 
  615 TEST(UriSuite, TestUriUserInfoHostPort3) {
  616         // User info without ":", no port
  617         UriParserStateA stateA;
  618         UriUriA uriA;
  619         stateA.uri = &uriA;
  620         //                          0   4  0  3  0      7  01  0        9
  621         const char * const input = "http" "://" "abcdefg" "@" "localhost";
  622         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  623 
  624         ASSERT_TRUE(uriA.userInfo.first == input + 4 + 3);
  625         ASSERT_TRUE(uriA.userInfo.afterLast == input + 4 + 3 + 7);
  626         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3 + 7 + 1);
  627         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 7 + 1 + 9);
  628         ASSERT_TRUE(uriA.portText.first == NULL);
  629         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  630         uriFreeUriMembersA(&uriA);
  631 }
  632 
  633 TEST(UriSuite, TestUriUserInfoHostPort4) {
  634         // User info without ":", with port
  635         UriParserStateA stateA;
  636         UriUriA uriA;
  637         stateA.uri = &uriA;
  638         //                          0   4  0  3  0      7  01  0        9
  639         const char * const input = "http" "://" "abcdefg" "@" "localhost"
  640         //      01   0  3
  641                 ":" "123";
  642         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  643 
  644         ASSERT_TRUE(uriA.userInfo.first == input + 4 + 3);
  645         ASSERT_TRUE(uriA.userInfo.afterLast == input + 4 + 3 + 7);
  646         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3 + 7 + 1);
  647         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 7 + 1 + 9);
  648         ASSERT_TRUE(uriA.portText.first == input + 4 + 3 + 7 + 1 + 9 + 1);
  649         ASSERT_TRUE(uriA.portText.afterLast == input + 4 + 3 + 7 + 1 + 9 + 1 + 3);
  650         uriFreeUriMembersA(&uriA);
  651 }
  652 
  653 TEST(UriSuite, TestUriUserInfoHostPort5) {
  654         // No user info, no port
  655         UriParserStateA stateA;
  656         UriUriA uriA;
  657         stateA.uri = &uriA;
  658         //                          0   4  0  3  0        9
  659         const char * const input = "http" "://" "localhost";
  660         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  661 
  662         ASSERT_TRUE(uriA.userInfo.first == NULL);
  663         ASSERT_TRUE(uriA.userInfo.afterLast == NULL);
  664         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3);
  665         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 9);
  666         ASSERT_TRUE(uriA.portText.first == NULL);
  667         ASSERT_TRUE(uriA.portText.afterLast == NULL);
  668         uriFreeUriMembersA(&uriA);
  669 }
  670 
  671 TEST(UriSuite, TestUriUserInfoHostPort6) {
  672         // No user info, with port
  673         UriParserStateA stateA;
  674         UriUriA uriA;
  675         stateA.uri = &uriA;
  676         //                          0   4  0  3  0        9  01  0  3
  677         const char * const input = "http" "://" "localhost" ":" "123";
  678         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  679 
  680         ASSERT_TRUE(uriA.userInfo.first == NULL);
  681         ASSERT_TRUE(uriA.userInfo.afterLast == NULL);
  682         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3);
  683         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 9);
  684         ASSERT_TRUE(uriA.portText.first == input + 4 + 3 + 9 + 1);
  685         ASSERT_TRUE(uriA.portText.afterLast == input + 4 + 3 + 9 + 1 + 3);
  686         uriFreeUriMembersA(&uriA);
  687 }
  688 
  689 TEST(UriSuite, TestUriHostRegname) {
  690         UriParserStateA stateA;
  691         UriUriA uriA;
  692         stateA.uri = &uriA;
  693         //                          0   4  0  3  0          11
  694         const char * const input = "http" "://" "example.com";
  695         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  696 
  697         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3);
  698         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 11);
  699         ASSERT_TRUE(uriA.hostData.ip4 == NULL);
  700         ASSERT_TRUE(uriA.hostData.ip6 == NULL);
  701         ASSERT_TRUE(uriA.hostData.ipFuture.first == NULL);
  702         ASSERT_TRUE(uriA.hostData.ipFuture.afterLast == NULL);
  703         uriFreeUriMembersA(&uriA);
  704 }
  705 
  706 TEST(UriSuite, TestUriHostIpFour1) {
  707         UriParserStateA stateA;
  708         UriUriA uriA;
  709         stateA.uri = &uriA;
  710         //                          0   4  0  3  0      7  01  0 2
  711         const char * const input = "http" "://" "1.2.3.4" ":" "80";
  712         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  713 
  714         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3);
  715         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 7);
  716         ASSERT_TRUE(uriA.hostData.ip4 != NULL);
  717         ASSERT_TRUE(uriA.hostData.ip6 == NULL);
  718         ASSERT_TRUE(uriA.hostData.ipFuture.first == NULL);
  719         ASSERT_TRUE(uriA.hostData.ipFuture.afterLast == NULL);
  720         uriFreeUriMembersA(&uriA);
  721 }
  722 
  723 TEST(UriSuite, TestUriHostIpFour2) {
  724         UriParserStateA stateA;
  725         UriUriA uriA;
  726         stateA.uri = &uriA;
  727         //                          0   4  0  3  0      7
  728         const char * const input = "http" "://" "1.2.3.4";
  729         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  730 
  731         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3);
  732         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 7);
  733         ASSERT_TRUE(uriA.hostData.ip4 != NULL);
  734         ASSERT_TRUE(uriA.hostData.ip6 == NULL);
  735         ASSERT_TRUE(uriA.hostData.ipFuture.first == NULL);
  736         ASSERT_TRUE(uriA.hostData.ipFuture.afterLast == NULL);
  737         uriFreeUriMembersA(&uriA);
  738 }
  739 
  740 TEST(UriSuite, TestUriHostIpSix1) {
  741         UriParserStateA stateA;
  742         UriUriA uriA;
  743         stateA.uri = &uriA;
  744         //                          0   4  0  3  01  45  01  0 2
  745         const char * const input = "http" "://" "[::1]" ":" "80";
  746         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  747 
  748         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3 + 1);
  749         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 4);
  750         ASSERT_TRUE(uriA.hostData.ip4 == NULL);
  751         ASSERT_TRUE(uriA.hostData.ip6 != NULL);
  752         ASSERT_TRUE(uriA.hostData.ipFuture.first == NULL);
  753         ASSERT_TRUE(uriA.hostData.ipFuture.afterLast == NULL);
  754         uriFreeUriMembersA(&uriA);
  755 }
  756 
  757 TEST(UriSuite, TestUriHostIpSix2) {
  758         UriParserStateA stateA;
  759         UriUriA uriA;
  760         stateA.uri = &uriA;
  761         //                          0   4  0  3  01  45
  762         const char * const input = "http" "://" "[::1]";
  763         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
  764 
  765         ASSERT_TRUE(uriA.hostText.first == input + 4 + 3 + 1);
  766         ASSERT_TRUE(uriA.hostText.afterLast == input + 4 + 3 + 4);
  767         ASSERT_TRUE(uriA.hostData.ip4 == NULL);
  768         ASSERT_TRUE(uriA.hostData.ip6 != NULL);
  769         ASSERT_TRUE(uriA.hostData.ipFuture.first == NULL);
  770         ASSERT_TRUE(uriA.hostData.ipFuture.afterLast == NULL);
  771         uriFreeUriMembersA(&uriA);
  772 }
  773 
  774 TEST(UriSuite, TestUriHostEmpty) {
  775         UriParserStateA stateA;
  776         UriUriA uriA;
  777         stateA.uri = &uriA;
  778         //                          0   4  0  3  01  0  3
  779         const char * const input = "http" "://" ":" "123";
  780         const int res = uriParseUriA(&stateA, input);
  781         ASSERT_TRUE(URI_SUCCESS == res);
  782         ASSERT_TRUE(uriA.userInfo.first == NULL);
  783         ASSERT_TRUE(uriA.userInfo.afterLast == NULL);
  784         ASSERT_TRUE(uriA.hostText.first != NULL);
  785         ASSERT_TRUE(uriA.hostText.afterLast != NULL);
  786         ASSERT_TRUE(uriA.hostText.afterLast - uriA.hostText.first == 0);
  787         ASSERT_TRUE(uriA.portText.first == input + 4 + 3 + 1);
  788         ASSERT_TRUE(uriA.portText.afterLast == input + 4 + 3 + 1 + 3);
  789         uriFreeUriMembersA(&uriA);
  790 }
  791 
  792 TEST(UriSuite, TestUriHostIpFuture) {
  793         // TODO
  794 }
  795 
  796 namespace {
  797     bool testEscapingHelper(const wchar_t * in, const wchar_t * expectedOut,
  798             bool spaceToPlus = false, bool normalizeBreaks = false) {
  799         wchar_t * const buffer = new wchar_t[(normalizeBreaks ? 6 : 3)
  800                 * wcslen(in) + 1];
  801         if (uriEscapeW(in, buffer, spaceToPlus, normalizeBreaks)
  802             != buffer + wcslen(expectedOut)) {
  803             delete [] buffer;
  804             return false;
  805         }
  806 
  807         const bool equal = !wcscmp(buffer, expectedOut);
  808         delete [] buffer;
  809         return equal;
  810     }
  811 }  // namespace
  812 
  813 TEST(UriSuite, TestEscaping) {
  814         const bool SPACE_TO_PLUS = true;
  815         const bool SPACE_TO_PERCENT = false;
  816         const bool KEEP_UNMODIFIED = false;
  817         const bool NORMALIZE = true;
  818 
  819         // '+' to ' '
  820         ASSERT_TRUE(testEscapingHelper(L"abc def", L"abc+def", SPACE_TO_PLUS));
  821         ASSERT_TRUE(testEscapingHelper(L"abc def", L"abc%20def", SPACE_TO_PERCENT));
  822 
  823         // Percent encoding
  824         ASSERT_TRUE(testEscapingHelper(L"\x00", L"\0"));
  825         ASSERT_TRUE(testEscapingHelper(L"\x01", L"%01"));
  826         ASSERT_TRUE(testEscapingHelper(L"\xff", L"%FF"));
  827 
  828         // Linebreak normalization
  829         ASSERT_TRUE(testEscapingHelper(L"\x0d", L"%0D%0A", SPACE_TO_PLUS, NORMALIZE));
  830         ASSERT_TRUE(testEscapingHelper(L"g\x0d", L"g%0D%0A", SPACE_TO_PLUS, NORMALIZE));
  831         ASSERT_TRUE(testEscapingHelper(L"\x0dg", L"%0D%0Ag", SPACE_TO_PLUS, NORMALIZE));
  832         ASSERT_TRUE(testEscapingHelper(L"\x0d", L"%0D", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  833         ASSERT_TRUE(testEscapingHelper(L"g\x0d", L"g%0D", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  834         ASSERT_TRUE(testEscapingHelper(L"\x0dg", L"%0Dg", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  835 
  836         ASSERT_TRUE(testEscapingHelper(L"\x0a", L"%0D%0A", SPACE_TO_PLUS, NORMALIZE));
  837         ASSERT_TRUE(testEscapingHelper(L"g\x0a", L"g%0D%0A", SPACE_TO_PLUS, NORMALIZE));
  838         ASSERT_TRUE(testEscapingHelper(L"\x0ag", L"%0D%0Ag", SPACE_TO_PLUS, NORMALIZE));
  839         ASSERT_TRUE(testEscapingHelper(L"\x0a", L"%0A", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  840         ASSERT_TRUE(testEscapingHelper(L"g\x0a", L"g%0A", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  841         ASSERT_TRUE(testEscapingHelper(L"\x0ag", L"%0Ag", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  842 
  843         ASSERT_TRUE(testEscapingHelper(L"\x0d\x0a", L"%0D%0A", SPACE_TO_PLUS, NORMALIZE));
  844         ASSERT_TRUE(testEscapingHelper(L"g\x0d\x0a", L"g%0D%0A", SPACE_TO_PLUS, NORMALIZE));
  845         ASSERT_TRUE(testEscapingHelper(L"\x0d\x0ag", L"%0D%0Ag", SPACE_TO_PLUS, NORMALIZE));
  846         ASSERT_TRUE(testEscapingHelper(L"\x0d\x0a", L"%0D%0A", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  847         ASSERT_TRUE(testEscapingHelper(L"g\x0d\x0a", L"g%0D%0A", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  848         ASSERT_TRUE(testEscapingHelper(L"\x0d\x0ag", L"%0D%0Ag", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  849 
  850         ASSERT_TRUE(testEscapingHelper(L"\x0a\x0d", L"%0D%0A%0D%0A", SPACE_TO_PLUS, NORMALIZE));
  851         ASSERT_TRUE(testEscapingHelper(L"g\x0a\x0d", L"g%0D%0A%0D%0A", SPACE_TO_PLUS, NORMALIZE));
  852         ASSERT_TRUE(testEscapingHelper(L"\x0a\x0dg", L"%0D%0A%0D%0Ag", SPACE_TO_PLUS, NORMALIZE));
  853         ASSERT_TRUE(testEscapingHelper(L"\x0a\x0d", L"%0A%0D", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  854         ASSERT_TRUE(testEscapingHelper(L"g\x0a\x0d", L"g%0A%0D", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  855         ASSERT_TRUE(testEscapingHelper(L"\x0a\x0dg", L"%0A%0Dg", SPACE_TO_PLUS, KEEP_UNMODIFIED));
  856 }
  857 
  858 namespace {
  859     bool testUnescapingHelper(const wchar_t * input, const wchar_t * output,
  860             bool plusToSpace = false, UriBreakConversion breakConversion = URI_BR_DONT_TOUCH) {
  861         wchar_t * working = new wchar_t[URI_STRLEN(input) + 1];
  862         wcscpy(working, input);
  863         const wchar_t * newTermZero = uriUnescapeInPlaceExW(working,
  864                 plusToSpace ? URI_TRUE : URI_FALSE, breakConversion);
  865         const bool success = ((newTermZero == working + wcslen(output))
  866                 && !wcscmp(working, output));
  867         delete[] working;
  868         return success;
  869     }
  870 }  // namespace
  871 
  872 TEST(UriSuite, TestUnescaping) {
  873         const bool PLUS_TO_SPACE = true;
  874         const bool PLUS_DONT_TOUCH = false;
  875 
  876 
  877         // Proper
  878         ASSERT_TRUE(testUnescapingHelper(L"abc%20%41BC", L"abc ABC"));
  879         ASSERT_TRUE(testUnescapingHelper(L"%20", L" "));
  880 
  881         // Incomplete
  882         ASSERT_TRUE(testUnescapingHelper(L"%0", L"%0"));
  883 
  884         // Nonhex
  885         ASSERT_TRUE(testUnescapingHelper(L"%0g", L"%0g"));
  886         ASSERT_TRUE(testUnescapingHelper(L"%G0", L"%G0"));
  887 
  888         // No double decoding
  889         ASSERT_TRUE(testUnescapingHelper(L"%2520", L"%20"));
  890 
  891         // Decoding of '+'
  892         ASSERT_TRUE(testUnescapingHelper(L"abc+def", L"abc+def", PLUS_DONT_TOUCH));
  893         ASSERT_TRUE(testUnescapingHelper(L"abc+def", L"abc def", PLUS_TO_SPACE));
  894 
  895         // Line break conversion
  896         ASSERT_TRUE(testUnescapingHelper(L"%0d", L"\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  897         ASSERT_TRUE(testUnescapingHelper(L"%0d", L"\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  898         ASSERT_TRUE(testUnescapingHelper(L"%0d", L"\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  899         ASSERT_TRUE(testUnescapingHelper(L"%0d", L"\x0d", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  900 
  901         ASSERT_TRUE(testUnescapingHelper(L"%0d%0d", L"\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  902         ASSERT_TRUE(testUnescapingHelper(L"%0d%0d", L"\x0d\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  903         ASSERT_TRUE(testUnescapingHelper(L"%0d%0d", L"\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  904         ASSERT_TRUE(testUnescapingHelper(L"%0d%0d", L"\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  905 
  906 
  907         ASSERT_TRUE(testUnescapingHelper(L"%0a", L"\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  908         ASSERT_TRUE(testUnescapingHelper(L"%0a", L"\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  909         ASSERT_TRUE(testUnescapingHelper(L"%0a", L"\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  910         ASSERT_TRUE(testUnescapingHelper(L"%0a", L"\x0a", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  911 
  912         ASSERT_TRUE(testUnescapingHelper(L"%0a%0a", L"\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  913         ASSERT_TRUE(testUnescapingHelper(L"%0a%0a", L"\x0d\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  914         ASSERT_TRUE(testUnescapingHelper(L"%0a%0a", L"\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  915         ASSERT_TRUE(testUnescapingHelper(L"%0a%0a", L"\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  916 
  917 
  918         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a", L"\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  919         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a", L"\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  920         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a", L"\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  921         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a", L"\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  922 
  923         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0a", L"\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  924         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0a", L"\x0d\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  925         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0a", L"\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  926         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0a", L"\x0d\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  927 
  928         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0d", L"\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  929         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0d", L"\x0d\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  930         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0d", L"\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  931         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0d", L"\x0d\x0a\x0d", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  932 
  933         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0d%0a", L"\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  934         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0d%0a", L"\x0d\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  935         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0d%0a", L"\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  936         ASSERT_TRUE(testUnescapingHelper(L"%0d%0a%0d%0a", L"\x0d\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  937 
  938 
  939         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d", L"\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  940         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d", L"\x0d\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  941         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d", L"\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  942         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d", L"\x0a\x0d", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  943 
  944         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0a", L"\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  945         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0a", L"\x0d\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  946         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0a", L"\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  947         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0a", L"\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  948 
  949         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0d", L"\x0a\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  950         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0d", L"\x0d\x0a\x0d\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  951         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0d", L"\x0d\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  952         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0d", L"\x0a\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  953 
  954         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0a%0d", L"\x0a\x0a\x0a", PLUS_DONT_TOUCH, URI_BR_TO_UNIX));
  955         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0a%0d", L"\x0d\x0a\x0d\x0a\x0d\x0a", PLUS_DONT_TOUCH, URI_BR_TO_WINDOWS));
  956         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0a%0d", L"\x0d\x0d\x0d", PLUS_DONT_TOUCH, URI_BR_TO_MAC));
  957         ASSERT_TRUE(testUnescapingHelper(L"%0a%0d%0a%0d", L"\x0a\x0d\x0a\x0d", PLUS_DONT_TOUCH, URI_BR_DONT_TOUCH));
  958 }
  959 
  960 namespace {
  961     bool testAddBaseHelper(const wchar_t * base, const wchar_t * rel, const wchar_t * expectedResult, bool backward_compatibility = false) {
  962         UriParserStateW stateW;
  963 
  964         // Base
  965         UriUriW baseUri;
  966         stateW.uri = &baseUri;
  967         int res = uriParseUriW(&stateW, base);
  968         if (res != 0) {
  969             uriFreeUriMembersW(&baseUri);
  970             return false;
  971         }
  972 
  973         // Rel
  974         UriUriW relUri;
  975         stateW.uri = &relUri;
  976         res = uriParseUriW(&stateW, rel);
  977         if (res != 0) {
  978             uriFreeUriMembersW(&baseUri);
  979             uriFreeUriMembersW(&relUri);
  980             return false;
  981         }
  982 
  983         // Expected result
  984         UriUriW expectedUri;
  985         stateW.uri = &expectedUri;
  986         res = uriParseUriW(&stateW, expectedResult);
  987         if (res != 0) {
  988             uriFreeUriMembersW(&baseUri);
  989             uriFreeUriMembersW(&relUri);
  990             uriFreeUriMembersW(&expectedUri);
  991             return false;
  992         }
  993 
  994         // Transform
  995         UriUriW transformedUri;
  996         if (backward_compatibility) {
  997             res = uriAddBaseUriExW(&transformedUri, &relUri, &baseUri, URI_RESOLVE_IDENTICAL_SCHEME_COMPAT);
  998         } else {
  999             res = uriAddBaseUriW(&transformedUri, &relUri, &baseUri);
 1000         }
 1001 
 1002         if (res != 0) {
 1003             uriFreeUriMembersW(&baseUri);
 1004             uriFreeUriMembersW(&relUri);
 1005             uriFreeUriMembersW(&expectedUri);
 1006             uriFreeUriMembersW(&transformedUri);
 1007             return false;
 1008         }
 1009 
 1010         const bool equal = (URI_TRUE == uriEqualsUriW(&transformedUri, &expectedUri));
 1011         if (!equal) {
 1012             wchar_t transformedUriText[1024 * 8];
 1013             wchar_t expectedUriText[1024 * 8];
 1014             uriToStringW(transformedUriText, &transformedUri, 1024 * 8, NULL);
 1015             uriToStringW(expectedUriText, &expectedUri, 1024 * 8, NULL);
 1016 #ifdef HAVE_WPRINTF
 1017             wprintf(L"\n\n\nExpected: \"%s\"\nReceived: \"%s\"\n\n\n", expectedUriText, transformedUriText);
 1018 #endif
 1019         }
 1020 
 1021         uriFreeUriMembersW(&baseUri);
 1022         uriFreeUriMembersW(&relUri);
 1023         uriFreeUriMembersW(&expectedUri);
 1024         uriFreeUriMembersW(&transformedUri);
 1025         return equal;
 1026     }
 1027 }  // namespace
 1028 
 1029 TEST(UriSuite, TestTrailingSlash) {
 1030         UriParserStateA stateA;
 1031         UriUriA uriA;
 1032         stateA.uri = &uriA;
 1033         //                          0  3  01
 1034         const char * const input = "abc" "/";
 1035         ASSERT_TRUE(0 == uriParseUriA(&stateA, input));
 1036 
 1037         ASSERT_TRUE(uriA.pathHead->text.first == input);
 1038         ASSERT_TRUE(uriA.pathHead->text.afterLast == input + 3);
 1039         ASSERT_TRUE(uriA.pathHead->next->text.first == uriA.pathHead->next->text.afterLast);
 1040         ASSERT_TRUE(uriA.pathHead->next->next == NULL);
 1041         ASSERT_TRUE(uriA.pathTail == uriA.pathHead->next);
 1042         uriFreeUriMembersA(&uriA);
 1043 }
 1044 
 1045 TEST(UriSuite, TestAddBase) {
 1046         // 5.4.1. Normal Examples
 1047         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g:h", L"g:h"));
 1048         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g", L"http://a/b/c/g"));
 1049         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"./g", L"http://a/b/c/g"));
 1050         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g/", L"http://a/b/c/g/"));
 1051         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"/g", L"http://a/g"));
 1052         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"//g", L"http://g"));
 1053         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"?y", L"http://a/b/c/d;p?y"));
 1054         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g?y", L"http://a/b/c/g?y"));
 1055         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"#s", L"http://a/b/c/d;p?q#s"));
 1056         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g#s", L"http://a/b/c/g#s"));
 1057         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g?y#s", L"http://a/b/c/g?y#s"));
 1058         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L";x", L"http://a/b/c/;x"));
 1059         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g;x", L"http://a/b/c/g;x"));
 1060         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g;x?y#s", L"http://a/b/c/g;x?y#s"));
 1061         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"", L"http://a/b/c/d;p?q"));
 1062         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L".", L"http://a/b/c/"));
 1063         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"./", L"http://a/b/c/"));
 1064         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"..", L"http://a/b/"));
 1065         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../", L"http://a/b/"));
 1066         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../g", L"http://a/b/g"));
 1067         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../..", L"http://a/"));
 1068         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../../", L"http://a/"));
 1069         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../../g", L"http://a/g"));
 1070 
 1071         // 5.4.2. Abnormal Examples
 1072         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../../../g", L"http://a/g"));
 1073         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../../../../g", L"http://a/g"));
 1074         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"/./g", L"http://a/g"));
 1075         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"/../g", L"http://a/g"));
 1076         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g.", L"http://a/b/c/g."));
 1077         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L".g", L"http://a/b/c/.g"));
 1078         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g..", L"http://a/b/c/g.."));
 1079         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"..g", L"http://a/b/c/..g"));
 1080         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"./../g", L"http://a/b/g"));
 1081         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"./g/.", L"http://a/b/c/g/"));
 1082         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g/./h", L"http://a/b/c/g/h"));
 1083         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g/../h", L"http://a/b/c/h"));
 1084         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g;x=1/./y", L"http://a/b/c/g;x=1/y"));
 1085         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g;x=1/../y", L"http://a/b/c/y"));
 1086         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g?y/./x", L"http://a/b/c/g?y/./x"));
 1087         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g?y/../x", L"http://a/b/c/g?y/../x"));
 1088         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g#s/./x", L"http://a/b/c/g#s/./x"));
 1089         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"g#s/../x", L"http://a/b/c/g#s/../x"));
 1090         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"http:g", L"http:g"));
 1091 
 1092         // Backward compatibility (feature request #4, RFC3986 5.4.2)
 1093         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"http:g", L"http:g", false));
 1094         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"http:g", L"http://a/b/c/g", true));
 1095         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"http:g?q#f", L"http://a/b/c/g?q#f", true));
 1096         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"other:g?q#f", L"other:g?q#f", true));
 1097 
 1098         // Bug related to absolutePath flag set despite presence of host
 1099         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"/", L"http://a/"));
 1100         ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"/g/", L"http://a/g/"));
 1101 
 1102         // GitHub issue #92
 1103         EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/../d;p?q", L"../..", L"http://a/"));
 1104         EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/../d;p?q", L"../../", L"http://a/"));
 1105 
 1106         EXPECT_TRUE(testAddBaseHelper(L"http://a/b/../c/d;p?q", L"../..", L"http://a/"));
 1107         EXPECT_TRUE(testAddBaseHelper(L"http://a/b/../c/d;p?q", L"../../", L"http://a/"));
 1108 
 1109         EXPECT_TRUE(testAddBaseHelper(L"http://a/../b/c/d;p?q", L"../..", L"http://a/"));
 1110         EXPECT_TRUE(testAddBaseHelper(L"http://a/../b/c/d;p?q", L"../../", L"http://a/"));
 1111 
 1112         EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../../..", L"http://a/"));
 1113         EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../../../", L"http://a/"));
 1114 }
 1115 
 1116 namespace {
 1117     bool testToStringHelper(const wchar_t * text) {
 1118         // Parse
 1119         UriParserStateW state;
 1120         UriUriW uri;
 1121         state.uri = &uri;
 1122         int res = uriParseUriW(&state, text);
 1123         if (res != 0) {
 1124             uriFreeUriMembersW(&uri);
 1125             return false;
 1126         }
 1127 
 1128         // Back to string, _huge_ limit
 1129         wchar_t shouldbeTheSame[1024 * 8];
 1130         res = uriToStringW(shouldbeTheSame, &uri, 1024 * 8, NULL);
 1131         if (res != 0) {
 1132             uriFreeUriMembersW(&uri);
 1133             return false;
 1134         }
 1135 
 1136         // Compare
 1137         bool equals = (0 == wcscmp(shouldbeTheSame, text));
 1138         if (!equals) {
 1139 #ifdef HAVE_WPRINTF
 1140             wprintf(L"\n\n\nExpected: \"%s\"\nReceived: \"%s\"\n\n\n", text, shouldbeTheSame);
 1141 #endif
 1142         }
 1143 
 1144         // Back to string, _exact_ limit
 1145         const int len = static_cast<int>(wcslen(text));
 1146         int charsWritten;
 1147         res = uriToStringW(shouldbeTheSame, &uri, len + 1, &charsWritten);
 1148         if ((res != 0) || (charsWritten != len + 1)) {
 1149             uriFreeUriMembersW(&uri);
 1150             return false;
 1151         }
 1152 
 1153         // Back to string, _too small_ limit
 1154         res = uriToStringW(shouldbeTheSame, &uri, len, &charsWritten);
 1155         if ((res == 0) || (charsWritten >= len + 1)) {
 1156             uriFreeUriMembersW(&uri);
 1157             return false;
 1158         }
 1159 
 1160         uriFreeUriMembersW(&uri);
 1161         return equals;
 1162     }
 1163 }  // namespace
 1164 
 1165 TEST(UriSuite, TestToString) {
 1166         // Scheme
 1167         ASSERT_TRUE(testToStringHelper(L"ftp://localhost/"));
 1168         // UserInfo
 1169         ASSERT_TRUE(testToStringHelper(L"http://user:pass@localhost/"));
 1170         // IPv4
 1171         ASSERT_TRUE(testToStringHelper(L"http://123.0.1.255/"));
 1172         // IPv6
 1173         ASSERT_TRUE(testToStringHelper(L"http://[abcd:abcd:abcd:abcd:abcd:abcd:abcd:abcd]/"));
 1174         // IPvFuture
 1175         ASSERT_TRUE(testToStringHelper(L"http://[vA.123456]/"));
 1176         // Port
 1177         ASSERT_TRUE(testToStringHelper(L"http://example.com:123/"));
 1178         // Path
 1179         ASSERT_TRUE(testToStringHelper(L"http://example.com"));
 1180         ASSERT_TRUE(testToStringHelper(L"http://example.com/"));
 1181         ASSERT_TRUE(testToStringHelper(L"http://example.com/abc/"));
 1182         ASSERT_TRUE(testToStringHelper(L"http://example.com/abc/def"));
 1183         ASSERT_TRUE(testToStringHelper(L"http://example.com/abc/def/"));
 1184         ASSERT_TRUE(testToStringHelper(L"http://example.com//"));
 1185         ASSERT_TRUE(testToStringHelper(L"http://example.com/./.."));
 1186         // Query
 1187         ASSERT_TRUE(testToStringHelper(L"http://example.com/?abc"));
 1188         // Fragment
 1189         ASSERT_TRUE(testToStringHelper(L"http://example.com/#abc"));
 1190         ASSERT_TRUE(testToStringHelper(L"http://example.com/?def#abc"));
 1191 
 1192         // Relative
 1193         ASSERT_TRUE(testToStringHelper(L"a"));
 1194         ASSERT_TRUE(testToStringHelper(L"a/"));
 1195         ASSERT_TRUE(testToStringHelper(L"/a"));
 1196         ASSERT_TRUE(testToStringHelper(L"/a/"));
 1197         ASSERT_TRUE(testToStringHelper(L"abc"));
 1198         ASSERT_TRUE(testToStringHelper(L"abc/"));
 1199         ASSERT_TRUE(testToStringHelper(L"/abc"));
 1200         ASSERT_TRUE(testToStringHelper(L"/abc/"));
 1201         ASSERT_TRUE(testToStringHelper(L"a/def"));
 1202         ASSERT_TRUE(testToStringHelper(L"a/def/"));
 1203         ASSERT_TRUE(testToStringHelper(L"/a/def"));
 1204         ASSERT_TRUE(testToStringHelper(L"/a/def/"));
 1205         ASSERT_TRUE(testToStringHelper(L"abc/def"));
 1206         ASSERT_TRUE(testToStringHelper(L"abc/def/"));
 1207         ASSERT_TRUE(testToStringHelper(L"/abc/def"));
 1208         ASSERT_TRUE(testToStringHelper(L"/abc/def/"));
 1209         ASSERT_TRUE(testToStringHelper(L"/"));
 1210         ASSERT_TRUE(testToStringHelper(L"//a/"));
 1211         ASSERT_TRUE(testToStringHelper(L"."));
 1212         ASSERT_TRUE(testToStringHelper(L"./"));
 1213         ASSERT_TRUE(testToStringHelper(L"/."));
 1214         ASSERT_TRUE(testToStringHelper(L"/./"));
 1215         ASSERT_TRUE(testToStringHelper(L""));
 1216         ASSERT_TRUE(testToStringHelper(L"./abc/def"));
 1217         ASSERT_TRUE(testToStringHelper(L"?query"));
 1218         ASSERT_TRUE(testToStringHelper(L"#fragment"));
 1219         ASSERT_TRUE(testToStringHelper(L"?query#fragment"));
 1220 
 1221         // Tests for bugs from the past
 1222         ASSERT_TRUE(testToStringHelper(L"f:/.//g"));
 1223 }
 1224 
 1225 TEST(UriSuite, TestToStringBug1950126) {
 1226         UriParserStateW state;
 1227         UriUriW uriOne;
 1228         UriUriW uriTwo;
 1229         const wchar_t * const uriOneString = L"http://e.com/";
 1230         const wchar_t * const uriTwoString = L"http://e.com";
 1231         state.uri = &uriOne;
 1232         ASSERT_TRUE(URI_SUCCESS == uriParseUriW(&state, uriOneString));
 1233         state.uri = &uriTwo;
 1234         ASSERT_TRUE(URI_SUCCESS == uriParseUriW(&state, uriTwoString));
 1235         ASSERT_TRUE(URI_FALSE == uriEqualsUriW(&uriOne, &uriTwo));
 1236         uriFreeUriMembersW(&uriOne);
 1237         uriFreeUriMembersW(&uriTwo);
 1238 
 1239         ASSERT_TRUE(testToStringHelper(uriOneString));
 1240         ASSERT_TRUE(testToStringHelper(uriTwoString));
 1241 }
 1242 
 1243 namespace {
 1244     bool testToStringCharsRequiredHelper(const wchar_t * text) {
 1245         // Parse
 1246         UriParserStateW state;
 1247         UriUriW uri;
 1248         state.uri = &uri;
 1249         int res = uriParseUriW(&state, text);
 1250         if (res != 0) {
 1251             uriFreeUriMembersW(&uri);
 1252             return false;
 1253         }
 1254 
 1255         // Required space?
 1256         int charsRequired;
 1257         if (uriToStringCharsRequiredW(&uri, &charsRequired) != 0) {
 1258             uriFreeUriMembersW(&uri);
 1259             return false;
 1260         }
 1261 
 1262         EXPECT_EQ(charsRequired, wcslen(text));
 1263 
 1264         // Minimum
 1265         wchar_t * buffer = new wchar_t[charsRequired + 1];
 1266         if (uriToStringW(buffer, &uri, charsRequired + 1, NULL) != 0) {
 1267             uriFreeUriMembersW(&uri);
 1268             delete [] buffer;
 1269             return false;
 1270         }
 1271 
 1272         // One less than minimum
 1273         if (uriToStringW(buffer, &uri, charsRequired, NULL) == 0) {
 1274             uriFreeUriMembersW(&uri);
 1275             delete [] buffer;
 1276             return false;
 1277         }
 1278 
 1279         uriFreeUriMembersW(&uri);
 1280         delete [] buffer;
 1281         return true;
 1282     }
 1283 }  // namespace
 1284 
 1285 TEST(UriSuite, TestToStringCharsRequired) {
 1286         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://1.1.1.1/"));
 1287         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://12.1.1.1/"));
 1288         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://123.1.1.1/"));
 1289         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://1.12.1.1/"));
 1290         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://1.123.1.1/"));
 1291         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://1.1.12.1/"));
 1292         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://1.1.123.1/"));
 1293         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://1.1.1.12/"));
 1294         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://1.1.1.123/"));
 1295         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://www.example.com/"));
 1296         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://www.example.com:80/"));
 1297         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://user:pass@www.example.com/"));
 1298         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://www.example.com/index.html"));
 1299         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://www.example.com/?abc"));
 1300         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://www.example.com/#def"));
 1301         EXPECT_TRUE(testToStringCharsRequiredHelper(L"http://www.example.com/?abc#def"));
 1302         EXPECT_TRUE(testToStringCharsRequiredHelper(L"/test"));
 1303         EXPECT_TRUE(testToStringCharsRequiredHelper(L"test"));
 1304 }
 1305 
 1306 namespace {
 1307     bool testNormalizeMaskHelper(const wchar_t * uriText, unsigned int expectedMask) {
 1308         UriParserStateW state;
 1309         UriUriW uri;
 1310         state.uri = &uri;
 1311         int res = uriParseUriW(&state, uriText);
 1312         if (res != 0) {
 1313             uriFreeUriMembersW(&uri);
 1314             return false;
 1315         }
 1316 
 1317         const unsigned int maskBefore = uriNormalizeSyntaxMaskRequiredW(&uri);
 1318         if (maskBefore != expectedMask) {
 1319             uriFreeUriMembersW(&uri);
 1320             return false;
 1321         }
 1322 
 1323         res = uriNormalizeSyntaxW(&uri);
 1324         if (res != 0) {
 1325             uriFreeUriMembersW(&uri);
 1326             return false;
 1327         }
 1328 
 1329         const unsigned int maskAfter = uriNormalizeSyntaxMaskRequiredW(&uri);
 1330         uriFreeUriMembersW(&uri);
 1331 
 1332         // Second call should be no problem
 1333         uriFreeUriMembersW(&uri);
 1334 
 1335         return (maskAfter == URI_NORMALIZED);
 1336     }
 1337 }  // namespace
 1338 
 1339 TEST(UriSuite, TestNormalizeSyntaxMaskRequired) {
 1340         ASSERT_TRUE(testNormalizeMaskHelper(L"http://localhost/", URI_NORMALIZED));
 1341         ASSERT_TRUE(testNormalizeMaskHelper(L"httP://localhost/", URI_NORMALIZE_SCHEME));
 1342         ASSERT_TRUE(testNormalizeMaskHelper(L"http://%0d@localhost/", URI_NORMALIZE_USER_INFO));
 1343         ASSERT_TRUE(testNormalizeMaskHelper(L"http://localhosT/", URI_NORMALIZE_HOST));
 1344         ASSERT_TRUE(testNormalizeMaskHelper(L"http://localhost/./abc", URI_NORMALIZE_PATH));
 1345         ASSERT_TRUE(testNormalizeMaskHelper(L"http://localhost/?AB%43", URI_NORMALIZE_QUERY));
 1346         ASSERT_TRUE(testNormalizeMaskHelper(L"http://localhost/#AB%43", URI_NORMALIZE_FRAGMENT));
 1347 }
 1348 
 1349 namespace {
 1350     bool testNormalizeSyntaxHelper(const wchar_t * uriText, const wchar_t * expectedNormalized,
 1351             unsigned int mask = static_cast<unsigned int>(-1)) {
 1352         UriParserStateW stateW;
 1353         int res;
 1354 
 1355         UriUriW testUri;
 1356         stateW.uri = &testUri;
 1357         res = uriParseUriW(&stateW, uriText);
 1358         if (res != 0) {
 1359             uriFreeUriMembersW(&testUri);
 1360             return false;
 1361         }
 1362 
 1363         // Expected result
 1364         UriUriW expectedUri;
 1365         stateW.uri = &expectedUri;
 1366         res = uriParseUriW(&stateW, expectedNormalized);
 1367         if (res != 0) {
 1368             uriFreeUriMembersW(&testUri);
 1369             uriFreeUriMembersW(&expectedUri);
 1370             return false;
 1371         }
 1372 
 1373         // First run
 1374         res = uriNormalizeSyntaxExW(&testUri, mask);
 1375         if (res != 0) {
 1376             uriFreeUriMembersW(&testUri);
 1377             uriFreeUriMembersW(&expectedUri);
 1378             return false;
 1379         }
 1380 
 1381         bool equalAfter = (URI_TRUE == uriEqualsUriW(&testUri, &expectedUri));
 1382 
 1383         // Second run
 1384         res = uriNormalizeSyntaxExW(&testUri, mask);
 1385         if (res != 0) {
 1386             uriFreeUriMembersW(&testUri);
 1387             uriFreeUriMembersW(&expectedUri);
 1388             return false;
 1389         }
 1390 
 1391         equalAfter = equalAfter
 1392                 && (URI_TRUE == uriEqualsUriW(&testUri, &expectedUri));
 1393 
 1394         uriFreeUriMembersW(&testUri);
 1395         uriFreeUriMembersW(&expectedUri);
 1396         return equalAfter;
 1397     }
 1398 }  // namespace
 1399 
 1400 TEST(UriSuite, TestNormalizeSyntax) {
 1401         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1402                 L"eXAMPLE://a/./b/../b/%63/%7bfoo%7d",
 1403                 L"example://a/b/c/%7Bfoo%7D"));
 1404 
 1405         // Testcase by Adrian Manrique
 1406         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1407                 L"http://examp%4Ce.com/",
 1408                 L"http://example.com/"));
 1409 
 1410         // Testcase by Adrian Manrique
 1411         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1412                 L"http://example.com/a/b/%2E%2E/",
 1413                 L"http://example.com/a/"));
 1414 
 1415         // Reported by Adrian Manrique
 1416         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1417                 L"http://user:pass@SOMEHOST.COM:123",
 1418                 L"http://user:pass@somehost.com:123"));
 1419 
 1420         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1421                 L"HTTP://a:b@HOST:123/./1/2/../%41?abc#def",
 1422                 L"http://a:b@host:123/1/A?abc#def"));
 1423 
 1424         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1425                 L"../../abc",
 1426                 L"../../abc"));
 1427 
 1428         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1429                 L"../../abc/..",
 1430                 L"../../"));
 1431 
 1432         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1433                 L"../../abc/../def",
 1434                 L"../../def"));
 1435 
 1436         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1437                 L"abc/..",
 1438                 L""));
 1439 
 1440         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1441                 L"abc/../",
 1442                 L""));
 1443 
 1444         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1445                 L"../../abc/./def",
 1446                 L"../../abc/def"));
 1447 
 1448         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1449                 L"./def",
 1450                 L"def"));
 1451 
 1452         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1453                 L"def/.",
 1454                 L"def/"));
 1455 
 1456         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1457                 L"./abc:def",
 1458                 L"./abc:def"));
 1459 }
 1460 
 1461 TEST(UriSuite, TestNormalizeSyntaxComponents) {
 1462         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1463                 L"HTTP://%41@EXAMPLE.ORG/../a?%41#%41",
 1464                 L"http://%41@EXAMPLE.ORG/../a?%41#%41",
 1465                 URI_NORMALIZE_SCHEME));
 1466 
 1467         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1468                 L"HTTP://%41@EXAMPLE.ORG/../a?%41#%41",
 1469                 L"HTTP://A@EXAMPLE.ORG/../a?%41#%41",
 1470                 URI_NORMALIZE_USER_INFO));
 1471 
 1472         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1473                 L"HTTP://%41@EXAMPLE.ORG/../a?%41#%41",
 1474                 L"HTTP://%41@example.org/../a?%41#%41",
 1475                 URI_NORMALIZE_HOST));
 1476 
 1477         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1478                 L"HTTP://%41@EXAMPLE.ORG/../a?%41#%41",
 1479                 L"HTTP://%41@EXAMPLE.ORG/a?%41#%41",
 1480                 URI_NORMALIZE_PATH));
 1481 
 1482         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1483                 L"HTTP://%41@EXAMPLE.ORG/../a?%41#%41",
 1484                 L"HTTP://%41@EXAMPLE.ORG/../a?A#%41",
 1485                 URI_NORMALIZE_QUERY));
 1486 
 1487         ASSERT_TRUE(testNormalizeSyntaxHelper(
 1488                 L"HTTP://%41@EXAMPLE.ORG/../a?%41#%41",
 1489                 L"HTTP://%41@EXAMPLE.ORG/../a?%41#A",
 1490                 URI_NORMALIZE_FRAGMENT));
 1491 }
 1492 
 1493 TEST(UriSuite, TestNormalizeSyntaxPath) {
 1494     // These are from GitHub issue #92
 1495     EXPECT_TRUE(testNormalizeSyntaxHelper(
 1496             L"http://a/b/c/../../..",
 1497             L"http://a/",
 1498             URI_NORMALIZE_PATH));
 1499     EXPECT_TRUE(testNormalizeSyntaxHelper(
 1500             L"http://a/b/../c/../..",
 1501             L"http://a/",
 1502             URI_NORMALIZE_PATH));
 1503     EXPECT_TRUE(testNormalizeSyntaxHelper(
 1504             L"http://a/b/c/../../..",
 1505             L"http://a/",
 1506             URI_NORMALIZE_PATH));
 1507 
 1508     // .. and these are related
 1509     EXPECT_TRUE(testNormalizeSyntaxHelper(
 1510             L"http://a/..",
 1511             L"http://a/",
 1512             URI_NORMALIZE_PATH));
 1513     EXPECT_TRUE(testNormalizeSyntaxHelper(
 1514             L"/..",
 1515             L"/",
 1516             URI_NORMALIZE_PATH));
 1517     EXPECT_TRUE(testNormalizeSyntaxHelper(
 1518             L"http://a/..///",
 1519             L"http://a///",
 1520             URI_NORMALIZE_PATH));
 1521     EXPECT_TRUE(testNormalizeSyntaxHelper(
 1522             L"http://a/..///..",
 1523             L"http://a//",
 1524             URI_NORMALIZE_PATH));
 1525     EXPECT_TRUE(testNormalizeSyntaxHelper(
 1526             L"a/b/c/../../..",
 1527             L"",
 1528             URI_NORMALIZE_PATH));
 1529     EXPECT_TRUE(testNormalizeSyntaxHelper(
 1530             L"a/b/../../c/..",
 1531             L"",
 1532             URI_NORMALIZE_PATH));
 1533 }
 1534 
 1535 TEST(UriSuite, TestNormalizeCrashBug20080224) {
 1536         UriParserStateW stateW;
 1537         int res;
 1538         UriUriW testUri;
 1539         stateW.uri = &testUri;
 1540 
 1541         res = uriParseUriW(&stateW, L"http://example.org/abc//../def");
 1542         ASSERT_TRUE(res == 0);
 1543 
 1544         // First call will make us owner of copied memory
 1545         res = uriNormalizeSyntaxExW(&testUri, URI_NORMALIZE_SCHEME);
 1546         ASSERT_TRUE(res == 0);
 1547         res = uriNormalizeSyntaxExW(&testUri, URI_NORMALIZE_HOST);
 1548         ASSERT_TRUE(res == 0);
 1549 
 1550         // Frees empty path segment -> crash
 1551         res = uriNormalizeSyntaxW(&testUri);
 1552         ASSERT_TRUE(res == 0);
 1553 
 1554         uriFreeUriMembersW(&testUri);
 1555 }
 1556 
 1557 namespace {
 1558     void testFilenameUriConversionHelper(const wchar_t * filename,
 1559             const wchar_t * uriString, bool forUnix,
 1560             const wchar_t * expectedUriString = NULL) {
 1561         const int prefixLen = forUnix ? 7 : 8;
 1562         if (! expectedUriString) {
 1563             expectedUriString = uriString;
 1564         }
 1565 
 1566         // Filename to URI string
 1567         const size_t uriBufferLen = prefixLen + 3 * wcslen(filename) + 1;
 1568         wchar_t * uriBuffer = new wchar_t[uriBufferLen];
 1569         if (forUnix) {
 1570             uriUnixFilenameToUriStringW(filename, uriBuffer);
 1571         } else {
 1572             uriWindowsFilenameToUriStringW(filename, uriBuffer);
 1573         }
 1574 #ifdef HAVE_WPRINTF
 1575         // wprintf(L"1 [%s][%s]\n", uriBuffer, expectedUriString);
 1576 #endif
 1577         ASSERT_TRUE(!wcscmp(uriBuffer, expectedUriString));
 1578         delete [] uriBuffer;
 1579 
 1580         // URI string to filename
 1581         const size_t filenameBufferLen = wcslen(uriString) + 1;
 1582         wchar_t * filenameBuffer = new wchar_t[filenameBufferLen];
 1583         if (forUnix) {
 1584             uriUriStringToUnixFilenameW(uriString, filenameBuffer);
 1585         } else {
 1586             uriUriStringToWindowsFilenameW(uriString, filenameBuffer);
 1587         }
 1588 #ifdef HAVE_WPRINTF
 1589         // wprintf(L"2 [%s][%s]\n", filenameBuffer, filename);
 1590 #endif
 1591         ASSERT_TRUE(!wcscmp(filenameBuffer, filename));
 1592         delete [] filenameBuffer;
 1593     }
 1594 }  // namespace
 1595 
 1596 TEST(UriSuite, TestFilenameUriConversion) {
 1597         const bool FOR_UNIX = true;
 1598         const bool FOR_WINDOWS = false;
 1599         testFilenameUriConversionHelper(L"/bin/bash", L"file:///bin/bash", FOR_UNIX);
 1600         testFilenameUriConversionHelper(L"/bin/bash", L"file:/bin/bash", FOR_UNIX, L"file:///bin/bash");
 1601         testFilenameUriConversionHelper(L"./configure", L"./configure", FOR_UNIX);
 1602 
 1603         testFilenameUriConversionHelper(L"E:\\Documents and Settings", L"file:///E:/Documents%20and%20Settings", FOR_WINDOWS);
 1604         testFilenameUriConversionHelper(L"c:\\path\\to\\file.txt", L"file:c:/path/to/file.txt", FOR_WINDOWS, L"file:///c:/path/to/file.txt");
 1605 
 1606         testFilenameUriConversionHelper(L".\\Readme.txt", L"./Readme.txt", FOR_WINDOWS);
 1607 
 1608         testFilenameUriConversionHelper(L"index.htm", L"index.htm", FOR_WINDOWS);
 1609         testFilenameUriConversionHelper(L"index.htm", L"index.htm", FOR_UNIX);
 1610 
 1611         testFilenameUriConversionHelper(L"abc def", L"abc%20def", FOR_WINDOWS);
 1612         testFilenameUriConversionHelper(L"abc def", L"abc%20def", FOR_UNIX);
 1613 
 1614         testFilenameUriConversionHelper(L"\\\\Server01\\user\\docs\\Letter.txt", L"file://Server01/user/docs/Letter.txt", FOR_WINDOWS);
 1615 }
 1616 
 1617 TEST(UriSuite, TestCrashFreeUriMembersBug20080116) {
 1618         // Testcase by Adrian Manrique
 1619         UriParserStateA state;
 1620         UriUriA uri;
 1621         state.uri = &uri;
 1622         uriParseUriA(&state, "http://test/?");
 1623         uriNormalizeSyntaxA(&uri);
 1624         uriFreeUriMembersA(&uri);
 1625 
 1626         ASSERT_TRUE(true);
 1627 }
 1628 
 1629 namespace {
 1630     void helperTestQueryString(char const * uriString, int pairsExpected);
 1631 }
 1632 
 1633 TEST(UriSuite, TestCrashReport2418192) {
 1634         // Testcase by Harvey Vrsalovic
 1635         helperTestQueryString("http://svcs.cnn.com/weather/wrapper.jsp?&csiID=csi1", 1);
 1636 }
 1637 
 1638 TEST(UriSuite, TestPervertedQueryString) {
 1639         helperTestQueryString("http://example.org/?&&=&&&=&&&&==&===&====", 5);
 1640 }
 1641 
 1642 TEST(UriSuite, TestQueryStringEndingInEqualSignNonBug32) {
 1643         const char * queryString = "firstname=sdsd&lastname=";
 1644 
 1645         UriQueryListA * queryList = NULL;
 1646         int itemCount = 0;
 1647         const int res = uriDissectQueryMallocA(&queryList, &itemCount,
 1648                 queryString, queryString + strlen(queryString));
 1649 
 1650         ASSERT_TRUE(res == URI_SUCCESS);
 1651         ASSERT_TRUE(itemCount == 2);
 1652         ASSERT_TRUE(queryList != NULL);
 1653         ASSERT_TRUE(strcmp(queryList->key, "firstname") == 0);
 1654         ASSERT_TRUE(strcmp(queryList->value, "sdsd") == 0);
 1655         ASSERT_TRUE(strcmp(queryList->next->key, "lastname") == 0);
 1656         ASSERT_TRUE(strcmp(queryList->next->value, "") == 0);
 1657         ASSERT_TRUE(queryList->next->next == NULL);
 1658 
 1659         uriFreeQueryListA(queryList);
 1660 }
 1661 
 1662 namespace {
 1663     void helperTestQueryString(char const * uriString, int pairsExpected) {
 1664         UriParserStateA state;
 1665         UriUriA uri;
 1666         state.uri = &uri;
 1667         int res = uriParseUriA(&state, uriString);
 1668         ASSERT_TRUE(res == URI_SUCCESS);
 1669 
 1670         UriQueryListA * queryList = NULL;
 1671         int itemCount = 0;
 1672 
 1673         res = uriDissectQueryMallocA(&queryList, &itemCount,
 1674                 uri.query.first, uri.query.afterLast);
 1675         ASSERT_TRUE(res == URI_SUCCESS);
 1676         ASSERT_TRUE(queryList != NULL);
 1677         ASSERT_TRUE(itemCount == pairsExpected);
 1678         uriFreeQueryListA(queryList);
 1679         uriFreeUriMembersA(&uri);
 1680     }
 1681 }  // namespace
 1682 
 1683 TEST(UriSuite, TestCrashMakeOwnerBug20080207) {
 1684         // Testcase by Adrian Manrique
 1685         UriParserStateA state;
 1686         UriUriA sourceUri;
 1687         state.uri = &sourceUri;
 1688         const char * const sourceUriString = "http://user:pass@somehost.com:80/";
 1689         if (uriParseUriA(&state, sourceUriString) != 0) {
 1690             ASSERT_TRUE(false);
 1691         }
 1692         if (uriNormalizeSyntaxA(&sourceUri) != 0) {
 1693             ASSERT_TRUE(false);
 1694         }
 1695         uriFreeUriMembersA(&sourceUri);
 1696         ASSERT_TRUE(true);
 1697 }
 1698 
 1699 namespace {
 1700     void testQueryListHelper(const wchar_t * input, int expectedItemCount) {
 1701         int res;
 1702 
 1703         UriBool spacePlusConversion = URI_TRUE;
 1704         UriBool normalizeBreaks = URI_FALSE;
 1705         UriBreakConversion breakConversion = URI_BR_DONT_TOUCH;
 1706 
 1707         int itemCount;
 1708         UriQueryListW * queryList;
 1709         res = uriDissectQueryMallocExW(&queryList, &itemCount,
 1710                 input, input + wcslen(input), spacePlusConversion, breakConversion);
 1711         ASSERT_TRUE(res == URI_SUCCESS);
 1712         ASSERT_TRUE(itemCount == expectedItemCount);
 1713         ASSERT_TRUE((queryList == NULL) == (expectedItemCount == 0));
 1714 
 1715         if (expectedItemCount != 0) {
 1716             // First
 1717             int charsRequired;
 1718             res = uriComposeQueryCharsRequiredExW(queryList, &charsRequired, spacePlusConversion,
 1719                     normalizeBreaks);
 1720             ASSERT_TRUE(res == URI_SUCCESS);
 1721             ASSERT_TRUE(charsRequired >= (int)wcslen(input));
 1722 
 1723             wchar_t * recomposed = new wchar_t[charsRequired + 1];
 1724             int charsWritten;
 1725             res = uriComposeQueryExW(recomposed, queryList, charsRequired + 1,
 1726                     &charsWritten, spacePlusConversion, normalizeBreaks);
 1727             ASSERT_TRUE(res == URI_SUCCESS);
 1728             ASSERT_TRUE(charsWritten <= charsRequired);
 1729             ASSERT_TRUE(charsWritten == (int)wcslen(input) + 1);
 1730             ASSERT_TRUE(!wcscmp(input, recomposed));
 1731             delete [] recomposed;
 1732 
 1733             recomposed = NULL;
 1734             res = uriComposeQueryMallocW(&recomposed, queryList);
 1735             ASSERT_TRUE(res == URI_SUCCESS);
 1736             ASSERT_TRUE(recomposed != NULL);
 1737             ASSERT_TRUE(charsWritten == (int)wcslen(input) + 1);
 1738             ASSERT_TRUE(!wcscmp(input, recomposed));
 1739             free(recomposed);
 1740         }
 1741 
 1742         uriFreeQueryListW(queryList);
 1743     }
 1744 }  // namespace
 1745 
 1746 TEST(UriSuite, QueryList) {
 1747         testQueryListHelper(L"one=ONE&two=TWO", 2);
 1748         testQueryListHelper(L"one=ONE&two=&three=THREE", 3);
 1749         testQueryListHelper(L"one=ONE&two&three=THREE", 3);
 1750         testQueryListHelper(L"one=ONE", 1);
 1751         testQueryListHelper(L"one", 1);
 1752         testQueryListHelper(L"", 0);
 1753 }
 1754 
 1755 namespace {
 1756     void testQueryListPairHelper(const char * pair, const char * unescapedKey,
 1757             const char * unescapedValue, const char * fixed = NULL) {
 1758         int res;
 1759         UriQueryListA * queryList;
 1760         int itemCount;
 1761 
 1762         res = uriDissectQueryMallocA(&queryList, &itemCount, pair, pair + strlen(pair));
 1763         ASSERT_TRUE(res == URI_SUCCESS);
 1764         ASSERT_TRUE(queryList != NULL);
 1765         ASSERT_TRUE(itemCount == 1);
 1766         ASSERT_TRUE(!strcmp(queryList->key, unescapedKey));
 1767         ASSERT_TRUE(!strcmp(queryList->value, unescapedValue));
 1768 
 1769         char * recomposed;
 1770         res = uriComposeQueryMallocA(&recomposed, queryList);
 1771         ASSERT_TRUE(res == URI_SUCCESS);
 1772         ASSERT_TRUE(recomposed != NULL);
 1773         ASSERT_TRUE(!strcmp(recomposed, (fixed != NULL) ? fixed : pair));
 1774         free(recomposed);
 1775         uriFreeQueryListA(queryList);
 1776     }
 1777 }  // namespace
 1778 
 1779 TEST(UriSuite, TestQueryListPair) {
 1780         testQueryListPairHelper("one+two+%26+three=%2B", "one two & three", "+");
 1781         testQueryListPairHelper("one=two=three", "one", "two=three", "one=two%3Dthree");
 1782         testQueryListPairHelper("one=two=three=four", "one", "two=three=four", "one=two%3Dthree%3Dfour");
 1783 }
 1784 
 1785 TEST(UriSuite, TestQueryDissectionBug3590761) {
 1786         int res;
 1787         UriQueryListA * queryList;
 1788         int itemCount;
 1789         const char * const pair = "q=hello&x=&y=";
 1790 
 1791         res = uriDissectQueryMallocA(&queryList, &itemCount, pair, pair + strlen(pair));
 1792         ASSERT_TRUE(res == URI_SUCCESS);
 1793         ASSERT_TRUE(queryList != NULL);
 1794         ASSERT_TRUE(itemCount == 3);
 1795 
 1796         ASSERT_TRUE(!strcmp(queryList->key, "q"));
 1797         ASSERT_TRUE(!strcmp(queryList->value, "hello"));
 1798 
 1799         ASSERT_TRUE(!strcmp(queryList->next->key, "x"));
 1800         ASSERT_TRUE(!strcmp(queryList->next->value, ""));
 1801 
 1802         ASSERT_TRUE(!strcmp(queryList->next->next->key, "y"));
 1803         ASSERT_TRUE(!strcmp(queryList->next->next->value, ""));
 1804 
 1805         ASSERT_TRUE(! queryList->next->next->next);
 1806 
 1807         uriFreeQueryListA(queryList);
 1808 }
 1809 
 1810 TEST(UriSuite, TestQueryCompositionMathCalc) {
 1811         UriQueryListA second = { /*.key =*/ "k2", /*.value =*/ "v2", /*.next =*/ NULL };
 1812         UriQueryListA first = { /*.key =*/ "k1", /*.value =*/ "v1", /*.next =*/ &second };
 1813 
 1814         int charsRequired;
 1815         ASSERT_TRUE(uriComposeQueryCharsRequiredA(&first, &charsRequired)
 1816                 == URI_SUCCESS);
 1817 
 1818         const int FACTOR = 6;  /* due to escaping with normalizeBreaks */
 1819         ASSERT_TRUE((unsigned)charsRequired ==
 1820             FACTOR * strlen(first.key) + 1 + FACTOR * strlen(first.value)
 1821             + 1
 1822             + FACTOR * strlen(second.key) + 1 + FACTOR * strlen(second.value)
 1823         );
 1824 }
 1825 
 1826 TEST(UriSuite, TestQueryCompositionMathWriteGoogleAutofuzz113244572) {
 1827         UriQueryListA second = { /*.key =*/ "\x11", /*.value =*/ NULL, /*.next =*/ NULL };
 1828         UriQueryListA first = { /*.key =*/ "\x01", /*.value =*/ "\x02", /*.next =*/ &second };
 1829 
 1830         const UriBool spaceToPlus = URI_TRUE;
 1831         const UriBool normalizeBreaks = URI_FALSE;  /* for factor 3 but 6 */
 1832 
 1833         const int charsRequired = (3 + 1 + 3) + 1 + (3);
 1834 
 1835         {
 1836             // Minimum space to hold everything fine
 1837             const char * const expected = "%01=%02" "&" "%11";
 1838             char dest[charsRequired + 1];
 1839             int charsWritten;
 1840             ASSERT_TRUE(uriComposeQueryExA(dest, &first, sizeof(dest),
 1841                     &charsWritten, spaceToPlus, normalizeBreaks)
 1842                 == URI_SUCCESS);
 1843             ASSERT_TRUE(! strcmp(dest, expected));
 1844             ASSERT_TRUE(charsWritten == strlen(expected) + 1);
 1845         }
 1846 
 1847         {
 1848             // Previous math failed to take ampersand into account
 1849             char dest[charsRequired + 1 - 1];
 1850             int charsWritten;
 1851             ASSERT_TRUE(uriComposeQueryExA(dest, &first, sizeof(dest),
 1852                     &charsWritten, spaceToPlus, normalizeBreaks)
 1853                 == URI_ERROR_OUTPUT_TOO_LARGE);
 1854         }
 1855 }
 1856 
 1857 TEST(UriSuite, TestFreeCrashBug20080827) {
 1858         char const * const sourceUri = "abc";
 1859         char const * const baseUri = "http://www.example.org/";
 1860 
 1861         int res;
 1862         UriParserStateA state;
 1863         UriUriA absoluteDest;
 1864         UriUriA relativeSource;
 1865         UriUriA absoluteBase;
 1866 
 1867         state.uri = &relativeSource;
 1868         res = uriParseUriA(&state, sourceUri);
 1869         ASSERT_TRUE(res == URI_SUCCESS);
 1870 
 1871         state.uri = &absoluteBase;
 1872         res = uriParseUriA(&state, baseUri);
 1873         ASSERT_TRUE(res == URI_SUCCESS);
 1874 
 1875         res = uriRemoveBaseUriA(&absoluteDest, &relativeSource, &absoluteBase, URI_FALSE);
 1876         ASSERT_TRUE(res == URI_ERROR_REMOVEBASE_REL_SOURCE);
 1877 
 1878         uriFreeUriMembersA(&relativeSource);
 1879         uriFreeUriMembersA(&absoluteBase);
 1880         uriFreeUriMembersA(&absoluteDest); // Crashed here
 1881 }
 1882 
 1883 TEST(UriSuite, TestInvalidInputBug16) {
 1884         UriParserStateA stateA;
 1885         UriUriA uriA;
 1886         stateA.uri = &uriA;
 1887         const char * const input = "A>B";
 1888 
 1889         const int res = uriParseUriA(&stateA, input);
 1890 
 1891         ASSERT_TRUE(res == URI_ERROR_SYNTAX);
 1892         ASSERT_TRUE(stateA.errorPos == input + 1);
 1893         ASSERT_TRUE(stateA.errorCode == URI_ERROR_SYNTAX);  /* failed previously */
 1894 
 1895         uriFreeUriMembersA(&uriA);
 1896 }
 1897 
 1898 namespace {
 1899     void testEqualsHelper(const char * uri_to_test) {
 1900         UriParserStateA state;
 1901         UriUriA uriOne;
 1902         UriUriA uriTwo;
 1903         state.uri = &uriOne;
 1904         ASSERT_TRUE(URI_SUCCESS == uriParseUriA(&state, uri_to_test));
 1905         state.uri = &uriTwo;
 1906         ASSERT_TRUE(URI_SUCCESS == uriParseUriA(&state, uri_to_test));
 1907         ASSERT_TRUE(URI_TRUE == uriEqualsUriA(&uriOne, &uriTwo));
 1908         uriFreeUriMembersA(&uriOne);
 1909         uriFreeUriMembersA(&uriTwo);
 1910     }
 1911 }  // namespace
 1912 
 1913 TEST(UriSuite, TestEquals) {
 1914         testEqualsHelper("http://host");
 1915         testEqualsHelper("http://host:123");
 1916         testEqualsHelper("http://foo:bar@host:123");
 1917         testEqualsHelper("http://foo:bar@host:123/");
 1918         testEqualsHelper("http://foo:bar@host:123/path");
 1919         testEqualsHelper("http://foo:bar@host:123/path?query");
 1920         testEqualsHelper("http://foo:bar@host:123/path?query#fragment");
 1921 
 1922         testEqualsHelper("path");
 1923         testEqualsHelper("/path");
 1924         testEqualsHelper("/path/");
 1925         testEqualsHelper("//path/");
 1926         testEqualsHelper("//host");
 1927         testEqualsHelper("//host:123");
 1928 }
 1929 
 1930 TEST(UriSuite, TestHostTextTerminationIssue15) {
 1931         UriParserStateA state;
 1932         UriUriA uri;
 1933         state.uri = &uri;
 1934 
 1935         // Empty host and port
 1936         const char * const emptyHostWithPortUri = "//:123";
 1937         ASSERT_TRUE(URI_SUCCESS == uriParseUriA(&state, emptyHostWithPortUri));
 1938         ASSERT_TRUE(uri.hostText.first == emptyHostWithPortUri + strlen("//"));
 1939         ASSERT_TRUE(uri.hostText.afterLast == uri.hostText.first + 0);
 1940         ASSERT_TRUE(uri.portText.first == emptyHostWithPortUri
 1941                                                             + strlen("//:"));
 1942         ASSERT_TRUE(uri.portText.afterLast == uri.portText.first
 1943                                                             + strlen("123"));
 1944         uriFreeUriMembersA(&uri);
 1945 
 1946         // Non-empty host and port
 1947         const char * const hostWithPortUri = "//h:123";
 1948         ASSERT_TRUE(URI_SUCCESS == uriParseUriA(&state, hostWithPortUri));
 1949         ASSERT_TRUE(uri.hostText.first == hostWithPortUri + strlen("//"));
 1950         ASSERT_TRUE(uri.hostText.afterLast == uri.hostText.first
 1951                                                             + strlen("h"));
 1952         ASSERT_TRUE(uri.portText.first == hostWithPortUri + strlen("//h:"));
 1953         ASSERT_TRUE(uri.portText.afterLast == uri.portText.first
 1954                                                             + strlen("123"));
 1955         uriFreeUriMembersA(&uri);
 1956 
 1957         // Empty host, empty user info
 1958         const char * const emptyHostEmptyUserInfoUri = "//@";
 1959         ASSERT_TRUE(URI_SUCCESS == uriParseUriA(&state,
 1960                                                 emptyHostEmptyUserInfoUri));
 1961         ASSERT_TRUE(uri.userInfo.first == emptyHostEmptyUserInfoUri
 1962                                                             + strlen("//"));
 1963         ASSERT_TRUE(uri.userInfo.afterLast == uri.userInfo.first + 0);
 1964         ASSERT_TRUE(uri.hostText.first == emptyHostEmptyUserInfoUri
 1965                                                             + strlen("//@"));
 1966         ASSERT_TRUE(uri.hostText.afterLast == uri.hostText.first + 0);
 1967         uriFreeUriMembersA(&uri);
 1968 
 1969         // Non-empty host, empty user info
 1970         const char * const hostEmptyUserInfoUri = "//@h";
 1971         ASSERT_TRUE(URI_SUCCESS == uriParseUriA(&state, hostEmptyUserInfoUri));
 1972         ASSERT_TRUE(uri.userInfo.first == hostEmptyUserInfoUri + strlen("//"));
 1973         ASSERT_TRUE(uri.userInfo.afterLast == uri.userInfo.first + 0);
 1974         ASSERT_TRUE(uri.hostText.first == hostEmptyUserInfoUri
 1975                                                             + strlen("//@"));
 1976         ASSERT_TRUE(uri.hostText.afterLast == uri.hostText.first
 1977                                                             + strlen("h"));
 1978         uriFreeUriMembersA(&uri);
 1979 
 1980         // Empty host, non-empty user info
 1981         const char * const emptyHostWithUserInfoUri = "//:@";
 1982         ASSERT_TRUE(URI_SUCCESS == uriParseUriA(&state,
 1983                                                 emptyHostWithUserInfoUri));
 1984         ASSERT_TRUE(uri.userInfo.first == emptyHostWithUserInfoUri
 1985                                                             + strlen("//"));
 1986         ASSERT_TRUE(uri.userInfo.afterLast == uri.userInfo.first + 1);
 1987         ASSERT_TRUE(uri.hostText.first == emptyHostWithUserInfoUri
 1988                                                             + strlen("//:@"));
 1989         ASSERT_TRUE(uri.hostText.afterLast == uri.hostText.first + 0);
 1990         uriFreeUriMembersA(&uri);
 1991 
 1992         // Exact case from issue #15
 1993         const char * const issue15Uri = "//:%aa@";
 1994         ASSERT_TRUE(URI_SUCCESS == uriParseUriA(&state, issue15Uri));
 1995         ASSERT_TRUE(uri.userInfo.first == issue15Uri + strlen("//"));
 1996         ASSERT_TRUE(uri.userInfo.afterLast == uri.userInfo.first
 1997                                                             + strlen(":%aa"));
 1998         ASSERT_TRUE(uri.hostText.first == issue15Uri + strlen("//:%aa@"));
 1999         ASSERT_TRUE(uri.hostText.afterLast == uri.hostText.first + 0);
 2000         uriFreeUriMembersA(&uri);
 2001 }
 2002 
 2003 namespace {
 2004     void testCompareRangeHelper(const char * a, const char * b, int expected, bool avoidNullRange = true) {
 2005         UriTextRangeA ra;
 2006         UriTextRangeA rb;
 2007 
 2008         if (a) {
 2009             ra.first = a;
 2010             ra.afterLast = a + strlen(a);
 2011         } else {
 2012             ra.first = NULL;
 2013             ra.afterLast = NULL;
 2014         }
 2015 
 2016         if (b) {
 2017             rb.first = b;
 2018             rb.afterLast = b + strlen(b);
 2019         } else {
 2020             rb.first = NULL;
 2021             rb.afterLast = NULL;
 2022         }
 2023 
 2024         const int received = uriCompareRangeA(
 2025                 ((a == NULL) && avoidNullRange) ? NULL : &ra,
 2026                 ((b == NULL) && avoidNullRange) ? NULL : &rb);
 2027         if (received != expected) {
 2028             printf("Comparing <%s> to <%s> yields %d, expected %d.\n",
 2029                     a, b, received, expected);
 2030         }
 2031         ASSERT_TRUE(received == expected);
 2032     }
 2033 }  // namespace
 2034 
 2035 TEST(UriSuite, TestRangeComparison) {
 2036         testCompareRangeHelper("", "", 0);
 2037         testCompareRangeHelper("a", "", 1);
 2038         testCompareRangeHelper("", "a", -1);
 2039 
 2040         testCompareRangeHelper("a", "a", 0);
 2041         testCompareRangeHelper("a", "b", -1);
 2042         testCompareRangeHelper("b", "a", 1);
 2043 
 2044         testCompareRangeHelper("a", "aa", -1);
 2045         testCompareRangeHelper("aa", "a", 1);
 2046 
 2047         // Fixed with 0.8.1:
 2048         testCompareRangeHelper(NULL, "a", -1);
 2049         testCompareRangeHelper("a", NULL, 1);
 2050         testCompareRangeHelper(NULL, NULL, 0);
 2051 
 2052         // Fixed with 0.8.3
 2053         const bool KEEP_NULL_RANGE = false;
 2054         const bool AVOID_NULL_RANGE = true;
 2055         testCompareRangeHelper(NULL, "", -1, AVOID_NULL_RANGE);
 2056         testCompareRangeHelper(NULL, "", -1, KEEP_NULL_RANGE);
 2057         testCompareRangeHelper("", NULL, 1, AVOID_NULL_RANGE);
 2058         testCompareRangeHelper("", NULL, 1, KEEP_NULL_RANGE);
 2059 }
 2060 
 2061 namespace {
 2062     void testRemoveBaseUriHelper(const char * expected,
 2063                                 const char * absSourceStr,
 2064                                 const char * absBaseStr) {
 2065         UriParserStateA state;
 2066         UriUriA absSource;
 2067         UriUriA absBase;
 2068         UriUriA dest;
 2069 
 2070         state.uri = &absSource;
 2071         ASSERT_TRUE(uriParseUriA(&state, absSourceStr) == URI_SUCCESS);
 2072 
 2073         state.uri = &absBase;
 2074         ASSERT_TRUE(uriParseUriA(&state, absBaseStr) == URI_SUCCESS);
 2075 
 2076         ASSERT_TRUE(uriRemoveBaseUriA(&dest, &absSource, &absBase, URI_FALSE)
 2077                 == URI_SUCCESS);
 2078 
 2079         int size = 0;
 2080         ASSERT_TRUE(uriToStringCharsRequiredA(&dest, &size) == URI_SUCCESS);
 2081         char * const buffer = (char *)malloc(size + 1);
 2082         ASSERT_TRUE(buffer);
 2083         ASSERT_TRUE(uriToStringA(buffer, &dest, size + 1, &size)
 2084                                                             == URI_SUCCESS);
 2085         if (strcmp(buffer, expected)) {
 2086             printf("Expected \"%s\" but got \"%s\"\n", expected, buffer);
 2087             ASSERT_TRUE(0);
 2088         }
 2089         free(buffer);
 2090 
 2091         uriFreeUriMembersA(&absSource);
 2092         uriFreeUriMembersA(&absBase);
 2093         uriFreeUriMembersA(&dest);
 2094     }
 2095 }  // namespace
 2096 
 2097 TEST(UriSuite, TestRangeComparisonRemoveBaseUriIssue19) {
 2098         // scheme
 2099         testRemoveBaseUriHelper("scheme://host/source",
 2100                                 "scheme://host/source",
 2101                                 "schemelonger://host/base");
 2102         testRemoveBaseUriHelper("schemelonger://host/source",
 2103                                 "schemelonger://host/source",
 2104                                 "scheme://host/base");
 2105 
 2106         // hostText
 2107         testRemoveBaseUriHelper("//host/source",
 2108                                 "http://host/source",
 2109                                 "http://hostlonger/base");
 2110         testRemoveBaseUriHelper("//hostlonger/source",
 2111                                 "http://hostlonger/source",
 2112                                 "http://host/base");
 2113 
 2114         // hostData.ipFuture
 2115         testRemoveBaseUriHelper("//[v7.host]/source",
 2116                                 "http://[v7.host]/source",
 2117                                 "http://[v7.hostlonger]/base");
 2118         testRemoveBaseUriHelper("//[v7.hostlonger]/source",
 2119                                 "http://[v7.hostlonger]/source",
 2120                                 "http://host/base");
 2121 
 2122         // path
 2123         testRemoveBaseUriHelper("path1",
 2124                                 "http://host/path1",
 2125                                 "http://host/path111");
 2126         testRemoveBaseUriHelper("../path1/path2",
 2127                                 "http://host/path1/path2",
 2128                                 "http://host/path111/path222");
 2129         testRemoveBaseUriHelper("path111",
 2130                                 "http://host/path111",
 2131                                 "http://host/path1");
 2132         testRemoveBaseUriHelper("../path111/path222",
 2133                                 "http://host/path111/path222",
 2134                                 "http://host/path1/path2");
 2135 
 2136         // Exact issue #19
 2137         testRemoveBaseUriHelper("//example/x/abc",
 2138                                 "http://example/x/abc",
 2139                                 "http://example2/x/y/z");
 2140 }
 2141 
 2142 TEST(ErrorPosSuite, TestErrorPosIPvFuture) {
 2143     UriUriA uri;
 2144     const char * errorPos;
 2145 
 2146     const char * const uriText = "http://[vA.123456";  // missing "]"
 2147     EXPECT_EQ(uriParseSingleUriA(&uri, uriText, &errorPos),
 2148                 URI_ERROR_SYNTAX);
 2149     EXPECT_EQ(errorPos, uriText + strlen(uriText));
 2150 }
 2151 
 2152 TEST(UriParseSingleSuite, Success) {
 2153     UriUriA uri;
 2154 
 2155     EXPECT_EQ(uriParseSingleUriA(&uri, "file:///home/user/song.mp3", NULL),
 2156             URI_SUCCESS);
 2157 
 2158     uriFreeUriMembersA(&uri);
 2159 }
 2160 
 2161 TEST(UriParseSingleSuite, ErrorSyntaxParseErrorSetsErrorPos) {
 2162     UriUriA uri;
 2163     const char * errorPos;
 2164     const char * const uriString = "abc{}def";
 2165 
 2166     EXPECT_EQ(uriParseSingleUriA(&uri, uriString, &errorPos),
 2167             URI_ERROR_SYNTAX);
 2168     EXPECT_EQ(errorPos, uriString + strlen("abc"));
 2169 
 2170     uriFreeUriMembersA(&uri);
 2171 }
 2172 
 2173 TEST(UriParseSingleSuite, ErrorNullFirstDetected) {
 2174     UriUriA uri;
 2175     const char * errorPos;
 2176 
 2177     EXPECT_EQ(uriParseSingleUriExA(&uri, NULL, "notnull", &errorPos),
 2178             URI_ERROR_NULL);
 2179 }
 2180 
 2181 TEST(UriParseSingleSuite, ErrorNullAfterLastDetected) {
 2182     UriUriA uri;
 2183 
 2184     EXPECT_EQ(uriParseSingleUriExA(&uri, "foo", NULL, NULL), URI_SUCCESS);
 2185 
 2186     uriFreeUriMembersA(&uri);
 2187 }
 2188 
 2189 TEST(UriParseSingleSuite, ErrorNullMemoryManagerDetected) {
 2190     UriUriA uri;
 2191     const char * errorPos;
 2192     const char * const uriString = "somethingwellformed";
 2193 
 2194     EXPECT_EQ(uriParseSingleUriExMmA(&uri,
 2195             uriString,
 2196             uriString + strlen(uriString),
 2197             &errorPos, NULL), URI_SUCCESS);
 2198 
 2199     EXPECT_EQ(uriFreeUriMembersMmA(&uri, NULL), URI_SUCCESS);
 2200 }
 2201 
 2202 TEST(FreeUriMembersSuite, MultiFreeWorksFine) {
 2203     UriUriA uri;
 2204 
 2205     EXPECT_EQ(uriParseSingleUriA(&uri, "file:///home/user/song.mp3", NULL),
 2206             URI_SUCCESS);
 2207 
 2208     UriUriA uriBackup = uri;
 2209     EXPECT_EQ(memcmp(&uriBackup, &uri, sizeof(UriUriA)), 0);
 2210 
 2211     uriFreeUriMembersA(&uri);
 2212 
 2213     // Did some pointers change (to NULL)?
 2214     EXPECT_NE(memcmp(&uriBackup, &uri, sizeof(UriUriA)), 0);
 2215 
 2216     uriFreeUriMembersA(&uri);  // second time
 2217 }
 2218 
 2219 TEST(MakeOwnerSuite, MakeOwner) {
 2220     const char * const uriString = "scheme://user:pass@[v7.X]:55555/path/../path/?query#fragment";
 2221     UriUriA uri;
 2222     char * uriFirst = strdup(uriString);
 2223     const size_t uriLen = strlen(uriFirst);
 2224     char * uriAfterLast = uriFirst + uriLen;
 2225 
 2226     EXPECT_EQ(uriParseSingleUriExA(&uri, uriFirst, uriAfterLast, NULL), URI_SUCCESS);
 2227 
 2228     // After plain parse, all strings should point inside the original URI string
 2229     EXPECT_EQ(uri.owner, URI_FALSE);
 2230     URI_EXPECT_RANGE_BETWEEN(uri.scheme, uriFirst, uriAfterLast);
 2231     URI_EXPECT_RANGE_BETWEEN(uri.userInfo, uriFirst, uriAfterLast);
 2232     URI_EXPECT_RANGE_BETWEEN(uri.hostText, uriFirst, uriAfterLast);
 2233     URI_EXPECT_RANGE_BETWEEN(uri.hostData.ipFuture, uriFirst, uriAfterLast);
 2234     URI_EXPECT_RANGE_BETWEEN(uri.portText, uriFirst, uriAfterLast);
 2235     URI_EXPECT_RANGE_BETWEEN(uri.pathHead->text, uriFirst, uriAfterLast);
 2236     URI_EXPECT_RANGE_BETWEEN(uri.pathHead->next->text, uriFirst, uriAfterLast);
 2237     URI_EXPECT_RANGE_BETWEEN(uri.pathHead->next->next->text, uriFirst, uriAfterLast);
 2238     URI_EXPECT_RANGE_EMPTY(uri.pathHead->next->next->next->text);
 2239     EXPECT_TRUE(uri.pathHead->next->next->next->next == NULL);
 2240     URI_EXPECT_RANGE_BETWEEN(uri.query, uriFirst, uriAfterLast);
 2241     URI_EXPECT_RANGE_BETWEEN(uri.fragment, uriFirst, uriAfterLast);
 2242 
 2243     EXPECT_EQ(uriMakeOwnerA(&uri), URI_SUCCESS);
 2244 
 2245     // After making owner, *none* of the strings should point inside the original URI string
 2246     EXPECT_EQ(uri.owner, URI_TRUE);
 2247     URI_EXPECT_RANGE_OUTSIDE(uri.scheme, uriFirst, uriAfterLast);
 2248     URI_EXPECT_RANGE_OUTSIDE(uri.userInfo, uriFirst, uriAfterLast);
 2249     URI_EXPECT_RANGE_OUTSIDE(uri.hostText, uriFirst, uriAfterLast);
 2250     URI_EXPECT_RANGE_OUTSIDE(uri.hostData.ipFuture, uriFirst, uriAfterLast);
 2251     URI_EXPECT_RANGE_OUTSIDE(uri.portText, uriFirst, uriAfterLast);
 2252     URI_EXPECT_RANGE_OUTSIDE(uri.pathHead->text, uriFirst, uriAfterLast);
 2253     URI_EXPECT_RANGE_OUTSIDE(uri.pathHead->next->text, uriFirst, uriAfterLast);
 2254     URI_EXPECT_RANGE_OUTSIDE(uri.pathHead->next->next->text, uriFirst, uriAfterLast);
 2255     URI_EXPECT_RANGE_EMPTY(uri.pathHead->next->next->next->text);
 2256     EXPECT_TRUE(uri.pathHead->next->next->next->next == NULL);
 2257     URI_EXPECT_RANGE_OUTSIDE(uri.query, uriFirst, uriAfterLast);
 2258     URI_EXPECT_RANGE_OUTSIDE(uri.fragment, uriFirst, uriAfterLast);
 2259 
 2260     // Free originally used memory so we'd get violations on access with ASan
 2261     uriAfterLast = NULL;
 2262     free(uriFirst);
 2263     uriFirst = NULL;
 2264 
 2265     // Can we recompose the URI without accessing any old freed memory?
 2266     int charsRequired;
 2267     EXPECT_EQ(uriToStringCharsRequiredA(&uri, &charsRequired), URI_SUCCESS);
 2268     EXPECT_TRUE((charsRequired >= 0) && (charsRequired >= static_cast<int>(uriLen)));
 2269     char * const uriRemake = new char[charsRequired + 1];
 2270     EXPECT_TRUE(uriRemake != NULL);
 2271     EXPECT_EQ(uriToStringA(uriRemake, &uri, charsRequired + 1, NULL), URI_SUCCESS);
 2272     EXPECT_TRUE(! strcmp(uriString, uriRemake));
 2273     delete [] uriRemake;
 2274 
 2275     uriFreeUriMembersA(&uri);
 2276 }
 2277 
 2278 TEST(ParseIpFourAddressSuite, FourSaneOctets) {
 2279     unsigned char octetOutput[4];
 2280     const char * const ipAddressText = "111.22.3.40";
 2281     const int res = uriParseIpFourAddressA(octetOutput, ipAddressText,
 2282             ipAddressText + strlen(ipAddressText));
 2283     EXPECT_EQ(res, URI_SUCCESS);
 2284     EXPECT_EQ(octetOutput[0], 111);
 2285     EXPECT_EQ(octetOutput[1], 22);
 2286     EXPECT_EQ(octetOutput[2], 3);
 2287     EXPECT_EQ(octetOutput[3], 40);
 2288 }
 2289 
 2290 
 2291 int main(int argc, char ** argv) {
 2292     ::testing::InitGoogleTest(&argc, argv);
 2293     return RUN_ALL_TESTS();
 2294 }