[Author: aa]
[google-gears.git] / gears / cctests / test.cc
blobd4e3f32c285414909b097903a7710c48093bc5e2
1 // Copyright 2007, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
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.
26 #ifdef DEBUG
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);
40 #ifdef WIN32
41 #include <windows.h> // must manually #include before nsIEventQueueService.h
42 #endif
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();
60 bool TestManifest();
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();
80 if (!permissions) {
81 context->SetException(GET_INTERNAL_ERROR_MESSAGE());
82 return;
85 permissions->SetCanAccessGears(cc_tests_origin,
86 PermissionsDB::PERMISSION_ALLOWED);
88 bool ok = true;
89 ok &= TestStringUtils();
90 ok &= TestFileUtils();
91 ok &= TestUrlUtils();
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 //------------------------------------------------------------------------------
119 // TestHttpCookies
120 //------------------------------------------------------------------------------
121 bool TestHttpCookies() {
122 #undef TEST_ASSERT
123 #define TEST_ASSERT(b) \
125 if (!(b)) { \
126 LOG(("TestHttpCookies - failed (%d)\n", __LINE__)); \
127 return false; \
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"));
159 CookieMap map;
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/"),
171 &cookie_string));
172 ParseCookieString(cookie_string, &map);
174 LOG(("TestHttpCookies - passed\n"));
175 return true;
179 //------------------------------------------------------------------------------
180 // TestManifest
181 //------------------------------------------------------------------------------
182 bool TestManifest() {
183 #undef TEST_ASSERT
184 #define TEST_ASSERT(b) \
186 if (!(b)) { \
187 LOG(("TestManifest - failed (%d)\n", __LINE__)); \
188 return false; \
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"
200 L" 'entries': [ \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"
205 L" ] \n"
206 L"}");
208 std::string json8;
209 TEST_ASSERT(String16ToUTF8(json16, &json8));
210 ReplaceAll(json8, std::string("'"), std::string("\""));
212 Manifest manifest;
213 bool ok = manifest.Parse(manifest_url, json8.c_str(), json8.length());
214 TEST_ASSERT(ok);
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);
246 TEST_ASSERT(!ok);
248 LOG(("TestManifest - passed\n"));
249 return true;
252 //------------------------------------------------------------------------------
253 // TestResourceStore
254 //------------------------------------------------------------------------------
255 bool TestResourceStore() {
256 #undef TEST_ASSERT
257 #define TEST_ASSERT(b) \
259 if (!(b)) { \
260 LOG(("TestResourceStore - failed (%d)\n", __LINE__)); \
261 return false; \
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));
276 ResourceStore wcs;
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"));
334 return true;
338 //------------------------------------------------------------------------------
339 // TestManagedResourceStore
340 //------------------------------------------------------------------------------
341 bool TestManagedResourceStore() {
342 #undef TEST_ASSERT
343 #define TEST_ASSERT(b) \
345 if (!(b)) { \
346 LOG(("TestManagedResourceStore - failed (%d)\n", __LINE__)); \
347 return false; \
351 const char *manifest1_json =
352 "{ \"betaManifestVersion\": 1, "
353 " \"version\": \"test_version\", "
354 " \"redirectUrl\": \"redirectUrl\", "
355 " \"entries\": [ "
356 " { \"url\": \"test_url\", \"src\": \"test_src\" }, "
357 " { \"url\": \"test_url2\" }, "
358 " { \"url\": \"test_url3\", \"ignoreQuery\": true } "
359 " ]"
360 "}";
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;
390 int64 last_time;
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
401 Manifest manifest1;
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,
411 &version_string));
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"));
421 return true;
424 //------------------------------------------------------------------------------
425 // TestLocalServerDB
426 //------------------------------------------------------------------------------
427 bool TestLocalServerDB() {
428 #undef TEST_ASSERT
429 #define TEST_ASSERT(b) \
431 if (!(b)) { \
432 LOG(("TestWebCacheDB - failed (%d)\n", __LINE__)); \
433 SetFakeCookieString(NULL, NULL); \
434 return false; \
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();
446 TEST_ASSERT(db);
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,
452 &existing_server)) {
453 db->DeleteServer(existing_server.id);
456 // insert a server
457 WebCacheDB::ServerInfo server;
458 server.server_type = WebCacheDB::MANAGED_RESOURCE_STORE;
459 server.security_origin_url = security_origin.url();
460 server.name = name;
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;
476 entry.url = testurl;
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));
510 // delete version1
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);
532 // off again
533 TEST_ASSERT(!db->CanService(testurl));
535 // delete version2
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"));
582 return true;
585 bool TestParseHttpStatusLine() {
586 #undef TEST_ASSERT
587 #define TEST_ASSERT(b) \
589 if (!(b)) { \
590 LOG(("TestParseHttpStatusLine - failed (%d)\n", __LINE__)); \
591 return false; \
594 std::string16 good(STRING16(L"HTTP/1.1 200 OK"));
595 std::string16 version, text;
596 int code;
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"));
630 return true;
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) {
639 int status = 0;
640 std::string16 headers;
641 std::string16 body;
642 source->GetStatus(&status);
643 source->GetAllResponseHeaders(&headers);
644 source->GetResponseBodyAsText(&body);
645 source->SetOnReadyStateChange(NULL);
646 source->ReleaseReference();
647 delete this;
648 LOG(("TestHttpRequest - complete (%d)\n", status));
653 #ifdef BROWSER_FF
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
657 bool IsUiThread();
658 #endif
660 bool TestHttpRequest() {
661 #undef TEST_ASSERT
662 #define TEST_ASSERT(b) \
664 if (!(b)) { \
665 LOG(("TestHttpRequest - failed (%d)\n", __LINE__)); \
666 return false; \
670 #ifdef BROWSER_FF
671 if (!IsUiThread()) {
672 return true;
674 #endif
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/"),
685 false);
686 TEST_ASSERT(ok);
687 ok = request->Send();
688 TEST_ASSERT(ok);
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/"),
695 true);
696 TEST_ASSERT(ok);
697 ok = request->Send();
698 TEST_ASSERT(ok);
699 return true;
702 bool TestBufferBlob() {
703 #undef TEST_ASSERT
704 #define TEST_ASSERT(b) \
706 if (!(b)) { \
707 printf("TestBufferBlob - failed (%d)\n", __LINE__); \
708 return false; \
711 #if BROWSER_FF || BROWSER_IE // blobs not implemented for npapi yet
712 int num_bytes = 0;
713 uint8 buffer[64] = {0};
715 // Empty blob tests
716 BufferBlob blob1;
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
720 blob1.Finalize();
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
730 BufferBlob blob2;
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
739 blob2.Finalize();
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');
760 #endif
762 return true;
765 #endif // DEBUG