1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc.  All rights reserved.
3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// http://code.google.com/p/protobuf/
4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without
6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are
7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met:
8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions of source code must retain the above copyright
10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer.
11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions in binary form must reproduce the above
12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer
13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the
14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution.
15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Neither the name of Google Inc. nor the names of its
16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from
17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission.
18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Author: kenton@google.com (Kenton Varda)
32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//  Based on original Protocol Buffers design by
33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//  Sanjay Ghemawat, Jeff Dean, and others.
34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Testing strategy:  For each type of I/O (array, string, file, etc.) we
36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// create an output stream and write some data to it, then create a
37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// corresponding input stream to read the same data back and expect it to
38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// match.  When the data is written, it is written in several small chunks
39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// of varying sizes, with a BackUp() after each chunk.  It is read back
40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// similarly, but with chunks separated at different points.  The whole
41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// process is run with a variety of block sizes for both the input and
42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// the output.
43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// TODO(kenton):  Rewrite this test to bring it up to the standards of all
45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//   the other proto2 tests.  May want to wait for gTest to implement
46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//   "parametized tests" so that one set of tests can be used on all the
47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//   implementations.
48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "config.h"
50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _MSC_VER
52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <io.h>
53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else
54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <unistd.h>
55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <stdlib.h>
57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/types.h>
58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/stat.h>
59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <fcntl.h>
60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <errno.h>
61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sstream>
62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/io/zero_copy_stream_impl.h>
64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if HAVE_ZLIB
66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/io/gzip_stream.h>
67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/common.h>
70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/testing/googletest.h>
71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/testing/file.h>
72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <gtest/gtest.h>
73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google {
75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf {
76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace io {
77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace {
78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32
80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define pipe(fds) _pipe(fds, 4096, O_BINARY)
81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef O_BINARY
84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _O_BINARY
85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define O_BINARY _O_BINARY
86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else
87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define O_BINARY 0     // If this isn't defined, the platform doesn't need it.
88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass IoTest : public testing::Test {
92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville protected:
93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Test helpers.
94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Helper to write an array of data to an output stream.
96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  bool WriteToOutput(ZeroCopyOutputStream* output, const void* data, int size);
97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Helper to read a fixed-length array of data from an input stream.
98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int ReadFromInput(ZeroCopyInputStream* input, void* data, int size);
99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Write a string to the output stream.
100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void WriteString(ZeroCopyOutputStream* output, const string& str);
101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Read a number of bytes equal to the size of the given string and checks
102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // that it matches the string.
103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ReadString(ZeroCopyInputStream* input, const string& str);
104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Writes some text to the output stream in a particular order.  Returns
105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // the number of bytes written, incase the caller needs that to set up an
106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // input stream.
107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int WriteStuff(ZeroCopyOutputStream* output);
108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Reads text from an input stream and expects it to match what
109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // WriteStuff() writes.
110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ReadStuff(ZeroCopyInputStream* input);
111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Similar to WriteStuff, but performs more sophisticated testing.
113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int WriteStuffLarge(ZeroCopyOutputStream* output);
114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Reads and tests a stream that should have been written to
115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // via WriteStuffLarge().
116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void ReadStuffLarge(ZeroCopyInputStream* input);
117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if HAVE_ZLIB
119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string Compress(const string& data, const GzipOutputStream::Options& options);
120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string Uncompress(const string& data);
121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  static const int kBlockSizes[];
124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  static const int kBlockSizeCount;
125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville};
126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst int IoTest::kBlockSizes[] = {-1, 1, 2, 5, 7, 10, 23, 64};
128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst int IoTest::kBlockSizeCount = GOOGLE_ARRAYSIZE(IoTest::kBlockSizes);
129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool IoTest::WriteToOutput(ZeroCopyOutputStream* output,
131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                           const void* data, int size) {
132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const uint8* in = reinterpret_cast<const uint8*>(data);
133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int in_size = size;
134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void* out;
136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int out_size;
137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  while (true) {
139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (!output->Next(&out, &out_size)) {
140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return false;
141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    EXPECT_GT(out_size, 0);
143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (in_size <= out_size) {
145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      memcpy(out, in, in_size);
146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      output->BackUp(out_size - in_size);
147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return true;
148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    memcpy(out, in, out_size);
151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    in += out_size;
152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    in_size -= out_size;
153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define MAX_REPEATED_ZEROS 100
157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint IoTest::ReadFromInput(ZeroCopyInputStream* input, void* data, int size) {
159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  uint8* out = reinterpret_cast<uint8*>(data);
160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int out_size = size;
161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const void* in;
163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int in_size = 0;
164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int repeated_zeros = 0;
166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  while (true) {
168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (!input->Next(&in, &in_size)) {
169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return size - out_size;
170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    EXPECT_GT(in_size, -1);
172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (in_size == 0) {
173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      repeated_zeros++;
174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    } else {
175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      repeated_zeros = 0;
176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    EXPECT_LT(repeated_zeros, MAX_REPEATED_ZEROS);
178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (out_size <= in_size) {
180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      memcpy(out, in, out_size);
181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      if (in_size > out_size) {
182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        input->BackUp(in_size - out_size);
183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return size;  // Copied all of it.
185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    memcpy(out, in, in_size);
188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    out += in_size;
189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    out_size -= in_size;
190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid IoTest::WriteString(ZeroCopyOutputStream* output, const string& str) {
194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(WriteToOutput(output, str.c_str(), str.size()));
195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid IoTest::ReadString(ZeroCopyInputStream* input, const string& str) {
198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  scoped_array<char> buffer(new char[str.size() + 1]);
199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  buffer[str.size()] = '\0';
200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(ReadFromInput(input, buffer.get(), str.size()), str.size());
201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_STREQ(str.c_str(), buffer.get());
202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint IoTest::WriteStuff(ZeroCopyOutputStream* output) {
205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, "Hello world!\n");
206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, "Some te");
207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, "xt.  Blah blah.");
208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, "abcdefg");
209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, "01234567890123456789");
210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, "foobar");
211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(output->ByteCount(), 68);
213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int result = output->ByteCount();
215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return result;
216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Reads text from an input stream and expects it to match what WriteStuff()
219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// writes.
220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid IoTest::ReadStuff(ZeroCopyInputStream* input) {
221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, "Hello world!\n");
222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, "Some text.  ");
223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, "Blah ");
224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, "blah.");
225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, "abcdefg");
226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(input->Skip(20));
227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, "foo");
228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, "bar");
229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(input->ByteCount(), 68);
231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  uint8 byte;
233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(ReadFromInput(input, &byte, 1), 0);
234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint IoTest::WriteStuffLarge(ZeroCopyOutputStream* output) {
237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, "Hello world!\n");
238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, "Some te");
239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, "xt.  Blah blah.");
240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, string(100000, 'x'));  // A very long string
241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, string(100000, 'y'));  // A very long string
242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteString(output, "01234567890123456789");
243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(output->ByteCount(), 200055);
245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int result = output->ByteCount();
247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return result;
248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Reads text from an input stream and expects it to match what WriteStuff()
251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// writes.
252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid IoTest::ReadStuffLarge(ZeroCopyInputStream* input) {
253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, "Hello world!\nSome text.  ");
254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(input->Skip(5));
255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, "blah.");
256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(input->Skip(100000 - 10));
257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, string(10, 'x') + string(100000 - 20000, 'y'));
258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(input->Skip(20000 - 10));
259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadString(input, "yyyyyyyyyy01234567890123456789");
260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(input->ByteCount(), 200055);
262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  uint8 byte;
264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(ReadFromInput(input, &byte, 1), 0);
265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ===================================================================
268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, ArrayIo) {
270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const int kBufferSize = 256;
271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  uint8 buffer[kBufferSize];
272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int i = 0; i < kBlockSizeCount; i++) {
274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (int j = 0; j < kBlockSizeCount; j++) {
275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      int size;
276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      {
277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        size = WriteStuff(&output);
279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      {
281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        ArrayInputStream input(buffer, size, kBlockSizes[j]);
282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        ReadStuff(&input);
283fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
284fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
285fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
286fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
287fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
288fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if HAVE_ZLIB
289fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, GzipIo) {
290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const int kBufferSize = 2*1024;
291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  uint8* buffer = new uint8[kBufferSize];
292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int i = 0; i < kBlockSizeCount; i++) {
293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (int j = 0; j < kBlockSizeCount; j++) {
294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      for (int z = 0; z < kBlockSizeCount; z++) {
295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        int gzip_buffer_size = kBlockSizes[z];
296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        int size;
297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        {
298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          GzipOutputStream gzout(
300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville              &output, GzipOutputStream::GZIP, gzip_buffer_size);
301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          WriteStuff(&gzout);
302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          gzout.Close();
303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          size = output.ByteCount();
304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        }
305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        {
306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          ArrayInputStream input(buffer, size, kBlockSizes[j]);
307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          GzipInputStream gzin(
308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville              &input, GzipInputStream::GZIP, gzip_buffer_size);
309fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          ReadStuff(&gzin);
310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        }
311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
312fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  delete [] buffer;
315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, ZlibIo) {
318fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const int kBufferSize = 2*1024;
319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  uint8* buffer = new uint8[kBufferSize];
320fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int i = 0; i < kBlockSizeCount; i++) {
321fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (int j = 0; j < kBlockSizeCount; j++) {
322fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      for (int z = 0; z < kBlockSizeCount; z++) {
323fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        int gzip_buffer_size = kBlockSizes[z];
324fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        int size;
325fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        {
326fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          GzipOutputStream gzout(
328fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville              &output, GzipOutputStream::ZLIB, gzip_buffer_size);
329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          WriteStuff(&gzout);
330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          gzout.Close();
331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          size = output.ByteCount();
332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        }
333fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        {
334fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          ArrayInputStream input(buffer, size, kBlockSizes[j]);
335fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          GzipInputStream gzin(
336fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville              &input, GzipInputStream::ZLIB, gzip_buffer_size);
337fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          ReadStuff(&gzin);
338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        }
339fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
340fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
341fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
342fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  delete [] buffer;
343fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
344fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
345fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, ZlibIoInputAutodetect) {
346fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const int kBufferSize = 2*1024;
347fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  uint8* buffer = new uint8[kBufferSize];
348fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int size;
349fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  {
350fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ArrayOutputStream output(buffer, kBufferSize);
351fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    GzipOutputStream gzout(&output, GzipOutputStream::ZLIB);
352fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    WriteStuff(&gzout);
353fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    gzout.Close();
354fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    size = output.ByteCount();
355fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
356fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  {
357fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ArrayInputStream input(buffer, size);
358fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    GzipInputStream gzin(&input, GzipInputStream::AUTO);
359fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ReadStuff(&gzin);
360fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
361fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  {
362fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ArrayOutputStream output(buffer, kBufferSize);
363fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    GzipOutputStream gzout(&output, GzipOutputStream::GZIP);
364fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    WriteStuff(&gzout);
365fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    gzout.Close();
366fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    size = output.ByteCount();
367fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
368fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  {
369fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ArrayInputStream input(buffer, size);
370fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    GzipInputStream gzin(&input, GzipInputStream::AUTO);
371fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ReadStuff(&gzin);
372fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
373fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  delete [] buffer;
374fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
375fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
376fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestring IoTest::Compress(const string& data,
377fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                        const GzipOutputStream::Options& options) {
378fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string result;
379fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  {
380fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    StringOutputStream output(&result);
381fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    GzipOutputStream gzout(&output, options);
382fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    WriteToOutput(&gzout, data.data(), data.size());
383fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
384fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return result;
385fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
386fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
387fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestring IoTest::Uncompress(const string& data) {
388fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string result;
389fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  {
390fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ArrayInputStream input(data.data(), data.size());
391fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    GzipInputStream gzin(&input);
392fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const void* buffer;
393fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    int size;
394fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    while (gzin.Next(&buffer, &size)) {
395fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      result.append(reinterpret_cast<const char*>(buffer), size);
396fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
397fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
398fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return result;
399fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
400fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
401fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, CompressionOptions) {
402fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Some ad-hoc testing of compression options.
403fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
404fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string golden;
405fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  File::ReadFileToStringOrDie(
406d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    TestSourceDir() + "/google/protobuf/testdata/golden_message",
407d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    &golden);
408fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
409fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GzipOutputStream::Options options;
410fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string gzip_compressed = Compress(golden, options);
411fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
412fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  options.compression_level = 0;
413fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string not_compressed = Compress(golden, options);
414fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
415fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Try zlib compression for fun.
416fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  options = GzipOutputStream::Options();
417fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  options.format = GzipOutputStream::ZLIB;
418fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string zlib_compressed = Compress(golden, options);
419fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
420fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Uncompressed should be bigger than the original since it should have some
421fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // sort of header.
422fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_GT(not_compressed.size(), golden.size());
423fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
424fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Higher compression levels should result in smaller sizes.
425fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_LT(zlib_compressed.size(), not_compressed.size());
426fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
427fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // ZLIB format should differ from GZIP format.
428fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(zlib_compressed != gzip_compressed);
429fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
430fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Everything should decompress correctly.
431fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(Uncompress(not_compressed) == golden);
432fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(Uncompress(gzip_compressed) == golden);
433fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(Uncompress(zlib_compressed) == golden);
434fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
435fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
436fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
437fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// There is no string input, only string output.  Also, it doesn't support
438fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// explicit block sizes.  So, we'll only run one test and we'll use
439fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ArrayInput to read back the results.
440fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, StringIo) {
441fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string str;
442fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  {
443fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    StringOutputStream output(&str);
444fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    WriteStuff(&output);
445fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
446fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  {
447fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ArrayInputStream input(str.data(), str.size());
448fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    ReadStuff(&input);
449fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
450fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
451fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
452fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
453fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// To test files, we create a temporary file, write, read, truncate, repeat.
454fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, FileIo) {
455fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string filename = TestTempDir() + "/zero_copy_stream_test_file";
456fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
457fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int i = 0; i < kBlockSizeCount; i++) {
458fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (int j = 0; j < kBlockSizeCount; j++) {
459fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Make a temporary file.
460fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      int file =
461fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777);
462fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      ASSERT_GE(file, 0);
463fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
464fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      {
465fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        FileOutputStream output(file, kBlockSizes[i]);
466fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        WriteStuff(&output);
467fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        EXPECT_EQ(0, output.GetErrno());
468fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
469fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
470fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Rewind.
471fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      ASSERT_NE(lseek(file, 0, SEEK_SET), (off_t)-1);
472fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
473fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      {
474fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        FileInputStream input(file, kBlockSizes[j]);
475fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        ReadStuff(&input);
476fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        EXPECT_EQ(0, input.GetErrno());
477fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
478fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
479fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      close(file);
480fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
481fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
482fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
483fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
484fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if HAVE_ZLIB
485fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, GzipFileIo) {
486fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string filename = TestTempDir() + "/zero_copy_stream_test_file";
487fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
488fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int i = 0; i < kBlockSizeCount; i++) {
489fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (int j = 0; j < kBlockSizeCount; j++) {
490fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Make a temporary file.
491fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      int file =
492fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777);
493fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      ASSERT_GE(file, 0);
494fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      {
495fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        FileOutputStream output(file, kBlockSizes[i]);
496fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        GzipOutputStream gzout(&output);
497fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        WriteStuffLarge(&gzout);
498fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        gzout.Close();
499fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        output.Flush();
500fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        EXPECT_EQ(0, output.GetErrno());
501fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
502fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
503fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Rewind.
504fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      ASSERT_NE(lseek(file, 0, SEEK_SET), (off_t)-1);
505fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
506fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      {
507fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        FileInputStream input(file, kBlockSizes[j]);
508fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        GzipInputStream gzin(&input);
509fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        ReadStuffLarge(&gzin);
510fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        EXPECT_EQ(0, input.GetErrno());
511fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
512fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
513fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      close(file);
514fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
515fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
516fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
517fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
518fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
519fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// MSVC raises various debugging exceptions if we try to use a file
520fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// descriptor of -1, defeating our tests below.  This class will disable
521fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// these debug assertions while in scope.
522fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass MsvcDebugDisabler {
523fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public:
524d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#if defined(_MSC_VER) && _MSC_VER >= 1400
525fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  MsvcDebugDisabler() {
526fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    old_handler_ = _set_invalid_parameter_handler(MyHandler);
527fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    old_mode_ = _CrtSetReportMode(_CRT_ASSERT, 0);
528fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
529fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ~MsvcDebugDisabler() {
530fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    old_handler_ = _set_invalid_parameter_handler(old_handler_);
531fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    old_mode_ = _CrtSetReportMode(_CRT_ASSERT, old_mode_);
532fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
533fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
534fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  static void MyHandler(const wchar_t *expr,
535fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                        const wchar_t *func,
536fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                        const wchar_t *file,
537fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                        unsigned int line,
538fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                        uintptr_t pReserved) {
539fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // do nothing
540fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
541fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
542fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _invalid_parameter_handler old_handler_;
543fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int old_mode_;
544fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else
545fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Dummy constructor and destructor to ensure that GCC doesn't complain
546fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // that debug_disabler is an unused variable.
547fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  MsvcDebugDisabler() {}
548fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ~MsvcDebugDisabler() {}
549fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif
550fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville};
551fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
552fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Test that FileInputStreams report errors correctly.
553fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, FileReadError) {
554fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  MsvcDebugDisabler debug_disabler;
555fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
556fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // -1 = invalid file descriptor.
557fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  FileInputStream input(-1);
558fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
559fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const void* buffer;
560fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int size;
561fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_FALSE(input.Next(&buffer, &size));
562fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(EBADF, input.GetErrno());
563fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
564fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
565fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Test that FileOutputStreams report errors correctly.
566fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, FileWriteError) {
567fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  MsvcDebugDisabler debug_disabler;
568fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
569fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // -1 = invalid file descriptor.
570fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  FileOutputStream input(-1);
571fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
572fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void* buffer;
573fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int size;
574fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
575fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // The first call to Next() succeeds because it doesn't have anything to
576fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // write yet.
577fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_TRUE(input.Next(&buffer, &size));
578fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
579fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Second call fails.
580fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_FALSE(input.Next(&buffer, &size));
581fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
582fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_EQ(EBADF, input.GetErrno());
583fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
584fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
585fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Pipes are not seekable, so File{Input,Output}Stream ends up doing some
586fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// different things to handle them.  We'll test by writing to a pipe and
587fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// reading back from it.
588fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, PipeIo) {
589fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int files[2];
590fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
591fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int i = 0; i < kBlockSizeCount; i++) {
592fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (int j = 0; j < kBlockSizeCount; j++) {
593fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // Need to create a new pipe each time because ReadStuff() expects
594fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // to see EOF at the end.
595fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      ASSERT_EQ(pipe(files), 0);
596fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
597fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      {
598fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        FileOutputStream output(files[1], kBlockSizes[i]);
599fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        WriteStuff(&output);
600fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        EXPECT_EQ(0, output.GetErrno());
601fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
602fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      close(files[1]);  // Send EOF.
603fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
604fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      {
605fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        FileInputStream input(files[0], kBlockSizes[j]);
606fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        ReadStuff(&input);
607fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        EXPECT_EQ(0, input.GetErrno());
608fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
609fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      close(files[0]);
610fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
611fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
612fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
613fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
614fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Test using C++ iostreams.
615fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, IostreamIo) {
616fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int i = 0; i < kBlockSizeCount; i++) {
617fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (int j = 0; j < kBlockSizeCount; j++) {
618fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      {
619fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        stringstream stream;
620fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
621fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        {
622fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          OstreamOutputStream output(&stream, kBlockSizes[i]);
623fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          WriteStuff(&output);
624fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          EXPECT_FALSE(stream.fail());
625fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        }
626fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
627fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        {
628fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          IstreamInputStream input(&stream, kBlockSizes[j]);
629fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          ReadStuff(&input);
630fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          EXPECT_TRUE(stream.eof());
631fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        }
632fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
633fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
634fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      {
635fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        stringstream stream;
636fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
637fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        {
638fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          OstreamOutputStream output(&stream, kBlockSizes[i]);
639fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          WriteStuffLarge(&output);
640fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          EXPECT_FALSE(stream.fail());
641fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        }
642fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
643fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        {
644fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          IstreamInputStream input(&stream, kBlockSizes[j]);
645fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          ReadStuffLarge(&input);
646fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          EXPECT_TRUE(stream.eof());
647fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        }
648fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
649fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
650fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
651fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
652fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
653fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// To test ConcatenatingInputStream, we create several ArrayInputStreams
654fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// covering a buffer and then concatenate them.
655fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, ConcatenatingInputStream) {
656fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const int kBufferSize = 256;
657fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  uint8 buffer[kBufferSize];
658fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
659fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Fill the buffer.
660fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayOutputStream output(buffer, kBufferSize);
661fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteStuff(&output);
662fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
663fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Now split it up into multiple streams of varying sizes.
664fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ASSERT_EQ(68, output.ByteCount());  // Test depends on this.
665fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayInputStream input1(buffer     , 12);
666fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayInputStream input2(buffer + 12,  7);
667fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayInputStream input3(buffer + 19,  6);
668fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayInputStream input4(buffer + 25, 15);
669fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayInputStream input5(buffer + 40,  0);
670fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Note:  We want to make sure we have a stream boundary somewhere between
671fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // bytes 42 and 62, which is the range that it Skip()ed by ReadStuff().  This
672fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // tests that a bug that existed in the original code for Skip() is fixed.
673fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayInputStream input6(buffer + 40, 10);
674fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayInputStream input7(buffer + 50, 18);  // Total = 68 bytes.
675fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
676fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ZeroCopyInputStream* streams[] =
677fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    {&input1, &input2, &input3, &input4, &input5, &input6, &input7};
678fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
679fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Create the concatenating stream and read.
680fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ConcatenatingInputStream input(streams, GOOGLE_ARRAYSIZE(streams));
681fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadStuff(&input);
682fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
683fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
684fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// To test LimitingInputStream, we write our golden text to a buffer, then
685fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// create an ArrayInputStream that contains the whole buffer (not just the
686fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// bytes written), then use a LimitingInputStream to limit it just to the
687fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// bytes written.
688fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST_F(IoTest, LimitingInputStream) {
689fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const int kBufferSize = 256;
690fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  uint8 buffer[kBufferSize];
691fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
692fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Fill the buffer.
693fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayOutputStream output(buffer, kBufferSize);
694fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  WriteStuff(&output);
695fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
696fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Set up input.
697fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayInputStream array_input(buffer, kBufferSize);
698fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  LimitingInputStream input(&array_input, output.ByteCount());
699fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
700fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ReadStuff(&input);
701fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
702fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
703fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Check that a zero-size array doesn't confuse the code.
704fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST(ZeroSizeArray, Input) {
705fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayInputStream input(NULL, 0);
706fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const void* data;
707fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int size;
708fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_FALSE(input.Next(&data, &size));
709fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
710fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
711fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleTEST(ZeroSizeArray, Output) {
712fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ArrayOutputStream output(NULL, 0);
713fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void* data;
714fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int size;
715fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  EXPECT_FALSE(output.Next(&data, &size));
716fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
717fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
718fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace
719fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace io
720fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace protobuf
721fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace google
722