3 * Copyright 2006,2007,2008 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
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)
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.
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.
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>
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");
52 define_protocol_classes()
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
62 get_top(mb_runtime_sptr rts)
64 return dynamic_cast<mb_runtime_nop *>(rts.get())->top();
67 // ================================================================
68 // test_simple_routing
69 // ================================================================
71 // sub-block for test_simple_routing
73 class sr1 : public mb_mblock
80 sr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
82 void initial_transition();
85 sr1::sr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
86 : mb_mblock(runtime, instance_name, user_arg)
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);
96 sr1::initial_transition()
98 // std::cout << instance_name() << "[sr1]: initial_transition\n";
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)));
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)));
109 REGISTER_MBLOCK_CLASS(sr1);
111 // ----------------------------------------------------------------
113 // top-level container block for test_simple_routing
114 class sr0 : public mb_mblock
119 sr0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
121 void initial_transition();
124 sr0::sr0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
125 : mb_mblock(runtime, instance_name, user_arg)
127 d_p0 = define_port("p0", "qa-send-cs", false, mb_port::INTERNAL);
129 define_component("mb1", "sr1");
130 define_component("mb2", "sr1");
132 connect("self", "p0", "mb1", "p1");
133 connect("mb1", "p2", "mb2", "p3");
134 connect("mb1", "p3", "mb2", "p2");
140 sr0::initial_transition()
142 // std::cout << instance_name() << "[sr0]: initial_transition\n";
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)));
150 REGISTER_MBLOCK_CLASS(sr0);
152 // ----------------------------------------------------------------
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.
160 qa_mblock_send::test_simple_routing()
162 define_protocol_classes();
166 mb_runtime_sptr rt = mb_make_runtime_nop();
167 rt->run("top", "sr0", PMT_F);
169 mb_mblock_sptr mb0 = get_top(rt);
171 // Reach into the guts and see if the messages ended up where they should have
173 // mb0 should have received two messages sent from mb1 via its p1
174 msg = mb0->impl()->msgq().get_highest_pri_msg_nowait();
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)),
181 msg = mb0->impl()->msgq().get_highest_pri_msg_nowait();
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)),
188 // mb1 should have received
189 // two messages from mb0 via its p0 and
190 // two messages from mb2 via its p3
192 mb_mblock_sptr mb1 = mb0->impl()->component("mb1");
194 msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
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)),
201 msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
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)),
208 msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
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)),
215 msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
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)),
223 // mb2 should have received
224 // two messages from mb2 via its p2
226 mb_mblock_sptr mb2 = mb0->impl()->component("mb2");
228 msg = mb2->impl()->msgq().get_highest_pri_msg_nowait();
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)),
235 msg = mb2->impl()->msgq().get_highest_pri_msg_nowait();
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)),
243 // ================================================================
244 // test_relay_routing_1
245 // ================================================================
247 // internal block for test_relay_routing
249 class rr2 : public mb_mblock
255 rr2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
257 void initial_transition();
260 rr2::rr2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
261 : mb_mblock(runtime, instance_name, user_arg)
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);
270 rr2::initial_transition()
272 // std::cout << instance_name() << "[rr2]: initial_transition\n";
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)));
280 REGISTER_MBLOCK_CLASS(rr2);
282 // ----------------------------------------------------------------
284 // intermediate block for test_relay_routing
286 class rr1 : public mb_mblock
292 rr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
296 rr1::rr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
297 : mb_mblock(runtime, instance_name, user_arg)
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);
302 define_component("c0", "rr2");
304 connect("self", "p1", "c0", "p1");
305 connect("self", "p2", "c0", "p2");
310 REGISTER_MBLOCK_CLASS(rr1);
312 // ----------------------------------------------------------------
314 // top-level container for test_relay_routing
316 class rr0_a : public mb_mblock
319 rr0_a(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
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)
326 define_component("c0", "rr1");
327 define_component("c1", "rr2");
329 connect("c0", "p1", "c1", "p2");
330 connect("c0", "p2", "c1", "p1");
335 REGISTER_MBLOCK_CLASS(rr0_a);
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.
343 qa_mblock_send::test_relay_routing_1()
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);
351 // Reach into the guts and see if the messages ended up where they should have
353 mb_mblock_sptr c0 = top->impl()->component("c0");
354 mb_mblock_sptr c0c0 = c0->impl()->component("c0");
356 mb_mblock_sptr c1 = top->impl()->component("c1");
358 // c0c0 should have received
359 // two message from c1 via its p2
361 msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
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)),
368 msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
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)),
375 // c1 should have received
376 // two message from c0c0 via its p2
378 msg = c1->impl()->msgq().get_highest_pri_msg_nowait();
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)),
385 msg = c1->impl()->msgq().get_highest_pri_msg_nowait();
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)),
393 // ================================================================
394 // test_relay_routing_2
395 // ================================================================
397 // top-level container for test_relay_routing_2
399 class rr0_b : public mb_mblock
402 rr0_b(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
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)
409 define_component("c0", "rr1");
410 define_component("c1", "rr1");
412 connect("c0", "p1", "c1", "p2");
413 connect("c0", "p2", "c1", "p1");
418 REGISTER_MBLOCK_CLASS(rr0_b);
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.
426 qa_mblock_send::test_relay_routing_2()
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);
434 // Reach into the guts and see if the messages ended up where they should have
436 mb_mblock_sptr c0 = top->impl()->component("c0");
437 mb_mblock_sptr c0c0 = c0->impl()->component("c0");
439 mb_mblock_sptr c1 = top->impl()->component("c1");
440 mb_mblock_sptr c1c0 = c1->impl()->component("c0");
442 // c0c0 should have received
443 // two message from c1c0 via its p2
445 msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
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)),
452 msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
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)),
459 // c1c0 should have received
460 // two message from c0c0 via its p2
462 msg = c1c0->impl()->msgq().get_highest_pri_msg_nowait();
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)),
469 msg = c1c0->impl()->msgq().get_highest_pri_msg_nowait();
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)),