~ubuntu-branches/ubuntu/oneiric/mozc/oneiric

« back to all changes in this revision

Viewing changes to protobuf/files/src/google/protobuf/io/zero_copy_stream_unittest.cc

  • Committer: Bazaar Package Importer
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2010-07-14 03:26:47 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100714032647-13qjisj6m8cm8jdx
Tags: 0.12.410.102-1
* New upstream release (Closes: #588971).
  - Add mozc-server, mozc-utils-gui and scim-mozc packages.
* Update debian/rules.
  Add --gypdir option to build_mozc.py.
* Update debian/control.
  - Bumped standards-version to 3.9.0.
  - Update description.
* Add mozc icon (Closes: #588972).
* Add patch which revises issue 18.
  ibus_mozc_issue18.patch
* kFreeBSD build support.
  support_kfreebsd.patch

Show diffs side-by-side

added added

removed removed

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