xrpld
Loading...
Searching...
No Matches
Coroutine_test.cpp
1
2#include <test/jtx/Env.h>
3#include <test/jtx/envconfig.h>
4
5#include <xrpld/core/Config.h>
6
7#include <xrpl/basics/LocalValue.h>
8#include <xrpl/beast/unit_test/suite.h>
9#include <xrpl/core/Job.h>
10#include <xrpl/core/JobQueue.h>
11
12#include <array>
13#include <chrono>
14#include <condition_variable>
15#include <memory>
16#include <mutex>
17
18namespace xrpl::test {
19
21{
22public:
23 class Gate
24 {
25 private:
28 bool signaled_ = false;
29
30 public:
31 // Thread safe, blocks until signaled or period expires.
32 // Returns `true` if signaled.
33 template <class Rep, class Period>
34 bool
36 {
38 auto b = cv_.wait_for(lk, relTime, [this] { return signaled_; });
39 signaled_ = false;
40 return b;
41 }
42
43 void
45 {
46 std::scoped_lock const lk(mutex_);
47 signaled_ = true;
48 cv_.notify_all();
49 }
50 };
51
52 void
54 {
55 using namespace std::chrono_literals;
56 using namespace jtx;
57
58 testcase("correct order");
59
60 Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
61 cfg->forceMultiThread = true;
62 return cfg;
63 }));
64
65 Gate g1, g2;
67 env.app().getJobQueue().postCoro(JtClient, "CoroTest", [&](auto const& cr) {
68 c = cr;
69 g1.signal();
70 c->yield();
71 g2.signal();
72 });
73 BEAST_EXPECT(g1.waitFor(5s));
74 c->join();
75 c->post();
76 BEAST_EXPECT(g2.waitFor(5s));
77 }
78
79 void
81 {
82 using namespace std::chrono_literals;
83 using namespace jtx;
84
85 testcase("incorrect order");
86
87 Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
88 cfg->forceMultiThread = true;
89 return cfg;
90 }));
91
92 Gate g;
93 env.app().getJobQueue().postCoro(JtClient, "CoroTest", [&](auto const& c) {
94 c->post();
95 c->yield();
96 g.signal();
97 });
98 BEAST_EXPECT(g.waitFor(5s));
99 }
100
101 void
103 {
104 using namespace std::chrono_literals;
105 using namespace jtx;
106
107 testcase("thread specific storage");
108 Env env(*this);
109
110 auto& jq = env.app().getJobQueue();
111
112 static int const kN = 4;
114
115 LocalValue<int> lv(-1);
116 BEAST_EXPECT(*lv == -1);
117
118 Gate g;
119 jq.addJob(JtClient, "LocalValTest", [&]() {
120 this->BEAST_EXPECT(*lv == -1);
121 *lv = -2;
122 this->BEAST_EXPECT(*lv == -2);
123 g.signal();
124 });
125 BEAST_EXPECT(g.waitFor(5s));
126 BEAST_EXPECT(*lv == -1);
127
128 for (int i = 0; i < kN; ++i)
129 {
130 jq.postCoro(JtClient, "CoroTest", [&, id = i](auto const& c) {
131 a[id] = c;
132 g.signal();
133 c->yield();
134
135 this->BEAST_EXPECT(*lv == -1);
136 *lv = id;
137 this->BEAST_EXPECT(*lv == id);
138 g.signal();
139 c->yield();
140
141 this->BEAST_EXPECT(*lv == id);
142 });
143 BEAST_EXPECT(g.waitFor(5s));
144 a[i]->join();
145 }
146 for (auto const& c : a)
147 {
148 c->post();
149 BEAST_EXPECT(g.waitFor(5s));
150 c->join();
151 }
152 for (auto const& c : a)
153 {
154 c->post();
155 c->join();
156 }
157
158 jq.addJob(JtClient, "LocalValTest", [&]() {
159 this->BEAST_EXPECT(*lv == -2);
160 g.signal();
161 });
162 BEAST_EXPECT(g.waitFor(5s));
163 BEAST_EXPECT(*lv == -1);
164 }
165
166 void
167 run() override
168 {
169 correctOrder();
172 }
173};
174
175BEAST_DEFINE_TESTSUITE(Coroutine, core, xrpl);
176
177} // namespace xrpl::test
A testsuite class.
Definition suite.h:50
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
virtual JobQueue & getJobQueue()=0
bool waitFor(std::chrono::duration< Rep, Period > const &relTime)
void run() override
Runs the suite.
A transaction testing environment.
Definition Env.h:143
Application & app()
Definition Env.h:280
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:28
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
@ JtClient
Definition Job.h:26