1 #include <cstdlib> 2 #include <cstring> 3 #include <cstdio> 4 #include <ctime> 5 #include <iostream> 6 7 #include <NetworkKit.h> 8 #include <SupportKit.h> 9 10 #ifdef ASSERT 11 #undef ASSERT 12 #endif 13 14 #define REPORT(i, assert, line) cout << "ASSERT() failed at line " << line \ 15 << ": " << #assert << " (test #" << i << ")" << endl 16 #define ASSERT(index, assertion) { if (!(assertion)) { REPORT(index, assertion, __LINE__ ); } } 17 18 19 using std::cout; 20 using std::endl; 21 22 23 typedef struct { 24 const char* cookieString; 25 const char* url; 26 struct 27 { 28 bool valid; 29 const char* name; 30 const char* value; 31 const char* domain; 32 const char* path; 33 bool secure; 34 bool httponly; 35 bool session; 36 BDateTime expire; 37 } expected; 38 } ExplodeTest; 39 40 41 ExplodeTest kTestExplode[] = 42 // Cookie string URL 43 // ------------- ------------- 44 // Valid Name Value Domain Path Secure HttpOnly Session Expiration 45 // --------- -------- --------- ----------------- --------- -------- -------- ------- ---------- 46 { 47 // Normal cookies 48 { "name=value", "http://www.example.com/path/path", 49 { true, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, 50 { "name=value; domain=example.com; path=/; secure", "http://www.example.com/path/path", 51 { true, "name", "value", "example.com", "/" , true, false, true, BDateTime() } }, 52 { "name=value; httponly; secure", "http://www.example.com/path/path", 53 { true, "name", "value", "www.example.com", "/path", true, true, true, BDateTime() } }, 54 { "name=value; expires=Wed, 20 Feb 2013 20:00:00 UTC", "http://www.example.com/path/path", 55 { true, "name", "value", "www.example.com", "/path", false, false, false, 56 BDateTime(BDate(2012, 2, 20), BTime(20, 0, 0, 0)) } }, 57 // Valid cookie with bad form 58 { "name= ; domain =example.com ;path=/; secure = yup ; blahblah ;)", "http://www.example.com/path/path", 59 { true, "name", "", "example.com", "/" , true, false, true, BDateTime() } }, 60 // Invalid path, default path should be used instead 61 { "name=value; path=invalid", "http://www.example.com/path/path", 62 { true, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, 63 // Setting for other subdomain (invalid) 64 { "name=value; domain=subdomain.example.com", "http://www.example.com/path/path", 65 { false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, 66 // Various invalid cookies 67 { "name", "http://www.example.com/path/path", 68 { false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }, 69 { "; domain=example.com", "http://www.example.com/path/path", 70 { false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } } 71 }; 72 73 74 void explodeImplodeTest() 75 { 76 uint32 testIndex; 77 BNetworkCookie cookie; 78 79 for (testIndex = 0; testIndex < (sizeof(kTestExplode) / sizeof(ExplodeTest)); testIndex++) 80 { 81 BUrl url(kTestExplode[testIndex].url); 82 cookie.ParseCookieStringFromUrl(kTestExplode[testIndex].cookieString, url); 83 84 ASSERT(testIndex, kTestExplode[testIndex].expected.valid == cookie.IsValid()); 85 86 if (kTestExplode[testIndex].expected.valid) { 87 ASSERT(testIndex, BString(kTestExplode[testIndex].expected.name) == cookie.Name()); 88 ASSERT(testIndex, BString(kTestExplode[testIndex].expected.value) == cookie.Value()); 89 ASSERT(testIndex, BString(kTestExplode[testIndex].expected.domain) == cookie.Domain()); 90 ASSERT(testIndex, BString(kTestExplode[testIndex].expected.path) == cookie.Path()); 91 ASSERT(testIndex, kTestExplode[testIndex].expected.secure == cookie.Secure()); 92 ASSERT(testIndex, kTestExplode[testIndex].expected.httponly == cookie.HttpOnly()); 93 ASSERT(testIndex, kTestExplode[testIndex].expected.session == cookie.IsSessionCookie()); 94 95 if (!cookie.IsSessionCookie()) 96 ASSERT(testIndex, kTestExplode[testIndex].expected.expire.Time_t() == cookie.ExpirationDate()); 97 } 98 } 99 } 100 101 102 void stressTest(int32 domainNumber, int32 totalCookies, char** flat, ssize_t* size) 103 { 104 char **domains = new char*[domainNumber]; 105 106 cout << "Creating random domains" << endl; 107 srand(time(NULL)); 108 for (int32 i = 0; i < domainNumber; i++) { 109 int16 charNum = (rand() % 16) + 1; 110 111 domains[i] = new char[charNum + 5]; 112 113 // Random domain 114 for (int32 c = 0; c < charNum; c++) 115 domains[i][c] = (rand() % 26) + 'a'; 116 117 domains[i][charNum] = '.'; 118 119 // Random tld 120 for (int32 c = 0; c < 3; c++) 121 domains[i][charNum+1+c] = (rand() % 26) + 'a'; 122 123 domains[i][charNum+4] = 0; 124 } 125 126 BNetworkCookieJar j; 127 BStopWatch* watch = new BStopWatch("Cookie insertion"); 128 for (int32 i = 0; i < totalCookies; i++) { 129 BNetworkCookie c; 130 int16 domain = (rand() % domainNumber); 131 BString name("Foo"); 132 name << i; 133 134 c.SetName(name); 135 c.SetValue("Bar"); 136 c.SetDomain(domains[domain]); 137 c.SetPath("/"); 138 139 j.AddCookie(c); 140 } 141 delete watch; 142 143 BNetworkCookie* c; 144 int16 domain = (rand() % domainNumber); 145 BString host("http://"); 146 host << domains[domain] << "/"; 147 148 watch = new BStopWatch("Cookie filtering"); 149 BUrl url(host); 150 int32 count = 0; 151 for (BNetworkCookieJar::UrlIterator it(j.GetUrlIterator(url)); (c = it.Next()); ) { 152 //for (BNetworkCookieJar::Iterator it(j.GetIterator()); c = it.Next(); ) { 153 count++; 154 } 155 delete watch; 156 cout << "Count for " << host << ": " << count << endl; 157 158 159 cout << "Flat view of cookie jar is " << j.FlattenedSize() << " bytes large." << endl; 160 *flat = new char[j.FlattenedSize()]; 161 *size = j.FlattenedSize(); 162 163 if (j.Flatten(*flat, j.FlattenedSize()) == B_OK) 164 cout << "Flatten() success!" << endl; 165 else 166 cout << "Flatten() error!" << endl; 167 168 delete[] domains; 169 } 170 171 172 int 173 main(int, char**) 174 { 175 cout << "Running explodeImplodeTest:" << endl; 176 explodeImplodeTest(); 177 cout << endl << endl; 178 179 cout << "Running stressTest:" << endl; 180 char* flatJar; 181 ssize_t size; 182 stressTest(10000, 40000, &flatJar, &size); 183 184 BNetworkCookieJar j; 185 j.Unflatten(B_ANY_TYPE, flatJar, size); 186 187 int32 count = 0; 188 BNetworkCookie* c; 189 for (BNetworkCookieJar::Iterator it(j.GetIterator()); (c = it.Next()); ) 190 count++; 191 cout << "Count : " << count << endl; 192 193 delete[] flatJar; 194 195 return EXIT_SUCCESS; 196 } 197