1 /* -*- c++ -*- */
2 /*
3 * Copyright 2010,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/block.h>
28 #include <gnuradio/blocks/annotator_1to1.h>
29 #include <gnuradio/blocks/annotator_alltoall.h>
30 #include <gnuradio/blocks/head.h>
31 #include <gnuradio/blocks/keep_one_in_n.h>
32 #include <gnuradio/blocks/null_sink.h>
33 #include <gnuradio/blocks/null_source.h>
34 #include <gnuradio/top_block.h>
35 #include <boost/test/unit_test.hpp>
36
37
38 // ----------------------------------------------------------------
39
40 // set to 1 to turn on debug output
41 // The debug output fully checks that the tags seen are what are expected. While
42 // this behavior currently works with our implementation, there is no guarantee
43 // that the tags will be coming in this specific order, so it's dangerous to
44 // rely on this as a test of the tag system working. We would really want to
45 // tags we know we should see and then test that they all occur once, but in no
46 // particular order.
47 #define QA_TAGS_DEBUG 0
48
make_tag(uint64_t offset,pmt::pmt_t key,pmt::pmt_t value,pmt::pmt_t srcid)49 gr::tag_t make_tag(uint64_t offset, pmt::pmt_t key, pmt::pmt_t value, pmt::pmt_t srcid)
50 {
51 gr::tag_t result;
52 result.offset = offset;
53 result.key = key;
54 result.value = value;
55 result.srcid = srcid;
56 return result;
57 }
58
operator <<(std::ostream & os,const gr::tag_t & t)59 std::ostream& operator<<(std::ostream& os, const gr::tag_t& t) { return os; }
60
BOOST_AUTO_TEST_CASE(t0)61 BOOST_AUTO_TEST_CASE(t0)
62 {
63 unsigned int N = 1000;
64 gr::top_block_sptr tb = gr::make_top_block("top");
65 gr::block_sptr src(gr::blocks::null_source::make(sizeof(int)));
66 gr::block_sptr head(gr::blocks::head::make(sizeof(int), N));
67 gr::block_sptr snk(gr::blocks::null_sink::make(sizeof(int)));
68
69 tb->connect(src, 0, head, 0);
70 tb->connect(head, 0, snk, 0);
71
72 BOOST_REQUIRE_EQUAL(src->nitems_read(0), (uint64_t)0);
73 BOOST_REQUIRE_EQUAL(src->nitems_written(0), (uint64_t)0);
74
75 tb->run();
76
77 BOOST_REQUIRE_THROW(src->nitems_read(0), std::invalid_argument);
78 BOOST_REQUIRE(src->nitems_written(0) >= N);
79 BOOST_REQUIRE_EQUAL(snk->nitems_read(0), (uint64_t)1000);
80 BOOST_REQUIRE_THROW(snk->nitems_written(0), std::invalid_argument);
81 }
82
83
BOOST_AUTO_TEST_CASE(t1)84 BOOST_AUTO_TEST_CASE(t1)
85 {
86 int N = 40000;
87 gr::top_block_sptr tb = gr::make_top_block("top");
88 gr::block_sptr src(gr::blocks::null_source::make(sizeof(int)));
89 gr::block_sptr head(gr::blocks::head::make(sizeof(int), N));
90 gr::blocks::annotator_alltoall::sptr ann0(
91 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
92 gr::blocks::annotator_alltoall::sptr ann1(
93 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
94 gr::blocks::annotator_alltoall::sptr ann2(
95 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
96 gr::blocks::annotator_alltoall::sptr ann3(
97 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
98 gr::blocks::annotator_alltoall::sptr ann4(
99 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
100 gr::block_sptr snk0(gr::blocks::null_sink::make(sizeof(int)));
101 gr::block_sptr snk1(gr::blocks::null_sink::make(sizeof(int)));
102
103 tb->connect(src, 0, head, 0);
104 tb->connect(head, 0, ann0, 0);
105
106 tb->connect(ann0, 0, ann1, 0);
107 tb->connect(ann0, 1, ann2, 0);
108 tb->connect(ann1, 0, ann3, 0);
109 tb->connect(ann2, 0, ann4, 0);
110
111 tb->connect(ann3, 0, snk0, 0);
112 tb->connect(ann4, 0, snk1, 0);
113
114 tb->run();
115
116 std::vector<gr::tag_t> tags0 = ann0->data();
117 std::vector<gr::tag_t> tags3 = ann3->data();
118 std::vector<gr::tag_t> tags4 = ann4->data();
119
120 // The first annotator does not receive any tags from the null sink upstream
121 BOOST_REQUIRE_EQUAL(tags0.size(), (size_t)0);
122 BOOST_REQUIRE_EQUAL(tags3.size(), (size_t)8);
123 BOOST_REQUIRE_EQUAL(tags4.size(), (size_t)8);
124
125 #if QA_TAGS_DEBUG
126 // Kludge together the tags that we know should result from the above graph
127 std::stringstream str0, str1, str2;
128 str0 << ann0->name() << ann0->unique_id();
129 str1 << ann1->name() << ann1->unique_id();
130 str2 << ann2->name() << ann2->unique_id();
131
132 gr::tag_t expected_tags3[8];
133 expected_tags3[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0));
134 expected_tags3[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0));
135 expected_tags3[2] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(1));
136 expected_tags3[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2));
137 expected_tags3[4] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2));
138 expected_tags3[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4));
139 expected_tags3[6] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3));
140 expected_tags3[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6));
141
142 gr::tag_t expected_tags4[8];
143 expected_tags4[0] = make_tag(0, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(0));
144 expected_tags4[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1));
145 expected_tags4[2] = make_tag(10000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(1));
146 expected_tags4[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3));
147 expected_tags4[4] = make_tag(20000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(2));
148 expected_tags4[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5));
149 expected_tags4[6] = make_tag(30000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(3));
150 expected_tags4[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7));
151
152 std::cout << std::endl << "qa_block_tags::t1" << std::endl;
153
154 // For annotator 3, we know it gets tags from ann0 and ann1, test this
155 for (size_t i = 0; i < tags3.size(); i++) {
156 std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i]
157 << std::endl;
158 BOOST_REQUIRE_EQUAL(tags3[i], expected_tags3[i]);
159 }
160
161 // For annotator 4, we know it gets tags from ann0 and ann2, test this
162 std::cout << std::endl;
163 for (size_t i = 0; i < tags4.size(); i++) {
164 std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i]
165 << std::endl;
166 BOOST_REQUIRE_EQUAL(tags4[i], expected_tags4[i]);
167 }
168 #endif
169 }
170
BOOST_AUTO_TEST_CASE(t2)171 BOOST_AUTO_TEST_CASE(t2)
172 {
173 int N = 40000;
174 gr::top_block_sptr tb = gr::make_top_block("top");
175 gr::block_sptr src(gr::blocks::null_source::make(sizeof(int)));
176 gr::block_sptr head(gr::blocks::head::make(sizeof(int), N));
177 gr::blocks::annotator_alltoall::sptr ann0(
178 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
179 gr::blocks::annotator_alltoall::sptr ann1(
180 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
181 gr::blocks::annotator_alltoall::sptr ann2(
182 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
183 gr::blocks::annotator_alltoall::sptr ann3(
184 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
185 gr::blocks::annotator_alltoall::sptr ann4(
186 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
187 gr::block_sptr snk0(gr::blocks::null_sink::make(sizeof(int)));
188 gr::block_sptr snk1(gr::blocks::null_sink::make(sizeof(int)));
189 gr::block_sptr snk2(gr::blocks::null_sink::make(sizeof(int)));
190
191 tb->connect(src, 0, head, 0);
192 tb->connect(head, 0, ann0, 0);
193
194 tb->connect(ann0, 0, ann1, 0);
195 tb->connect(ann0, 1, ann1, 1);
196 tb->connect(ann1, 0, ann2, 0);
197 tb->connect(ann1, 1, ann3, 0);
198 tb->connect(ann1, 2, ann4, 0);
199
200 tb->connect(ann2, 0, snk0, 0);
201 tb->connect(ann3, 0, snk1, 0);
202 tb->connect(ann4, 0, snk2, 0);
203
204 tb->run();
205
206 std::vector<gr::tag_t> tags0 = ann0->data();
207 std::vector<gr::tag_t> tags1 = ann1->data();
208 std::vector<gr::tag_t> tags2 = ann2->data();
209 std::vector<gr::tag_t> tags3 = ann4->data();
210 std::vector<gr::tag_t> tags4 = ann4->data();
211
212 // The first annotator does not receive any tags from the null sink upstream
213 BOOST_REQUIRE_EQUAL(tags0.size(), (size_t)0);
214 BOOST_REQUIRE_EQUAL(tags1.size(), (size_t)8);
215
216 // Make sure the rest all have 12 tags
217 BOOST_REQUIRE_EQUAL(tags2.size(), (size_t)12);
218 BOOST_REQUIRE_EQUAL(tags3.size(), (size_t)12);
219 BOOST_REQUIRE_EQUAL(tags4.size(), (size_t)12);
220
221
222 #if QA_TAGS_DEBUG
223 // Kludge together the tags that we know should result from the above graph
224 std::stringstream str0, str1;
225 str0 << ann0->name() << ann0->unique_id();
226 str1 << ann1->name() << ann1->unique_id();
227
228 gr::tag_t expected_tags2[12];
229 expected_tags2[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0));
230 expected_tags2[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0));
231 expected_tags2[2] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1));
232 expected_tags2[3] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3));
233 expected_tags2[4] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2));
234 expected_tags2[5] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3));
235 expected_tags2[6] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(6));
236 expected_tags2[7] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4));
237 expected_tags2[8] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5));
238 expected_tags2[9] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(9));
239 expected_tags2[10] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6));
240 expected_tags2[11] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7));
241
242 gr::tag_t expected_tags4[12];
243 expected_tags4[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2));
244 expected_tags4[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0));
245 expected_tags4[2] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1));
246 expected_tags4[3] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(5));
247 expected_tags4[4] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2));
248 expected_tags4[5] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3));
249 expected_tags4[6] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(8));
250 expected_tags4[7] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4));
251 expected_tags4[8] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5));
252 expected_tags4[9] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(11));
253 expected_tags4[10] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6));
254 expected_tags4[11] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7));
255
256 std::cout << std::endl << "qa_block_tags::t2" << std::endl;
257
258 // For annotator[2-4], we know it gets tags from ann0 and ann1
259 // but the tags from the different outputs of ann1 are different for each.
260 // Just testing ann2 and ann4; if they are correct it would be
261 // inconceivable for ann3 to have it wrong.
262 for (size_t i = 0; i < tags2.size(); i++) {
263 std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i]
264 << std::endl;
265 BOOST_REQUIRE_EQUAL(tags2[i], expected_tags2[i]);
266 }
267
268 std::cout << std::endl;
269 for (size_t i = 0; i < tags4.size(); i++) {
270 std::cout << "tags2[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i]
271 << std::endl;
272 BOOST_REQUIRE_EQUAL(tags4[i], expected_tags4[i]);
273 }
274 #endif
275 }
276
277
BOOST_AUTO_TEST_CASE(t3)278 BOOST_AUTO_TEST_CASE(t3)
279 {
280 int N = 40000;
281 gr::top_block_sptr tb = gr::make_top_block("top");
282 gr::block_sptr src(gr::blocks::null_source::make(sizeof(int)));
283 gr::block_sptr head(gr::blocks::head::make(sizeof(int), N));
284 gr::blocks::annotator_1to1::sptr ann0(
285 gr::blocks::annotator_1to1::make(10000, sizeof(int)));
286 gr::blocks::annotator_alltoall::sptr ann1(
287 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
288 gr::blocks::annotator_alltoall::sptr ann2(
289 gr::blocks::annotator_alltoall::make(10000, sizeof(int)));
290 gr::blocks::annotator_1to1::sptr ann3(
291 gr::blocks::annotator_1to1::make(10000, sizeof(int)));
292 gr::blocks::annotator_1to1::sptr ann4(
293 gr::blocks::annotator_1to1::make(10000, sizeof(int)));
294 gr::block_sptr snk0(gr::blocks::null_sink::make(sizeof(int)));
295 gr::block_sptr snk1(gr::blocks::null_sink::make(sizeof(int)));
296
297 tb->connect(src, 0, head, 0);
298 tb->connect(head, 0, ann0, 0);
299 tb->connect(head, 0, ann0, 1);
300
301 tb->connect(ann0, 0, ann1, 0);
302 tb->connect(ann0, 1, ann2, 0);
303 tb->connect(ann1, 0, ann3, 0);
304 tb->connect(ann2, 0, ann4, 0);
305
306 tb->connect(ann3, 0, snk0, 0);
307 tb->connect(ann4, 0, snk1, 0);
308
309 tb->run();
310
311
312 std::vector<gr::tag_t> tags0 = ann0->data();
313 std::vector<gr::tag_t> tags3 = ann3->data();
314 std::vector<gr::tag_t> tags4 = ann4->data();
315
316 // The first annotator does not receive any tags from the null sink upstream
317 BOOST_REQUIRE_EQUAL(tags0.size(), (size_t)0);
318 BOOST_REQUIRE_EQUAL(tags3.size(), (size_t)8);
319 BOOST_REQUIRE_EQUAL(tags4.size(), (size_t)8);
320
321 #if QA_TAGS_DEBUG
322 // Kludge together the tags that we know should result from the above graph
323 std::stringstream str0, str1, str2;
324 str0 << ann0->name() << ann0->unique_id();
325 str1 << ann1->name() << ann1->unique_id();
326 str2 << ann2->name() << ann2->unique_id();
327
328 gr::tag_t expected_tags3[8];
329 expected_tags3[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0));
330 expected_tags3[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0));
331 expected_tags3[2] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(1));
332 expected_tags3[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2));
333 expected_tags3[4] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2));
334 expected_tags3[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4));
335 expected_tags3[6] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3));
336 expected_tags3[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6));
337
338 gr::tag_t expected_tags4[8];
339 expected_tags4[0] = make_tag(0, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(0));
340 expected_tags4[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1));
341 expected_tags4[2] = make_tag(10000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(1));
342 expected_tags4[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3));
343 expected_tags4[4] = make_tag(20000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(2));
344 expected_tags4[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5));
345 expected_tags4[6] = make_tag(30000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(3));
346 expected_tags4[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7));
347
348 std::cout << std::endl << "qa_block_tags::t3" << std::endl;
349
350 // For annotator 3, we know it gets tags from ann0 and ann1, test this
351 for (size_t i = 0; i < tags3.size(); i++) {
352 std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i]
353 << std::endl;
354 BOOST_REQUIRE_EQUAL(tags3[i], expected_tags3[i]);
355 }
356
357 // For annotator 4, we know it gets tags from ann0 and ann2, test this
358 std::cout << std::endl;
359 for (size_t i = 0; i < tags4.size(); i++) {
360 std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i]
361 << std::endl;
362 BOOST_REQUIRE_EQUAL(tags4[i], expected_tags4[i]);
363 }
364 #endif
365 }
366
367
BOOST_AUTO_TEST_CASE(t4)368 BOOST_AUTO_TEST_CASE(t4)
369 {
370 int N = 40000;
371 gr::top_block_sptr tb = gr::make_top_block("top");
372 gr::block_sptr src(gr::blocks::null_source::make(sizeof(int)));
373 gr::block_sptr head(gr::blocks::head::make(sizeof(int), N));
374 gr::blocks::annotator_1to1::sptr ann0(
375 gr::blocks::annotator_1to1::make(10000, sizeof(int)));
376 gr::blocks::annotator_1to1::sptr ann1(
377 gr::blocks::annotator_1to1::make(10000, sizeof(int)));
378 gr::blocks::annotator_1to1::sptr ann2(
379 gr::blocks::annotator_1to1::make(10000, sizeof(int)));
380 gr::block_sptr snk0(gr::blocks::null_sink::make(sizeof(int)));
381 gr::block_sptr snk1(gr::blocks::null_sink::make(sizeof(int)));
382
383 // using 1-to-1 tag propagation without having equal number of
384 // ins and outs. Make sure this works; will just exit run early.
385 tb->connect(src, 0, head, 0);
386 tb->connect(head, 0, ann0, 0);
387 tb->connect(ann0, 0, ann1, 0);
388 tb->connect(ann0, 1, ann2, 0);
389 tb->connect(ann1, 0, snk0, 0);
390 tb->connect(ann2, 0, snk1, 0);
391
392 std::cerr << std::endl
393 << "NOTE: This is supposed to produce an error from block_executor"
394 << std::endl;
395 tb->run();
396 }
397
398
BOOST_AUTO_TEST_CASE(t5)399 BOOST_AUTO_TEST_CASE(t5)
400 {
401 int N = 40000;
402 gr::top_block_sptr tb = gr::make_top_block("top");
403 gr::block_sptr src(gr::blocks::null_source::make(sizeof(float)));
404 gr::block_sptr head(gr::blocks::head::make(sizeof(float), N));
405 gr::blocks::annotator_alltoall::sptr ann0(
406 gr::blocks::annotator_alltoall::make(10000, sizeof(float)));
407 gr::blocks::annotator_alltoall::sptr ann1(
408 gr::blocks::annotator_alltoall::make(10000, sizeof(float)));
409 gr::blocks::annotator_alltoall::sptr ann2(
410 gr::blocks::annotator_alltoall::make(1000, sizeof(float)));
411 gr::block_sptr snk0(gr::blocks::null_sink::make(sizeof(float)));
412
413 // Rate change blocks
414 gr::blocks::keep_one_in_n::sptr dec10(
415 gr::blocks::keep_one_in_n::make(sizeof(float), 10));
416
417 tb->connect(src, 0, head, 0);
418 tb->connect(head, 0, ann0, 0);
419 tb->connect(ann0, 0, ann1, 0);
420 tb->connect(ann1, 0, dec10, 0);
421 tb->connect(dec10, 0, ann2, 0);
422 tb->connect(ann2, 0, snk0, 0);
423
424 tb->run();
425
426 std::vector<gr::tag_t> tags0 = ann0->data();
427 std::vector<gr::tag_t> tags1 = ann1->data();
428 std::vector<gr::tag_t> tags2 = ann2->data();
429
430 // The first annotator does not receive any tags from the null sink upstream
431 BOOST_REQUIRE_EQUAL(tags0.size(), (size_t)0);
432 BOOST_REQUIRE_EQUAL(tags1.size(), (size_t)4);
433 BOOST_REQUIRE_EQUAL(tags2.size(), (size_t)8);
434
435
436 #if QA_TAGS_DEBUG
437 // Kludge together the tags that we know should result from the above graph
438 std::stringstream str0, str1, str2;
439 str0 << ann0->name() << ann0->unique_id();
440 str1 << ann1->name() << ann1->unique_id();
441 str2 << ann2->name() << ann2->unique_id();
442
443 gr::tag_t expected_tags1[5];
444 expected_tags1[0] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0));
445 expected_tags1[1] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1));
446 expected_tags1[2] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2));
447 expected_tags1[3] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3));
448
449 gr::tag_t expected_tags2[10];
450 expected_tags2[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0));
451 expected_tags2[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0));
452 expected_tags2[2] = make_tag(1000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(1));
453 expected_tags2[3] = make_tag(1000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1));
454 expected_tags2[4] = make_tag(2000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2));
455 expected_tags2[5] = make_tag(2000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2));
456 expected_tags2[6] = make_tag(3000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3));
457 expected_tags2[7] = make_tag(3000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3));
458 expected_tags2[8] = make_tag(4000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(4));
459 expected_tags2[9] = make_tag(4000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4));
460
461 std::cout << std::endl << "qa_block_tags::t5" << std::endl;
462
463 // annotator 1 gets tags from annotator 0
464 std::cout << "tags1.size(): " << tags1.size() << std::endl;
465 for (size_t i = 0; i < tags1.size(); i++) {
466 std::cout << "tags1[" << i << "] = " << tags1[i] << "\t\t" << expected_tags1[i]
467 << std::endl;
468 BOOST_REQUIRE_EQUAL(tags1[i], expected_tags1[i]);
469 }
470
471 // annotator 2 gets tags from annotators 0 and 1
472 std::cout << std::endl;
473 std::cout << "tags2.size(): " << tags2.size() << std::endl;
474 for (size_t i = 0; i < tags2.size(); i++) {
475 std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i]
476 << std::endl;
477 BOOST_REQUIRE_EQUAL(tags2[i], expected_tags2[i]);
478 }
479 #endif
480 }
481