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