You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by sb...@apache.org on 2010/04/08 18:48:20 UTC

svn commit: r931999 [2/2] - in /hadoop/avro/trunk: ./ lang/c++/ lang/c++/api/ lang/c++/api/buffer/ lang/c++/api/buffer/detail/ lang/c++/impl/ lang/c++/m4/ lang/c++/test/

Added: hadoop/avro/trunk/lang/c++/m4/m4_ax_boost_thread.m4
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c%2B%2B/m4/m4_ax_boost_thread.m4?rev=931999&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c++/m4/m4_ax_boost_thread.m4 (added)
+++ hadoop/avro/trunk/lang/c++/m4/m4_ax_boost_thread.m4 Thu Apr  8 16:48:19 2010
@@ -0,0 +1,146 @@
+# ===========================================================================
+#      http://www.gnu.org/software/autoconf-archive/ax_boost_thread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_BOOST_THREAD
+#
+# DESCRIPTION
+#
+#   Test for Thread library from the Boost C++ libraries. The macro requires
+#   a preceding call to AX_BOOST_BASE. Further documentation is available at
+#   <http://randspringer.de/boost/index.html>.
+#
+#   This macro calls:
+#
+#     AC_SUBST(BOOST_THREAD_LIB)
+#
+#   And sets:
+#
+#     HAVE_BOOST_THREAD
+#
+# LICENSE
+#
+#   Copyright (c) 2009 Thomas Porschberg <th...@randspringer.de>
+#   Copyright (c) 2009 Michael Tindal
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 15
+
+AC_DEFUN([AX_BOOST_THREAD],
+[
+	AC_ARG_WITH([boost-thread],
+	AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@],
+                   [use the Thread library from boost - it is possible to specify a certain library for the linker
+                        e.g. --with-boost-thread=boost_thread-gcc-mt ]),
+        [
+        if test "$withval" = "no"; then
+			want_boost="no"
+        elif test "$withval" = "yes"; then
+            want_boost="yes"
+            ax_boost_user_thread_lib=""
+        else
+		    want_boost="yes"
+        	ax_boost_user_thread_lib="$withval"
+		fi
+        ],
+        [want_boost="yes"]
+	)
+
+	if test "x$want_boost" = "xyes"; then
+        AC_REQUIRE([AC_PROG_CC])
+        AC_REQUIRE([AC_CANONICAL_BUILD])
+		CPPFLAGS_SAVED="$CPPFLAGS"
+		CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+		export CPPFLAGS
+
+		LDFLAGS_SAVED="$LDFLAGS"
+		LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+		export LDFLAGS
+
+        AC_CACHE_CHECK(whether the Boost::Thread library is available,
+					   ax_cv_boost_thread,
+        [AC_LANG_PUSH([C++])
+			 CXXFLAGS_SAVE=$CXXFLAGS
+
+			 if test "x$build_os" = "xsolaris" ; then
+  				 CXXFLAGS="-pthreads $CXXFLAGS"
+			 elif test "x$build_os" = "xming32" ; then
+				 CXXFLAGS="-mthreads $CXXFLAGS"
+			 else
+				CXXFLAGS="-pthread $CXXFLAGS"
+			 fi
+			 AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[@%:@include <boost/thread/thread.hpp>]],
+                                   [[boost::thread_group thrds;
+                                   return 0;]]),
+                   ax_cv_boost_thread=yes, ax_cv_boost_thread=no)
+			 CXXFLAGS=$CXXFLAGS_SAVE
+             AC_LANG_POP([C++])
+		])
+		if test "x$ax_cv_boost_thread" = "xyes"; then
+           if test "x$build_os" = "xsolaris" ; then
+			  BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS"
+		   elif test "x$build_os" = "xming32" ; then
+			  BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS"
+		   else
+			  BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS"
+		   fi
+
+			AC_SUBST(BOOST_CPPFLAGS)
+
+			AC_DEFINE(HAVE_BOOST_THREAD,,[define if the Boost::Thread library is available])
+            BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+
+			LDFLAGS_SAVE=$LDFLAGS
+                        case "x$build_os" in
+                          *bsd* )
+                               LDFLAGS="-pthread $LDFLAGS"
+                          break;
+                          ;;
+                        esac
+            if test "x$ax_boost_user_thread_lib" = "x"; then
+                for libextension in `ls $BOOSTLIBDIR/libboost_thread*.so* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_thread.*\)\.so.*$;\1;'` `ls $BOOSTLIBDIR/libboost_thread*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_thread.*\)\.a*$;\1;'`; do
+                     ax_lib=${libextension}
+				    AC_CHECK_LIB($ax_lib, exit,
+                                 [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
+                                 [link_thread="no"])
+  				done
+                if test "x$link_thread" != "xyes"; then
+                for libextension in `ls $BOOSTLIBDIR/boost_thread*.dll* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_thread.*\)\.dll.*$;\1;'` `ls $BOOSTLIBDIR/boost_thread*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_thread.*\)\.a*$;\1;'` ; do
+                     ax_lib=${libextension}
+				    AC_CHECK_LIB($ax_lib, exit,
+                                 [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
+                                 [link_thread="no"])
+  				done
+                fi
+
+            else
+               for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do
+				      AC_CHECK_LIB($ax_lib, exit,
+                                   [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
+                                   [link_thread="no"])
+                  done
+
+            fi
+			if test "x$link_thread" = "xno"; then
+				AC_MSG_ERROR(Could not link against $ax_lib !)
+                        else
+                           case "x$build_os" in
+                              *bsd* )
+			        BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS"
+                              break;
+                              ;;
+                           esac
+
+			fi
+		fi
+
+		CPPFLAGS="$CPPFLAGS_SAVED"
+    	LDFLAGS="$LDFLAGS_SAVED"
+	fi
+])

Propchange: hadoop/avro/trunk/lang/c++/m4/m4_ax_boost_thread.m4
------------------------------------------------------------------------------
    svn:eol-style = native

