1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/kasko/upload.h"
16 :
17 : #include <algorithm>
18 : #include <cstring>
19 : #include <map>
20 : #include <memory>
21 : #include <queue>
22 : #include <string>
23 : #include <vector>
24 :
25 : #include "base/macros.h"
26 : #include "base/strings/string16.h"
27 : #include "base/strings/string_tokenizer.h"
28 : #include "base/strings/string_util.h"
29 : #include "base/strings/utf_string_conversions.h"
30 : #include "gtest/gtest.h"
31 : #include "syzygy/kasko/http_agent.h"
32 : #include "syzygy/kasko/http_response.h"
33 : #include "syzygy/kasko/internet_helpers.h"
34 : #include "syzygy/kasko/internet_unittest_helpers.h"
35 :
36 m : namespace kasko {
37 :
38 m : namespace {
39 :
40 : // An implementation of HttpAgent that performs a sanity check on the request
41 : // parameters before returning a fixed HttpResponse.
42 m : class MockHttpAgent : public HttpAgent {
43 m : public:
44 : // Defines the expected request parameters.
45 m : struct Expectations {
46 m : base::string16 host;
47 m : uint16_t port;
48 m : base::string16 path;
49 m : bool secure;
50 m : std::map<base::string16, base::string16> parameters;
51 m : std::string file;
52 m : base::string16 file_name;
53 m : };
54 :
55 m : MockHttpAgent();
56 m : ~MockHttpAgent() override;
57 :
58 m : Expectations& expectations();
59 m : void set_response(std::unique_ptr<HttpResponse> response);
60 m : void set_expect_invocation(bool expect_invocation) {
61 m : invoked_ = !expect_invocation;
62 m : }
63 :
64 : // HttpAgent implementation
65 m : std::unique_ptr<HttpResponse> Post(const base::string16& host,
66 m : uint16_t port,
67 m : const base::string16& path,
68 m : bool secure,
69 m : const base::string16& extra_headers,
70 m : const std::string& body) override;
71 :
72 m : private:
73 m : Expectations expectations_;
74 m : std::unique_ptr<HttpResponse> response_;
75 m : bool invoked_;
76 :
77 m : DISALLOW_COPY_AND_ASSIGN(MockHttpAgent);
78 m : };
79 :
80 m : MockHttpAgent::MockHttpAgent() : invoked_(false) {
81 m : }
82 :
83 m : MockHttpAgent::~MockHttpAgent() {
84 m : EXPECT_TRUE(invoked_);
85 m : }
86 :
87 m : MockHttpAgent::Expectations& MockHttpAgent::expectations() {
88 m : return expectations_;
89 m : }
90 :
91 m : void MockHttpAgent::set_response(std::unique_ptr<HttpResponse> response) {
92 m : response_ = std::move(response);
93 m : }
94 :
95 m : std::unique_ptr<HttpResponse> MockHttpAgent::Post(
96 m : const base::string16& host,
97 m : uint16_t port,
98 m : const base::string16& path,
99 m : bool secure,
100 m : const base::string16& extra_headers,
101 m : const std::string& body) {
102 m : EXPECT_FALSE(invoked_);
103 m : invoked_ = true;
104 m : EXPECT_EQ(expectations_.host, host);
105 m : EXPECT_EQ(expectations_.port, port);
106 m : EXPECT_EQ(expectations_.path, path);
107 m : EXPECT_EQ(expectations_.secure, secure);
108 :
109 m : base::string16 boundary;
110 :
111 m : base::StringTokenizerT<base::string16, base::string16::const_iterator>
112 m : tokenizer(extra_headers.begin(), extra_headers.end(), L":");
113 m : if (!tokenizer.GetNext()) {
114 m : ADD_FAILURE() << "Failed to parse Content-Type from extra headers: "
115 m : << extra_headers;
116 m : } else {
117 m : EXPECT_EQ(L"content-type", base::ToLowerASCII(tokenizer.token()));
118 m : if (!tokenizer.GetNext()) {
119 m : ADD_FAILURE() << "Failed to parse Content-Type value from extra headers: "
120 m : << extra_headers;
121 m : } else {
122 m : base::string16 mime_type, charset;
123 m : bool had_charset = false;
124 : // Use extra_headers.end() since we don't want to choke on a theoretical :
125 : // embedded in the value.
126 m : ParseContentType(
127 m : base::string16(tokenizer.token_begin(), extra_headers.end()),
128 m : &mime_type, &charset, &had_charset, &boundary);
129 m : }
130 m : }
131 :
132 m : EXPECT_FALSE(boundary.empty());
133 :
134 m : ExpectMultipartMimeMessageIsPlausible(
135 m : boundary, expectations_.parameters, expectations_.file,
136 m : base::WideToUTF8(expectations_.file_name), body);
137 :
138 m : EXPECT_EQ(expectations_.host, host);
139 :
140 m : return std::move(response_);
141 m : }
142 :
143 : // An implementation of HttpResponse that may be configured to fail at any point
144 : // and to serve a response in a configurable series of packets.
145 m : class MockHttpResponse : public HttpResponse {
146 m : public:
147 m : MockHttpResponse();
148 :
149 : // HttpResponse implementation
150 m : bool GetStatusCode(uint16_t* status_code) override;
151 m : bool GetContentLength(bool* has_content_length,
152 m : size_t* content_length) override;
153 m : bool GetContentType(bool* has_content_type,
154 m : base::string16* content_type) override;
155 m : bool HasData(bool* has_data) override;
156 m : bool ReadData(char* buffer, size_t* count) override;
157 :
158 : // Sets the values that will be returned by GetStatusCode().
159 m : void set_status_code(bool success, uint16_t status_code);
160 :
161 : // Sets the values that will be returned by GetContentLength();
162 m : void set_content_length(bool success,
163 m : bool has_content_length,
164 m : size_t content_length);
165 :
166 : // Sets the values that will be returned by GetContentType();
167 m : void set_content_type(bool success,
168 m : bool has_content_type,
169 m : base::string16 content_type);
170 :
171 : // Configures the behaviour of HasData() and ReadData(). Each element in
172 : // |data| will be treated as a packet. Calls to ReadData() will consume all or
173 : // part of the current packet. HasData() will return true if there are
174 : // remaining packets. An empty element in |data| will signal the successful
175 : // completion of the data stream. If, after consuming all elements in |data|,
176 : // no empty packet is found, a read error will be simulated (ReadData() and
177 : // HasData() will both return false).
178 m : void set_data(const std::vector<std::string>& data);
179 :
180 m : private:
181 m : bool status_code_success_;
182 m : uint16_t status_code_;
183 m : bool content_length_success_;
184 m : bool has_content_length_;
185 m : size_t content_length_;
186 m : bool content_type_success_;
187 m : bool has_content_type_;
188 m : base::string16 content_type_;
189 m : std::vector<std::string> data_;
190 :
191 m : DISALLOW_COPY_AND_ASSIGN(MockHttpResponse);
192 m : };
193 :
194 m : MockHttpResponse::MockHttpResponse()
195 m : : status_code_success_(true),
196 m : status_code_(200),
197 m : content_length_success_(true),
198 m : has_content_length_(false),
199 m : content_length_(0),
200 m : content_type_success_(true),
201 m : has_content_type_(false) {
202 m : data_.push_back(std::string());
203 m : }
204 :
205 m : bool MockHttpResponse::GetStatusCode(uint16_t* status_code) {
206 m : DCHECK(status_code);
207 m : if (status_code && status_code_success_)
208 m : *status_code = status_code_;
209 m : return status_code_success_;
210 m : }
211 :
212 m : bool MockHttpResponse::GetContentLength(bool* has_content_length,
213 m : size_t* content_length) {
214 m : DCHECK(has_content_length);
215 m : DCHECK(content_length);
216 m : if (content_length_success_) {
217 m : *has_content_length = has_content_length_;
218 m : if (has_content_length_)
219 m : *content_length = content_length_;
220 m : }
221 m : return content_length_success_;
222 m : }
223 :
224 m : bool MockHttpResponse::GetContentType(bool* has_content_type,
225 m : base::string16* content_type) {
226 m : DCHECK(has_content_type);
227 m : DCHECK(content_type);
228 m : if (content_type_success_) {
229 m : *has_content_type = has_content_type_;
230 m : if (has_content_type_)
231 m : *content_type = content_type_;
232 m : }
233 m : return content_type_success_;
234 m : }
235 :
236 m : bool MockHttpResponse::HasData(bool* has_data) {
237 m : DCHECK(has_data);
238 m : if (data_.empty())
239 m : return false;
240 m : *has_data = !data_.front().empty();
241 m : return true;
242 m : }
243 :
244 m : bool MockHttpResponse::ReadData(char* buffer, size_t* count) {
245 m : DCHECK(buffer);
246 m : DCHECK(count);
247 m : if (data_.empty())
248 m : return false;
249 m : if (data_.front().empty()) {
250 m : *count = 0;
251 m : return true;
252 m : }
253 m : *count = std::min(*count, data_.front().length());
254 m : ::memcpy(buffer, data_.front().c_str(), *count);
255 m : data_.front().erase(0, *count);
256 m : if (data_.front().empty())
257 m : data_.erase(data_.begin());
258 m : return true;
259 m : }
260 :
261 m : void MockHttpResponse::set_status_code(bool success, uint16_t status_code) {
262 m : status_code_success_ = success;
263 m : status_code_ = status_code;
264 m : }
265 :
266 m : void MockHttpResponse::set_content_length(bool success,
267 m : bool has_content_length,
268 m : size_t content_length) {
269 m : content_length_success_ = success;
270 m : has_content_length_ = has_content_length;
271 m : content_length_ = content_length;
272 m : }
273 :
274 m : void MockHttpResponse::set_content_type(bool success,
275 m : bool has_content_type,
276 m : base::string16 content_type) {
277 m : content_type_success_ = success;
278 m : has_content_type_ = has_content_type;
279 m : content_type_ = content_type;
280 m : }
281 :
282 m : void MockHttpResponse::set_data(const std::vector<std::string>& data) {
283 m : data_ = data;
284 m : }
285 :
286 m : } // namespace
287 :
288 m : class UploadTest : public testing::Test {
289 m : protected:
290 m : void SetUp() override {
291 m : agent().expectations().host = L"example.com";
292 m : agent().expectations().port = 80;
293 m : agent().expectations().secure = false;
294 m : agent().expectations().path = L"/path/to/resource";
295 m : agent().expectations().file_name = L"file_name";
296 m : agent().expectations().file = "file contents";
297 m : agent().expectations().parameters[L"param"] = L"value";
298 m : }
299 :
300 m : MockHttpAgent& agent() { return agent_; }
301 :
302 m : bool SendUpload(base::string16* response_body, uint16_t* response_code);
303 :
304 m : private:
305 m : MockHttpAgent agent_;
306 m : };
307 :
308 m : bool UploadTest::SendUpload(base::string16* response_body,
309 m : uint16_t* response_code) {
310 m : return SendHttpUpload(
311 m : &agent(), (agent().expectations().secure ? L"https://" : L"http://") +
312 m : agent().expectations().host + agent().expectations().path,
313 m : agent().expectations().parameters, agent().expectations().file,
314 m : agent().expectations().file_name, response_body, response_code);
315 m : }
316 :
317 m : TEST_F(UploadTest, PostFails) {
318 m : base::string16 response_body;
319 m : uint16_t response_code = 0;
320 m : EXPECT_FALSE(SendUpload(&response_body, &response_code));
321 m : }
322 :
323 m : TEST_F(UploadTest, PostSucceeds) {
324 m : const std::string kResponse = "hello world";
325 :
326 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
327 m : std::vector<std::string> data;
328 m : data.push_back(kResponse);
329 m : data.push_back(std::string());
330 m : mock_response->set_data(data);
331 m : agent().set_response(std::move(mock_response));
332 :
333 m : base::string16 response_body;
334 m : uint16_t response_code = 0;
335 m : EXPECT_TRUE(SendUpload(&response_body, &response_code));
336 m : EXPECT_EQ(200, response_code);
337 m : EXPECT_EQ(base::UTF8ToWide(kResponse), response_body);
338 m : }
339 :
340 m : TEST_F(UploadTest, PostSucceedsSecure) {
341 m : const std::string kResponse = "hello world";
342 :
343 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
344 m : std::vector<std::string> data;
345 m : data.push_back(kResponse);
346 m : data.push_back(std::string());
347 m : mock_response->set_data(data);
348 m : agent().set_response(std::move(mock_response));
349 m : agent().expectations().secure = true;
350 m : agent().expectations().port = 443;
351 :
352 m : base::string16 response_body;
353 m : uint16_t response_code = 0;
354 m : EXPECT_TRUE(SendUpload(&response_body, &response_code));
355 m : EXPECT_EQ(200, response_code);
356 m : EXPECT_EQ(base::UTF8ToWide(kResponse), response_body);
357 m : }
358 :
359 m : TEST_F(UploadTest, InvalidURL) {
360 m : agent().set_expect_invocation(false);
361 m : base::string16 response_body;
362 m : uint16_t response_code = 0;
363 m : EXPECT_FALSE(SendHttpUpload(
364 m : &agent(),
365 m : L"@@::/:" + agent().expectations().host + agent().expectations().path,
366 m : agent().expectations().parameters, agent().expectations().file,
367 m : agent().expectations().file_name, &response_body, &response_code));
368 m : }
369 :
370 m : TEST_F(UploadTest, BadScheme) {
371 m : agent().set_expect_invocation(false);
372 m : base::string16 response_body;
373 m : uint16_t response_code = 0;
374 m : EXPECT_FALSE(SendHttpUpload(
375 m : &agent(),
376 m : L"ftp://" + agent().expectations().host + agent().expectations().path,
377 m : agent().expectations().parameters, agent().expectations().file,
378 m : agent().expectations().file_name, &response_body, &response_code));
379 m : }
380 :
381 m : TEST_F(UploadTest, GetStatusFails) {
382 m : const std::string kResponse = "hello world";
383 :
384 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
385 m : mock_response->set_status_code(false, 500);
386 m : agent().set_response(std::move(mock_response));
387 :
388 m : base::string16 response_body;
389 m : uint16_t response_code = 0;
390 m : EXPECT_FALSE(SendUpload(&response_body, &response_code));
391 m : }
392 :
393 m : TEST_F(UploadTest, PostSucceedsInMultiplePackets) {
394 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
395 m : const std::string kResponse1 = "hello ";
396 m : const std::string kResponse2 = "world";
397 m : std::vector<std::string> data;
398 m : data.push_back(kResponse1);
399 m : data.push_back(kResponse2);
400 m : data.push_back(std::string());
401 m : mock_response->set_data(data);
402 m : agent().set_response(std::move(mock_response));
403 :
404 m : base::string16 response_body;
405 m : uint16_t response_code = 0;
406 m : EXPECT_TRUE(SendUpload(&response_body, &response_code));
407 m : EXPECT_EQ(200, response_code);
408 m : EXPECT_EQ(base::UTF8ToWide(kResponse1 + kResponse2), response_body);
409 m : }
410 :
411 m : TEST_F(UploadTest, PostFailsInMultiplePackets) {
412 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
413 m : const std::string kResponse1 = "hello ";
414 m : const std::string kResponse2 = "world";
415 m : std::vector<std::string> data;
416 m : data.push_back(kResponse1);
417 m : data.push_back(kResponse2);
418 : // By omitting an empty packet here, we tell the MockHttpResponse to fail
419 : // after returning the above two packets.
420 m : mock_response->set_data(data);
421 m : agent().set_response(std::move(mock_response));
422 :
423 m : base::string16 response_body;
424 m : uint16_t response_code = 0;
425 m : EXPECT_FALSE(SendUpload(&response_body, &response_code));
426 m : }
427 :
428 m : TEST_F(UploadTest, TooMuchData) {
429 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
430 m : std::vector<std::string> data;
431 m : data.push_back(std::string(8192, 'x'));
432 m : data.push_back(std::string());
433 m : mock_response->set_data(data);
434 m : agent().set_response(std::move(mock_response));
435 :
436 m : base::string16 response_body;
437 m : uint16_t response_code = 0;
438 m : EXPECT_FALSE(SendUpload(&response_body, &response_code));
439 m : }
440 :
441 m : TEST_F(UploadTest, CorrectContentLength) {
442 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
443 m : std::string kResponse = "0123456789";
444 m : std::vector<std::string> data;
445 m : data.push_back(kResponse);
446 m : data.push_back(std::string());
447 m : mock_response->set_data(data);
448 m : mock_response->set_content_length(true, true, kResponse.length());
449 m : agent().set_response(std::move(mock_response));
450 :
451 m : base::string16 response_body;
452 m : uint16_t response_code = 0;
453 m : EXPECT_TRUE(SendUpload(&response_body, &response_code));
454 m : EXPECT_EQ(200, response_code);
455 m : EXPECT_EQ(base::UTF8ToWide(kResponse), response_body);
456 m : }
457 :
458 m : TEST_F(UploadTest, UnderContentLength) {
459 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
460 m : std::string kResponse = "0123456789";
461 m : std::vector<std::string> data;
462 m : data.push_back(kResponse);
463 m : data.push_back(std::string());
464 m : mock_response->set_data(data);
465 m : mock_response->set_content_length(true, true, kResponse.length() + 1);
466 m : agent().set_response(std::move(mock_response));
467 :
468 m : base::string16 response_body;
469 m : uint16_t response_code = 0;
470 m : EXPECT_FALSE(SendUpload(&response_body, &response_code));
471 m : }
472 :
473 m : TEST_F(UploadTest, OverContentLength) {
474 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
475 m : std::string kResponse = "0123456789";
476 m : std::vector<std::string> data;
477 m : data.push_back(kResponse);
478 m : data.push_back(std::string());
479 m : mock_response->set_data(data);
480 m : mock_response->set_content_length(true, true, kResponse.length() - 1);
481 m : agent().set_response(std::move(mock_response));
482 :
483 m : base::string16 response_body;
484 m : uint16_t response_code = 0;
485 m : EXPECT_FALSE(SendUpload(&response_body, &response_code));
486 m : }
487 :
488 m : TEST_F(UploadTest, OverContentLengthTwoPackets) {
489 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
490 m : std::string kResponse = "0123456789";
491 m : std::vector<std::string> data;
492 m : data.push_back(kResponse);
493 m : data.push_back(kResponse);
494 m : data.push_back(std::string());
495 m : mock_response->set_data(data);
496 m : mock_response->set_content_length(true, true, kResponse.length());
497 m : agent().set_response(std::move(mock_response));
498 :
499 m : base::string16 response_body;
500 m : uint16_t response_code = 0;
501 m : EXPECT_FALSE(SendUpload(&response_body, &response_code));
502 m : }
503 :
504 m : TEST_F(UploadTest, CorrectContentTypeAndCharset) {
505 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
506 m : std::string kResponse = "0123456789";
507 m : std::vector<std::string> data;
508 m : data.push_back(kResponse);
509 m : data.push_back(std::string());
510 m : mock_response->set_data(data);
511 m : mock_response->set_content_type(true, true, L"text/plain; charset=utf-8");
512 m : agent().set_response(std::move(mock_response));
513 :
514 m : base::string16 response_body;
515 m : uint16_t response_code = 0;
516 m : EXPECT_TRUE(SendUpload(&response_body, &response_code));
517 m : EXPECT_EQ(200, response_code);
518 m : EXPECT_EQ(base::UTF8ToWide(kResponse), response_body);
519 m : }
520 :
521 m : TEST_F(UploadTest, UnsupportedCharset) {
522 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
523 m : unsigned char kResponseArray[] = {'0', '1', '2', '3', 128, 0};
524 m : std::string kResponse = reinterpret_cast<char*>(kResponseArray);
525 m : std::vector<std::string> data;
526 m : data.push_back(kResponse);
527 m : data.push_back(std::string());
528 m : mock_response->set_data(data);
529 m : mock_response->set_content_type(true, true,
530 m : L"text/plain; charset=iso-8859-1");
531 m : agent().set_response(std::move(mock_response));
532 :
533 m : base::string16 response_body;
534 m : uint16_t response_code = 0;
535 m : EXPECT_FALSE(SendUpload(&response_body, &response_code));
536 m : }
537 :
538 m : TEST_F(UploadTest, ASCIISubsetOfLatin1) {
539 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
540 m : char kResponseArray[] = {'0', '1', '2', '3', 127, 0};
541 m : std::string kResponse = kResponseArray;
542 m : std::vector<std::string> data;
543 m : data.push_back(kResponse);
544 m : data.push_back(std::string());
545 m : mock_response->set_data(data);
546 m : mock_response->set_content_type(true, true,
547 m : L"text/plain; charset=iso-8859-1");
548 m : agent().set_response(std::move(mock_response));
549 :
550 m : base::string16 response_body;
551 m : uint16_t response_code = 0;
552 m : EXPECT_TRUE(SendUpload(&response_body, &response_code));
553 m : EXPECT_EQ(200, response_code);
554 m : EXPECT_EQ(base::UTF8ToWide(kResponse), response_body);
555 m : }
556 :
557 m : TEST_F(UploadTest, UnsupportedContentType) {
558 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
559 m : std::string kResponse = "<html><body>0123456789</body></html>";
560 m : std::vector<std::string> data;
561 m : data.push_back(kResponse);
562 m : data.push_back(std::string());
563 m : mock_response->set_data(data);
564 m : mock_response->set_content_type(true, true, L"text/html; charset=utf-8");
565 m : agent().set_response(std::move(mock_response));
566 :
567 m : base::string16 response_body;
568 m : uint16_t response_code = 0;
569 m : EXPECT_FALSE(SendUpload(&response_body, &response_code));
570 m : }
571 :
572 m : TEST_F(UploadTest, TextLabeledAsHTML) {
573 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
574 m : std::string kResponse = "0123456789";
575 m : std::vector<std::string> data;
576 m : data.push_back(kResponse);
577 m : data.push_back(std::string());
578 m : mock_response->set_data(data);
579 m : mock_response->set_content_type(true, true, L"text/html; charset=utf-8");
580 m : agent().set_response(std::move(mock_response));
581 :
582 m : base::string16 response_body;
583 m : uint16_t response_code = 0;
584 m : EXPECT_TRUE(SendUpload(&response_body, &response_code));
585 m : EXPECT_EQ(200, response_code);
586 m : EXPECT_EQ(base::UTF8ToWide(kResponse), response_body);
587 m : }
588 :
589 m : TEST_F(UploadTest, CorrectContentTypeNoCharset) {
590 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
591 m : std::string kResponse = "0123456789";
592 m : std::vector<std::string> data;
593 m : data.push_back(kResponse);
594 m : data.push_back(std::string());
595 m : mock_response->set_data(data);
596 m : mock_response->set_content_type(true, true, L"text/plain");
597 m : agent().set_response(std::move(mock_response));
598 :
599 m : base::string16 response_body;
600 m : uint16_t response_code = 0;
601 m : EXPECT_TRUE(SendUpload(&response_body, &response_code));
602 m : EXPECT_EQ(200, response_code);
603 m : EXPECT_EQ(base::UTF8ToWide(kResponse), response_body);
604 m : }
605 :
606 m : TEST_F(UploadTest, WideResponse) {
607 m : std::unique_ptr<MockHttpResponse> mock_response(new MockHttpResponse);
608 m : base::string16 kResponse = L"0123456789";
609 m : std::vector<std::string> data;
610 m : data.push_back(std::string(reinterpret_cast<const char*>(kResponse.data()),
611 m : kResponse.length() * sizeof(*kResponse.data())));
612 m : data.push_back(std::string());
613 m : mock_response->set_data(data);
614 m : mock_response->set_content_type(true, true, L"text/plain; charset=utf-16");
615 m : agent().set_response(std::move(mock_response));
616 :
617 m : base::string16 response_body;
618 m : uint16_t response_code = 0;
619 m : EXPECT_TRUE(SendUpload(&response_body, &response_code));
620 m : EXPECT_EQ(200, response_code);
621 m : EXPECT_EQ(kResponse, response_body);
622 m : }
623 :
624 m : } // namespace kasko
|