15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol Buffers - Google's data interchange format
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2008 Google Inc.  All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/protobuf/
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: kenton@google.com (Kenton Varda)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Based on original Protocol Buffers design by
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Sanjay Ghemawat, Jeff Dean, and others.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Testing strategy:  For each type of I/O (array, string, file, etc.) we
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// create an output stream and write some data to it, then create a
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// corresponding input stream to read the same data back and expect it to
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// match.  When the data is written, it is written in several small chunks
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of varying sizes, with a BackUp() after each chunk.  It is read back
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// similarly, but with chunks separated at different points.  The whole
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// process is run with a variety of block sizes for both the input and
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the output.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(kenton):  Rewrite this test to bring it up to the standards of all
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   the other proto2 tests.  May want to wait for gTest to implement
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   "parametized tests" so that one set of tests can be used on all the
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   implementations.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _MSC_VER
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <io.h>
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h>
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream>
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/zero_copy_stream_impl.h>
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/coded_stream.h>
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if HAVE_ZLIB
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/gzip_stream.h>
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/common.h>
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/testing/googletest.h>
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/testing/file.h>
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtest/gtest.h>
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace io {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _WIN32
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define pipe(fds) _pipe(fds, 4096, O_BINARY)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef O_BINARY
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _O_BINARY
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define O_BINARY _O_BINARY
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define O_BINARY 0     // If this isn't defined, the platform doesn't need it.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IoTest : public testing::Test {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test helpers.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper to write an array of data to an output stream.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool WriteToOutput(ZeroCopyOutputStream* output, const void* data, int size);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper to read a fixed-length array of data from an input stream.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ReadFromInput(ZeroCopyInputStream* input, void* data, int size);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write a string to the output stream.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WriteString(ZeroCopyOutputStream* output, const string& str);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read a number of bytes equal to the size of the given string and checks
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that it matches the string.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReadString(ZeroCopyInputStream* input, const string& str);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Writes some text to the output stream in a particular order.  Returns
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the number of bytes written, incase the caller needs that to set up an
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // input stream.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int WriteStuff(ZeroCopyOutputStream* output);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reads text from an input stream and expects it to match what
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WriteStuff() writes.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReadStuff(ZeroCopyInputStream* input);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Similar to WriteStuff, but performs more sophisticated testing.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int WriteStuffLarge(ZeroCopyOutputStream* output);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reads and tests a stream that should have been written to
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // via WriteStuffLarge().
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReadStuffLarge(ZeroCopyInputStream* input);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if HAVE_ZLIB
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string Compress(const string& data, const GzipOutputStream::Options& options);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string Uncompress(const string& data);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kBlockSizes[];
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kBlockSizeCount;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int IoTest::kBlockSizes[] = {-1, 1, 2, 5, 7, 10, 23, 64};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int IoTest::kBlockSizeCount = GOOGLE_ARRAYSIZE(IoTest::kBlockSizes);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IoTest::WriteToOutput(ZeroCopyOutputStream* output,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const void* data, int size) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8* in = reinterpret_cast<const uint8*>(data);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int in_size = size;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* out;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int out_size;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!output->Next(&out, &out_size)) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(out_size, 0);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (in_size <= out_size) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(out, in, in_size);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output->BackUp(out_size - in_size);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(out, in, out_size);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    in += out_size;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    in_size -= out_size;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_REPEATED_ZEROS 100
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int IoTest::ReadFromInput(ZeroCopyInputStream* input, void* data, int size) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* out = reinterpret_cast<uint8*>(data);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int out_size = size;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void* in;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int in_size = 0;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int repeated_zeros = 0;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!input->Next(&in, &in_size)) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return size - out_size;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(in_size, -1);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (in_size == 0) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      repeated_zeros++;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      repeated_zeros = 0;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_LT(repeated_zeros, MAX_REPEATED_ZEROS);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (out_size <= in_size) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(out, in, out_size);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (in_size > out_size) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        input->BackUp(in_size - out_size);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return size;  // Copied all of it.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(out, in, in_size);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out += in_size;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out_size -= in_size;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IoTest::WriteString(ZeroCopyOutputStream* output, const string& str) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(WriteToOutput(output, str.c_str(), str.size()));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IoTest::ReadString(ZeroCopyInputStream* input, const string& str) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_array<char> buffer(new char[str.size() + 1]);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer[str.size()] = '\0';
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ReadFromInput(input, buffer.get(), str.size()), str.size());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ(str.c_str(), buffer.get());
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int IoTest::WriteStuff(ZeroCopyOutputStream* output) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, "Hello world!\n");
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, "Some te");
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, "xt.  Blah blah.");
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, "abcdefg");
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, "01234567890123456789");
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, "foobar");
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output->ByteCount(), 68);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = output->ByteCount();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads text from an input stream and expects it to match what WriteStuff()
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// writes.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IoTest::ReadStuff(ZeroCopyInputStream* input) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, "Hello world!\n");
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, "Some text.  ");
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, "Blah ");
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, "blah.");
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, "abcdefg");
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(input->Skip(20));
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, "foo");
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, "bar");
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(input->ByteCount(), 68);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 byte;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ReadFromInput(input, &byte, 1), 0);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int IoTest::WriteStuffLarge(ZeroCopyOutputStream* output) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, "Hello world!\n");
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, "Some te");
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, "xt.  Blah blah.");
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, string(100000, 'x'));  // A very long string
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, string(100000, 'y'));  // A very long string
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteString(output, "01234567890123456789");
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output->ByteCount(), 200055);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = output->ByteCount();
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads text from an input stream and expects it to match what WriteStuff()
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// writes.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IoTest::ReadStuffLarge(ZeroCopyInputStream* input) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, "Hello world!\nSome text.  ");
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(input->Skip(5));
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, "blah.");
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(input->Skip(100000 - 10));
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, string(10, 'x') + string(100000 - 20000, 'y'));
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(input->Skip(20000 - 10));
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadString(input, "yyyyyyyyyy01234567890123456789");
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(input->ByteCount(), 200055);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 byte;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ReadFromInput(input, &byte, 1), 0);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, ArrayIo) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kBufferSize = 256;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 buffer[kBufferSize];
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kBlockSizeCount; i++) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < kBlockSizeCount; j++) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int size;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size = WriteStuff(&output);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ArrayInputStream input(buffer, size, kBlockSizes[j]);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ReadStuff(&input);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, TwoSessionWrite) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that two concatenated write sessions read correctly
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* strA = "0123456789";
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* strB = "WhirledPeas";
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kBufferSize = 2*1024;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* buffer = new uint8[kBufferSize];
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* temp_buffer = new char[40];
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kBlockSizeCount; i++) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < kBlockSizeCount; j++) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ArrayOutputStream* output =
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CodedOutputStream* coded_output = new CodedOutputStream(output);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_output->WriteVarint32(strlen(strA));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_output->WriteRaw(strA, strlen(strA));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete coded_output;  // flush
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 pos = output->ByteCount();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete output;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output = new ArrayOutputStream(
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          buffer + pos, kBufferSize - pos, kBlockSizes[i]);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_output = new CodedOutputStream(output);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_output->WriteVarint32(strlen(strB));
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_output->WriteRaw(strB, strlen(strB));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete coded_output;  // flush
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 size = pos + output->ByteCount();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete output;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ArrayInputStream* input =
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new ArrayInputStream(buffer, size, kBlockSizes[j]);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CodedInputStream* coded_input = new CodedInputStream(input);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32 insize;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(strlen(strA), insize);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(0, memcmp(temp_buffer, strA, insize));
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(strlen(strB), insize);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(0, memcmp(temp_buffer, strB, insize));
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete coded_input;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete input;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] temp_buffer;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] buffer;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if HAVE_ZLIB
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, GzipIo) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kBufferSize = 2*1024;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* buffer = new uint8[kBufferSize];
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kBlockSizeCount; i++) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < kBlockSizeCount; j++) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int z = 0; z < kBlockSizeCount; z++) {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int gzip_buffer_size = kBlockSizes[z];
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int size;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GzipOutputStream::Options options;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          options.format = GzipOutputStream::GZIP;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (gzip_buffer_size != -1) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            options.buffer_size = gzip_buffer_size;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GzipOutputStream gzout(&output, options);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          WriteStuff(&gzout);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          gzout.Close();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          size = output.ByteCount();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ArrayInputStream input(buffer, size, kBlockSizes[j]);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GzipInputStream gzin(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &input, GzipInputStream::GZIP, gzip_buffer_size);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ReadStuff(&gzin);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] buffer;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3733d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST_F(IoTest, GzipIoWithFlush) {
3743d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  const int kBufferSize = 2*1024;
3753d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  uint8* buffer = new uint8[kBufferSize];
3763d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  // We start with i = 4 as we want a block size > 6. With block size <= 6
3773d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  // Flush() fills up the entire 2K buffer with flush markers and the test
3783d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  // fails. See documentation for Flush() for more detail.
3793d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  for (int i = 4; i < kBlockSizeCount; i++) {
3803d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    for (int j = 0; j < kBlockSizeCount; j++) {
3813d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch      for (int z = 0; z < kBlockSizeCount; z++) {
3823d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch        int gzip_buffer_size = kBlockSizes[z];
3833d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch        int size;
3843d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch        {
3853d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
3863d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          GzipOutputStream::Options options;
3873d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          options.format = GzipOutputStream::GZIP;
3883d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          if (gzip_buffer_size != -1) {
3893d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch            options.buffer_size = gzip_buffer_size;
3903d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          }
3913d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          GzipOutputStream gzout(&output, options);
3923d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          WriteStuff(&gzout);
3933d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          EXPECT_TRUE(gzout.Flush());
3943d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          gzout.Close();
3953d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          size = output.ByteCount();
3963d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch        }
3973d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch        {
3983d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          ArrayInputStream input(buffer, size, kBlockSizes[j]);
3993d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          GzipInputStream gzin(
4003d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch              &input, GzipInputStream::GZIP, gzip_buffer_size);
4013d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch          ReadStuff(&gzin);
4023d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch        }
4033d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch      }
4043d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    }
4053d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  }
4063d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  delete [] buffer;
4073d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch}
4083d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4093d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST_F(IoTest, GzipIoContiguousFlushes) {
4103d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  const int kBufferSize = 2*1024;
4113d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  uint8* buffer = new uint8[kBufferSize];
4123d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4133d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  int block_size = kBlockSizes[4];
4143d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  int gzip_buffer_size = block_size;
4153d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  int size;
4163d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4173d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  ArrayOutputStream output(buffer, kBufferSize, block_size);
4183d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  GzipOutputStream::Options options;
4193d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  options.format = GzipOutputStream::GZIP;
4203d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  if (gzip_buffer_size != -1) {
4213d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    options.buffer_size = gzip_buffer_size;
4223d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  }
4233d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  GzipOutputStream gzout(&output, options);
4243d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  WriteStuff(&gzout);
4253d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  EXPECT_TRUE(gzout.Flush());
4263d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  EXPECT_TRUE(gzout.Flush());
4273d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  gzout.Close();
4283d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  size = output.ByteCount();
4293d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4303d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  ArrayInputStream input(buffer, size, block_size);
4313d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  GzipInputStream gzin(
4323d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch      &input, GzipInputStream::GZIP, gzip_buffer_size);
4333d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  ReadStuff(&gzin);
4343d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4353d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  delete [] buffer;
4363d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch}
4373d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4383d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST_F(IoTest, GzipIoReadAfterFlush) {
4393d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  const int kBufferSize = 2*1024;
4403d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  uint8* buffer = new uint8[kBufferSize];
4413d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4423d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  int block_size = kBlockSizes[4];
4433d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  int gzip_buffer_size = block_size;
4443d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  int size;
4453d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  ArrayOutputStream output(buffer, kBufferSize, block_size);
4463d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  GzipOutputStream::Options options;
4473d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  options.format = GzipOutputStream::GZIP;
4483d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  if (gzip_buffer_size != -1) {
4493d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    options.buffer_size = gzip_buffer_size;
4503d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  }
4513d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4523d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  GzipOutputStream gzout(&output, options);
4533d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  WriteStuff(&gzout);
4543d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  EXPECT_TRUE(gzout.Flush());
4553d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  size = output.ByteCount();
4563d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4573d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  ArrayInputStream input(buffer, size, block_size);
4583d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  GzipInputStream gzin(
4593d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch      &input, GzipInputStream::GZIP, gzip_buffer_size);
4603d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  ReadStuff(&gzin);
4613d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4623d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  gzout.Close();
4633d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4643d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  delete [] buffer;
4653d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch}
4663d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, ZlibIo) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kBufferSize = 2*1024;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* buffer = new uint8[kBufferSize];
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kBlockSizeCount; i++) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < kBlockSizeCount; j++) {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int z = 0; z < kBlockSizeCount; z++) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int gzip_buffer_size = kBlockSizes[z];
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int size;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GzipOutputStream::Options options;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          options.format = GzipOutputStream::ZLIB;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (gzip_buffer_size != -1) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            options.buffer_size = gzip_buffer_size;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GzipOutputStream gzout(&output, options);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          WriteStuff(&gzout);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          gzout.Close();
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          size = output.ByteCount();
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ArrayInputStream input(buffer, size, kBlockSizes[j]);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GzipInputStream gzin(
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &input, GzipInputStream::ZLIB, gzip_buffer_size);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ReadStuff(&gzin);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] buffer;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, ZlibIoInputAutodetect) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kBufferSize = 2*1024;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* buffer = new uint8[kBufferSize];
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ArrayOutputStream output(buffer, kBufferSize);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GzipOutputStream::Options options;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options.format = GzipOutputStream::ZLIB;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GzipOutputStream gzout(&output, options);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WriteStuff(&gzout);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gzout.Close();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size = output.ByteCount();
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ArrayInputStream input(buffer, size);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GzipInputStream gzin(&input, GzipInputStream::AUTO);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadStuff(&gzin);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ArrayOutputStream output(buffer, kBufferSize);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GzipOutputStream::Options options;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options.format = GzipOutputStream::GZIP;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GzipOutputStream gzout(&output, options);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WriteStuff(&gzout);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gzout.Close();
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size = output.ByteCount();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ArrayInputStream input(buffer, size);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GzipInputStream gzin(&input, GzipInputStream::AUTO);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadStuff(&gzin);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] buffer;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string IoTest::Compress(const string& data,
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const GzipOutputStream::Options& options) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string result;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StringOutputStream output(&result);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GzipOutputStream gzout(&output, options);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WriteToOutput(&gzout, data.data(), data.size());
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string IoTest::Uncompress(const string& data) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string result;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ArrayInputStream input(data.data(), data.size());
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GzipInputStream gzin(&input);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* buffer;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int size;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (gzin.Next(&buffer, &size)) {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.append(reinterpret_cast<const char*>(buffer), size);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, CompressionOptions) {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some ad-hoc testing of compression options.
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string golden;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  File::ReadFileToStringOrDie(
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestSourceDir() + "/google/protobuf/testdata/golden_message",
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &golden);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GzipOutputStream::Options options;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string gzip_compressed = Compress(golden, options);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.compression_level = 0;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string not_compressed = Compress(golden, options);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try zlib compression for fun.
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options = GzipOutputStream::Options();
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.format = GzipOutputStream::ZLIB;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string zlib_compressed = Compress(golden, options);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Uncompressed should be bigger than the original since it should have some
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sort of header.
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(not_compressed.size(), golden.size());
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Higher compression levels should result in smaller sizes.
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(zlib_compressed.size(), not_compressed.size());
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ZLIB format should differ from GZIP format.
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(zlib_compressed != gzip_compressed);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Everything should decompress correctly.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(Uncompress(not_compressed) == golden);
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(Uncompress(gzip_compressed) == golden);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(Uncompress(zlib_compressed) == golden);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, TwoSessionWriteGzip) {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that two concatenated gzip streams can be read correctly
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* strA = "0123456789";
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* strB = "QuickBrownFox";
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kBufferSize = 2*1024;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* buffer = new uint8[kBufferSize];
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* temp_buffer = new char[40];
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kBlockSizeCount; i++) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < kBlockSizeCount; j++) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ArrayOutputStream* output =
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GzipOutputStream* gzout = new GzipOutputStream(output);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CodedOutputStream* coded_output = new CodedOutputStream(gzout);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int32 outlen = strlen(strA) + 1;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_output->WriteVarint32(outlen);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_output->WriteRaw(strA, outlen);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete coded_output;  // flush
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete gzout;  // flush
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 pos = output->ByteCount();
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete output;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output = new ArrayOutputStream(
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          buffer + pos, kBufferSize - pos, kBlockSizes[i]);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gzout = new GzipOutputStream(output);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_output = new CodedOutputStream(gzout);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      outlen = strlen(strB) + 1;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_output->WriteVarint32(outlen);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_output->WriteRaw(strB, outlen);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete coded_output;  // flush
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete gzout;  // flush
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 size = pos + output->ByteCount();
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete output;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ArrayInputStream* input =
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new ArrayInputStream(buffer, size, kBlockSizes[j]);
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GzipInputStream* gzin = new GzipInputStream(input);
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CodedInputStream* coded_input = new CodedInputStream(gzin);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32 insize;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(strlen(strA) + 1, insize);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(0, memcmp(temp_buffer, strA, insize))
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "strA=" << strA << " in=" << temp_buffer;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(strlen(strB) + 1, insize);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(0, memcmp(temp_buffer, strB, insize))
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " out_block_size=" << kBlockSizes[i]
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " in_block_size=" << kBlockSizes[j]
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " pos=" << pos
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " size=" << size
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " strB=" << strB << " in=" << temp_buffer;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete coded_input;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete gzin;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete input;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] temp_buffer;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] buffer;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// There is no string input, only string output.  Also, it doesn't support
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// explicit block sizes.  So, we'll only run one test and we'll use
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ArrayInput to read back the results.
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, StringIo) {
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string str;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StringOutputStream output(&str);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WriteStuff(&output);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ArrayInputStream input(str.data(), str.size());
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadStuff(&input);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To test files, we create a temporary file, write, read, truncate, repeat.
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, FileIo) {
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string filename = TestTempDir() + "/zero_copy_stream_test_file";
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kBlockSizeCount; i++) {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < kBlockSizeCount; j++) {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Make a temporary file.
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int file =
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_GE(file, 0);
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileOutputStream output(file, kBlockSizes[i]);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WriteStuff(&output);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(0, output.GetErrno());
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Rewind.
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(lseek(file, 0, SEEK_SET), (off_t)-1);
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileInputStream input(file, kBlockSizes[j]);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ReadStuff(&input);
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(0, input.GetErrno());
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close(file);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if HAVE_ZLIB
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, GzipFileIo) {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string filename = TestTempDir() + "/zero_copy_stream_test_file";
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kBlockSizeCount; i++) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < kBlockSizeCount; j++) {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Make a temporary file.
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int file =
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_GE(file, 0);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileOutputStream output(file, kBlockSizes[i]);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GzipOutputStream gzout(&output);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WriteStuffLarge(&gzout);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gzout.Close();
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output.Flush();
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(0, output.GetErrno());
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Rewind.
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(lseek(file, 0, SEEK_SET), (off_t)-1);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileInputStream input(file, kBlockSizes[j]);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GzipInputStream gzin(&input);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ReadStuffLarge(&gzin);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(0, input.GetErrno());
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close(file);
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MSVC raises various debugging exceptions if we try to use a file
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// descriptor of -1, defeating our tests below.  This class will disable
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// these debug assertions while in scope.
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MsvcDebugDisabler {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_MSC_VER) && _MSC_VER >= 1400
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MsvcDebugDisabler() {
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_handler_ = _set_invalid_parameter_handler(MyHandler);
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_mode_ = _CrtSetReportMode(_CRT_ASSERT, 0);
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~MsvcDebugDisabler() {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_handler_ = _set_invalid_parameter_handler(old_handler_);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_mode_ = _CrtSetReportMode(_CRT_ASSERT, old_mode_);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void MyHandler(const wchar_t *expr,
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const wchar_t *func,
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const wchar_t *file,
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        unsigned int line,
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        uintptr_t pReserved) {
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // do nothing
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _invalid_parameter_handler old_handler_;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int old_mode_;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dummy constructor and destructor to ensure that GCC doesn't complain
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that debug_disabler is an unused variable.
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MsvcDebugDisabler() {}
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~MsvcDebugDisabler() {}
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that FileInputStreams report errors correctly.
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, FileReadError) {
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MsvcDebugDisabler debug_disabler;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -1 = invalid file descriptor.
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileInputStream input(-1);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void* buffer;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(input.Next(&buffer, &size));
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(EBADF, input.GetErrno());
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that FileOutputStreams report errors correctly.
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, FileWriteError) {
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MsvcDebugDisabler debug_disabler;
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -1 = invalid file descriptor.
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileOutputStream input(-1);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* buffer;
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size;
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first call to Next() succeeds because it doesn't have anything to
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // write yet.
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(input.Next(&buffer, &size));
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Second call fails.
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(input.Next(&buffer, &size));
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(EBADF, input.GetErrno());
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pipes are not seekable, so File{Input,Output}Stream ends up doing some
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different things to handle them.  We'll test by writing to a pipe and
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reading back from it.
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, PipeIo) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int files[2];
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kBlockSizeCount; i++) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < kBlockSizeCount; j++) {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Need to create a new pipe each time because ReadStuff() expects
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to see EOF at the end.
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(pipe(files), 0);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileOutputStream output(files[1], kBlockSizes[i]);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WriteStuff(&output);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(0, output.GetErrno());
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close(files[1]);  // Send EOF.
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileInputStream input(files[0], kBlockSizes[j]);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ReadStuff(&input);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(0, input.GetErrno());
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close(files[0]);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test using C++ iostreams.
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, IostreamIo) {
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kBlockSizeCount; i++) {
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < kBlockSizeCount; j++) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        stringstream stream;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          OstreamOutputStream output(&stream, kBlockSizes[i]);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          WriteStuff(&output);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EXPECT_FALSE(stream.fail());
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          IstreamInputStream input(&stream, kBlockSizes[j]);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ReadStuff(&input);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EXPECT_TRUE(stream.eof());
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        stringstream stream;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          OstreamOutputStream output(&stream, kBlockSizes[i]);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          WriteStuffLarge(&output);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EXPECT_FALSE(stream.fail());
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          IstreamInputStream input(&stream, kBlockSizes[j]);
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ReadStuffLarge(&input);
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EXPECT_TRUE(stream.eof());
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To test ConcatenatingInputStream, we create several ArrayInputStreams
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// covering a buffer and then concatenate them.
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, ConcatenatingInputStream) {
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kBufferSize = 256;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 buffer[kBufferSize];
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill the buffer.
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayOutputStream output(buffer, kBufferSize);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteStuff(&output);
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now split it up into multiple streams of varying sizes.
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(68, output.ByteCount());  // Test depends on this.
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayInputStream input1(buffer     , 12);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayInputStream input2(buffer + 12,  7);
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayInputStream input3(buffer + 19,  6);
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayInputStream input4(buffer + 25, 15);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayInputStream input5(buffer + 40,  0);
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note:  We want to make sure we have a stream boundary somewhere between
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bytes 42 and 62, which is the range that it Skip()ed by ReadStuff().  This
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tests that a bug that existed in the original code for Skip() is fixed.
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayInputStream input6(buffer + 40, 10);
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayInputStream input7(buffer + 50, 18);  // Total = 68 bytes.
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ZeroCopyInputStream* streams[] =
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {&input1, &input2, &input3, &input4, &input5, &input6, &input7};
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the concatenating stream and read.
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConcatenatingInputStream input(streams, GOOGLE_ARRAYSIZE(streams));
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadStuff(&input);
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To test LimitingInputStream, we write our golden text to a buffer, then
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// create an ArrayInputStream that contains the whole buffer (not just the
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bytes written), then use a LimitingInputStream to limit it just to the
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bytes written.
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(IoTest, LimitingInputStream) {
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kBufferSize = 256;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 buffer[kBufferSize];
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill the buffer.
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayOutputStream output(buffer, kBufferSize);
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteStuff(&output);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up input.
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayInputStream array_input(buffer, kBufferSize);
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LimitingInputStream input(&array_input, output.ByteCount());
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadStuff(&input);
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that a zero-size array doesn't confuse the code.
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ZeroSizeArray, Input) {
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayInputStream input(NULL, 0);
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void* data;
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size;
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(input.Next(&data, &size));
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ZeroSizeArray, Output) {
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayOutputStream output(NULL, 0);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* data;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size;
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(output.Next(&data, &size));
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace io
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protobuf
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace google
945