blob: 65de0d0a2ee095fc8a7cb50537e0702b3504a56c [file] [log] [blame]
// Copyright 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 "components/download/internal/background_service/in_memory_download_driver.h"
#include <memory>
#include "components/download/internal/background_service/test/mock_download_driver_client.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
namespace download {
namespace {
MATCHER_P(DriverEntryEqual, entry, "") {
return entry.guid == arg.guid && entry.state == arg.state &&
entry.bytes_downloaded == arg.bytes_downloaded;
}
// Test in memory download that doesn't do complex IO.
class TestInMemoryDownload : public InMemoryDownload {
public:
TestInMemoryDownload(const std::string& guid,
InMemoryDownload::Delegate* delegate)
: InMemoryDownload(guid), delegate_(delegate) {
DCHECK(delegate_) << "Delegate can't be nullptr.";
}
void SimulateDownloadStarted() {
state_ = InMemoryDownload::State::IN_PROGRESS;
delegate_->OnDownloadStarted(this);
}
void SimulateDownloadProgress() {
state_ = InMemoryDownload::State::IN_PROGRESS;
delegate_->OnDownloadProgress(this);
}
void SimulateDownloadComplete(bool success) {
state_ = success ? InMemoryDownload::State::COMPLETE
: InMemoryDownload::State::FAILED;
delegate_->OnDownloadComplete(this);
}
// InMemoryDownload implementation.
void Start() override {}
void Pause() override {}
void Resume() override {}
std::unique_ptr<storage::BlobDataHandle> ResultAsBlob() const override {
return nullptr;
}
size_t EstimateMemoryUsage() const override { return 0u; }
private:
InMemoryDownload::Delegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(TestInMemoryDownload);
};
// Factory that injects to InMemoryDownloadDriver and only creates fake objects.
class TestInMemoryDownloadFactory : public InMemoryDownload::Factory {
public:
TestInMemoryDownloadFactory() = default;
~TestInMemoryDownloadFactory() override = default;
// InMemoryDownload::Factory implementation.
std::unique_ptr<InMemoryDownload> Create(
const std::string& guid,
const RequestParams& request_params,
scoped_refptr<network::ResourceRequestBody> request_body,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
InMemoryDownload::Delegate* delegate) override {
auto download = std::make_unique<TestInMemoryDownload>(guid, delegate);
download_ = download.get();
return download;
}
// Returns the last created download, if the driver remove the object, this
// can be invalid memory, so need to use with caution.
TestInMemoryDownload* last_created_download() { return download_; }
private:
TestInMemoryDownload* download_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(TestInMemoryDownloadFactory);
};
class InMemoryDownloadDriverTest : public testing::Test {
public:
InMemoryDownloadDriverTest() = default;
~InMemoryDownloadDriverTest() override = default;
// Helper method to call public method on |driver_|.
DownloadDriver* driver() {
return static_cast<DownloadDriver*>(driver_.get());
}
MockDriverClient* driver_client() { return &driver_client_; }
TestInMemoryDownloadFactory* factory() { return factory_; }
void SetUp() override {
auto factory = std::make_unique<TestInMemoryDownloadFactory>();
factory_ = factory.get();
driver_ = std::make_unique<InMemoryDownloadDriver>(std::move(factory));
driver()->Initialize(&driver_client_);
}
void TearDown() override {
// Driver should be teared down before its owner.
driver_.reset();
}
void Start(const std::string& guid) {
RequestParams params;
base::FilePath path;
driver()->Start(params, guid, path, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
}
private:
testing::NiceMock<MockDriverClient> driver_client_;
std::unique_ptr<InMemoryDownloadDriver> driver_;
TestInMemoryDownloadFactory* factory_;
DISALLOW_COPY_AND_ASSIGN(InMemoryDownloadDriverTest);
};
// Verifies in memory download success and remove API.
TEST_F(InMemoryDownloadDriverTest, DownloadSuccessAndRemove) {
// General states check.
EXPECT_TRUE(driver()->IsReady());
const std::string guid = "1234";
EXPECT_CALL(*driver_client(), OnDownloadCreated(_)).Times(1);
Start(guid);
factory()->last_created_download()->SimulateDownloadStarted();
// After starting a download, we should be able to find a record in the
// driver.
base::Optional<DriverEntry> entry = driver()->Find(guid);
EXPECT_TRUE(entry.has_value());
EXPECT_EQ(guid, entry->guid);
EXPECT_EQ(DriverEntry::State::IN_PROGRESS, entry->state);
EXPECT_CALL(*driver_client(), OnDownloadUpdated(_));
factory()->last_created_download()->SimulateDownloadProgress();
DriverEntry match_entry;
match_entry.state = DriverEntry::State::COMPLETE;
match_entry.guid = guid;
EXPECT_CALL(*driver_client(),
OnDownloadSucceeded(DriverEntryEqual(match_entry)))
.Times(1);
EXPECT_CALL(*driver_client(), OnDownloadFailed(_, _)).Times(0);
// Trigger download complete.
factory()->last_created_download()->SimulateDownloadComplete(
true /* success*/);
EXPECT_TRUE(entry.has_value());
entry = driver()->Find(guid);
EXPECT_EQ(guid, entry->guid);
EXPECT_EQ(DriverEntry::State::COMPLETE, entry->state);
driver()->Remove(guid, false);
entry = driver()->Find(guid);
EXPECT_FALSE(entry.has_value());
}
// Verifies in memory download failure.
TEST_F(InMemoryDownloadDriverTest, DownloadFailure) {
// General states check.
EXPECT_TRUE(driver()->IsReady());
EXPECT_CALL(*driver_client(), OnDownloadCreated(_)).Times(1);
EXPECT_CALL(*driver_client(), OnDownloadUpdated(_)).Times(0);
const std::string guid = "1234";
Start(guid);
factory()->last_created_download()->SimulateDownloadStarted();
DriverEntry match_entry;
match_entry.state = DriverEntry::State::INTERRUPTED;
match_entry.guid = guid;
EXPECT_CALL(*driver_client(),
OnDownloadFailed(DriverEntryEqual(match_entry), _))
.Times(1);
EXPECT_CALL(*driver_client(), OnDownloadSucceeded(_)).Times(0);
// Trigger download complete.
factory()->last_created_download()->SimulateDownloadComplete(
false /* success*/);
base::Optional<DriverEntry> entry = driver()->Find(guid);
EXPECT_TRUE(entry.has_value());
EXPECT_EQ(guid, entry->guid);
EXPECT_EQ(DriverEntry::State::INTERRUPTED, entry->state);
}
} // namespace
} // namespace download