[Author: zork]
[google-gears.git] / gears / cctests / test.cc
blob1c06e3fbbaf52529ddaec514737758f8cb3ec2f1
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 template<>
37 void Dispatcher<GearsTest>::Init() {
38 RegisterMethod("runTests", &GearsTest::RunTests);
39 RegisterMethod("testCoerceBool", &GearsTest::TestCoerceBool);
40 RegisterMethod("testCoerceInt", &GearsTest::TestCoerceInt);
41 RegisterMethod("testCoerceDouble", &GearsTest::TestCoerceDouble);
42 RegisterMethod("testCoerceString", &GearsTest::TestCoerceString);
43 RegisterMethod("testGetType", &GearsTest::TestGetType);
46 #ifdef WIN32
47 #include <windows.h> // must manually #include before nsIEventQueueService.h
48 #endif
50 #include "gears/base/common/name_value_table_test.h"
51 #include "gears/base/common/permissions_db.h"
52 #include "gears/base/common/permissions_db_test.h"
53 #include "gears/base/common/sqlite_wrapper_test.h"
54 #include "gears/base/common/string_utils.h"
55 #ifndef OFFICIAL_BUILD
56 // The blob API has not been finalized for official builds
57 #include "gears/blob/buffer_blob.h"
58 #endif
59 #include "gears/localserver/common/http_cookies.h"
60 #include "gears/localserver/common/http_request.h"
61 #include "gears/localserver/common/localserver_db.h"
62 #include "gears/localserver/common/managed_resource_store.h"
63 #include "gears/localserver/common/manifest.h"
64 #include "gears/localserver/common/resource_store.h"
65 #include "gears/third_party/scoped_ptr/scoped_ptr.h"
67 bool TestHttpCookies();
68 bool TestHttpRequest();
69 bool TestManifest();
70 bool TestMessageService(); // from message_service_test.cc
71 bool TestLocalServerDB();
72 bool TestResourceStore();
73 bool TestManagedResourceStore();
74 bool TestParseHttpStatusLine();
75 bool TestSecurityModel(); // from security_model_test.cc
76 bool TestFileUtils(); // from file_test.cc
77 bool TestUrlUtils(); // from url_utils_test.cc
78 bool TestJsRootedTokenLifetime(); // from base_class_test.cc
79 bool TestStringUtils(); // from string_utils_test.cc
80 bool TestSerialization(); // from serialization_test.cc
81 #ifndef OFFICIAL_BUILD
82 // The blob API has not been finalized for official builds
83 bool TestBufferBlob();
84 #endif // not OFFICIAL_BUILD
87 void GearsTest::RunTests(JsCallContext *context) {
88 // We need permissions to use the localserver.
89 SecurityOrigin cc_tests_origin;
90 cc_tests_origin.InitFromUrl(STRING16(L"http://cc_tests/"));
91 PermissionsDB *permissions = PermissionsDB::GetDB();
92 if (!permissions) {
93 context->SetException(GET_INTERNAL_ERROR_MESSAGE());
94 return;
97 permissions->SetCanAccessGears(cc_tests_origin,
98 PermissionsDB::PERMISSION_ALLOWED);
100 bool ok = true;
101 ok &= TestStringUtils();
102 ok &= TestFileUtils();
103 ok &= TestUrlUtils();
104 ok &= TestParseHttpStatusLine();
105 ok &= TestHttpRequest();
106 ok &= TestHttpCookies();
107 ok &= TestSecurityModel();
108 ok &= TestSqliteUtilsAll();
109 ok &= TestNameValueTableAll();
110 ok &= TestPermissionsDBAll();
111 ok &= TestLocalServerDB();
112 ok &= TestResourceStore();
113 ok &= TestManifest();
114 ok &= TestManagedResourceStore();
115 ok &= TestMessageService();
116 ok &= TestSerialization();
117 #ifndef OFFICIAL_BUILD
118 // The blob API has not been finalized for official builds
119 ok &= TestBufferBlob();
120 #endif // not OFFICIAL_BUILD
121 // TODO(zork): Add this test back in once it doesn't crash the browser.
122 //ok &= TestJsRootedTokenLifetime();
124 // We have to call GetDB again since TestCapabilitiesDBAll deletes
125 // the previous instance.
126 permissions = PermissionsDB::GetDB();
127 permissions->SetCanAccessGears(cc_tests_origin,
128 PermissionsDB::PERMISSION_DEFAULT);
130 context->SetReturnValue(JSPARAM_BOOL, &ok);
133 //------------------------------------------------------------------------------
134 // Coercion Tests
135 //------------------------------------------------------------------------------
136 // Coerces the first parameter to a bool and ensures the coerced value is equal
137 // to the expected value.
138 void GearsTest::TestCoerceBool(JsCallContext *context) {
139 bool value;
140 bool expected_value;
141 const int argc = 2;
142 JsArgument argv[argc] = {
143 { JSPARAM_REQUIRED, JSPARAM_BOOL, &value },
144 { JSPARAM_REQUIRED, JSPARAM_BOOL, &expected_value }
146 context->GetArguments(argc, argv);
147 if (context->is_exception_set()) return;
149 bool ok = (value == expected_value);
150 context->SetReturnValue(JSPARAM_BOOL, &ok);
153 // Coerces the first parameter to an int and ensures the coerced value is equal
154 // to the expected value.
155 void GearsTest::TestCoerceInt(JsCallContext *context) {
156 int value;
157 int expected_value;
158 const int argc = 2;
159 JsArgument argv[argc] = {
160 { JSPARAM_REQUIRED, JSPARAM_INT, &value },
161 { JSPARAM_REQUIRED, JSPARAM_INT, &expected_value },
163 context->GetArguments(argc, argv);
164 if (context->is_exception_set()) return;
166 bool ok = (value == expected_value);
167 context->SetReturnValue(JSPARAM_BOOL, &ok);
170 // Coerces the first parameter to a double and ensures the coerced value is
171 // equal to the expected value.
172 void GearsTest::TestCoerceDouble(JsCallContext *context) {
173 double value;
174 double expected_value;
175 const int argc = 2;
176 JsArgument argv[argc] = {
177 { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &value },
178 { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &expected_value },
180 context->GetArguments(argc, argv);
181 if (context->is_exception_set()) return;
183 bool ok = (value == expected_value);
184 context->SetReturnValue(JSPARAM_BOOL, &ok);
187 // Coerces the first parameter to a string and ensures the coerced value is
188 // equal to the expected value.
189 void GearsTest::TestCoerceString(JsCallContext *context) {
190 std::string16 value;
191 std::string16 expected_value;
192 const int argc = 2;
193 JsArgument argv[argc] = {
194 { JSPARAM_REQUIRED, JSPARAM_STRING16, &value },
195 { JSPARAM_REQUIRED, JSPARAM_STRING16, &expected_value },
197 context->GetArguments(argc, argv);
198 if (context->is_exception_set()) return;
200 bool ok = (value == expected_value);
201 context->SetReturnValue(JSPARAM_BOOL, &ok);
204 // Checks that the second parameter is of the type specified by the first
205 // parameter using GetType(). First parameter should be one of "bool", "int",
206 // "double", "string", "null", "undefined", "array", "function", "object".
207 void GearsTest::TestGetType(JsCallContext *context) {
208 std::string16 type;
209 const int argc = 1;
210 // Don't really care about the actual value of the second parameter
211 JsArgument argv[argc] = {
212 { JSPARAM_REQUIRED, JSPARAM_STRING16, &type },
214 context->GetArguments(argc, argv);
215 if (context->is_exception_set()) return;
217 bool ok = false;
218 JsParamType t = context->GetArgumentType(1);
219 if (type == STRING16(L"bool") && t == JSPARAM_BOOL ||
220 type == STRING16(L"int") && t == JSPARAM_INT ||
221 type == STRING16(L"double") && t == JSPARAM_DOUBLE ||
222 type == STRING16(L"string") && t == JSPARAM_STRING16 ||
223 type == STRING16(L"null") && t == JSPARAM_NULL ||
224 type == STRING16(L"undefined") && t == JSPARAM_UNDEFINED ||
225 type == STRING16(L"array") && t == JSPARAM_ARRAY ||
226 type == STRING16(L"function") && t == JSPARAM_FUNCTION ||
227 type == STRING16(L"object") && t == JSPARAM_OBJECT) {
228 ok = true;
230 context->SetReturnValue(JSPARAM_BOOL, &ok);
233 //------------------------------------------------------------------------------
234 // TestHttpCookies
235 //------------------------------------------------------------------------------
236 bool TestHttpCookies() {
237 #undef TEST_ASSERT
238 #define TEST_ASSERT(b) \
240 if (!(b)) { \
241 LOG(("TestHttpCookies - failed (%d)\n", __LINE__)); \
242 return false; \
246 std::vector<std::string> tokens;
247 std::string tokens_string("a,b,c,d");
248 TEST_ASSERT(Tokenize(tokens_string, std::string(","), &tokens) == 4);
249 TEST_ASSERT(tokens[0] == "a");
250 TEST_ASSERT(tokens[1] == "b");
251 TEST_ASSERT(tokens[2] == "c");
252 TEST_ASSERT(tokens[3] == "d");
253 tokens_string = ", aaaa;bbbb ,;cccc;,";
254 TEST_ASSERT(Tokenize(tokens_string, std::string(",;"), &tokens) == 3);
255 TEST_ASSERT(tokens[0] == " aaaa");
256 TEST_ASSERT(tokens[1] == "bbbb ");
257 TEST_ASSERT(tokens[2] == "cccc");
259 std::string16 name, value;
260 const std::string16 kName(STRING16(L"name"));
261 const std::string16 kNameEq(STRING16(L"name="));
262 const std::string16 kNameEqSp(STRING16(L"name= "));
263 ParseCookieNameAndValue(kNameEq, &name, &value);
264 TEST_ASSERT(name == kName);
265 TEST_ASSERT(value.empty());
266 ParseCookieNameAndValue(kNameEqSp, &name, &value);
267 TEST_ASSERT(name == kName);
268 TEST_ASSERT(value.empty());
270 const std::string16 kValue(STRING16(L"value"));
271 const std::string16 kName2(STRING16(L"name 2"));
272 const std::string16 kValue2(STRING16(L"value 2"));
273 const std::string16 kCookie3(STRING16(L"cookie3"));
274 CookieMap map;
275 std::string16 cookie_string(
276 STRING16(L"name=value; name 2 = value 2; cookie3 "));
277 ParseCookieString(cookie_string, &map);
278 TEST_ASSERT(map.size() == 3);
279 TEST_ASSERT(map.GetCookie(kName, &value));
280 TEST_ASSERT(value == kValue);
281 TEST_ASSERT(map.HasSpecificCookie(kName2, kValue2));
282 TEST_ASSERT(map.HasCookie(kCookie3));
283 TEST_ASSERT(!map.HasCookie(kCookie3 + kName2));
285 TEST_ASSERT(GetCookieString(STRING16(L"http://www.google.com/"),
286 &cookie_string));
287 ParseCookieString(cookie_string, &map);
289 LOG(("TestHttpCookies - passed\n"));
290 return true;
294 //------------------------------------------------------------------------------
295 // TestManifest
296 //------------------------------------------------------------------------------
297 bool TestManifest() {
298 #undef TEST_ASSERT
299 #define TEST_ASSERT(b) \
301 if (!(b)) { \
302 LOG(("TestManifest - failed (%d)\n", __LINE__)); \
303 return false; \
307 const char16 *manifest_url = STRING16(L"http://cc_tests/manifest.json");
308 const std::string16 expected_version = STRING16(L"expected_version");
309 const std::string16 expected_redirect(
310 STRING16(L"http://cc_tests.other_origin/redirectUrl"));
311 const char16 *json16 = STRING16(
312 L"{ 'betaManifestVersion': 1, \n"
313 L" 'version': 'expected_version', \n"
314 L" 'redirectUrl': 'http://cc_tests.other_origin/redirectUrl', \n"
315 L" 'entries': [ \n"
316 L" { 'url': 'test_url', 'src': 'test_src' }, \n"
317 L" { 'url': 'test_url2' }, \n"
318 L" { 'url': 'test_url3', 'ignoreQuery': true}, \n"
319 L" { 'url': 'test_redirect_url', 'redirect': 'test_url3?blah' } \n"
320 L" ] \n"
321 L"}");
323 std::string json8;
324 TEST_ASSERT(String16ToUTF8(json16, &json8));
325 ReplaceAll(json8, std::string("'"), std::string("\""));
327 Manifest manifest;
328 bool ok = manifest.Parse(manifest_url, json8.c_str(), json8.length());
329 TEST_ASSERT(ok);
330 TEST_ASSERT(manifest.IsValid());
331 TEST_ASSERT(expected_version == manifest.GetVersion());
332 TEST_ASSERT(expected_redirect == manifest.GetRedirectUrl());
333 TEST_ASSERT(manifest.GetEntries()->size() == 4);
335 const Manifest::Entry *entry1 = &manifest.GetEntries()->at(0);
336 TEST_ASSERT(entry1->url == STRING16(L"http://cc_tests/test_url"));
337 TEST_ASSERT(entry1->src == STRING16(L"http://cc_tests/test_src"));
338 TEST_ASSERT(entry1->redirect.empty());
339 TEST_ASSERT(!entry1->ignore_query);
341 const Manifest::Entry *entry2 = &manifest.GetEntries()->at(1);
342 TEST_ASSERT(entry2->url == STRING16(L"http://cc_tests/test_url2"));
343 TEST_ASSERT(entry2->src.empty());
344 TEST_ASSERT(entry2->redirect.empty());
346 const Manifest::Entry *entry3 = &manifest.GetEntries()->at(2);
347 TEST_ASSERT(entry3->url == STRING16(L"http://cc_tests/test_url3"));
348 TEST_ASSERT(entry3->src.empty());
349 TEST_ASSERT(entry3->redirect.empty());
350 TEST_ASSERT(entry3->ignore_query);
352 const Manifest::Entry *entry4 = &manifest.GetEntries()->at(3);
353 TEST_ASSERT(entry4->url == STRING16(L"http://cc_tests/test_redirect_url"));
354 TEST_ASSERT(entry4->src.empty());
355 TEST_ASSERT(entry4->redirect == STRING16(L"http://cc_tests/test_url3?blah"));
358 const char *json_not_an_object = "\"A string, but we need an object\"";
359 Manifest manifest_should_not_parse;
360 ok = manifest_should_not_parse.Parse(manifest_url, json_not_an_object);
361 TEST_ASSERT(!ok);
363 LOG(("TestManifest - passed\n"));
364 return true;
367 //------------------------------------------------------------------------------
368 // TestResourceStore
369 //------------------------------------------------------------------------------
370 bool TestResourceStore() {
371 #undef TEST_ASSERT
372 #define TEST_ASSERT(b) \
374 if (!(b)) { \
375 LOG(("TestResourceStore - failed (%d)\n", __LINE__)); \
376 return false; \
379 const char16 *name = STRING16(L"name");
380 const char16 *url1 = STRING16(L"http://cc_tests/url1");
381 const char16 *url2 = STRING16(L"http://cc_tests/url2");
382 const char16 *url3 = STRING16(L"http://cc_tests/url3");
383 const char16 *required_cookie = STRING16(L"required_cookie");
384 const char *data1 = "Hello world";
385 const char16 *headers1 =
386 STRING16(L"Content-Type: text/plain\r\nContent-Length: 11\r\n\r\n");
388 SecurityOrigin security_origin;
389 TEST_ASSERT(security_origin.InitFromUrl(url1));
391 ResourceStore wcs;
392 TEST_ASSERT(wcs.CreateOrOpen(security_origin, name, required_cookie));
394 ResourceStore::Item item1;
395 item1.entry.url = url1;
396 item1.payload.headers = headers1;
397 item1.payload.data.reset(new std::vector<uint8>);
398 item1.payload.data->assign(data1, data1 + strlen(data1));
399 item1.payload.status_line = STRING16(L"HTTP/1.0 200 OK");
400 item1.payload.status_code = HttpConstants::HTTP_OK;
401 TEST_ASSERT(wcs.PutItem(&item1));
403 TEST_ASSERT(wcs.IsCaptured(url1));
405 std::string16 headers;
406 TEST_ASSERT(wcs.GetAllHeaders(url1, &headers));
407 TEST_ASSERT(headers == item1.payload.headers);
409 std::string16 content_type;
410 TEST_ASSERT(wcs.GetHeader(url1, STRING16(L"Content-Type"), &content_type));
411 TEST_ASSERT(content_type == STRING16(L"text/plain"));
413 ResourceStore::Item test_item1;
414 TEST_ASSERT(wcs.GetItem(url1, &test_item1));
416 TEST_ASSERT(wcs.Copy(url1, url2));
418 ResourceStore::Item test_item2;
419 TEST_ASSERT(wcs.GetItem(url2, &test_item2));
420 TEST_ASSERT(test_item1.entry.id != test_item2.entry.id);
421 TEST_ASSERT(test_item1.entry.payload_id == test_item2.entry.payload_id);
422 TEST_ASSERT(test_item1.entry.src == test_item2.entry.src);
423 TEST_ASSERT(test_item1.entry.url != test_item2.entry.url);
424 TEST_ASSERT(test_item1.entry.version_id == test_item2.entry.version_id);
425 TEST_ASSERT(test_item1.payload.id == test_item2.payload.id);
426 TEST_ASSERT(test_item1.payload.creation_date ==
427 test_item2.payload.creation_date);
428 TEST_ASSERT(test_item1.payload.headers == test_item2.payload.headers);
429 TEST_ASSERT(test_item1.payload.status_line == test_item2.payload.status_line);
430 TEST_ASSERT(test_item1.payload.status_code == test_item2.payload.status_code);
432 TEST_ASSERT(wcs.Rename(url2, url3));
434 ResourceStore::Item test_item3;
435 TEST_ASSERT(wcs.GetItem(url3, &test_item3));
436 TEST_ASSERT(test_item3.entry.id == test_item2.entry.id);
437 TEST_ASSERT(test_item3.entry.payload_id == test_item2.entry.payload_id);
438 TEST_ASSERT(test_item3.entry.src == test_item2.entry.src);
439 TEST_ASSERT(test_item3.entry.url != test_item2.entry.url);
440 TEST_ASSERT(test_item3.entry.version_id == test_item2.entry.version_id);
441 TEST_ASSERT(test_item3.payload.id == test_item2.payload.id);
442 TEST_ASSERT(test_item3.payload.creation_date ==
443 test_item2.payload.creation_date);
444 TEST_ASSERT(test_item3.payload.headers == test_item2.payload.headers);
445 TEST_ASSERT(test_item3.payload.status_line == test_item2.payload.status_line);
446 TEST_ASSERT(test_item3.payload.status_code == test_item2.payload.status_code);
448 LOG(("TestResourceStore - passed\n"));
449 return true;
453 //------------------------------------------------------------------------------
454 // TestManagedResourceStore
455 //------------------------------------------------------------------------------
456 bool TestManagedResourceStore() {
457 #undef TEST_ASSERT
458 #define TEST_ASSERT(b) \
460 if (!(b)) { \
461 LOG(("TestManagedResourceStore - failed (%d)\n", __LINE__)); \
462 return false; \
466 const char *manifest1_json =
467 "{ \"betaManifestVersion\": 1, "
468 " \"version\": \"test_version\", "
469 " \"redirectUrl\": \"redirectUrl\", "
470 " \"entries\": [ "
471 " { \"url\": \"test_url\", \"src\": \"test_src\" }, "
472 " { \"url\": \"test_url2\" }, "
473 " { \"url\": \"test_url3\", \"ignoreQuery\": true } "
474 " ]"
475 "}";
477 const char16 *manifest_url = STRING16(L"http://cc_tests/manifest.json");
478 const char16 *name = STRING16(L"name");
479 const char16 *required_cookie = STRING16(L"user=joe");
481 SecurityOrigin security_origin;
482 TEST_ASSERT(security_origin.InitFromUrl(manifest_url));
484 // Clear out data from previous test runs
485 int64 existing_store_id = WebCacheDB::kInvalidID;
486 if (ManagedResourceStore::ExistsInDB(security_origin, name,
487 required_cookie, &existing_store_id)) {
488 ManagedResourceStore remover;
489 TEST_ASSERT(remover.Open(existing_store_id));
490 TEST_ASSERT(remover.Remove());
492 // Bring the ManagedResourceStore thru the states that it will go thru
493 // during an install / update process, and verify that it works as expected.
495 ManagedResourceStore app;
496 TEST_ASSERT(app.CreateOrOpen(security_origin, name, required_cookie));
498 // Ensure it looks freshly created
499 TEST_ASSERT(app.StillExistsInDB());
500 TEST_ASSERT(!app.HasVersion(WebCacheDB::VERSION_CURRENT));
501 TEST_ASSERT(!app.HasVersion(WebCacheDB::VERSION_DOWNLOADING));
503 // Test Get/Set UpdateInfo
504 WebCacheDB::UpdateStatus update_status;
505 int64 last_time;
506 TEST_ASSERT(app.GetUpdateInfo(&update_status, &last_time, NULL, NULL));
507 TEST_ASSERT(update_status == WebCacheDB::UPDATE_OK);
508 TEST_ASSERT(last_time == 0);
509 TEST_ASSERT(app.SetUpdateInfo(WebCacheDB::UPDATE_FAILED, 1, NULL, NULL));
510 TEST_ASSERT(app.GetUpdateInfo(&update_status, &last_time, NULL, NULL));
511 TEST_ASSERT(update_status == WebCacheDB::UPDATE_FAILED);
512 TEST_ASSERT(last_time == 1);
514 // Add a version in the "downloading" state
516 Manifest manifest1;
517 TEST_ASSERT(manifest1.Parse(manifest_url, manifest1_json));
519 int64 manifest1_version_id;
520 TEST_ASSERT(app.AddManifestAsDownloadingVersion(&manifest1,
521 &manifest1_version_id));
522 TEST_ASSERT(app.HasVersion(WebCacheDB::VERSION_DOWNLOADING));
524 std::string16 version_string;
525 TEST_ASSERT(app.GetVersionString(WebCacheDB::VERSION_DOWNLOADING,
526 &version_string));
527 TEST_ASSERT(version_string == manifest1.GetVersion());
529 // Transition to current
531 TEST_ASSERT(app.SetDownloadingVersionAsCurrent());
532 TEST_ASSERT(app.HasVersion(WebCacheDB::VERSION_CURRENT));
533 TEST_ASSERT(!app.HasVersion(WebCacheDB::VERSION_DOWNLOADING));
535 LOG(("TestManagedResourceStore - passed\n"));
536 return true;
539 //------------------------------------------------------------------------------
540 // TestLocalServerDB
541 //------------------------------------------------------------------------------
542 bool TestLocalServerDB() {
543 #undef TEST_ASSERT
544 #define TEST_ASSERT(b) \
546 if (!(b)) { \
547 LOG(("TestWebCacheDB - failed (%d)\n", __LINE__)); \
548 SetFakeCookieString(NULL, NULL); \
549 return false; \
553 const char16 *name = STRING16(L"name");
554 const char16 *required_cookie = STRING16(L"user=joe");
555 const char16 *testurl = STRING16(L"http://cc_tests/url");
557 SecurityOrigin security_origin;
558 TEST_ASSERT(security_origin.InitFromUrl(testurl));
560 WebCacheDB *db = WebCacheDB::GetDB();
561 TEST_ASSERT(db);
563 // delete existing info from a previous test run
564 WebCacheDB::ServerInfo existing_server;
565 if (db->FindServer(security_origin, name, required_cookie,
566 WebCacheDB::MANAGED_RESOURCE_STORE,
567 &existing_server)) {
568 db->DeleteServer(existing_server.id);
571 // insert a server
572 WebCacheDB::ServerInfo server;
573 server.server_type = WebCacheDB::MANAGED_RESOURCE_STORE;
574 server.security_origin_url = security_origin.url();
575 server.name = name;
576 server.required_cookie = required_cookie;
577 server.manifest_url = STRING16(L"http://cc_tests/manifest_url");
578 TEST_ASSERT(db->InsertServer(&server));
580 // insert a current version1 that specifies a redirect
581 WebCacheDB::VersionInfo version1;
582 version1.server_id = server.id;
583 version1.version_string = STRING16(L"version_string");
584 version1.ready_state = WebCacheDB::VERSION_CURRENT;
585 version1.session_redirect_url = STRING16(L"http://cc_tests/redirect_url");
586 TEST_ASSERT(db->InsertVersion(&version1));
588 // insert an entry with a bogus payload id for the current version
589 WebCacheDB::EntryInfo entry;
590 entry.version_id = version1.id;
591 entry.url = testurl;
592 entry.payload_id = kint64max;
593 TEST_ASSERT(db->InsertEntry(&entry));
595 // we should be able to service a request for testurl, the response
596 // should redirect to our session_redirect_url
597 SetFakeCookieString(testurl, NULL);
598 TEST_ASSERT(db->CanService(testurl));
600 WebCacheDB::PayloadInfo payload;
601 TEST_ASSERT(db->Service(testurl, true, &payload));
602 TEST_ASSERT(payload.IsHttpRedirect());
603 std::string16 test_redirect_url;
604 TEST_ASSERT(payload.GetHeader(HttpConstants::kLocationHeader,
605 &test_redirect_url) &&
606 test_redirect_url == version1.session_redirect_url);
608 // insert a downloaded version2 w/o a redirect
609 WebCacheDB::VersionInfo version2;
610 version2.server_id = server.id;
611 version2.version_string = STRING16(L"version_string2");
612 version2.ready_state = WebCacheDB::VERSION_DOWNLOADING;
613 TEST_ASSERT(db->InsertVersion(&version2));
615 // insert an entry for version2
616 WebCacheDB::EntryInfo entry2;
617 entry2.version_id = version2.id;
618 entry2.url = testurl;
619 entry2.payload_id = kint64max;
620 TEST_ASSERT(db->InsertEntry(&entry2));
622 // we should still be able to service a request for testurl from version1
623 TEST_ASSERT(db->CanService(testurl));
625 // delete version1
626 TEST_ASSERT(db->DeleteVersion(version1.id));
628 // we shouldn't be able to service a request for testurl
629 TEST_ASSERT(!db->CanService(testurl));
631 // now make the ready version current
632 TEST_ASSERT(db->UpdateVersion(version2.id, WebCacheDB::VERSION_CURRENT));
634 // we should still not be able to service a request for testurl as there
635 // is no session yet and version2 does not have a redirect_url
636 TEST_ASSERT(!db->CanService(testurl));
638 // now set the required cookie (fake)
639 SetFakeCookieString(testurl, required_cookie);
641 // we should be able to service a request for testurl again
642 TEST_ASSERT(db->CanService(testurl));
644 // clear the cookie string for our testurl (fake)
645 SetFakeCookieString(testurl, NULL);
647 // off again
648 TEST_ASSERT(!db->CanService(testurl));
650 // delete version2
651 TEST_ASSERT(db->DeleteVersion(version2.id));
653 // insert version3 for that server that requires a session and has a redirect
654 WebCacheDB::VersionInfo version3;
655 version3.server_id = server.id;
656 version3.version_string = STRING16(L"version_string3");
657 version3.ready_state = WebCacheDB::VERSION_CURRENT;
658 version3.session_redirect_url = STRING16(
659 L"http://cc_tests/session_redirect_url");
660 TEST_ASSERT(db->InsertVersion(&version3));
662 // insert an entry for the ready version
663 WebCacheDB::EntryInfo entry3;
664 entry3.version_id = version3.id;
665 entry3.url = testurl;
666 entry3.ignore_query = true;
667 entry3.payload_id = kint64max;
668 TEST_ASSERT(db->InsertEntry(&entry3));
670 // this entry s/b hit for request with arbitrary query parameters
671 std::string16 testurl_query(testurl);
672 testurl_query += STRING16(L"?blah");
674 // on again, s/b responding with redirects
675 SetFakeCookieString(testurl, NULL);
676 TEST_ASSERT(db->CanService(testurl));
677 SetFakeCookieString(testurl_query.c_str(), NULL);
678 TEST_ASSERT(db->CanService(testurl_query.c_str()));
680 // still on, s/b responding with payloads
681 SetFakeCookieString(testurl, required_cookie);
682 TEST_ASSERT(db->CanService(testurl));
683 SetFakeCookieString(testurl_query.c_str(), required_cookie);
684 TEST_ASSERT(db->CanService(testurl_query.c_str()));
686 // delete the server altogether
687 TEST_ASSERT(db->DeleteServer(server.id));
689 // we shouldn't be able to service a request for the test url
690 TEST_ASSERT(!db->CanService(testurl));
691 TEST_ASSERT(!db->CanService(testurl_query.c_str()));
693 SetFakeCookieString(NULL, NULL);
695 // we made it thru as expected
696 LOG(("TestWebCacheDB - passed\n"));
697 return true;
700 bool TestParseHttpStatusLine() {
701 #undef TEST_ASSERT
702 #define TEST_ASSERT(b) \
704 if (!(b)) { \
705 LOG(("TestParseHttpStatusLine - failed (%d)\n", __LINE__)); \
706 return false; \
709 std::string16 good(STRING16(L"HTTP/1.1 200 OK"));
710 std::string16 version, text;
711 int code;
712 TEST_ASSERT(ParseHttpStatusLine(good, &version, &code, &text));
713 TEST_ASSERT(version == STRING16(L"HTTP/1.1"));
714 TEST_ASSERT(code == 200);
715 TEST_ASSERT(text == STRING16(L"OK"));
716 TEST_ASSERT(ParseHttpStatusLine(good, &version, NULL, NULL));
717 TEST_ASSERT(ParseHttpStatusLine(good, NULL, &code, NULL));
718 TEST_ASSERT(ParseHttpStatusLine(good, NULL, NULL, &text));
720 const char16 *acceptable[] = {
721 STRING16(L"HTTP/1.0 200"), // no status
722 STRING16(L"HTTP 200 ABBREVIATED VERSION"),
723 STRING16(L"HTTP/1.1 500 REASON: CONTAINING COLON")
725 for (size_t i = 0; i < ARRAYSIZE(acceptable); ++i) {
726 std::string16 acceptable_str(acceptable[i]);
727 TEST_ASSERT(ParseHttpStatusLine(acceptable_str, NULL, NULL, NULL));
730 const char16 *bad[] = {
731 STRING16(L" HTTP/1.1 200 SPACE AT START"),
732 STRING16(L"WTFP/1.1 200 WRONG SCHEME"),
733 STRING16(L"HTTP/1.1 2 CODE TOO SMALL"),
734 STRING16(L"HTTP/1.0 2000 CODE TOO BIG"),
735 STRING16(L"HTTP/1.0 NO CODE"),
736 STRING16(L"complete_gibberish"),
737 STRING16(L""), // an empty string
738 STRING16(L" \t \t "), // whitespace only
740 for (size_t i = 0; i < ARRAYSIZE(bad); ++i) {
741 std::string16 bad_str(bad[i]);
742 TEST_ASSERT(!ParseHttpStatusLine(bad_str, NULL, NULL, NULL));
744 LOG(("TestParseHttpStatusLine - passed\n"));
745 return true;
749 class TestHttpRequestListener : public HttpRequest::ReadyStateListener {
750 virtual void ReadyStateChanged(HttpRequest *source) {
751 HttpRequest::ReadyState state = HttpRequest::UNINITIALIZED;
752 source->GetReadyState(&state);
753 if (state == HttpRequest::COMPLETE) {
754 int status = 0;
755 std::string16 headers;
756 std::string16 body;
757 source->GetStatus(&status);
758 source->GetAllResponseHeaders(&headers);
759 source->GetResponseBodyAsText(&body);
760 source->SetOnReadyStateChange(NULL);
761 source->ReleaseReference();
762 delete this;
763 LOG(("TestHttpRequest - complete (%d)\n", status));
768 #ifdef BROWSER_FF
769 // Returns true if the currently executing thread is the main UI thread,
770 // firefox/mozila has one such very special thread
771 // See cache_intercept.cc for implementation
772 bool IsUiThread();
773 #endif
775 bool TestHttpRequest() {
776 #undef TEST_ASSERT
777 #define TEST_ASSERT(b) \
779 if (!(b)) { \
780 LOG(("TestHttpRequest - failed (%d)\n", __LINE__)); \
781 return false; \
785 #ifdef BROWSER_FF
786 if (!IsUiThread()) {
787 return true;
789 #endif
791 // A request is created with a refcount of one, our listener will
792 // release this reference upon completion. If something goes wrong
793 // we leak, not good in a real program but fine for this test.
795 // Send a request synchronously
796 HttpRequest *request = HttpRequest::Create();
797 request->SetOnReadyStateChange(new TestHttpRequestListener());
798 bool ok = request->Open(HttpConstants::kHttpGET,
799 STRING16(L"http://www.google.com/"),
800 false);
801 TEST_ASSERT(ok);
802 ok = request->Send();
803 TEST_ASSERT(ok);
805 // Send an async request
806 request = HttpRequest::Create();
807 request->SetOnReadyStateChange(new TestHttpRequestListener());
808 ok = request->Open(HttpConstants::kHttpGET,
809 STRING16(L"http://www.google.com/"),
810 true);
811 TEST_ASSERT(ok);
812 ok = request->Send();
813 TEST_ASSERT(ok);
814 return true;
817 #ifndef OFFICIAL_BUILD
818 // The blob API has not been finalized for official builds
819 bool TestBufferBlob() {
820 #undef TEST_ASSERT
821 #define TEST_ASSERT(b) \
823 if (!(b)) { \
824 printf("TestBufferBlob - failed (%d)\n", __LINE__); \
825 return false; \
828 #if BROWSER_FF || BROWSER_IE // blobs not implemented for npapi yet
829 int num_bytes = 0;
830 uint8 buffer[64] = {0};
832 // Empty blob tests
833 BufferBlob blob1;
834 TEST_ASSERT(blob1.Length() == 0);
835 num_bytes = blob1.Read(buffer, 64, 0);
836 TEST_ASSERT(num_bytes == 0); // a non-finalized blob is not readable
837 blob1.Finalize();
838 TEST_ASSERT(blob1.Length() == 0);
839 num_bytes = blob1.Read(buffer, 64, 0);
840 TEST_ASSERT(num_bytes == 0); // because it's actually empty
841 num_bytes = blob1.Append("abc", 3);
842 TEST_ASSERT(num_bytes == 0); // a finalized blob is not writable
844 memset(buffer, 0, sizeof(buffer));
846 // Typical blob operation
847 BufferBlob blob2;
848 num_bytes = blob2.Append("abc", 3);
849 TEST_ASSERT(num_bytes == 3);
850 TEST_ASSERT(blob2.Length() == 3);
851 num_bytes = blob2.Append("de", 2);
852 TEST_ASSERT(num_bytes == 2);
853 TEST_ASSERT(blob2.Length() == 5);
854 num_bytes = blob2.Read(buffer, 64, 0);
855 TEST_ASSERT(num_bytes == 0); // a non-finalized blob is not readable
856 blob2.Finalize();
857 TEST_ASSERT(blob2.Length() == 5);
858 num_bytes = blob2.Read(buffer, 64, 0);
859 TEST_ASSERT(num_bytes == 5);
860 num_bytes = blob2.Append("fgh", 3);
861 TEST_ASSERT(num_bytes == 0); // a finalized blob is not writable
862 TEST_ASSERT(buffer[0] == 'a');
863 TEST_ASSERT(buffer[1] == 'b');
864 TEST_ASSERT(buffer[2] == 'c');
865 TEST_ASSERT(buffer[3] == 'd');
866 TEST_ASSERT(buffer[4] == 'e');
867 TEST_ASSERT(buffer[5] == '\0');
869 // Overwrite the first three bytes of buffer, but don't touch the rest
870 num_bytes = blob2.Read(buffer, 3, 2);
871 TEST_ASSERT(num_bytes == 3);
872 TEST_ASSERT(buffer[0] == 'c');
873 TEST_ASSERT(buffer[1] == 'd');
874 TEST_ASSERT(buffer[2] == 'e');
875 TEST_ASSERT(buffer[3] == 'd');
876 TEST_ASSERT(buffer[4] == 'e');
878 // Initialize a blob with an empty vector
879 std::vector<uint8> *vec3 = new std::vector<uint8>;
880 BufferBlob blob3(vec3);
881 TEST_ASSERT(blob1.Length() == 0);
882 num_bytes = blob1.Read(buffer, 64, 0);
883 TEST_ASSERT(num_bytes == 0);
885 memset(buffer, 0, sizeof(buffer));
887 // Initialize a blob with a typical vector
888 std::vector<uint8> *vec4 = new std::vector<uint8>;
889 vec4->push_back('a');
890 vec4->push_back('b');
891 vec4->push_back('c');
892 BufferBlob blob4(vec4);
893 TEST_ASSERT(blob4.Length() == 3);
894 num_bytes = blob4.Read(buffer, 64, 0);
895 TEST_ASSERT(num_bytes == 3);
896 TEST_ASSERT(buffer[0] == 'a');
897 TEST_ASSERT(buffer[1] == 'b');
898 TEST_ASSERT(buffer[2] == 'c');
899 #endif
901 return true;
904 #endif // not OFFICIAL_BUILD
906 #endif // DEBUG