1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
content / browser / background_sync / background_sync_op_scheduler_unittest.cc [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/background_sync/background_sync_op_scheduler.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/scoped_feature_list.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace background_sync_op_scheduler_unittest {
class TestTask {
public:
explicit TestTask(BackgroundSyncOpScheduler* scheduler)
: scheduler_(scheduler), callback_count_(0) {}
virtual void Run() {
callback_count_++;
run_loop_.Quit();
}
void Done() { scheduler_->CompleteOperationAndRunNext(); }
int callback_count() const { return callback_count_; }
base::RunLoop& run_loop() { return run_loop_; }
protected:
raw_ptr<BackgroundSyncOpScheduler> scheduler_;
base::RunLoop run_loop_;
int callback_count_;
};
class TestScheduler : public BackgroundSyncOpScheduler {
public:
TestScheduler()
: BackgroundSyncOpScheduler(
base::SingleThreadTaskRunner::GetCurrentDefault()) {}
void SetDoneStartingClosure(base::OnceClosure done_closure) {
CHECK(!done_closure_);
done_closure_ = std::move(done_closure);
}
protected:
void DoneStartingAvailableOperations() override {
if (done_closure_) {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, std::move(done_closure_));
}
BackgroundSyncOpScheduler::DoneStartingAvailableOperations();
}
base::OnceClosure done_closure_;
};
class BackgroundSyncOpSchedulerTest : public testing::Test {
protected:
BackgroundSyncOpSchedulerTest()
: task_environment_(BrowserTaskEnvironment::IO_MAINLOOP),
task1_(&scheduler_),
task2_(&scheduler_),
task3_(&scheduler_) {}
BrowserTaskEnvironment task_environment_;
TestScheduler scheduler_;
TestTask task1_;
TestTask task2_;
TestTask task3_;
};
TEST_F(BackgroundSyncOpSchedulerTest, ScheduleOne) {
base::RunLoop done_loop;
scheduler_.SetDoneStartingClosure(done_loop.QuitClosure());
scheduler_.ScheduleOperation(
base::BindOnce(&TestTask::Run, base::Unretained(&task1_)));
task1_.run_loop().Run();
done_loop.Run();
EXPECT_EQ(1, task1_.callback_count());
}
TEST_F(BackgroundSyncOpSchedulerTest, ScheduledOperations) {
base::RunLoop done_loop;
scheduler_.SetDoneStartingClosure(done_loop.QuitClosure());
scheduler_.ScheduleOperation(
base::BindOnce(&TestTask::Run, base::Unretained(&task1_)));
EXPECT_TRUE(scheduler_.ScheduledOperations());
task1_.run_loop().Run();
done_loop.Run();
EXPECT_EQ(1, task1_.callback_count());
EXPECT_TRUE(scheduler_.ScheduledOperations());
task1_.Done();
EXPECT_FALSE(scheduler_.ScheduledOperations());
}
TEST_F(BackgroundSyncOpSchedulerTest, ScheduleTwoExclusive) {
scheduler_.ScheduleOperation(
base::BindOnce(&TestTask::Run, base::Unretained(&task1_)));
base::RunLoop done_loop1;
scheduler_.SetDoneStartingClosure(done_loop1.QuitClosure());
scheduler_.ScheduleOperation(
base::BindOnce(&TestTask::Run, base::Unretained(&task2_)));
// Should only run the first exclusive op.
task1_.run_loop().Run();
done_loop1.Run();
EXPECT_EQ(1, task1_.callback_count());
EXPECT_EQ(0, task2_.callback_count());
base::RunLoop done_loop2;
scheduler_.SetDoneStartingClosure(done_loop2.QuitClosure());
// Should run the second exclusive op after the first completes.
task1_.Done();
EXPECT_TRUE(scheduler_.ScheduledOperations());
task2_.run_loop().Run();
done_loop2.Run();
EXPECT_EQ(1, task1_.callback_count());
EXPECT_EQ(1, task2_.callback_count());
}
} // namespace background_sync_op_scheduler_unittest
} // namespace content