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