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" | |
16 #include "base/threading/non_thread_safe.h" | 14 #include "base/threading/non_thread_safe.h" |
17 #include "base/threading/thread.h" | 15 #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" | |
21 #include "net/test/embedded_test_server/embedded_test_server.h" | 16 #include "net/test/embedded_test_server/embedded_test_server.h" |
22 #include "net/test/embedded_test_server/http_request.h" | 17 #include "net/test/embedded_test_server/http_request.h" |
23 #include "net/test/embedded_test_server/http_response.h" | 18 #include "net/test/embedded_test_server/http_response.h" |
24 #include "net/url_request/url_request_test_util.h" | 19 #include "net/url_request/url_request_test_util.h" |
25 #include "sync/api/attachments/attachment.h" | 20 #include "sync/api/attachments/attachment.h" |
26 #include "sync/protocol/sync.pb.h" | 21 #include "sync/protocol/sync.pb.h" |
27 #include "testing/gmock/include/gmock/gmock-matchers.h" | |
28 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
29 | 23 |
30 namespace { | 24 namespace { |
31 | 25 |
32 const char kAttachmentData[] = "some data"; | 26 const char kAttachmentData[] = "some data"; |
33 const char kAccountId[] = "some-account-id"; | |
34 const char kAccessToken[] = "some-access-token"; | |
35 const char kAuthorization[] = "Authorization"; | |
36 | 27 |
37 } // namespace | 28 } // namespace |
38 | 29 |
39 namespace syncer { | 30 namespace syncer { |
40 | 31 |
41 using net::test_server::BasicHttpResponse; | 32 using net::test_server::BasicHttpResponse; |
42 using net::test_server::HttpRequest; | 33 using net::test_server::HttpRequest; |
43 using net::test_server::HttpResponse; | 34 using net::test_server::HttpResponse; |
44 | 35 |
45 class RequestHandler; | 36 class RequestHandler; |
46 | 37 |
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 | |
168 // Text fixture for AttachmentUploaderImpl test. | 38 // Text fixture for AttachmentUploaderImpl test. |
169 // | 39 // |
170 // This fixture provides an embedded HTTP server and a mock OAuth2 token service | 40 // This fixture provides an embedded HTTP server for interacting with |
171 // for interacting with AttachmentUploaderImpl | 41 // AttachmentUploaderImpl. |
172 class AttachmentUploaderImplTest : public testing::Test, | 42 class AttachmentUploaderImplTest : public testing::Test, |
173 public base::NonThreadSafe { | 43 public base::NonThreadSafe { |
174 public: | 44 public: |
175 void OnRequestReceived(const HttpRequest& request); | 45 void OnRequestReceived(const HttpRequest& request); |
176 | 46 |
177 protected: | 47 protected: |
178 AttachmentUploaderImplTest(); | 48 AttachmentUploaderImplTest(); |
179 virtual void SetUp(); | 49 virtual void SetUp(); |
180 virtual void TearDown(); | |
181 | 50 |
182 // Run the message loop until UploadDone has been invoked |num_uploads| times. | 51 // Run the message loop until UploadDone has been invoked |num_uploads| times. |
183 void RunAndWaitFor(int num_uploads); | 52 void RunAndWaitFor(int num_uploads); |
184 | 53 |
185 scoped_ptr<AttachmentUploader>& uploader(); | 54 scoped_ptr<AttachmentUploader>& uploader(); |
186 const AttachmentUploader::UploadCallback& upload_callback() const; | 55 const AttachmentUploader::UploadCallback& upload_callback() const; |
187 std::vector<HttpRequest>& http_requests_received(); | 56 std::vector<HttpRequest>& http_requests_received(); |
188 std::vector<AttachmentUploader::UploadResult>& upload_results(); | 57 std::vector<AttachmentUploader::UploadResult>& upload_results(); |
189 std::vector<AttachmentId>& updated_attachment_ids(); | 58 std::vector<AttachmentId>& updated_attachment_ids(); |
190 MockOAuth2TokenService& token_service(); | |
191 base::MessageLoopForIO& message_loop(); | |
192 RequestHandler& request_handler(); | |
193 | 59 |
194 private: | 60 private: |
195 // An UploadCallback invoked by AttachmentUploaderImpl. | 61 // An UploadCallback invoked by AttachmentUploaderImpl. |
196 void UploadDone(const AttachmentUploader::UploadResult& result, | 62 void UploadDone(const AttachmentUploader::UploadResult& result, |
197 const AttachmentId& updated_attachment_id); | 63 const AttachmentId& updated_attachment_id); |
198 | 64 |
199 base::MessageLoopForIO message_loop_; | 65 base::MessageLoopForIO message_loop_; |
200 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; | 66 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; |
201 scoped_ptr<RequestHandler> request_handler_; | 67 scoped_ptr<RequestHandler> request_handler_; |
202 scoped_ptr<AttachmentUploader> uploader_; | 68 scoped_ptr<AttachmentUploader> uploader_; |
203 AttachmentUploader::UploadCallback upload_callback_; | 69 AttachmentUploader::UploadCallback upload_callback_; |
204 net::test_server::EmbeddedTestServer server_; | 70 net::test_server::EmbeddedTestServer server_; |
| 71 |
205 // A closure that signals an upload has finished. | 72 // A closure that signals an upload has finished. |
206 base::Closure signal_upload_done_; | 73 base::Closure signal_upload_done_; |
207 std::vector<HttpRequest> http_requests_received_; | 74 std::vector<HttpRequest> http_requests_received_; |
208 std::vector<AttachmentUploader::UploadResult> upload_results_; | 75 std::vector<AttachmentUploader::UploadResult> upload_results_; |
209 std::vector<AttachmentId> updated_attachment_ids_; | 76 std::vector<AttachmentId> updated_attachment_ids_; |
210 scoped_ptr<MockOAuth2TokenService> token_service_; | |
211 | 77 |
212 // Must be last data member. | 78 // Must be last data member. |
213 base::WeakPtrFactory<AttachmentUploaderImplTest> weak_ptr_factory_; | 79 base::WeakPtrFactory<AttachmentUploaderImplTest> weak_ptr_factory_; |
214 }; | 80 }; |
215 | 81 |
216 // Handles HTTP requests received by the EmbeddedTestServer. | 82 // Handles HTTP requests received by the EmbeddedTestServer. |
217 // | |
218 // Responds with HTTP_OK by default. See |SetStatusCode|. | |
219 class RequestHandler : public base::NonThreadSafe { | 83 class RequestHandler : public base::NonThreadSafe { |
220 public: | 84 public: |
221 // Construct a RequestHandler that will PostTask to |test| using | 85 // Construct a RequestHandler that will PostTask to |test| using |
222 // |test_task_runner|. | 86 // |test_task_runner|. |
223 RequestHandler( | 87 RequestHandler( |
224 const scoped_refptr<base::SingleThreadTaskRunner>& test_task_runner, | 88 const scoped_refptr<base::SingleThreadTaskRunner>& test_task_runner, |
225 const base::WeakPtr<AttachmentUploaderImplTest>& test); | 89 const base::WeakPtr<AttachmentUploaderImplTest>& test); |
226 | 90 |
227 ~RequestHandler(); | 91 ~RequestHandler(); |
228 | 92 |
229 scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request); | 93 scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request); |
230 | 94 |
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 | |
237 private: | 95 private: |
238 // Protects status_code_. | |
239 mutable base::Lock mutex_; | |
240 net::HttpStatusCode status_code_; | |
241 | |
242 scoped_refptr<base::SingleThreadTaskRunner> test_task_runner_; | 96 scoped_refptr<base::SingleThreadTaskRunner> test_task_runner_; |
243 base::WeakPtr<AttachmentUploaderImplTest> test_; | 97 base::WeakPtr<AttachmentUploaderImplTest> test_; |
244 }; | 98 }; |
245 | 99 |
246 AttachmentUploaderImplTest::AttachmentUploaderImplTest() | 100 AttachmentUploaderImplTest::AttachmentUploaderImplTest() |
247 : weak_ptr_factory_(this) { | 101 : weak_ptr_factory_(this) { |
248 } | 102 } |
249 | 103 |
250 void AttachmentUploaderImplTest::OnRequestReceived(const HttpRequest& request) { | 104 void AttachmentUploaderImplTest::OnRequestReceived(const HttpRequest& request) { |
251 DCHECK(CalledOnValidThread()); | 105 DCHECK(CalledOnValidThread()); |
252 http_requests_received_.push_back(request); | 106 http_requests_received_.push_back(request); |
253 } | 107 } |
254 | 108 |
255 void AttachmentUploaderImplTest::SetUp() { | 109 void AttachmentUploaderImplTest::SetUp() { |
256 DCHECK(CalledOnValidThread()); | 110 DCHECK(CalledOnValidThread()); |
257 request_handler_.reset(new RequestHandler(message_loop_.message_loop_proxy(), | 111 request_handler_.reset(new RequestHandler(message_loop_.message_loop_proxy(), |
258 weak_ptr_factory_.GetWeakPtr())); | 112 weak_ptr_factory_.GetWeakPtr())); |
259 url_request_context_getter_ = | 113 url_request_context_getter_ = |
260 new net::TestURLRequestContextGetter(message_loop_.message_loop_proxy()); | 114 new net::TestURLRequestContextGetter(message_loop_.message_loop_proxy()); |
261 | 115 |
262 ASSERT_TRUE(server_.InitializeAndWaitUntilReady()); | 116 ASSERT_TRUE(server_.InitializeAndWaitUntilReady()); |
263 server_.RegisterRequestHandler( | 117 server_.RegisterRequestHandler( |
264 base::Bind(&RequestHandler::HandleRequest, | 118 base::Bind(&RequestHandler::HandleRequest, |
265 base::Unretained(request_handler_.get()))); | 119 base::Unretained(request_handler_.get()))); |
266 | 120 |
267 std::string url_prefix( | 121 std::string url_prefix( |
268 base::StringPrintf("http://localhost:%d/uploads/", server_.port())); | 122 base::StringPrintf("http://localhost:%d/uploads/", server_.port())); |
269 | 123 |
270 token_service_.reset(new MockOAuth2TokenService); | 124 uploader().reset( |
271 scoped_ptr<OAuth2TokenServiceRequest::TokenServiceProvider> | 125 new AttachmentUploaderImpl(url_prefix, url_request_context_getter_)); |
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 | |
282 upload_callback_ = base::Bind(&AttachmentUploaderImplTest::UploadDone, | 126 upload_callback_ = base::Bind(&AttachmentUploaderImplTest::UploadDone, |
283 base::Unretained(this)); | 127 base::Unretained(this)); |
284 } | 128 } |
285 | 129 |
286 void AttachmentUploaderImplTest::TearDown() { | |
287 base::RunLoop().RunUntilIdle(); | |
288 } | |
289 | |
290 void AttachmentUploaderImplTest::RunAndWaitFor(int num_uploads) { | 130 void AttachmentUploaderImplTest::RunAndWaitFor(int num_uploads) { |
291 for (int i = 0; i < num_uploads; ++i) { | 131 for (int i = 0; i < num_uploads; ++i) { |
292 // Run the loop until one upload completes. | 132 // Run the loop until one upload completes. |
293 base::RunLoop run_loop; | 133 base::RunLoop run_loop; |
294 signal_upload_done_ = run_loop.QuitClosure(); | 134 signal_upload_done_ = run_loop.QuitClosure(); |
295 run_loop.Run(); | 135 run_loop.Run(); |
296 } | 136 } |
297 } | 137 } |
298 | 138 |
299 scoped_ptr<AttachmentUploader>& AttachmentUploaderImplTest::uploader() { | 139 scoped_ptr<AttachmentUploader>& AttachmentUploaderImplTest::uploader() { |
(...skipping 12 matching lines...) Expand all Loading... |
312 std::vector<AttachmentUploader::UploadResult>& | 152 std::vector<AttachmentUploader::UploadResult>& |
313 AttachmentUploaderImplTest::upload_results() { | 153 AttachmentUploaderImplTest::upload_results() { |
314 return upload_results_; | 154 return upload_results_; |
315 } | 155 } |
316 | 156 |
317 std::vector<AttachmentId>& | 157 std::vector<AttachmentId>& |
318 AttachmentUploaderImplTest::updated_attachment_ids() { | 158 AttachmentUploaderImplTest::updated_attachment_ids() { |
319 return updated_attachment_ids_; | 159 return updated_attachment_ids_; |
320 } | 160 } |
321 | 161 |
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 | |
334 void AttachmentUploaderImplTest::UploadDone( | 162 void AttachmentUploaderImplTest::UploadDone( |
335 const AttachmentUploader::UploadResult& result, | 163 const AttachmentUploader::UploadResult& result, |
336 const AttachmentId& updated_attachment_id) { | 164 const AttachmentId& updated_attachment_id) { |
337 DCHECK(CalledOnValidThread()); | 165 DCHECK(CalledOnValidThread()); |
338 upload_results_.push_back(result); | 166 upload_results_.push_back(result); |
339 updated_attachment_ids_.push_back(updated_attachment_id); | 167 updated_attachment_ids_.push_back(updated_attachment_id); |
340 signal_upload_done_.Run(); | 168 signal_upload_done_.Run(); |
341 } | 169 } |
342 | 170 |
343 RequestHandler::RequestHandler( | 171 RequestHandler::RequestHandler( |
344 const scoped_refptr<base::SingleThreadTaskRunner>& test_task_runner, | 172 const scoped_refptr<base::SingleThreadTaskRunner>& test_task_runner, |
345 const base::WeakPtr<AttachmentUploaderImplTest>& test) | 173 const base::WeakPtr<AttachmentUploaderImplTest>& test) |
346 : status_code_(net::HTTP_OK), | 174 : test_task_runner_(test_task_runner), test_(test) { |
347 test_task_runner_(test_task_runner), | |
348 test_(test) { | |
349 DetachFromThread(); | 175 DetachFromThread(); |
350 } | 176 } |
351 | 177 |
352 RequestHandler::~RequestHandler() { | 178 RequestHandler::~RequestHandler() { |
353 DetachFromThread(); | 179 DetachFromThread(); |
354 } | 180 } |
355 | 181 |
356 scoped_ptr<HttpResponse> RequestHandler::HandleRequest( | 182 scoped_ptr<HttpResponse> RequestHandler::HandleRequest( |
357 const HttpRequest& request) { | 183 const HttpRequest& request) { |
358 DCHECK(CalledOnValidThread()); | 184 DCHECK(CalledOnValidThread()); |
359 test_task_runner_->PostTask( | 185 test_task_runner_->PostTask( |
360 FROM_HERE, | 186 FROM_HERE, |
361 base::Bind( | 187 base::Bind( |
362 &AttachmentUploaderImplTest::OnRequestReceived, test_, request)); | 188 &AttachmentUploaderImplTest::OnRequestReceived, test_, request)); |
363 scoped_ptr<BasicHttpResponse> response(new BasicHttpResponse); | 189 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); |
364 response->set_code(GetStatusCode()); | 190 http_response->set_code(net::HTTP_OK); |
365 response->set_content_type("text/plain"); | 191 http_response->set_content("hello"); |
366 return response.PassAs<HttpResponse>(); | 192 http_response->set_content_type("text/plain"); |
367 } | 193 return http_response.PassAs<HttpResponse>(); |
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_; | |
377 } | 194 } |
378 | 195 |
379 // Verify the "happy case" of uploading an attachment. | 196 // 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. | |
383 TEST_F(AttachmentUploaderImplTest, UploadAttachment_HappyCase) { | 197 TEST_F(AttachmentUploaderImplTest, UploadAttachment_HappyCase) { |
384 token_service().AddAccount(kAccountId); | |
385 request_handler().SetStatusCode(net::HTTP_OK); | |
386 | |
387 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); | 198 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); |
388 some_data->data() = kAttachmentData; | 199 some_data->data() = kAttachmentData; |
389 Attachment attachment = Attachment::Create(some_data); | 200 Attachment attachment = Attachment::Create(some_data); |
390 uploader()->UploadAttachment(attachment, upload_callback()); | 201 uploader()->UploadAttachment(attachment, upload_callback()); |
391 | |
392 // Run until the done callback is invoked. | |
393 RunAndWaitFor(1); | 202 RunAndWaitFor(1); |
394 | 203 |
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 | |
401 // See that the HTTP server received one request. | 204 // See that the HTTP server received one request. |
402 ASSERT_EQ(1U, http_requests_received().size()); | 205 EXPECT_EQ(1U, http_requests_received().size()); |
403 const HttpRequest& http_request = http_requests_received().front(); | 206 const HttpRequest& http_request = http_requests_received().front(); |
404 EXPECT_EQ(net::test_server::METHOD_POST, http_request.method); | 207 EXPECT_EQ(net::test_server::METHOD_POST, http_request.method); |
405 std::string expected_relative_url("/uploads/" + | 208 std::string expected_relative_url("/uploads/" + |
406 attachment.GetId().GetProto().unique_id()); | 209 attachment.GetId().GetProto().unique_id()); |
407 EXPECT_EQ(expected_relative_url, http_request.relative_url); | 210 EXPECT_EQ(expected_relative_url, http_request.relative_url); |
408 EXPECT_TRUE(http_request.has_content); | 211 EXPECT_TRUE(http_request.has_content); |
409 EXPECT_EQ(kAttachmentData, http_request.content); | 212 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))); | |
414 | 213 |
| 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()); |
415 // TODO(maniscalco): Once AttachmentUploaderImpl is capable of updating the | 219 // TODO(maniscalco): Once AttachmentUploaderImpl is capable of updating the |
416 // AttachmentId with server address information about the attachment, add some | 220 // AttachmentId with server address information about the attachment, add some |
417 // checks here to verify it works properly (bug 371522). | 221 // checks here to verify it works properly (bug 371522). |
418 } | 222 } |
419 | 223 |
420 // Verify two overlapping calls to upload the same attachment result in only one | 224 // Verify two overlapping calls to upload the same attachment result in only one |
421 // HTTP request. | 225 // HTTP request. |
422 TEST_F(AttachmentUploaderImplTest, UploadAttachment_Collapse) { | 226 TEST_F(AttachmentUploaderImplTest, UploadAttachment_Collapse) { |
423 token_service().AddAccount(kAccountId); | |
424 request_handler().SetStatusCode(net::HTTP_OK); | |
425 | |
426 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); | 227 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); |
427 some_data->data() = kAttachmentData; | 228 some_data->data() = kAttachmentData; |
428 Attachment attachment1 = Attachment::Create(some_data); | 229 Attachment attachment1 = Attachment::Create(some_data); |
429 Attachment attachment2 = attachment1; | 230 Attachment attachment2 = attachment1; |
430 uploader()->UploadAttachment(attachment1, upload_callback()); | 231 uploader()->UploadAttachment(attachment1, upload_callback()); |
431 uploader()->UploadAttachment(attachment2, upload_callback()); | 232 uploader()->UploadAttachment(attachment2, upload_callback()); |
432 base::RunLoop().RunUntilIdle(); | |
433 | |
434 // Wait for upload_callback() to be invoked twice. | 233 // Wait for upload_callback() to be invoked twice. |
435 RunAndWaitFor(2); | 234 RunAndWaitFor(2); |
436 // See there was only one request. | 235 // See there was only one request. |
437 EXPECT_EQ(1U, http_requests_received().size()); | 236 EXPECT_EQ(1U, http_requests_received().size()); |
438 } | 237 } |
439 | 238 |
440 // Verify that the internal state associated with an upload is removed when the | 239 // Verify that the internal state associated with an upload is removed when the |
441 // uplaod finishes. We do this by issuing two non-overlapping uploads for the | 240 // uplaod finishes. We do this by issuing two non-overlapping uploads for the |
442 // same attachment and see that it results in two HTTP requests. | 241 // same attachment and see that it results in two HTTP requests. |
443 TEST_F(AttachmentUploaderImplTest, UploadAttachment_CleanUpAfterUpload) { | 242 TEST_F(AttachmentUploaderImplTest, UploadAttachment_CleanUpAfterUpload) { |
444 token_service().AddAccount(kAccountId); | |
445 request_handler().SetStatusCode(net::HTTP_OK); | |
446 | |
447 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); | 243 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString); |
448 some_data->data() = kAttachmentData; | 244 some_data->data() = kAttachmentData; |
449 Attachment attachment1 = Attachment::Create(some_data); | 245 Attachment attachment1 = Attachment::Create(some_data); |
450 Attachment attachment2 = attachment1; | 246 Attachment attachment2 = attachment1; |
451 uploader()->UploadAttachment(attachment1, upload_callback()); | 247 uploader()->UploadAttachment(attachment1, upload_callback()); |
452 base::RunLoop().RunUntilIdle(); | |
453 | |
454 // Wait for upload_callback() to be invoked before starting the second upload. | 248 // Wait for upload_callback() to be invoked before starting the second upload. |
455 RunAndWaitFor(1); | 249 RunAndWaitFor(1); |
456 uploader()->UploadAttachment(attachment2, upload_callback()); | 250 uploader()->UploadAttachment(attachment2, upload_callback()); |
457 base::RunLoop().RunUntilIdle(); | |
458 | |
459 // Wait for upload_callback() to be invoked a second time. | 251 // Wait for upload_callback() to be invoked a second time. |
460 RunAndWaitFor(1); | 252 RunAndWaitFor(1); |
461 // See there were two requests. | 253 // See there were two requests. |
462 ASSERT_EQ(2U, http_requests_received().size()); | 254 EXPECT_EQ(2U, http_requests_received().size()); |
463 } | 255 } |
464 | 256 |
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 | |
567 } // namespace syncer | 257 } // namespace syncer |
OLD | NEW |