blob: 7293e2b793b92f165b15275311936ea294a1658c [file] [log] [blame]
Patrick Venture15f0f942020-07-09 09:38:18 -07001#include "sys_file_impl.hpp"
Kun Yi9125e632019-01-09 13:52:06 -08002#include "sys_mock.hpp"
3
4#include <fcntl.h>
5
6#include <cstring>
7#include <memory>
8
9#include <gmock/gmock.h>
10
11using namespace binstore;
12using namespace std::string_literals;
13
14using ::testing::_;
Kun Yi9125e632019-01-09 13:52:06 -080015using ::testing::IsEmpty;
16using ::testing::NotNull;
17using ::testing::Return;
18using ::testing::SetErrnoAndReturn;
19using ::testing::StrEq;
20using ::testing::WithArgs;
21
22static constexpr int sysFileTestFd = 42;
23static inline std::string sysFileTestPath = "/test/path"s;
24static constexpr size_t sysFileTestOffset = 0;
25auto static const sysFileTestStr = "Hello, \0+.world!\0"s;
26std::vector<uint8_t> static const sysFileTestBuf(sysFileTestStr.begin(),
27 sysFileTestStr.end());
28
29class SysFileTest : public ::testing::Test
30{
31 protected:
32 SysFileTest()
33 {
34 EXPECT_CALL(sys, open(StrEq(sysFileTestPath), O_RDWR))
35 .WillOnce(Return(sysFileTestFd));
36 EXPECT_CALL(sys, close(sysFileTestFd));
37
38 file = std::make_unique<SysFileImpl>(sysFileTestPath, sysFileTestOffset,
39 &sys);
40 }
41
42 const internal::SysMock sys;
43
44 std::unique_ptr<SysFile> file;
45};
46
47ACTION_P(BufSet, buf)
48{
49 size_t count = std::min(arg1, buf.size());
50 std::memcpy(arg0, buf.data(), count);
51
52 return count;
53}
54
55ACTION_P2(BufSetAndGetStartAddr, buf, addrPtr)
56{
57 size_t count = std::min(arg1, buf.size());
58 std::memcpy(arg0, buf.data(), count);
59 *addrPtr = arg0;
60
61 return count;
62}
63
64ACTION_P2(BufSetTruncated, buf, offset)
65{
66 size_t count = std::min(arg1, buf.size() - offset);
67 std::memcpy(arg0, buf.data() + offset, count);
68
69 return count;
70}
71
72TEST_F(SysFileTest, ReadSucceeds)
73{
74 EXPECT_CALL(sys, lseek(sysFileTestFd, 0, SEEK_SET));
75 EXPECT_CALL(sys, read(sysFileTestFd, NotNull(), _))
76 .WillOnce(WithArgs<1, 2>(BufSet(sysFileTestBuf)));
77
78 EXPECT_EQ(sysFileTestStr, file->readAsStr(0, sysFileTestBuf.size()));
79}
80
81TEST_F(SysFileTest, ReadMoreThanAvailable)
82{
83 EXPECT_CALL(sys, lseek(sysFileTestFd, 0, SEEK_SET));
84 EXPECT_CALL(sys, read(sysFileTestFd, NotNull(), _))
85 .WillOnce(WithArgs<1, 2>(BufSet(sysFileTestBuf)))
86 .WillOnce(Return(0));
87
88 EXPECT_EQ(sysFileTestStr, file->readAsStr(0, sysFileTestBuf.size() + 1024));
89}
90
91TEST_F(SysFileTest, ReadAtOffset)
92{
93 const size_t testOffset = 2;
94 std::string truncBuf = sysFileTestStr.substr(testOffset);
95
96 EXPECT_CALL(sys, lseek(sysFileTestFd, testOffset, SEEK_SET));
97 EXPECT_CALL(sys, read(sysFileTestFd, NotNull(), _))
98 .WillOnce(WithArgs<1, 2>(BufSetTruncated(sysFileTestBuf, testOffset)));
99
100 EXPECT_EQ(truncBuf, file->readAsStr(testOffset, truncBuf.size()));
101}
102
103TEST_F(SysFileTest, ReadRemainingFail)
104{
105 EXPECT_CALL(sys, lseek(sysFileTestFd, 0, SEEK_SET));
106 EXPECT_CALL(sys, read(sysFileTestFd, NotNull(), _))
107 .WillOnce(SetErrnoAndReturn(EIO, -1));
108
109 EXPECT_THROW(file->readRemainingAsStr(0), std::exception);
110}
111
112TEST_F(SysFileTest, ReadRemainingSucceeds)
113{
114 EXPECT_CALL(sys, lseek(sysFileTestFd, 0, SEEK_SET));
115 EXPECT_CALL(sys, read(sysFileTestFd, NotNull(), _))
116 .WillOnce(WithArgs<1, 2>(BufSet(sysFileTestBuf)))
117 .WillOnce(Return(0)); // EOF
118
119 EXPECT_EQ(sysFileTestStr, file->readRemainingAsStr(0));
120}
121
122TEST_F(SysFileTest, ReadRemainingBeyondEndReturnsEmpty)
123{
124 const size_t largeOffset = 9000;
125 EXPECT_CALL(sys, lseek(sysFileTestFd, largeOffset, SEEK_SET));
126 EXPECT_CALL(sys, read(sysFileTestFd, NotNull(), _)).WillOnce(Return(0));
127
128 EXPECT_THAT(file->readRemainingAsStr(largeOffset), IsEmpty());
129}