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
);
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
);
47 #include <windows.h> // must manually #include before nsIEventQueueService.h
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"
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();
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();
93 context
->SetException(GET_INTERNAL_ERROR_MESSAGE());
97 permissions
->SetCanAccessGears(cc_tests_origin
,
98 PermissionsDB::PERMISSION_ALLOWED
);
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 //------------------------------------------------------------------------------
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
) {
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
) {
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
) {
174 double expected_value
;
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
) {
191 std::string16 expected_value
;
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
) {
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;
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
) {
230 context
->SetReturnValue(JSPARAM_BOOL
, &ok
);
233 //------------------------------------------------------------------------------
235 //------------------------------------------------------------------------------
236 bool TestHttpCookies() {
238 #define TEST_ASSERT(b) \
241 LOG(("TestHttpCookies - failed (%d)\n", __LINE__)); \
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"));
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/"),
287 ParseCookieString(cookie_string
, &map
);
289 LOG(("TestHttpCookies - passed\n"));
294 //------------------------------------------------------------------------------
296 //------------------------------------------------------------------------------
297 bool TestManifest() {
299 #define TEST_ASSERT(b) \
302 LOG(("TestManifest - failed (%d)\n", __LINE__)); \
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"
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"
324 TEST_ASSERT(String16ToUTF8(json16
, &json8
));
325 ReplaceAll(json8
, std::string("'"), std::string("\""));
328 bool ok
= manifest
.Parse(manifest_url
, json8
.c_str(), json8
.length());
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
);
363 LOG(("TestManifest - passed\n"));
367 //------------------------------------------------------------------------------
369 //------------------------------------------------------------------------------
370 bool TestResourceStore() {
372 #define TEST_ASSERT(b) \
375 LOG(("TestResourceStore - failed (%d)\n", __LINE__)); \
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
));
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"));
453 //------------------------------------------------------------------------------
454 // TestManagedResourceStore
455 //------------------------------------------------------------------------------
456 bool TestManagedResourceStore() {
458 #define TEST_ASSERT(b) \
461 LOG(("TestManagedResourceStore - failed (%d)\n", __LINE__)); \
466 const char *manifest1_json
=
467 "{ \"betaManifestVersion\": 1, "
468 " \"version\": \"test_version\", "
469 " \"redirectUrl\": \"redirectUrl\", "
471 " { \"url\": \"test_url\", \"src\": \"test_src\" }, "
472 " { \"url\": \"test_url2\" }, "
473 " { \"url\": \"test_url3\", \"ignoreQuery\": true } "
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
;
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
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
,
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"));
539 //------------------------------------------------------------------------------
541 //------------------------------------------------------------------------------
542 bool TestLocalServerDB() {
544 #define TEST_ASSERT(b) \
547 LOG(("TestWebCacheDB - failed (%d)\n", __LINE__)); \
548 SetFakeCookieString(NULL, NULL); \
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();
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
,
568 db
->DeleteServer(existing_server
.id
);
572 WebCacheDB::ServerInfo server
;
573 server
.server_type
= WebCacheDB::MANAGED_RESOURCE_STORE
;
574 server
.security_origin_url
= security_origin
.url();
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
;
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
));
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
);
648 TEST_ASSERT(!db
->CanService(testurl
));
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"));
700 bool TestParseHttpStatusLine() {
702 #define TEST_ASSERT(b) \
705 LOG(("TestParseHttpStatusLine - failed (%d)\n", __LINE__)); \
709 std::string16
good(STRING16(L
"HTTP/1.1 200 OK"));
710 std::string16 version
, text
;
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"));
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
) {
755 std::string16 headers
;
757 source
->GetStatus(&status
);
758 source
->GetAllResponseHeaders(&headers
);
759 source
->GetResponseBodyAsText(&body
);
760 source
->SetOnReadyStateChange(NULL
);
761 source
->ReleaseReference();
763 LOG(("TestHttpRequest - complete (%d)\n", status
));
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
775 bool TestHttpRequest() {
777 #define TEST_ASSERT(b) \
780 LOG(("TestHttpRequest - failed (%d)\n", __LINE__)); \
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/"),
802 ok
= request
->Send();
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/"),
812 ok
= request
->Send();
817 #ifndef OFFICIAL_BUILD
818 // The blob API has not been finalized for official builds
819 bool TestBufferBlob() {
821 #define TEST_ASSERT(b) \
824 printf("TestBufferBlob - failed (%d)\n", __LINE__); \
828 #if BROWSER_FF || BROWSER_IE // blobs not implemented for npapi yet
830 uint8 buffer
[64] = {0};
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
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
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
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');
904 #endif // not OFFICIAL_BUILD