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_write_unittest {
31
32 using ::testing::_;
33 using ::testing::InSequence;
34 using ::testing::Return;
35 using ::testing::SetErrnoAndReturn;
36
37 class MockWrite
38 {
39 public:
~MockWrite()40 virtual ~MockWrite() {}
41 MOCK_METHOD3(mockwrite, ssize_t(int, const void *, size_t));
42 };
43
44 MockWrite *mockfs= NULL;
45
46 // We need to mock away write(2), do it with a macro:
47 #define write(fd, buf, count) mockfs->mockwrite(fd, buf, count)
48
49 /*
50 Include the source file, which will give us
51 mysys_my_write_unittest::my_write() for testing.
52 */
53 #include "../../mysys/my_write.c"
54
55 #undef write
56
57 class MysysMyWriteTest : public ::testing::Test
58 {
SetUp()59 virtual void SetUp()
60 {
61 mockfs= new MockWrite;
62 }
TearDown()63 virtual void TearDown()
64 {
65 delete mockfs;
66 mockfs= NULL;
67 }
68 };
69
70
71 // Test of normal case: write OK
TEST_F(MysysMyWriteTest,MyWriteOK)72 TEST_F(MysysMyWriteTest, MyWriteOK)
73 {
74 uchar buf[4096];
75 InSequence s;
76 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096))
77 .Times(1)
78 .WillOnce(Return(4096));
79
80 const size_t result= my_write(42, buf, 4096, 0);
81 EXPECT_EQ(4096U, result);
82 }
83
84
85 // Test of normal case: write OK with MY_NABP
TEST_F(MysysMyWriteTest,MyWriteOKNABP)86 TEST_F(MysysMyWriteTest, MyWriteOKNABP)
87 {
88 uchar buf[4096];
89 InSequence s;
90 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096))
91 .Times(1)
92 .WillOnce(Return(4096));
93
94 const size_t result= my_write(42, buf, 4096, MYF(MY_NABP));
95 EXPECT_EQ(0U, result);
96 }
97
98
99 // Test of disk full: write not OK
TEST_F(MysysMyWriteTest,MyWriteFail)100 TEST_F(MysysMyWriteTest, MyWriteFail)
101 {
102 uchar buf[4096];
103 InSequence s;
104 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096))
105 .Times(1)
106 .WillOnce(SetErrnoAndReturn(ENOSPC, -1));
107
108 const size_t result= my_write(42, buf, 4096, 0);
109 EXPECT_EQ(MY_FILE_ERROR, result);
110 }
111
112
113 // Test of disk full: write not OK, with MY_NABP
TEST_F(MysysMyWriteTest,MyWriteFailNABP)114 TEST_F(MysysMyWriteTest, MyWriteFailNABP)
115 {
116 uchar buf[4096];
117 InSequence s;
118 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096))
119 .Times(1)
120 .WillOnce(SetErrnoAndReturn(ENOSPC, -1));
121
122 const size_t result= my_write(42, buf, 4096, MYF(MY_NABP));
123 EXPECT_EQ(MY_FILE_ERROR, result);
124 }
125
126
127 // Test of disk full after partial write.
TEST_F(MysysMyWriteTest,MyWrite8192)128 TEST_F(MysysMyWriteTest, MyWrite8192)
129 {
130 uchar buf[8192];
131 InSequence s;
132 // Expect call to write 8192 bytes, return 4096.
133 EXPECT_CALL(*mockfs, mockwrite(_, _, 8192))
134 .Times(1)
135 .WillOnce(Return(4096));
136 // Expect second call to write remaining 4096 bytes, return disk full.
137 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096))
138 .Times(1)
139 .WillOnce(SetErrnoAndReturn(ENOSPC, -1));
140
141 const size_t result= my_write(42, buf, 8192, 0);
142 EXPECT_EQ(4096U, result);
143 }
144
145
146 // Test of disk full after partial write.
TEST_F(MysysMyWriteTest,MyWrite8192NABP)147 TEST_F(MysysMyWriteTest, MyWrite8192NABP)
148 {
149 uchar buf[8192];
150 InSequence s;
151 // Expect call to write 8192 bytes, return 4096.
152 EXPECT_CALL(*mockfs, mockwrite(_, _, 8192))
153 .Times(1)
154 .WillOnce(Return(4096));
155 // Expect second call to write remaining 4096 bytes, return disk full.
156 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096))
157 .Times(1)
158 .WillOnce(SetErrnoAndReturn(ENOSPC, -1));
159
160 const size_t result= my_write(42, buf, 8192, MYF(MY_NABP));
161 EXPECT_EQ(MY_FILE_ERROR, result);
162 }
163
164
165 // Test of partial write, followed by interrupt, followed by successful write.
TEST_F(MysysMyWriteTest,MyWrite8192Interrupt)166 TEST_F(MysysMyWriteTest, MyWrite8192Interrupt)
167 {
168 uchar buf[8192];
169 InSequence s;
170 // Expect call to write 8192 bytes, return 4096.
171 EXPECT_CALL(*mockfs, mockwrite(_, _, 8192))
172 .Times(1)
173 .WillOnce(Return(4096));
174 // Expect second call to write remaining 4096 bytes, return interrupt.
175 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096))
176 .Times(1)
177 .WillOnce(SetErrnoAndReturn(EINTR, -1));
178 // Expect third call to write remaining 4096 bytes, return 4096.
179 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096))
180 .Times(1)
181 .WillOnce(Return(4096));
182
183 const size_t result= my_write(42, buf, 8192, 0);
184 EXPECT_EQ(8192U, result);
185 }
186
187
188 // Test of partial write, followed by interrupt, followed by successful write.
TEST_F(MysysMyWriteTest,MyWrite8192InterruptNABP)189 TEST_F(MysysMyWriteTest, MyWrite8192InterruptNABP)
190 {
191 uchar buf[8192];
192 InSequence s;
193 // Expect call to write 8192 bytes, return 4096.
194 EXPECT_CALL(*mockfs, mockwrite(_, _, 8192))
195 .Times(1)
196 .WillOnce(Return(4096));
197 // Expect second call to write remaining 4096 bytes, return interrupt.
198 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096))
199 .Times(1)
200 .WillOnce(SetErrnoAndReturn(EINTR, -1));
201 // Expect third call to write remaining 4096 bytes, return 4096.
202 EXPECT_CALL(*mockfs, mockwrite(_, _, 4096))
203 .Times(1)
204 .WillOnce(Return(4096));
205
206 const size_t result= my_write(42, buf, 8192, MYF(MY_NABP));
207 EXPECT_EQ(0U, result);
208 }
209
210
211 // Test of partial write, followed successful write.
TEST_F(MysysMyWriteTest,MyWrite400)212 TEST_F(MysysMyWriteTest, MyWrite400)
213 {
214 uchar buf[400];
215 InSequence s;
216 EXPECT_CALL(*mockfs, mockwrite(_, _, 400))
217 .Times(1)
218 .WillOnce(Return(200));
219 EXPECT_CALL(*mockfs, mockwrite(_, _, 200))
220 .Times(1)
221 .WillOnce(Return(200));
222
223 const size_t result= my_write(42, buf, 400, 0);
224 EXPECT_EQ(400U, result);
225 }
226
227
228 // Test of partial write, followed successful write.
TEST_F(MysysMyWriteTest,MyWrite400NABP)229 TEST_F(MysysMyWriteTest, MyWrite400NABP)
230 {
231 uchar buf[400];
232 InSequence s;
233 EXPECT_CALL(*mockfs, mockwrite(_, _, 400))
234 .Times(1)
235 .WillOnce(Return(200));
236 EXPECT_CALL(*mockfs, mockwrite(_, _, 200))
237 .Times(1)
238 .WillOnce(Return(200));
239
240 const size_t result= my_write(42, buf, 400, MYF(MY_NABP));
241 EXPECT_EQ(0U, result);
242 }
243
244
245 // Test of partial write, followed by failure, followed successful write.
TEST_F(MysysMyWriteTest,MyWrite300)246 TEST_F(MysysMyWriteTest, MyWrite300)
247 {
248 uchar buf[300];
249 InSequence s;
250 EXPECT_CALL(*mockfs, mockwrite(_, _, 300))
251 .Times(1)
252 .WillOnce(Return(100));
253 EXPECT_CALL(*mockfs, mockwrite(_, _, 200))
254 .Times(1)
255 .WillOnce(SetErrnoAndReturn(EAGAIN, 0));
256 EXPECT_CALL(*mockfs, mockwrite(_, _, 200))
257 .Times(1)
258 .WillOnce(Return(200));
259
260 const size_t result= my_write(42, buf, 300, 0);
261 EXPECT_EQ(300U, result);
262 }
263
264 }
265 #endif
266