blob: 156d262cdafd09c6610f2cc22ef472b4d9ca54ae [file] [log] [blame]
// Copyright 2017 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 "content/browser/background_fetch/background_fetch_scheduler.h"
#include <vector>
#include "base/guid.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
#include "content/public/browser/browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::ElementsAre;
namespace content {
namespace {
const int kExampleServiceWorkerRegistrationId = 1;
const char kExampleDeveloperId1[] = "my-example-id";
const char kExampleDeveloperId2[] = "my-other-id";
class FakeController : public BackgroundFetchScheduler::Controller {
public:
FakeController(const BackgroundFetchRegistrationId& registration_id,
BackgroundFetchScheduler* scheduler,
const std::string& name,
std::vector<std::string>* controller_sequence_list,
int total_jobs)
: BackgroundFetchScheduler::Controller(scheduler,
registration_id,
base::DoNothing()),
controller_sequence_list_(controller_sequence_list),
name_(name),
total_jobs_(total_jobs) {}
~FakeController() override {}
// BackgroundFetchScheduler::Controller implementation:
bool HasMoreRequests() override { return jobs_started_ < total_jobs_; }
void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request,
RequestFinishedCallback callback) override {
DCHECK_LT(jobs_started_, total_jobs_);
++jobs_started_;
controller_sequence_list_->push_back(name_ +
base::IntToString(jobs_started_));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(std::move(callback), std::move(request)));
}
private:
int jobs_started_ = 0;
std::vector<std::string>* controller_sequence_list_;
std::string name_;
int total_jobs_;
};
class BackgroundFetchSchedulerTest
: public BackgroundFetchTestBase,
public BackgroundFetchScheduler::RequestProvider {
public:
BackgroundFetchSchedulerTest() : scheduler_(this) {}
// Posts itself as a task |number_of_barriers| times and on the last iteration
// invokes the quit_closure.
void PostQuitAfterRepeatingBarriers(base::Closure quit_closure,
int number_of_barriers) {
if (--number_of_barriers == 0) {
std::move(quit_closure).Run();
return;
}
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&BackgroundFetchSchedulerTest::PostQuitAfterRepeatingBarriers,
base::Unretained(this), std::move(quit_closure),
number_of_barriers));
}
void PopNextRequest(
const BackgroundFetchRegistrationId& registration_id,
BackgroundFetchScheduler::NextRequestCallback callback) override {
ServiceWorkerFetchRequest fetch_request(GURL(), "GET",
ServiceWorkerHeaderMap(),
Referrer(), false /* is_reload */);
auto request = base::MakeRefCounted<BackgroundFetchRequestInfo>(
0 /* request_count */, fetch_request);
request->InitializeDownloadGuid();
std::move(callback).Run(std::move(request));
}
void MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
base::OnceClosure closure) override {
std::move(closure).Run();
}
protected:
BackgroundFetchScheduler scheduler_;
std::vector<std::string> controller_sequence_list_;
};
} // namespace
TEST_F(BackgroundFetchSchedulerTest, SingleController) {
BackgroundFetchRegistrationId registration_id1(
kExampleServiceWorkerRegistrationId, origin(), kExampleDeveloperId1,
base::GenerateGUID());
FakeController controller(registration_id1, &scheduler_, "A",
&controller_sequence_list_, 4);
scheduler_.AddJobController(&controller);
base::RunLoop().RunUntilIdle();
EXPECT_THAT(controller_sequence_list_, ElementsAre("A1", "A2", "A3", "A4"));
}
TEST_F(BackgroundFetchSchedulerTest, TwoControllers) {
BackgroundFetchRegistrationId registration_id1(
kExampleServiceWorkerRegistrationId, origin(), kExampleDeveloperId1,
base::GenerateGUID());
BackgroundFetchRegistrationId registration_id2(
kExampleServiceWorkerRegistrationId, origin(), kExampleDeveloperId2,
base::GenerateGUID());
FakeController controller1(registration_id1, &scheduler_, "A",
&controller_sequence_list_, 4);
FakeController controller2(registration_id2, &scheduler_, "B",
&controller_sequence_list_, 4);
scheduler_.AddJobController(&controller1);
scheduler_.AddJobController(&controller2);
{
base::RunLoop run_loop;
PostQuitAfterRepeatingBarriers(run_loop.QuitClosure(), 3);
run_loop.Run();
// Only one task is run at a time so after 3 barrier iterations, 3 tasks
// should have been have run.
EXPECT_THAT(controller_sequence_list_, ElementsAre("A1", "A2", "A3"));
}
base::RunLoop().RunUntilIdle();
EXPECT_THAT(controller_sequence_list_,
ElementsAre("A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"));
}
} // namespace content