1 /* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA */
22
23 // First include (the generated) my_config.h, to get correct platform defines.
24 #include "my_config.h"
25 #include <gtest/gtest.h>
26 #include <gmock/gmock.h>
27
28 // Ignore test on windows, as we are mocking away a unix function, see below.
29 #ifndef __WIN__
30 namespace mysys_my_pwrite_unittest {
31
32 using ::testing::_;
33 using ::testing::InSequence;
34 using ::testing::Return;
35 using ::testing::ReturnPointee;
36 using ::testing::SetErrnoAndReturn;
37
38 class MockWrite
39 {
40 public:
~MockWrite()41 virtual ~MockWrite() {}
42 MOCK_METHOD4(mockwrite, ssize_t(int, const void *, size_t, off_t));
43 MOCK_METHOD3(mockseek, off_t(int, off_t, int));
44 };
45
46 MockWrite *mockfs= NULL;
47
48 // We need to mock away pwrite(2), do it with a macro:
49 #define pwrite(fd, buf, count, offset) mockfs->mockwrite(fd, buf, count, offset)
50 #define lseek(fd, offset, whence) mockfs->mockseek(fd, offset, whence)
51
52 /*
53 Include the source file, which will give us
54 mysys_my_pwrite_unittest::my_pwrite() for testing.
55 */
56 #include "../../mysys/my_pread.c"
57
58 #undef pwrite
59 #undef lseek
60
61 class MysysMyPWriteTest : public ::testing::Test
62 {
SetUp()63 virtual void SetUp()
64 {
65 mockfs= new MockWrite;
66 m_offset= 0;
67 EXPECT_CALL(*mockfs, mockseek(_, m_offset, _))
68 .WillRepeatedly(ReturnPointee(&m_offset));
69 }
TearDown()70 virtual void TearDown()
71 {
72 delete mockfs;
73 mockfs= NULL;
74 }
75 public:
76 my_off_t m_offset;
77 };
78
79
80 // Test of normal case: write OK
TEST_F(MysysMyPWriteTest,MyPWriteOK)81 TEST_F(MysysMyPWriteTest, MyPWriteOK)
82 {
83 uchar buf[4096];
84 InSequence s;
85 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096, _))
86 .Times(1)
87 .WillOnce(Return(4096));
88
89 const size_t result= my_pwrite(42, buf, 4096, m_offset, 0);
90 EXPECT_EQ(4096U, result);
91 }
92
93
94 // Test of normal case: write OK with MY_NABP
TEST_F(MysysMyPWriteTest,MyPWriteOKNABP)95 TEST_F(MysysMyPWriteTest, MyPWriteOKNABP)
96 {
97 uchar buf[4096];
98 InSequence s;
99 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096, _))
100 .Times(1)
101 .WillOnce(Return(4096));
102
103 const size_t result= my_pwrite(42, buf, 4096, m_offset, MYF(MY_NABP));
104 EXPECT_EQ(0U, result);
105 }
106
107
108 // Test of disk full: write not OK
TEST_F(MysysMyPWriteTest,MyPWriteFail)109 TEST_F(MysysMyPWriteTest, MyPWriteFail)
110 {
111 uchar buf[4096];
112 InSequence s;
113 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096, _))
114 .Times(1)
115 .WillOnce(SetErrnoAndReturn(ENOSPC, -1));
116
117 const size_t result= my_pwrite(42, buf, 4096, m_offset, 0);
118 EXPECT_EQ(MY_FILE_ERROR, result);
119 }
120
121
122 // Test of disk full: write not OK, with MY_NABP
TEST_F(MysysMyPWriteTest,MyPWriteFailNABP)123 TEST_F(MysysMyPWriteTest, MyPWriteFailNABP)
124 {
125 uchar buf[4096];
126 InSequence s;
127 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096, _))
128 .Times(1)
129 .WillOnce(SetErrnoAndReturn(ENOSPC, -1));
130
131 const size_t result= my_pwrite(42, buf, 4096, m_offset, MYF(MY_NABP));
132 EXPECT_EQ(MY_FILE_ERROR, result);
133 }
134
135
136 // Test of disk full after partial write.
TEST_F(MysysMyPWriteTest,MyPWrite8192)137 TEST_F(MysysMyPWriteTest, MyPWrite8192)
138 {
139 uchar buf[8192];
140 InSequence s;
141 // Expect call to write 8192 bytes, return 4096.
142 EXPECT_CALL(*mockfs, mockwrite(_, _, 8192, _))
143 .Times(1)
144 .WillOnce(Return(4096));
145 // Expect second call to write remaining 4096 bytes, return disk full.
146 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096, _))
147 .Times(1)
148 .WillOnce(SetErrnoAndReturn(ENOSPC, -1));
149
150 const size_t result= my_pwrite(42, buf, 8192, m_offset, 0);
151 EXPECT_EQ(4096U, result);
152 }
153
154
155 // Test of disk full after partial write.
TEST_F(MysysMyPWriteTest,MyPWrite8192NABP)156 TEST_F(MysysMyPWriteTest, MyPWrite8192NABP)
157 {
158 uchar buf[8192];
159 InSequence s;
160 // Expect call to write 8192 bytes, return 4096.
161 EXPECT_CALL(*mockfs, mockwrite(_, _, 8192, _))
162 .Times(1)
163 .WillOnce(Return(4096));
164 // Expect second call to write remaining 4096 bytes, return disk full.
165 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096, _))
166 .Times(1)
167 .WillOnce(SetErrnoAndReturn(ENOSPC, -1));
168
169 const size_t result= my_pwrite(42, buf, 8192, m_offset, MYF(MY_NABP));
170 EXPECT_EQ(MY_FILE_ERROR, result);
171 }
172
173
174 // Test of partial write, followed by interrupt, followed by successful write.
TEST_F(MysysMyPWriteTest,MyPWrite8192Interrupt)175 TEST_F(MysysMyPWriteTest, MyPWrite8192Interrupt)
176 {
177 uchar buf[8192];
178 InSequence s;
179 // Expect call to write 8192 bytes, return 4096.
180 EXPECT_CALL(*mockfs, mockwrite(_, _, 8192, _))
181 .Times(1)
182 .WillOnce(Return(4096));
183 // Expect second call to write remaining 4096 bytes, return interrupt.
184 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096, _))
185 .Times(1)
186 .WillOnce(SetErrnoAndReturn(EINTR, -1));
187 // Expect third call to write remaining 4096 bytes, return 4096.
188 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096, _))
189 .Times(1)
190 .WillOnce(Return(4096));
191
192 const size_t result= my_pwrite(42, buf, 8192, m_offset, 0);
193 EXPECT_EQ(8192U, result);
194 }
195
196
197 // Test of partial write, followed by interrupt, followed by successful write.
TEST_F(MysysMyPWriteTest,MyPWrite8192InterruptNABP)198 TEST_F(MysysMyPWriteTest, MyPWrite8192InterruptNABP)
199 {
200 uchar buf[8192];
201 InSequence s;
202 // Expect call to write 8192 bytes, return 4096.
203 EXPECT_CALL(*mockfs, mockwrite(_, _, 8192, _))
204 .Times(1)
205 .WillOnce(Return(4096));
206 // Expect second call to write remaining 4096 bytes, return interrupt.
207 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096, _))
208 .Times(1)
209 .WillOnce(SetErrnoAndReturn(EINTR, -1));
210 // Expect third call to write remaining 4096 bytes, return 4096.
211 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096, _))
212 .Times(1)
213 .WillOnce(Return(4096));
214
215 const size_t result= my_pwrite(42, buf, 8192, m_offset, MYF(MY_NABP));
216 EXPECT_EQ(0U, result);
217 }
218
219
220 // Test of partial write, followed successful write.
TEST_F(MysysMyPWriteTest,MyPWrite400)221 TEST_F(MysysMyPWriteTest, MyPWrite400)
222 {
223 uchar buf[400];
224 InSequence s;
225 EXPECT_CALL(*mockfs, mockwrite(_, _, 400, _))
226 .Times(1)
227 .WillOnce(Return(200));
228 EXPECT_CALL(*mockfs, mockwrite(_, _, 200, _))
229 .Times(1)
230 .WillOnce(Return(200));
231
232 const size_t result= my_pwrite(42, buf, 400, m_offset, 0);
233 EXPECT_EQ(400U, result);
234 }
235
236
237 // Test of partial write, followed successful write.
TEST_F(MysysMyPWriteTest,MyPWrite400NABP)238 TEST_F(MysysMyPWriteTest, MyPWrite400NABP)
239 {
240 uchar buf[400];
241 InSequence s;
242 EXPECT_CALL(*mockfs, mockwrite(_, _, 400, _))
243 .Times(1)
244 .WillOnce(Return(200));
245 EXPECT_CALL(*mockfs, mockwrite(_, _, 200, _))
246 .Times(1)
247 .WillOnce(Return(200));
248
249 const size_t result= my_pwrite(42, buf, 400, m_offset, MYF(MY_NABP));
250 EXPECT_EQ(0U, result);
251 }
252
253
254 // Test of partial write, followed by failure, followed successful write.
TEST_F(MysysMyPWriteTest,MyPWrite300)255 TEST_F(MysysMyPWriteTest, MyPWrite300)
256 {
257 uchar buf[300];
258 InSequence s;
259 EXPECT_CALL(*mockfs, mockwrite(_, _, 300, _))
260 .Times(1)
261 .WillOnce(Return(100));
262 EXPECT_CALL(*mockfs, mockwrite(_, _, 200, _))
263 .Times(1)
264 .WillOnce(SetErrnoAndReturn(EAGAIN, 0));
265 EXPECT_CALL(*mockfs, mockwrite(_, _, 200, _))
266 .Times(1)
267 .WillOnce(Return(200));
268
269 const size_t result= my_pwrite(42, buf, 300, m_offset, 0);
270 EXPECT_EQ(300U, result);
271 }
272
273 }
274 #endif
275