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