Merged mblock work-in-progress from eb/mb -r4341:4633 into trunk.
[debian/gnuradio] / mblock / src / lib / qa_mblock_send.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006,2007 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 2, 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 <mb_mblock.h>
30 #include <mb_runtime.h>
31 #include <mb_protocol_class.h>
32 #include <mb_exception.h>
33 #include <mb_msg_queue.h>
34 #include <mb_message.h>
35 #include <mb_mblock_impl.h>
36 #include <mb_msg_accepter.h>
37 #include <stdio.h>
38
39 static pmt_t s_data    = pmt_intern("data");
40 static pmt_t s_status  = pmt_intern("status");
41 static pmt_t s_control = pmt_intern("control");
42 static pmt_t s_p0   = pmt_intern("p0");
43 static pmt_t s_p1   = pmt_intern("p1");
44 static pmt_t s_p2   = pmt_intern("p2");
45 static pmt_t s_p3   = pmt_intern("p3");
46 static pmt_t s_e1   = pmt_intern("e1");
47 static pmt_t s_r1   = pmt_intern("r1");
48
49 static void
50 define_protocol_classes()
51 {
52   // Defined from client point-of-view.
53   mb_make_protocol_class(pmt_intern("qa-send-cs"),      // name
54                          pmt_list1(s_status),           // incoming
55                          pmt_list1(s_control));         // outgoing
56
57 }
58
59 // ================================================================
60 //                     test_simple_routing
61 // ================================================================
62
63 // sub-block for test_simple_routing
64
65 class sr1 : public mb_mblock
66 {
67   mb_port_sptr  d_p1;
68   mb_port_sptr  d_p2;
69   mb_port_sptr  d_p3;
70
71 public:
72   sr1();
73   ~sr1();
74   void init_fsm();
75 };
76
77 sr1::sr1()
78 {
79   d_p1 = define_port("p1", "qa-send-cs", true, mb_port::EXTERNAL);
80   d_p2 = define_port("p2", "qa-send-cs", true, mb_port::EXTERNAL);
81   d_p3 = define_port("p3", "qa-send-cs", false, mb_port::EXTERNAL);
82 }
83
84 sr1::~sr1(){}
85   
86 void
87 sr1::init_fsm()
88 {
89   // std::cout << fullname() << "[sr1]: init_fsm\n";
90
91   // send two messages to each port
92   pmt_t our_name = pmt_intern(fullname());
93   d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(0)));
94   d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(1)));
95
96   d_p2->send(s_status, pmt_list3(our_name, s_p2, pmt_from_long(0)));
97   d_p2->send(s_status, pmt_list3(our_name, s_p2, pmt_from_long(1)));
98 }
99
100 // ----------------------------------------------------------------
101
102 // top-level container block for test_simple_routing
103 class sr0 : public mb_mblock
104 {
105   mb_port_sptr  d_p0;
106   
107 public:
108   sr0();
109   ~sr0();
110   void init_fsm();
111 };
112
113 sr0::sr0()
114 {
115   d_p0 = define_port("p0", "qa-send-cs", false, mb_port::INTERNAL);
116
117   define_component("mb1", mb_mblock_sptr(new sr1()));
118   define_component("mb2", mb_mblock_sptr(new sr1()));
119
120   connect("self", "p0", "mb1", "p1");
121   connect("mb1", "p2", "mb2", "p3");
122   connect("mb1", "p3", "mb2", "p2");
123 }
124
125 sr0::~sr0(){}
126
127 void
128 sr0::init_fsm()
129 {
130   // std::cout << fullname() << "[sr0]: init_fsm\n";
131
132   // send two messages to p0
133   pmt_t our_name = pmt_intern(fullname());
134   d_p0->send(s_control, pmt_list3(our_name, s_p0, pmt_from_long(0)));
135   d_p0->send(s_control, pmt_list3(our_name, s_p0, pmt_from_long(1)));
136 }
137   
138 // ----------------------------------------------------------------
139
140 /*
141  * This tests basic message routing using INTERNAL and EXTERNAL ports.
142  * It does not rely on the guts of the runtime being complete,
143  * which is good, because at the time this is being written, it isn't.
144  */
145 void
146 qa_mblock_send::test_simple_routing()
147 {
148   define_protocol_classes();
149
150   mb_message_sptr msg;
151
152   mb_runtime_sptr rt = mb_make_runtime();
153   mb_mblock_sptr mb0 = mb_mblock_sptr(new sr0());
154   rt->run(mb0);
155
156   // Reach into the guts and see if the messages ended up where they should have
157
158   // mb0 should have received two messages sent from mb1 via its p1
159   msg = mb0->impl()->msgq().get_highest_pri_msg();
160   CPPUNIT_ASSERT(msg);
161   // std::cerr << msg->data() << std::endl;
162   CPPUNIT_ASSERT_EQUAL(s_p0, msg->port_id());
163   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p1, pmt_from_long(0)),
164                            msg->data()));
165
166   msg = mb0->impl()->msgq().get_highest_pri_msg();
167   CPPUNIT_ASSERT(msg);
168   // std::cerr << msg->data() << std::endl;
169   CPPUNIT_ASSERT_EQUAL(s_p0, msg->port_id());
170   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p1, pmt_from_long(1)),
171                            msg->data()));
172
173   // mb1 should have received
174   //   two messages from mb0 via its p0 and
175   //   two messages from mb2 via its p3
176
177   mb_mblock_sptr mb1 = mb0->impl()->component("mb1");
178
179   msg = mb1->impl()->msgq().get_highest_pri_msg();
180   CPPUNIT_ASSERT(msg);
181   // std::cerr << msg->data() << std::endl;
182   CPPUNIT_ASSERT_EQUAL(s_p1, msg->port_id());
183   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top"), s_p0, pmt_from_long(0)),
184                            msg->data()));
185
186   msg = mb1->impl()->msgq().get_highest_pri_msg();
187   CPPUNIT_ASSERT(msg);
188   // std::cerr << msg->data() << std::endl;
189   CPPUNIT_ASSERT_EQUAL(s_p1, msg->port_id());
190   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top"), s_p0, pmt_from_long(1)),
191                            msg->data()));
192
193   msg = mb1->impl()->msgq().get_highest_pri_msg();
194   CPPUNIT_ASSERT(msg);
195   // std::cerr << msg->data() << std::endl;
196   CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
197   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb2"), s_p2, pmt_from_long(0)),
198                            msg->data()));
199
200   msg = mb1->impl()->msgq().get_highest_pri_msg();
201   CPPUNIT_ASSERT(msg);
202   // std::cerr << msg->data() << std::endl;
203   CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
204   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb2"), s_p2, pmt_from_long(1)),
205                            msg->data()));
206
207
208   // mb2 should have received
209   //   two messages from mb2 via its p2
210
211   mb_mblock_sptr mb2 = mb0->impl()->component("mb2");
212
213   msg = mb2->impl()->msgq().get_highest_pri_msg();
214   CPPUNIT_ASSERT(msg);
215   // std::cerr << msg->data() << std::endl;
216   CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
217   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p2, pmt_from_long(0)),
218                            msg->data()));
219
220   msg = mb2->impl()->msgq().get_highest_pri_msg();
221   CPPUNIT_ASSERT(msg);
222   // std::cerr << msg->data() << std::endl;
223   CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
224   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p2, pmt_from_long(1)),
225                            msg->data()));
226 }
227
228 // ================================================================
229 //                     test_relay_routing_1
230 // ================================================================
231
232 // internal block for test_relay_routing
233
234 class rr2 : public mb_mblock
235 {
236   mb_port_sptr  d_p1;
237   mb_port_sptr  d_p2;
238
239 public:
240   rr2();
241   ~rr2();
242   void init_fsm();
243 };
244
245 rr2::rr2()
246 {
247   d_p1 = define_port("p1", "qa-send-cs", true,  mb_port::EXTERNAL);
248   d_p2 = define_port("p2", "qa-send-cs", false, mb_port::EXTERNAL);
249 }
250
251 rr2::~rr2(){}
252   
253 void
254 rr2::init_fsm()
255 {
256   // std::cout << fullname() << "[rr2]: init_fsm\n";
257
258   // send two messages via p1
259   pmt_t our_name = pmt_intern(fullname());
260   d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(0)));
261   d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(1)));
262 }
263
264 // ----------------------------------------------------------------
265
266 // intermediate block for test_relay_routing
267
268 class rr1 : public mb_mblock
269 {
270   mb_port_sptr  d_p1;
271   mb_port_sptr  d_p2;
272
273 public:
274   rr1();
275   ~rr1();
276 };
277
278 rr1::rr1()
279 {
280   d_p1 = define_port("p1", "qa-send-cs", true,  mb_port::RELAY);
281   d_p2 = define_port("p2", "qa-send-cs", false, mb_port::RELAY);
282
283   define_component("c0", mb_mblock_sptr(new rr2()));
284
285   connect("self", "p1", "c0", "p1");
286   connect("self", "p2", "c0", "p2");
287 }
288
289 rr1::~rr1(){}
290
291 // ----------------------------------------------------------------
292
293 // top-level container for test_relay_routing
294
295 class rr0_a : public mb_mblock
296 {
297 public:
298   rr0_a();
299   ~rr0_a();
300 };
301
302 rr0_a::rr0_a()
303 {
304   define_component("c0", mb_mblock_sptr(new rr1()));
305   define_component("c1", mb_mblock_sptr(new rr2()));
306
307   connect("c0", "p1", "c1", "p2");
308   connect("c0", "p2", "c1", "p1");
309 }
310
311 rr0_a::~rr0_a(){}
312
313
314 /*
315  * This tests basic message routing using RELAY and EXTERNAL ports.
316  * It does not rely on the guts of the runtime being complete,
317  * which is good, because at the time this is being written, it isn't.
318  */
319 void
320 qa_mblock_send::test_relay_routing_1()
321 {
322   mb_message_sptr msg;
323
324   mb_runtime_sptr rt = mb_make_runtime();
325   mb_mblock_sptr  top = mb_mblock_sptr(new rr0_a());
326   rt->run(top);
327
328   // Reach into the guts and see if the messages ended up where they should have
329
330   mb_mblock_sptr c0 = top->impl()->component("c0");
331   mb_mblock_sptr c0c0 = c0->impl()->component("c0");
332
333   mb_mblock_sptr c1 = top->impl()->component("c1");
334
335   // c0c0 should have received
336   //   two message from c1 via its p2
337
338   msg = c0c0->impl()->msgq().get_highest_pri_msg();
339   CPPUNIT_ASSERT(msg);
340   //std::cerr << msg->data() << std::endl;
341   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
342   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1"), s_p1, pmt_from_long(0)),
343                            msg->data()));
344
345   msg = c0c0->impl()->msgq().get_highest_pri_msg();
346   CPPUNIT_ASSERT(msg);
347   //std::cerr << msg->data() << std::endl;
348   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
349   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1"), s_p1, pmt_from_long(1)),
350                            msg->data()));
351
352   // c1 should have received
353   //   two message from c0c0 via its p2
354
355   msg = c1->impl()->msgq().get_highest_pri_msg();
356   CPPUNIT_ASSERT(msg);
357   //std::cerr << msg->data() << std::endl;
358   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
359   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(0)),
360                            msg->data()));
361
362   msg = c1->impl()->msgq().get_highest_pri_msg();
363   CPPUNIT_ASSERT(msg);
364   //std::cerr << msg->data() << std::endl;
365   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
366   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(1)),
367                            msg->data()));
368 }
369
370 // ================================================================
371 //                     test_relay_routing_2
372 // ================================================================
373
374 // top-level container for test_relay_routing_2
375
376 class rr0_b : public mb_mblock
377 {
378 public:
379   rr0_b();
380   ~rr0_b();
381 };
382
383 rr0_b::rr0_b()
384 {
385   define_component("c0", mb_mblock_sptr(new rr1()));
386   define_component("c1", mb_mblock_sptr(new rr1()));
387
388   connect("c0", "p1", "c1", "p2");
389   connect("c0", "p2", "c1", "p1");
390 }
391
392 rr0_b::~rr0_b(){}
393
394
395 /*
396  * This tests basic message routing using RELAY and EXTERNAL ports.
397  * It does not rely on the guts of the runtime being complete,
398  * which is good, because at the time this is being written, it isn't.
399  */
400 void
401 qa_mblock_send::test_relay_routing_2()
402 {
403   mb_message_sptr msg;
404
405   mb_runtime_sptr rt = mb_make_runtime();
406   mb_mblock_sptr  top = mb_mblock_sptr(new rr0_b());
407   rt->run(top);
408
409   // Reach into the guts and see if the messages ended up where they should have
410
411   mb_mblock_sptr c0 = top->impl()->component("c0");
412   mb_mblock_sptr c0c0 = c0->impl()->component("c0");
413
414   mb_mblock_sptr c1 = top->impl()->component("c1");
415   mb_mblock_sptr c1c0 = c1->impl()->component("c0");
416
417   // c0c0 should have received
418   //   two message from c1c0 via its p2
419
420   msg = c0c0->impl()->msgq().get_highest_pri_msg();
421   CPPUNIT_ASSERT(msg);
422   // std::cerr << msg->data() << std::endl;
423   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
424   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1/c0"), s_p1, pmt_from_long(0)),
425                            msg->data()));
426
427   msg = c0c0->impl()->msgq().get_highest_pri_msg();
428   CPPUNIT_ASSERT(msg);
429   // std::cerr << msg->data() << std::endl;
430   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
431   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1/c0"), s_p1, pmt_from_long(1)),
432                            msg->data()));
433
434   // c1c0 should have received
435   //   two message from c0c0 via its p2
436
437   msg = c1c0->impl()->msgq().get_highest_pri_msg();
438   CPPUNIT_ASSERT(msg);
439   // std::cerr << msg->data() << std::endl;
440   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
441   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(0)),
442                            msg->data()));
443
444   msg = c1c0->impl()->msgq().get_highest_pri_msg();
445   CPPUNIT_ASSERT(msg);
446   // std::cerr << msg->data() << std::endl;
447   CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
448   CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(1)),
449                            msg->data()));
450 }