rippled
Loading...
Searching...
No Matches
JobQueue_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2017 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/Env.h>
21
22#include <xrpld/core/JobQueue.h>
23
24#include <xrpl/beast/unit_test.h>
25
26namespace ripple {
27namespace test {
28
29//------------------------------------------------------------------------------
30
32{
33 void
35 {
36 jtx::Env env{*this};
37
38 JobQueue& jQueue = env.app().getJobQueue();
39 {
40 // addJob() should run the Job (and return true).
41 std::atomic<bool> jobRan{false};
42 BEAST_EXPECT(jQueue.addJob(jtCLIENT, "JobAddTest1", [&jobRan]() {
43 jobRan = true;
44 }) == true);
45
46 // Wait for the Job to run.
47 while (jobRan == false)
48 ;
49 }
50 {
51 // If the JobQueue is stopped, we should no
52 // longer be able to add Jobs (and calling addJob() should
53 // return false).
54 using namespace std::chrono_literals;
55 jQueue.stop();
56
57 // The Job should never run, so having the Job access this
58 // unprotected variable on the stack should be completely safe.
59 // Not recommended for the faint of heart...
60 bool unprotected;
61 BEAST_EXPECT(
62 jQueue.addJob(jtCLIENT, "JobAddTest2", [&unprotected]() {
63 unprotected = false;
64 }) == false);
65 }
66 }
67
68 void
70 {
71 jtx::Env env{*this};
72
73 JobQueue& jQueue = env.app().getJobQueue();
74 {
75 // Test repeated post()s until the Coro completes.
76 std::atomic<int> yieldCount{0};
77 auto const coro = jQueue.postCoro(
79 "PostCoroTest1",
80 [&yieldCount](std::shared_ptr<JobQueue::Coro> const& coroCopy) {
81 while (++yieldCount < 4)
82 coroCopy->yield();
83 });
84 BEAST_EXPECT(coro != nullptr);
85
86 // Wait for the Job to run and yield.
87 while (yieldCount == 0)
88 ;
89
90 // Now re-post until the Coro says it is done.
91 int old = yieldCount;
92 while (coro->runnable())
93 {
94 BEAST_EXPECT(coro->post());
95 while (old == yieldCount)
96 {
97 }
98 coro->join();
99 BEAST_EXPECT(++old == yieldCount);
100 }
101 BEAST_EXPECT(yieldCount == 4);
102 }
103 {
104 // Test repeated resume()s until the Coro completes.
105 int yieldCount{0};
106 auto const coro = jQueue.postCoro(
107 jtCLIENT,
108 "PostCoroTest2",
109 [&yieldCount](std::shared_ptr<JobQueue::Coro> const& coroCopy) {
110 while (++yieldCount < 4)
111 coroCopy->yield();
112 });
113 if (!coro)
114 {
115 // There's no good reason we should not get a Coro, but we
116 // can't continue without one.
117 BEAST_EXPECT(false);
118 return;
119 }
120
121 // Wait for the Job to run and yield.
122 coro->join();
123
124 // Now resume until the Coro says it is done.
125 int old = yieldCount;
126 while (coro->runnable())
127 {
128 coro->resume(); // Resume runs synchronously on this thread.
129 BEAST_EXPECT(++old == yieldCount);
130 }
131 BEAST_EXPECT(yieldCount == 4);
132 }
133 {
134 // If the JobQueue is stopped, we should no
135 // longer be able to add a Coro (and calling postCoro() should
136 // return false).
137 using namespace std::chrono_literals;
138 jQueue.stop();
139
140 // The Coro should never run, so having the Coro access this
141 // unprotected variable on the stack should be completely safe.
142 // Not recommended for the faint of heart...
143 bool unprotected;
144 auto const coro = jQueue.postCoro(
145 jtCLIENT,
146 "PostCoroTest3",
147 [&unprotected](std::shared_ptr<JobQueue::Coro> const&) {
148 unprotected = false;
149 });
150 BEAST_EXPECT(coro == nullptr);
151 }
152 }
153
154public:
155 void
156 run() override
157 {
158 testAddJob();
159 testPostCoro();
160 }
161};
162
163BEAST_DEFINE_TESTSUITE(JobQueue, core, ripple);
164
165} // namespace test
166} // namespace ripple
A testsuite class.
Definition suite.h:55
A pool of threads to perform work.
Definition JobQueue.h:58
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:413
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
Definition JobQueue.h:168
void run() override
Runs the suite.
A transaction testing environment.
Definition Env.h:121
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
@ jtCLIENT
Definition Job.h:45