Added: hadoop/avro/trunk/lang/c++/test/buffertest.cc
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c%2B%2B/test/buffertest.cc?rev=931999&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c++/test/buffertest.cc (added)
+++ hadoop/avro/trunk/lang/c++/test/buffertest.cc Thu Apr  8 16:48:19 2010
@@ -0,0 +1,1124 @@
+#include <boost/test/included/unit_test_framework.hpp>
+
+#include <boost/thread.hpp>
+#include <boost/bind.hpp>
+#include <fstream>
+#include <iostream>
+#include <boost/asio.hpp>
+
+#define BUFFER_UNITTEST
+#include "buffer/BufferStream.hh"
+#include "buffer/BufferReader.hh"
+#include "buffer/BufferPrint.hh"
+
+using namespace avro;
+using std::cout;
+using std::endl;
+using detail::kDefaultBlockSize;
+using detail::kMinBlockSize;
+using detail::kMaxBlockSize;
+
+std::string makeString(size_t len)
+{
+    std::string newstring;
+    newstring.reserve(len);
+
+    for(size_t i=0; i < len; ++i) {
+        char newchar = '0' + i%16;
+        if(newchar > '9') {
+            newchar += 7;
+        }
+        newstring.push_back(newchar);
+    }
+
+    return newstring;
+}
+
+void printBuffer(const InputBuffer &buf) 
+{
+    avro::istream is(buf);
+    cout << is.rdbuf() << endl;
+}
+
+void TestReserve()
+{
+    BOOST_MESSAGE( "TestReserve");
+    {
+        OutputBuffer ob;
+        BOOST_CHECK_EQUAL(ob.size(), 0U);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), 0U);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 0);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 0);
+    }
+
+    {
+        size_t reserveSize = kMinBlockSize/2;
+
+        OutputBuffer ob (reserveSize);
+        BOOST_CHECK_EQUAL(ob.size(), 0U);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kMinBlockSize);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 0);
+
+        // reserve should add a single block
+        reserveSize += 8192;
+
+        ob.reserve(reserveSize);
+        BOOST_CHECK_EQUAL(ob.size(), 0U);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), reserveSize);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 2);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 0);
+
+        // reserve should add two blocks, one of the maximum size and
+        // one of the minimum size
+        reserveSize += (kMaxBlockSize + kMinBlockSize/2);
+
+        ob.reserve(reserveSize);
+        BOOST_CHECK_EQUAL(ob.size(), 0U);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), reserveSize + kMinBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 4);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 0);
+    }
+}
+
+void addDataToBuffer(OutputBuffer &buf, size_t size)
+{
+    std::string data = makeString(size);
+    buf.writeTo(data.c_str(), data.size());
+}
+
+void TestGrow()
+{
+    BOOST_MESSAGE( "TestGrow");
+    { 
+        OutputBuffer ob;
+
+        // add exactly one block
+        addDataToBuffer(ob, kDefaultBlockSize);
+
+        BOOST_CHECK_EQUAL(ob.size(), kDefaultBlockSize);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), 0U);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 0);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 1);
+
+        // add another block, half full
+        addDataToBuffer(ob, kDefaultBlockSize/2);
+
+        BOOST_CHECK_EQUAL(ob.size(), kDefaultBlockSize + kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 2);
+
+        // reserve more capacity
+        size_t reserveSize = ob.freeSpace() + 8192;
+        ob.reserve(reserveSize);
+
+        BOOST_CHECK_EQUAL(ob.size(), kDefaultBlockSize + kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), reserveSize);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 2);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 2);
+
+        // fill beyond capacity
+        addDataToBuffer(ob, reserveSize + 1);
+        BOOST_CHECK_EQUAL(ob.size(), kDefaultBlockSize + kDefaultBlockSize/2 + reserveSize +1);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize - 1);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 4);
+    }
+}
+
+void TestDiscard()
+{
+    BOOST_MESSAGE( "TestDiscard");
+    {
+        OutputBuffer ob;
+        size_t dataSize = kDefaultBlockSize*2 + kDefaultBlockSize/2;
+        addDataToBuffer(ob, dataSize);
+
+        BOOST_CHECK_EQUAL(ob.size(), dataSize);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 3);
+
+        ob.discardData();
+
+        BOOST_CHECK_EQUAL(ob.size(), 0U);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 0);
+    }
+
+    {
+        // discard no bytes
+        OutputBuffer ob;
+        size_t dataSize = kDefaultBlockSize*2 + kDefaultBlockSize/2;
+        addDataToBuffer(ob, dataSize);
+
+        BOOST_CHECK_EQUAL(ob.size(), dataSize);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 3);
+
+        ob.discardData(0);
+
+        BOOST_CHECK_EQUAL(ob.size(), dataSize);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 3);
+    }
+
+    { 
+        // discard exactly one block
+        OutputBuffer ob;
+        size_t dataSize = kDefaultBlockSize*2 + kDefaultBlockSize/2;
+        addDataToBuffer(ob, dataSize);
+
+        BOOST_CHECK_EQUAL(ob.size(), dataSize);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 3);
+
+        ob.discardData(kDefaultBlockSize);
+
+        BOOST_CHECK_EQUAL(ob.size(), dataSize - kDefaultBlockSize);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 2);
+    }
+
+    {
+        OutputBuffer ob;
+        size_t dataSize = kDefaultBlockSize*2 + kDefaultBlockSize/2;
+        addDataToBuffer(ob, dataSize);
+
+        BOOST_CHECK_EQUAL(ob.size(), dataSize);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 3);
+
+        size_t remainder = dataSize % 100;
+
+        // discard data 100 bytes at a time
+        size_t discarded = 0;
+        while(ob.size() > 100) {
+            ob.discardData(100);
+            dataSize -= 100;
+            discarded += 100;
+
+            BOOST_CHECK_EQUAL(ob.size(), dataSize);
+            BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+            BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+
+            int chunks = 3 - (discarded / kDefaultBlockSize);
+            BOOST_CHECK_EQUAL(ob.numDataChunks(), chunks);
+        }
+
+        BOOST_CHECK_EQUAL(ob.size(), remainder);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 1);
+
+        try {
+            ob.discardData(ob.size()+1);
+        }
+        catch (std::exception &e) {
+            std::cout << "Intentionally triggered exception: " << e.what() << std::endl; 
+        }
+        ob.discardData(ob.size());
+
+        BOOST_CHECK_EQUAL(ob.size(), 0U);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 0);
+    }
+}
+
+void TestConvertToInput()
+{
+    BOOST_MESSAGE( "TestConvertToInput");
+    {
+        OutputBuffer ob;
+        size_t dataSize = kDefaultBlockSize*2 + kDefaultBlockSize/2;
+        addDataToBuffer(ob, dataSize);
+
+        InputBuffer ib(ob);
+
+        BOOST_CHECK_EQUAL(ib.size(), dataSize);
+        BOOST_CHECK_EQUAL(ib.numChunks(), 3);
+
+        BOOST_CHECK_EQUAL(ob.size(), dataSize);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 3);
+    }
+}
+
+void TestExtractToInput()
+{
+    BOOST_MESSAGE( "TestExtractToInput");
+    {
+        OutputBuffer ob;
+        size_t dataSize = kDefaultBlockSize*2 + kDefaultBlockSize/2;
+        addDataToBuffer(ob, dataSize);
+
+        InputBuffer ib = ob.extractData();
+
+        BOOST_CHECK_EQUAL(ib.size(), dataSize);
+        BOOST_CHECK_EQUAL(ib.numChunks(), 3);
+
+        BOOST_CHECK_EQUAL(ob.size(), 0U);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 0);
+    }
+
+    {
+        // extract no bytes
+        OutputBuffer ob;
+        size_t dataSize = kDefaultBlockSize*2 + kDefaultBlockSize/2;
+        addDataToBuffer(ob, dataSize);
+
+        InputBuffer ib = ob.extractData(0);
+
+        BOOST_CHECK_EQUAL(ib.size(), 0U);
+        BOOST_CHECK_EQUAL(ib.numChunks(), 0);
+
+        BOOST_CHECK_EQUAL(ob.size(), dataSize);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 3);
+    }
+    
+    {
+        // extract exactly one block
+        OutputBuffer ob;
+        size_t dataSize = kDefaultBlockSize*2 + kDefaultBlockSize/2;
+        addDataToBuffer(ob, dataSize);
+
+        InputBuffer ib = ob.extractData(kDefaultBlockSize);
+
+        BOOST_CHECK_EQUAL(ib.size(), kDefaultBlockSize);
+        BOOST_CHECK_EQUAL(ib.numChunks(), 1);
+
+        BOOST_CHECK_EQUAL(ob.size(), dataSize - kDefaultBlockSize);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 2);
+    }
+
+    {
+        OutputBuffer ob;
+        size_t dataSize = kDefaultBlockSize*2 + kDefaultBlockSize/2;
+        addDataToBuffer(ob, dataSize);
+
+        size_t remainder = dataSize % 100;
+
+        // extract data 100 bytes at a time
+        size_t extracted = 0;
+        while(ob.size() > 100) {
+            ob.extractData(100);
+            dataSize -= 100;
+            extracted += 100;
+
+            BOOST_CHECK_EQUAL(ob.size(), dataSize);
+            BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+            BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+
+            int chunks = 3 - (extracted / kDefaultBlockSize);
+            BOOST_CHECK_EQUAL(ob.numDataChunks(), chunks);
+        }
+
+        BOOST_CHECK_EQUAL(ob.size(), remainder);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 1);
+
+        try {
+            ob.extractData(ob.size()+1);
+        }
+        catch (std::exception &e) {
+            std::cout << "Intentionally triggered exception: " << e.what() << std::endl; 
+        }
+
+        InputBuffer ib = ob.extractData(remainder);
+
+        BOOST_CHECK_EQUAL(ib.size(), remainder);
+        BOOST_CHECK_EQUAL(ib.numChunks(), 1);
+
+        BOOST_CHECK_EQUAL(ob.size(), 0U);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kDefaultBlockSize/2);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 0);
+    }
+}
+
+void TestAppend()
+{
+    BOOST_MESSAGE( "TestAppend");
+    {
+        OutputBuffer ob;
+        size_t dataSize = kDefaultBlockSize + kDefaultBlockSize/2;
+        addDataToBuffer(ob, dataSize);
+
+        OutputBuffer a;
+        a.append(ob);
+
+        BOOST_CHECK_EQUAL(a.size(), dataSize);
+        BOOST_CHECK_EQUAL(a.freeSpace(), 0U);
+        BOOST_CHECK_EQUAL(a.numChunks(), 0);
+        BOOST_CHECK_EQUAL(a.numDataChunks(), 2);
+
+        // reserve on a, then append from an input buffer
+        a.reserve(7000);
+
+        InputBuffer ib(ob);
+        a.append(ib);
+
+        BOOST_CHECK_EQUAL(a.size(), dataSize*2);
+        BOOST_CHECK_EQUAL(a.freeSpace(), 7000U);
+        BOOST_CHECK_EQUAL(a.numChunks(), 1);
+        BOOST_CHECK_EQUAL(a.numDataChunks(), 4);
+    }
+}
+
+void TestBufferStream()
+{
+    BOOST_MESSAGE( "TestBufferStream");
+
+    {
+        // write enough bytes to a buffer, to create at least 3 blocks
+        std::string junk = makeString(kDefaultBlockSize);
+        ostream os;
+        int i = 0;
+        for(; i < 3; ++i) {
+            os << junk;
+        }
+
+        const OutputBuffer &buf = os.getBuffer();
+        cout << "Buffer has " << buf.size() << " bytes\n";
+        BOOST_CHECK_EQUAL(buf.size(), junk.size() * i);
+    }
+}
+
+template<typename T>
+void TestEof()
+{
+    // create a message full of eof chars
+    std::vector<char> eofs(sizeof(T) * 3 / 2, -1);
+
+    OutputBuffer buf1;
+    buf1.writeTo(&eofs[0], eofs.size());
+
+    OutputBuffer buf2;
+    buf2.writeTo(&eofs[0], eofs.size());
+
+    // append the buffers, so the first 
+    // character on a buffer boundary is eof
+    buf1.append(buf2);
+
+    avro::istream is(buf1);
+
+    for(int i = 0; i < 3; ++i) {
+        T d;
+        char *addr = reinterpret_cast<char *>(&d);
+        is.read(addr, sizeof(T));
+        BOOST_CHECK_EQUAL(is.gcount(), static_cast<std::streamsize>(sizeof(T)));
+        BOOST_CHECK_EQUAL(is.eof(), false);
+    }
+
+    char c;
+    is.read(&c, sizeof(c));
+    BOOST_CHECK_EQUAL(is.gcount(), 0);
+    BOOST_CHECK_EQUAL(is.eof(), true);
+}
+
+void TestBufferStreamEof()
+{
+    BOOST_MESSAGE( "TestBufferStreamEof");
+
+    TestEof<int32_t>();
+
+    TestEof<int64_t>();
+
+    TestEof<float>();
+
+    TestEof<double>();
+}
+
+void TestSeekAndTell()
+{
+    BOOST_MESSAGE( "TestSeekAndTell");
+
+    {
+        std::string junk = makeString(kDefaultBlockSize/2);
+
+        ostream os;
+
+        // write enough bytes to a buffer, to create at least 3 blocks
+        int i = 0;
+        for(; i < 5; ++i) {
+            os << junk;
+        }
+
+        const OutputBuffer &buf = os.getBuffer();
+        cout << "Buffer has " << buf.size() << " bytes\n";
+
+        istream is(os.getBuffer());
+        BOOST_CHECK_EQUAL(is.getBuffer().size(), junk.size() * i);
+        is.seekg(2000);
+        BOOST_CHECK_EQUAL(is.tellg(), static_cast<std::streampos>(2000));
+        is.seekg(6000);
+        BOOST_CHECK_EQUAL(is.tellg(), static_cast<std::streampos>(6000));
+        is.seekg(is.getBuffer().size());
+        BOOST_CHECK_EQUAL(is.tellg(), static_cast<std::streampos>(is.getBuffer().size()));
+        is.seekg(is.getBuffer().size()+1);
+        BOOST_CHECK_EQUAL(is.tellg(), static_cast<std::streampos>(-1));
+
+    }
+}
+
+void TestReadSome()
+{
+    BOOST_MESSAGE( "TestReadSome");
+    {
+        std::string junk = makeString(kDefaultBlockSize/2);
+
+        ostream os;
+
+        // write enough bytes to a buffer, to create at least 3 blocks
+        int i = 0;
+        for(; i < 5; ++i) {
+            os << junk;
+        }
+
+        cout << "Buffer has " << os.getBuffer().size() << " bytes\n";
+
+        istream is(os.getBuffer());
+
+        char datain[5000];
+
+        while(is.rdbuf()->in_avail()) {
+            size_t bytesAvail = is.rdbuf()->in_avail();
+            cout << "Bytes avail = " << bytesAvail << endl;
+            size_t in = is.readsome(datain, sizeof(datain));
+            cout << "Bytes read = " << in << endl;
+            BOOST_CHECK_EQUAL(bytesAvail, in);
+        }
+    }
+}
+
+void TestSeek()
+{
+    BOOST_MESSAGE( "TestSeek");
+    {
+        const std::string str = "SampleMessage";
+
+        avro::OutputBuffer tmp1, tmp2, tmp3;
+        tmp1.writeTo(str.c_str(), 3); // Sam
+        tmp2.writeTo(str.c_str()+3, 7);  // pleMess
+        tmp3.writeTo(str.c_str()+10, 3); // age
+        
+        tmp2.append(tmp3);
+        tmp1.append(tmp2);
+
+        BOOST_CHECK_EQUAL(tmp3.numDataChunks(), 1);
+        BOOST_CHECK_EQUAL(tmp2.numDataChunks(), 2);
+        BOOST_CHECK_EQUAL(tmp1.numDataChunks(), 3);
+
+        avro::InputBuffer buf(tmp1);
+
+        cout << "Starting string: " << str << '\n';
+        BOOST_CHECK_EQUAL(static_cast<std::string::size_type>( buf.size()) , str.size());
+
+        avro::istream is(buf);
+
+        const std::string part1 = "Sample";
+        char buffer[16];
+        is.read(buffer, part1.size());
+        std::string sample1(buffer, part1.size());
+        cout << "After reading bytes: " << sample1 << '\n';
+        BOOST_CHECK_EQUAL(sample1, part1);
+
+        const std::string part2 = "Message";
+        is.read(buffer, part2.size());
+        std::string sample2(buffer, part2.size());
+        cout << "After reading remaining bytes: " << sample2 << '\n';
+        BOOST_CHECK_EQUAL(sample2, part2);
+
+        cout << "Seeking back " << '\n';
+        is.seekg( - static_cast<std::streamoff>(part2.size()), std::ios_base::cur);
+
+        std::streampos loc = is.tellg();
+        cout << "Saved loc = " << loc << '\n';
+        BOOST_CHECK_EQUAL(static_cast<std::string::size_type>( loc ), (str.size()-part2.size()));
+
+        cout << "Reading remaining bytes: " << is.rdbuf() << '\n';
+        cout << "bytes avail = " << is.rdbuf()->in_avail() << '\n';
+        BOOST_CHECK_EQUAL(is.rdbuf()->in_avail(), 0);
+
+        cout << "Moving to saved loc = " << loc << '\n';
+        is.seekg(loc);
+        cout << "bytes avail = " << is.rdbuf()->in_avail() << '\n';
+
+        std::ostringstream oss;
+        oss << is.rdbuf();
+        cout << "After reading bytes: " << oss.str() << '\n';
+        BOOST_CHECK_EQUAL(oss.str(), part2);
+        
+    }
+}
+
+void TestIterator() 
+{
+    BOOST_MESSAGE( "TestIterator");
+    {
+        OutputBuffer ob(2 * kMaxBlockSize + 10);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 3);
+        BOOST_CHECK_EQUAL(ob.size(), 0U);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), 2 * kMaxBlockSize + kMinBlockSize);
+
+        BOOST_CHECK_EQUAL (std::distance(ob.begin(), ob.end()), 3);
+
+        OutputBuffer::const_iterator iter = ob.begin();
+        BOOST_CHECK_EQUAL( iter->size(), kMaxBlockSize);
+        ++iter;
+        BOOST_CHECK_EQUAL( iter->size(), kMaxBlockSize);
+        ++iter;
+        BOOST_CHECK_EQUAL( iter->size(), kMinBlockSize);
+        ++iter;
+        BOOST_CHECK( iter == ob.end());
+
+        size_t toWrite = kMaxBlockSize + kMinBlockSize;
+        ob.wroteTo(toWrite);
+        BOOST_CHECK_EQUAL(ob.size(), toWrite);
+        BOOST_CHECK_EQUAL(ob.freeSpace(), kMaxBlockSize);
+        BOOST_CHECK_EQUAL(ob.numChunks(), 2);
+        BOOST_CHECK_EQUAL(ob.numDataChunks(), 2);
+
+        InputBuffer ib = ob;
+        BOOST_CHECK_EQUAL (std::distance(ib.begin(), ib.end()), 2);
+
+        size_t acc = 0;
+        for(OutputBuffer::const_iterator iter = ob.begin();
+            iter != ob.end(); 
+            ++iter) {
+            acc += iter->size();
+        }
+        BOOST_CHECK_EQUAL(ob.freeSpace(), acc);
+
+        try {
+            ob.wroteTo(acc+1);
+        }
+        catch (std::exception &e) {
+            std::cout << "Intentionally triggered exception: " << e.what() << std::endl; 
+        }
+    }
+}
+
+void server(boost::barrier &b) 
+{
+    using boost::asio::ip::tcp;
+    boost::asio::io_service io_service;
+    tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), 33333));
+    tcp::socket sock(io_service);
+    a.listen();
+
+    b.wait();
+
+    a.accept(sock);
+    avro::OutputBuffer buf(100);
+
+    size_t length = sock.receive(buf);
+    buf.wroteTo(length);
+    cout << "Server got " << length << " bytes\n";
+
+    InputBuffer rbuf(buf);
+
+    std::string res;
+
+    avro::InputBuffer::const_iterator iter = rbuf.begin();
+    while(iter != rbuf.end() ) {
+        res.append(boost::asio::buffer_cast<const char *>(*iter), boost::asio::buffer_size(*iter));
+        cout << "Received Buffer size: " << boost::asio::buffer_size(*iter) << endl;
+        BOOST_CHECK_EQUAL(length, boost::asio::buffer_size(*iter));
+        cout << "Received Buffer: \"" << res << '"' << endl;
+        ++iter;
+    }
+
+    BOOST_CHECK_EQUAL(res, "hello world");
+}
+
+void TestAsioBuffer()
+{
+    using boost::asio::ip::tcp;
+    BOOST_MESSAGE( "TestAsioBuffer");
+    {
+        boost::barrier b(2);
+
+        boost::thread t(boost::bind(server, boost::ref(b)));
+
+        b.wait();
+
+        // set up the thing 
+        boost::asio::io_service io_service;
+
+        tcp::resolver resolver(io_service);
+        tcp::resolver::query query(tcp::v4(), "localhost", "33333");
+        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
+        tcp::resolver::iterator end;
+
+        tcp::socket socket(io_service);
+        boost::system::error_code error = boost::asio::error::host_not_found;
+        while (error && endpoint_iterator != end)
+        {
+          socket.close();
+          socket.connect(*endpoint_iterator++, error);
+        }
+        if (error) {
+          throw error;
+        }
+
+        std::string hello = "hello ";
+        std::string world = "world";
+        avro::OutputBuffer buf;
+        buf.writeTo(hello.c_str(), hello.size());
+        
+        BOOST_CHECK_EQUAL(buf.size(), hello.size());
+
+        avro::OutputBuffer buf2;
+        buf2.writeTo(world.c_str(), world.size());
+        BOOST_CHECK_EQUAL(buf2.size(), world.size());
+
+        buf.append(buf2);
+        BOOST_CHECK_EQUAL(buf.size(), hello.size() + world.size());
+
+        cout << "Distance " << std::distance(buf.begin(), buf.end()) << endl;
+        BOOST_CHECK_EQUAL(std::distance(buf.begin(), buf.end()), 1);
+
+        const avro::InputBuffer rbuf(buf);
+
+        avro::InputBuffer::const_iterator iter = rbuf.begin();
+        while(iter != rbuf.end() ) {
+            std::string str(boost::asio::buffer_cast<const char *>(*iter), boost::asio::buffer_size(*iter));
+            cout << "Buffer size: " << boost::asio::buffer_size(*iter) << endl;
+            cout << "Buffer: \"" << str << '"' << endl;
+            ++iter;
+        }
+
+        cout << "Buffer size " << rbuf.size() << endl;
+
+        std::size_t wrote = boost::asio::write(socket, rbuf);
+        cout << "Wrote " << wrote << endl;
+        BOOST_CHECK_EQUAL(wrote, rbuf.size());
+
+        t.join();
+    }
+}
+
+void TestSplit()
+{
+    BOOST_MESSAGE( "TestSplit");
+    {
+        const std::string str = "This message is to be split";
+
+        avro::OutputBuffer buf;
+        buf.writeTo(str.c_str(), str.size()); 
+
+        char datain[12];
+        avro::istream is(buf);
+        size_t in = is.readsome(datain, sizeof(datain));
+        BOOST_CHECK_EQUAL(in, sizeof(datain));
+        BOOST_CHECK_EQUAL(static_cast<size_t>(is.tellg()), sizeof(datain));
+
+        OutputBuffer part2;
+        part2.append(is.getBuffer());
+        BOOST_CHECK_EQUAL(part2.size(), buf.size());
+        InputBuffer part1 = part2.extractData(is.tellg());
+
+        BOOST_CHECK_EQUAL(part2.size(), str.size() - in);
+
+        printBuffer(part1);
+        printBuffer(part2);
+    }
+}
+
+void TestSplitOnBorder()
+{
+    BOOST_MESSAGE( "TestSplitOnBorder");
+    {
+
+        const std::string part1 = "This message";
+        const std::string part2 = " is to be split";
+
+        avro::OutputBuffer buf;
+        buf.writeTo(part1.c_str(), part1.size()); 
+        size_t firstChunkSize = buf.size();
+
+        {
+            avro::OutputBuffer tmp;
+            tmp.writeTo(part2.c_str(), part2.size()); 
+            buf.append(tmp);
+            printBuffer(InputBuffer(buf));
+        }
+
+        BOOST_CHECK_EQUAL(buf.numDataChunks(), 2);
+        size_t bufsize = buf.size();
+    
+        char datain[firstChunkSize];
+        avro::istream is(buf);
+        size_t in = is.readsome(datain, firstChunkSize);
+        BOOST_CHECK_EQUAL(in, firstChunkSize);
+
+        OutputBuffer newBuf;
+        newBuf.append(is.getBuffer());
+        newBuf.discardData(is.tellg());
+        BOOST_CHECK_EQUAL(newBuf.numDataChunks(), 1);
+
+        BOOST_CHECK_EQUAL(newBuf.size(), bufsize - in);
+
+        cout << is.rdbuf() << endl;
+        printBuffer(newBuf);
+    }
+}
+
+void TestSplitTwice() 
+{
+    BOOST_MESSAGE( "TestSplitTwice");
+    {
+        const std::string msg1 = makeString(30);
+
+        avro::OutputBuffer buf1;
+        buf1.writeTo(msg1.c_str(), msg1.size());
+
+        BOOST_CHECK_EQUAL(buf1.size(), msg1.size());
+
+        printBuffer(buf1);
+
+        avro::istream is(buf1);
+        char buffer[6];
+        is.readsome(buffer, 5);
+        buffer[5] = 0;
+        std::cout << "buffer =" << buffer << std::endl;
+        
+        buf1.discardData(is.tellg());
+        printBuffer(buf1);
+
+        avro::istream is2(buf1);
+        is2.seekg(15);
+
+        buf1.discardData(is2.tellg());
+        printBuffer(buf1);
+    }
+}
+
+void TestCopy() 
+{
+    BOOST_MESSAGE( "TestCopy");
+
+    const std::string msg = makeString(30);
+    // Test1, small data, small buffer
+    {
+        std::cout << "Test1\n";
+        // put a small amount of data in the buffer
+        avro::OutputBuffer wb;
+
+        wb.writeTo(msg.c_str(), msg.size());
+
+        BOOST_CHECK_EQUAL(msg.size(), wb.size());
+        BOOST_CHECK_EQUAL(wb.numDataChunks(), 1);
+        BOOST_CHECK_EQUAL(kDefaultBlockSize - msg.size(), 
+                wb.freeSpace());
+
+        // copy starting at offset 5 and copying 10 less bytes
+        BufferReader br(wb);
+        br.seek(5);
+        avro::InputBuffer ib = br.copyData(msg.size() - 10);
+
+        printBuffer(ib);
+
+        BOOST_CHECK_EQUAL(ib.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ib.size(), msg.size()-10);
+
+        // buf 1 should be unchanged
+        BOOST_CHECK_EQUAL(msg.size(), wb.size());
+        BOOST_CHECK_EQUAL(wb.numDataChunks(), 1);
+        BOOST_CHECK_EQUAL(kDefaultBlockSize - msg.size(), 
+                wb.freeSpace());
+
+        // make sure wb is still functional
+        wb.reserve(kDefaultBlockSize);
+        BOOST_CHECK_EQUAL(wb.size(), msg.size());
+        BOOST_CHECK_EQUAL(wb.numChunks(), 2);
+        BOOST_CHECK_EQUAL(kDefaultBlockSize * 2 - msg.size(), 
+                wb.freeSpace());
+    }
+
+    // Test2, small data, large buffer
+    {
+        std::cout << "Test2\n";
+        // put a small amount of data in the buffer
+        const OutputBuffer::size_type bufsize= 3*kMaxBlockSize;
+
+        avro::OutputBuffer wb(bufsize);
+        BOOST_CHECK_EQUAL(wb.numChunks(), 3);
+        BOOST_CHECK_EQUAL(wb.freeSpace(), bufsize);
+
+        wb.writeTo(msg.c_str(), msg.size());
+
+        BOOST_CHECK_EQUAL(wb.size(), msg.size());
+        BOOST_CHECK_EQUAL(wb.numDataChunks(), 1);
+        BOOST_CHECK_EQUAL(bufsize - msg.size(), 
+                wb.freeSpace());
+
+        BufferReader br(wb);
+        br.seek(5);
+        avro::InputBuffer ib = br.copyData(msg.size() - 10);
+
+        printBuffer(ib);
+
+        BOOST_CHECK_EQUAL(ib.numChunks(), 1);
+        BOOST_CHECK_EQUAL(ib.size(), msg.size()-10);
+
+        // wb should be unchanged
+        BOOST_CHECK_EQUAL(msg.size(), wb.size());
+        BOOST_CHECK_EQUAL(wb.numChunks(), 3);
+        BOOST_CHECK_EQUAL(wb.numDataChunks(), 1);
+        BOOST_CHECK_EQUAL(bufsize - msg.size(), wb.freeSpace());
+
+        // reserving a small amount should have no effect
+        wb.reserve(1);
+        BOOST_CHECK_EQUAL(msg.size(), wb.size());
+        BOOST_CHECK_EQUAL(wb.numChunks(), 3);
+        BOOST_CHECK_EQUAL(bufsize - msg.size(), wb.freeSpace());
+
+        // reserve more (will get extra block)
+        wb.reserve(bufsize);
+        BOOST_CHECK_EQUAL(msg.size(), wb.size());
+        BOOST_CHECK_EQUAL(wb.numChunks(), 4);
+        BOOST_CHECK_EQUAL(kMaxBlockSize * 3 - msg.size() + kMinBlockSize, 
+                wb.freeSpace());
+    }
+
+    // Test3 Border case, buffer is exactly full
+    {
+        std::cout << "Test3\n";
+        const OutputBuffer::size_type bufsize= 2*kDefaultBlockSize;
+        avro::OutputBuffer wb;
+
+        for(unsigned i = 0; i < bufsize; ++i) {
+            wb.writeTo('a');
+        }
+
+        BOOST_CHECK_EQUAL(wb.size(), bufsize);
+        BOOST_CHECK_EQUAL(wb.freeSpace(), 0U);
+        BOOST_CHECK_EQUAL(wb.numChunks(), 0);
+        BOOST_CHECK_EQUAL(wb.numDataChunks(), 2);
+
+        // copy where the chunks overlap
+        BufferReader br(wb);
+        br.seek(bufsize/2 - 10);
+        avro::InputBuffer ib = br.copyData(20);
+
+        printBuffer(ib);
+
+        BOOST_CHECK_EQUAL(ib.size(), 20U);
+        BOOST_CHECK_EQUAL(ib.numChunks(), 2);
+
+        // wb should be unchanged
+        BOOST_CHECK_EQUAL(wb.size(), bufsize);
+        BOOST_CHECK_EQUAL(wb.freeSpace(), 0U);
+        BOOST_CHECK_EQUAL(wb.numDataChunks(), 2);
+    }
+
+    // Test4, no data 
+    {
+        const OutputBuffer::size_type bufsize= 2*kMaxBlockSize;
+        std::cout << "Test4\n";
+        avro::OutputBuffer wb(bufsize);
+        BOOST_CHECK_EQUAL(wb.numChunks(), 2);
+        BOOST_CHECK_EQUAL(wb.size(), 0U);
+        BOOST_CHECK_EQUAL(wb.freeSpace(), bufsize);
+
+        avro::InputBuffer ib;
+        try {
+            BufferReader br(wb);
+            br.seek(10);
+        }
+        catch (std::exception &e) {
+            cout << "Intentially triggered exception: " << e.what() << endl;
+        }
+        try {
+            BufferReader br(wb);
+            avro::InputBuffer ib = br.copyData(10);
+        }
+        catch (std::exception &e) {
+            cout << "Intentially triggered exception: " << e.what() << endl;
+        }
+
+
+        BOOST_CHECK_EQUAL(ib.numChunks(), 0);
+        BOOST_CHECK_EQUAL(ib.size(), 0U);
+
+        // wb should keep all blocks remaining
+        BOOST_CHECK_EQUAL(wb.numChunks(), 2);
+        BOOST_CHECK_EQUAL(wb.size(), 0U);
+        BOOST_CHECK_EQUAL(wb.freeSpace(), bufsize);
+    }
+}
+
+// this is reproducing a sequence of steps that caused a crash
+void TestBug()  
+{
+    BOOST_MESSAGE( "TestBug");
+    {
+        OutputBuffer rxBuf;
+        OutputBuffer  buf;
+        rxBuf.reserve(64 * 1024);
+
+        rxBuf.wroteTo(2896);
+
+        {
+            avro::InputBuffer ib(rxBuf.extractData());
+            buf.append(ib);
+        }
+        
+        buf.discardData(61);
+
+        rxBuf.reserve(64 * 1024);
+        rxBuf.wroteTo(381);
+
+        {
+            avro::InputBuffer ib(rxBuf.extractData());
+            buf.append(ib);
+        }
+
+        buf.discardData(3216);
+
+
+        rxBuf.reserve(64 * 1024);
+    }
+}
+
+bool safeToDelete = false;
+
+void deleteForeign(const std::string &val) 
+{
+    std::cout << "Deleting foreign string containing " << val << '\n';
+    BOOST_CHECK(safeToDelete);
+}
+
+void TestForeign ()  
+{
+    BOOST_MESSAGE( "TestForeign");
+    {
+        std::string hello = "hello ";
+        std::string there = "there ";
+        std::string world = "world ";
+
+        OutputBuffer copy;
+
+        {
+            OutputBuffer buf;
+            buf.writeTo(hello.c_str(), hello.size());
+            buf.appendForeignData(there.c_str(), there.size(), boost::bind(&deleteForeign, there));
+            buf.writeTo(world.c_str(), world.size());
+        
+            printBuffer(buf);
+            BOOST_CHECK_EQUAL(buf.size(), 18U);
+            copy = buf;
+        }
+        std::cout << "Leaving inner scope\n";
+        safeToDelete = true;
+    }
+    std::cout << "Leaving outer scope\n";
+    safeToDelete = false;
+}
+
+void TestForeignDiscard ()  
+{
+    BOOST_MESSAGE( "TestForeign");
+    {
+        std::string hello = "hello ";
+        std::string again = "again ";
+        std::string there = "there ";
+        std::string world = "world ";
+
+        OutputBuffer buf;
+        buf.writeTo(hello.c_str(), hello.size());
+        buf.appendForeignData(again.c_str(), again.size(), boost::bind(&deleteForeign, again));
+        buf.appendForeignData(there.c_str(), there.size(), boost::bind(&deleteForeign, there));
+        buf.writeTo(world.c_str(), world.size());
+        
+        printBuffer(buf);
+        BOOST_CHECK_EQUAL(buf.size(), 24U);
+
+        // discard some data including half the foreign buffer
+        buf.discardData(9);
+        printBuffer(buf);
+        BOOST_CHECK_EQUAL(buf.size(), 15U);
+        
+        // discard some more data, which will lop off the first foreign buffer
+        safeToDelete = true;
+        buf.discardData(6);
+        safeToDelete = false;
+        printBuffer(buf);
+        BOOST_CHECK_EQUAL(buf.size(), 9U);
+
+        // discard some more data, which will lop off the second foreign buffer
+        safeToDelete = true;
+        buf.discardData(3);
+        safeToDelete = false;
+        printBuffer(buf);
+        BOOST_CHECK_EQUAL(buf.size(), 6U);
+    }
+}
+
+void TestPrinter()
+{
+    BOOST_MESSAGE( "TestPrinter");
+    {
+        OutputBuffer ob;
+        addDataToBuffer(ob, 128);
+
+        std::cout << ob << std::endl;
+    }
+}
+
+struct BufferTestSuite : public boost::unit_test::test_suite
+{
+    BufferTestSuite()  : 
+        boost::unit_test::test_suite("BufferTestSuite")
+    {
+        add (BOOST_TEST_CASE( TestReserve ));
+        add (BOOST_TEST_CASE( TestGrow ));
+        add (BOOST_TEST_CASE( TestDiscard ));
+        add (BOOST_TEST_CASE( TestConvertToInput ));
+        add (BOOST_TEST_CASE( TestExtractToInput ));
+        add (BOOST_TEST_CASE( TestAppend ));
+        add (BOOST_TEST_CASE( TestBufferStream ));
+        add (BOOST_TEST_CASE( TestBufferStreamEof ));
+        add (BOOST_TEST_CASE( TestSeekAndTell ));
+        add (BOOST_TEST_CASE( TestReadSome ));
+        add (BOOST_TEST_CASE( TestSeek));
+        add (BOOST_TEST_CASE( TestIterator));
+        add (BOOST_TEST_CASE( TestAsioBuffer));
+        add (BOOST_TEST_CASE( TestSplit));
+        add (BOOST_TEST_CASE( TestSplitOnBorder));
+        add (BOOST_TEST_CASE( TestSplitTwice));
+        add (BOOST_TEST_CASE( TestCopy));
+        add (BOOST_TEST_CASE( TestBug));
+        add (BOOST_TEST_CASE( TestForeign));
+        add (BOOST_TEST_CASE( TestForeignDiscard));
+        add (BOOST_TEST_CASE( TestPrinter));
+    }
+};
+
+boost::unit_test::test_suite*
+init_unit_test_suite( int, char* [] ) 
+{
+    boost::unit_test::test_suite *test (BOOST_TEST_SUITE ("Buffer Unit Tests"));
+    test->add (new BufferTestSuite() );
+
+    return test;
+}
+

