NetworkCookieJar: various small fixes and updated tests

This commit is contained in:
Hamish Morrison
2013-02-09 17:10:10 +00:00
parent c8bc218363
commit 64a1f5a020
4 changed files with 198 additions and 152 deletions
+13 -14
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010 Haiku Inc. All rights reserved. * Copyright 2010-2013 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _B_NETWORK_COOKIE_JAR_H_ #ifndef _B_NETWORK_COOKIE_JAR_H_
@@ -24,7 +24,7 @@ public:
class UrlIterator; class UrlIterator;
struct PrivateIterator; struct PrivateIterator;
struct PrivateHashMap; struct PrivateHashMap;
public: public:
BNetworkCookieJar(); BNetworkCookieJar();
BNetworkCookieJar( BNetworkCookieJar(
@@ -34,16 +34,15 @@ public:
BNetworkCookieJar(BMessage* archive); BNetworkCookieJar(BMessage* archive);
virtual ~BNetworkCookieJar(); virtual ~BNetworkCookieJar();
bool AddCookie(const BNetworkCookie& cookie); status_t AddCookie(const BNetworkCookie& cookie);
bool AddCookie(BNetworkCookie* cookie); status_t AddCookie(BNetworkCookie* cookie);
bool AddCookies( status_t AddCookies(const BNetworkCookieList& cookies);
const BNetworkCookieList& cookies);
uint32 DeleteOutdatedCookies(); uint32 DeleteOutdatedCookies();
uint32 PurgeForExit(); uint32 PurgeForExit();
// BArchivable members // BArchivable members
virtual status_t Archive(BMessage* into, virtual status_t Archive(BMessage* into,
bool deep = true) const; bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive); static BArchivable* Instantiate(BMessage* archive);
@@ -54,20 +53,20 @@ public:
virtual status_t Flatten(void* buffer, ssize_t size) virtual status_t Flatten(void* buffer, ssize_t size)
const; const;
virtual bool AllowsTypeCode(type_code code) const; virtual bool AllowsTypeCode(type_code code) const;
virtual status_t Unflatten(type_code code, virtual status_t Unflatten(type_code code,
const void* buffer, ssize_t size); const void* buffer, ssize_t size);
// Iterators // Iterators
Iterator GetIterator() const; Iterator GetIterator() const;
UrlIterator GetUrlIterator(const BUrl& url) const; UrlIterator GetUrlIterator(const BUrl& url) const;
private: private:
void _DoFlatten() const; void _DoFlatten() const;
private: private:
friend class Iterator; friend class Iterator;
friend class UrlIterator; friend class UrlIterator;
PrivateHashMap* fCookieHashMap; PrivateHashMap* fCookieHashMap;
mutable BString fFlattened; mutable BString fFlattened;
}; };
@@ -117,7 +116,7 @@ private:
UrlIterator(const BNetworkCookieJar* map, UrlIterator(const BNetworkCookieJar* map,
const BUrl& url); const BUrl& url);
bool _SupDomain(); bool _SuperDomain();
void _FindNext(); void _FindNext();
void _FindDomain(); void _FindDomain();
bool _FindPath(); bool _FindPath();
@@ -131,10 +130,10 @@ private:
BNetworkCookieList* fLastList; BNetworkCookieList* fLastList;
BNetworkCookie* fElement; BNetworkCookie* fElement;
BNetworkCookie* fLastElement; BNetworkCookie* fLastElement;
int32 fIndex; int32 fIndex;
int32 fLastIndex; int32 fLastIndex;
BUrl fUrl; BUrl fUrl;
}; };
+26 -19
View File
@@ -100,14 +100,15 @@ BNetworkCookie::ParseCookieStringFromUrl(const BString& string,
// Parse the name and value of the cookie // Parse the name and value of the cookie
index = _ExtractNameValuePair(string, name, value, index); index = _ExtractNameValuePair(string, name, value, index);
// The set-cookie-string is not valid if (index == -1) {
if (index == -1) // The set-cookie-string is not valid
return *this; return *this;
}
SetName(name); SetName(name);
SetValue(value); SetValue(value);
// Parse the remaining cookie attributes // Parse the remaining cookie attributes.
while (index < string.Length()) { while (index < string.Length()) {
ASSERT(string[index] == ';'); ASSERT(string[index] == ';');
index++; index++;
@@ -119,12 +120,12 @@ BNetworkCookie::ParseCookieStringFromUrl(const BString& string,
else if (name.ICompare("httponly") == 0) else if (name.ICompare("httponly") == 0)
SetHttpOnly(true); SetHttpOnly(true);
// The following attributes require a value // The following attributes require a value.
if (value.IsEmpty()) if (value.IsEmpty())
continue; continue;
if (name.ICompare("max-age") == 0) { if (name.ICompare("max-age") == 0) {
// Validate the max-age value // Validate the max-age value.
char* end = NULL; char* end = NULL;
long maxAge = strtol(value.String(), &end, 10); long maxAge = strtol(value.String(), &end, 10);
if (*end == '\0') if (*end == '\0')
@@ -132,20 +133,31 @@ BNetworkCookie::ParseCookieStringFromUrl(const BString& string,
} else if (name.ICompare("expires") == 0) { } else if (name.ICompare("expires") == 0) {
BHttpTime date(value); BHttpTime date(value);
SetExpirationDate(date.Parse()); SetExpirationDate(date.Parse());
} else if (name.ICompare("domain") == 0) } else if (name.ICompare("domain") == 0) {
SetDomain(value); SetDomain(value);
else if (name.ICompare("path") == 0) } else if (name.ICompare("path") == 0) {
SetPath(value); SetPath(value);
}
} }
// If no domain was specified, we set a host-only domain from the URL // If no domain was specified, we set a host-only domain from the URL.
if (!HasDomain()) { if (!HasDomain()) {
SetDomain(url.Host()); SetDomain(url.Host());
fHostOnly = true; fHostOnly = true;
} else {
// Otherwise the setting URL must domain-match the domain it set.
if (!IsValidForDomain(url.Host())) {
// Invalidate the cookie.
_Reset();
return *this;
}
// We should also reject cookies with domains that match public
// suffixes.
} }
// If no path was specified we compute the default path from the URL // If no path was specified or the path is invalid, we compute the default
if (!HasPath()) // path from the URL.
if (!HasPath() || Path()[0] != '/')
SetPath(_DefaultPathForUrl(url)); SetPath(_DefaultPathForUrl(url));
return *this; return *this;
@@ -187,6 +199,7 @@ BNetworkCookie::SetValue(const BString& value)
BNetworkCookie& BNetworkCookie&
BNetworkCookie::SetPath(const BString& path) BNetworkCookie::SetPath(const BString& path)
{ {
// TODO: canonicalize the path
fPath = path; fPath = path;
fRawFullCookieValid = false; fRawFullCookieValid = false;
return *this; return *this;
@@ -196,13 +209,10 @@ BNetworkCookie::SetPath(const BString& path)
BNetworkCookie& BNetworkCookie&
BNetworkCookie::SetDomain(const BString& domain) BNetworkCookie::SetDomain(const BString& domain)
{ {
// TODO: canonicalize the domain
fDomain = domain; fDomain = domain;
fHostOnly = false; fHostOnly = false;
// We always use pre-dotted domains for tail matching
if (fDomain.ByteAt(0) != '.')
fDomain.Prepend(".");
fRawFullCookieValid = false; fRawFullCookieValid = false;
return *this; return *this;
} }
@@ -387,13 +397,10 @@ BNetworkCookie::IsValid() const
bool bool
BNetworkCookie::IsValidForUrl(const BUrl& url) const BNetworkCookie::IsValidForUrl(const BUrl& url) const
{ {
if (IsSecure() && url.Protocol() != "https") if (Secure() && url.Protocol() != "https")
return false; return false;
BString urlHost = url.Host(); return IsValidForDomain(url.Host()) && IsValidForPath(url.Path());
BString urlPath = url.Path();
return IsValidForDomain(urlHost) && IsValidForPath(urlPath);
} }
+86 -69
View File
@@ -1,35 +1,37 @@
/* /*
* Copyright 2010 Haiku Inc. All rights reserved. * Copyright 2010-2013 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Christophe Huriaux, c.huriaux@gmail.com * Christophe Huriaux, c.huriaux@gmail.com
* Hamish Morrison, hamishm53@gmail.com
*/ */
#include <new>
#include <Debug.h> #include <Debug.h>
#include <HashMap.h> #include <HashMap.h>
#include <HashString.h> #include <HashString.h>
#include <Message.h> #include <Message.h>
#include <NetworkCookieJar.h> #include <NetworkCookieJar.h>
#include <new>
#include "NetworkCookieJarPrivate.h" #include "NetworkCookieJarPrivate.h"
const char* kArchivedCookieMessageName = "be:cookie";
const char* kArchivedCookieMessageName = "be:cookie";
BNetworkCookieJar::BNetworkCookieJar() BNetworkCookieJar::BNetworkCookieJar()
: :
fCookieHashMap(new PrivateHashMap) fCookieHashMap(new PrivateHashMap())
{ {
} }
BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieJar&) BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieJar&)
: :
BArchivable(), fCookieHashMap(new PrivateHashMap())
fCookieHashMap(new PrivateHashMap)
{ {
// TODO // TODO
} }
@@ -37,7 +39,7 @@ BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieJar&)
BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieList& otherList) BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieList& otherList)
: :
fCookieHashMap(new PrivateHashMap) fCookieHashMap(new PrivateHashMap())
{ {
AddCookies(otherList); AddCookies(otherList);
} }
@@ -45,19 +47,22 @@ BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieList& otherList)
BNetworkCookieJar::BNetworkCookieJar(BMessage* archive) BNetworkCookieJar::BNetworkCookieJar(BMessage* archive)
: :
fCookieHashMap(new PrivateHashMap) fCookieHashMap(new PrivateHashMap())
{ {
BMessage extractedCookie; BMessage extractedCookie;
for (int32 i = 0; for (int32 i = 0; archive->FindMessage(kArchivedCookieMessageName, i,
archive->FindMessage(kArchivedCookieMessageName, i, &extractedCookie) &extractedCookie) == B_OK; i++) {
== B_OK;
i++) {
BNetworkCookie* heapCookie BNetworkCookie* heapCookie
= new(std::nothrow) BNetworkCookie(&extractedCookie); = new(std::nothrow) BNetworkCookie(&extractedCookie);
if (heapCookie == NULL || !AddCookie(heapCookie)) if (heapCookie == NULL)
break; break;
if (!AddCookie(heapCookie)) {
delete heapCookie;
continue;
}
} }
} }
@@ -66,7 +71,7 @@ BNetworkCookieJar::~BNetworkCookieJar()
{ {
BNetworkCookie* cookiePtr; BNetworkCookie* cookiePtr;
for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;)
delete it.Remove(); delete it.Remove();
} }
@@ -74,49 +79,58 @@ BNetworkCookieJar::~BNetworkCookieJar()
// #pragma mark Add cookie to cookie jar // #pragma mark Add cookie to cookie jar
bool status_t
BNetworkCookieJar::AddCookie(const BNetworkCookie& cookie) BNetworkCookieJar::AddCookie(const BNetworkCookie& cookie)
{ {
BNetworkCookie* heapCookie = new(std::nothrow) BNetworkCookie(cookie); BNetworkCookie* heapCookie = new(std::nothrow) BNetworkCookie(cookie);
if (heapCookie == NULL)
return B_NO_MEMORY;
if (!AddCookie(heapCookie)) { status_t result = AddCookie(heapCookie);
if (result != B_OK) {
delete heapCookie; delete heapCookie;
return false; return result;
} }
return true; return B_OK;
} }
bool status_t
BNetworkCookieJar::AddCookie(BNetworkCookie* cookie) BNetworkCookieJar::AddCookie(BNetworkCookie* cookie)
{ {
if (cookie == NULL || cookie->ShouldDeleteNow()) if (cookie == NULL)
return false; return B_BAD_VALUE;
HashString key(cookie->Domain()); HashString key(cookie->Domain());
if (!fCookieHashMap->fHashMap.ContainsKey(key))
fCookieHashMap->fHashMap.Put(key, new BList);
BNetworkCookieList* list = fCookieHashMap->fHashMap.Get(key); BNetworkCookieList* list = fCookieHashMap->fHashMap.Get(key);
if (list == NULL) {
list = new(std::nothrow) BNetworkCookieList();
if (list == NULL || fCookieHashMap->fHashMap.Put(key, list) != B_OK)
return B_NO_MEMORY;
}
for (int32 i = 0; i < list->CountItems(); i++) { for (int32 i = 0; i < list->CountItems(); i++) {
BNetworkCookie* c BNetworkCookie* c
= reinterpret_cast<BNetworkCookie*>(list->ItemAt(i)); = reinterpret_cast<BNetworkCookie*>(list->ItemAt(i));
if (c->Name() == cookie->Name()) { if (c->Name() == cookie->Name() && c->Path() == cookie->Path()) {
list->RemoveItem(i); list->RemoveItem(i);
break; break;
} }
} }
list->AddItem(cookie); if (cookie->ShouldDeleteNow())
return true; delete cookie;
else
list->AddItem(cookie);
return B_OK;
} }
bool status_t
BNetworkCookieJar::AddCookies(const BNetworkCookieList& cookies) BNetworkCookieJar::AddCookies(const BNetworkCookieList& cookies)
{ {
for (int32 i = 0; i < cookies.CountItems(); i++) { for (int32 i = 0; i < cookies.CountItems(); i++) {
@@ -125,11 +139,12 @@ BNetworkCookieJar::AddCookies(const BNetworkCookieList& cookies)
// Using AddCookie by reference in order to avoid multiple // Using AddCookie by reference in order to avoid multiple
// cookie jar share the same cookie pointers // cookie jar share the same cookie pointers
if (!AddCookie(*cookiePtr)) status_t result = AddCookie(*cookiePtr);
return false; if (result != B_OK)
return result;
} }
return true; return B_OK;
} }
@@ -437,7 +452,7 @@ BNetworkCookieJar::Iterator::NextDomain()
return NULL; return NULL;
} }
fList = *(fIterator->fCookieMapIterator.NextValue()); fList = *fIterator->fCookieMapIterator.NextValue();
fIndex = 0; fIndex = 0;
fElement = reinterpret_cast<BNetworkCookie*>(fList->ItemAt(fIndex)); fElement = reinterpret_cast<BNetworkCookie*>(fList->ItemAt(fIndex));
@@ -461,8 +476,8 @@ BNetworkCookieJar::Iterator::Remove()
else else
fLastList->RemoveItem(fLastList->CountItems() - 1); fLastList->RemoveItem(fLastList->CountItems() - 1);
} else { } else {
fList->RemoveItem(fIndex-1);
fIndex--; fIndex--;
fList->RemoveItem(fIndex);
} }
fLastElement = NULL; fLastElement = NULL;
@@ -474,12 +489,18 @@ BNetworkCookieJar::Iterator&
BNetworkCookieJar::Iterator::operator=(const BNetworkCookieJar::Iterator& other) BNetworkCookieJar::Iterator::operator=(const BNetworkCookieJar::Iterator& other)
{ {
fCookieJar = other.fCookieJar; fCookieJar = other.fCookieJar;
fIterator = other.fIterator;
fLastList = other.fLastList; fLastList = other.fLastList;
fList = other.fList; fList = other.fList;
fElement = other.fElement; fElement = other.fElement;
fLastElement = other.fLastElement; fLastElement = other.fLastElement;
fIndex = other.fIndex; fIndex = other.fIndex;
fIterator = new(std::nothrow) PrivateIterator(*other.fIterator);
if (fIterator == NULL) {
// Make the iterator unusable.
fElement = NULL;
fLastElement = NULL;
}
return *this; return *this;
} }
@@ -527,25 +548,22 @@ BNetworkCookieJar::UrlIterator::UrlIterator(const BNetworkCookieJar* cookieJar,
fLastElement(NULL), fLastElement(NULL),
fIndex(0), fIndex(0),
fLastIndex(0), fLastIndex(0),
fUrl(const_cast<BUrl&>(url)) fUrl(url)
{ {
BString domain(url.Host()); BString domain = url.Host();
if (!domain.Length()) if (!domain.Length())
return; return;
if (domain[0] != '.')
domain.Prepend(".");
// Prepending another dot since _FindNext is going to
// call _SupDomain()
domain.Prepend(".");
fIterator = new(std::nothrow) PrivateIterator( fIterator = new(std::nothrow) PrivateIterator(
fCookieJar->fCookieHashMap->fHashMap.GetIterator()); fCookieJar->fCookieHashMap->fHashMap.GetIterator());
fIterator->fKey.SetTo(domain, domain.Length());
_FindNext(); if (fIterator != NULL) {
// Prepending a dot since _FindNext is going to call _SupDomain()
domain.Prepend(".");
fIterator->fKey.SetTo(domain, domain.Length());
_FindNext();
}
} }
@@ -607,23 +625,28 @@ BNetworkCookieJar::UrlIterator::operator=(
fLastElement = other.fLastElement; fLastElement = other.fLastElement;
fIndex = other.fIndex; fIndex = other.fIndex;
fLastIndex = other.fLastIndex; fLastIndex = other.fLastIndex;
fUrl = other.fUrl;
fIterator = other.fIterator; fIterator = new(std::nothrow) PrivateIterator(*other.fIterator);
if (fIterator == NULL) {
// Make the iterator unusable.
fElement = NULL;
fLastElement = NULL;
}
return *this; return *this;
} }
bool bool
BNetworkCookieJar::UrlIterator::_SupDomain() BNetworkCookieJar::UrlIterator::_SuperDomain()
{ {
BString domain(fIterator->fKey.GetString()); const char* domain = fIterator->fKey.GetString();
int32 nextDot = domain.FindFirst('.', 1); const char* nextDot = strchr(domain, '.');
if (nextDot == -1) if (nextDot == NULL)
return false; return false;
domain.Remove(0, nextDot); fIterator->fKey.SetTo(nextDot + 1);
fIterator->fKey.SetTo(domain.String(), domain.Length());
return true; return true;
} }
@@ -633,19 +656,16 @@ BNetworkCookieJar::UrlIterator::_FindNext()
{ {
fLastIndex = fIndex; fLastIndex = fIndex;
fLastElement = fElement; fLastElement = fElement;
if (_FindPath())
return;
fLastList = fList; fLastList = fList;
do {
if (!_SupDomain()) { while (!_FindPath()) {
if (!_SuperDomain()) {
fElement = NULL; fElement = NULL;
return; return;
} }
_FindDomain(); _FindDomain();
} while (!_FindPath()); }
} }
@@ -665,16 +685,13 @@ bool
BNetworkCookieJar::UrlIterator::_FindPath() BNetworkCookieJar::UrlIterator::_FindPath()
{ {
fIndex++; fIndex++;
if (fList && fIndex < fList->CountItems()) { while (fList && fIndex < fList->CountItems()) {
do { fElement = reinterpret_cast<BNetworkCookie*>(fList->ItemAt(fIndex));
fElement
= reinterpret_cast<BNetworkCookie*>(fList->ItemAt(fIndex));
if (fElement->IsValidForPath(fUrl.Path())) if (fElement->IsValidForPath(fUrl.Path()))
return true; return true;
fIndex++; fIndex++;
} while (fList && fIndex < fList->CountItems());
} }
return false; return false;
+73 -50
View File
@@ -20,58 +20,81 @@ using std::cout;
using std::endl; using std::endl;
typedef struct typedef struct {
{
const char* cookieString; const char* cookieString;
const char* url;
struct struct
{ {
bool valid;
const char* name; const char* name;
const char* value; const char* value;
const char* domain; const char* domain;
const char* path; const char* path;
bool secure; bool secure;
bool discard; bool httponly;
bool session; bool session;
int32 maxAge; BDateTime expire;
} expected; } expected;
} ExplodeTest; } ExplodeTest;
const ExplodeTest kTestExplode[] =
// Cookie string ExplodeTest kTestExplode[] =
// Name Value Domain Path Secure Discard Session maxAge // Cookie string URL
// -------- --------- --------- --------- ------ ------- -------- ------- // ------------- -------------
// Valid Name Value Domain Path Secure HttpOnly Session Expiration
// --------- -------- --------- ----------------- --------- -------- -------- ------- ----------
{ {
{ "name=value", // Normal cookies
{ "name", "value", "", "", false, false, true, 0 } }, { "name=value", "http://www.example.com/path/path",
{ "name=value;secure=true", { true, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } },
{ "name", "value", "", "", true, false, true, 0 } }, { "name=value; domain=example.com; path=/; secure", "http://www.example.com/path/path",
{ "name=value;secure=false;maxage=5", { true, "name", "value", "example.com", "/" , true, false, true, BDateTime() } },
{ "name", "value", "", "", false, false, false, 5 } }, { "name=value; httponly; secure", "http://www.example.com/path/path",
{ "name=value;discard=true", { true, "name", "value", "www.example.com", "/path", true, true, true, BDateTime() } },
{ "name", "value", "", "", false, true, true, 0 } }, { "name=value; expires=Wed, 20 Feb 2013 20:00:00 UTC", "http://www.example.com/path/path",
{ true, "name", "value", "www.example.com", "/path", false, false, false,
BDateTime(BDate(2012, 2, 20), BTime(20, 0, 0, 0)) } },
// Valid cookie with bad form
{ "name= ; domain =example.com ;path=/; secure = yup ; blahblah ;)", "http://www.example.com/path/path",
{ true, "name", "", "example.com", "/" , true, false, true, BDateTime() } },
// Invalid path, default path should be used instead
{ "name=value; path=invalid", "http://www.example.com/path/path",
{ true, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } },
// Setting for other subdomain (invalid)
{ "name=value; domain=subdomain.example.com", "http://www.example.com/path/path",
{ false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } },
// Various invalid cookies
{ "name", "http://www.example.com/path/path",
{ false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } },
{ "; domain=example.com", "http://www.example.com/path/path",
{ false, "name", "value", "www.example.com", "/path", false, false, true, BDateTime() } }
}; };
void explodeImplodeTest() void explodeImplodeTest()
{ {
uint8 testIndex; uint32 testIndex;
BNetworkCookie cookie; BNetworkCookie cookie;
for (testIndex = 0; testIndex < (sizeof(kTestExplode) / sizeof(ExplodeTest)); testIndex++) for (testIndex = 0; testIndex < (sizeof(kTestExplode) / sizeof(ExplodeTest)); testIndex++)
{ {
cookie.ParseCookieString(kTestExplode[testIndex].cookieString); BUrl url(kTestExplode[testIndex].url);
cookie.ParseCookieStringFromUrl(kTestExplode[testIndex].cookieString, url);
ASSERT(testIndex, BString(kTestExplode[testIndex].expected.name) == BString(cookie.Name())); ASSERT(testIndex, kTestExplode[testIndex].expected.valid == cookie.IsValid());
ASSERT(testIndex, BString(kTestExplode[testIndex].expected.value) == BString(cookie.Value()));
ASSERT(testIndex, BString(kTestExplode[testIndex].expected.domain) == BString(cookie.Domain()));
ASSERT(testIndex, BString(kTestExplode[testIndex].expected.path) == BString(cookie.Path()));
ASSERT(testIndex, kTestExplode[testIndex].expected.secure == cookie.Secure());
ASSERT(testIndex, kTestExplode[testIndex].expected.discard == cookie.Discard());
ASSERT(testIndex, kTestExplode[testIndex].expected.session == cookie.IsSessionCookie());
if (!cookie.IsSessionCookie()) if (kTestExplode[testIndex].expected.valid) {
ASSERT(testIndex, kTestExplode[testIndex].expected.maxAge == cookie.MaxAge()); ASSERT(testIndex, BString(kTestExplode[testIndex].expected.name) == cookie.Name());
ASSERT(testIndex, BString(kTestExplode[testIndex].expected.value) == cookie.Value());
ASSERT(testIndex, BString(kTestExplode[testIndex].expected.domain) == cookie.Domain());
ASSERT(testIndex, BString(kTestExplode[testIndex].expected.path) == cookie.Path());
ASSERT(testIndex, kTestExplode[testIndex].expected.secure == cookie.Secure());
ASSERT(testIndex, kTestExplode[testIndex].expected.httponly == cookie.HttpOnly());
ASSERT(testIndex, kTestExplode[testIndex].expected.session == cookie.IsSessionCookie());
if (!cookie.IsSessionCookie())
ASSERT(testIndex, kTestExplode[testIndex].expected.expire.Time_t() == cookie.ExpirationDate());
}
} }
} }
@@ -79,27 +102,27 @@ void explodeImplodeTest()
void stressTest(int32 domainNumber, int32 totalCookies, char** flat, ssize_t* size) void stressTest(int32 domainNumber, int32 totalCookies, char** flat, ssize_t* size)
{ {
char **domains = new char*[domainNumber]; char **domains = new char*[domainNumber];
cout << "Creating random domains" << endl; cout << "Creating random domains" << endl;
srand(time(NULL)); srand(time(NULL));
for (int32 i = 0; i < domainNumber; i++) { for (int32 i = 0; i < domainNumber; i++) {
int16 charNum = (rand() % 16) + 1; int16 charNum = (rand() % 16) + 1;
domains[i] = new char[charNum + 5]; domains[i] = new char[charNum + 5];
// Random domain // Random domain
for (int32 c = 0; c < charNum; c++) for (int32 c = 0; c < charNum; c++)
domains[i][c] = (rand() % 26) + 'a'; domains[i][c] = (rand() % 26) + 'a';
domains[i][charNum] = '.'; domains[i][charNum] = '.';
// Random tld // Random tld
for (int32 c = 0; c < 3; c++) for (int32 c = 0; c < 3; c++)
domains[i][charNum+1+c] = (rand() % 26) + 'a'; domains[i][charNum+1+c] = (rand() % 26) + 'a';
domains[i][charNum+4] = 0; domains[i][charNum+4] = 0;
} }
BNetworkCookieJar j; BNetworkCookieJar j;
BStopWatch* watch = new BStopWatch("Cookie insertion"); BStopWatch* watch = new BStopWatch("Cookie insertion");
for (int32 i = 0; i < totalCookies; i++) { for (int32 i = 0; i < totalCookies; i++) {
@@ -107,21 +130,21 @@ void stressTest(int32 domainNumber, int32 totalCookies, char** flat, ssize_t* si
int16 domain = (rand() % domainNumber); int16 domain = (rand() % domainNumber);
BString name("Foo"); BString name("Foo");
name << i; name << i;
c.SetName(name); c.SetName(name);
c.SetValue("Bar"); c.SetValue("Bar");
c.SetDomain(domains[domain]); c.SetDomain(domains[domain]);
c.SetPath("/"); c.SetPath("/");
j.AddCookie(c); j.AddCookie(c);
} }
delete watch; delete watch;
BNetworkCookie* c; BNetworkCookie* c;
int16 domain = (rand() % domainNumber); int16 domain = (rand() % domainNumber);
BString host("http://"); BString host("http://");
host << domains[domain] << "/"; host << domains[domain] << "/";
watch = new BStopWatch("Cookie filtering"); watch = new BStopWatch("Cookie filtering");
BUrl url(host); BUrl url(host);
int32 count = 0; int32 count = 0;
@@ -131,17 +154,17 @@ void stressTest(int32 domainNumber, int32 totalCookies, char** flat, ssize_t* si
} }
delete watch; delete watch;
cout << "Count for " << host << ": " << count << endl; cout << "Count for " << host << ": " << count << endl;
cout << "Flat view of cookie jar is " << j.FlattenedSize() << " bytes large." << endl; cout << "Flat view of cookie jar is " << j.FlattenedSize() << " bytes large." << endl;
*flat = new char[j.FlattenedSize()]; *flat = new char[j.FlattenedSize()];
*size = j.FlattenedSize(); *size = j.FlattenedSize();
if (j.Flatten(*flat, j.FlattenedSize()) == B_OK) if (j.Flatten(*flat, j.FlattenedSize()) == B_OK)
cout << "Flatten() success!" << endl; cout << "Flatten() success!" << endl;
else else
cout << "Flatten() error!" << endl; cout << "Flatten() error!" << endl;
delete[] domains; delete[] domains;
} }
@@ -152,22 +175,22 @@ main(int, char**)
cout << "Running explodeImplodeTest:" << endl; cout << "Running explodeImplodeTest:" << endl;
explodeImplodeTest(); explodeImplodeTest();
cout << endl << endl; cout << endl << endl;
cout << "Running stressTest:" << endl; cout << "Running stressTest:" << endl;
char* flatJar; char* flatJar;
ssize_t size; ssize_t size;
stressTest(10000, 40000, &flatJar, &size); stressTest(10000, 40000, &flatJar, &size);
BNetworkCookieJar j; BNetworkCookieJar j;
j.Unflatten(B_ANY_TYPE, flatJar, size); j.Unflatten(B_ANY_TYPE, flatJar, size);
int32 count = 0; int32 count = 0;
BNetworkCookie* c; BNetworkCookie* c;
for (BNetworkCookieJar::Iterator it(j.GetIterator()); (c = it.Next()); ) for (BNetworkCookieJar::Iterator it(j.GetIterator()); (c = it.Next()); )
count++; count++;
cout << "Count : " << count << endl; cout << "Count : " << count << endl;
delete[] flatJar; delete[] flatJar;
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }