1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007,2013 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 3, 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., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <gnuradio/blocks/nop.h>
28 #include <gnuradio/blocks/null_sink.h>
29 #include <gnuradio/blocks/null_source.h>
30 #include <gnuradio/flowgraph.h>
31 #include <boost/test/unit_test.hpp>
32 
33 namespace gr {
34 namespace blocks {
35 class null_qa_source : virtual public sync_block
36 {
37 public:
38     typedef boost::shared_ptr<null_qa_source> sptr;
39     static sptr make(size_t sizeof_stream_item);
40 };
41 class null_source_qa_impl : public null_qa_source
42 {
43 public:
null_source_qa_impl(size_t sizeof_stream_item)44     null_source_qa_impl(size_t sizeof_stream_item)
45         : sync_block("null_source",
46                      io_signature::make(0, 0, 0),
47                      io_signature::make(1, 1, sizeof_stream_item))
48     {
49     }
~null_source_qa_impl()50     ~null_source_qa_impl() {}
51 
work(int noutput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)52     int work(int noutput_items,
53              gr_vector_const_void_star& input_items,
54              gr_vector_void_star& output_items)
55     {
56         void* optr;
57         for (size_t n = 0; n < input_items.size(); n++) {
58             optr = (void*)output_items[n];
59             memset(optr, 0, noutput_items * output_signature()->sizeof_stream_item(n));
60         }
61         return noutput_items;
62     }
63 };
make(size_t sizeof_stream_item)64 null_qa_source::sptr null_qa_source::make(size_t sizeof_stream_item)
65 {
66     return gnuradio::get_initial_sptr(new null_source_qa_impl(sizeof_stream_item));
67 }
68 class null_qa_sink : virtual public sync_block
69 {
70 public:
71     typedef boost::shared_ptr<null_qa_sink> sptr;
72     static sptr make(size_t sizeof_stream_item);
73 };
74 class null_sink_qa_impl : public null_qa_sink
75 {
76 public:
null_sink_qa_impl(size_t sizeof_stream_item)77     null_sink_qa_impl(size_t sizeof_stream_item)
78         : sync_block("null_qa_sink",
79                      io_signature::make(1, 1, sizeof_stream_item),
80                      io_signature::make(0, 0, 0))
81     {
82     }
~null_sink_qa_impl()83     ~null_sink_qa_impl() {}
work(int noutput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)84     int work(int noutput_items,
85              gr_vector_const_void_star& input_items,
86              gr_vector_void_star& output_items)
87     {
88         return noutput_items;
89     }
90 };
make(size_t sizeof_stream_item)91 null_qa_sink::sptr null_qa_sink::make(size_t sizeof_stream_item)
92 {
93     return gnuradio::get_initial_sptr(new null_sink_qa_impl(sizeof_stream_item));
94 }
95 } /* namespace blocks */
96 } /* namespace gr */
97 
BOOST_AUTO_TEST_CASE(t0)98 BOOST_AUTO_TEST_CASE(t0)
99 {
100     gr::flowgraph_sptr fg = gr::make_flowgraph();
101 
102     BOOST_REQUIRE(fg);
103 }
104 
BOOST_AUTO_TEST_CASE(t1_connect)105 BOOST_AUTO_TEST_CASE(t1_connect)
106 {
107     gr::flowgraph_sptr fg = gr::make_flowgraph();
108 
109     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(int));
110     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
111 
112     fg->connect(nop1, 0, nop2, 0);
113 }
114 
BOOST_AUTO_TEST_CASE(t2_connect_invalid_src_port_neg)115 BOOST_AUTO_TEST_CASE(t2_connect_invalid_src_port_neg)
116 {
117     gr::flowgraph_sptr fg = gr::make_flowgraph();
118 
119     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(int));
120     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
121 
122     BOOST_REQUIRE_THROW(fg->connect(nop1, -1, nop2, 0), std::invalid_argument);
123 }
124 
BOOST_AUTO_TEST_CASE(t3_connect_src_port_exceeds)125 BOOST_AUTO_TEST_CASE(t3_connect_src_port_exceeds)
126 {
127     gr::flowgraph_sptr fg = gr::make_flowgraph();
128 
129     gr::block_sptr src = gr::blocks::null_qa_source::make(sizeof(int));
130     gr::block_sptr dst = gr::blocks::null_sink::make(sizeof(int));
131 
132     BOOST_REQUIRE_THROW(fg->connect(src, 1, dst, 0), std::invalid_argument);
133 }
134 
BOOST_AUTO_TEST_CASE(t4_connect_invalid_dst_port_neg)135 BOOST_AUTO_TEST_CASE(t4_connect_invalid_dst_port_neg)
136 {
137     gr::flowgraph_sptr fg = gr::make_flowgraph();
138 
139     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(int));
140     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
141 
142     BOOST_REQUIRE_THROW(fg->connect(nop1, 0, nop2, -1), std::invalid_argument);
143 }
144 
BOOST_AUTO_TEST_CASE(t5_connect_dst_port_exceeds)145 BOOST_AUTO_TEST_CASE(t5_connect_dst_port_exceeds)
146 {
147     gr::flowgraph_sptr fg = gr::make_flowgraph();
148 
149     gr::block_sptr src = gr::blocks::null_source::make(sizeof(int));
150     gr::block_sptr dst = gr::blocks::null_qa_sink::make(sizeof(int));
151 
152     BOOST_REQUIRE_THROW(fg->connect(src, 0, dst, 1), std::invalid_argument);
153 }
154 
BOOST_AUTO_TEST_CASE(t6_connect_dst_in_use)155 BOOST_AUTO_TEST_CASE(t6_connect_dst_in_use)
156 {
157     gr::flowgraph_sptr fg = gr::make_flowgraph();
158 
159     gr::block_sptr src1 = gr::blocks::null_source::make(sizeof(int));
160     gr::block_sptr src2 = gr::blocks::null_source::make(sizeof(int));
161     gr::block_sptr dst = gr::blocks::null_sink::make(sizeof(int));
162 
163     fg->connect(src1, 0, dst, 0);
164     BOOST_REQUIRE_THROW(fg->connect(src2, 0, dst, 0), std::invalid_argument);
165 }
166 
BOOST_AUTO_TEST_CASE(t7_connect_one_src_two_dst)167 BOOST_AUTO_TEST_CASE(t7_connect_one_src_two_dst)
168 {
169     gr::flowgraph_sptr fg = gr::make_flowgraph();
170 
171     gr::block_sptr src = gr::blocks::null_source::make(sizeof(int));
172     gr::block_sptr dst1 = gr::blocks::null_sink::make(sizeof(int));
173     gr::block_sptr dst2 = gr::blocks::null_sink::make(sizeof(int));
174 
175     fg->connect(src, 0, dst1, 0);
176     fg->connect(src, 0, dst2, 0);
177 }
178 
BOOST_AUTO_TEST_CASE(t8_connect_type_mismatch)179 BOOST_AUTO_TEST_CASE(t8_connect_type_mismatch)
180 {
181     gr::flowgraph_sptr fg = gr::make_flowgraph();
182 
183     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(char));
184     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
185 
186     BOOST_REQUIRE_THROW(fg->connect(nop1, 0, nop2, 0), std::invalid_argument);
187 }
188 
BOOST_AUTO_TEST_CASE(t9_disconnect)189 BOOST_AUTO_TEST_CASE(t9_disconnect)
190 {
191     gr::flowgraph_sptr fg = gr::make_flowgraph();
192 
193     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(int));
194     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
195 
196     fg->connect(nop1, 0, nop2, 0);
197     fg->disconnect(nop1, 0, nop2, 0);
198 }
199 
BOOST_AUTO_TEST_CASE(t10_disconnect_unconnected_block)200 BOOST_AUTO_TEST_CASE(t10_disconnect_unconnected_block)
201 {
202     gr::flowgraph_sptr fg = gr::make_flowgraph();
203 
204     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(int));
205     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
206     gr::block_sptr nop3 = gr::blocks::nop::make(sizeof(int));
207 
208     fg->connect(nop1, 0, nop2, 0);
209     BOOST_REQUIRE_THROW(fg->disconnect(nop1, 0, nop3, 0), std::invalid_argument);
210 }
211 
BOOST_AUTO_TEST_CASE(t11_disconnect_unconnected_port)212 BOOST_AUTO_TEST_CASE(t11_disconnect_unconnected_port)
213 {
214     gr::flowgraph_sptr fg = gr::make_flowgraph();
215 
216     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(int));
217     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
218 
219     fg->connect(nop1, 0, nop2, 0);
220     BOOST_REQUIRE_THROW(fg->disconnect(nop1, 0, nop2, 1), std::invalid_argument);
221 }
222 
BOOST_AUTO_TEST_CASE(t12_validate)223 BOOST_AUTO_TEST_CASE(t12_validate)
224 {
225     gr::flowgraph_sptr fg = gr::make_flowgraph();
226 
227     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(int));
228     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
229 
230     fg->connect(nop1, 0, nop2, 0);
231     fg->validate();
232 }
233 
BOOST_AUTO_TEST_CASE(t13_validate_missing_input_assignment)234 BOOST_AUTO_TEST_CASE(t13_validate_missing_input_assignment)
235 {
236     gr::flowgraph_sptr fg = gr::make_flowgraph();
237 
238     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(int));
239     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
240 
241     fg->connect(nop1, 0, nop2, 0);
242     fg->connect(nop1, 0, nop2, 2);
243     BOOST_REQUIRE_THROW(fg->validate(), std::runtime_error);
244 }
245 
BOOST_AUTO_TEST_CASE(t14_validate_missing_output_assignment)246 BOOST_AUTO_TEST_CASE(t14_validate_missing_output_assignment)
247 {
248     gr::flowgraph_sptr fg = gr::make_flowgraph();
249 
250     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(int));
251     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
252 
253     fg->connect(nop1, 0, nop2, 0);
254     fg->connect(nop1, 2, nop2, 1);
255     BOOST_REQUIRE_THROW(fg->validate(), std::runtime_error);
256 }
257 
BOOST_AUTO_TEST_CASE(t15_clear)258 BOOST_AUTO_TEST_CASE(t15_clear)
259 {
260     gr::flowgraph_sptr fg = gr::make_flowgraph();
261 
262     gr::block_sptr nop1 = gr::blocks::nop::make(sizeof(int));
263     gr::block_sptr nop2 = gr::blocks::nop::make(sizeof(int));
264 
265     fg->connect(nop1, 0, nop2, 0);
266 
267     BOOST_REQUIRE(fg->edges().size() == 1);
268     BOOST_REQUIRE(fg->calc_used_blocks().size() == 2);
269 
270     fg->clear();
271 
272     BOOST_REQUIRE(fg->edges().empty());
273     BOOST_REQUIRE(fg->calc_used_blocks().empty());
274 }
275 
BOOST_AUTO_TEST_CASE(t16_partition)276 BOOST_AUTO_TEST_CASE(t16_partition)
277 {
278     gr::flowgraph_sptr fg = gr::make_flowgraph();
279 
280     gr::block_sptr nop11 = gr::blocks::nop::make(sizeof(int));
281     gr::block_sptr nop12 = gr::blocks::nop::make(sizeof(int));
282     gr::block_sptr nop13 = gr::blocks::nop::make(sizeof(int));
283     gr::block_sptr nop14 = gr::blocks::nop::make(sizeof(int));
284 
285     gr::block_sptr nop21 = gr::blocks::nop::make(sizeof(int));
286     gr::block_sptr nop22 = gr::blocks::nop::make(sizeof(int));
287     gr::block_sptr nop23 = gr::blocks::nop::make(sizeof(int));
288 
289     gr::block_sptr nop31 = gr::blocks::nop::make(sizeof(int));
290     gr::block_sptr nop32 = gr::blocks::nop::make(sizeof(int));
291 
292     // Build disjoint graph #1
293     fg->connect(nop11, 0, nop12, 0);
294     fg->connect(nop12, 0, nop13, 0);
295     fg->connect(nop13, 0, nop14, 0);
296 
297     // Build disjoint graph #2
298     fg->connect(nop21, 0, nop22, 0);
299     fg->connect(nop22, 0, nop23, 0);
300 
301     // Build disjoint graph #3
302     fg->connect(nop31, 0, nop32, 0);
303 
304     std::vector<gr::basic_block_vector_t> graphs = fg->partition();
305 
306     BOOST_REQUIRE(graphs.size() == 3);
307     BOOST_REQUIRE(graphs[0].size() == 4);
308     BOOST_REQUIRE(graphs[1].size() == 3);
309     BOOST_REQUIRE(graphs[2].size() == 2);
310 }
311