1 #include <stdlib.h>
2 #include <unistd.h>
3
4 #include <gtest/gtest.h>
5
6 #include <vector>
7 #include <iostream>
8 #include <fstream>
9 #include <sstream>
10 #include <stdexcept>
11
12 #include <jellyfish/err.hpp>
13 #include <jellyfish/misc.hpp>
14 #include <jellyfish/stream_iterator.hpp>
15
16 namespace {
17 namespace err = jellyfish::err;
18
19 typedef std::vector<const char*> path_vector;
20 typedef path_vector::const_iterator path_iterator;
21 typedef jellyfish::stream_iterator<path_iterator> stream_iterator;
22
23 class StreamIterator : public ::testing::Test {
24 protected:
25 static path_vector paths;
26 static int total_lines;
27 static char* tmpdir;
28
SetUpTestCase()29 static void SetUpTestCase() {
30 tmpdir = strdup("/tmp/stream_iterator_XXXXXX");
31 if(!mkdtemp(tmpdir))
32 throw std::runtime_error(err::msg() << "Failed to create tmp directory: " << err::no);
33
34 int nb_files = jellyfish::random_bits(5);
35 for(int i = 0; i < nb_files; ++i) {
36 std::ostringstream path;
37 path << tmpdir << "/" << i;
38 paths.push_back(strdup(path.str().c_str()));
39 std::ofstream tmp_file(path.str().c_str());
40 if(tmp_file.fail())
41 throw std::runtime_error(err::msg() << "Failed to open file '" << path.str() << "' for writing");
42 int nb_lines = jellyfish::random_bits(6);
43 total_lines += nb_lines;
44 for(int j = 0; j < nb_lines; ++j)
45 tmp_file << "line " << j << "\n";
46 }
47 }
48
TearDownTestCase()49 static void TearDownTestCase() {
50 for(path_iterator it = paths.begin(); it != paths.end(); ++it) {
51 if(unlink(*it) == -1)
52 throw std::runtime_error(err::msg() << "Failed to unlink file '" << *it << ": " << err::no);
53 free((void*)*it);
54 }
55 if(rmdir(tmpdir) == -1)
56 throw std::runtime_error(err::msg() << "Failed to rmdir '" << tmpdir << ": " << err::no);
57 free(tmpdir);
58 }
59 };
60 path_vector StreamIterator::paths;
61 int StreamIterator::total_lines = 0;
62 char* StreamIterator::tmpdir;
63
TEST_F(StreamIterator,Empty)64 TEST_F(StreamIterator, Empty) {
65 stream_iterator sit(paths.begin(), paths.begin());
66 stream_iterator send;
67
68 int nb_files = 0;
69 int nb_lines = 0;
70 for( ; sit != send; ++sit, ++nb_files)
71 for(std::string line; std::getline(*sit, line); ++nb_lines) ;
72
73 EXPECT_EQ(0, nb_files);
74 EXPECT_EQ(0, nb_lines);
75 }
76
77
TEST_F(StreamIterator,RandomFiles)78 TEST_F(StreamIterator, RandomFiles) {
79 SCOPED_TRACE(::testing::Message() << "nb_files:" << paths.size() << " nb_lines:" << total_lines);
80
81 stream_iterator sit(paths.begin(), paths.end());
82 stream_iterator send;
83
84 int nb_files = 0;
85 int nb_lines = 0;
86 for( ; sit != send; ++sit, ++nb_files) {
87 for(std::string line; std::getline(*sit, line); ++nb_lines) ;
88 EXPECT_TRUE(sit->eof());
89 }
90
91 EXPECT_EQ(paths.size(), (size_t)nb_files);
92 EXPECT_EQ(total_lines, nb_lines);
93 }
94 }
95