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