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 using namespace gruel;
43 static pmt_t s_data = pmt_intern("data");
44 static pmt_t s_status = pmt_intern("status");
45 static pmt_t s_control = pmt_intern("control");
46 static pmt_t s_p0 = pmt_intern("p0");
47 static pmt_t s_p1 = pmt_intern("p1");
48 static pmt_t s_p2 = pmt_intern("p2");
49 static pmt_t s_p3 = pmt_intern("p3");
50 static pmt_t s_e1 = pmt_intern("e1");
51 static pmt_t s_r1 = pmt_intern("r1");
54 define_protocol_classes()
56 // Defined from client point-of-view.
57 mb_make_protocol_class(pmt_intern("qa-send-cs"), // name
58 pmt_list1(s_status), // incoming
59 pmt_list1(s_control)); // outgoing
64 get_top(mb_runtime_sptr rts)
66 return dynamic_cast<mb_runtime_nop *>(rts.get())->top();
69 // ================================================================
70 // test_simple_routing
71 // ================================================================
73 // sub-block for test_simple_routing
75 class sr1 : public mb_mblock
82 sr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
84 void initial_transition();
87 sr1::sr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
88 : mb_mblock(runtime, instance_name, user_arg)
90 d_p1 = define_port("p1", "qa-send-cs", true, mb_port::EXTERNAL);
91 d_p2 = define_port("p2", "qa-send-cs", true, mb_port::EXTERNAL);
92 d_p3 = define_port("p3", "qa-send-cs", false, mb_port::EXTERNAL);
98 sr1::initial_transition()
100 // std::cout << instance_name() << "[sr1]: initial_transition\n";
102 // send two messages to each port
103 pmt_t our_name = pmt_intern(instance_name());
104 d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(0)));
105 d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(1)));
107 d_p2->send(s_status, pmt_list3(our_name, s_p2, pmt_from_long(0)));
108 d_p2->send(s_status, pmt_list3(our_name, s_p2, pmt_from_long(1)));
111 REGISTER_MBLOCK_CLASS(sr1);
113 // ----------------------------------------------------------------
115 // top-level container block for test_simple_routing
116 class sr0 : public mb_mblock
121 sr0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
123 void initial_transition();
126 sr0::sr0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
127 : mb_mblock(runtime, instance_name, user_arg)
129 d_p0 = define_port("p0", "qa-send-cs", false, mb_port::INTERNAL);
131 define_component("mb1", "sr1");
132 define_component("mb2", "sr1");
134 connect("self", "p0", "mb1", "p1");
135 connect("mb1", "p2", "mb2", "p3");
136 connect("mb1", "p3", "mb2", "p2");
142 sr0::initial_transition()
144 // std::cout << instance_name() << "[sr0]: initial_transition\n";
146 // send two messages to p0
147 pmt_t our_name = pmt_intern(instance_name());
148 d_p0->send(s_control, pmt_list3(our_name, s_p0, pmt_from_long(0)));
149 d_p0->send(s_control, pmt_list3(our_name, s_p0, pmt_from_long(1)));
152 REGISTER_MBLOCK_CLASS(sr0);
154 // ----------------------------------------------------------------
157 * This tests basic message routing using INTERNAL and EXTERNAL ports.
158 * It does not rely on the guts of the runtime being complete,
159 * which is good, because at the time this is being written, it isn't.
162 qa_mblock_send::test_simple_routing()
164 define_protocol_classes();
168 mb_runtime_sptr rt = mb_make_runtime_nop();
169 rt->run("top", "sr0", PMT_F);
171 mb_mblock_sptr mb0 = get_top(rt);
173 // Reach into the guts and see if the messages ended up where they should have
175 // mb0 should have received two messages sent from mb1 via its p1
176 msg = mb0->impl()->msgq().get_highest_pri_msg_nowait();
178 // std::cerr << msg->data() << std::endl;
179 CPPUNIT_ASSERT_EQUAL(s_p0, msg->port_id());
180 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p1, pmt_from_long(0)),
183 msg = mb0->impl()->msgq().get_highest_pri_msg_nowait();
185 // std::cerr << msg->data() << std::endl;
186 CPPUNIT_ASSERT_EQUAL(s_p0, msg->port_id());
187 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p1, pmt_from_long(1)),
190 // mb1 should have received
191 // two messages from mb0 via its p0 and
192 // two messages from mb2 via its p3
194 mb_mblock_sptr mb1 = mb0->impl()->component("mb1");
196 msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
198 // std::cerr << msg->data() << std::endl;
199 CPPUNIT_ASSERT_EQUAL(s_p1, msg->port_id());
200 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top"), s_p0, pmt_from_long(0)),
203 msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
205 // std::cerr << msg->data() << std::endl;
206 CPPUNIT_ASSERT_EQUAL(s_p1, msg->port_id());
207 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top"), s_p0, pmt_from_long(1)),
210 msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
212 // std::cerr << msg->data() << std::endl;
213 CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
214 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb2"), s_p2, pmt_from_long(0)),
217 msg = mb1->impl()->msgq().get_highest_pri_msg_nowait();
219 // std::cerr << msg->data() << std::endl;
220 CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
221 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb2"), s_p2, pmt_from_long(1)),
225 // mb2 should have received
226 // two messages from mb2 via its p2
228 mb_mblock_sptr mb2 = mb0->impl()->component("mb2");
230 msg = mb2->impl()->msgq().get_highest_pri_msg_nowait();
232 // std::cerr << msg->data() << std::endl;
233 CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
234 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p2, pmt_from_long(0)),
237 msg = mb2->impl()->msgq().get_highest_pri_msg_nowait();
239 // std::cerr << msg->data() << std::endl;
240 CPPUNIT_ASSERT_EQUAL(s_p3, msg->port_id());
241 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/mb1"), s_p2, pmt_from_long(1)),
245 // ================================================================
246 // test_relay_routing_1
247 // ================================================================
249 // internal block for test_relay_routing
251 class rr2 : public mb_mblock
257 rr2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
259 void initial_transition();
262 rr2::rr2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
263 : mb_mblock(runtime, instance_name, user_arg)
265 d_p1 = define_port("p1", "qa-send-cs", true, mb_port::EXTERNAL);
266 d_p2 = define_port("p2", "qa-send-cs", false, mb_port::EXTERNAL);
272 rr2::initial_transition()
274 // std::cout << instance_name() << "[rr2]: initial_transition\n";
276 // send two messages via p1
277 pmt_t our_name = pmt_intern(instance_name());
278 d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(0)));
279 d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(1)));
282 REGISTER_MBLOCK_CLASS(rr2);
284 // ----------------------------------------------------------------
286 // intermediate block for test_relay_routing
288 class rr1 : public mb_mblock
294 rr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
298 rr1::rr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
299 : mb_mblock(runtime, instance_name, user_arg)
301 d_p1 = define_port("p1", "qa-send-cs", true, mb_port::RELAY);
302 d_p2 = define_port("p2", "qa-send-cs", false, mb_port::RELAY);
304 define_component("c0", "rr2");
306 connect("self", "p1", "c0", "p1");
307 connect("self", "p2", "c0", "p2");
312 REGISTER_MBLOCK_CLASS(rr1);
314 // ----------------------------------------------------------------
316 // top-level container for test_relay_routing
318 class rr0_a : public mb_mblock
321 rr0_a(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
325 rr0_a::rr0_a(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
326 : mb_mblock(runtime, instance_name, user_arg)
328 define_component("c0", "rr1");
329 define_component("c1", "rr2");
331 connect("c0", "p1", "c1", "p2");
332 connect("c0", "p2", "c1", "p1");
337 REGISTER_MBLOCK_CLASS(rr0_a);
340 * This tests basic message routing using RELAY and EXTERNAL ports.
341 * It does not rely on the guts of the runtime being complete,
342 * which is good, because at the time this is being written, it isn't.
345 qa_mblock_send::test_relay_routing_1()
349 mb_runtime_sptr rt = mb_make_runtime_nop();
350 rt->run("top", "rr0_a", PMT_F);
351 mb_mblock_sptr top = get_top(rt);
353 // Reach into the guts and see if the messages ended up where they should have
355 mb_mblock_sptr c0 = top->impl()->component("c0");
356 mb_mblock_sptr c0c0 = c0->impl()->component("c0");
358 mb_mblock_sptr c1 = top->impl()->component("c1");
360 // c0c0 should have received
361 // two message from c1 via its p2
363 msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
365 //std::cerr << msg->data() << std::endl;
366 CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
367 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1"), s_p1, pmt_from_long(0)),
370 msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
372 //std::cerr << msg->data() << std::endl;
373 CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
374 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1"), s_p1, pmt_from_long(1)),
377 // c1 should have received
378 // two message from c0c0 via its p2
380 msg = c1->impl()->msgq().get_highest_pri_msg_nowait();
382 //std::cerr << msg->data() << std::endl;
383 CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
384 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(0)),
387 msg = c1->impl()->msgq().get_highest_pri_msg_nowait();
389 //std::cerr << msg->data() << std::endl;
390 CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
391 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(1)),
395 // ================================================================
396 // test_relay_routing_2
397 // ================================================================
399 // top-level container for test_relay_routing_2
401 class rr0_b : public mb_mblock
404 rr0_b(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
408 rr0_b::rr0_b(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
409 : mb_mblock(runtime, instance_name, user_arg)
411 define_component("c0", "rr1");
412 define_component("c1", "rr1");
414 connect("c0", "p1", "c1", "p2");
415 connect("c0", "p2", "c1", "p1");
420 REGISTER_MBLOCK_CLASS(rr0_b);
423 * This tests basic message routing using RELAY and EXTERNAL ports.
424 * It does not rely on the guts of the runtime being complete,
425 * which is good, because at the time this is being written, it isn't.
428 qa_mblock_send::test_relay_routing_2()
432 mb_runtime_sptr rt = mb_make_runtime_nop();
433 rt->run("top", "rr0_b", PMT_F);
434 mb_mblock_sptr top = get_top(rt);
436 // Reach into the guts and see if the messages ended up where they should have
438 mb_mblock_sptr c0 = top->impl()->component("c0");
439 mb_mblock_sptr c0c0 = c0->impl()->component("c0");
441 mb_mblock_sptr c1 = top->impl()->component("c1");
442 mb_mblock_sptr c1c0 = c1->impl()->component("c0");
444 // c0c0 should have received
445 // two message from c1c0 via its p2
447 msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
449 // std::cerr << msg->data() << std::endl;
450 CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
451 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1/c0"), s_p1, pmt_from_long(0)),
454 msg = c0c0->impl()->msgq().get_highest_pri_msg_nowait();
456 // std::cerr << msg->data() << std::endl;
457 CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
458 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c1/c0"), s_p1, pmt_from_long(1)),
461 // c1c0 should have received
462 // two message from c0c0 via its p2
464 msg = c1c0->impl()->msgq().get_highest_pri_msg_nowait();
466 // std::cerr << msg->data() << std::endl;
467 CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
468 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(0)),
471 msg = c1c0->impl()->msgq().get_highest_pri_msg_nowait();
473 // std::cerr << msg->data() << std::endl;
474 CPPUNIT_ASSERT_EQUAL(s_p2, msg->port_id());
475 CPPUNIT_ASSERT(pmt_equal(pmt_list3(pmt_intern("top/c0/c0"), s_p1, pmt_from_long(1)),