]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rgw/test_rgw_reshard_wait.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / rgw / test_rgw_reshard_wait.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2018 Red Hat, Inc.
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include "rgw/rgw_reshard.h"
16 #include <spawn/spawn.hpp>
17
18 #include <gtest/gtest.h>
19
20 using namespace std::chrono_literals;
21 using Clock = RGWReshardWait::Clock;
22
23 TEST(ReshardWait, wait_block)
24 {
25 constexpr ceph::timespan wait_duration = 10ms;
26 RGWReshardWait waiter(wait_duration);
27
28 const auto start = Clock::now();
29 EXPECT_EQ(0, waiter.wait(null_yield));
30 const ceph::timespan elapsed = Clock::now() - start;
31
32 EXPECT_LE(wait_duration, elapsed); // waited at least 10ms
33 waiter.stop();
34 }
35
36 TEST(ReshardWait, stop_block)
37 {
38 constexpr ceph::timespan short_duration = 10ms;
39 constexpr ceph::timespan long_duration = 10s;
40
41 RGWReshardWait long_waiter(long_duration);
42 RGWReshardWait short_waiter(short_duration);
43
44 const auto start = Clock::now();
45 std::thread thread([&long_waiter] {
46 EXPECT_EQ(-ECANCELED, long_waiter.wait(null_yield));
47 });
48
49 EXPECT_EQ(0, short_waiter.wait(null_yield));
50
51 long_waiter.stop(); // cancel long waiter
52
53 thread.join();
54 const ceph::timespan elapsed = Clock::now() - start;
55
56 EXPECT_LE(short_duration, elapsed); // waited at least 10ms
57 EXPECT_GT(long_duration, elapsed); // waited less than 10s
58 short_waiter.stop();
59 }
60
61 TEST(ReshardWait, wait_yield)
62 {
63 constexpr ceph::timespan wait_duration = 50ms;
64 RGWReshardWait waiter(wait_duration);
65
66 boost::asio::io_context context;
67 spawn::spawn(context, [&] (yield_context yield) {
68 EXPECT_EQ(0, waiter.wait(optional_yield{context, yield}));
69 });
70
71 const auto start = Clock::now();
72 EXPECT_EQ(1u, context.poll()); // spawn
73 EXPECT_FALSE(context.stopped());
74
75 EXPECT_EQ(1u, context.run_one()); // timeout
76 EXPECT_TRUE(context.stopped());
77 const ceph::timespan elapsed = Clock::now() - start;
78
79 EXPECT_LE(wait_duration, elapsed); // waited at least 10ms
80 waiter.stop();
81 }
82
83 TEST(ReshardWait, stop_yield)
84 {
85 constexpr ceph::timespan short_duration = 50ms;
86 constexpr ceph::timespan long_duration = 10s;
87
88 RGWReshardWait long_waiter(long_duration);
89 RGWReshardWait short_waiter(short_duration);
90
91 boost::asio::io_context context;
92 spawn::spawn(context,
93 [&] (yield_context yield) {
94 EXPECT_EQ(-ECANCELED, long_waiter.wait(optional_yield{context, yield}));
95 });
96
97 const auto start = Clock::now();
98 EXPECT_EQ(1u, context.poll()); // spawn
99 EXPECT_FALSE(context.stopped());
100
101 EXPECT_EQ(0, short_waiter.wait(null_yield));
102
103 long_waiter.stop(); // cancel long waiter
104
105 EXPECT_EQ(1u, context.run_one_for(short_duration)); // timeout
106 EXPECT_TRUE(context.stopped());
107 const ceph::timespan elapsed = Clock::now() - start;
108
109 EXPECT_LE(short_duration, elapsed); // waited at least 10ms
110 EXPECT_GT(long_duration, elapsed); // waited less than 10s
111 short_waiter.stop();
112 }
113
114 TEST(ReshardWait, stop_multiple)
115 {
116 constexpr ceph::timespan short_duration = 50ms;
117 constexpr ceph::timespan long_duration = 10s;
118
119 RGWReshardWait long_waiter(long_duration);
120 RGWReshardWait short_waiter(short_duration);
121
122 // spawn 4 threads
123 std::vector<std::thread> threads;
124 {
125 auto sync_waiter([&long_waiter] {
126 EXPECT_EQ(-ECANCELED, long_waiter.wait(null_yield));
127 });
128 threads.emplace_back(sync_waiter);
129 threads.emplace_back(sync_waiter);
130 threads.emplace_back(sync_waiter);
131 threads.emplace_back(sync_waiter);
132 }
133 // spawn 4 coroutines
134 boost::asio::io_context context;
135 {
136 auto async_waiter = [&] (yield_context yield) {
137 EXPECT_EQ(-ECANCELED, long_waiter.wait(optional_yield{context, yield}));
138 };
139 spawn::spawn(context, async_waiter);
140 spawn::spawn(context, async_waiter);
141 spawn::spawn(context, async_waiter);
142 spawn::spawn(context, async_waiter);
143 }
144
145 const auto start = Clock::now();
146 EXPECT_EQ(4u, context.poll()); // spawn
147 EXPECT_FALSE(context.stopped());
148
149 EXPECT_EQ(0, short_waiter.wait(null_yield));
150
151 long_waiter.stop(); // cancel long waiter
152
153 EXPECT_EQ(4u, context.run_for(short_duration)); // timeout
154 EXPECT_TRUE(context.stopped());
155
156 for (auto& thread : threads) {
157 thread.join();
158 }
159 const ceph::timespan elapsed = Clock::now() - start;
160
161 EXPECT_LE(short_duration, elapsed); // waited at least 10ms
162 EXPECT_GT(long_duration, elapsed); // waited less than 10s
163 short_waiter.stop();
164 }