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
22#include <xrpld/core/JobQueue.h>
23
24#include <chrono>
25#include <mutex>
26
27namespace ripple {
28namespace test {
29
31{
32public:
33 class gate
34 {
35 private:
38 bool signaled_ = false;
39
40 public:
41 // Thread safe, blocks until signaled or period expires.
42 // Returns `true` if signaled.
43 template <class Rep, class Period>
44 bool
46 {
48 auto b = cv_.wait_for(lk, rel_time, [this] { return signaled_; });
49 signaled_ = false;
50 return b;
51 }
52
53 void
55 {
57 signaled_ = true;
59 }
60 };
61
62 void
64 {
65 using namespace std::chrono_literals;
66 using namespace jtx;
67
68 testcase("correct order");
69
70 Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
71 cfg->FORCE_MULTI_THREAD = true;
72 return cfg;
73 }));
74
75 gate g1, g2;
77 env.app().getJobQueue().postCoro(
78 jtCLIENT, "Coroutine-Test", [&](auto const& cr) {
79 c = cr;
80 g1.signal();
81 c->yield();
82 g2.signal();
83 });
84 BEAST_EXPECT(g1.wait_for(5s));
85 c->join();
86 c->post();
87 BEAST_EXPECT(g2.wait_for(5s));
88 }
89
90 void
92 {
93 using namespace std::chrono_literals;
94 using namespace jtx;
95
96 testcase("incorrect order");
97
98 Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
99 cfg->FORCE_MULTI_THREAD = true;
100 return cfg;
101 }));
102
103 gate g;
104 env.app().getJobQueue().postCoro(
105 jtCLIENT, "Coroutine-Test", [&](auto const& c) {
106 c->post();
107 c->yield();
108 g.signal();
109 });
110 BEAST_EXPECT(g.wait_for(5s));
111 }
112
113 void
115 {
116 using namespace std::chrono_literals;
117 using namespace jtx;
118
119 testcase("thread specific storage");
120 Env env(*this);
121
122 auto& jq = env.app().getJobQueue();
123
124 static int const N = 4;
126
127 LocalValue<int> lv(-1);
128 BEAST_EXPECT(*lv == -1);
129
130 gate g;
131 jq.addJob(jtCLIENT, "LocalValue-Test", [&]() {
132 this->BEAST_EXPECT(*lv == -1);
133 *lv = -2;
134 this->BEAST_EXPECT(*lv == -2);
135 g.signal();
136 });
137 BEAST_EXPECT(g.wait_for(5s));
138 BEAST_EXPECT(*lv == -1);
139
140 for (int i = 0; i < N; ++i)
141 {
142 jq.postCoro(jtCLIENT, "Coroutine-Test", [&, id = i](auto const& c) {
143 a[id] = c;
144 g.signal();
145 c->yield();
146
147 this->BEAST_EXPECT(*lv == -1);
148 *lv = id;
149 this->BEAST_EXPECT(*lv == id);
150 g.signal();
151 c->yield();
152
153 this->BEAST_EXPECT(*lv == id);
154 });
155 BEAST_EXPECT(g.wait_for(5s));
156 a[i]->join();
157 }
158 for (auto const& c : a)
159 {
160 c->post();
161 BEAST_EXPECT(g.wait_for(5s));
162 c->join();
163 }
164 for (auto const& c : a)
165 {
166 c->post();
167 c->join();
168 }
169
170 jq.addJob(jtCLIENT, "LocalValue-Test", [&]() {
171 this->BEAST_EXPECT(*lv == -2);
172 g.signal();
173 });
174 BEAST_EXPECT(g.wait_for(5s));
175 BEAST_EXPECT(*lv == -1);
176 }
177
178 void
179 run() override
180 {
184 }
185};
186
187BEAST_DEFINE_TESTSUITE(Coroutine, core, ripple);
188
189} // namespace test
190} // namespace ripple
A testsuite class.
Definition: suite.h:55
testcase_t testcase
Memberspace for declaring test cases.
Definition: suite.h:155
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:121
Application & app()
Definition: Env.h:261
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