@@ -61,7 +61,7 @@ struct test_service {
6161
6262TEST_F (AsyncContextTest, AsyncServiceTest)
6363{
64- using enum async_context::context_states ;
64+ using enum async_context::context_state ;
6565
6666 auto service = basic_context_thread<test_service>();
6767 service.start ();
@@ -74,7 +74,7 @@ TEST_F(AsyncContextTest, AsyncServiceTest)
7474
7575TEST_F (AsyncContextTest, StartTwiceTest)
7676{
77- using enum async_context::context_states ;
77+ using enum async_context::context_state ;
7878
7979 auto service = basic_context_thread<test_service>{};
8080
@@ -89,7 +89,7 @@ TEST_F(AsyncContextTest, StartTwiceTest)
8989
9090TEST_F (AsyncContextTest, TestUser1Signal)
9191{
92- using enum async_context::context_states ;
92+ using enum async_context::context_state ;
9393
9494 auto service = basic_context_thread<test_service>();
9595
@@ -103,4 +103,205 @@ TEST_F(AsyncContextTest, TestUser1Signal)
103103 }
104104 EXPECT_EQ (test_signal, service.user1 );
105105}
106+
107+ TEST_F (AsyncContextTest, WaitUntilStarted)
108+ {
109+ using enum async_context::context_state;
110+
111+ auto service = basic_context_thread<test_service>();
112+ ASSERT_EQ (service.state , PENDING);
113+
114+ auto wait_thread = std::thread ([&] { service.wait_until (STARTED); });
115+
116+ service.start ();
117+ wait_thread.join ();
118+
119+ ASSERT_EQ (service.state , STARTED);
120+ }
121+
122+ TEST_F (AsyncContextTest, WaitUntilStopped)
123+ {
124+ using enum async_context::context_state;
125+
126+ auto service = basic_context_thread<test_service>();
127+ service.start ();
128+ ASSERT_EQ (service.state , STARTED);
129+
130+ auto wait_thread = std::thread ([&] { service.wait_until (STOPPED); });
131+
132+ service.signal (service.terminate );
133+ wait_thread.join ();
134+
135+ ASSERT_EQ (service.state , STOPPED);
136+ }
137+
138+ TEST_F (AsyncContextTest, WaitUntilAlreadySatisfied)
139+ {
140+ using enum async_context::context_state;
141+
142+ auto service = basic_context_thread<test_service>();
143+ service.start ();
144+ ASSERT_EQ (service.state , STARTED);
145+
146+ service.wait_until (PENDING);
147+ EXPECT_EQ (service.state , STARTED);
148+
149+ service.wait_until (STARTED);
150+ EXPECT_EQ (service.state , STARTED);
151+ }
152+
153+ TEST_F (AsyncContextTest, WaitUntilMultipleWaiters)
154+ {
155+ using enum async_context::context_state;
156+
157+ auto service = basic_context_thread<test_service>();
158+ ASSERT_EQ (service.state , PENDING);
159+
160+ std::atomic<int > waiters_unblocked{0 };
161+
162+ auto wait_thread1 = std::thread ([&] {
163+ service.wait_until (STARTED);
164+ waiters_unblocked.fetch_add (1 );
165+ });
166+
167+ auto wait_thread2 = std::thread ([&] {
168+ service.wait_until (STARTED);
169+ waiters_unblocked.fetch_add (1 );
170+ });
171+
172+ auto wait_thread3 = std::thread ([&] {
173+ service.wait_until (STARTED);
174+ waiters_unblocked.fetch_add (1 );
175+ });
176+
177+ std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
178+ EXPECT_EQ (waiters_unblocked.load (), 0 );
179+
180+ service.start ();
181+
182+ wait_thread1.join ();
183+ wait_thread2.join ();
184+ wait_thread3.join ();
185+
186+ EXPECT_EQ (waiters_unblocked.load (), 3 );
187+ ASSERT_EQ (service.state , STARTED);
188+ }
189+
190+ TEST_F (AsyncContextTest, WaitUntilPendingToStopped)
191+ {
192+ using enum async_context::context_state;
193+
194+ auto service = basic_context_thread<test_service>();
195+ ASSERT_EQ (service.state , PENDING);
196+
197+ auto wait_thread = std::thread ([&] { service.wait_until (STOPPED); });
198+
199+ service.start ();
200+ std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
201+
202+ service.signal (service.terminate );
203+ wait_thread.join ();
204+
205+ ASSERT_EQ (service.state , STOPPED);
206+ }
207+
208+ TEST_F (AsyncContextTest, WaitFromPendingToStopped)
209+ {
210+ using enum async_context::context_state;
211+
212+ auto service = basic_context_thread<test_service>();
213+ ASSERT_EQ (service.state , PENDING);
214+
215+ auto wait_thread = std::thread ([&] { service.wait (); });
216+
217+ service.start ();
218+ std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
219+
220+ service.signal (service.terminate );
221+ wait_thread.join ();
222+
223+ ASSERT_EQ (service.state , STOPPED);
224+ }
225+
226+ TEST_F (AsyncContextTest, WaitFromStartedToStopped)
227+ {
228+ using enum async_context::context_state;
229+
230+ auto service = basic_context_thread<test_service>();
231+ service.start ();
232+ ASSERT_EQ (service.state , STARTED);
233+
234+ auto wait_thread = std::thread ([&] { service.wait (); });
235+
236+ service.signal (service.terminate );
237+ wait_thread.join ();
238+
239+ ASSERT_EQ (service.state , STOPPED);
240+ }
241+
242+ TEST_F (AsyncContextTest, WaitWhenAlreadyStopped)
243+ {
244+ using enum async_context::context_state;
245+
246+ auto service = basic_context_thread<test_service>();
247+ service.start ();
248+ ASSERT_EQ (service.state , STARTED);
249+
250+ service.signal (service.terminate );
251+ service.state .wait (STARTED);
252+ ASSERT_EQ (service.state , STOPPED);
253+
254+ service.wait ();
255+
256+ EXPECT_EQ (service.state , STOPPED);
257+ }
258+
259+ TEST_F (AsyncContextTest, WaitMultipleWaiters)
260+ {
261+ using enum async_context::context_state;
262+
263+ auto service = basic_context_thread<test_service>();
264+ service.start ();
265+ ASSERT_EQ (service.state , STARTED);
266+
267+ std::atomic<int > waiters_unblocked{0 };
268+
269+ auto wait_thread1 = std::thread ([&] {
270+ service.wait ();
271+ waiters_unblocked.fetch_add (1 );
272+ });
273+
274+ auto wait_thread2 = std::thread ([&] {
275+ service.wait ();
276+ waiters_unblocked.fetch_add (1 );
277+ });
278+
279+ auto wait_thread3 = std::thread ([&] {
280+ service.wait ();
281+ waiters_unblocked.fetch_add (1 );
282+ });
283+
284+ std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
285+ EXPECT_EQ (waiters_unblocked.load (), 0 );
286+
287+ service.signal (service.terminate );
288+
289+ wait_thread1.join ();
290+ wait_thread2.join ();
291+ wait_thread3.join ();
292+
293+ EXPECT_EQ (waiters_unblocked.load (), 3 );
294+ ASSERT_EQ (service.state , STOPPED);
295+ }
296+
297+ TEST_F (AsyncContextTest, WaitNoexceptGuarantee)
298+ {
299+ auto service = basic_context_thread<test_service>();
300+ service.start ();
301+
302+ EXPECT_TRUE (noexcept (service.wait ()));
303+
304+ service.signal (service.terminate );
305+ service.wait ();
306+ }
106307// NOLINTEND
0 commit comments