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