blob: 3fc511c05cad785f9b232ff1f9d9905230cce0c2 [file] [log] [blame]
William A. Kennington III93ae9702023-12-22 16:41:17 -08001#include "util.hpp"
2
3#include <stdplus/exception.hpp>
4#include <stdplus/fd/gmock.hpp>
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07005#include <stdplus/fd/ops.hpp>
William A. Kennington III93ae9702023-12-22 16:41:17 -08006#include <stdplus/numeric/endian.hpp>
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07007
Patrick Williamsd1984dd2023-05-10 16:12:44 -05008#include <gtest/gtest.h>
9
William A. Kennington III93ae9702023-12-22 16:41:17 -080010namespace stdplus::fd
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070011{
William A. Kennington III93ae9702023-12-22 16:41:17 -080012
13using testing::_;
14using testing::Ge;
15using testing::SizeIs;
16using std::literals::string_view_literals::operator""sv;
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070017
18TEST(Flags, Flags)
19{
20 FdFlags f = FdFlags(0).set(FdFlag::CloseOnExec).unset(FdFlag::CloseOnExec);
21 f.set(FdFlag::CloseOnExec).unset(FdFlag::CloseOnExec);
22 EXPECT_EQ(0, static_cast<int>(f));
23}
24
William A. Kennington III1786e9a2023-12-17 23:23:33 -080025TEST(Connect, Success)
26{
27 testing::StrictMock<FdMock> fd;
28 SockAddrBuf buf;
29 EXPECT_CALL(fd, connect(_)).WillOnce([&](std::span<const std::byte> addr) {
30 std::copy(addr.begin(), addr.end(), reinterpret_cast<std::byte*>(&buf));
31 buf.len = addr.size();
32 });
33 Sock6Addr addr(In6Addr{0xff}, 365, 0);
34 connect(fd, addr);
35 EXPECT_EQ(Sock6Addr::fromBuf(buf), addr);
36}
37
William A. Kennington III93ae9702023-12-22 16:41:17 -080038TEST(ReadExact, Success)
39{
40 testing::StrictMock<FdMock> fd;
41 {
42 testing::InSequence seq;
43 EXPECT_CALL(fd, read(SizeIs(Ge(4)))).WillOnce(readSv("alph"));
44 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("a "));
45 EXPECT_CALL(fd, read(SizeIs(Ge(3)))).WillOnce(readSv("one"));
46 }
47 char buf[9];
48 readExact(fd, buf);
49 EXPECT_EQ(std::string_view(buf, sizeof(buf)), "alpha one");
50}
51
52TEST(ReadExact, NotEnoughEof)
53{
54 testing::StrictMock<FdMock> fd;
55 {
56 testing::InSequence seq;
57 EXPECT_CALL(fd, read(_)).WillOnce(readSv("alph"));
58 EXPECT_CALL(fd, read(_)).WillOnce(readSv("a "));
59 EXPECT_CALL(fd, read(_))
60 .WillRepeatedly(testing::Throw(exception::Eof("test")));
61 }
62 char buf[9];
63 EXPECT_THROW(readExact(fd, buf), exception::Incomplete);
64 EXPECT_THROW(readExact(fd, buf), exception::Eof);
65}
66
67TEST(ReadExact, NotEnoughBlock)
68{
69 testing::StrictMock<FdMock> fd;
70 {
71 testing::InSequence seq;
72 EXPECT_CALL(fd, read(_)).WillOnce(readSv("alph"));
73 EXPECT_CALL(fd, read(_)).WillOnce(readSv("a "));
74 EXPECT_CALL(fd, read(_)).WillRepeatedly(readSv(""));
75 }
76 char buf[9];
77 EXPECT_THROW(readExact(fd, buf), exception::Incomplete);
78 EXPECT_THROW(readExact(fd, buf), exception::WouldBlock);
79}
80
81TEST(ReadExact, NotEnoughBlockInt)
82{
83 testing::StrictMock<FdMock> fd;
84 {
85 testing::InSequence seq;
86 EXPECT_CALL(fd, read(_)).WillOnce(readSv("\0\0\0"sv));
87 EXPECT_CALL(fd, read(_)).WillRepeatedly(readSv(""));
88 }
89 int32_t i;
90 EXPECT_THROW(readExact(fd, i), exception::Incomplete);
91 EXPECT_THROW(readExact(fd, i), exception::WouldBlock);
92}
93
94TEST(ReadExact, EnoughInt)
95{
96 testing::StrictMock<FdMock> fd;
97 {
98 testing::InSequence seq;
99 EXPECT_CALL(fd, read(_)).WillOnce(readSv("\0\0\0\0"sv));
100 EXPECT_CALL(fd, read(_)).WillOnce(readSv("\x01\x02"sv));
101 EXPECT_CALL(fd, read(_)).WillOnce(readSv("\x03\x04"sv));
102 }
103 int32_t i;
104 readExact(fd, i);
105 EXPECT_EQ(i, 0);
106 readExact(fd, i);
107 EXPECT_EQ(ntoh(i), 0x01020304);
108}
109
William A. Kennington IIIb88c4572023-12-22 16:43:42 -0800110TEST(Read, Success)
111{
112 testing::StrictMock<FdMock> fd;
113 {
114 testing::InSequence seq;
115 EXPECT_CALL(fd, read(_)).WillOnce(readSv("alph"));
116 EXPECT_CALL(fd, read(_)).WillOnce(readSv("one"));
117 EXPECT_CALL(fd, read(_)).WillOnce(readSv(""));
118 }
119 char buf[15];
120 auto res = read(fd, buf);
121 EXPECT_EQ(std::string_view(res.begin(), res.end()), "alph");
122 res = read(fd, buf);
123 EXPECT_EQ(std::string_view(res.begin(), res.end()), "one");
124 EXPECT_TRUE(read(fd, buf).empty());
125}
126
127TEST(Read, NotEnoughInt)
128{
129 testing::StrictMock<FdMock> fd;
130 {
131 testing::InSequence seq;
132 EXPECT_CALL(fd, read(_)).WillOnce(readSv("\0\0\0"sv));
133 EXPECT_CALL(fd, read(_)).WillRepeatedly(readSv(""));
134 }
135 std::array<int32_t, 1> i;
136 EXPECT_THROW(read(fd, i), exception::Incomplete);
137 EXPECT_TRUE(read(fd, i).empty());
138}
139
140TEST(Read, NotEnoughEofInt)
141{
142 testing::StrictMock<FdMock> fd;
143 {
144 testing::InSequence seq;
145 EXPECT_CALL(fd, read(_)).WillOnce(readSv("\0\0\0"sv));
146 EXPECT_CALL(fd, read(_))
147 .WillRepeatedly(testing::Throw(exception::Eof("test")));
148 }
149 std::array<int32_t, 1> i;
150 EXPECT_THROW(read(fd, i), exception::Incomplete);
151 EXPECT_THROW(read(fd, i), exception::Eof);
152}
153
154TEST(Read, EnoughInt)
155{
156 testing::StrictMock<FdMock> fd;
157 {
158 testing::InSequence seq;
159 EXPECT_CALL(fd, read(_)).WillOnce(readSv("\0\0\0\0"sv));
160 EXPECT_CALL(fd, read(_)).WillOnce(readSv("\x01\x02"sv));
161 EXPECT_CALL(fd, read(_)).WillOnce(readSv("\x03\x04"sv));
162 }
163 std::array<int32_t, 1> i;
164 read(fd, i);
165 EXPECT_EQ(i[0], 0);
166 read(fd, i);
167 EXPECT_EQ(stdplus::ntoh(i[0]), 0x01020304);
168}
169
William A. Kennington IIId589b1b2023-12-24 10:39:30 -0800170TEST(ReadAll, SuccessEmpty)
171{
172 testing::StrictMock<FdMock> fd;
173 {
174 testing::InSequence seq;
175 EXPECT_CALL(fd, read(_))
176 .WillRepeatedly(testing::Throw(exception::Eof("test")));
177 }
178 EXPECT_EQ(readAll<std::string>(fd), "");
179}
180
181TEST(ReadAll, Success)
182{
183 testing::StrictMock<FdMock> fd;
184 {
185 testing::InSequence seq;
186 EXPECT_CALL(fd, read(SizeIs(Ge(4)))).WillOnce(readSv("alph"));
187 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("a "));
188 EXPECT_CALL(fd, read(SizeIs(Ge(3)))).WillOnce(readSv("one"));
189 EXPECT_CALL(fd, read(_))
190 .WillRepeatedly(testing::Throw(exception::Eof("test")));
191 }
192 EXPECT_EQ(readAll<std::string>(fd), "alpha one");
193}
194
195TEST(ReadAll, Block)
196{
197 testing::StrictMock<FdMock> fd;
198 {
199 testing::InSequence seq;
200 EXPECT_CALL(fd, read(SizeIs(Ge(4)))).WillOnce(readSv("alph"));
201 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("a "));
202 EXPECT_CALL(fd, read(_)).WillRepeatedly(readSv(""));
203 }
204 EXPECT_THROW(readAll<std::string>(fd), exception::WouldBlock);
205}
206
207TEST(ReadAll, NotEnough)
208{
209 testing::StrictMock<FdMock> fd;
210 {
211 testing::InSequence seq;
212 EXPECT_CALL(fd, read(SizeIs(Ge(5))))
213 .WillOnce(readSv("\x01\x02\x03\x04\x05"));
214 EXPECT_CALL(fd, read(SizeIs(Ge(1)))).WillOnce(readSv("\x06"));
215 EXPECT_CALL(fd, read(_)).WillRepeatedly(readSv(""));
216 }
217 EXPECT_THROW(readAll<std::vector<int32_t>>(fd), exception::Incomplete);
218}
219
220TEST(ReadAll, NotEnoughEof)
221{
222 testing::StrictMock<FdMock> fd;
223 {
224 testing::InSequence seq;
225 EXPECT_CALL(fd, read(SizeIs(Ge(5))))
226 .WillOnce(readSv("\x01\x02\x03\x04\x05"));
227 EXPECT_CALL(fd, read(SizeIs(Ge(1)))).WillOnce(readSv("\x06"));
228 EXPECT_CALL(fd, read(_))
229 .WillRepeatedly(testing::Throw(exception::Eof("test")));
230 }
231 EXPECT_THROW(readAll<std::vector<int32_t>>(fd), exception::Incomplete);
232}
233
234TEST(ReadAll, EnoughInt)
235{
236 testing::StrictMock<FdMock> fd;
237 {
238 testing::InSequence seq;
239 EXPECT_CALL(fd, read(SizeIs(Ge(5))))
240 .WillOnce(readSv("\x01\x02\x03\x04\x05"));
241 EXPECT_CALL(fd, read(SizeIs(Ge(1)))).WillOnce(readSv("\x06"));
242 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("\x07\x08"));
243 EXPECT_CALL(fd, read(_))
244 .WillRepeatedly(testing::Throw(exception::Eof("test")));
245 }
246 EXPECT_EQ(readAll<std::vector<int32_t>>(fd),
247 (std::vector{stdplus::hton(int32_t{0x01020304}),
248 stdplus::hton(int32_t{0x05060708})}));
249}
250
William A. Kennington III4829c9d2023-12-24 10:39:43 -0800251TEST(ReadAllFixed, SuccessEmpty)
252{
253 testing::StrictMock<FdMock> fd;
254 {
255 testing::InSequence seq;
256 EXPECT_CALL(fd, read(_))
257 .WillRepeatedly(testing::Throw(exception::Eof("test")));
258 }
259 std::array<char, 16> buf;
260 auto ret = readAllFixed(fd, buf);
261 EXPECT_EQ(std::string_view(ret.begin(), ret.end()), "");
262}
263
264TEST(ReadAllFixed, Success)
265{
266 testing::StrictMock<FdMock> fd;
267 {
268 testing::InSequence seq;
269 EXPECT_CALL(fd, read(SizeIs(Ge(4)))).WillOnce(readSv("alph"));
270 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("a "));
271 EXPECT_CALL(fd, read(SizeIs(Ge(3)))).WillOnce(readSv("one"));
272 EXPECT_CALL(fd, read(_))
273 .WillRepeatedly(testing::Throw(exception::Eof("test")));
274 }
275 std::array<char, 16> buf;
276 auto ret = readAllFixed(fd, buf);
277 EXPECT_EQ(std::string_view(ret.begin(), ret.end()), "alpha one");
278}
279
280TEST(ReadAllFixed, Block)
281{
282 testing::StrictMock<FdMock> fd;
283 {
284 testing::InSequence seq;
285 EXPECT_CALL(fd, read(SizeIs(Ge(4)))).WillOnce(readSv("alph"));
286 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("a "));
287 EXPECT_CALL(fd, read(_)).WillRepeatedly(readSv(""));
288 }
289 std::array<char, 16> buf;
290 EXPECT_THROW(readAllFixed(fd, buf), exception::WouldBlock);
291}
292
293TEST(ReadAllFixed, NotEnough)
294{
295 testing::StrictMock<FdMock> fd;
296 {
297 testing::InSequence seq;
298 EXPECT_CALL(fd, read(SizeIs(Ge(5))))
299 .WillOnce(readSv("\x01\x02\x03\x04\x05"));
300 EXPECT_CALL(fd, read(SizeIs(Ge(1)))).WillOnce(readSv("\x06"));
301 EXPECT_CALL(fd, read(_)).WillRepeatedly(readSv(""));
302 }
303 std::array<int32_t, 2> buf;
304 EXPECT_THROW(readAllFixed(fd, buf), exception::Incomplete);
305}
306
307TEST(ReadAllFixed, NotEnoughEof)
308{
309 testing::StrictMock<FdMock> fd;
310 {
311 testing::InSequence seq;
312 EXPECT_CALL(fd, read(SizeIs(Ge(5))))
313 .WillOnce(readSv("\x01\x02\x03\x04\x05"));
314 EXPECT_CALL(fd, read(SizeIs(Ge(1)))).WillOnce(readSv("\x06"));
315 EXPECT_CALL(fd, read(_))
316 .WillRepeatedly(testing::Throw(exception::Eof("test")));
317 }
318 std::array<int32_t, 2> buf;
319 EXPECT_THROW(readAllFixed(fd, buf), exception::Incomplete);
320}
321
322TEST(ReadAllFixed, EnoughInt)
323{
324 testing::StrictMock<FdMock> fd;
325 {
326 testing::InSequence seq;
327 EXPECT_CALL(fd, read(SizeIs(Ge(5))))
328 .WillOnce(readSv("\x01\x02\x03\x04\x05"));
329 EXPECT_CALL(fd, read(SizeIs(Ge(1)))).WillOnce(readSv("\x06"));
330 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("\x07\x08"));
331 EXPECT_CALL(fd, read(_))
332 .WillRepeatedly(testing::Throw(exception::Eof("test")));
333 }
334 std::array<int32_t, 2> buf;
335 EXPECT_THAT(readAllFixed(fd, buf),
336 testing::ElementsAre(stdplus::hton(int32_t{0x01020304}),
337 stdplus::hton(int32_t{0x05060708})));
338}
339
340TEST(ReadAllFixed, TooMuch)
341{
342 testing::StrictMock<FdMock> fd;
343 {
344 testing::InSequence seq;
345 EXPECT_CALL(fd, read(SizeIs(Ge(5))))
346 .WillOnce(readSv("\x01\x02\x03\x04\x05"));
347 EXPECT_CALL(fd, read(SizeIs(Ge(1)))).WillOnce(readSv("\x06"));
348 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("\x07\x08"));
349 EXPECT_CALL(fd, read(SizeIs(Ge(1)))).WillOnce(readSv("\x09"));
350 }
351 std::array<int32_t, 2> buf;
352 EXPECT_THROW(readAllFixed(fd, buf), std::system_error);
353}
354
William A. Kennington III4aec6d12024-01-08 15:28:34 -0800355TEST(ReadAllExact, FailEmpty)
356{
357 testing::StrictMock<FdMock> fd;
358 {
359 testing::InSequence seq;
360 EXPECT_CALL(fd, read(_))
361 .WillRepeatedly(testing::Throw(exception::Eof("test")));
362 }
363 std::array<char, 16> buf;
364 EXPECT_THROW(readAllExact(fd, buf), std::system_error);
365}
366
367TEST(ReadAllExact, FailPartial)
368{
369 testing::StrictMock<FdMock> fd;
370 {
371 testing::InSequence seq;
372 EXPECT_CALL(fd, read(SizeIs(Ge(4)))).WillOnce(readSv("alph"));
373 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("a "));
374 EXPECT_CALL(fd, read(SizeIs(Ge(3)))).WillOnce(readSv("one"));
375 EXPECT_CALL(fd, read(_))
376 .WillRepeatedly(testing::Throw(exception::Eof("test")));
377 }
378 std::array<char, 16> buf;
379 EXPECT_THROW(readAllExact(fd, buf), std::system_error);
380}
381
382TEST(ReadAllExact, Success)
383{
384 testing::StrictMock<FdMock> fd;
385 {
386 testing::InSequence seq;
387 EXPECT_CALL(fd, read(SizeIs(Ge(4)))).WillOnce(readSv("alph"));
388 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("a "));
389 EXPECT_CALL(fd, read(SizeIs(Ge(10)))).WillOnce(readSv("one tenner"));
390 EXPECT_CALL(fd, read(_))
391 .WillRepeatedly(testing::Throw(exception::Eof("test")));
392 }
393 std::array<char, 16> buf;
394 readAllExact(fd, buf);
395 EXPECT_EQ(std::string_view(buf.begin(), buf.end()), "alpha one tenner");
396}
397
398TEST(ReadAllExact, TooMuch)
399{
400 testing::StrictMock<FdMock> fd;
401 {
402 testing::InSequence seq;
403 EXPECT_CALL(fd, read(SizeIs(Ge(4)))).WillOnce(readSv("alph"));
404 EXPECT_CALL(fd, read(SizeIs(Ge(2)))).WillOnce(readSv("a "));
405 EXPECT_CALL(fd, read(SizeIs(Ge(10)))).WillOnce(readSv("one tenner"));
406 EXPECT_CALL(fd, read(SizeIs(Ge(1)))).WillOnce(readSv("r"));
407 }
408 std::array<char, 16> buf;
409 EXPECT_THROW(readAllExact(fd, buf), std::system_error);
410}
411
William A. Kennington III93ae9702023-12-22 16:41:17 -0800412} // namespace stdplus::fd