Imported Upstream version 3.0
[debian/gnuradio] / gnuradio-core / src / lib / runtime / qa_gr_buffer.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004 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 2, 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 #include <qa_gr_buffer.h>
27 #include <gr_buffer.h>
28 #include <cppunit/TestAssert.h>
29 #include <stdlib.h>
30 #include <gr_random.h>
31
32 static void
33 leak_check (void f ())
34 {
35   long  buffer_count = gr_buffer_ncurrently_allocated ();
36   long  buffer_reader_count = gr_buffer_reader_ncurrently_allocated ();
37
38   f ();
39
40   CPPUNIT_ASSERT_EQUAL (buffer_reader_count, gr_buffer_reader_ncurrently_allocated ());
41   CPPUNIT_ASSERT_EQUAL (buffer_count, gr_buffer_ncurrently_allocated ());
42 }
43
44
45 // ----------------------------------------------------------------------------
46 // test single writer, no readers...
47 //
48
49 static void
50 t0_body ()
51 {
52   int   nitems = 4000 / sizeof (int);
53   int   counter = 0;
54
55   gr_buffer_sptr buf (gr_make_buffer (nitems, sizeof (int)));
56
57   int last_sa;
58   int sa;
59
60   sa = buf->space_available ();
61   CPPUNIT_ASSERT (sa > 0);
62   last_sa = sa;
63
64   for (int i = 0; i < 5; i++){
65     sa = buf->space_available ();
66     CPPUNIT_ASSERT_EQUAL (last_sa, sa);
67     last_sa = sa;
68     
69     int *p = (int *) buf->write_pointer ();
70     CPPUNIT_ASSERT (p != 0);
71
72     for (int j = 0; j < sa; j++)
73       *p++ = counter++;
74
75     buf->update_write_pointer (sa);
76   }
77 }
78
79 // ----------------------------------------------------------------------------
80 // test single writer, single reader
81 //
82
83 static void 
84 t1_body ()
85  {
86   int   nitems = 4000 / sizeof (int);
87   int   write_counter = 0;
88   int   read_counter = 0;
89
90   gr_buffer_sptr buf (gr_make_buffer (nitems, sizeof (int)));
91   gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 0));
92   
93
94   int sa;
95
96   // write 1/3 of buffer
97
98   sa = buf->space_available ();
99   CPPUNIT_ASSERT (sa > 0);
100
101   int *p = (int *) buf->write_pointer ();
102   CPPUNIT_ASSERT (p != 0);
103
104   for (int j = 0; j < sa/3; j++){
105     *p++ = write_counter++;
106   }
107   buf->update_write_pointer (sa/3);
108
109   
110   // write the next 1/3 (1/2 of what's left)
111
112   sa = buf->space_available ();
113   CPPUNIT_ASSERT (sa > 0);
114
115   p = (int *) buf->write_pointer ();
116   CPPUNIT_ASSERT (p != 0);
117
118   for (int j = 0; j < sa/2; j++){
119     *p++ = write_counter++;
120   }
121   buf->update_write_pointer (sa/2);
122
123
124   // check that we can read it OK
125
126   int ia = r1->items_available ();
127   CPPUNIT_ASSERT_EQUAL (write_counter, ia);
128   
129   int *rp = (int *) r1->read_pointer ();
130   CPPUNIT_ASSERT (rp != 0);
131
132   for (int i = 0; i < ia/2; i++){
133     CPPUNIT_ASSERT_EQUAL (read_counter, *rp);
134     read_counter++;
135     rp++;
136   }
137   r1->update_read_pointer (ia/2);
138
139   // read the rest
140
141   ia = r1->items_available ();
142   rp = (int *) r1->read_pointer ();
143   CPPUNIT_ASSERT (rp != 0);
144
145   for (int i = 0; i < ia; i++){
146     CPPUNIT_ASSERT_EQUAL (read_counter, *rp);
147     read_counter++;
148     rp++;
149   }
150   r1->update_read_pointer (ia);
151 }
152
153 // ----------------------------------------------------------------------------
154 // single writer, single reader: check wrap-around
155 //
156
157 static void
158 t2_body ()
159 {
160   // 64K is the largest granularity we've seen so far (MS windows file mapping).
161   // This allows a bit of "white box testing"
162   
163   int   nitems = (64 * (1L << 10)) / sizeof (int);      // 64K worth of ints
164
165   gr_buffer_sptr buf (gr_make_buffer (nitems, sizeof (int)));
166   gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 0));
167
168   int   read_counter = 0;
169   int   write_counter = 0;
170   int   n;
171   int   *wp = 0;
172   int   *rp = 0;
173   
174   // Write 3/4 of buffer
175
176   n = (int) (buf->space_available () * 0.75);
177   wp = (int *) buf->write_pointer ();
178
179   for (int i = 0; i < n; i++)
180     *wp++ = write_counter++;
181   buf->update_write_pointer (n);
182
183   // Now read it all
184
185   int m = r1->items_available ();
186   CPPUNIT_ASSERT_EQUAL (n, m);
187   rp = (int *) r1->read_pointer ();
188
189   for (int i = 0; i < m; i++){
190     CPPUNIT_ASSERT_EQUAL (read_counter, *rp);
191     read_counter++;
192     rp++;
193   }
194   r1->update_read_pointer (m);
195
196   // Now write as much as we can.
197   // This will wrap around the buffer
198
199   n = buf->space_available ();
200   CPPUNIT_ASSERT_EQUAL (nitems - 1, n);         // white box test
201   wp = (int *) buf->write_pointer ();
202
203   for (int i = 0; i < n; i++)
204     *wp++ = write_counter++;
205   buf->update_write_pointer (n);
206   
207   // now read it all
208
209   m = r1->items_available ();
210   CPPUNIT_ASSERT_EQUAL (n, m);
211   rp = (int *) r1->read_pointer ();
212
213   for (int i = 0; i < m; i++){
214     CPPUNIT_ASSERT_EQUAL (read_counter, *rp);
215     read_counter++;
216     rp++;
217   }
218   r1->update_read_pointer (m);
219
220 }
221
222 // ----------------------------------------------------------------------------
223 // single writer, N readers, randomized order and lengths
224 // ----------------------------------------------------------------------------
225
226 static void
227 t3_body ()
228 {
229   int   nitems = (64 * (1L << 10)) / sizeof (int);
230
231   static const int N = 5;
232   gr_buffer_sptr buf (gr_make_buffer (nitems, sizeof (int)));
233   gr_buffer_reader_sptr         reader[N];
234   int                   read_counter[N];
235   int                   write_counter = 0;
236   gr_random             random;
237
238   for (int i = 0; i < N; i++){
239     read_counter[i] = 0;
240     reader[i] = gr_buffer_add_reader (buf, 0);
241   }
242
243   for (int lc = 0; lc < 1000; lc++){
244
245     // write some
246
247     int n = (int) (buf->space_available () * random.ran1 ());
248     int *wp = (int *) buf->write_pointer ();
249
250     for (int i = 0; i < n; i++)
251       *wp++ = write_counter++;
252
253     buf->update_write_pointer (n);
254
255     // pick a random reader and read some
256
257     int r = (int) (N * random.ran1 ());
258     CPPUNIT_ASSERT (0 <= r && r < N);
259
260     int m = reader[r]->items_available ();
261     int *rp = (int *) reader[r]->read_pointer ();
262
263     for (int i = 0; i < m; i++){
264       CPPUNIT_ASSERT_EQUAL (read_counter[r], *rp);
265       read_counter[r]++;
266       rp++;
267     }
268     reader[r]->update_read_pointer (m);
269   }
270 }
271
272
273 // ----------------------------------------------------------------------------
274
275 void
276 qa_gr_buffer::t0 ()
277 {
278   leak_check (t0_body);
279 }
280
281 void
282 qa_gr_buffer::t1 ()
283 {
284   leak_check (t1_body);
285 }
286
287 void
288 qa_gr_buffer::t2 ()
289 {
290   leak_check (t2_body);
291 }
292
293 void
294 qa_gr_buffer::t3 ()
295 {
296   leak_check (t3_body);
297 }
298
299 void
300 qa_gr_buffer::t4 ()
301 {
302 }
303
304 void
305 qa_gr_buffer::t5 ()
306 {
307 }