1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
3 #include "gtest/gtest.h"
5 #include "global/global_context.h"
6 #include "global/global_init.h"
7 #include "common/common_init.h"
9 #include "osd/scheduler/mClockScheduler.h"
10 #include "osd/scheduler/OpSchedulerItem.h"
12 using namespace ceph::osd::scheduler
;
14 int main(int argc
, char **argv
) {
15 std::vector
<const char*> args(argv
, argv
+argc
);
16 auto cct
= global_init(nullptr, args
, CEPH_ENTITY_TYPE_OSD
,
17 CODE_ENVIRONMENT_UTILITY
,
18 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE
);
19 common_init_finish(g_ceph_context
);
21 ::testing::InitGoogleTest(&argc
, argv
);
22 return RUN_ALL_TESTS();
26 class mClockSchedulerTest
: public testing::Test
{
34 mClockSchedulerTest() :
41 struct MockDmclockItem
: public PGOpQueueable
{
42 op_scheduler_class scheduler_class
;
44 MockDmclockItem(op_scheduler_class _scheduler_class
) :
45 PGOpQueueable(spg_t()),
46 scheduler_class(_scheduler_class
) {}
49 : MockDmclockItem(op_scheduler_class::background_best_effort
) {}
51 op_type_t
get_op_type() const final
{
52 return op_type_t::client_op
; // not used
55 ostream
&print(ostream
&rhs
) const final
{ return rhs
; }
57 std::optional
<OpRequestRef
> maybe_get_op() const final
{
61 op_scheduler_class
get_scheduler_class() const final
{
62 return scheduler_class
;
65 void run(OSD
*osd
, OSDShard
*sdata
, PGRef
& pg
, ThreadPool::TPHandle
&handle
) final
{}
69 template <typename
... Args
>
70 OpSchedulerItem
create_item(
71 epoch_t e
, uint64_t owner
, Args
&&... args
)
73 return OpSchedulerItem(
74 std::make_unique
<mClockSchedulerTest::MockDmclockItem
>(
75 std::forward
<Args
>(args
)...),
80 TEST_F(mClockSchedulerTest
, TestEmpty
) {
81 ASSERT_TRUE(q
.empty());
83 q
.enqueue(create_item(100, client1
, op_scheduler_class::client
));
84 q
.enqueue(create_item(102, client1
, op_scheduler_class::client
));
85 q
.enqueue(create_item(104, client1
, op_scheduler_class::client
));
87 ASSERT_FALSE(q
.empty());
89 std::list
<OpSchedulerItem
> reqs
;
91 reqs
.push_back(q
.dequeue());
92 reqs
.push_back(q
.dequeue());
94 ASSERT_FALSE(q
.empty());
96 for (auto &&i
: reqs
) {
97 q
.enqueue_front(std::move(i
));
101 ASSERT_FALSE(q
.empty());
103 for (int i
= 0; i
< 3; ++i
) {
104 ASSERT_FALSE(q
.empty());
108 ASSERT_TRUE(q
.empty());
111 TEST_F(mClockSchedulerTest
, TestSingleClientOrderedEnqueueDequeue
) {
112 q
.enqueue(create_item(100, client1
));
113 q
.enqueue(create_item(101, client1
));
114 q
.enqueue(create_item(102, client1
));
115 q
.enqueue(create_item(103, client1
));
116 q
.enqueue(create_item(104, client1
));
118 auto r
= q
.dequeue();
119 ASSERT_EQ(100u, r
.get_map_epoch());
122 ASSERT_EQ(101u, r
.get_map_epoch());
125 ASSERT_EQ(102u, r
.get_map_epoch());
128 ASSERT_EQ(103u, r
.get_map_epoch());
131 ASSERT_EQ(104u, r
.get_map_epoch());
134 TEST_F(mClockSchedulerTest
, TestMultiClientOrderedEnqueueDequeue
) {
135 const unsigned NUM
= 1000;
136 for (unsigned i
= 0; i
< NUM
; ++i
) {
137 for (auto &&c
: {client1
, client2
, client3
}) {
138 q
.enqueue(create_item(i
, c
));
142 std::map
<uint64_t, epoch_t
> next
;
143 for (auto &&c
: {client1
, client2
, client3
}) {
146 for (unsigned i
= 0; i
< NUM
* 3; ++i
) {
147 ASSERT_FALSE(q
.empty());
148 auto r
= q
.dequeue();
149 auto owner
= r
.get_owner();
150 auto niter
= next
.find(owner
);
151 ASSERT_FALSE(niter
== next
.end());
152 ASSERT_EQ(niter
->second
, r
.get_map_epoch());
155 ASSERT_TRUE(q
.empty());