Coverage for /Syzygy/kasko/upload_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%00485.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 <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

Coverage information generated Fri Jul 29 11:00:21 2016.