Modified: hadoop/avro/trunk/lang/c++/test/testgen.cc
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c%2B%2B/test/testgen.cc?rev=931999&r1=931998&r2=931999&view=diff
==============================================================================
--- hadoop/avro/trunk/lang/c++/test/testgen.cc (original)
+++ hadoop/avro/trunk/lang/c++/test/testgen.cc Thu Apr  8 16:48:19 2010
@@ -25,8 +25,6 @@
 #include "testgen.hh" // < generated header
 #include "testgen2.hh" // < generated header
 
-#include "OutputStreamer.hh"
-#include "InputStreamer.hh"
 #include "Serializer.hh"
 #include "Writer.hh"
 #include "ValidatingWriter.hh"
@@ -37,6 +35,7 @@
 #include "Compiler.hh"
 #include "ResolvingReader.hh"
 #include "ResolverSchema.hh"
+#include "buffer/BufferPrint.hh"
 
 std::string gWriter ("jsonschemas/bigrecord");
 std::string gReader ("jsonschemas/bigrecord2");
@@ -207,20 +206,20 @@ struct TestCodeGenerator {
     void serializeToScreen()
     {
         std::cout << "Serialize:\n";
-        avro::ScreenStreamer os;
-        avro::Writer writer(os);
+        avro::Writer writer;
 
         avro::serialize(writer, myRecord_);
+        std::cout << writer.buffer();
         std::cout << "end Serialize\n";
     }
 
     void serializeToScreenValid()
     {
         std::cout << "Validated Serialize:\n";
-        avro::ScreenStreamer os;
-        avro::ValidatingWriter writer(schema_, os);
+        avro::ValidatingWriter writer(schema_);
 
         avro::serialize(writer, myRecord_);
+        std::cout << writer.buffer();
         std::cout << "end Validated Serialize\n";
     }
 
@@ -303,16 +302,12 @@ struct TestCodeGenerator {
 
     void testParser()
     {
-        std::ostringstream ostring;
-        avro::OStreamer os(ostring);
-        avro::Writer s (os);
+        avro::Writer s;
 
         avro::serialize(s, myRecord_); 
 
         testgen::RootRecord inRecord;
-        std::istringstream istring(ostring.str());
-        avro::IStreamer is(istring);
-        avro::Reader p(is);
+        avro::Reader p(s.buffer());
         avro::parse(p, inRecord);
 
         checkOk(myRecord_, inRecord);
@@ -321,19 +316,15 @@ struct TestCodeGenerator {
 
     void testParserValid()
     {
-        std::ostringstream ostring;
-        avro::OStreamer os(ostring);
-        avro::ValidatingWriter s (schema_, os);
+        avro::ValidatingWriter s (schema_);
 
         avro::serialize(s, myRecord_);
 
         testgen::RootRecord inRecord;
-        std::istringstream istring(ostring.str());
-        avro::IStreamer is(istring);
-        avro::ValidatingReader p(schema_, is);
+        avro::ValidatingReader p(schema_, s.buffer());
         avro::parse(p, inRecord);
 
-        //checkOk(myRecord_, inRecord);
+        checkOk(myRecord_, inRecord);
     }
 
     void testNameIndex()
@@ -476,20 +467,17 @@ struct TestSchemaResolving {
         }
     }
 
-    std::string serializeWriteRecordToString()
+    avro::InputBuffer serializeWriteRecordToBuffer()
     {
         std::ostringstream ostring;
-        avro::OStreamer os(ostring);
-        avro::Writer s (os);
+        avro::Writer s;
         avro::serialize(s, writeRecord_);
-        return ostring.str();
+        return s.buffer();
     }
 
-    void parseData(const std::string &data, avro::ResolverSchema &xSchema)
+    void parseData(const avro::InputBuffer &buf, avro::ResolverSchema &xSchema)
     {
-        std::istringstream istring(data);
-        avro::IStreamer is(istring);
-        avro::ResolvingReader r(xSchema, is);
+        avro::ResolvingReader r(xSchema, buf);
 
         avro::parse(r, readRecord_);
     }
@@ -503,8 +491,8 @@ struct TestSchemaResolving {
 
         printRecord(writeRecord_);
 
-        std::string writtenData = serializeWriteRecordToString();
-        parseData(writtenData, xSchema);
+        avro::InputBuffer buffer = serializeWriteRecordToBuffer();
+        parseData(buffer, xSchema);
 
         printRecord(readRecord_);
 

Modified: hadoop/avro/trunk/lang/c++/test/unittest.cc
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c%2B%2B/test/unittest.cc?rev=931999&r1=931998&r2=931999&view=diff
==============================================================================
--- hadoop/avro/trunk/lang/c++/test/unittest.cc (original)
+++ hadoop/avro/trunk/lang/c++/test/unittest.cc Thu Apr  8 16:48:19 2010
@@ -25,12 +25,13 @@
 #include "Node.hh"
 #include "Schema.hh"
 #include "ValidSchema.hh"
-#include "OutputStreamer.hh"
 #include "Serializer.hh"
 #include "Parser.hh"
 #include "SymbolMap.hh"
 #include "Compiler.hh"
 #include "SchemaResolution.hh"
+#include "buffer/BufferStream.hh"
+#include "buffer/BufferPrint.hh"
 
 #include "AvroSerialize.hh"
 
@@ -232,25 +233,27 @@ struct TestSchema
 
     void printEncoding() {
         std::cout << "Encoding\n";
-        ScreenStreamer os;
-        Serializer<Writer> s(os);
+        Serializer<Writer> s;
         writeEncoding(s, 0);
+        std::cout << s.buffer();
     }
 
     void printValidatingEncoding(int path)
     {
         std::cout << "Validating Encoding " << path << "\n";
-        ScreenStreamer os;
-        Serializer<ValidatingWriter> s(schema_, os);
+        Serializer<ValidatingWriter> s(schema_);
         writeEncoding(s, path);
+        std::cout << s.buffer();
     }
 
     void saveValidatingEncoding(int path) 
     {
         std::ofstream out("test.avro");
-        OStreamer os(out);
-        Serializer<ValidatingWriter> s(schema_, os);
+        Serializer<ValidatingWriter> s(schema_);
         writeEncoding(s, path);
+        InputBuffer buf = s.buffer();
+        istream is(buf);
+        out << is.rdbuf();
     }
 
     void printNext(Parser<Reader> &p) {
@@ -379,16 +382,18 @@ struct TestSchema
 
     void readRawData() {
         std::ifstream in("test.avro");
-        IStreamer ins(in);
-        Parser<Reader> p(ins);
+        ostream os;
+        os << in.rdbuf();
+        Parser<Reader> p(os.getBuffer());
         readData(p);
     }
 
     void readValidatedData()
     {
         std::ifstream in("test.avro");
-        IStreamer ins(in);
-        Parser<ValidatingReader> p(schema_, ins);
+        ostream os;
+        os << in.rdbuf();
+        Parser<ValidatingReader> p(schema_, os.getBuffer());
         readData(p);
     }
 
@@ -505,21 +510,23 @@ struct TestNested
         schema_.toFlatList(std::cout);
     }
 
-    void serializeNoRecurse(OutputStreamer &os)
+    InputBuffer serializeNoRecurse()
     {
         std::cout << "No recurse\n";
-        Serializer<ValidatingWriter> s(schema_, os);
+        Serializer<ValidatingWriter> s(schema_);
         s.writeRecord();
         s.writeLong(1);
         s.writeUnion(0);
         s.writeNull();
         s.writeBool(true);
+
+        return s.buffer();
     }
 
-    void serializeRecurse(OutputStreamer &os)
+    InputBuffer serializeRecurse()
     {
         std::cout << "Recurse\n";
-        Serializer<ValidatingWriter> s(schema_, os);
+        Serializer<ValidatingWriter> s(schema_);
         s.writeRecord();
         s.writeLong(1);
         s.writeUnion(1);
@@ -535,11 +542,13 @@ struct TestNested
             s.writeNull();
         }
         s.writeBool(true);
+
+        return s.buffer();
     }
 
-    void validatingParser(InputStreamer &is) 
+    void validatingParser(InputBuffer &buf) 
     {
-        Parser<ValidatingReader> p(schema_, is);
+        Parser<ValidatingReader> p(schema_, buf);
         int64_t val = 0;
         int64_t path = 0;
     
@@ -556,31 +565,24 @@ struct TestNested
     }
 
     void testToScreen() {
-        ScreenStreamer os;
-        serializeNoRecurse(os);
-        serializeRecurse(os);
+        InputBuffer buf1 = serializeNoRecurse();
+        InputBuffer buf2 = serializeRecurse();
+        std::cout << buf1;
+        std::cout << buf2;
     }
 
     void testParseNoRecurse() {
-        std::ostringstream ostring;
-        OStreamer os(ostring);
-        serializeNoRecurse(os);
         std::cout << "ParseNoRecurse\n";
-
-        std::istringstream istring(ostring.str());
-        IStreamer is(istring);
-        validatingParser(is);
+        InputBuffer buf = serializeNoRecurse();
+    
+        validatingParser(buf);
     }
 
     void testParseRecurse() {
-        std::ostringstream ostring;
-        OStreamer os(ostring);
-        serializeRecurse(os);
         std::cout << "ParseRecurse\n";
+        InputBuffer buf = serializeRecurse();
 
-        std::istringstream istring(ostring.str());
-        IStreamer is(istring);
-        validatingParser(is);
+        validatingParser(buf);
     }
 
 
@@ -608,13 +610,13 @@ struct TestGenerated
         int32_t val = 100;
         float   f   = 200.0;
 
-        ScreenStreamer os;
-        Writer writer(os);
+        Writer writer;
 
         serialize(writer, val);
         serialize(writer, Null());
         serialize(writer, f);
-        
+
+        std::cout << writer.buffer();
     }
 };