3 * Copyright 2006,2007 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 2, 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.
23 #include <qa_mblock_prims.h>
24 #include <cppunit/TestAssert.h>
25 #include <mb_mblock.h>
26 #include <mb_runtime.h>
27 #include <mb_protocol_class.h>
28 #include <mb_exception.h>
29 #include <mb_msg_queue.h>
30 #include <mb_message.h>
31 #include <mb_mblock_impl.h>
32 #include <mb_msg_accepter.h>
35 static pmt_t s_cs = pmt_intern("cs");
36 static pmt_t s_debug = pmt_intern("debug");
37 static pmt_t s_in = pmt_intern("in");
38 static pmt_t s_out = pmt_intern("out");
41 // ================================================================
43 class dp_1 : public mb_mblock
56 // ----------------------------------------------------------------
58 class dp_2 : public mb_mblock
67 define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);
72 // ----------------------------------------------------------------
74 class dp_3 : public mb_mblock
83 define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);
84 define_port("cs", "cs-protocol", false, mb_port::EXTERNAL); // duplicate def
89 // ----------------------------------------------------------------
92 qa_mblock_prims::test_define_ports()
94 mb_runtime_sptr rt = mb_make_runtime();
95 // std::vector<mb_port_sptr> intf;
97 mb_mblock_sptr mb1 = mb_mblock_sptr(new dp_1());
98 // intf = mb1->peer_interface();
99 // CPPUNIT_ASSERT_EQUAL(size_t(0), intf.size());
101 // raises runtime_error because of unknown protocol "cs-protocol"
102 CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_2()), std::runtime_error);
104 // define the protocol class
105 pmt_t pc = mb_make_protocol_class(pmt_intern("cs-protocol"),
106 pmt_cons(pmt_intern("start"),
107 pmt_cons(pmt_intern("stop"),
111 // std::cout << "pc = " << pc << '\n';
113 mb_mblock_sptr mb2 = mb_mblock_sptr(new dp_2());
115 // intf = mb2->peer_interface();
116 // CPPUNIT_ASSERT_EQUAL(size_t(1), intf.size());
117 // CPPUNIT_ASSERT(pmt_eq(s_cs, intf[0]->port_name()));
120 // raises pmt_exception because of duplicate port definition of "cs"
121 CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_3()), mbe_duplicate_port);
125 mb_mblock_sptr mb2 = mb_mblock_sptr(new dp_2());
127 catch (pmt_exception &e){
128 std::cerr << e.msg() << ' ' << e.obj() << '\n';
134 // ================================================================
136 class dc_0 : public mb_mblock
149 // ----------------------------------------------------------------
151 class dc_ok : public mb_mblock
160 define_component("c0", mb_mblock_sptr(new dc_0()));
161 define_component("c1", mb_mblock_sptr(new dc_0()));
162 define_component("c2", mb_mblock_sptr(new dc_0()));
167 // ----------------------------------------------------------------
169 class dc_not_ok : public mb_mblock
176 dc_not_ok::dc_not_ok()
179 define_component("c0", mb_mblock_sptr(new dc_0()));
180 define_component("c0", mb_mblock_sptr(new dc_0())); // duplicate name
183 dc_not_ok::~dc_not_ok(){}
185 // ----------------------------------------------------------------
188 qa_mblock_prims::test_define_components()
190 mb_runtime_sptr rt = mb_make_runtime();
191 mb_mblock_sptr mb1 = mb_mblock_sptr(new dc_ok()); // OK
193 // raises pmt_exception because of duplicate component definition of "c0"
194 CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dc_not_ok()), mbe_duplicate_component);
197 // ================================================================
199 class tc_norm : public mb_mblock
203 define_port("data", "i/o", false, mb_port::EXTERNAL);
204 define_port("norm", "i/o", false, mb_port::EXTERNAL);
205 define_port("conj", "i/o", true, mb_port::EXTERNAL);
206 define_port("int", "i/o", false, mb_port::INTERNAL);
212 tc_norm::~tc_norm(){}
214 ////////////////////////////////////////////////////////////////
216 class tc_0 : public mb_mblock
220 define_port("norm", "i/o", false, mb_port::EXTERNAL);
221 define_port("conj", "i/o", true, mb_port::EXTERNAL);
222 define_port("int", "i/o", false, mb_port::INTERNAL);
224 define_component("c0", mb_mblock_sptr(new tc_norm()));
225 define_component("c1", mb_mblock_sptr(new tc_norm()));
226 define_component("c2", mb_mblock_sptr(new tc_norm()));
227 define_component("c3", mb_mblock_sptr(new tc_norm()));
228 define_component("c4", mb_mblock_sptr(new tc_norm()));
229 define_component("c5", mb_mblock_sptr(new tc_norm()));
232 connect("c0", "norm", "c1", "conj");
234 // No: No such component name
235 CPPUNIT_ASSERT_THROW(connect("foo", "data", "c1", "norm"), mbe_no_such_component);
237 // No: No such port name
238 CPPUNIT_ASSERT_THROW(connect("c0", "data", "c1", "foo"), mbe_no_such_port);
240 // No: already connected
241 CPPUNIT_ASSERT_THROW(connect("c0", "norm", "c2", "data"), mbe_already_connected);
243 // No: already connected
244 CPPUNIT_ASSERT_THROW(connect("c2", "data", "c0", "norm"), mbe_already_connected);
246 // No: incompatible ports
247 CPPUNIT_ASSERT_THROW(connect("c1", "norm", "c2", "norm"), mbe_incompatible_ports);
250 connect("c1", "norm", "c2", "conj");
252 // No: No such port name
253 CPPUNIT_ASSERT_THROW(connect("c2", "norm", "self", "foo"), mbe_no_such_port);
255 // No: can't connect to child's internal port
256 CPPUNIT_ASSERT_THROW(connect("c0", "conj", "c2", "int"), mbe_no_such_port);
258 // No: can't connect to our own external port
259 CPPUNIT_ASSERT_THROW(connect("self", "norm", "c0", "conj"), mbe_invalid_port_type);
261 // OK: connecting to one of our internal ports
262 connect("self", "int", "c3", "conj");
264 // ===== Now test disconnecting some stuff =====
266 // Confirm we're already connected
267 CPPUNIT_ASSERT_THROW(connect("self", "int", "c3", "conj"), mbe_already_connected);
269 int nc = nconnections();
270 disconnect("self", "int", "c3", "conj"); // disconnect
271 CPPUNIT_ASSERT_EQUAL(nc-1, nconnections());
273 connect("self", "int", "c3", "conj"); // reconnect
274 CPPUNIT_ASSERT_EQUAL(nc, nconnections());
276 // confirm we're already connected
277 CPPUNIT_ASSERT_THROW(connect("self", "int", "c3", "conj"), mbe_already_connected);
280 connect("c0", "conj", "c5", "data");
281 connect("c4", "norm", "c5", "conj");
282 connect("c4", "conj", "c5", "norm");
285 disconnect_component("c4");
286 CPPUNIT_ASSERT_EQUAL(nc-2, nconnections());
288 disconnect_component("c5");
289 CPPUNIT_ASSERT_EQUAL(nc-3, nconnections());
292 CPPUNIT_ASSERT_EQUAL(0, nconnections());
301 ////////////////////////////////////////////////////////////////
303 class tc_1 : public mb_mblock
307 define_component("c0", mb_mblock_sptr(new tc_norm()));
308 define_component("c1", mb_mblock_sptr(new tc_norm()));
310 connect("c0", "norm", "c1", "conj");
318 ////////////////////////////////////////////////////////////////
321 qa_mblock_prims::test_connect()
323 // define the protocol class
324 mb_make_protocol_class(pmt_intern("data"), // name of class
325 pmt_cons(pmt_intern("data"), PMT_NIL), // in
328 mb_make_protocol_class(pmt_intern("i/o"), // name of class
329 pmt_cons(pmt_intern("in"), PMT_NIL), // in
330 pmt_cons(pmt_intern("out"), PMT_NIL)); // out
333 mb_runtime_sptr rt = mb_make_runtime();
334 mb_mblock_sptr mb0 = mb_mblock_sptr(new tc_0());
337 ////////////////////////////////////////////////////////////////
340 qa_mblock_prims::test_msg_queue()
344 // check initial state
345 CPPUNIT_ASSERT(q.get_highest_pri_msg() == 0);
347 CPPUNIT_ASSERT(MB_NPRI >= 5); // sanity check for this test
349 // insert three messages at the same pri and ensure that they come out in order
350 // signal data metadata pri
351 q.insert(mb_make_message(PMT_NIL, pmt_from_long(0), PMT_NIL, MB_PRI_BEST + 2));
352 q.insert(mb_make_message(PMT_NIL, pmt_from_long(1), PMT_NIL, MB_PRI_BEST + 2));
353 q.insert(mb_make_message(PMT_NIL, pmt_from_long(2), PMT_NIL, MB_PRI_BEST + 2));
355 CPPUNIT_ASSERT_EQUAL(0L, pmt_to_long(q.get_highest_pri_msg()->data()));
356 CPPUNIT_ASSERT_EQUAL(1L, pmt_to_long(q.get_highest_pri_msg()->data()));
357 CPPUNIT_ASSERT_EQUAL(2L, pmt_to_long(q.get_highest_pri_msg()->data()));
359 CPPUNIT_ASSERT(q.get_highest_pri_msg() == 0);
362 // insert messages of different priorities in pseudo-random order
363 // signal data metadata pri
364 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 3));
365 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 2));
366 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 4));
367 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 0));
368 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 1));
369 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 3));
370 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 2));
371 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 4));
372 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 0));
373 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 1));
375 // confirm that they come out in order
376 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 0, q.get_highest_pri_msg()->priority());
377 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 0, q.get_highest_pri_msg()->priority());
378 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 1, q.get_highest_pri_msg()->priority());
379 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 1, q.get_highest_pri_msg()->priority());
380 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 2, q.get_highest_pri_msg()->priority());
381 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 2, q.get_highest_pri_msg()->priority());
382 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 3, q.get_highest_pri_msg()->priority());
383 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 3, q.get_highest_pri_msg()->priority());
384 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 4, q.get_highest_pri_msg()->priority());
385 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 4, q.get_highest_pri_msg()->priority());
388 CPPUNIT_ASSERT(q.get_highest_pri_msg() == 0);
391 ////////////////////////////////////////////////////////////////
394 qa_mblock_prims::test_make_accepter()
397 mb_mblock_sptr mb = mb_mblock_sptr(new dp_2());
399 // use "internal use only" method...
400 mb_msg_accepter_sptr accepter = mb->impl()->make_accepter("cs");
402 // Now push a few messages into it...
403 // signal data metadata pri
404 (*accepter)(PMT_NIL, pmt_from_long(0), PMT_NIL, MB_PRI_BEST + 2);
405 (*accepter)(PMT_NIL, pmt_from_long(1), PMT_NIL, MB_PRI_BEST + 2);
406 (*accepter)(PMT_NIL, pmt_from_long(2), PMT_NIL, MB_PRI_BEST + 2);
408 // try to pull them out
410 pmt_t cs = pmt_intern("cs");
412 mb_message_sptr msg = mb->impl()->msgq().get_highest_pri_msg();
413 CPPUNIT_ASSERT(pmt_eq(cs, msg->port_id())); // confirm that port_id is set
414 CPPUNIT_ASSERT_EQUAL(0L, pmt_to_long(msg->data())); // and that data is correct
416 CPPUNIT_ASSERT_EQUAL(1L, pmt_to_long(mb->impl()->msgq().get_highest_pri_msg()->data()));
417 CPPUNIT_ASSERT_EQUAL(2L, pmt_to_long(mb->impl()->msgq().get_highest_pri_msg()->data()));