1 /* Copyright (c) 2013, 2021, Oracle and/or its affiliates.
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  02110-1301  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 _WIN32
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