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
CookieTest()23 CookieTest::CookieTest()
24 {
25 }
26
27
~CookieTest()28 CookieTest::~CookieTest()
29 {
30 }
31
32
33 // #pragma mark - Positive functionality tests
34
35
36 void
SimpleTest()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
StandardTest()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
ExpireTest()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
PathTest()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
MaxSizeTest()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
MaxNumberTest()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
UpdateTest()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
HttpOnlyTest()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
EncodingTest()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
DomainTest()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
PersistantTest()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
OverwriteTest()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
OrderTest()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
ExpireParsingTest()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
PathMatchingTest()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
DomainMatchingTest()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
MaxAgeParsingTest()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
ExplodeTest()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
AddTests(BTestSuite & parent)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*
_GetCookie(BNetworkCookieJar & jar,const BUrl & url,const char * name)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