1 /* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/core/lib/io/buffered_inputstream.h"
17
18 #include "tensorflow/core/lib/core/status_test_util.h"
19 #include "tensorflow/core/lib/io/random_inputstream.h"
20 #include "tensorflow/core/platform/env.h"
21 #include "tensorflow/core/platform/test.h"
22 #include "tensorflow/core/platform/test_benchmark.h"
23
24 namespace tensorflow {
25 namespace io {
26 namespace {
27
BufferSizes()28 static std::vector<int> BufferSizes() {
29 return {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
30 12, 13, 14, 15, 16, 17, 18, 19, 20, 65536};
31 }
32
33 // This class will only return OutOfRange error once to make sure that
34 // BufferedInputStream is able to cache the error.
35 class ReadOnceInputStream : public InputStreamInterface {
36 public:
ReadOnceInputStream()37 ReadOnceInputStream() : start_(true) {}
38
ReadNBytes(int64_t bytes_to_read,tstring * result)39 virtual Status ReadNBytes(int64_t bytes_to_read, tstring* result) {
40 if (bytes_to_read < 11) {
41 return errors::InvalidArgument("Not reading all bytes: ", bytes_to_read);
42 }
43 if (start_) {
44 *result = "0123456789";
45 start_ = false;
46 return errors::OutOfRange("Out of range.");
47 }
48 return errors::InvalidArgument(
49 "Redudant call to ReadNBytes after an OutOfRange error.");
50 }
51
Tell() const52 int64_t Tell() const override { return start_ ? 0 : 10; }
53
54 // Resets the stream to the beginning.
Reset()55 Status Reset() override {
56 start_ = true;
57 return OkStatus();
58 }
59
60 private:
61 bool start_;
62 };
63
TEST(BufferedInputStream,ReadLine_Empty)64 TEST(BufferedInputStream, ReadLine_Empty) {
65 Env* env = Env::Default();
66 string fname;
67 ASSERT_TRUE(env->LocalTempFilename(&fname));
68 TF_ASSERT_OK(WriteStringToFile(env, fname, ""));
69 std::unique_ptr<RandomAccessFile> file;
70 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
71
72 for (auto buf_size : BufferSizes()) {
73 std::unique_ptr<RandomAccessInputStream> input_stream(
74 new RandomAccessInputStream(file.get()));
75 BufferedInputStream in(input_stream.get(), buf_size);
76 string line;
77 EXPECT_TRUE(errors::IsOutOfRange(in.ReadLine(&line)));
78 }
79 }
80
TEST(BufferedInputStream,ReadLine1)81 TEST(BufferedInputStream, ReadLine1) {
82 Env* env = Env::Default();
83 string fname;
84 ASSERT_TRUE(env->LocalTempFilename(&fname));
85 TF_ASSERT_OK(
86 WriteStringToFile(env, fname, "line one\nline two\nline three\n"));
87 std::unique_ptr<RandomAccessFile> file;
88 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
89
90 for (auto buf_size : BufferSizes()) {
91 std::unique_ptr<RandomAccessInputStream> input_stream(
92 new RandomAccessInputStream(file.get()));
93 BufferedInputStream in(input_stream.get(), buf_size);
94 string line;
95 TF_ASSERT_OK(in.ReadLine(&line));
96 EXPECT_EQ(line, "line one");
97 TF_ASSERT_OK(in.ReadLine(&line));
98 EXPECT_EQ(line, "line two");
99 TF_ASSERT_OK(in.ReadLine(&line));
100 EXPECT_EQ(line, "line three");
101 EXPECT_TRUE(errors::IsOutOfRange(in.ReadLine(&line)));
102 // A second call should also return end of file
103 EXPECT_TRUE(errors::IsOutOfRange(in.ReadLine(&line)));
104 }
105 }
106
TEST(BufferedInputStream,ReadLine_NoTrailingNewLine)107 TEST(BufferedInputStream, ReadLine_NoTrailingNewLine) {
108 Env* env = Env::Default();
109 string fname;
110 ASSERT_TRUE(env->LocalTempFilename(&fname));
111 TF_ASSERT_OK(WriteStringToFile(env, fname, "line one\nline two\nline three"));
112 std::unique_ptr<RandomAccessFile> file;
113 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
114
115 for (auto buf_size : BufferSizes()) {
116 std::unique_ptr<RandomAccessInputStream> input_stream(
117 new RandomAccessInputStream(file.get()));
118 BufferedInputStream in(input_stream.get(), buf_size);
119 string line;
120 TF_ASSERT_OK(in.ReadLine(&line));
121 EXPECT_EQ(line, "line one");
122 TF_ASSERT_OK(in.ReadLine(&line));
123 EXPECT_EQ(line, "line two");
124 TF_ASSERT_OK(in.ReadLine(&line));
125 EXPECT_EQ(line, "line three");
126 EXPECT_TRUE(errors::IsOutOfRange(in.ReadLine(&line)));
127 // A second call should also return end of file
128 EXPECT_TRUE(errors::IsOutOfRange(in.ReadLine(&line)));
129 }
130 }
131
TEST(BufferedInputStream,ReadLine_EmptyLines)132 TEST(BufferedInputStream, ReadLine_EmptyLines) {
133 Env* env = Env::Default();
134 string fname;
135 ASSERT_TRUE(env->LocalTempFilename(&fname));
136 TF_ASSERT_OK(
137 WriteStringToFile(env, fname, "line one\n\n\nline two\nline three"));
138 std::unique_ptr<RandomAccessFile> file;
139 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
140
141 for (auto buf_size : BufferSizes()) {
142 std::unique_ptr<RandomAccessInputStream> input_stream(
143 new RandomAccessInputStream(file.get()));
144 BufferedInputStream in(input_stream.get(), buf_size);
145 string line;
146 TF_ASSERT_OK(in.ReadLine(&line));
147 EXPECT_EQ(line, "line one");
148 TF_ASSERT_OK(in.ReadLine(&line));
149 EXPECT_EQ(line, "");
150 TF_ASSERT_OK(in.ReadLine(&line));
151 EXPECT_EQ(line, "");
152 TF_ASSERT_OK(in.ReadLine(&line));
153 EXPECT_EQ(line, "line two");
154 TF_ASSERT_OK(in.ReadLine(&line));
155 EXPECT_EQ(line, "line three");
156 EXPECT_TRUE(errors::IsOutOfRange(in.ReadLine(&line)));
157 // A second call should also return end of file
158 EXPECT_TRUE(errors::IsOutOfRange(in.ReadLine(&line)));
159 }
160 }
161
TEST(BufferedInputStream,ReadLine_CRLF)162 TEST(BufferedInputStream, ReadLine_CRLF) {
163 Env* env = Env::Default();
164 string fname;
165 ASSERT_TRUE(env->LocalTempFilename(&fname));
166 TF_ASSERT_OK(WriteStringToFile(env, fname,
167 "line one\r\n\r\n\r\nline two\r\nline three"));
168 std::unique_ptr<RandomAccessFile> file;
169 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
170
171 for (auto buf_size : BufferSizes()) {
172 std::unique_ptr<RandomAccessInputStream> input_stream(
173 new RandomAccessInputStream(file.get()));
174 BufferedInputStream in(input_stream.get(), buf_size);
175 string line;
176 TF_ASSERT_OK(in.ReadLine(&line));
177 EXPECT_EQ(line, "line one");
178 TF_ASSERT_OK(in.ReadLine(&line));
179 EXPECT_EQ(line, "");
180 TF_ASSERT_OK(in.ReadLine(&line));
181 EXPECT_EQ(line, "");
182 TF_ASSERT_OK(in.ReadLine(&line));
183 EXPECT_EQ(line, "line two");
184 TF_ASSERT_OK(in.ReadLine(&line));
185 EXPECT_EQ(line, "line three");
186 EXPECT_TRUE(errors::IsOutOfRange(in.ReadLine(&line)));
187 // A second call should also return end of file
188 EXPECT_TRUE(errors::IsOutOfRange(in.ReadLine(&line)));
189 }
190 }
191
TEST(BufferedInputStream,SkipLine1)192 TEST(BufferedInputStream, SkipLine1) {
193 Env* env = Env::Default();
194 string fname;
195 ASSERT_TRUE(env->LocalTempFilename(&fname));
196 TF_ASSERT_OK(
197 WriteStringToFile(env, fname, "line one\nline two\nline three\n"));
198 std::unique_ptr<RandomAccessFile> file;
199 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
200
201 for (auto buf_size : BufferSizes()) {
202 std::unique_ptr<RandomAccessInputStream> input_stream(
203 new RandomAccessInputStream(file.get()));
204 BufferedInputStream in(input_stream.get(), buf_size);
205 string line;
206 TF_ASSERT_OK(in.SkipLine());
207 TF_ASSERT_OK(in.ReadLine(&line));
208 EXPECT_EQ(line, "line two");
209 TF_ASSERT_OK(in.SkipLine());
210 EXPECT_TRUE(errors::IsOutOfRange(in.SkipLine()));
211 // A second call should also return end of file
212 EXPECT_TRUE(errors::IsOutOfRange(in.SkipLine()));
213 }
214 }
215
TEST(BufferedInputStream,SkipLine_NoTrailingNewLine)216 TEST(BufferedInputStream, SkipLine_NoTrailingNewLine) {
217 Env* env = Env::Default();
218 string fname;
219 ASSERT_TRUE(env->LocalTempFilename(&fname));
220 TF_ASSERT_OK(WriteStringToFile(env, fname, "line one\nline two\nline three"));
221 std::unique_ptr<RandomAccessFile> file;
222 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
223
224 for (auto buf_size : BufferSizes()) {
225 std::unique_ptr<RandomAccessInputStream> input_stream(
226 new RandomAccessInputStream(file.get()));
227 BufferedInputStream in(input_stream.get(), buf_size);
228 string line;
229 TF_ASSERT_OK(in.SkipLine());
230 TF_ASSERT_OK(in.ReadLine(&line));
231 EXPECT_EQ(line, "line two");
232 TF_ASSERT_OK(in.SkipLine());
233 EXPECT_TRUE(errors::IsOutOfRange(in.SkipLine()));
234 // A second call should also return end of file
235 EXPECT_TRUE(errors::IsOutOfRange(in.SkipLine()));
236 }
237 }
238
TEST(BufferedInputStream,SkipLine_EmptyLines)239 TEST(BufferedInputStream, SkipLine_EmptyLines) {
240 Env* env = Env::Default();
241 string fname;
242 ASSERT_TRUE(env->LocalTempFilename(&fname));
243 TF_ASSERT_OK(WriteStringToFile(env, fname, "line one\n\n\nline two"));
244 std::unique_ptr<RandomAccessFile> file;
245 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
246
247 for (auto buf_size : BufferSizes()) {
248 std::unique_ptr<RandomAccessInputStream> input_stream(
249 new RandomAccessInputStream(file.get()));
250 BufferedInputStream in(input_stream.get(), buf_size);
251 string line;
252 TF_ASSERT_OK(in.SkipLine());
253 TF_ASSERT_OK(in.ReadLine(&line));
254 EXPECT_EQ(line, "");
255 TF_ASSERT_OK(in.SkipLine());
256 TF_ASSERT_OK(in.ReadLine(&line));
257 EXPECT_EQ(line, "line two");
258 }
259 }
260
TEST(BufferedInputStream,ReadNBytes)261 TEST(BufferedInputStream, ReadNBytes) {
262 Env* env = Env::Default();
263 string fname;
264 ASSERT_TRUE(env->LocalTempFilename(&fname));
265 TF_ASSERT_OK(WriteStringToFile(env, fname, "0123456789"));
266 std::unique_ptr<RandomAccessFile> file;
267 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
268
269 for (auto buf_size : BufferSizes()) {
270 std::unique_ptr<RandomAccessInputStream> input_stream(
271 new RandomAccessInputStream(file.get()));
272 tstring read;
273 BufferedInputStream in(input_stream.get(), buf_size);
274 EXPECT_EQ(0, in.Tell());
275 TF_ASSERT_OK(in.ReadNBytes(3, &read));
276 EXPECT_EQ(read, "012");
277 EXPECT_EQ(3, in.Tell());
278 TF_ASSERT_OK(in.ReadNBytes(0, &read));
279 EXPECT_EQ(read, "");
280 EXPECT_EQ(3, in.Tell());
281 TF_ASSERT_OK(in.ReadNBytes(4, &read));
282 EXPECT_EQ(read, "3456");
283 EXPECT_EQ(7, in.Tell());
284 TF_ASSERT_OK(in.ReadNBytes(0, &read));
285 EXPECT_EQ(read, "");
286 EXPECT_EQ(7, in.Tell());
287 EXPECT_TRUE(errors::IsOutOfRange(in.ReadNBytes(5, &read)));
288 EXPECT_EQ(read, "789");
289 EXPECT_EQ(10, in.Tell());
290 EXPECT_TRUE(errors::IsOutOfRange(in.ReadNBytes(5, &read)));
291 EXPECT_EQ(read, "");
292 EXPECT_EQ(10, in.Tell());
293 TF_ASSERT_OK(in.ReadNBytes(0, &read));
294 EXPECT_EQ(read, "");
295 EXPECT_EQ(10, in.Tell());
296 }
297 }
298
TEST(BufferedInputStream,OutOfRangeCache)299 TEST(BufferedInputStream, OutOfRangeCache) {
300 for (auto buf_size : BufferSizes()) {
301 if (buf_size < 11) {
302 continue;
303 }
304 ReadOnceInputStream input_stream;
305 tstring read;
306 BufferedInputStream in(&input_stream, buf_size);
307 EXPECT_EQ(0, in.Tell());
308 TF_ASSERT_OK(in.ReadNBytes(3, &read));
309 EXPECT_EQ(read, "012");
310 EXPECT_EQ(3, in.Tell());
311 TF_ASSERT_OK((in.ReadNBytes(7, &read)));
312 EXPECT_EQ(read, "3456789");
313 EXPECT_EQ(10, in.Tell());
314 Status s = in.ReadNBytes(5, &read);
315 // Make sure the read is failing with OUT_OF_RANGE error. If it is failing
316 // with other errors, it is not caching the OUT_OF_RANGE properly.
317 EXPECT_EQ(error::OUT_OF_RANGE, s.code()) << s;
318 EXPECT_EQ(read, "");
319 // Empty read shouldn't cause an error even at the end of the file.
320 TF_ASSERT_OK(in.ReadNBytes(0, &read));
321 EXPECT_EQ(read, "");
322 }
323 }
324
TEST(BufferedInputStream,SkipNBytes)325 TEST(BufferedInputStream, SkipNBytes) {
326 Env* env = Env::Default();
327 string fname;
328 ASSERT_TRUE(env->LocalTempFilename(&fname));
329 TF_ASSERT_OK(WriteStringToFile(env, fname, "0123456789"));
330 std::unique_ptr<RandomAccessFile> file;
331 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
332
333 for (auto buf_size : BufferSizes()) {
334 std::unique_ptr<RandomAccessInputStream> input_stream(
335 new RandomAccessInputStream(file.get()));
336 tstring read;
337 BufferedInputStream in(input_stream.get(), buf_size);
338 EXPECT_EQ(0, in.Tell());
339 TF_ASSERT_OK(in.SkipNBytes(3));
340 EXPECT_EQ(3, in.Tell());
341 TF_ASSERT_OK(in.SkipNBytes(0));
342 EXPECT_EQ(3, in.Tell());
343 TF_ASSERT_OK(in.ReadNBytes(2, &read));
344 EXPECT_EQ(read, "34");
345 EXPECT_EQ(5, in.Tell());
346 TF_ASSERT_OK(in.SkipNBytes(0));
347 EXPECT_EQ(5, in.Tell());
348 TF_ASSERT_OK(in.SkipNBytes(2));
349 EXPECT_EQ(7, in.Tell());
350 TF_ASSERT_OK(in.ReadNBytes(1, &read));
351 EXPECT_EQ(read, "7");
352 EXPECT_EQ(8, in.Tell());
353 EXPECT_TRUE(errors::IsOutOfRange(in.SkipNBytes(5)));
354 EXPECT_EQ(10, in.Tell());
355 EXPECT_TRUE(errors::IsOutOfRange(in.SkipNBytes(5)));
356 EXPECT_EQ(10, in.Tell());
357 EXPECT_TRUE(errors::IsOutOfRange(in.ReadNBytes(5, &read)));
358 EXPECT_EQ(read, "");
359 EXPECT_EQ(10, in.Tell());
360 }
361 }
362
TEST(BufferedInputStream,ReadNBytesRandomAccessFile)363 TEST(BufferedInputStream, ReadNBytesRandomAccessFile) {
364 Env* env = Env::Default();
365 string fname;
366 ASSERT_TRUE(env->LocalTempFilename(&fname));
367 TF_ASSERT_OK(WriteStringToFile(env, fname, "0123456789"));
368 std::unique_ptr<RandomAccessFile> file;
369 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
370
371 for (auto buf_size : BufferSizes()) {
372 tstring read;
373 BufferedInputStream in(file.get(), buf_size);
374 EXPECT_EQ(0, in.Tell());
375 TF_ASSERT_OK(in.ReadNBytes(3, &read));
376 EXPECT_EQ(read, "012");
377 EXPECT_EQ(3, in.Tell());
378 TF_ASSERT_OK(in.ReadNBytes(0, &read));
379 EXPECT_EQ(read, "");
380 EXPECT_EQ(3, in.Tell());
381 TF_ASSERT_OK(in.ReadNBytes(4, &read));
382 EXPECT_EQ(read, "3456");
383 EXPECT_EQ(7, in.Tell());
384 TF_ASSERT_OK(in.ReadNBytes(0, &read));
385 EXPECT_EQ(read, "");
386 EXPECT_EQ(7, in.Tell());
387 EXPECT_TRUE(errors::IsOutOfRange(in.ReadNBytes(5, &read)));
388 EXPECT_EQ(read, "789");
389 EXPECT_EQ(10, in.Tell());
390 EXPECT_TRUE(errors::IsOutOfRange(in.ReadNBytes(5, &read)));
391 EXPECT_EQ(read, "");
392 EXPECT_EQ(10, in.Tell());
393 TF_ASSERT_OK(in.ReadNBytes(0, &read));
394 EXPECT_EQ(read, "");
395 EXPECT_EQ(10, in.Tell());
396 }
397 }
398
TEST(BufferedInputStream,SkipNBytesRandomAccessFile)399 TEST(BufferedInputStream, SkipNBytesRandomAccessFile) {
400 Env* env = Env::Default();
401 string fname;
402 ASSERT_TRUE(env->LocalTempFilename(&fname));
403 TF_ASSERT_OK(WriteStringToFile(env, fname, "0123456789"));
404 std::unique_ptr<RandomAccessFile> file;
405 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
406
407 for (auto buf_size : BufferSizes()) {
408 tstring read;
409 BufferedInputStream in(file.get(), buf_size);
410 EXPECT_EQ(0, in.Tell());
411 TF_ASSERT_OK(in.SkipNBytes(3));
412 EXPECT_EQ(3, in.Tell());
413 TF_ASSERT_OK(in.SkipNBytes(0));
414 EXPECT_EQ(3, in.Tell());
415 TF_ASSERT_OK(in.ReadNBytes(2, &read));
416 EXPECT_EQ(read, "34");
417 EXPECT_EQ(5, in.Tell());
418 TF_ASSERT_OK(in.SkipNBytes(0));
419 EXPECT_EQ(5, in.Tell());
420 TF_ASSERT_OK(in.SkipNBytes(2));
421 EXPECT_EQ(7, in.Tell());
422 TF_ASSERT_OK(in.ReadNBytes(1, &read));
423 EXPECT_EQ(read, "7");
424 EXPECT_EQ(8, in.Tell());
425 EXPECT_TRUE(errors::IsOutOfRange(in.SkipNBytes(5)));
426 EXPECT_EQ(10, in.Tell());
427 EXPECT_TRUE(errors::IsOutOfRange(in.SkipNBytes(5)));
428 EXPECT_EQ(10, in.Tell());
429 EXPECT_TRUE(errors::IsOutOfRange(in.ReadNBytes(5, &read)));
430 EXPECT_EQ(read, "");
431 EXPECT_EQ(10, in.Tell());
432 }
433 }
434
TEST(BufferedInputStream,Seek)435 TEST(BufferedInputStream, Seek) {
436 Env* env = Env::Default();
437 string fname;
438 ASSERT_TRUE(env->LocalTempFilename(&fname));
439 TF_ASSERT_OK(WriteStringToFile(env, fname, "0123456789"));
440 std::unique_ptr<RandomAccessFile> file;
441 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
442
443 for (auto buf_size : BufferSizes()) {
444 std::unique_ptr<RandomAccessInputStream> input_stream(
445 new RandomAccessInputStream(file.get()));
446 tstring read;
447 BufferedInputStream in(input_stream.get(), buf_size);
448
449 // Seek forward
450 TF_ASSERT_OK(in.Seek(3));
451 EXPECT_EQ(3, in.Tell());
452
453 // Read 4 bytes
454 TF_ASSERT_OK(in.ReadNBytes(4, &read));
455 EXPECT_EQ(read, "3456");
456 EXPECT_EQ(7, in.Tell());
457
458 // Seek backwards
459 TF_ASSERT_OK(in.Seek(1));
460 TF_ASSERT_OK(in.ReadNBytes(4, &read));
461 EXPECT_EQ(read, "1234");
462 EXPECT_EQ(5, in.Tell());
463 }
464 }
465
TEST(BufferedInputStream,Seek_NotReset)466 TEST(BufferedInputStream, Seek_NotReset) {
467 // This test verifies seek backwards within the buffer doesn't reset
468 // input_stream
469 Env* env = Env::Default();
470 string fname;
471 ASSERT_TRUE(env->LocalTempFilename(&fname));
472 TF_ASSERT_OK(WriteStringToFile(env, fname, "0123456789"));
473 std::unique_ptr<RandomAccessFile> file;
474 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
475
476 std::unique_ptr<RandomAccessInputStream> input_stream(
477 new RandomAccessInputStream(file.get()));
478 tstring read;
479 BufferedInputStream in(input_stream.get(), 3);
480
481 TF_ASSERT_OK(in.ReadNBytes(4, &read));
482 int before_tell = input_stream.get()->Tell();
483 EXPECT_EQ(before_tell, 6);
484 // Seek backwards
485 TF_ASSERT_OK(in.Seek(3));
486 int after_tell = input_stream.get()->Tell();
487 EXPECT_EQ(before_tell, after_tell);
488 }
489
TEST(BufferedInputStream,ReadAll_Empty)490 TEST(BufferedInputStream, ReadAll_Empty) {
491 Env* env = Env::Default();
492 string fname;
493 ASSERT_TRUE(env->LocalTempFilename(&fname));
494 const string expected = "";
495 TF_ASSERT_OK(WriteStringToFile(env, fname, expected));
496 std::unique_ptr<RandomAccessFile> file;
497 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
498
499 for (auto buf_size : BufferSizes()) {
500 RandomAccessInputStream input_stream(file.get());
501 BufferedInputStream in(&input_stream, buf_size);
502 string contents;
503 TF_ASSERT_OK(in.ReadAll(&contents));
504 EXPECT_EQ(expected, contents);
505 }
506 }
507
TEST(BufferedInputStream,ReadAll_Text)508 TEST(BufferedInputStream, ReadAll_Text) {
509 Env* env = Env::Default();
510 string fname;
511 ASSERT_TRUE(env->LocalTempFilename(&fname));
512 const string expected = "line one\nline two\nline three";
513 TF_ASSERT_OK(WriteStringToFile(env, fname, expected));
514 std::unique_ptr<RandomAccessFile> file;
515 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
516
517 for (auto buf_size : BufferSizes()) {
518 RandomAccessInputStream input_stream(file.get());
519 BufferedInputStream in(&input_stream, buf_size);
520 string contents;
521 TF_ASSERT_OK(in.ReadAll(&contents));
522 EXPECT_EQ(expected, contents);
523 }
524 }
525
BM_BufferedReaderSmallReads(::testing::benchmark::State & state)526 void BM_BufferedReaderSmallReads(::testing::benchmark::State& state) {
527 const int buff_size = state.range(0);
528 const int file_size = state.range(1);
529 Env* env = Env::Default();
530 string fname;
531 ASSERT_TRUE(env->LocalTempFilename(&fname));
532
533 const string file_elem = "0123456789";
534 std::unique_ptr<WritableFile> write_file;
535 TF_ASSERT_OK(env->NewWritableFile(fname, &write_file));
536 for (int i = 0; i < file_size; ++i) {
537 TF_ASSERT_OK(write_file->Append(file_elem));
538 }
539 TF_ASSERT_OK(write_file->Close());
540
541 std::unique_ptr<RandomAccessFile> file;
542 TF_ASSERT_OK(env->NewRandomAccessFile(fname, &file));
543
544 tstring result;
545
546 int itr = 0;
547 for (auto s : state) {
548 BufferedInputStream in(file.get(), buff_size);
549 for (int64_t i = 0; i < 10 * file_size; ++i) {
550 TF_ASSERT_OK(in.ReadNBytes(1, &result))
551 << "i: " << i << " itr: " << itr << " buff_size: " << buff_size
552 << " file size: " << file_size;
553 }
554 ++itr;
555 }
556 }
557 BENCHMARK(BM_BufferedReaderSmallReads)
558 ->ArgPair(1, 5)
559 ->ArgPair(1, 1024)
560 ->ArgPair(10, 5)
561 ->ArgPair(10, 1024)
562 ->ArgPair(1024, 1024)
563 ->ArgPair(1024 * 1024, 1024)
564 ->ArgPair(1024 * 1024, 1024 * 1024)
565 ->ArgPair(256 * 1024 * 1024, 1024);
566
567 } // anonymous namespace
568 } // namespace io
569 } // namespace tensorflow
570