Imported Upstream version 3.2.2
[debian/gnuradio] / mblock / src / lib / qa_mblock_send.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006,2007,2008 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <qa_mblock_send.h>
28 #include <cppunit/TestAssert.h>
29 #include <mblock/mblock.h>
30 #include <mblock/runtime.h>
31 #include <mb_runtime_nop.h>             // QA only
32 #include <mblock/protocol_class.h>
33 #include <mblock/exception.h>
34 #include <mblock/msg_queue.h>
35 #include <mblock/message.h>
36 #include <mb_mblock_impl.h>
37 #include <mblock/msg_accepter.h>
38 #include <mblock/class_registry.h>
39 #include <stdio.h>
40
41 static pmt_t s_data    = pmt_intern("data");
42 static pmt_t s_status  = pmt_intern("status");
43 static pmt_t s_control = pmt_intern("control");
44 static pmt_t s_p0   = pmt_intern("p0");
45 static pmt_t s_p1   = pmt_intern("p1");
46 static pmt_t s_p2   = pmt_intern("p2");
47 static pmt_t s_p3   = pmt_intern("p3");
48 static pmt_t s_e1   = pmt_intern("e1");
49 static pmt_t s_r1   = pmt_intern("r1");
50
51 static void
52 define_protocol_classes()
53 {
54   // Defined from client point-of-view.
55   mb_make_protocol_class(pmt_intern("qa-send-cs"),      // name
56                          pmt_list1(s_status),           // incoming
57                          pmt_list1(s_control));         // outgoing
58
59 }
60
61 mb_mblock_sptr
62 get_top(mb_runtime_sptr rts)
63 {
64   return dynamic_cast<mb_runtime_nop *>(rts.get())->top();
65 }
66
67 // ================================================================
68 //                     test_simple_routing
69 // ================================================================
70
71 // sub-block for test_simple_routing
72
73 class sr1 : public mb_mblock
74 {
75   mb_port_sptr  d_p1;
76   mb_port_sptr  d_p2;
77   mb_port_sptr  d_p3;
78
79 public:
80   sr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
81   ~sr1();
82   void initial_transition();
83 };
84
85 sr1::sr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
86   : mb_mblock(runtime, instance_name, user_arg)
87 {
88   d_p1 = define_port("p1", "qa-send-cs", true, mb_port::EXTERNAL);
89   d_p2 = define_port("p2", "qa-send-cs", true, mb_port::EXTERNAL);
90   d_p3 = define_port("p3", "qa-send-cs", false, mb_port::EXTERNAL);
91 }
92
93 sr1::~sr1(){}
94   
95 void
96 sr1::initial_transition()
97 {
98   // std::cout << instance_name() << "[sr1]: initial_transition\n";
99
100   // send two messages to each port
101   pmt_t our_name = pmt_intern(instance_name());
102   d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(0)));
103   d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(1)));
104
105   d_p2->send(s_status, pmt_list3(our_name, s_p2, pmt_from_long(0)));
106   d_p2->send(s_status, pmt_list3(our_name, s_p2, pmt_from_long(1)));
107 }
108
109 REGISTER_MBLOCK_CLASS(sr1);
110
111 // ----------------------------------------------------------------
112
113 // top-level container block for test_simple_routing
114 class sr0 : public mb_mblock
115 {
116   mb_port_sptr  d_p0;
117   
118 public:
119   sr0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
120   ~sr0();
121   void initial_transition();
122 };
123
124 sr0::sr0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
125   : mb_mblock(runtime, instance_name, user_arg)
126 {
127   d_p0 = define_port("p0", "qa-send-cs", false, mb_port::INTERNAL);
128
129   define_component("mb1", "sr1");
130   define_component("mb2", "sr1");
131
132   connect("self", "p0", "mb1", "p1");
133   connect("mb1", "p2", "mb2", "p3");
134   connect("mb1", "p3", "mb2", "p2");
135 }
136
137 sr0::~sr0(){}
138
139 void
140 sr0::initial_transition()
141 {
142   // std::cout << instance_name() << "[sr0]: initial_transition\n";
143
144   // send two messages to p0
145   pmt_t our_name = pmt_intern(instance_name());
146   d_p0->send(s_control, pmt_list3(our_name, s_p0, pmt_from_long(0)));
147   d_p0->send(s_control, pmt_list3(our_name, s_p0, pmt_from_long(1)));
148 }
149   
150 REGISTER_MBLOCK_CLASS(sr0);
151
152 // ----------------------------------------------------------------
153
154 /*
155  * This tests basic message routing using INTERNAL and EXTERNAL ports.
156  * It does not rely on the guts of the runtime being complete,
157  * which is good, because at the time this is being written, it isn't.
158  */
159 void
160 qa_mblock_send::test_simple_routing()
161 {
162   define_protocol_classes();
163
164   mb_message_sptr msg;
165
166   mb_runtime_sptr rt = mb_make_runtime_nop();
167   rt->run("top", "sr0", PMT_F);
168
169   mb_mblock_sptr mb0 = get_top(rt);
170   
171   // Reach into the guts and see if the messages ended up where they should have
172
173   // mb0 should have received two messages sent from mb1 via its p1
174   msg = mb0->impl()->msgq().get_highest_pri_msg_nowait();
175   CPPUNIT_ASSERT(msg);
176   // std::cerr << msg->data() << std::endl;
177   CPPUNIT_ASSERT_EQUAL(s_p0, msg->port_id());
178   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p1, pmt_from_long(0)),
179                            msg->data()));
180
181   msg = mb0->impl()->msgq().get_highest_pri_msg_nowait();
182   CPPUNIT_ASSERT(msg);
183   // std::cerr << msg->data() << std::endl;
184   CPPUNIT_ASSERT_EQUAL(s_p0, msg->port_id());
185   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p1, pmt_from_long(1)),
186                            msg->data()));
187
188   // mb1 should have received
189   //   two messages from mb0 via its p0 and
190   //   two messages from mb2 via its p3
191
192   mb_mblock_sptr mb1 = mb0->impl()->component("mb1");
193
194   msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
195   CPPUNIT_ASSERT(msg);
196   // std::cerr << msg->data() << std::endl;
197   CPPUNIT_ASSERT_EQUAL(s_p1, msg->port_id());
198   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top"), s_p0, pmt_from_long(0)),
199                            msg->data()));
200
201   msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
202   CPPUNIT_ASSERT(msg);
203   // std::cerr << msg->data() << std::endl;
204   CPPUNIT_ASSERT_EQUAL(s_p1, msg->port_id());
205   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top"), s_p0, pmt_from_long(1)),
206                            msg->data()));
207
208   msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
209   CPPUNIT_ASSERT(msg);
210   // std::cerr << msg->data() << std::endl;
211   CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
212   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb2"), s_p2, pmt_from_long(0)),
213                            msg->data()));
214
215   msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
216   CPPUNIT_ASSERT(msg);
217   // std::cerr << msg->data() << std::endl;
218   CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
219   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb2"), s_p2, pmt_from_long(1)),
220                            msg->data()));
221
222
223   // mb2 should have received
224   //   two messages from mb2 via its p2
225
226   mb_mblock_sptr mb2 = mb0->impl()->component("mb2");
227
228   msg = mb2->impl()->msgq().get_highest_pri_msg_nowait();
229   CPPUNIT_ASSERT(msg);
230   // std::cerr << msg->data() << std::endl;
231   CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
232   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p2, pmt_from_long(0)),
233                            msg->data()));
234
235   msg = mb2->impl()->msgq().get_highest_pri_msg_nowait();
236   CPPUNIT_ASSERT(msg);
237   // std::cerr << msg->data() << std::endl;
238   CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
239   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p2, pmt_from_long(1)),
240                            msg->data()));
241 }
242
243 // ================================================================
244 //                     test_relay_routing_1
245 // ================================================================
246
247 // internal block for test_relay_routing
248
249 class rr2 : public mb_mblock
250 {
251   mb_port_sptr  d_p1;
252   mb_port_sptr  d_p2;
253
254 public:
255   rr2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
256   ~rr2();
257   void initial_transition();
258 };
259
260 rr2::rr2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
261   : mb_mblock(runtime, instance_name, user_arg)
262 {
263   d_p1 = define_port("p1", "qa-send-cs", true,  mb_port::EXTERNAL);
264   d_p2 = define_port("p2", "qa-send-cs", false, mb_port::EXTERNAL);
265 }
266
267 rr2::~rr2(){}
268   
269 void
270 rr2::initial_transition()
271 {
272   // std::cout << instance_name() << "[rr2]: initial_transition\n";
273
274   // send two messages via p1
275   pmt_t our_name = pmt_intern(instance_name());
276   d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(0)));
277   d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(1)));
278 }
279
280 REGISTER_MBLOCK_CLASS(rr2);
281
282 // ----------------------------------------------------------------
283
284 // intermediate block for test_relay_routing
285
286 class rr1 : public mb_mblock
287 {
288   mb_port_sptr  d_p1;
289   mb_port_sptr  d_p2;
290
291 public:
292   rr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
293   ~rr1();
294 };
295
296 rr1::rr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
297   : mb_mblock(runtime, instance_name, user_arg)
298 {
299   d_p1 = define_port("p1", "qa-send-cs", true,  mb_port::RELAY);
300   d_p2 = define_port("p2", "qa-send-cs", false, mb_port::RELAY);
301
302   define_component("c0", "rr2");
303
304   connect("self", "p1", "c0", "p1");
305   connect("self", "p2", "c0", "p2");
306 }
307
308 rr1::~rr1(){}
309
310 REGISTER_MBLOCK_CLASS(rr1);
311
312 // ----------------------------------------------------------------
313
314 // top-level container for test_relay_routing
315
316 class rr0_a : public mb_mblock
317 {
318 public:
319   rr0_a(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
320   ~rr0_a();
321 };
322
323 rr0_a::rr0_a(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
324   : mb_mblock(runtime, instance_name, user_arg)
325 {
326   define_component("c0", "rr1");
327   define_component("c1", "rr2");
328
329   connect("c0", "p1", "c1", "p2");
330   connect("c0", "p2", "c1", "p1");
331 }
332
333 rr0_a::~rr0_a(){}
334
335 REGISTER_MBLOCK_CLASS(rr0_a);
336
337 /*
338  * This tests basic message routing using RELAY and EXTERNAL ports.
339  * It does not rely on the guts of the runtime being complete,
340  * which is good, because at the time this is being written, it isn't.
341  */
342 void
343 qa_mblock_send::test_relay_routing_1()
344 {
345   mb_message_sptr msg;
346
347   mb_runtime_sptr rt = mb_make_runtime_nop();
348   rt->run("top", "rr0_a", PMT_F);
349   mb_mblock_sptr top = get_top(rt);
350
351   // Reach into the guts and see if the messages ended up where they should have
352
353   mb_mblock_sptr c0 = top->impl()->component("c0");
354   mb_mblock_sptr c0c0 = c0->impl()->component("c0");
355
356   mb_mblock_sptr c1 = top->impl()->component("c1");
357
358   // c0c0 should have received
359   //   two message from c1 via its p2
360
361   msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
362   CPPUNIT_ASSERT(msg);
363   //std::cerr << msg->data() << std::endl;
364   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
365   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1"), s_p1, pmt_from_long(0)),
366                            msg->data()));
367
368   msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
369   CPPUNIT_ASSERT(msg);
370   //std::cerr << msg->data() << std::endl;
371   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
372   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1"), s_p1, pmt_from_long(1)),
373                            msg->data()));
374
375   // c1 should have received
376   //   two message from c0c0 via its p2
377
378   msg = c1->impl()->msgq().get_highest_pri_msg_nowait();
379   CPPUNIT_ASSERT(msg);
380   //std::cerr << msg->data() << std::endl;
381   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
382   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(0)),
383                            msg->data()));
384
385   msg = c1->impl()->msgq().get_highest_pri_msg_nowait();
386   CPPUNIT_ASSERT(msg);
387   //std::cerr << msg->data() << std::endl;
388   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
389   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(1)),
390                            msg->data()));
391 }
392
393 // ================================================================
394 //                     test_relay_routing_2
395 // ================================================================
396
397 // top-level container for test_relay_routing_2
398
399 class rr0_b : public mb_mblock
400 {
401 public:
402   rr0_b(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
403   ~rr0_b();
404 };
405
406 rr0_b::rr0_b(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
407   : mb_mblock(runtime, instance_name, user_arg)
408 {
409   define_component("c0", "rr1");
410   define_component("c1", "rr1");
411
412   connect("c0", "p1", "c1", "p2");
413   connect("c0", "p2", "c1", "p1");
414 }
415
416 rr0_b::~rr0_b(){}
417
418 REGISTER_MBLOCK_CLASS(rr0_b);
419
420 /*
421  * This tests basic message routing using RELAY and EXTERNAL ports.
422  * It does not rely on the guts of the runtime being complete,
423  * which is good, because at the time this is being written, it isn't.
424  */
425 void
426 qa_mblock_send::test_relay_routing_2()
427 {
428   mb_message_sptr msg;
429
430   mb_runtime_sptr rt = mb_make_runtime_nop();
431   rt->run("top", "rr0_b", PMT_F);
432   mb_mblock_sptr top = get_top(rt);
433
434   // Reach into the guts and see if the messages ended up where they should have
435
436   mb_mblock_sptr c0 = top->impl()->component("c0");
437   mb_mblock_sptr c0c0 = c0->impl()->component("c0");
438
439   mb_mblock_sptr c1 = top->impl()->component("c1");
440   mb_mblock_sptr c1c0 = c1->impl()->component("c0");
441
442   // c0c0 should have received
443   //   two message from c1c0 via its p2
444
445   msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
446   CPPUNIT_ASSERT(msg);
447   // std::cerr << msg->data() << std::endl;
448   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
449   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1/c0"), s_p1, pmt_from_long(0)),
450                            msg->data()));
451
452   msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
453   CPPUNIT_ASSERT(msg);
454   // std::cerr << msg->data() << std::endl;
455   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
456   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1/c0"), s_p1, pmt_from_long(1)),
457                            msg->data()));
458
459   // c1c0 should have received
460   //   two message from c0c0 via its p2
461
462   msg = c1c0->impl()->msgq().get_highest_pri_msg_nowait();
463   CPPUNIT_ASSERT(msg);
464   // std::cerr << msg->data() << std::endl;
465   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
466   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(0)),
467                            msg->data()));
468
469   msg = c1c0->impl()->msgq().get_highest_pri_msg_nowait();
470   CPPUNIT_ASSERT(msg);
471   // std::cerr << msg->data() << std::endl;
472   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
473   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(1)),
474                            msg->data()));
475 }