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.
27 #include <qa_mblock_prims.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>
39 static pmt_t s_cs = pmt_intern("cs");
40 static pmt_t s_debug = pmt_intern("debug");
41 static pmt_t s_in = pmt_intern("in");
42 static pmt_t s_out = pmt_intern("out");
45 // ================================================================
47 class dp_1 : public mb_mblock
60 // ----------------------------------------------------------------
62 class dp_2 : public mb_mblock
71 define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);
76 // ----------------------------------------------------------------
78 class dp_3 : public mb_mblock
87 define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);
88 define_port("cs", "cs-protocol", false, mb_port::EXTERNAL); // duplicate def
93 // ----------------------------------------------------------------
96 qa_mblock_prims::test_define_ports()
98 mb_runtime_sptr rt = mb_make_runtime();
99 // std::vector<mb_port_sptr> intf;
101 mb_mblock_sptr mb1 = mb_mblock_sptr(new dp_1());
102 // intf = mb1->peer_interface();
103 // CPPUNIT_ASSERT_EQUAL(size_t(0), intf.size());
105 // raises runtime_error because of unknown protocol "cs-protocol"
106 CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_2()), std::runtime_error);
108 // define the protocol class
109 pmt_t pc = mb_make_protocol_class(pmt_intern("cs-protocol"),
110 pmt_list2(pmt_intern("start"),
114 // std::cout << "pc = " << pc << '\n';
116 mb_mblock_sptr mb2 = mb_mblock_sptr(new dp_2());
118 // raises pmt_exception because of duplicate port definition of "cs"
119 CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_3()), mbe_duplicate_port);
122 // ================================================================
124 class dc_0 : public mb_mblock
137 // ----------------------------------------------------------------
139 class dc_ok : public mb_mblock
148 define_component("c0", mb_mblock_sptr(new dc_0()));
149 define_component("c1", mb_mblock_sptr(new dc_0()));
150 define_component("c2", mb_mblock_sptr(new dc_0()));
155 // ----------------------------------------------------------------
157 class dc_not_ok : public mb_mblock
164 dc_not_ok::dc_not_ok()
167 define_component("c0", mb_mblock_sptr(new dc_0()));
168 define_component("c0", mb_mblock_sptr(new dc_0())); // duplicate name
171 dc_not_ok::~dc_not_ok(){}
173 // ----------------------------------------------------------------
176 qa_mblock_prims::test_define_components()
178 mb_runtime_sptr rt = mb_make_runtime();
179 mb_mblock_sptr mb1 = mb_mblock_sptr(new dc_ok()); // OK
181 // raises pmt_exception because of duplicate component definition of "c0"
182 CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dc_not_ok()), mbe_duplicate_component);
185 // ================================================================
187 class tc_norm : public mb_mblock
191 define_port("data", "i/o", false, mb_port::EXTERNAL);
192 define_port("norm", "i/o", false, mb_port::EXTERNAL);
193 define_port("conj", "i/o", true, mb_port::EXTERNAL);
194 define_port("int", "i/o", false, mb_port::INTERNAL);
200 tc_norm::~tc_norm(){}
202 ////////////////////////////////////////////////////////////////
204 class tc_0 : public mb_mblock
208 define_port("norm", "i/o", false, mb_port::EXTERNAL);
209 define_port("conj", "i/o", true, mb_port::EXTERNAL);
210 define_port("int", "i/o", false, mb_port::INTERNAL);
212 define_component("c0", mb_mblock_sptr(new tc_norm()));
213 define_component("c1", mb_mblock_sptr(new tc_norm()));
214 define_component("c2", mb_mblock_sptr(new tc_norm()));
215 define_component("c3", mb_mblock_sptr(new tc_norm()));
216 define_component("c4", mb_mblock_sptr(new tc_norm()));
217 define_component("c5", mb_mblock_sptr(new tc_norm()));
220 connect("c0", "norm", "c1", "conj");
222 // No: No such component name
223 CPPUNIT_ASSERT_THROW(connect("foo", "data", "c1", "norm"), mbe_no_such_component);
225 // No: No such port name
226 CPPUNIT_ASSERT_THROW(connect("c0", "data", "c1", "foo"), mbe_no_such_port);
228 // No: already connected
229 CPPUNIT_ASSERT_THROW(connect("c0", "norm", "c2", "data"), mbe_already_connected);
231 // No: already connected
232 CPPUNIT_ASSERT_THROW(connect("c2", "data", "c0", "norm"), mbe_already_connected);
234 // No: incompatible ports
235 CPPUNIT_ASSERT_THROW(connect("c1", "norm", "c2", "norm"), mbe_incompatible_ports);
238 connect("c1", "norm", "c2", "conj");
240 // No: No such port name
241 CPPUNIT_ASSERT_THROW(connect("c2", "norm", "self", "foo"), mbe_no_such_port);
243 // No: can't connect to child's internal port
244 CPPUNIT_ASSERT_THROW(connect("c0", "conj", "c2", "int"), mbe_no_such_port);
246 // No: can't connect to our own external port
247 CPPUNIT_ASSERT_THROW(connect("self", "norm", "c0", "conj"), mbe_invalid_port_type);
249 // OK: connecting to one of our internal ports
250 connect("self", "int", "c3", "conj");
252 // ===== Now test disconnecting some stuff =====
254 // Confirm we're already connected
255 CPPUNIT_ASSERT_THROW(connect("self", "int", "c3", "conj"), mbe_already_connected);
257 int nc = nconnections();
258 disconnect("self", "int", "c3", "conj"); // disconnect
259 CPPUNIT_ASSERT_EQUAL(nc-1, nconnections());
261 connect("self", "int", "c3", "conj"); // reconnect
262 CPPUNIT_ASSERT_EQUAL(nc, nconnections());
264 // confirm we're already connected
265 CPPUNIT_ASSERT_THROW(connect("self", "int", "c3", "conj"), mbe_already_connected);
268 connect("c0", "conj", "c5", "data");
269 connect("c4", "norm", "c5", "conj");
270 connect("c4", "conj", "c5", "norm");
273 disconnect_component("c4");
274 CPPUNIT_ASSERT_EQUAL(nc-2, nconnections());
276 disconnect_component("c5");
277 CPPUNIT_ASSERT_EQUAL(nc-3, nconnections());
280 CPPUNIT_ASSERT_EQUAL(0, nconnections());
289 ////////////////////////////////////////////////////////////////
291 class tc_1 : public mb_mblock
295 define_component("c0", mb_mblock_sptr(new tc_norm()));
296 define_component("c1", mb_mblock_sptr(new tc_norm()));
298 connect("c0", "norm", "c1", "conj");
306 ////////////////////////////////////////////////////////////////
309 qa_mblock_prims::test_connect()
311 // define the protocol class
312 mb_make_protocol_class(pmt_intern("data"), // name of class
313 pmt_list1(pmt_intern("data")), // in
316 mb_make_protocol_class(pmt_intern("i/o"), // name of class
317 pmt_list1(pmt_intern("in")), // in
318 pmt_list1(pmt_intern("out"))); // out
321 mb_runtime_sptr rt = mb_make_runtime();
322 mb_mblock_sptr mb0 = mb_mblock_sptr(new tc_0());
325 ////////////////////////////////////////////////////////////////
328 qa_mblock_prims::test_msg_queue()
332 // check initial state
333 CPPUNIT_ASSERT(q.get_highest_pri_msg() == 0);
335 CPPUNIT_ASSERT(MB_NPRI >= 5); // sanity check for this test
337 // insert three messages at the same pri and ensure that they come out in order
338 // signal data metadata pri
339 q.insert(mb_make_message(PMT_NIL, pmt_from_long(0), PMT_NIL, MB_PRI_BEST + 2));
340 q.insert(mb_make_message(PMT_NIL, pmt_from_long(1), PMT_NIL, MB_PRI_BEST + 2));
341 q.insert(mb_make_message(PMT_NIL, pmt_from_long(2), PMT_NIL, MB_PRI_BEST + 2));
343 CPPUNIT_ASSERT_EQUAL(0L, pmt_to_long(q.get_highest_pri_msg()->data()));
344 CPPUNIT_ASSERT_EQUAL(1L, pmt_to_long(q.get_highest_pri_msg()->data()));
345 CPPUNIT_ASSERT_EQUAL(2L, pmt_to_long(q.get_highest_pri_msg()->data()));
347 CPPUNIT_ASSERT(q.get_highest_pri_msg() == 0);
350 // insert messages of different priorities in pseudo-random order
351 // signal data metadata pri
352 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 3));
353 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 2));
354 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 4));
355 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 0));
356 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 1));
357 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 3));
358 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 2));
359 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 4));
360 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 0));
361 q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 1));
363 // confirm that they come out in order
364 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 0, q.get_highest_pri_msg()->priority());
365 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 0, q.get_highest_pri_msg()->priority());
366 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 1, q.get_highest_pri_msg()->priority());
367 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 1, q.get_highest_pri_msg()->priority());
368 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 2, q.get_highest_pri_msg()->priority());
369 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 2, q.get_highest_pri_msg()->priority());
370 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 3, q.get_highest_pri_msg()->priority());
371 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 3, q.get_highest_pri_msg()->priority());
372 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 4, q.get_highest_pri_msg()->priority());
373 CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 4, q.get_highest_pri_msg()->priority());
376 CPPUNIT_ASSERT(q.get_highest_pri_msg() == 0);
379 ////////////////////////////////////////////////////////////////
382 qa_mblock_prims::test_make_accepter()
385 mb_mblock_sptr mb = mb_mblock_sptr(new dp_2());
387 // use "internal use only" method...
388 mb_msg_accepter_sptr accepter = mb->impl()->make_accepter("cs");
390 // Now push a few messages into it...
391 // signal data metadata pri
392 (*accepter)(PMT_NIL, pmt_from_long(0), PMT_NIL, MB_PRI_BEST + 2);
393 (*accepter)(PMT_NIL, pmt_from_long(1), PMT_NIL, MB_PRI_BEST + 2);
394 (*accepter)(PMT_NIL, pmt_from_long(2), PMT_NIL, MB_PRI_BEST + 2);
396 // try to pull them out
398 pmt_t cs = pmt_intern("cs");
400 mb_message_sptr msg = mb->impl()->msgq().get_highest_pri_msg();
401 CPPUNIT_ASSERT(pmt_eq(cs, msg->port_id())); // confirm that port_id is set
402 CPPUNIT_ASSERT_EQUAL(0L, pmt_to_long(msg->data())); // and that data is correct
404 CPPUNIT_ASSERT_EQUAL(1L, pmt_to_long(mb->impl()->msgq().get_highest_pri_msg()->data()));
405 CPPUNIT_ASSERT_EQUAL(2L, pmt_to_long(mb->impl()->msgq().get_highest_pri_msg()->data()));