1 /* 2 * Copyright 2014, Haiku, inc. 3 * Distributed under the terms of the MIT licence 4 */ 5 6 7 #include "CookieTest.h" 8 9 10 #include <cstdlib> 11 #include <cstring> 12 #include <cstdio> 13 14 #include <NetworkKit.h> 15 16 #include <cppunit/TestCaller.h> 17 #include <cppunit/TestSuite.h> 18 19 20 CookieTest::CookieTest() 21 { 22 } 23 24 25 CookieTest::~CookieTest() 26 { 27 } 28 29 30 // #pragma mark - Positive functionality tests 31 32 33 void 34 CookieTest::SimpleTest() 35 { 36 BNetworkCookieJar jar; 37 char buffer[256]; 38 BUrl url("http://www.chipchapin.com/WebTools/cookietest.php"); 39 40 time_t t = time(NULL) + 6400; // Cookies expire in 1h45 41 struct tm* now = gmtime(&t); 42 status_t result; 43 44 // Add various cookies 45 result = jar.AddCookie("testcookie1=present;", url); 46 CPPUNIT_ASSERT(result == B_OK); 47 48 strftime(buffer, sizeof(buffer), 49 "testcookie2=present; expires=%A, %d-%b-%Y %H:%M:%S", now); 50 result = jar.AddCookie(buffer, url); 51 CPPUNIT_ASSERT(result == B_OK); 52 53 strftime(buffer, sizeof(buffer), 54 "testcookie3=present; expires=%A, %d-%b-%Y %H:%M:%S; path=/", now); 55 result = jar.AddCookie(buffer, url); 56 CPPUNIT_ASSERT(result == B_OK); 57 58 t += 3200; // expire in 2h40 59 now = gmtime(&t); 60 strftime(buffer, sizeof(buffer), 61 "testcookie4=present; path=/; domain=www.chipchapin.com; " 62 "expires=%A, %d-%b-%Y %H:%M:%S", now); 63 result = jar.AddCookie(buffer, url); 64 CPPUNIT_ASSERT(result == B_OK); 65 66 // Now check they were all properly added 67 BNetworkCookieJar::Iterator it = jar.GetIterator(); 68 69 int count = 0; 70 while (it.HasNext()) { 71 count ++; 72 it.Next(); 73 } 74 75 CPPUNIT_ASSERT_EQUAL(4, count); 76 } 77 78 79 void 80 CookieTest::StandardTest() 81 { 82 BNetworkCookieJar jar; 83 status_t result; 84 85 BUrl url("http://testsuites.opera.com/cookies/001.php"); 86 result = jar.AddCookie("001=1", url); 87 CPPUNIT_ASSERT(result == B_OK); 88 89 url.SetUrlString("http://testsuites.opera.com/cookies/001-1.php"); 90 const BNetworkCookie* cookie = _GetCookie(jar, url, "001"); 91 92 CPPUNIT_ASSERT(cookie != NULL); 93 94 CPPUNIT_ASSERT(cookie->HasValue()); 95 CPPUNIT_ASSERT_EQUAL(BString("1"), cookie->Value()); 96 CPPUNIT_ASSERT(cookie->IsSessionCookie()); 97 CPPUNIT_ASSERT(cookie->ShouldDeleteAtExit()); 98 99 CPPUNIT_ASSERT(!cookie->HasExpirationDate()); 100 CPPUNIT_ASSERT(!cookie->Secure()); 101 CPPUNIT_ASSERT(!cookie->HttpOnly()); 102 } 103 104 105 void 106 CookieTest::ExpireTest() 107 { 108 BNetworkCookieJar jar; 109 status_t result; 110 111 BUrl url("http://testsuites.opera.com/cookies/003.php"); 112 result = jar.AddCookie("003=1", url); 113 CPPUNIT_ASSERT(result == B_OK); 114 115 url.SetUrlString("http://testsuites.opera.com/cookies/003-1.php"); 116 result = jar.AddCookie("003=1; expires=Thu, 01-Jan-1970 00:00:10 GMT", url); 117 CPPUNIT_ASSERT(result == B_OK); 118 119 url.SetUrlString("http://testsuites.opera.com/cookies/003-2.php"); 120 // The cookie should be expired. 121 CPPUNIT_ASSERT(_GetCookie(jar, url, "003") == NULL); 122 } 123 124 125 void 126 CookieTest::PathTest() 127 { 128 BNetworkCookieJar jar; 129 status_t result; 130 131 BUrl url("http://testsuites.opera.com/cookies/004/004.php"); 132 result = jar.AddCookie("004=1", url); 133 CPPUNIT_ASSERT(result == B_OK); 134 135 // Page in the same path can access the cookie 136 url.SetUrlString("http://testsuites.opera.com/cookies/004/004-1.php"); 137 CPPUNIT_ASSERT(_GetCookie(jar, url, "004") != NULL); 138 139 // Page in parent directory cannot access the cookie 140 url.SetUrlString("http://testsuites.opera.com/cookies/004-2.php"); 141 CPPUNIT_ASSERT(_GetCookie(jar, url, "004") == NULL); 142 } 143 144 145 void 146 CookieTest::MaxSizeTest() 147 { 148 BNetworkCookieJar jar; 149 status_t result; 150 151 BUrl url("http://testsuites.opera.com/cookies/006.php"); 152 BString cookieString("006="); 153 for (int i = 0; i < 128; i++) { 154 cookieString << "00xxxxxxxxxxxxxx16xxxxxxxxxxxxxx"; 155 } 156 result = jar.AddCookie(cookieString, url); 157 CPPUNIT_ASSERT(result == B_OK); 158 159 url.SetUrlString("http://testsuites.opera.com/cookies/006-1.php"); 160 const BNetworkCookie* cookie = _GetCookie(jar, url, "006"); 161 CPPUNIT_ASSERT(cookie != NULL); 162 CPPUNIT_ASSERT(cookie->Value().Length() == 4096); 163 } 164 165 166 void 167 CookieTest::MaxNumberTest() 168 { 169 BNetworkCookieJar jar; 170 status_t result; 171 172 BUrl url("http://testsuites.opera.com/cookies/007.php"); 173 BString cookieString; 174 175 for (int i = 1; i <= 20; i++) 176 { 177 cookieString.SetToFormat("007-%d=1", i); 178 result = jar.AddCookie(cookieString, url); 179 CPPUNIT_ASSERT(result == B_OK); 180 } 181 182 url.SetUrlString("http://testsuites.opera.com/cookies/007-1.php"); 183 for (int i = 1; i <= 20; i++) 184 { 185 cookieString.SetToFormat("007-%d", i); 186 const BNetworkCookie* cookie = _GetCookie(jar, url, cookieString.String()); 187 CPPUNIT_ASSERT(cookie != NULL); 188 CPPUNIT_ASSERT(cookie->Value() == "1"); 189 } 190 } 191 192 193 void 194 CookieTest::UpdateTest() 195 { 196 BNetworkCookieJar jar; 197 status_t result; 198 199 BUrl url("http://testsuites.opera.com/cookies/008.php"); 200 result = jar.AddCookie("008=1", url); 201 CPPUNIT_ASSERT(result == B_OK); 202 203 url.SetUrlString("http://testsuites.opera.com/cookies/008-1.php"); 204 result = jar.AddCookie("008=2", url); 205 CPPUNIT_ASSERT(result == B_OK); 206 207 url.SetUrlString("http://testsuites.opera.com/cookies/008-2.php"); 208 const BNetworkCookie* cookie = _GetCookie(jar, url, "008"); 209 CPPUNIT_ASSERT(cookie != NULL); 210 CPPUNIT_ASSERT(cookie->Value() == "2"); 211 } 212 213 214 void 215 CookieTest::HttpOnlyTest() 216 { 217 BNetworkCookieJar jar; 218 status_t result; 219 220 BUrl url("http://testsuites.opera.com/cookies/010.php"); 221 result = jar.AddCookie("010=1; Httponly; Max-age=1", url); 222 CPPUNIT_ASSERT(result == B_OK); 223 224 url.SetUrlString("http://testsuites.opera.com/cookies/010-1.php"); 225 const BNetworkCookie* cookie = _GetCookie(jar, url, "010"); 226 CPPUNIT_ASSERT(cookie != NULL); 227 CPPUNIT_ASSERT(cookie->Value() == "1"); 228 CPPUNIT_ASSERT(cookie->HttpOnly()); 229 CPPUNIT_ASSERT(cookie->HasExpirationDate()); 230 } 231 232 233 void 234 CookieTest::EncodingTest() 235 { 236 BNetworkCookieJar jar; 237 status_t result; 238 239 BUrl url("http://testsuites.opera.com/cookies/011.php"); 240 result = jar.AddCookie("011=UTF-8 \303\246\303\270\303\245 \346\227\245\346\234\254;", url); 241 CPPUNIT_ASSERT(result == B_OK); 242 243 url.SetUrlString("http://testsuites.opera.com/cookies/011-1.php"); 244 const BNetworkCookie* cookie = _GetCookie(jar, url, "011"); 245 CPPUNIT_ASSERT(cookie != NULL); 246 CPPUNIT_ASSERT_EQUAL( 247 BString("UTF-8 \303\246\303\270\303\245 \346\227\245\346\234\254"), 248 cookie->Value()); 249 } 250 251 252 void 253 CookieTest::DomainTest() 254 { 255 BNetworkCookieJar jar; 256 status_t result; 257 258 BUrl url("http://testsuites.opera.com/cookies/012.php"); 259 result = jar.AddCookie("012-1=1; Domain=\"opera.com\"", url); 260 CPPUNIT_ASSERT(result == B_OK); 261 result = jar.AddCookie("012-1=1; Domain=\"example.com\"", url); 262 CPPUNIT_ASSERT(result != B_OK); 263 264 url.SetUrlString("http://testsuites.opera.com/cookies/012-1.php"); 265 const BNetworkCookie* cookie = _GetCookie(jar, url, "012-1"); 266 CPPUNIT_ASSERT(cookie != NULL); 267 CPPUNIT_ASSERT(cookie->Value() == "1"); 268 269 cookie = _GetCookie(jar, url, "012-2"); 270 CPPUNIT_ASSERT(cookie == NULL); 271 } 272 273 274 void 275 CookieTest::PersistantTest() 276 { 277 BNetworkCookieJar jar; 278 status_t result; 279 char buffer[256]; 280 281 time_t t = time(NULL) + 100000; 282 struct tm* now = gmtime(&t); 283 284 NextSubTest(); 285 286 BUrl url("http://testsuites.opera.com/cookies/013.php"); 287 288 strftime(buffer, sizeof(buffer), 289 "013-1=1; Expires=%a, %d-%b-%Y %H:%M:%S", now); 290 result = jar.AddCookie(buffer, url); 291 CPPUNIT_ASSERT(result == B_OK); 292 293 result = jar.AddCookie("013-2=1", url); 294 CPPUNIT_ASSERT(result == B_OK); 295 296 NextSubTest(); 297 298 url.SetUrlString("http://testsuites.opera.com/cookies/013-1.php"); 299 300 const BNetworkCookie* cookie = _GetCookie(jar, url, "013-1"); 301 CPPUNIT_ASSERT(cookie != NULL); 302 CPPUNIT_ASSERT(cookie->Value() == "1"); 303 CPPUNIT_ASSERT(cookie->HasExpirationDate()); 304 305 cookie = _GetCookie(jar, url, "013-2"); 306 CPPUNIT_ASSERT(cookie != NULL); 307 CPPUNIT_ASSERT(cookie->Value() == "1"); 308 CPPUNIT_ASSERT(!cookie->HasExpirationDate()); 309 310 // Simulate exit 311 jar.PurgeForExit(); 312 313 NextSubTest(); 314 315 cookie = _GetCookie(jar, url, "013-1"); 316 CPPUNIT_ASSERT(cookie != NULL); 317 CPPUNIT_ASSERT(cookie->Value() == "1"); 318 CPPUNIT_ASSERT(cookie->HasExpirationDate()); 319 320 cookie = _GetCookie(jar, url, "013-2"); 321 CPPUNIT_ASSERT(cookie == NULL); 322 } 323 324 325 void 326 CookieTest::OverwriteTest() 327 { 328 BNetworkCookieJar jar; 329 status_t result; 330 331 BUrl url("http://testsuites.opera.com/cookies/015/015.php"); 332 result = jar.AddCookie("015-01=1", url); 333 CPPUNIT_ASSERT(result == B_OK); 334 335 url.SetUrlString("http://testsuites.opera.com/cookies/015-1.php"); 336 result = jar.AddCookie("015-01=1", url); 337 result = jar.AddCookie("015-02=1", url); 338 CPPUNIT_ASSERT(result == B_OK); 339 340 url.SetUrlString("http://testsuites.opera.com/cookies/015/015-2.php"); 341 result = jar.AddCookie("015-01=1", url); 342 result = jar.AddCookie("015-02=1", url); 343 CPPUNIT_ASSERT(result == B_OK); 344 345 url.SetUrlString("http://testsuites.opera.com/cookies/015/015-3.php"); 346 BNetworkCookieJar::UrlIterator it = jar.GetUrlIterator(url); 347 int count = 0; 348 349 while (it.HasNext()) { 350 it.Next(); 351 count++; 352 } 353 354 CPPUNIT_ASSERT_EQUAL(4, count); 355 } 356 357 358 void 359 CookieTest::OrderTest() 360 { 361 BNetworkCookieJar jar; 362 status_t result; 363 364 BUrl url("http://testsuites.opera.com/cookies/016.php"); 365 result = jar.AddCookie("016-01=1", url); 366 CPPUNIT_ASSERT(result == B_OK); 367 368 url.SetUrlString("http://testsuites.opera.com/cookies/016/016-1.php"); 369 result = jar.AddCookie("016-02=1", url); 370 CPPUNIT_ASSERT(result == B_OK); 371 372 url.SetUrlString("http://testsuites.opera.com/cookies/016/016-2.php"); 373 BNetworkCookieJar::UrlIterator it = jar.GetUrlIterator(url); 374 int count = 0; 375 376 // Check that the cookie with the most specific path is sent first 377 while (it.HasNext()) { 378 const BNetworkCookie* cookie = it.Next(); 379 switch(count) 380 { 381 case 0: 382 CPPUNIT_ASSERT_EQUAL(BString("016-02"), cookie->Name()); 383 break; 384 case 1: 385 CPPUNIT_ASSERT_EQUAL(BString("016-01"), cookie->Name()); 386 break; 387 } 388 count++; 389 } 390 391 CPPUNIT_ASSERT_EQUAL(2, count); 392 } 393 394 395 // #pragma mark - Error handling and extended tests 396 397 398 void 399 CookieTest::ExpireParsingTest() 400 { 401 BUrl url("http://testsuites.opera.com/cookies/301.php"); 402 BNetworkCookie cookie; 403 status_t result; 404 405 BString bigData("301-16=1; Expires=\""); 406 for (int i = 0; i < 1500; i++) 407 bigData << "abcdefghijklmnopqrstuvwxyz"; 408 bigData << "\";"; 409 410 struct Test { 411 const char* cookieString; 412 bool canParse; 413 bool sessionOnly; 414 bool expired; 415 }; 416 417 Test tests[] = { 418 { "301-01=1; Expires=\"notAValidValue\";", 419 true, true, false }, // Obviously invalid date 420 { "301-02=1; Expires=\"Wed, 08-Nov-2035 01:04:33\";", 421 true, false, false }, // Valid date 422 { "301-03=1; Expires=\"Tue, 19-Jan-2038 03:14:06\";", 423 true, false, false }, // Valid date, after year 2038 time_t overflow 424 { "301-04=1; Expires=\"Fri, 13-Dec-1901 20:45:51\";", 425 true, false, true }, // Valid date, in the past 426 { "301-05=1; Expires=\"Thu, 33-Nov-2035 01:04:33\";", 427 true, true, false }, // Invalid day 428 { "301-06=1; Expires=\"Wed, 08-Siz-2035 01:04:33\";", 429 true, true, false }, // Invalid month 430 { "301-07=1; Expires=\"Wed, 08-Nov-9035 01:04:33\";", 431 true, false, false }, // Very far in the future 432 // NOTE: Opera testsuite considers it should be a session cookie. 433 { "301-08=1; Expires=\"Wed, 08-Nov-2035 75:04:33\";", 434 true, true, false }, // Invalid hour 435 { "301-09=1; Expires=\"Wed, 08-Nov-2035 01:75:33\";", 436 true, true, false }, // Invalid minute 437 { "301-10=1; Expires=\"Wed, 08-Nov-2035 01:04:75\";", 438 true, true, false }, // Invalid second 439 { "301-11=1; Expires=\"XXX, 08-Nov-2035 01:04:33\";", 440 true, true, false }, // Invalid weekday 441 { "301-12=1; Expires=\"Thu, XX-Nov-2035 01:04:33\";", 442 true, true, false }, // Non-digit day 443 { "301-13=1; Expires=\"Thu, 08-Nov-XXXX 01:04:33\";", 444 true, true, false }, // Non-digit year 445 { "301-14=1; Expires=\"Thu, 08-Nov-2035 XX:XX:33\";", 446 true, true, false }, // Non-digit hour and minute 447 { "301-15=1; Expires=\"Thu, 08-Nov-2035 01:04:XX\";", 448 true, true, false }, // Non-digit second 449 { bigData.String(), 450 true, true, false }, // Very long invalid string 451 // NOTE: Opera doesn't register the cookie at all. 452 { "301-17=1; Expires=\"Thu, 99999-Nov-2035 01:04:33\";", 453 true, true, false }, // Day with many digits 454 { "301-18=1; Expires=\"Thu, 25-Nov-99999 01:04:33\";", 455 true, true, false }, // Year with many digits 456 // NOTE: Opera tests 301-17 twice and misses this test. 457 { "301-19=1; Expires=\"Thu, 25-Nov-2035 99999:04:33\";", 458 true, true, false }, // Hour with many digits 459 { "301-20=1; Expires=\"Thu, 25-Nov-2035 01:99999:33\";", 460 true, true, false }, // Minute with many digits 461 { "301-21=1; Expires=\"Thu, 25-Nov-2035 01:04:99999\";", 462 true, true, false }, // Second with many digits 463 { "301-22=1; Expires=\"99999999999999999999\";", 464 true, true, false }, // Huge number 465 { "301-23=1; Expires=\"Fri, 13-Dec-101 20:45:51\";", 466 true, false, true }, // Very far in the past 467 { "301-24=1; EXPiReS=\"Wed, 08-Nov-2035 01:04:33\";", 468 true, false, false }, // Case insensitive key parsing 469 { "301-25=1; Expires=Wed, 08-Nov-2035 01:04:33\";", 470 true, true, false }, // Missing opening quote 471 // NOTE: unlike Opera, we accept badly quoted values for cookie 472 // attributes. This allows to handle unquoted values from the early 473 // cookie spec properly. However, a date with a quote inside it 474 // should not be accepted, so this will be a session cookie. 475 { "301-26=1; Expires=\"Wed, 08-Nov-2035 01:04:33;", 476 true, true, false }, // Missing closing quote 477 { "301-27=1; Expires:\"Wed, 08-Nov-2035 01:04:33\";", 478 true, true, false }, // Uses : instead of = 479 // NOTE: unlike Opera, we allow this as a cookie with a strange 480 // name and no value 481 { "301-28=1; Expires;=\"Wed, 08-Nov-2035 01:04:33\";", 482 true, true, false }, // Extra ; after name 483 { "301-29=1; Expired=\"Wed, 08-Nov-2035 01:04:33\";", 484 true, true, false }, // Expired instead of Expires 485 { "301-30=1; Expires=\"Wed; 08-Nov-2035 01:04:33\";", 486 true, true, false }, // ; in value 487 { "301-31=1; Expires=\"Wed,\\r\\n 08-Nov-2035 01:04:33\";", 488 true, true, false }, // escaped newline in value 489 // NOTE: Only here for completeness. This is what the Opera 490 // testsuite sends in test 31, but I suspect they were trying to 491 // test the following case. 492 { "301-31b=1; Expires=\"Wed,\r\n 08-Nov-2035 01:04:33\";", 493 true, false, false }, // newline in value 494 // NOTE: This can't really happen when we get cookies from HTTP 495 // headers. It could happen when the cookie is set from meta html 496 // tags or from JS. 497 { "301-32=1; expires=Mon, 31-Oct-2035 08:08:40 GMT;", 498 true, false, false }, // Wrong weekday 499 { "301-33=1; expires=Tue, 19-Oct-66 07:08:40;", 500 true, false, false }, // RFC1036 format with 2 digit year 501 { "301-34=1; expires=Sat, 21-Oct-56 07:08:40 GMT;", 502 true, false, false }, // RFC1036 format with 2 digit year 503 }; 504 505 for (unsigned int i = 0; i < sizeof(tests) / sizeof(Test); i++) 506 { 507 NextSubTest(); 508 509 result = cookie.ParseCookieString(tests[i].cookieString, url); 510 CPPUNIT_ASSERT_EQUAL_MESSAGE("Cookie can be parsed", 511 tests[i].canParse, result == B_OK); 512 CPPUNIT_ASSERT_EQUAL_MESSAGE("Cookie is session only", 513 tests[i].sessionOnly, cookie.IsSessionCookie()); 514 CPPUNIT_ASSERT_EQUAL_MESSAGE("Cookie has expired", 515 tests[i].expired, cookie.ShouldDeleteNow()); 516 } 517 } 518 519 520 void 521 CookieTest::PathMatchingTest() 522 { 523 const BUrl url("http://testsuites.opera.com/cookies/302/302.php"); 524 const BUrl url1("http://testsuites.opera.com/cookies/302-5.php"); 525 const BUrl url2("http://testsuites.opera.com/cookies/302/302-3.php"); 526 const BUrl url3("http://testsuites.opera.com/cookies/302/sub/302-4.php"); 527 const BUrl url4("http://testsuites.opera.com/cookies/302-2/302-6.php"); 528 BNetworkCookie cookie; 529 status_t result; 530 531 BString bigData("302-24=1; Path=\"/cookies/302/"); 532 for (int i = 0; i < 1500; i++) 533 bigData << "abcdefghijklmnopqrstuvwxyz"; 534 bigData << "\";"; 535 536 struct Test { 537 const char* cookieString; 538 bool canSet; 539 bool url1; 540 bool url2; 541 bool url3; 542 bool url4; 543 }; 544 545 const Test tests[] = { 546 { "302-01=1; Path=\"/\"", 547 true, true, true, true, true }, 548 { "302-02=1; Path=\"/cookies\"", 549 true, true, true, true, true }, 550 { "302-03=1; Path=\"/cookies/\"", 551 true, true, true, true, true }, 552 { "302-04=1; Path=\"/cookies/302\"", 553 true, false, true, true, true }, 554 { "302-05=1; Path=\"/cookies/302/\"", 555 true, false, true, true, false }, 556 { "302-06=1; Path=\"/cookies/302/.\"", 557 false, false, false, false, false }, 558 { "302-07=1; Path=\"/cookies/302/../302\"", 559 false, false, false, false, false }, 560 { "302-08=1; Path=\"/cookies/302/../302-2\"", 561 false, false, false, false, false }, 562 { "302-09=1; Path=\"/side\"", 563 false, false, false, false, false }, 564 { "302-10=1; Path=\"/cookies/302-2\"", 565 true, false, false, false, true }, 566 { "302-11=1; Path=\"/cookies/302-2/\"", 567 true, false, false, false, true }, 568 { "302-12=1; Path=\"sub\"", 569 false, false, false, false, false }, 570 { "302-13=1; Path=\"sub/\"", 571 false, false, false, false, false }, 572 { "302-14=1; Path=\".\"", 573 false, false, false, false, false }, 574 { "302-15=1; Path=\"/cookies/302/sub\"", 575 true, false, false, true, false }, 576 { "302-16=1; Path=\"/cookies/302/sub/\"", 577 true, false, false, true, false }, 578 { "302-17=1; Path=\"/cookies/302/sub/..\"", 579 false, false, false, false, false }, 580 { "302-18=1; Path=/", 581 true, true, true, true, true }, 582 { "302-19=1; Path=/ /", 583 false, false, false, false, false }, 584 { "302-20=1; Path=\"/", 585 false, false, false, false, false }, 586 { "302-21=1; Path=/\"", 587 false, false, false, false, false }, 588 { "302-22=1; Path=\\/", 589 false, false, false, false, false }, 590 { "302-23=1; Path=\n/", 591 false, false, false, false, false }, 592 { bigData, 593 false, false, false, false, false }, 594 }; 595 596 for (unsigned int i = 0; i < sizeof(tests) / sizeof(Test); i++) 597 { 598 NextSubTest(); 599 600 result = cookie.ParseCookieString(tests[i].cookieString, url); 601 602 CPPUNIT_ASSERT_EQUAL_MESSAGE("Allowed to set cookie", 603 tests[i].canSet, result == B_OK); 604 CPPUNIT_ASSERT_EQUAL(tests[i].url1, cookie.IsValidForUrl(url1)); 605 CPPUNIT_ASSERT_EQUAL(tests[i].url2, cookie.IsValidForUrl(url2)); 606 CPPUNIT_ASSERT_EQUAL(tests[i].url3, cookie.IsValidForUrl(url3)); 607 CPPUNIT_ASSERT_EQUAL(tests[i].url4, cookie.IsValidForUrl(url4)); 608 } 609 } 610 611 612 void 613 CookieTest::DomainMatchingTest() 614 { 615 const BUrl setter("http://testsuites.opera.com/cookies/304.php"); 616 const BUrl getter("http://testsuites.opera.com/cookies/304-1.php"); 617 618 BString bigData("304-12=1; Domain=\""); 619 for (int i = 0; i < 1500; i++) 620 bigData << "abcdefghijklmnopqrstuvwxyz"; 621 bigData << "\";"; 622 623 struct Test { 624 const char* cookieString; 625 bool shouldMatch; 626 }; 627 628 const Test tests[] = { 629 { "304-01=1; Domain=\"opera.com\"", true }, 630 { "304-02=1; Domain=\".opera.com\"", true }, 631 { "304-03=1; Domain=\".com\"", false }, 632 { "304-04=1; Domain=\"pera.com\"", false }, 633 { "304-05=1; Domain=\"?pera.com\"", false }, 634 { "304-06=1; Domain=\"*.opera.com\"", false }, 635 { "304-07=1; Domain=\"300.300.300.300\"", false }, 636 { "304-08=1; Domain=\"123456123456123456\"", false }, 637 { "304-09=1; Domain=\"/opera.com\"", false }, 638 { "304-10=1; Domain=\"opera.com/\"", false }, 639 { "304-11=1; Domain=\"example.com\"", false }, 640 { bigData, false }, 641 { "304-13=1; Domain=\"opera com\"", false }, 642 { "304-14=1; Domain=opera.com\"", false }, 643 { "304-15=1; Domain=\"opera.com", false }, 644 { "304-16=1; Domain=opera.com", true }, 645 { "304-17=1; Domain=\"*.com\"", false }, 646 { "304-18=1; Domain=\"*opera.com\"", false }, 647 { "304-19=1; Domain=\"*pera.com\"", false }, 648 { "304-20=1; Domain=\"\"", false }, 649 { "304-21=1; Domain=\"\346\227\245\346\234\254\"", false }, 650 { "304-22=1; Domain=\"OPERA.COM\"", true }, 651 { "304-23=1; Domain=\"195.189.143.182\"", false }, 652 }; 653 654 for (unsigned int i = 0; i < sizeof(tests) / sizeof(Test); i++) 655 { 656 NextSubTest(); 657 658 BNetworkCookie cookie(tests[i].cookieString, setter); 659 CPPUNIT_ASSERT_EQUAL(tests[i].shouldMatch, 660 cookie.IsValidForUrl(getter)); 661 } 662 } 663 664 665 void 666 CookieTest::MaxAgeParsingTest() 667 { 668 const BUrl setter("http://testsuites.opera.com/cookies/305.php"); 669 670 BString bigData("305-12=1; Max-Age=\""); 671 for (int i = 0; i < 1500; i++) 672 bigData << "abcdefghijklmnopqrstuvwxyz"; 673 bigData << "\";"; 674 675 struct Test { 676 const char* cookieString; 677 bool expired; 678 }; 679 680 const Test tests[] = { 681 { "305-01=1; Max-Age=\"notAValidValue\"", true }, 682 { "305-02=1; Max-Age=\"Wed, 08-Nov-2035 01:04:33\"", true }, 683 { "305-03=1; Max-Age=\"0\"", true }, 684 { "305-04=1; Max-Age=\"1\"", false }, 685 { "305-05=1; Max-Age=\"10000\"", false }, 686 { "305-06=1; Max-Age=\"-1\"", true }, 687 { "305-07=1; Max-Age=\"0.5\"", true }, 688 { "305-08=1; Max-Age=\"9999999999999999999999999\"", false }, 689 { "305-09=1; Max-Age=\"-9999999999999999999999999\"", true }, 690 { "305-10=1; Max-Age=\"+10000\"", false }, 691 { "305-11=1; Max-Age=\"Fri, 13-Dec-1901 20:45:52\"", true }, 692 { bigData, true }, 693 { "305-13=1; Max-Age=\"0+10000\"", true }, 694 { "305-14=1; Max-Age=\"10000+0\"", true }, 695 { "305-15=1; Max-Age=10000\"", true }, 696 { "305-16=1; Max-Age=\"10000", true }, 697 { "305-17=1; Max-Age=10000", false }, 698 { "305-18=1; Max-Age=100\"00", true }, 699 }; 700 701 for (unsigned int i = 0; i < sizeof(tests) / sizeof(Test); i++) 702 { 703 NextSubTest(); 704 705 BNetworkCookie cookie(tests[i].cookieString, setter); 706 CPPUNIT_ASSERT_EQUAL(tests[i].expired, cookie.ShouldDeleteNow()); 707 } 708 } 709 710 711 void 712 CookieTest::ExplodeTest() 713 { 714 struct Test { 715 const char* cookieString; 716 const char* url; 717 struct 718 { 719 bool valid; 720 const char* name; 721 const char* value; 722 const char* domain; 723 const char* path; 724 bool secure; 725 bool httponly; 726 bool session; 727 BDateTime expire; 728 } expected; 729 }; 730 731 Test tests[] = { 732 // Cookie string URL 733 // ------------- ------------- 734 // Valid Name Value Domain Path Secure HttpOnly Session Expiration 735 // --------- -------- --------- ----------------- --------- -------- -------- ------- ---------- 736 // Normal cookies 737 { "name=value", "http://www.example.com/path/path", 738 { true, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, 739 { "name=value; domain=example.com; path=/; secure", "http://www.example.com/path/path", 740 { true, "name", "value", "example.com", "/" , true, false, true, BDateTime() } }, 741 { "name=value; httponly; secure", "http://www.example.com/path/path", 742 { true, "name", "value", "www.example.com", "/path", true, true, true, BDateTime() } }, 743 { "name=value; expires=Wed, 20-Feb-2013 20:00:00 UTC", "http://www.example.com/path/path", 744 { true, "name", "value", "www.example.com", "/path", false, false, false, 745 BDateTime(BDate(2013, 2, 20), BTime(20, 0, 0, 0)) } }, 746 // Valid cookie with bad form 747 { "name= ; domain =example.com ;path=/; secure = yup ; blahblah ;)", "http://www.example.com/path/path", 748 { true, "name", "", "example.com", "/" , true, false, true, BDateTime() } }, 749 // Invalid path 750 { "name=value; path=invalid", "http://www.example.com/path/path", 751 { false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, 752 // Setting for other subdomain (invalid) 753 { "name=value; domain=subdomain.example.com", "http://www.example.com/path/path", 754 { false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, 755 // Various invalid cookies 756 { "name", "http://www.example.com/path/path", 757 { false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, 758 { "; domain=example.com", "http://www.example.com/path/path", 759 { false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } } 760 }; 761 762 BNetworkCookie cookie; 763 764 for (uint32 i = 0; i < (sizeof(tests) / sizeof(Test)); i++) { 765 NextSubTest(); 766 767 BUrl url(tests[i].url); 768 cookie.ParseCookieString(tests[i].cookieString, url); 769 770 CPPUNIT_ASSERT(tests[i].expected.valid == cookie.IsValid()); 771 772 if (!tests[i].expected.valid) 773 continue; 774 775 CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected.name), cookie.Name()); 776 CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected.value), cookie.Value()); 777 CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected.domain), 778 cookie.Domain()); 779 CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected.path), cookie.Path()); 780 CPPUNIT_ASSERT(tests[i].expected.secure == cookie.Secure()); 781 CPPUNIT_ASSERT(tests[i].expected.httponly == cookie.HttpOnly()); 782 CPPUNIT_ASSERT(tests[i].expected.session == cookie.IsSessionCookie()); 783 784 if (!cookie.IsSessionCookie()) 785 CPPUNIT_ASSERT_EQUAL(tests[i].expected.expire.Time_t(), 786 cookie.ExpirationDate()); 787 } 788 } 789 790 791 /* static */ void 792 CookieTest::AddTests(BTestSuite& parent) 793 { 794 CppUnit::TestSuite& suite = *new CppUnit::TestSuite("CookieTest"); 795 796 suite.addTest(new CppUnit::TestCaller<CookieTest>("CookieTest::SimpleTest", 797 &CookieTest::SimpleTest)); 798 suite.addTest(new CppUnit::TestCaller<CookieTest>( 799 "CookieTest::StandardTest", &CookieTest::StandardTest)); 800 suite.addTest(new CppUnit::TestCaller<CookieTest>("CookieTest::ExpireTest", 801 &CookieTest::ExpireTest)); 802 suite.addTest(new CppUnit::TestCaller<CookieTest>("CookieTest::PathTest", 803 &CookieTest::PathTest)); 804 suite.addTest(new CppUnit::TestCaller<CookieTest>("CookieTest::MaxSizeTest", 805 &CookieTest::MaxSizeTest)); 806 suite.addTest(new CppUnit::TestCaller<CookieTest>( 807 "CookieTest::MaxNumberTest", &CookieTest::MaxNumberTest)); 808 suite.addTest(new CppUnit::TestCaller<CookieTest>("CookieTest::UpdateTest", 809 &CookieTest::UpdateTest)); 810 suite.addTest(new CppUnit::TestCaller<CookieTest>( 811 "CookieTest::HttpOnlyTest", &CookieTest::HttpOnlyTest)); 812 suite.addTest(new CppUnit::TestCaller<CookieTest>( 813 "CookieTest::EncodingTest", &CookieTest::EncodingTest)); 814 suite.addTest(new CppUnit::TestCaller<CookieTest>("CookieTest::DomainTest", 815 &CookieTest::DomainTest)); 816 suite.addTest(new CppUnit::TestCaller<CookieTest>( 817 "CookieTest::PersistantTest", &CookieTest::PersistantTest)); 818 suite.addTest(new CppUnit::TestCaller<CookieTest>( 819 "CookieTest::OverwriteTest", &CookieTest::OverwriteTest)); 820 suite.addTest(new CppUnit::TestCaller<CookieTest>( 821 "CookieTest::OrderTest", &CookieTest::OrderTest)); 822 823 suite.addTest(new CppUnit::TestCaller<CookieTest>( 824 "CookieTest::ExpireParsingTest", &CookieTest::ExpireParsingTest)); 825 suite.addTest(new CppUnit::TestCaller<CookieTest>( 826 "CookieTest::PathMatchingTest", &CookieTest::PathMatchingTest)); 827 suite.addTest(new CppUnit::TestCaller<CookieTest>( 828 "CookieTest::DomainMatchingTest", &CookieTest::DomainMatchingTest)); 829 suite.addTest(new CppUnit::TestCaller<CookieTest>( 830 "CookieTest::MaxAgeParsingTest", &CookieTest::MaxAgeParsingTest)); 831 suite.addTest(new CppUnit::TestCaller<CookieTest>( 832 "CookieTest::ExplodeTest", &CookieTest::ExplodeTest)); 833 834 parent.addTest("CookieTest", &suite); 835 } 836 837 838 const BNetworkCookie* 839 CookieTest::_GetCookie(BNetworkCookieJar& jar, const BUrl& url, 840 const char* name) 841 { 842 BNetworkCookieJar::UrlIterator it = jar.GetUrlIterator(url); 843 const BNetworkCookie* result = NULL; 844 845 while (it.HasNext()) { 846 const BNetworkCookie* cookie = it.Next(); 847 if (cookie->Name() == name) { 848 // Make sure the cookie is found only once. 849 CPPUNIT_ASSERT(result == NULL); 850 851 result = cookie; 852 } 853 } 854 855 return result; 856 } 857