Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/metrics/field_trial.h" | |
| 5 #include "base/strings/stringprintf.h" | 6 #include "base/strings/stringprintf.h" |
| 6 #include "base/synchronization/waitable_event.h" | 7 #include "base/synchronization/waitable_event.h" |
| 8 #include "base/test/mock_entropy_provider.h" | |
| 7 #include "base/threading/thread.h" | 9 #include "base/threading/thread.h" |
| 8 #include "net/http/http_response_headers.h" | 10 #include "net/http/http_response_headers.h" |
| 9 #include "net/test/spawned_test_server/spawned_test_server.h" | 11 #include "net/test/spawned_test_server/spawned_test_server.h" |
| 10 #include "net/url_request/test_url_fetcher_factory.h" | 12 #include "net/url_request/test_url_fetcher_factory.h" |
| 11 #include "net/url_request/url_fetcher_delegate.h" | 13 #include "net/url_request/url_fetcher_delegate.h" |
| 12 #include "net/url_request/url_request_test_util.h" | 14 #include "net/url_request/url_request_test_util.h" |
| 13 #include "sync/internal_api/public/base/cancelation_signal.h" | 15 #include "sync/internal_api/public/base/cancelation_signal.h" |
| 14 #include "sync/internal_api/public/http_bridge.h" | 16 #include "sync/internal_api/public/http_bridge.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 #include "third_party/zlib/zlib.h" | |
| 16 | 19 |
| 17 namespace syncer { | 20 namespace syncer { |
| 18 | 21 |
| 19 namespace { | 22 namespace { |
|
Alexei Svitkine (slow)
2015/08/03 18:12:30
Nit: Add an empty line after this.
Gang Wu
2015/08/04 22:14:00
Done.
| |
| 20 // TODO(timsteele): Should use PathService here. See Chromium Issue 3113. | 23 // TODO(timsteele): Should use PathService here. See Chromium Issue 3113. |
| 21 const base::FilePath::CharType kDocRoot[] = | 24 const base::FilePath::CharType kDocRoot[] = |
| 22 FILE_PATH_LITERAL("chrome/test/data"); | 25 FILE_PATH_LITERAL("chrome/test/data"); |
| 26 | |
| 27 // ----------------------------------------------------------------------------- | |
| 28 // he rest of the code in the anon namespace is copied from | |
| 29 // components/metrics/compression_utils.cc | |
| 30 // TODO(gangwu): crbug.com/515695. The following codes are copied from | |
| 31 // components/metrics/compression_utils.cc, we copied them because if we | |
| 32 // reference them, we will get cycle dependency warning. Once the functions | |
| 33 // have been moved from //component to //base, we can remove the following | |
| 34 // functions. | |
| 35 //------------------------------------------------------------------------------ | |
| 36 // Pass an integer greater than the following get a gzip header instead of a | |
| 37 // zlib header when calling deflateInit2() and inflateInit2(). | |
| 38 const int kWindowBitsToGetGzipHeader = 16; | |
| 39 | |
| 40 // This code is taken almost verbatim from third_party/zlib/uncompr.c. The only | |
| 41 // difference is inflateInit2() is called which sets the window bits to be > 16. | |
| 42 // That causes a gzip header to be parsed rather than a zlib header. | |
| 43 int GzipUncompressHelper(Bytef* dest, | |
| 44 uLongf* dest_length, | |
| 45 const Bytef* source, | |
| 46 uLong source_length) { | |
| 47 z_stream stream; | |
| 48 | |
| 49 stream.next_in = bit_cast<Bytef*>(source); | |
| 50 stream.avail_in = static_cast<uInt>(source_length); | |
| 51 if (static_cast<uLong>(stream.avail_in) != source_length) | |
| 52 return Z_BUF_ERROR; | |
| 53 | |
| 54 stream.next_out = dest; | |
| 55 stream.avail_out = static_cast<uInt>(*dest_length); | |
| 56 if (static_cast<uLong>(stream.avail_out) != *dest_length) | |
| 57 return Z_BUF_ERROR; | |
| 58 | |
| 59 stream.zalloc = static_cast<alloc_func>(0); | |
| 60 stream.zfree = static_cast<free_func>(0); | |
| 61 | |
| 62 int err = inflateInit2(&stream, MAX_WBITS + kWindowBitsToGetGzipHeader); | |
| 63 if (err != Z_OK) | |
| 64 return err; | |
| 65 | |
| 66 err = inflate(&stream, Z_FINISH); | |
| 67 if (err != Z_STREAM_END) { | |
| 68 inflateEnd(&stream); | |
| 69 if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) | |
| 70 return Z_DATA_ERROR; | |
| 71 return err; | |
| 72 } | |
| 73 *dest_length = stream.total_out; | |
| 74 | |
| 75 err = inflateEnd(&stream); | |
| 76 return err; | |
| 77 } | |
| 78 | |
| 79 // Returns the uncompressed size from GZIP-compressed |compressed_data|. | |
| 80 uint32 GetUncompressedSize(const std::string& compressed_data) { | |
| 81 // The uncompressed size is stored in the last 4 bytes of |input| in LE. | |
| 82 uint32 size; | |
| 83 if (compressed_data.length() < sizeof(size)) | |
| 84 return 0; | |
| 85 memcpy(&size, &compressed_data[compressed_data.length() - sizeof(size)], | |
| 86 sizeof(size)); | |
| 87 return base::ByteSwapToLE32(size); | |
| 88 } | |
| 89 | |
| 90 bool GzipUncompress(const std::string& input, std::string* output) { | |
| 91 std::string uncompressed_output; | |
| 92 uLongf uncompressed_size = static_cast<uLongf>(GetUncompressedSize(input)); | |
| 93 uncompressed_output.resize(uncompressed_size); | |
| 94 if (GzipUncompressHelper(bit_cast<Bytef*>(uncompressed_output.data()), | |
| 95 &uncompressed_size, | |
| 96 bit_cast<const Bytef*>(input.data()), | |
| 97 static_cast<uLongf>(input.length())) == Z_OK) { | |
| 98 output->swap(uncompressed_output); | |
| 99 return true; | |
| 100 } | |
| 101 return false; | |
| 102 } | |
|
Alexei Svitkine (slow)
2015/08/03 18:12:30
Nit: Add an empty line after this.
Gang Wu
2015/08/04 22:14:00
Done.
| |
| 23 } | 103 } |
|
Alexei Svitkine (slow)
2015/08/03 18:12:30
Nit: // namespace
Gang Wu
2015/08/04 22:14:00
Done.
| |
| 24 | 104 |
| 25 const char kUserAgent[] = "user-agent"; | 105 const char kUserAgent[] = "user-agent"; |
| 26 | 106 |
| 27 class SyncHttpBridgeTest : public testing::Test { | 107 class SyncHttpBridgeTest : public testing::Test { |
| 28 public: | 108 public: |
| 29 SyncHttpBridgeTest() | 109 SyncHttpBridgeTest() |
| 30 : test_server_(net::SpawnedTestServer::TYPE_HTTP, | 110 : test_server_(net::SpawnedTestServer::TYPE_HTTP, |
| 31 net::SpawnedTestServer::kLocalhost, | 111 net::SpawnedTestServer::kLocalhost, |
| 32 base::FilePath(kDocRoot)), | 112 base::FilePath(kDocRoot)), |
| 33 fake_default_request_context_getter_(NULL), | 113 fake_default_request_context_getter_(NULL), |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 private: | 219 private: |
| 140 ~ShuntedHttpBridge() override {} | 220 ~ShuntedHttpBridge() override {} |
| 141 | 221 |
| 142 void CallOnURLFetchComplete() { | 222 void CallOnURLFetchComplete() { |
| 143 ASSERT_TRUE(base::MessageLoop::current() == test_->GetIOThreadLoop()); | 223 ASSERT_TRUE(base::MessageLoop::current() == test_->GetIOThreadLoop()); |
| 144 // We return no cookies and a dummy content response. | 224 // We return no cookies and a dummy content response. |
| 145 net::ResponseCookies cookies; | 225 net::ResponseCookies cookies; |
| 146 | 226 |
| 147 std::string response_content = "success!"; | 227 std::string response_content = "success!"; |
| 148 net::TestURLFetcher fetcher(0, GURL("http://www.google.com"), NULL); | 228 net::TestURLFetcher fetcher(0, GURL("http://www.google.com"), NULL); |
| 229 scoped_refptr<net::HttpResponseHeaders> response_headers( | |
| 230 new net::HttpResponseHeaders("")); | |
| 149 fetcher.set_response_code(200); | 231 fetcher.set_response_code(200); |
| 150 fetcher.set_cookies(cookies); | 232 fetcher.set_cookies(cookies); |
| 151 fetcher.SetResponseString(response_content); | 233 fetcher.SetResponseString(response_content); |
| 234 fetcher.set_response_headers(response_headers); | |
| 152 OnURLFetchComplete(&fetcher); | 235 OnURLFetchComplete(&fetcher); |
| 153 } | 236 } |
| 154 SyncHttpBridgeTest* test_; | 237 SyncHttpBridgeTest* test_; |
| 155 bool never_finishes_; | 238 bool never_finishes_; |
| 156 }; | 239 }; |
| 157 | 240 |
| 158 void SyncHttpBridgeTest::RunSyncThreadBridgeUseTest( | 241 void SyncHttpBridgeTest::RunSyncThreadBridgeUseTest( |
| 159 base::WaitableEvent* signal_when_created, | 242 base::WaitableEvent* signal_when_created, |
| 160 base::WaitableEvent* signal_when_released) { | 243 base::WaitableEvent* signal_when_released) { |
| 161 scoped_refptr<net::URLRequestContextGetter> ctx_getter( | 244 scoped_refptr<net::URLRequestContextGetter> ctx_getter( |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code); | 308 bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code); |
| 226 EXPECT_TRUE(success); | 309 EXPECT_TRUE(success); |
| 227 EXPECT_EQ(200, response_code); | 310 EXPECT_EQ(200, response_code); |
| 228 EXPECT_EQ(0, os_error); | 311 EXPECT_EQ(0, os_error); |
| 229 | 312 |
| 230 EXPECT_EQ(payload.length() + 1, | 313 EXPECT_EQ(payload.length() + 1, |
| 231 static_cast<size_t>(http_bridge->GetResponseContentLength())); | 314 static_cast<size_t>(http_bridge->GetResponseContentLength())); |
| 232 EXPECT_EQ(payload, std::string(http_bridge->GetResponseContent())); | 315 EXPECT_EQ(payload, std::string(http_bridge->GetResponseContent())); |
| 233 } | 316 } |
| 234 | 317 |
| 318 // Full round-trip test of the HttpBridge with compressed data, check if the | |
| 319 // data is correctly compressed. | |
| 320 TEST_F(SyncHttpBridgeTest, CompressedRequestPayloadCheck) { | |
| 321 ASSERT_TRUE(test_server_.Start()); | |
| 322 | |
| 323 scoped_refptr<HttpBridge> http_bridge(BuildBridge()); | |
| 324 | |
| 325 std::string payload = "this should be echoed back"; | |
| 326 GURL echo = test_server_.GetURL("echo"); | |
| 327 http_bridge->SetURL(echo.spec().c_str(), echo.IntPort()); | |
| 328 http_bridge->SetPostPayload("application/x-www-form-urlencoded", | |
| 329 payload.length(), payload.c_str()); | |
| 330 int os_error = 0; | |
| 331 int response_code = 0; | |
| 332 base::FieldTrialList field_trial_list(new base::MockEntropyProvider()); | |
| 333 base::FieldTrialList::CreateFieldTrial("SyncHttpContentCompression", | |
| 334 "Enabled"); | |
| 335 bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code); | |
| 336 EXPECT_TRUE(success); | |
| 337 EXPECT_EQ(200, response_code); | |
| 338 EXPECT_EQ(0, os_error); | |
| 339 | |
| 340 EXPECT_NE(payload.length() + 1, | |
| 341 static_cast<size_t>(http_bridge->GetResponseContentLength())); | |
| 342 std::string compressed_payload(http_bridge->GetResponseContent(), | |
| 343 http_bridge->GetResponseContentLength()); | |
| 344 std::string uncompressed_payload; | |
| 345 GzipUncompress(compressed_payload, &uncompressed_payload); | |
| 346 EXPECT_EQ(payload, uncompressed_payload); | |
| 347 } | |
| 348 | |
| 349 // Full round-trip test of the HttpBridge with compression, check if header | |
| 350 // fields("Content-Encoding" ,"Accept-Encoding" and user agent) are set | |
| 351 // correctly. | |
| 352 TEST_F(SyncHttpBridgeTest, CompressedRequestHeaderCheck) { | |
| 353 ASSERT_TRUE(test_server_.Start()); | |
| 354 | |
| 355 scoped_refptr<HttpBridge> http_bridge(BuildBridge()); | |
| 356 | |
| 357 GURL echo_header = test_server_.GetURL("echoall"); | |
| 358 http_bridge->SetURL(echo_header.spec().c_str(), echo_header.IntPort()); | |
| 359 | |
| 360 std::string test_payload = "###TEST PAYLOAD###"; | |
| 361 http_bridge->SetPostPayload("text/html", test_payload.length() + 1, | |
| 362 test_payload.c_str()); | |
| 363 | |
| 364 int os_error = 0; | |
| 365 int response_code = 0; | |
| 366 base::FieldTrialList field_trial_list(new base::MockEntropyProvider()); | |
| 367 base::FieldTrialList::CreateFieldTrial("SyncHttpContentCompression", | |
| 368 "Enabled"); | |
| 369 bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code); | |
| 370 EXPECT_TRUE(success); | |
| 371 EXPECT_EQ(200, response_code); | |
| 372 EXPECT_EQ(0, os_error); | |
| 373 | |
| 374 std::string response(http_bridge->GetResponseContent(), | |
| 375 http_bridge->GetResponseContentLength()); | |
| 376 EXPECT_NE(std::string::npos, response.find("Content-Encoding: gzip")); | |
| 377 EXPECT_NE(std::string::npos, response.find("Accept-Encoding: gzip, deflate")); | |
| 378 EXPECT_NE(std::string::npos, | |
| 379 response.find(base::StringPrintf( | |
| 380 "%s: %s", net::HttpRequestHeaders::kUserAgent, kUserAgent))); | |
| 381 } | |
| 382 | |
| 235 // Full round-trip test of the HttpBridge. | 383 // Full round-trip test of the HttpBridge. |
| 236 TEST_F(SyncHttpBridgeTest, TestMakeSynchronousPostLiveComprehensive) { | 384 TEST_F(SyncHttpBridgeTest, TestMakeSynchronousPostLiveComprehensive) { |
| 237 ASSERT_TRUE(test_server_.Start()); | 385 ASSERT_TRUE(test_server_.Start()); |
| 238 | 386 |
| 239 scoped_refptr<HttpBridge> http_bridge(BuildBridge()); | 387 scoped_refptr<HttpBridge> http_bridge(BuildBridge()); |
| 240 | 388 |
| 241 GURL echo_header = test_server_.GetURL("echoall"); | 389 GURL echo_header = test_server_.GetURL("echoall"); |
| 242 http_bridge->SetURL(echo_header.spec().c_str(), echo_header.IntPort()); | 390 http_bridge->SetURL(echo_header.spec().c_str(), echo_header.IntPort()); |
| 243 | 391 |
| 244 std::string test_payload = "###TEST PAYLOAD###"; | 392 std::string test_payload = "###TEST PAYLOAD###"; |
| 245 http_bridge->SetPostPayload("text/html", test_payload.length() + 1, | 393 http_bridge->SetPostPayload("text/html", test_payload.length() + 1, |
| 246 test_payload.c_str()); | 394 test_payload.c_str()); |
| 247 | 395 |
| 248 int os_error = 0; | 396 int os_error = 0; |
| 249 int response_code = 0; | 397 int response_code = 0; |
| 250 bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code); | 398 bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code); |
| 251 EXPECT_TRUE(success); | 399 EXPECT_TRUE(success); |
| 252 EXPECT_EQ(200, response_code); | 400 EXPECT_EQ(200, response_code); |
| 253 EXPECT_EQ(0, os_error); | 401 EXPECT_EQ(0, os_error); |
| 254 | 402 |
| 255 std::string response(http_bridge->GetResponseContent(), | 403 std::string response(http_bridge->GetResponseContent(), |
| 256 http_bridge->GetResponseContentLength()); | 404 http_bridge->GetResponseContentLength()); |
| 257 EXPECT_EQ(std::string::npos, response.find("Cookie:")); | 405 EXPECT_EQ(std::string::npos, response.find("Cookie:")); |
| 406 EXPECT_NE(std::string::npos, response.find("Accept-Encoding: deflate")); | |
| 258 EXPECT_NE(std::string::npos, | 407 EXPECT_NE(std::string::npos, |
| 259 response.find(base::StringPrintf("%s: %s", | 408 response.find(base::StringPrintf("%s: %s", |
| 260 net::HttpRequestHeaders::kUserAgent, kUserAgent))); | 409 net::HttpRequestHeaders::kUserAgent, kUserAgent))); |
| 261 EXPECT_NE(std::string::npos, response.find(test_payload.c_str())); | 410 EXPECT_NE(std::string::npos, response.find(test_payload.c_str())); |
| 262 } | 411 } |
| 263 | 412 |
| 264 TEST_F(SyncHttpBridgeTest, TestExtraRequestHeaders) { | 413 TEST_F(SyncHttpBridgeTest, TestExtraRequestHeaders) { |
| 265 ASSERT_TRUE(test_server_.Start()); | 414 ASSERT_TRUE(test_server_.Start()); |
| 266 | 415 |
| 267 scoped_refptr<HttpBridge> http_bridge(BuildBridge()); | 416 scoped_refptr<HttpBridge> http_bridge(BuildBridge()); |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 512 | 661 |
| 513 // Sync thread: Finally run the posted task, only to find that our | 662 // Sync thread: Finally run the posted task, only to find that our |
| 514 // HttpBridgeFactory has been neutered. Should not crash. | 663 // HttpBridgeFactory has been neutered. Should not crash. |
| 515 factory->Init("TestUserAgent"); | 664 factory->Init("TestUserAgent"); |
| 516 | 665 |
| 517 // At this point, attempting to use the factory would trigger a crash. Both | 666 // At this point, attempting to use the factory would trigger a crash. Both |
| 518 // this test and the real world code should make sure this never happens. | 667 // this test and the real world code should make sure this never happens. |
| 519 }; | 668 }; |
| 520 | 669 |
| 521 } // namespace syncer | 670 } // namespace syncer |
| OLD | NEW |