rippled
Loading...
Searching...
No Matches
Coroutine_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <test/jtx.h>
21#include <xrpld/core/JobQueue.h>
22#include <chrono>
23#include <condition_variable>
24#include <mutex>
25
26namespace ripple {
27namespace test {
28
30{
31public:
32 class gate
33 {
34 private:
37 bool signaled_ = false;
38
39 public:
40 // Thread safe, blocks until signaled or period expires.
41 // Returns `true` if signaled.
42 template <class Rep, class Period>
43 bool
45 {
47 auto b = cv_.wait_for(lk, rel_time, [this] { return signaled_; });
48 signaled_ = false;
49 return b;
50 }
51
52 void
54 {
56 signaled_ = true;
58 }
59 };
60
61 void
63 {
64 using namespace std::chrono_literals;
65 using namespace jtx;
66
67 testcase("correct order");
68
69 Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
70 cfg->FORCE_MULTI_THREAD = true;
71 return cfg;
72 }));
73
74 gate g1, g2;
76 env.app().getJobQueue().postCoro(
77 jtCLIENT, "Coroutine-Test", [&](auto const& cr) {
78 c = cr;
79 g1.signal();
80 c->yield();
81 g2.signal();
82 });
83 BEAST_EXPECT(g1.wait_for(5s));
84 c->join();
85 c->post();
86 BEAST_EXPECT(g2.wait_for(5s));
87 }
88
89 void
91 {
92 using namespace std::chrono_literals;
93 using namespace jtx;
94
95 testcase("incorrect order");
96
97 Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
98 cfg->FORCE_MULTI_THREAD = true;
99 return cfg;
100 }));
101
102 gate g;
103 env.app().getJobQueue().postCoro(
104 jtCLIENT, "Coroutine-Test", [&](auto const& c) {
105 c->post();
106 c->yield();
107 g.signal();
108 });
109 BEAST_EXPECT(g.wait_for(5s));
110 }
111
112 void
114 {
115 using namespace std::chrono_literals;
116 using namespace jtx;
117
118 testcase("thread specific storage");
119 Env env(*this);
120
121 auto& jq = env.app().getJobQueue();
122
123 static int const N = 4;
125
126 LocalValue<int> lv(-1);
127 BEAST_EXPECT(*lv == -1);
128
129 gate g;
130 jq.addJob(jtCLIENT, "LocalValue-Test", [&]() {
131 this->BEAST_EXPECT(*lv == -1);
132 *lv = -2;
133 this->BEAST_EXPECT(*lv == -2);
134 g.signal();
135 });
136 BEAST_EXPECT(g.wait_for(5s));
137 BEAST_EXPECT(*lv == -1);
138
139 for (int i = 0; i < N; ++i)
140 {
141 jq.postCoro(jtCLIENT, "Coroutine-Test", [&, id = i](auto const& c) {
142 a[id] = c;
143 g.signal();
144 c->yield();
145
146 this->BEAST_EXPECT(*lv == -1);
147 *lv = id;
148 this->BEAST_EXPECT(*lv == id);
149 g.signal();
150 c->yield();
151
152 this->BEAST_EXPECT(*lv == id);
153 });
154 BEAST_EXPECT(g.wait_for(5s));
155 a[i]->join();
156 }
157 for (auto const& c : a)
158 {
159 c->post();
160 BEAST_EXPECT(g.wait_for(5s));
161 c->join();
162 }
163 for (auto const& c : a)
164 {
165 c->post();
166 c->join();
167 }
168
169 jq.addJob(jtCLIENT, "LocalValue-Test", [&]() {
170 this->BEAST_EXPECT(*lv == -2);
171 g.signal();
172 });
173 BEAST_EXPECT(g.wait_for(5s));
174 BEAST_EXPECT(*lv == -1);
175 }
176
177 void
178 run() override
179 {
183 }
184};
185
186BEAST_DEFINE_TESTSUITE(Coroutine, core, ripple);
187
188} // namespace test
189} // namespace ripple
A testsuite class.
Definition: suite.h:53
testcase_t testcase
Memberspace for declaring test cases.
Definition: suite.h:153
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:411
bool wait_for(std::chrono::duration< Rep, Period > const &rel_time)
void run() override
Runs the suite.
A transaction testing environment.
Definition: Env.h:117
Application & app()
Definition: Env.h:255
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:54
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
@ jtCLIENT
Definition: Job.h:45