1 /*
2  * A simple test for so_has_subscription method.
3  */
4 
5 #include <iostream>
6 #include <map>
7 #include <exception>
8 #include <stdexcept>
9 #include <cstdlib>
10 #include <thread>
11 #include <chrono>
12 
13 #include <so_5/all.hpp>
14 
15 #include <test/3rd_party/various_helpers/time_limited_execution.hpp>
16 #include <test/3rd_party/various_helpers/ensure.hpp>
17 
18 class a_test_t : public so_5::agent_t
19 {
20 	struct finish : public so_5::signal_t {};
21 
22 	struct sig_1 : public so_5::signal_t {};
23 	struct sig_2 : public so_5::signal_t {};
24 
25 	struct msg_1 : public so_5::message_t {};
26 	struct msg_2 : public so_5::message_t {};
27 	struct msg_3 : public so_5::message_t {};
28 	struct msg_4 : public so_5::message_t {};
29 	struct msg_5 : public so_5::message_t {};
30 
31 	struct umsg_1 {};
32 	struct umsg_2 {};
33 	struct umsg_3 {};
34 	struct umsg_4 {};
35 	struct umsg_5 {};
36 	struct umsg_6 {};
37 
38 	struct ret_msg_1 : public so_5::message_t {};
39 	struct ret_msg_2 : public so_5::message_t {};
40 	struct ret_msg_3 : public so_5::message_t {};
41 	struct ret_msg_4 : public so_5::message_t {};
42 	struct ret_msg_5 : public so_5::message_t {};
43 
44 	struct ret_umsg_1 {};
45 	struct ret_umsg_2 {};
46 	struct ret_umsg_3 {};
47 	struct ret_umsg_4 {};
48 	struct ret_umsg_5 {};
49 	struct ret_umsg_6 {};
50 
51 public :
a_test_t(context_t ctx)52 	a_test_t( context_t ctx )
53 		:	so_5::agent_t( ctx )
54 	{}
55 
56 	virtual void
so_define_agent()57 	so_define_agent() override
58 	{
59 		so_subscribe_self()
60 				.event( &a_test_t::on_finish )
61 				.event( &a_test_t::on_sig_1 )
62 				.event( &a_test_t::on_sig_2 )
63 				.event( &a_test_t::on_msg_1 )
64 				.event( &a_test_t::on_msg_2 )
65 				.event( &a_test_t::on_msg_3 )
66 				.event( &a_test_t::on_msg_4 )
67 				.event( &a_test_t::on_msg_5 )
68 				.event( &a_test_t::on_umsg_1 )
69 				.event( &a_test_t::on_umsg_2 )
70 				.event( &a_test_t::on_umsg_3 )
71 				.event( &a_test_t::on_umsg_4 )
72 				.event( &a_test_t::on_umsg_5 )
73 				.event( &a_test_t::on_umsg_6 )
74 				.event( &a_test_t::on_ret_msg_1 )
75 				.event( &a_test_t::on_ret_msg_2 )
76 				.event( &a_test_t::on_ret_msg_3 )
77 				.event( &a_test_t::on_ret_msg_4 )
78 				.event( &a_test_t::on_ret_msg_5 )
79 				.event( &a_test_t::on_ret_umsg_1 )
80 				.event( &a_test_t::on_ret_umsg_2 )
81 				.event( &a_test_t::on_ret_umsg_3 )
82 				.event( &a_test_t::on_ret_umsg_4 )
83 				.event( &a_test_t::on_ret_umsg_5 )
84 				.event( &a_test_t::on_ret_umsg_6 )
85 				;
86 
87 #define ENSURE_SUBSCRIBED(handler) \
88 ensure( so_has_subscription(so_direct_mbox(), \
89 		so_default_state(), \
90 		&a_test_t:: handler), \
91 		#handler " must be subscribed" )
92 
93 		ENSURE_SUBSCRIBED(on_sig_1);
94 		ENSURE_SUBSCRIBED(on_sig_2);
95 		ENSURE_SUBSCRIBED(on_msg_1);
96 		ENSURE_SUBSCRIBED(on_msg_2);
97 		ENSURE_SUBSCRIBED(on_msg_3);
98 		ENSURE_SUBSCRIBED(on_msg_4);
99 		ENSURE_SUBSCRIBED(on_msg_5);
100 
101 		ENSURE_SUBSCRIBED(on_umsg_1);
102 		ENSURE_SUBSCRIBED(on_umsg_2);
103 		ENSURE_SUBSCRIBED(on_umsg_3);
104 		ENSURE_SUBSCRIBED(on_umsg_4);
105 		ENSURE_SUBSCRIBED(on_umsg_5);
106 		ENSURE_SUBSCRIBED(on_umsg_6);
107 
108 		ENSURE_SUBSCRIBED(on_ret_msg_1);
109 		ENSURE_SUBSCRIBED(on_ret_msg_2);
110 		ENSURE_SUBSCRIBED(on_ret_msg_3);
111 		ENSURE_SUBSCRIBED(on_ret_msg_4);
112 		ENSURE_SUBSCRIBED(on_ret_msg_5);
113 
114 		ENSURE_SUBSCRIBED(on_ret_umsg_1);
115 		ENSURE_SUBSCRIBED(on_ret_umsg_2);
116 		ENSURE_SUBSCRIBED(on_ret_umsg_3);
117 		ENSURE_SUBSCRIBED(on_ret_umsg_4);
118 		ENSURE_SUBSCRIBED(on_ret_umsg_5);
119 		ENSURE_SUBSCRIBED(on_ret_umsg_6);
120 
121 #undef ENSURE_SUBSCRIBED
122 	}
123 
124 	virtual void
so_evt_start()125 	so_evt_start() override
126 	{
127 		so_5::send<sig_1>( *this );
128 		so_5::send<sig_2>( *this );
129 
130 		so_5::send<msg_1>( *this );
131 		so_5::send<msg_2>( *this );
132 		so_5::send<msg_3>( *this );
133 		so_5::send<so_5::mutable_msg<msg_4>>( *this );
134 		so_5::send<so_5::mutable_msg<msg_5>>( *this );
135 
136 		so_5::send<umsg_1>( *this );
137 		so_5::send<umsg_2>( *this );
138 		so_5::send<umsg_3>( *this );
139 		so_5::send<so_5::mutable_msg<umsg_4>>( *this );
140 		so_5::send<so_5::mutable_msg<umsg_5>>( *this );
141 		so_5::send<umsg_6>( *this );
142 
143 		so_5::send<ret_msg_1>( *this );
144 		so_5::send<ret_msg_2>( *this );
145 		so_5::send<ret_msg_3>( *this );
146 		so_5::send<so_5::mutable_msg<ret_msg_4>>( *this );
147 		so_5::send<so_5::mutable_msg<ret_msg_5>>( *this );
148 
149 		so_5::send<ret_umsg_1>( *this );
150 		so_5::send<ret_umsg_2>( *this );
151 		so_5::send<ret_umsg_3>( *this );
152 		so_5::send<so_5::mutable_msg<ret_umsg_4>>( *this );
153 		so_5::send<so_5::mutable_msg<ret_umsg_5>>( *this );
154 		so_5::send<ret_umsg_6>( *this );
155 
156 		so_5::send<finish>( *this );
157 	}
158 
159 private:
160 	void
on_sig_1(const mhood_t<sig_1> &)161 	on_sig_1(const mhood_t<sig_1> &)
162 	{
163 		so_drop_subscription(
164 				so_direct_mbox(), so_default_state(), &a_test_t::on_sig_1 );
165 	}
166 
167 	void
on_sig_2(mhood_t<sig_2>)168 	on_sig_2(mhood_t<sig_2>)
169 	{
170 		so_drop_subscription(
171 				so_direct_mbox(), so_default_state(), &a_test_t::on_sig_2 );
172 	}
173 
174 	void
on_msg_1(const msg_1 &)175 	on_msg_1(const msg_1 &)
176 	{
177 		so_drop_subscription(
178 				so_direct_mbox(), so_default_state(), &a_test_t::on_msg_1 );
179 	}
180 	void
on_msg_2(const mhood_t<msg_2> &)181 	on_msg_2(const mhood_t<msg_2> &)
182 	{
183 		so_drop_subscription(
184 				so_direct_mbox(), so_default_state(), &a_test_t::on_msg_2 );
185 	}
186 	void
on_msg_3(mhood_t<msg_3>)187 	on_msg_3(mhood_t<msg_3>)
188 	{
189 		so_drop_subscription(
190 				so_direct_mbox(), so_default_state(), &a_test_t::on_msg_3 );
191 	}
192 	void
on_msg_4(mutable_mhood_t<msg_4>)193 	on_msg_4(mutable_mhood_t<msg_4>)
194 	{
195 		so_drop_subscription(
196 				so_direct_mbox(), so_default_state(), &a_test_t::on_msg_4 );
197 	}
198 	void
on_msg_5(const mutable_mhood_t<msg_5> &)199 	on_msg_5(const mutable_mhood_t<msg_5> &)
200 	{
201 		so_drop_subscription(
202 				so_direct_mbox(), so_default_state(), &a_test_t::on_msg_5 );
203 	}
204 
205 	void
on_umsg_1(const umsg_1 &)206 	on_umsg_1(const umsg_1 &)
207 	{
208 		so_drop_subscription(
209 				so_direct_mbox(), so_default_state(), &a_test_t::on_umsg_1 );
210 	}
211 	void
on_umsg_2(const mhood_t<umsg_2> &)212 	on_umsg_2(const mhood_t<umsg_2> &)
213 	{
214 		so_drop_subscription(
215 				so_direct_mbox(), so_default_state(), &a_test_t::on_umsg_2 );
216 	}
217 	void
on_umsg_3(mhood_t<umsg_3>)218 	on_umsg_3(mhood_t<umsg_3>)
219 	{
220 		so_drop_subscription(
221 				so_direct_mbox(), so_default_state(), &a_test_t::on_umsg_3 );
222 	}
223 	void
on_umsg_4(mutable_mhood_t<umsg_4>)224 	on_umsg_4(mutable_mhood_t<umsg_4>)
225 	{
226 		so_drop_subscription(
227 				so_direct_mbox(), so_default_state(), &a_test_t::on_umsg_4 );
228 	}
229 	void
on_umsg_5(const mutable_mhood_t<umsg_5> &)230 	on_umsg_5(const mutable_mhood_t<umsg_5> &)
231 	{
232 		so_drop_subscription(
233 				so_direct_mbox(), so_default_state(), &a_test_t::on_umsg_5 );
234 	}
235 	void
on_umsg_6(umsg_6)236 	on_umsg_6(umsg_6)
237 	{
238 		so_drop_subscription(
239 				so_direct_mbox(), so_default_state(), &a_test_t::on_umsg_6 );
240 	}
241 
242 	int
on_ret_msg_1(const ret_msg_1 &)243 	on_ret_msg_1(const ret_msg_1 &)
244 	{
245 		so_drop_subscription(
246 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_msg_1 );
247 		return 0;
248 	}
249 	int
on_ret_msg_2(const mhood_t<ret_msg_2> &)250 	on_ret_msg_2(const mhood_t<ret_msg_2> &)
251 	{
252 		so_drop_subscription(
253 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_msg_2 );
254 		return 0;
255 	}
256 	int
on_ret_msg_3(mhood_t<ret_msg_3>)257 	on_ret_msg_3(mhood_t<ret_msg_3>)
258 	{
259 		so_drop_subscription(
260 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_msg_3 );
261 		return 0;
262 	}
263 	int
on_ret_msg_4(mutable_mhood_t<ret_msg_4>)264 	on_ret_msg_4(mutable_mhood_t<ret_msg_4>)
265 	{
266 		so_drop_subscription(
267 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_msg_4 );
268 		return 0;
269 	}
270 	int
on_ret_msg_5(const mutable_mhood_t<ret_msg_5> &)271 	on_ret_msg_5(const mutable_mhood_t<ret_msg_5> &)
272 	{
273 		so_drop_subscription(
274 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_msg_5 );
275 		return 0;
276 	}
277 
278 	int
on_ret_umsg_1(const ret_umsg_1 &)279 	on_ret_umsg_1(const ret_umsg_1 &)
280 	{
281 		so_drop_subscription(
282 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_umsg_1 );
283 		return 0;
284 	}
285 	int
on_ret_umsg_2(const mhood_t<ret_umsg_2> &)286 	on_ret_umsg_2(const mhood_t<ret_umsg_2> &)
287 	{
288 		so_drop_subscription(
289 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_umsg_2 );
290 		return 0;
291 	}
292 	int
on_ret_umsg_3(mhood_t<ret_umsg_3>)293 	on_ret_umsg_3(mhood_t<ret_umsg_3>)
294 	{
295 		so_drop_subscription(
296 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_umsg_3 );
297 		return 0;
298 	}
299 	int
on_ret_umsg_4(mutable_mhood_t<ret_umsg_4>)300 	on_ret_umsg_4(mutable_mhood_t<ret_umsg_4>)
301 	{
302 		so_drop_subscription(
303 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_umsg_4 );
304 		return 0;
305 	}
306 	int
on_ret_umsg_5(const mutable_mhood_t<ret_umsg_5> &)307 	on_ret_umsg_5(const mutable_mhood_t<ret_umsg_5> &)
308 	{
309 		so_drop_subscription(
310 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_umsg_5 );
311 		return 0;
312 	}
313 	int
on_ret_umsg_6(ret_umsg_6)314 	on_ret_umsg_6(ret_umsg_6)
315 	{
316 		so_drop_subscription(
317 				so_direct_mbox(), so_default_state(), &a_test_t::on_ret_umsg_6 );
318 		return 0;
319 	}
320 
321 	void
on_finish(mhood_t<finish>)322 	on_finish(mhood_t<finish>)
323 	{
324 #define ENSURE_UNSUBSCRIBED(handler) \
325 ensure( !so_has_subscription(so_direct_mbox(), \
326 		so_default_state(), \
327 		&a_test_t:: handler), \
328 		#handler " must not be subscribed" )
329 
330 		ENSURE_UNSUBSCRIBED(on_sig_1);
331 		ENSURE_UNSUBSCRIBED(on_sig_2);
332 		ENSURE_UNSUBSCRIBED(on_msg_1);
333 		ENSURE_UNSUBSCRIBED(on_msg_2);
334 		ENSURE_UNSUBSCRIBED(on_msg_3);
335 		ENSURE_UNSUBSCRIBED(on_msg_4);
336 		ENSURE_UNSUBSCRIBED(on_msg_5);
337 
338 		ENSURE_UNSUBSCRIBED(on_umsg_1);
339 		ENSURE_UNSUBSCRIBED(on_umsg_2);
340 		ENSURE_UNSUBSCRIBED(on_umsg_3);
341 		ENSURE_UNSUBSCRIBED(on_umsg_4);
342 		ENSURE_UNSUBSCRIBED(on_umsg_5);
343 		ENSURE_UNSUBSCRIBED(on_umsg_6);
344 
345 		ENSURE_UNSUBSCRIBED(on_ret_msg_1);
346 		ENSURE_UNSUBSCRIBED(on_ret_msg_2);
347 		ENSURE_UNSUBSCRIBED(on_ret_msg_3);
348 		ENSURE_UNSUBSCRIBED(on_ret_msg_4);
349 		ENSURE_UNSUBSCRIBED(on_ret_msg_5);
350 
351 		ENSURE_UNSUBSCRIBED(on_ret_umsg_1);
352 		ENSURE_UNSUBSCRIBED(on_ret_umsg_2);
353 		ENSURE_UNSUBSCRIBED(on_ret_umsg_3);
354 		ENSURE_UNSUBSCRIBED(on_ret_umsg_4);
355 		ENSURE_UNSUBSCRIBED(on_ret_umsg_5);
356 		ENSURE_UNSUBSCRIBED(on_ret_umsg_6);
357 
358 #undef ENSURE_UNSUBSCRIBED
359 
360 		so_deregister_agent_coop_normally();
361 	}
362 };
363 
364 int
main()365 main()
366 {
367 	try
368 	{
369 		run_with_time_limit(
370 			[]()
371 			{
372 				so_5::launch( []( so_5::environment_t & env ) {
373 						env.introduce_coop( []( so_5::coop_t & coop ) {
374 								coop.make_agent< a_test_t >();
375 							} );
376 					} );
377 			},
378 			20,
379 			"so_has_subscription test" );
380 	}
381 	catch( const std::exception & ex )
382 	{
383 		std::cerr << "Error: " << ex.what() << std::endl;
384 		return 1;
385 	}
386 
387 	return 0;
388 }
389 
390