/* -*- c++ -*- */ /* * Copyright 2004 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include static void leak_check (void f ()) { long buffer_count = gr_buffer_ncurrently_allocated (); long buffer_reader_count = gr_buffer_reader_ncurrently_allocated (); f (); CPPUNIT_ASSERT_EQUAL (buffer_reader_count, gr_buffer_reader_ncurrently_allocated ()); CPPUNIT_ASSERT_EQUAL (buffer_count, gr_buffer_ncurrently_allocated ()); } // ---------------------------------------------------------------------------- // test single writer, no readers... // static void t0_body () { int nitems = 4000 / sizeof (int); int counter = 0; gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr())); int last_sa; int sa; sa = buf->space_available (); CPPUNIT_ASSERT (sa > 0); last_sa = sa; for (int i = 0; i < 5; i++){ sa = buf->space_available (); CPPUNIT_ASSERT_EQUAL (last_sa, sa); last_sa = sa; int *p = (int *) buf->write_pointer (); CPPUNIT_ASSERT (p != 0); for (int j = 0; j < sa; j++) *p++ = counter++; buf->update_write_pointer (sa); } } // ---------------------------------------------------------------------------- // test single writer, single reader // static void t1_body () { int nitems = 4000 / sizeof (int); int write_counter = 0; int read_counter = 0; gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr())); gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 0, gr_block_sptr())); int sa; // write 1/3 of buffer sa = buf->space_available (); CPPUNIT_ASSERT (sa > 0); int *p = (int *) buf->write_pointer (); CPPUNIT_ASSERT (p != 0); for (int j = 0; j < sa/3; j++){ *p++ = write_counter++; } buf->update_write_pointer (sa/3); // write the next 1/3 (1/2 of what's left) sa = buf->space_available (); CPPUNIT_ASSERT (sa > 0); p = (int *) buf->write_pointer (); CPPUNIT_ASSERT (p != 0); for (int j = 0; j < sa/2; j++){ *p++ = write_counter++; } buf->update_write_pointer (sa/2); // check that we can read it OK int ia = r1->items_available (); CPPUNIT_ASSERT_EQUAL (write_counter, ia); int *rp = (int *) r1->read_pointer (); CPPUNIT_ASSERT (rp != 0); for (int i = 0; i < ia/2; i++){ CPPUNIT_ASSERT_EQUAL (read_counter, *rp); read_counter++; rp++; } r1->update_read_pointer (ia/2); // read the rest ia = r1->items_available (); rp = (int *) r1->read_pointer (); CPPUNIT_ASSERT (rp != 0); for (int i = 0; i < ia; i++){ CPPUNIT_ASSERT_EQUAL (read_counter, *rp); read_counter++; rp++; } r1->update_read_pointer (ia); } // ---------------------------------------------------------------------------- // single writer, single reader: check wrap-around // static void t2_body () { // 64K is the largest granularity we've seen so far (MS windows file mapping). // This allows a bit of "white box testing" int nitems = (64 * (1L << 10)) / sizeof (int); // 64K worth of ints gr_buffer_sptr buf(gr_make_buffer (nitems, sizeof (int), gr_block_sptr())); gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 0, gr_block_sptr())); int read_counter = 0; int write_counter = 0; int n; int *wp = 0; int *rp = 0; // Write 3/4 of buffer n = (int) (buf->space_available () * 0.75); wp = (int *) buf->write_pointer (); for (int i = 0; i < n; i++) *wp++ = write_counter++; buf->update_write_pointer (n); // Now read it all int m = r1->items_available (); CPPUNIT_ASSERT_EQUAL (n, m); rp = (int *) r1->read_pointer (); for (int i = 0; i < m; i++){ CPPUNIT_ASSERT_EQUAL (read_counter, *rp); read_counter++; rp++; } r1->update_read_pointer (m); // Now write as much as we can. // This will wrap around the buffer n = buf->space_available (); CPPUNIT_ASSERT_EQUAL (nitems - 1, n); // white box test wp = (int *) buf->write_pointer (); for (int i = 0; i < n; i++) *wp++ = write_counter++; buf->update_write_pointer (n); // now read it all m = r1->items_available (); CPPUNIT_ASSERT_EQUAL (n, m); rp = (int *) r1->read_pointer (); for (int i = 0; i < m; i++){ CPPUNIT_ASSERT_EQUAL (read_counter, *rp); read_counter++; rp++; } r1->update_read_pointer (m); } // ---------------------------------------------------------------------------- // single writer, N readers, randomized order and lengths // ---------------------------------------------------------------------------- static void t3_body () { int nitems = (64 * (1L << 10)) / sizeof (int); static const int N = 5; gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr())); gr_buffer_reader_sptr reader[N]; int read_counter[N]; int write_counter = 0; gr_random random; for (int i = 0; i < N; i++){ read_counter[i] = 0; reader[i] = gr_buffer_add_reader (buf, 0, gr_block_sptr()); } for (int lc = 0; lc < 1000; lc++){ // write some int n = (int) (buf->space_available () * random.ran1 ()); int *wp = (int *) buf->write_pointer (); for (int i = 0; i < n; i++) *wp++ = write_counter++; buf->update_write_pointer (n); // pick a random reader and read some int r = (int) (N * random.ran1 ()); CPPUNIT_ASSERT (0 <= r && r < N); int m = reader[r]->items_available (); int *rp = (int *) reader[r]->read_pointer (); for (int i = 0; i < m; i++){ CPPUNIT_ASSERT_EQUAL (read_counter[r], *rp); read_counter[r]++; rp++; } reader[r]->update_read_pointer (m); } } // ---------------------------------------------------------------------------- void qa_gr_buffer::t0 () { leak_check (t0_body); } void qa_gr_buffer::t1 () { leak_check (t1_body); } void qa_gr_buffer::t2 () { leak_check (t2_body); } void qa_gr_buffer::t3 () { leak_check (t3_body); } void qa_gr_buffer::t4 () { } void qa_gr_buffer::t5 () { }