blob: 38b18f5f88ff43d2859a2d93af24c8c34f0212c7 [file] [log] [blame]
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/chrome_cleaner/http/mock_http_agent_factory.h"
#include <stdint.h>
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include "base/logging.h"
#include "chrome/chrome_cleaner/http/http_agent.h"
#include "chrome/chrome_cleaner/http/http_agent_factory.h"
#include "chrome/chrome_cleaner/http/http_response.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chrome_cleaner {
namespace {
// Class that provides a response based on how the MockHttpAgentConfig is
// configured.
class MockHttpResponse : public chrome_cleaner::HttpResponse {
public:
explicit MockHttpResponse(MockHttpAgentConfig* config) : config_(config) {
DCHECK(config);
}
~MockHttpResponse() override = default;
// chrome_cleaner::HttpResponse:
bool GetStatusCode(uint16_t* status_code) override {
if (config_->GetCurrentCalls().get_status_code_succeeds) {
*status_code = static_cast<uint16_t>(
config_->GetCurrentCalls().get_status_code_result);
}
return config_->GetCurrentCalls().get_status_code_succeeds;
}
bool GetContentLength(bool* has_content_length,
size_t* content_length) override {
ADD_FAILURE() << "This method should not be called.";
return false;
}
bool GetContentType(bool* has_content_type,
base::string16* content_type) override {
ADD_FAILURE() << "This method should not be called.";
return false;
}
bool HasData(bool* has_data) override {
if (config_->GetCurrentCalls().has_data_succeeds)
*has_data = !config_->GetCurrentCalls().read_data_result.empty();
return config_->GetCurrentCalls().has_data_succeeds;
}
bool ReadData(char* buffer, size_t* count) override {
MockHttpAgentConfig::Calls& calls = config_->GetCurrentCalls();
bool succeeds = calls.read_data_succeeds_by_default;
if (!calls.read_data_success_sequence.empty()) {
succeeds = calls.read_data_success_sequence[0];
calls.read_data_success_sequence.erase(
calls.read_data_success_sequence.begin());
}
if (succeeds)
config_->ReadData(buffer, count);
return succeeds;
}
private:
MockHttpAgentConfig* config_{nullptr};
DISALLOW_COPY_AND_ASSIGN(MockHttpResponse);
};
// Class that acts as an HttpAgent based on how the MockHttpAgentConfig is
// configured.
class MockHttpAgent : public chrome_cleaner::HttpAgent {
public:
explicit MockHttpAgent(MockHttpAgentConfig* config) : config_(config) {
DCHECK(config);
}
~MockHttpAgent() override = default;
// chrome_cleaner::HttpAgent:
std::unique_ptr<chrome_cleaner::HttpResponse> Post(
const base::string16& host,
uint16_t port,
const base::string16& path,
bool secure,
const base::string16& extra_headers,
const std::string& body,
const net::NetworkTrafficAnnotationTag& /*traffic_annotation*/) override {
const bool post_succeeds = config_->GetCurrentCalls().request_succeeds;
MockHttpAgentConfig::RequestData post_data;
post_data.host = host;
post_data.port = port;
post_data.path = path;
post_data.secure = secure;
post_data.extra_headers = extra_headers;
post_data.body = body;
config_->AddRequestData(post_data);
if (post_succeeds)
return std::make_unique<MockHttpResponse>(config_);
return std::unique_ptr<MockHttpResponse>();
}
// chrome_cleaner::HttpAgent:
std::unique_ptr<chrome_cleaner::HttpResponse> Get(
const base::string16& host,
uint16_t port,
const base::string16& path,
bool secure,
const base::string16& extra_headers,
const net::NetworkTrafficAnnotationTag& /*traffic_annotation*/) override {
const bool get_succeeds = config_->GetCurrentCalls().request_succeeds;
MockHttpAgentConfig::RequestData get_data;
get_data.host = host;
get_data.port = port;
get_data.path = path;
get_data.secure = secure;
get_data.extra_headers = extra_headers;
config_->AddRequestData(get_data);
if (get_succeeds)
return std::make_unique<MockHttpResponse>(config_);
return std::unique_ptr<MockHttpResponse>();
}
private:
MockHttpAgentConfig* config_{nullptr};
DISALLOW_COPY_AND_ASSIGN(MockHttpAgent);
};
} // namespace
MockHttpAgentConfig::Calls::Calls(HttpStatus status)
: get_status_code_result(status) {}
MockHttpAgentConfig::Calls::Calls(const Calls& other) = default;
MockHttpAgentConfig::Calls::~Calls() = default;
MockHttpAgentConfig::Calls& MockHttpAgentConfig::Calls::operator=(
const MockHttpAgentConfig::Calls& other) = default;
MockHttpAgentConfig::RequestData::RequestData() = default;
MockHttpAgentConfig::RequestData::RequestData(const RequestData& other) =
default;
MockHttpAgentConfig::RequestData::~RequestData() = default;
MockHttpAgentConfig::RequestData& MockHttpAgentConfig::RequestData::operator=(
const MockHttpAgentConfig::RequestData& other) = default;
MockHttpAgentConfig::MockHttpAgentConfig() = default;
MockHttpAgentConfig::~MockHttpAgentConfig() = default;
size_t MockHttpAgentConfig::AddCalls(const Calls& calls) {
calls_.push_back(calls);
return calls_.size() - 1;
}
MockHttpAgentConfig::Calls& MockHttpAgentConfig::GetCurrentCalls() {
if (current_index_ >= calls_.size()) {
static Calls default_calls(HttpStatus::kOk);
ADD_FAILURE() << "Did not expect more than " << calls_.size() << " tries";
return default_calls;
}
return calls_[current_index_];
}
void MockHttpAgentConfig::ReadData(char* buffer, size_t* count) {
if (current_index_ >= calls_.size()) {
ADD_FAILURE() << "Reading data for an unexpected call";
*count = 0;
return;
}
Calls& calls = calls_[current_index_];
*count = std::min(*count, calls.read_data_result.size());
memcpy(buffer, calls.read_data_result.c_str(), *count);
calls.read_data_result = calls.read_data_result.substr(*count);
}
void MockHttpAgentConfig::AddRequestData(const RequestData& request_data) {
ASSERT_EQ(request_data_.size(), current_index_)
<< "MockHttpAgentConfig does not support creating multiple agents "
<< "without calling Post or Get on each before creating the next one. "
<< "Suggest adding support to MockHttpAgentConfig for that if necessary, "
<< "or updating your code to avoid this.";
request_data_.push_back(request_data);
}
MockHttpAgentFactory::MockHttpAgentFactory(MockHttpAgentConfig* config)
: config_(config) {
DCHECK(config);
}
std::unique_ptr<chrome_cleaner::HttpAgent>
MockHttpAgentFactory::CreateHttpAgent() {
// Set the configuration index to the next one (one per HttpAgent).
if (config_->current_index_ == MockHttpAgentConfig::kInvalidIndex)
config_->current_index_ = 0;
else
++config_->current_index_;
return std::make_unique<MockHttpAgent>(config_);
}
} // namespace chrome_cleaner