Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "sync/internal_api/public/attachments/attachment_uploader_impl.h" | 5 #include "sync/internal_api/public/attachments/attachment_uploader_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
| 10 #include "base/memory/ref_counted_memory.h" | 10 #include "base/memory/ref_counted_memory.h" |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
| 13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 14 #include "base/synchronization/lock.h" | |
| 15 #include "base/thread_task_runner_handle.h" | |
| 14 #include "base/threading/non_thread_safe.h" | 16 #include "base/threading/non_thread_safe.h" |
| 15 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
| 18 #include "google_apis/gaia/fake_oauth2_token_service.h" | |
| 19 #include "google_apis/gaia/gaia_constants.h" | |
| 20 #include "google_apis/gaia/oauth2_token_service_request.h" | |
| 16 #include "net/test/embedded_test_server/embedded_test_server.h" | 21 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 17 #include "net/test/embedded_test_server/http_request.h" | 22 #include "net/test/embedded_test_server/http_request.h" |
| 18 #include "net/test/embedded_test_server/http_response.h" | 23 #include "net/test/embedded_test_server/http_response.h" |
| 19 #include "net/url_request/url_request_test_util.h" | 24 #include "net/url_request/url_request_test_util.h" |
| 20 #include "sync/api/attachments/attachment.h" | 25 #include "sync/api/attachments/attachment.h" |
| 21 #include "sync/protocol/sync.pb.h" | 26 #include "sync/protocol/sync.pb.h" |
| 27 #include "testing/gmock/include/gmock/gmock-matchers.h" | |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 28 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 29 |
| 24 namespace { | 30 namespace { |
| 25 | 31 |
| 26 const char kAttachmentData[] = "some data"; | 32 const char kAttachmentData[] = "some data"; |
| 33 const char kAccountId[] = "some-account-id"; | |
| 34 const char kAccessToken[] = "some-access-token"; | |
| 35 const char kAuthorization[] = "Authorization"; | |
| 27 | 36 |
| 28 } // namespace | 37 } // namespace |
| 29 | 38 |
| 30 namespace syncer { | 39 namespace syncer { |
| 31 | 40 |
| 32 using net::test_server::BasicHttpResponse; | 41 using net::test_server::BasicHttpResponse; |
| 33 using net::test_server::HttpRequest; | 42 using net::test_server::HttpRequest; |
| 34 using net::test_server::HttpResponse; | 43 using net::test_server::HttpResponse; |
| 35 | 44 |
| 36 class RequestHandler; | 45 class RequestHandler; |
| 37 | 46 |
| 47 // A mock implementation of an OAuth2TokenService. | |
| 48 // | |
| 49 // Use |SetResponse| to vary the response to token requests. | |
| 50 // | |
| 51 // Use |num_invalidate_token| and |last_token_invalidated| to check the number | |
| 52 // of invalidate token operations performed and the last token invalidated. | |
| 53 class MockOAuth2TokenService : public FakeOAuth2TokenService { | |
| 54 public: | |
| 55 MockOAuth2TokenService(); | |
| 56 virtual ~MockOAuth2TokenService(); | |
| 57 | |
| 58 void SetResponse(const GoogleServiceAuthError& error, | |
| 59 const std::string& access_token, | |
| 60 const base::Time& expiration); | |
| 61 | |
| 62 int num_invalidate_token() const { return num_invalidate_token_; } | |
| 63 | |
| 64 const std::string& last_token_invalidated() const { | |
| 65 return last_token_invalidated_; | |
| 66 } | |
| 67 | |
| 68 protected: | |
| 69 virtual void FetchOAuth2Token(RequestImpl* request, | |
| 70 const std::string& account_id, | |
| 71 net::URLRequestContextGetter* getter, | |
| 72 const std::string& client_id, | |
| 73 const std::string& client_secret, | |
| 74 const ScopeSet& scopes) OVERRIDE; | |
| 75 | |
| 76 virtual void InvalidateOAuth2Token(const std::string& account_id, | |
| 77 const std::string& client_id, | |
| 78 const ScopeSet& scopes, | |
| 79 const std::string& access_token) OVERRIDE; | |
| 80 | |
| 81 private: | |
| 82 GoogleServiceAuthError response_error_; | |
| 83 std::string response_access_token_; | |
| 84 base::Time response_expiration_; | |
| 85 int num_invalidate_token_; | |
| 86 std::string last_token_invalidated_; | |
| 87 }; | |
| 88 | |
| 89 MockOAuth2TokenService::MockOAuth2TokenService() | |
| 90 : response_error_(GoogleServiceAuthError::AuthErrorNone()), | |
| 91 response_access_token_(kAccessToken), | |
| 92 response_expiration_(base::Time::Max()), | |
| 93 num_invalidate_token_(0) { | |
| 94 } | |
| 95 | |
| 96 MockOAuth2TokenService::~MockOAuth2TokenService() { | |
| 97 } | |
| 98 | |
| 99 void MockOAuth2TokenService::SetResponse(const GoogleServiceAuthError& error, | |
| 100 const std::string& access_token, | |
| 101 const base::Time& expiration) { | |
| 102 response_error_ = error; | |
| 103 response_access_token_ = access_token; | |
| 104 response_expiration_ = expiration; | |
| 105 } | |
| 106 | |
| 107 void MockOAuth2TokenService::FetchOAuth2Token( | |
| 108 RequestImpl* request, | |
| 109 const std::string& account_id, | |
| 110 net::URLRequestContextGetter* getter, | |
| 111 const std::string& client_id, | |
| 112 const std::string& client_secret, | |
| 113 const ScopeSet& scopes) { | |
| 114 base::MessageLoop::current()->PostTask( | |
| 115 FROM_HERE, | |
| 116 base::Bind(&OAuth2TokenService::RequestImpl::InformConsumer, | |
| 117 request->AsWeakPtr(), | |
| 118 response_error_, | |
| 119 response_access_token_, | |
| 120 response_expiration_)); | |
| 121 } | |
| 122 | |
| 123 void MockOAuth2TokenService::InvalidateOAuth2Token( | |
| 124 const std::string& account_id, | |
| 125 const std::string& client_id, | |
| 126 const ScopeSet& scopes, | |
| 127 const std::string& access_token) { | |
| 128 ++num_invalidate_token_; | |
| 129 last_token_invalidated_ = access_token; | |
| 130 } | |
| 131 | |
| 132 class TokenServiceProvider | |
| 133 : public OAuth2TokenServiceRequest::TokenServiceProvider, | |
| 134 base::NonThreadSafe { | |
| 135 public: | |
| 136 TokenServiceProvider(OAuth2TokenService* token_service); | |
| 137 virtual ~TokenServiceProvider(); | |
| 138 | |
| 139 // OAuth2TokenService::TokenServiceProvider implementation. | |
| 140 virtual scoped_refptr<base::SingleThreadTaskRunner> | |
| 141 GetTokenServiceTaskRunner() OVERRIDE; | |
| 142 virtual OAuth2TokenService* GetTokenService() OVERRIDE; | |
| 143 | |
| 144 private: | |
| 145 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
| 146 OAuth2TokenService* token_service_; | |
| 147 }; | |
| 148 | |
| 149 TokenServiceProvider::TokenServiceProvider(OAuth2TokenService* token_service) | |
| 150 : task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
| 151 token_service_(token_service) { | |
| 152 DCHECK(token_service_); | |
| 153 } | |
| 154 | |
| 155 TokenServiceProvider::~TokenServiceProvider() { | |
| 156 } | |
| 157 | |
| 158 scoped_refptr<base::SingleThreadTaskRunner> | |
| 159 TokenServiceProvider::GetTokenServiceTaskRunner() { | |
| 160 return task_runner_; | |
| 161 } | |
| 162 | |
| 163 OAuth2TokenService* TokenServiceProvider::GetTokenService() { | |
| 164 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 165 return token_service_; | |
| 166 } | |
| 167 | |
| 38 // Text fixture for AttachmentUploaderImpl test. | 168 // Text fixture for AttachmentUploaderImpl test. |
| 39 // | 169 // |
| 40 // This fixture provides an embedded HTTP server for interacting with | 170 // This fixture provides an embedded HTTP server and a mock OAuth2 token service |
| 41 // AttachmentUploaderImpl. | 171 // for interacting with AttachmentUploaderImpl |
| 42 class AttachmentUploaderImplTest : public testing::Test, | 172 class AttachmentUploaderImplTest : public testing::Test, |
| 43 public base::NonThreadSafe { | 173 public base::NonThreadSafe { |
| 44 public: | 174 public: |
| 45 void OnRequestReceived(const HttpRequest& request); | 175 void OnRequestReceived(const HttpRequest& request); |
| 46 | 176 |
| 47 protected: | 177 protected: |
| 48 AttachmentUploaderImplTest(); | 178 AttachmentUploaderImplTest(); |
| 49 virtual void SetUp(); | 179 virtual void SetUp(); |
| 50 | 180 |
| 51 // Run the message loop until UploadDone has been invoked |num_uploads| times. | 181 // Run the message loop until UploadDone has been invoked |num_uploads| times. |
| 52 void RunAndWaitFor(int num_uploads); | 182 void RunAndWaitFor(int num_uploads); |
| 53 | 183 |
| 54 scoped_ptr<AttachmentUploader>& uploader(); | 184 scoped_ptr<AttachmentUploader>& uploader(); |
| 55 const AttachmentUploader::UploadCallback& upload_callback() const; | 185 const AttachmentUploader::UploadCallback& upload_callback() const; |
| 56 std::vector<HttpRequest>& http_requests_received(); | 186 std::vector<HttpRequest>& http_requests_received(); |
| 57 std::vector<AttachmentUploader::UploadResult>& upload_results(); | 187 std::vector<AttachmentUploader::UploadResult>& upload_results(); |
| 58 std::vector<AttachmentId>& updated_attachment_ids(); | 188 std::vector<AttachmentId>& updated_attachment_ids(); |
| 189 MockOAuth2TokenService& token_service(); | |
| 190 base::MessageLoopForIO& message_loop(); | |
| 191 RequestHandler& request_handler(); | |
| 59 | 192 |
| 60 private: | 193 private: |
| 61 // An UploadCallback invoked by AttachmentUploaderImpl. | 194 // An UploadCallback invoked by AttachmentUploaderImpl. |
| 62 void UploadDone(const AttachmentUploader::UploadResult& result, | 195 void UploadDone(const AttachmentUploader::UploadResult& result, |
| 63 const AttachmentId& updated_attachment_id); | 196 const AttachmentId& updated_attachment_id); |
| 64 | 197 |
| 65 base::MessageLoopForIO message_loop_; | 198 base::MessageLoopForIO message_loop_; |
| 66 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; | 199 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; |
| 67 scoped_ptr<RequestHandler> request_handler_; | 200 scoped_ptr<RequestHandler> request_handler_; |
| 68 scoped_ptr<AttachmentUploader> uploader_; | 201 scoped_ptr<AttachmentUploader> uploader_; |
| 69 AttachmentUploader::UploadCallback upload_callback_; | 202 AttachmentUploader::UploadCallback upload_callback_; |
| 70 net::test_server::EmbeddedTestServer server_; | 203 net::test_server::EmbeddedTestServer server_; |
| 71 | |
| 72 // A closure that signals an upload has finished. | 204 // A closure that signals an upload has finished. |
| 73 base::Closure signal_upload_done_; | 205 base::Closure signal_upload_done_; |
| 74 std::vector<HttpRequest> http_requests_received_; | 206 std::vector<HttpRequest> http_requests_received_; |
| 75 std::vector<AttachmentUploader::UploadResult> upload_results_; | 207 std::vector<AttachmentUploader::UploadResult> upload_results_; |
| 76 std::vector<AttachmentId> updated_attachment_ids_; | 208 std::vector<AttachmentId> updated_attachment_ids_; |
| 209 scoped_ptr<MockOAuth2TokenService> token_service_; | |
| 77 | 210 |
| 78 // Must be last data member. | 211 // Must be last data member. |
| 79 base::WeakPtrFactory<AttachmentUploaderImplTest> weak_ptr_factory_; | 212 base::WeakPtrFactory<AttachmentUploaderImplTest> weak_ptr_factory_; |
| 80 }; | 213 }; |
| 81 | 214 |
| 82 // Handles HTTP requests received by the EmbeddedTestServer. | 215 // Handles HTTP requests received by the EmbeddedTestServer. |
| 216 // | |
| 217 // Responds with HTTP_OK by default. See |SetStatusCode|. | |
| 83 class RequestHandler : public base::NonThreadSafe { | 218 class RequestHandler : public base::NonThreadSafe { |
| 84 public: | 219 public: |
| 85 // Construct a RequestHandler that will PostTask to |test| using | 220 // Construct a RequestHandler that will PostTask to |test| using |
| 86 // |test_task_runner|. | 221 // |test_task_runner|. |
| 87 RequestHandler( | 222 RequestHandler( |
| 88 const scoped_refptr<base::SingleThreadTaskRunner>& test_task_runner, | 223 const scoped_refptr<base::SingleThreadTaskRunner>& test_task_runner, |
| 89 const base::WeakPtr<AttachmentUploaderImplTest>& test); | 224 const base::WeakPtr<AttachmentUploaderImplTest>& test); |
| 90 | 225 |
| 91 ~RequestHandler(); | 226 ~RequestHandler(); |
| 92 | 227 |
| 93 scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request); | 228 scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request); |
| 94 | 229 |
| 230 // Set the HTTP status code to respond with. | |
| 231 void SetStatusCode(const net::HttpStatusCode& status_code); | |
| 232 | |
| 233 // Returns the HTTP status code that will be used in responses. | |
| 234 net::HttpStatusCode GetStatusCode() const; | |
| 235 | |
| 95 private: | 236 private: |
| 237 // Protects status_code_. | |
| 238 mutable base::Lock mutex_; | |
| 239 net::HttpStatusCode status_code_; | |
| 240 | |
| 96 scoped_refptr<base::SingleThreadTaskRunner> test_task_runner_; | 241 scoped_refptr<base::SingleThreadTaskRunner> test_task_runner_; |
| 97 base::WeakPtr<AttachmentUploaderImplTest> test_; | 242 base::WeakPtr<AttachmentUploaderImplTest> test_; |
| 98 }; | 243 }; |
| 99 | 244 |
| 100 AttachmentUploaderImplTest::AttachmentUploaderImplTest() | 245 AttachmentUploaderImplTest::AttachmentUploaderImplTest() |
| 101 : weak_ptr_factory_(this) { | 246 : weak_ptr_factory_(this) { |
| 102 } | 247 } |
| 103 | 248 |
| 104 void AttachmentUploaderImplTest::OnRequestReceived(const HttpRequest& request) { | 249 void AttachmentUploaderImplTest::OnRequestReceived(const HttpRequest& request) { |
| 105 DCHECK(CalledOnValidThread()); | 250 DCHECK(CalledOnValidThread()); |
| 106 http_requests_received_.push_back(request); | 251 http_requests_received_.push_back(request); |
| 107 } | 252 } |
| 108 | 253 |
| 109 void AttachmentUploaderImplTest::SetUp() { | 254 void AttachmentUploaderImplTest::SetUp() { |
| 110 DCHECK(CalledOnValidThread()); | 255 DCHECK(CalledOnValidThread()); |
| 111 request_handler_.reset(new RequestHandler(message_loop_.message_loop_proxy(), | 256 request_handler_.reset(new RequestHandler(message_loop_.message_loop_proxy(), |
| 112 weak_ptr_factory_.GetWeakPtr())); | 257 weak_ptr_factory_.GetWeakPtr())); |
| 113 url_request_context_getter_ = | 258 url_request_context_getter_ = |
| 114 new net::TestURLRequestContextGetter(message_loop_.message_loop_proxy()); | 259 new net::TestURLRequestContextGetter(message_loop_.message_loop_proxy()); |
| 115 | 260 |
| 116 ASSERT_TRUE(server_.InitializeAndWaitUntilReady()); | 261 ASSERT_TRUE(server_.InitializeAndWaitUntilReady()); |
| 117 server_.RegisterRequestHandler( | 262 server_.RegisterRequestHandler( |
| 118 base::Bind(&RequestHandler::HandleRequest, | 263 base::Bind(&RequestHandler::HandleRequest, |
| 119 base::Unretained(request_handler_.get()))); | 264 base::Unretained(request_handler_.get()))); |
| 120 | 265 |
| 121 std::string url_prefix( | 266 std::string url_prefix( |
| 122 base::StringPrintf("http://localhost:%d/uploads/", server_.port())); | 267 base::StringPrintf("http://localhost:%d/uploads/", server_.port())); |
| 123 | 268 |
| 124 uploader().reset( | 269 token_service_.reset(new MockOAuth2TokenService); |
| 125 new AttachmentUploaderImpl(url_prefix, url_request_context_getter_)); | 270 scoped_ptr<OAuth2TokenServiceRequest::TokenServiceProvider> |
| 271 token_service_provider(new TokenServiceProvider(token_service_.get())); | |
| 272 | |
| 273 OAuth2TokenService::ScopeSet scopes; | |
| 274 scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope); | |
| 275 uploader().reset(new AttachmentUploaderImpl(url_prefix, | |
| 276 url_request_context_getter_, | |
| 277 kAccountId, | |
| 278 scopes, | |
| 279 token_service_provider.Pass())); | |
| 280 | |
| 126 upload_callback_ = base::Bind(&AttachmentUploaderImplTest::UploadDone, | 281 upload_callback_ = base::Bind(&AttachmentUploaderImplTest::UploadDone, |
| 127 base::Unretained(this)); | 282 base::Unretained(this)); |
| 128 } | 283 } |
| 129 | 284 |
| 130 void AttachmentUploaderImplTest::RunAndWaitFor(int num_uploads) { | 285 void AttachmentUploaderImplTest::RunAndWaitFor(int num_uploads) { |
| 131 for (int i = 0; i < num_uploads; ++i) { | 286 for (int i = 0; i < num_uploads; ++i) { |
| 132 // Run the loop until one upload completes. | 287 // Run the loop until one upload completes. |
| 133 base::RunLoop run_loop; | 288 base::RunLoop run_loop; |
| 134 signal_upload_done_ = run_loop.QuitClosure(); | 289 signal_upload_done_ = run_loop.QuitClosure(); |
| 135 run_loop.Run(); | 290 run_loop.Run(); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 152 std::vector<AttachmentUploader::UploadResult>& | 307 std::vector<AttachmentUploader::UploadResult>& |
| 153 AttachmentUploaderImplTest::upload_results() { | 308 AttachmentUploaderImplTest::upload_results() { |
| 154 return upload_results_; | 309 return upload_results_; |
| 155 } | 310 } |
| 156 | 311 |
| 157 std::vector<AttachmentId>& | 312 std::vector<AttachmentId>& |
| 158 AttachmentUploaderImplTest::updated_attachment_ids() { | 313 AttachmentUploaderImplTest::updated_attachment_ids() { |
| 159 return updated_attachment_ids_; | 314 return updated_attachment_ids_; |
| 160 } | 315 } |
| 161 | 316 |
| 317 MockOAuth2TokenService& AttachmentUploaderImplTest::token_service() { | |
| 318 return *token_service_; | |
| 319 } | |
| 320 | |
| 321 base::MessageLoopForIO& AttachmentUploaderImplTest::message_loop() { | |
| 322 return message_loop_; | |
| 323 } | |
| 324 | |
| 325 RequestHandler& AttachmentUploaderImplTest::request_handler() { | |
| 326 return *request_handler_; | |
| 327 } | |
| 328 | |
| 162 void AttachmentUploaderImplTest::UploadDone( | 329 void AttachmentUploaderImplTest::UploadDone( |
| 163 const AttachmentUploader::UploadResult& result, | 330 const AttachmentUploader::UploadResult& result, |
| 164 const AttachmentId& updated_attachment_id) { | 331 const AttachmentId& updated_attachment_id) { |
| 165 DCHECK(CalledOnValidThread()); | 332 DCHECK(CalledOnValidThread()); |
| 166 upload_results_.push_back(result); | 333 upload_results_.push_back(result); |
| 167 updated_attachment_ids_.push_back(updated_attachment_id); | 334 updated_attachment_ids_.push_back(updated_attachment_id); |
| 168 signal_upload_done_.Run(); | 335 signal_upload_done_.Run(); |
| 169 } | 336 } |
| 170 | 337 |
| 171 RequestHandler::RequestHandler( | 338 RequestHandler::RequestHandler( |
| 172 const scoped_refptr<base::SingleThreadTaskRunner>& test_task_runner, | 339 const scoped_refptr<base::SingleThreadTaskRunner>& test_task_runner, |
| 173 const base::WeakPtr<AttachmentUploaderImplTest>& test) | 340 const base::WeakPtr<AttachmentUploaderImplTest>& test) |
| 174 : test_task_runner_(test_task_runner), test_(test) { | 341 : status_code_(net::HTTP_OK), |
| 342 test_task_runner_(test_task_runner), | |
| 343 test_(test) { | |
| 175 DetachFromThread(); | 344 DetachFromThread(); |
| 176 } | 345 } |
| 177 | 346 |
| 178 RequestHandler::~RequestHandler() { | 347 RequestHandler::~RequestHandler() { |
| 179 DetachFromThread(); | 348 DetachFromThread(); |
| 180 } | 349 } |
| 181 | 350 |
| 182 scoped_ptr<HttpResponse> RequestHandler::HandleRequest( | 351 scoped_ptr<HttpResponse> RequestHandler::HandleRequest( |
| 183 const HttpRequest& request) { | 352 const HttpRequest& request) { |
| 184 DCHECK(CalledOnValidThread()); | 353 DCHECK(CalledOnValidThread()); |
| 185 test_task_runner_->PostTask( | 354 test_task_runner_->PostTask( |
| 186 FROM_HERE, | 355 FROM_HERE, |
| 187 base::Bind( | 356 base::Bind( |
| 188 &AttachmentUploaderImplTest::OnRequestReceived, test_, request)); | 357 &AttachmentUploaderImplTest::OnRequestReceived, test_, request)); |
| 189 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 358 scoped_ptr<BasicHttpResponse> response(new BasicHttpResponse); |
| 190 http_response->set_code(net::HTTP_OK); | 359 response->set_code(GetStatusCode()); |
| 191 http_response->set_content("hello"); | 360 response->set_content_type("text/plain"); |
| 192 http_response->set_content_type("text/plain"); | 361 return response.PassAs<HttpResponse>(); |
| 193 return http_response.PassAs<HttpResponse>(); | 362 } |
| 363 | |
| 364 void RequestHandler::SetStatusCode(const net::HttpStatusCode& status_code) { | |
| 365 base::AutoLock lock(mutex_); | |
| 366 status_code_ = status_code; | |
| 367 } | |
| 368 | |
| 369 net::HttpStatusCode RequestHandler::GetStatusCode() const { | |
| 370 base::AutoLock lock(mutex_); | |
| 371 return status_code_; | |
| 194 } | 372 } |
| 195 | 373 |
| 196 // Verify the "happy case" of uploading an attachment. | 374 // Verify the "happy case" of uploading an attachment. |
| 375 // | |
| 376 // Token is requested, token is returned, HTTP request is made, attachment is | |
| 377 // received by server. | |
| 197 TEST_F(AttachmentUploaderImplTest, UploadAttachment_HappyCase) { | 378 TEST_F(AttachmentUploaderImplTest, UploadAttachment_HappyCase) { |
| 379 token_service().AddAccount(kAccountId); | |
| 380 request_handler().SetStatusCode(net::HTTP_OK); | |
| 381 | |
| 198 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); | 382 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); |
| 199 some_data->data() = kAttachmentData; | 383 some_data->data() = kAttachmentData; |
| 200 Attachment attachment = Attachment::Create(some_data); | 384 Attachment attachment = Attachment::Create(some_data); |
| 201 uploader()->UploadAttachment(attachment, upload_callback()); | 385 uploader()->UploadAttachment(attachment, upload_callback()); |
| 386 | |
| 387 // Run until the done callback is invoked. | |
| 202 RunAndWaitFor(1); | 388 RunAndWaitFor(1); |
| 203 | 389 |
| 390 // See that the done callback was invoked with the right arguments. | |
| 391 ASSERT_EQ(1U, upload_results().size()); | |
| 392 EXPECT_EQ(AttachmentUploader::UPLOAD_SUCCESS, upload_results()[0]); | |
| 393 ASSERT_EQ(1U, updated_attachment_ids().size()); | |
| 394 EXPECT_EQ(attachment.GetId(), updated_attachment_ids()[0]); | |
| 395 | |
| 204 // See that the HTTP server received one request. | 396 // See that the HTTP server received one request. |
| 205 EXPECT_EQ(1U, http_requests_received().size()); | 397 ASSERT_EQ(1U, http_requests_received().size()); |
| 206 const HttpRequest& http_request = http_requests_received().front(); | 398 const HttpRequest& http_request = http_requests_received().front(); |
| 207 EXPECT_EQ(net::test_server::METHOD_POST, http_request.method); | 399 EXPECT_EQ(net::test_server::METHOD_POST, http_request.method); |
| 208 std::string expected_relative_url("/uploads/" + | 400 std::string expected_relative_url("/uploads/" + |
| 209 attachment.GetId().GetProto().unique_id()); | 401 attachment.GetId().GetProto().unique_id()); |
| 210 EXPECT_EQ(expected_relative_url, http_request.relative_url); | 402 EXPECT_EQ(expected_relative_url, http_request.relative_url); |
| 211 EXPECT_TRUE(http_request.has_content); | 403 EXPECT_TRUE(http_request.has_content); |
| 212 EXPECT_EQ(kAttachmentData, http_request.content); | 404 EXPECT_EQ(kAttachmentData, http_request.content); |
| 405 std::string expected_header(kAuthorization); | |
|
pavely
2014/06/04 23:34:39
expected_header is not used.
maniscalco
2014/06/05 00:12:12
Removed!
On 2014/06/04 23:34:39, pavely wrote:
| |
| 406 const std::string header_name(kAuthorization); | |
| 407 const std::string header_value(std::string("Bearer ") + kAccessToken); | |
| 408 EXPECT_THAT(http_request.headers, | |
| 409 testing::Contains(testing::Pair(header_name, header_value))); | |
| 213 | 410 |
| 214 // See that the UploadCallback received a result and updated AttachmentId. | |
| 215 EXPECT_EQ(1U, upload_results().size()); | |
| 216 EXPECT_EQ(1U, updated_attachment_ids().size()); | |
| 217 EXPECT_EQ(AttachmentUploader::UPLOAD_SUCCESS, upload_results().front()); | |
| 218 EXPECT_EQ(attachment.GetId(), updated_attachment_ids().front()); | |
| 219 // TODO(maniscalco): Once AttachmentUploaderImpl is capable of updating the | 411 // TODO(maniscalco): Once AttachmentUploaderImpl is capable of updating the |
| 220 // AttachmentId with server address information about the attachment, add some | 412 // AttachmentId with server address information about the attachment, add some |
| 221 // checks here to verify it works properly (bug 371522). | 413 // checks here to verify it works properly (bug 371522). |
| 222 } | 414 } |
| 223 | 415 |
| 224 // Verify two overlapping calls to upload the same attachment result in only one | 416 // Verify two overlapping calls to upload the same attachment result in only one |
| 225 // HTTP request. | 417 // HTTP request. |
| 226 TEST_F(AttachmentUploaderImplTest, UploadAttachment_Collapse) { | 418 TEST_F(AttachmentUploaderImplTest, UploadAttachment_Collapse) { |
| 419 token_service().AddAccount(kAccountId); | |
| 420 request_handler().SetStatusCode(net::HTTP_OK); | |
| 421 | |
| 227 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); | 422 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); |
| 228 some_data->data() = kAttachmentData; | 423 some_data->data() = kAttachmentData; |
| 229 Attachment attachment1 = Attachment::Create(some_data); | 424 Attachment attachment1 = Attachment::Create(some_data); |
| 230 Attachment attachment2 = attachment1; | 425 Attachment attachment2 = attachment1; |
| 231 uploader()->UploadAttachment(attachment1, upload_callback()); | 426 uploader()->UploadAttachment(attachment1, upload_callback()); |
| 232 uploader()->UploadAttachment(attachment2, upload_callback()); | 427 uploader()->UploadAttachment(attachment2, upload_callback()); |
| 428 base::RunLoop().RunUntilIdle(); | |
| 429 | |
| 233 // Wait for upload_callback() to be invoked twice. | 430 // Wait for upload_callback() to be invoked twice. |
| 234 RunAndWaitFor(2); | 431 RunAndWaitFor(2); |
| 235 // See there was only one request. | 432 // See there was only one request. |
| 236 EXPECT_EQ(1U, http_requests_received().size()); | 433 EXPECT_EQ(1U, http_requests_received().size()); |
| 237 } | 434 } |
| 238 | 435 |
| 239 // Verify that the internal state associated with an upload is removed when the | 436 // Verify that the internal state associated with an upload is removed when the |
| 240 // uplaod finishes. We do this by issuing two non-overlapping uploads for the | 437 // uplaod finishes. We do this by issuing two non-overlapping uploads for the |
| 241 // same attachment and see that it results in two HTTP requests. | 438 // same attachment and see that it results in two HTTP requests. |
| 242 TEST_F(AttachmentUploaderImplTest, UploadAttachment_CleanUpAfterUpload) { | 439 TEST_F(AttachmentUploaderImplTest, UploadAttachment_CleanUpAfterUpload) { |
| 440 token_service().AddAccount(kAccountId); | |
| 441 request_handler().SetStatusCode(net::HTTP_OK); | |
| 442 | |
| 243 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); | 443 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); |
| 244 some_data->data() = kAttachmentData; | 444 some_data->data() = kAttachmentData; |
| 245 Attachment attachment1 = Attachment::Create(some_data); | 445 Attachment attachment1 = Attachment::Create(some_data); |
| 246 Attachment attachment2 = attachment1; | 446 Attachment attachment2 = attachment1; |
| 247 uploader()->UploadAttachment(attachment1, upload_callback()); | 447 uploader()->UploadAttachment(attachment1, upload_callback()); |
| 448 base::RunLoop().RunUntilIdle(); | |
| 449 | |
| 248 // Wait for upload_callback() to be invoked before starting the second upload. | 450 // Wait for upload_callback() to be invoked before starting the second upload. |
| 249 RunAndWaitFor(1); | 451 RunAndWaitFor(1); |
| 250 uploader()->UploadAttachment(attachment2, upload_callback()); | 452 uploader()->UploadAttachment(attachment2, upload_callback()); |
| 453 base::RunLoop().RunUntilIdle(); | |
| 454 | |
| 251 // Wait for upload_callback() to be invoked a second time. | 455 // Wait for upload_callback() to be invoked a second time. |
| 252 RunAndWaitFor(1); | 456 RunAndWaitFor(1); |
| 253 // See there were two requests. | 457 // See there were two requests. |
| 254 EXPECT_EQ(2U, http_requests_received().size()); | 458 ASSERT_EQ(2U, http_requests_received().size()); |
| 255 } | 459 } |
| 256 | 460 |
| 461 // Verify that we do not issue an HTTP request when we fail to receive an access | |
| 462 // token. | |
| 463 // | |
| 464 // Token is requested, no token is returned, no HTTP request is made | |
| 465 TEST_F(AttachmentUploaderImplTest, UploadAttachment_FailToGetToken) { | |
| 466 // Note, we won't receive a token because we did not add kAccountId to the | |
| 467 // token service. | |
| 468 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); | |
| 469 some_data->data() = kAttachmentData; | |
| 470 Attachment attachment = Attachment::Create(some_data); | |
| 471 uploader()->UploadAttachment(attachment, upload_callback()); | |
| 472 | |
| 473 RunAndWaitFor(1); | |
| 474 | |
| 475 // See that the done callback was invoked. | |
| 476 ASSERT_EQ(1U, upload_results().size()); | |
| 477 EXPECT_EQ(AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR, upload_results()[0]); | |
| 478 ASSERT_EQ(1U, updated_attachment_ids().size()); | |
| 479 EXPECT_EQ(attachment.GetId(), updated_attachment_ids()[0]); | |
| 480 | |
| 481 // See that no HTTP request was received. | |
| 482 ASSERT_EQ(0U, http_requests_received().size()); | |
| 483 } | |
| 484 | |
| 485 // Verify behavior when the server returns "503 Service Unavailable". | |
| 486 TEST_F(AttachmentUploaderImplTest, UploadAttachment_ServiceUnavilable) { | |
| 487 token_service().AddAccount(kAccountId); | |
| 488 request_handler().SetStatusCode(net::HTTP_SERVICE_UNAVAILABLE); | |
| 489 | |
| 490 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); | |
| 491 some_data->data() = kAttachmentData; | |
| 492 Attachment attachment = Attachment::Create(some_data); | |
| 493 uploader()->UploadAttachment(attachment, upload_callback()); | |
| 494 | |
| 495 RunAndWaitFor(1); | |
| 496 | |
| 497 // See that the done callback was invoked. | |
| 498 ASSERT_EQ(1U, upload_results().size()); | |
| 499 EXPECT_EQ(AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR, upload_results()[0]); | |
| 500 ASSERT_EQ(1U, updated_attachment_ids().size()); | |
| 501 EXPECT_EQ(attachment.GetId(), updated_attachment_ids()[0]); | |
| 502 | |
| 503 // See that the HTTP server received one request. | |
| 504 ASSERT_EQ(1U, http_requests_received().size()); | |
| 505 const HttpRequest& http_request = http_requests_received().front(); | |
| 506 EXPECT_EQ(net::test_server::METHOD_POST, http_request.method); | |
| 507 std::string expected_relative_url("/uploads/" + | |
| 508 attachment.GetId().GetProto().unique_id()); | |
| 509 EXPECT_EQ(expected_relative_url, http_request.relative_url); | |
| 510 EXPECT_TRUE(http_request.has_content); | |
| 511 EXPECT_EQ(kAttachmentData, http_request.content); | |
| 512 std::string expected_header(kAuthorization); | |
| 513 const std::string header_name(kAuthorization); | |
| 514 const std::string header_value(std::string("Bearer ") + kAccessToken); | |
| 515 EXPECT_THAT(http_request.headers, | |
| 516 testing::Contains(testing::Pair(header_name, header_value))); | |
| 517 | |
| 518 // See that we did not invalidate the token. | |
| 519 ASSERT_EQ(0, token_service().num_invalidate_token()); | |
| 520 } | |
| 521 | |
| 522 // Verify that when we receive an "401 Unauthorized" we invalidate the access | |
| 523 // token. | |
| 524 TEST_F(AttachmentUploaderImplTest, UploadAttachment_BadToken) { | |
| 525 token_service().AddAccount(kAccountId); | |
| 526 request_handler().SetStatusCode(net::HTTP_UNAUTHORIZED); | |
| 527 | |
| 528 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); | |
| 529 some_data->data() = kAttachmentData; | |
| 530 Attachment attachment = Attachment::Create(some_data); | |
| 531 uploader()->UploadAttachment(attachment, upload_callback()); | |
| 532 | |
| 533 RunAndWaitFor(1); | |
| 534 | |
| 535 // See that the done callback was invoked. | |
| 536 ASSERT_EQ(1U, upload_results().size()); | |
| 537 EXPECT_EQ(AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR, upload_results()[0]); | |
| 538 ASSERT_EQ(1U, updated_attachment_ids().size()); | |
| 539 EXPECT_EQ(attachment.GetId(), updated_attachment_ids()[0]); | |
| 540 | |
| 541 // See that the HTTP server received one request. | |
| 542 ASSERT_EQ(1U, http_requests_received().size()); | |
| 543 const HttpRequest& http_request = http_requests_received().front(); | |
| 544 EXPECT_EQ(net::test_server::METHOD_POST, http_request.method); | |
| 545 std::string expected_relative_url("/uploads/" + | |
| 546 attachment.GetId().GetProto().unique_id()); | |
| 547 EXPECT_EQ(expected_relative_url, http_request.relative_url); | |
| 548 EXPECT_TRUE(http_request.has_content); | |
| 549 EXPECT_EQ(kAttachmentData, http_request.content); | |
| 550 std::string expected_header(kAuthorization); | |
| 551 const std::string header_name(kAuthorization); | |
| 552 const std::string header_value(std::string("Bearer ") + kAccessToken); | |
| 553 EXPECT_THAT(http_request.headers, | |
| 554 testing::Contains(testing::Pair(header_name, header_value))); | |
| 555 | |
| 556 // See that we invalidated the token. | |
| 557 ASSERT_EQ(1, token_service().num_invalidate_token()); | |
| 558 } | |
| 559 | |
| 560 // TODO(maniscalco): Add test case for when we are uploading an attachment that | |
| 561 // already exists. 409 Conflict? (bug 379825) | |
| 562 | |
| 257 } // namespace syncer | 563 } // namespace syncer |
| OLD | NEW |