blob: 8d9eb32d8a44423d614fe40c0c29daad33a6339d [file] [log] [blame]
William A. Kennington III9a512c92022-08-12 15:15:55 -07001#include <gtest/gtest.h>
2#include <stdplus/exception.hpp>
3#include <stdplus/fd/gmock.hpp>
4#include <stdplus/fd/line.hpp>
5#include <stdplus/fd/managed.hpp>
6#include <stdplus/fd/ops.hpp>
7#include <stdplus/raw.hpp>
8#include <stdplus/util/cexec.hpp>
9#include <string_view>
10#include <sys/mman.h>
11
12namespace stdplus
13{
14namespace fd
15{
16
17ManagedFd makeMemfd(std::string_view contents)
18{
19 auto fd = ManagedFd(CHECK_ERRNO(memfd_create("test", 0), "memfd_create"));
20 write(fd, contents);
21 lseek(fd, 0, Whence::Set);
22 return fd;
23}
24
25TEST(LineReader, Empty)
26{
27 auto fd = makeMemfd("");
28 LineReader reader(fd);
29 EXPECT_EQ("", *reader.readLine());
30 EXPECT_THROW(reader.readLine(), exception::Eof);
31 EXPECT_THROW(reader.readLine(), exception::Eof);
32}
33
34TEST(LineReader, SingleLine)
35{
36 auto fd = makeMemfd("\n");
37 LineReader reader(fd);
38 EXPECT_EQ("", *reader.readLine());
39 EXPECT_EQ("", *reader.readLine());
40 EXPECT_THROW(reader.readLine(), exception::Eof);
41 EXPECT_THROW(reader.readLine(), exception::Eof);
42}
43
44TEST(LineReader, SomeData)
45{
46 auto fd = makeMemfd("A\nbcd\n\ne");
47 LineReader reader(fd);
48 EXPECT_EQ("A", *reader.readLine());
49 EXPECT_EQ("bcd", *reader.readLine());
50 EXPECT_EQ("", *reader.readLine());
51 EXPECT_EQ("e", *reader.readLine());
52 EXPECT_THROW(reader.readLine(), exception::Eof);
53 EXPECT_THROW(reader.readLine(), exception::Eof);
54}
55
56TEST(LineReader, LargerThanBuf)
57{
58 std::string big(LineReader::buf_size + 10, 'a');
59 auto fd = makeMemfd(std::string("alpha\n") + big + "\ndef");
60 LineReader reader(fd);
61 EXPECT_EQ("alpha", *reader.readLine());
62 EXPECT_EQ(big, *reader.readLine());
63 EXPECT_EQ("def", *reader.readLine());
64 EXPECT_THROW(reader.readLine(), exception::Eof);
65 EXPECT_THROW(reader.readLine(), exception::Eof);
66}
67
68using testing::_;
69
70inline auto readSv(std::string_view s)
71{
72 return [s](std::span<std::byte> buf) {
73 memcpy(buf.data(), s.data(), s.size());
74 return buf.subspan(0, s.size());
75 };
76}
77
78TEST(LineReader, Nonblock)
79{
80 FdMock fd;
81 {
82 testing::InSequence seq;
83 EXPECT_CALL(fd, read(_)).WillOnce(readSv("alph"));
84 EXPECT_CALL(fd, read(_)).WillOnce(readSv({}));
85 EXPECT_CALL(fd, read(_)).WillOnce(readSv("a"));
86 EXPECT_CALL(fd, read(_))
87 .WillRepeatedly(testing::Throw(stdplus::exception::Eof("test")));
88 }
89
90 LineReader reader(fd);
91 EXPECT_EQ(nullptr, reader.readLine());
92 EXPECT_EQ("alpha", *reader.readLine());
93 EXPECT_THROW(reader.readLine(), exception::Eof);
94 EXPECT_THROW(reader.readLine(), exception::Eof);
95}
96
97} // namespace fd
98} // namespace stdplus