Coverage for /Syzygy/kasko/upload_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
98.7%3673720.C++test

Line-by-line coverage:

   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

Coverage information generated Thu Jan 14 17:40:38 2016.