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