1 // Copyright 2007, Google Inc.
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "gears/cctests/test.h"
30 #include "gears/base/common/dispatcher.h"
31 #include "gears/base/common/js_types.h"
32 #include "gears/base/common/module_wrapper.h"
34 DECLARE_GEARS_WRAPPER(GearsTest
);
36 void Dispatcher
<GearsTest
>::Init() {
37 RegisterMethod("runTests", &GearsTest::RunTests
);
41 #include <windows.h> // must manually #include before nsIEventQueueService.h
44 #include "gears/base/common/name_value_table_test.h"
45 #include "gears/base/common/permissions_db.h"
46 #include "gears/base/common/permissions_db_test.h"
47 #include "gears/base/common/sqlite_wrapper_test.h"
48 #include "gears/base/common/string_utils.h"
49 #include "gears/blob/buffer_blob.h"
50 #include "gears/localserver/common/http_cookies.h"
51 #include "gears/localserver/common/http_request.h"
52 #include "gears/localserver/common/localserver_db.h"
53 #include "gears/localserver/common/managed_resource_store.h"
54 #include "gears/localserver/common/manifest.h"
55 #include "gears/localserver/common/resource_store.h"
56 #include "gears/third_party/scoped_ptr/scoped_ptr.h"
58 bool TestHttpCookies();
59 bool TestHttpRequest();
61 bool TestMessageService(); // from message_service_test.cc
62 bool TestLocalServerDB();
63 bool TestResourceStore();
64 bool TestManagedResourceStore();
65 bool TestParseHttpStatusLine();
66 bool TestSecurityModel(); // from security_model_test.cc
67 bool TestFileUtils(); // from file_test.cc
68 bool TestUrlUtils(); // from url_utils_test.cc
69 bool TestJsRootedTokenLifetime(); // from base_class_test.cc
70 bool TestStringUtils(); // from string_utils_test.cc
71 bool TestSerialization(); // from serialization_test.cc
72 bool TestBufferBlob();
75 void GearsTest::RunTests(JsCallContext
*context
) {
76 // We need permissions to use the localserver.
77 SecurityOrigin cc_tests_origin
;
78 cc_tests_origin
.InitFromUrl(STRING16(L
"http://cc_tests/"));
79 PermissionsDB
*permissions
= PermissionsDB::GetDB();
81 context
->SetException(GET_INTERNAL_ERROR_MESSAGE());
85 permissions
->SetCanAccessGears(cc_tests_origin
,
86 PermissionsDB::PERMISSION_ALLOWED
);
89 ok
&= TestStringUtils();
90 ok
&= TestFileUtils();
92 ok
&= TestParseHttpStatusLine();
93 ok
&= TestHttpRequest();
94 ok
&= TestHttpCookies();
95 ok
&= TestSecurityModel();
96 ok
&= TestSqliteUtilsAll();
97 ok
&= TestNameValueTableAll();
98 ok
&= TestPermissionsDBAll();
99 ok
&= TestLocalServerDB();
100 ok
&= TestResourceStore();
101 ok
&= TestManifest();
102 ok
&= TestManagedResourceStore();
103 ok
&= TestMessageService();
104 ok
&= TestSerialization();
105 ok
&= TestBufferBlob();
106 // TODO(zork): Add this test back in once it doesn't crash the browser.
107 //ok &= TestJsRootedTokenLifetime();
109 // We have to call GetDB again since TestCapabilitiesDBAll deletes
110 // the previous instance.
111 permissions
= PermissionsDB::GetDB();
112 permissions
->SetCanAccessGears(cc_tests_origin
,
113 PermissionsDB::PERMISSION_DEFAULT
);
115 context
->SetReturnValue(JSPARAM_BOOL
, &ok
);
118 //------------------------------------------------------------------------------
120 //------------------------------------------------------------------------------
121 bool TestHttpCookies() {
123 #define TEST_ASSERT(b) \
126 LOG(("TestHttpCookies - failed (%d)\n", __LINE__)); \
131 std::vector
<std::string
> tokens
;
132 std::string
tokens_string("a,b,c,d");
133 TEST_ASSERT(Tokenize(tokens_string
, std::string(","), &tokens
) == 4);
134 TEST_ASSERT(tokens
[0] == "a");
135 TEST_ASSERT(tokens
[1] == "b");
136 TEST_ASSERT(tokens
[2] == "c");
137 TEST_ASSERT(tokens
[3] == "d");
138 tokens_string
= ", aaaa;bbbb ,;cccc;,";
139 TEST_ASSERT(Tokenize(tokens_string
, std::string(",;"), &tokens
) == 3);
140 TEST_ASSERT(tokens
[0] == " aaaa");
141 TEST_ASSERT(tokens
[1] == "bbbb ");
142 TEST_ASSERT(tokens
[2] == "cccc");
144 std::string16 name
, value
;
145 const std::string16
kName(STRING16(L
"name"));
146 const std::string16
kNameEq(STRING16(L
"name="));
147 const std::string16
kNameEqSp(STRING16(L
"name= "));
148 ParseCookieNameAndValue(kNameEq
, &name
, &value
);
149 TEST_ASSERT(name
== kName
);
150 TEST_ASSERT(value
.empty());
151 ParseCookieNameAndValue(kNameEqSp
, &name
, &value
);
152 TEST_ASSERT(name
== kName
);
153 TEST_ASSERT(value
.empty());
155 const std::string16
kValue(STRING16(L
"value"));
156 const std::string16
kName2(STRING16(L
"name 2"));
157 const std::string16
kValue2(STRING16(L
"value 2"));
158 const std::string16
kCookie3(STRING16(L
"cookie3"));
160 std::string16
cookie_string(
161 STRING16(L
"name=value; name 2 = value 2; cookie3 "));
162 ParseCookieString(cookie_string
, &map
);
163 TEST_ASSERT(map
.size() == 3);
164 TEST_ASSERT(map
.GetCookie(kName
, &value
));
165 TEST_ASSERT(value
== kValue
);
166 TEST_ASSERT(map
.HasSpecificCookie(kName2
, kValue2
));
167 TEST_ASSERT(map
.HasCookie(kCookie3
));
168 TEST_ASSERT(!map
.HasCookie(kCookie3
+ kName2
));
170 TEST_ASSERT(GetCookieString(STRING16(L
"http://www.google.com/"),
172 ParseCookieString(cookie_string
, &map
);
174 LOG(("TestHttpCookies - passed\n"));
179 //------------------------------------------------------------------------------
181 //------------------------------------------------------------------------------
182 bool TestManifest() {
184 #define TEST_ASSERT(b) \
187 LOG(("TestManifest - failed (%d)\n", __LINE__)); \
192 const char16
*manifest_url
= STRING16(L
"http://cc_tests/manifest.json");
193 const std::string16 expected_version
= STRING16(L
"expected_version");
194 const std::string16
expected_redirect(
195 STRING16(L
"http://cc_tests.other_origin/redirectUrl"));
196 const char16
*json16
= STRING16(
197 L
"{ 'betaManifestVersion': 1, \n"
198 L
" 'version': 'expected_version', \n"
199 L
" 'redirectUrl': 'http://cc_tests.other_origin/redirectUrl', \n"
201 L
" { 'url': 'test_url', 'src': 'test_src' }, \n"
202 L
" { 'url': 'test_url2' }, \n"
203 L
" { 'url': 'test_url3', 'ignoreQuery': true}, \n"
204 L
" { 'url': 'test_redirect_url', 'redirect': 'test_url3?blah' } \n"
209 TEST_ASSERT(String16ToUTF8(json16
, &json8
));
210 ReplaceAll(json8
, std::string("'"), std::string("\""));
213 bool ok
= manifest
.Parse(manifest_url
, json8
.c_str(), json8
.length());
215 TEST_ASSERT(manifest
.IsValid());
216 TEST_ASSERT(expected_version
== manifest
.GetVersion());
217 TEST_ASSERT(expected_redirect
== manifest
.GetRedirectUrl());
218 TEST_ASSERT(manifest
.GetEntries()->size() == 4);
220 const Manifest::Entry
*entry1
= &manifest
.GetEntries()->at(0);
221 TEST_ASSERT(entry1
->url
== STRING16(L
"http://cc_tests/test_url"));
222 TEST_ASSERT(entry1
->src
== STRING16(L
"http://cc_tests/test_src"));
223 TEST_ASSERT(entry1
->redirect
.empty());
224 TEST_ASSERT(!entry1
->ignore_query
);
226 const Manifest::Entry
*entry2
= &manifest
.GetEntries()->at(1);
227 TEST_ASSERT(entry2
->url
== STRING16(L
"http://cc_tests/test_url2"));
228 TEST_ASSERT(entry2
->src
.empty());
229 TEST_ASSERT(entry2
->redirect
.empty());
231 const Manifest::Entry
*entry3
= &manifest
.GetEntries()->at(2);
232 TEST_ASSERT(entry3
->url
== STRING16(L
"http://cc_tests/test_url3"));
233 TEST_ASSERT(entry3
->src
.empty());
234 TEST_ASSERT(entry3
->redirect
.empty());
235 TEST_ASSERT(entry3
->ignore_query
);
237 const Manifest::Entry
*entry4
= &manifest
.GetEntries()->at(3);
238 TEST_ASSERT(entry4
->url
== STRING16(L
"http://cc_tests/test_redirect_url"));
239 TEST_ASSERT(entry4
->src
.empty());
240 TEST_ASSERT(entry4
->redirect
== STRING16(L
"http://cc_tests/test_url3?blah"));
243 const char *json_not_an_object
= "\"A string, but we need an object\"";
244 Manifest manifest_should_not_parse
;
245 ok
= manifest_should_not_parse
.Parse(manifest_url
, json_not_an_object
);
248 LOG(("TestManifest - passed\n"));
252 //------------------------------------------------------------------------------
254 //------------------------------------------------------------------------------
255 bool TestResourceStore() {
257 #define TEST_ASSERT(b) \
260 LOG(("TestResourceStore - failed (%d)\n", __LINE__)); \
264 const char16
*name
= STRING16(L
"name");
265 const char16
*url1
= STRING16(L
"http://cc_tests/url1");
266 const char16
*url2
= STRING16(L
"http://cc_tests/url2");
267 const char16
*url3
= STRING16(L
"http://cc_tests/url3");
268 const char16
*required_cookie
= STRING16(L
"required_cookie");
269 const char *data1
= "Hello world";
270 const char16
*headers1
=
271 STRING16(L
"Content-Type: text/plain\r\nContent-Length: 11\r\n\r\n");
273 SecurityOrigin security_origin
;
274 TEST_ASSERT(security_origin
.InitFromUrl(url1
));
277 TEST_ASSERT(wcs
.CreateOrOpen(security_origin
, name
, required_cookie
));
279 ResourceStore::Item item1
;
280 item1
.entry
.url
= url1
;
281 item1
.payload
.headers
= headers1
;
282 item1
.payload
.data
.reset(new std::vector
<uint8
>);
283 item1
.payload
.data
->assign(data1
, data1
+ strlen(data1
));
284 item1
.payload
.status_line
= STRING16(L
"HTTP/1.0 200 OK");
285 item1
.payload
.status_code
= HttpConstants::HTTP_OK
;
286 TEST_ASSERT(wcs
.PutItem(&item1
));
288 TEST_ASSERT(wcs
.IsCaptured(url1
));
290 std::string16 headers
;
291 TEST_ASSERT(wcs
.GetAllHeaders(url1
, &headers
));
292 TEST_ASSERT(headers
== item1
.payload
.headers
);
294 std::string16 content_type
;
295 TEST_ASSERT(wcs
.GetHeader(url1
, STRING16(L
"Content-Type"), &content_type
));
296 TEST_ASSERT(content_type
== STRING16(L
"text/plain"));
298 ResourceStore::Item test_item1
;
299 TEST_ASSERT(wcs
.GetItem(url1
, &test_item1
));
301 TEST_ASSERT(wcs
.Copy(url1
, url2
));
303 ResourceStore::Item test_item2
;
304 TEST_ASSERT(wcs
.GetItem(url2
, &test_item2
));
305 TEST_ASSERT(test_item1
.entry
.id
!= test_item2
.entry
.id
);
306 TEST_ASSERT(test_item1
.entry
.payload_id
== test_item2
.entry
.payload_id
);
307 TEST_ASSERT(test_item1
.entry
.src
== test_item2
.entry
.src
);
308 TEST_ASSERT(test_item1
.entry
.url
!= test_item2
.entry
.url
);
309 TEST_ASSERT(test_item1
.entry
.version_id
== test_item2
.entry
.version_id
);
310 TEST_ASSERT(test_item1
.payload
.id
== test_item2
.payload
.id
);
311 TEST_ASSERT(test_item1
.payload
.creation_date
==
312 test_item2
.payload
.creation_date
);
313 TEST_ASSERT(test_item1
.payload
.headers
== test_item2
.payload
.headers
);
314 TEST_ASSERT(test_item1
.payload
.status_line
== test_item2
.payload
.status_line
);
315 TEST_ASSERT(test_item1
.payload
.status_code
== test_item2
.payload
.status_code
);
317 TEST_ASSERT(wcs
.Rename(url2
, url3
));
319 ResourceStore::Item test_item3
;
320 TEST_ASSERT(wcs
.GetItem(url3
, &test_item3
));
321 TEST_ASSERT(test_item3
.entry
.id
== test_item2
.entry
.id
);
322 TEST_ASSERT(test_item3
.entry
.payload_id
== test_item2
.entry
.payload_id
);
323 TEST_ASSERT(test_item3
.entry
.src
== test_item2
.entry
.src
);
324 TEST_ASSERT(test_item3
.entry
.url
!= test_item2
.entry
.url
);
325 TEST_ASSERT(test_item3
.entry
.version_id
== test_item2
.entry
.version_id
);
326 TEST_ASSERT(test_item3
.payload
.id
== test_item2
.payload
.id
);
327 TEST_ASSERT(test_item3
.payload
.creation_date
==
328 test_item2
.payload
.creation_date
);
329 TEST_ASSERT(test_item3
.payload
.headers
== test_item2
.payload
.headers
);
330 TEST_ASSERT(test_item3
.payload
.status_line
== test_item2
.payload
.status_line
);
331 TEST_ASSERT(test_item3
.payload
.status_code
== test_item2
.payload
.status_code
);
333 LOG(("TestResourceStore - passed\n"));
338 //------------------------------------------------------------------------------
339 // TestManagedResourceStore
340 //------------------------------------------------------------------------------
341 bool TestManagedResourceStore() {
343 #define TEST_ASSERT(b) \
346 LOG(("TestManagedResourceStore - failed (%d)\n", __LINE__)); \
351 const char *manifest1_json
=
352 "{ \"betaManifestVersion\": 1, "
353 " \"version\": \"test_version\", "
354 " \"redirectUrl\": \"redirectUrl\", "
356 " { \"url\": \"test_url\", \"src\": \"test_src\" }, "
357 " { \"url\": \"test_url2\" }, "
358 " { \"url\": \"test_url3\", \"ignoreQuery\": true } "
362 const char16
*manifest_url
= STRING16(L
"http://cc_tests/manifest.json");
363 const char16
*name
= STRING16(L
"name");
364 const char16
*required_cookie
= STRING16(L
"user=joe");
366 SecurityOrigin security_origin
;
367 TEST_ASSERT(security_origin
.InitFromUrl(manifest_url
));
369 // Clear out data from previous test runs
370 int64 existing_store_id
= WebCacheDB::kInvalidID
;
371 if (ManagedResourceStore::ExistsInDB(security_origin
, name
,
372 required_cookie
, &existing_store_id
)) {
373 ManagedResourceStore remover
;
374 TEST_ASSERT(remover
.Open(existing_store_id
));
375 TEST_ASSERT(remover
.Remove());
377 // Bring the ManagedResourceStore thru the states that it will go thru
378 // during an install / update process, and verify that it works as expected.
380 ManagedResourceStore app
;
381 TEST_ASSERT(app
.CreateOrOpen(security_origin
, name
, required_cookie
));
383 // Ensure it looks freshly created
384 TEST_ASSERT(app
.StillExistsInDB());
385 TEST_ASSERT(!app
.HasVersion(WebCacheDB::VERSION_CURRENT
));
386 TEST_ASSERT(!app
.HasVersion(WebCacheDB::VERSION_DOWNLOADING
));
388 // Test Get/Set UpdateInfo
389 WebCacheDB::UpdateStatus update_status
;
391 TEST_ASSERT(app
.GetUpdateInfo(&update_status
, &last_time
, NULL
, NULL
));
392 TEST_ASSERT(update_status
== WebCacheDB::UPDATE_OK
);
393 TEST_ASSERT(last_time
== 0);
394 TEST_ASSERT(app
.SetUpdateInfo(WebCacheDB::UPDATE_FAILED
, 1, NULL
, NULL
));
395 TEST_ASSERT(app
.GetUpdateInfo(&update_status
, &last_time
, NULL
, NULL
));
396 TEST_ASSERT(update_status
== WebCacheDB::UPDATE_FAILED
);
397 TEST_ASSERT(last_time
== 1);
399 // Add a version in the "downloading" state
402 TEST_ASSERT(manifest1
.Parse(manifest_url
, manifest1_json
));
404 int64 manifest1_version_id
;
405 TEST_ASSERT(app
.AddManifestAsDownloadingVersion(&manifest1
,
406 &manifest1_version_id
));
407 TEST_ASSERT(app
.HasVersion(WebCacheDB::VERSION_DOWNLOADING
));
409 std::string16 version_string
;
410 TEST_ASSERT(app
.GetVersionString(WebCacheDB::VERSION_DOWNLOADING
,
412 TEST_ASSERT(version_string
== manifest1
.GetVersion());
414 // Transition to current
416 TEST_ASSERT(app
.SetDownloadingVersionAsCurrent());
417 TEST_ASSERT(app
.HasVersion(WebCacheDB::VERSION_CURRENT
));
418 TEST_ASSERT(!app
.HasVersion(WebCacheDB::VERSION_DOWNLOADING
));
420 LOG(("TestManagedResourceStore - passed\n"));
424 //------------------------------------------------------------------------------
426 //------------------------------------------------------------------------------
427 bool TestLocalServerDB() {
429 #define TEST_ASSERT(b) \
432 LOG(("TestWebCacheDB - failed (%d)\n", __LINE__)); \
433 SetFakeCookieString(NULL, NULL); \
438 const char16
*name
= STRING16(L
"name");
439 const char16
*required_cookie
= STRING16(L
"user=joe");
440 const char16
*testurl
= STRING16(L
"http://cc_tests/url");
442 SecurityOrigin security_origin
;
443 TEST_ASSERT(security_origin
.InitFromUrl(testurl
));
445 WebCacheDB
*db
= WebCacheDB::GetDB();
448 // delete existing info from a previous test run
449 WebCacheDB::ServerInfo existing_server
;
450 if (db
->FindServer(security_origin
, name
, required_cookie
,
451 WebCacheDB::MANAGED_RESOURCE_STORE
,
453 db
->DeleteServer(existing_server
.id
);
457 WebCacheDB::ServerInfo server
;
458 server
.server_type
= WebCacheDB::MANAGED_RESOURCE_STORE
;
459 server
.security_origin_url
= security_origin
.url();
461 server
.required_cookie
= required_cookie
;
462 server
.manifest_url
= STRING16(L
"http://cc_tests/manifest_url");
463 TEST_ASSERT(db
->InsertServer(&server
));
465 // insert a current version1 that specifies a redirect
466 WebCacheDB::VersionInfo version1
;
467 version1
.server_id
= server
.id
;
468 version1
.version_string
= STRING16(L
"version_string");
469 version1
.ready_state
= WebCacheDB::VERSION_CURRENT
;
470 version1
.session_redirect_url
= STRING16(L
"http://cc_tests/redirect_url");
471 TEST_ASSERT(db
->InsertVersion(&version1
));
473 // insert an entry with a bogus payload id for the current version
474 WebCacheDB::EntryInfo entry
;
475 entry
.version_id
= version1
.id
;
477 entry
.payload_id
= kint64max
;
478 TEST_ASSERT(db
->InsertEntry(&entry
));
480 // we should be able to service a request for testurl, the response
481 // should redirect to our session_redirect_url
482 SetFakeCookieString(testurl
, NULL
);
483 TEST_ASSERT(db
->CanService(testurl
));
485 WebCacheDB::PayloadInfo payload
;
486 TEST_ASSERT(db
->Service(testurl
, true, &payload
));
487 TEST_ASSERT(payload
.IsHttpRedirect());
488 std::string16 test_redirect_url
;
489 TEST_ASSERT(payload
.GetHeader(HttpConstants::kLocationHeader
,
490 &test_redirect_url
) &&
491 test_redirect_url
== version1
.session_redirect_url
);
493 // insert a downloaded version2 w/o a redirect
494 WebCacheDB::VersionInfo version2
;
495 version2
.server_id
= server
.id
;
496 version2
.version_string
= STRING16(L
"version_string2");
497 version2
.ready_state
= WebCacheDB::VERSION_DOWNLOADING
;
498 TEST_ASSERT(db
->InsertVersion(&version2
));
500 // insert an entry for version2
501 WebCacheDB::EntryInfo entry2
;
502 entry2
.version_id
= version2
.id
;
503 entry2
.url
= testurl
;
504 entry2
.payload_id
= kint64max
;
505 TEST_ASSERT(db
->InsertEntry(&entry2
));
507 // we should still be able to service a request for testurl from version1
508 TEST_ASSERT(db
->CanService(testurl
));
511 TEST_ASSERT(db
->DeleteVersion(version1
.id
));
513 // we shouldn't be able to service a request for testurl
514 TEST_ASSERT(!db
->CanService(testurl
));
516 // now make the ready version current
517 TEST_ASSERT(db
->UpdateVersion(version2
.id
, WebCacheDB::VERSION_CURRENT
));
519 // we should still not be able to service a request for testurl as there
520 // is no session yet and version2 does not have a redirect_url
521 TEST_ASSERT(!db
->CanService(testurl
));
523 // now set the required cookie (fake)
524 SetFakeCookieString(testurl
, required_cookie
);
526 // we should be able to service a request for testurl again
527 TEST_ASSERT(db
->CanService(testurl
));
529 // clear the cookie string for our testurl (fake)
530 SetFakeCookieString(testurl
, NULL
);
533 TEST_ASSERT(!db
->CanService(testurl
));
536 TEST_ASSERT(db
->DeleteVersion(version2
.id
));
538 // insert version3 for that server that requires a session and has a redirect
539 WebCacheDB::VersionInfo version3
;
540 version3
.server_id
= server
.id
;
541 version3
.version_string
= STRING16(L
"version_string3");
542 version3
.ready_state
= WebCacheDB::VERSION_CURRENT
;
543 version3
.session_redirect_url
= STRING16(
544 L
"http://cc_tests/session_redirect_url");
545 TEST_ASSERT(db
->InsertVersion(&version3
));
547 // insert an entry for the ready version
548 WebCacheDB::EntryInfo entry3
;
549 entry3
.version_id
= version3
.id
;
550 entry3
.url
= testurl
;
551 entry3
.ignore_query
= true;
552 entry3
.payload_id
= kint64max
;
553 TEST_ASSERT(db
->InsertEntry(&entry3
));
555 // this entry s/b hit for request with arbitrary query parameters
556 std::string16
testurl_query(testurl
);
557 testurl_query
+= STRING16(L
"?blah");
559 // on again, s/b responding with redirects
560 SetFakeCookieString(testurl
, NULL
);
561 TEST_ASSERT(db
->CanService(testurl
));
562 SetFakeCookieString(testurl_query
.c_str(), NULL
);
563 TEST_ASSERT(db
->CanService(testurl_query
.c_str()));
565 // still on, s/b responding with payloads
566 SetFakeCookieString(testurl
, required_cookie
);
567 TEST_ASSERT(db
->CanService(testurl
));
568 SetFakeCookieString(testurl_query
.c_str(), required_cookie
);
569 TEST_ASSERT(db
->CanService(testurl_query
.c_str()));
571 // delete the server altogether
572 TEST_ASSERT(db
->DeleteServer(server
.id
));
574 // we shouldn't be able to service a request for the test url
575 TEST_ASSERT(!db
->CanService(testurl
));
576 TEST_ASSERT(!db
->CanService(testurl_query
.c_str()));
578 SetFakeCookieString(NULL
, NULL
);
580 // we made it thru as expected
581 LOG(("TestWebCacheDB - passed\n"));
585 bool TestParseHttpStatusLine() {
587 #define TEST_ASSERT(b) \
590 LOG(("TestParseHttpStatusLine - failed (%d)\n", __LINE__)); \
594 std::string16
good(STRING16(L
"HTTP/1.1 200 OK"));
595 std::string16 version
, text
;
597 TEST_ASSERT(ParseHttpStatusLine(good
, &version
, &code
, &text
));
598 TEST_ASSERT(version
== STRING16(L
"HTTP/1.1"));
599 TEST_ASSERT(code
== 200);
600 TEST_ASSERT(text
== STRING16(L
"OK"));
601 TEST_ASSERT(ParseHttpStatusLine(good
, &version
, NULL
, NULL
));
602 TEST_ASSERT(ParseHttpStatusLine(good
, NULL
, &code
, NULL
));
603 TEST_ASSERT(ParseHttpStatusLine(good
, NULL
, NULL
, &text
));
605 const char16
*acceptable
[] = {
606 STRING16(L
"HTTP/1.0 200"), // no status
607 STRING16(L
"HTTP 200 ABBREVIATED VERSION"),
608 STRING16(L
"HTTP/1.1 500 REASON: CONTAINING COLON")
610 for (size_t i
= 0; i
< ARRAYSIZE(acceptable
); ++i
) {
611 std::string16
acceptable_str(acceptable
[i
]);
612 TEST_ASSERT(ParseHttpStatusLine(acceptable_str
, NULL
, NULL
, NULL
));
615 const char16
*bad
[] = {
616 STRING16(L
" HTTP/1.1 200 SPACE AT START"),
617 STRING16(L
"WTFP/1.1 200 WRONG SCHEME"),
618 STRING16(L
"HTTP/1.1 2 CODE TOO SMALL"),
619 STRING16(L
"HTTP/1.0 2000 CODE TOO BIG"),
620 STRING16(L
"HTTP/1.0 NO CODE"),
621 STRING16(L
"complete_gibberish"),
622 STRING16(L
""), // an empty string
623 STRING16(L
" \t \t "), // whitespace only
625 for (size_t i
= 0; i
< ARRAYSIZE(bad
); ++i
) {
626 std::string16
bad_str(bad
[i
]);
627 TEST_ASSERT(!ParseHttpStatusLine(bad_str
, NULL
, NULL
, NULL
));
629 LOG(("TestParseHttpStatusLine - passed\n"));
634 class TestHttpRequestListener
: public HttpRequest::ReadyStateListener
{
635 virtual void ReadyStateChanged(HttpRequest
*source
) {
636 HttpRequest::ReadyState state
= HttpRequest::UNINITIALIZED
;
637 source
->GetReadyState(&state
);
638 if (state
== HttpRequest::COMPLETE
) {
640 std::string16 headers
;
642 source
->GetStatus(&status
);
643 source
->GetAllResponseHeaders(&headers
);
644 source
->GetResponseBodyAsText(&body
);
645 source
->SetOnReadyStateChange(NULL
);
646 source
->ReleaseReference();
648 LOG(("TestHttpRequest - complete (%d)\n", status
));
654 // Returns true if the currently executing thread is the main UI thread,
655 // firefox/mozila has one such very special thread
656 // See cache_intercept.cc for implementation
660 bool TestHttpRequest() {
662 #define TEST_ASSERT(b) \
665 LOG(("TestHttpRequest - failed (%d)\n", __LINE__)); \
676 // A request is created with a refcount of one, our listener will
677 // release this reference upon completion. If something goes wrong
678 // we leak, not good in a real program but fine for this test.
680 // Send a request synchronously
681 HttpRequest
*request
= HttpRequest::Create();
682 request
->SetOnReadyStateChange(new TestHttpRequestListener());
683 bool ok
= request
->Open(HttpConstants::kHttpGET
,
684 STRING16(L
"http://www.google.com/"),
687 ok
= request
->Send();
690 // Send an async request
691 request
= HttpRequest::Create();
692 request
->SetOnReadyStateChange(new TestHttpRequestListener());
693 ok
= request
->Open(HttpConstants::kHttpGET
,
694 STRING16(L
"http://www.google.com/"),
697 ok
= request
->Send();
702 bool TestBufferBlob() {
704 #define TEST_ASSERT(b) \
707 printf("TestBufferBlob - failed (%d)\n", __LINE__); \
711 #if BROWSER_FF || BROWSER_IE // blobs not implemented for npapi yet
713 uint8 buffer
[64] = {0};
717 TEST_ASSERT(blob1
.Length() == 0);
718 num_bytes
= blob1
.Read(buffer
, 64, 0);
719 TEST_ASSERT(num_bytes
== 0); // a non-finalized blob is not readable
721 TEST_ASSERT(blob1
.Length() == 0);
722 num_bytes
= blob1
.Read(buffer
, 64, 0);
723 TEST_ASSERT(num_bytes
== 0); // because it's actually empty
724 num_bytes
= blob1
.Append("abc", 3);
725 TEST_ASSERT(num_bytes
== 0); // a finalized blob is not writable
727 memset(buffer
, 0, sizeof(buffer
));
729 // Typical blob operation
731 num_bytes
= blob2
.Append("abc", 3);
732 TEST_ASSERT(num_bytes
== 3);
733 TEST_ASSERT(blob2
.Length() == 3);
734 num_bytes
= blob2
.Append("de", 2);
735 TEST_ASSERT(num_bytes
== 2);
736 TEST_ASSERT(blob2
.Length() == 5);
737 num_bytes
= blob2
.Read(buffer
, 64, 0);
738 TEST_ASSERT(num_bytes
== 0); // a non-finalized blob is not readable
740 TEST_ASSERT(blob2
.Length() == 5);
741 num_bytes
= blob2
.Read(buffer
, 64, 0);
742 TEST_ASSERT(num_bytes
== 5);
743 num_bytes
= blob2
.Append("fgh", 3);
744 TEST_ASSERT(num_bytes
== 0); // a finalized blob is not writable
745 TEST_ASSERT(buffer
[0] == 'a');
746 TEST_ASSERT(buffer
[1] == 'b');
747 TEST_ASSERT(buffer
[2] == 'c');
748 TEST_ASSERT(buffer
[3] == 'd');
749 TEST_ASSERT(buffer
[4] == 'e');
750 TEST_ASSERT(buffer
[5] == '\0');
752 // overwrite the first three bytes of buffer, but don't touch the rest
753 num_bytes
= blob2
.Read(buffer
, 3, 2);
754 TEST_ASSERT(num_bytes
== 3);
755 TEST_ASSERT(buffer
[0] == 'c');
756 TEST_ASSERT(buffer
[1] == 'd');
757 TEST_ASSERT(buffer
[2] == 'e');
758 TEST_ASSERT(buffer
[3] == 'd');
759 TEST_ASSERT(buffer
[4] == 'e');