xref: /openbmc/phosphor-power/test/file_descriptor_tests.cpp (revision 9462e0667fdc6bf32b265fc393e057c1b67d9cbe)
1*9462e066SShawn McCarney /**
2*9462e066SShawn McCarney  * Copyright © 2020 IBM Corporation
3*9462e066SShawn McCarney  *
4*9462e066SShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
5*9462e066SShawn McCarney  * you may not use this file except in compliance with the License.
6*9462e066SShawn McCarney  * You may obtain a copy of the License at
7*9462e066SShawn McCarney  *
8*9462e066SShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
9*9462e066SShawn McCarney  *
10*9462e066SShawn McCarney  * Unless required by applicable law or agreed to in writing, software
11*9462e066SShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
12*9462e066SShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9462e066SShawn McCarney  * See the License for the specific language governing permissions and
14*9462e066SShawn McCarney  * limitations under the License.
15*9462e066SShawn McCarney  */
16*9462e066SShawn McCarney #include "file_descriptor.hpp"
17*9462e066SShawn McCarney 
18*9462e066SShawn McCarney #include <errno.h>     // for errno
19*9462e066SShawn McCarney #include <fcntl.h>     // for open() and fcntl()
20*9462e066SShawn McCarney #include <sys/stat.h>  // for open()
21*9462e066SShawn McCarney #include <sys/types.h> // for open()
22*9462e066SShawn McCarney #include <unistd.h>    // for fcntl()
23*9462e066SShawn McCarney 
24*9462e066SShawn McCarney #include <utility>
25*9462e066SShawn McCarney 
26*9462e066SShawn McCarney #include <gtest/gtest.h>
27*9462e066SShawn McCarney 
28*9462e066SShawn McCarney using namespace phosphor::power::util;
29*9462e066SShawn McCarney 
30*9462e066SShawn McCarney /**
31*9462e066SShawn McCarney  * Returns whether the specified file descriptor is valid/open.
32*9462e066SShawn McCarney  *
33*9462e066SShawn McCarney  * @param[in] fd - File descriptor
34*9462e066SShawn McCarney  * @return true if descriptor is valid/open, false otherwise
35*9462e066SShawn McCarney  */
36*9462e066SShawn McCarney bool isValid(int fd)
37*9462e066SShawn McCarney {
38*9462e066SShawn McCarney     return (fcntl(fd, F_GETFL) != -1) || (errno != EBADF);
39*9462e066SShawn McCarney }
40*9462e066SShawn McCarney 
41*9462e066SShawn McCarney /**
42*9462e066SShawn McCarney  * Creates an open file descriptor.
43*9462e066SShawn McCarney  *
44*9462e066SShawn McCarney  * Verifies the file descriptor is valid.
45*9462e066SShawn McCarney  *
46*9462e066SShawn McCarney  * @return file descriptor
47*9462e066SShawn McCarney  */
48*9462e066SShawn McCarney int createOpenFileDescriptor()
49*9462e066SShawn McCarney {
50*9462e066SShawn McCarney     int fd = open("/etc/hosts", O_RDONLY);
51*9462e066SShawn McCarney     EXPECT_NE(fd, -1);
52*9462e066SShawn McCarney     EXPECT_TRUE(isValid(fd));
53*9462e066SShawn McCarney     return fd;
54*9462e066SShawn McCarney }
55*9462e066SShawn McCarney 
56*9462e066SShawn McCarney TEST(FileDescriptorTests, DefaultConstructor)
57*9462e066SShawn McCarney {
58*9462e066SShawn McCarney     FileDescriptor descriptor;
59*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
60*9462e066SShawn McCarney     EXPECT_FALSE(descriptor.operator bool());
61*9462e066SShawn McCarney }
62*9462e066SShawn McCarney 
63*9462e066SShawn McCarney TEST(FileDescriptorTests, IntConstructor)
64*9462e066SShawn McCarney {
65*9462e066SShawn McCarney     int fd = createOpenFileDescriptor();
66*9462e066SShawn McCarney     FileDescriptor descriptor{fd};
67*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd);
68*9462e066SShawn McCarney     EXPECT_TRUE(descriptor.operator bool());
69*9462e066SShawn McCarney     EXPECT_TRUE(isValid(fd));
70*9462e066SShawn McCarney }
71*9462e066SShawn McCarney 
72*9462e066SShawn McCarney TEST(FileDescriptorTests, MoveConstructor)
73*9462e066SShawn McCarney {
74*9462e066SShawn McCarney     // Create first FileDescriptor object with open file descriptor
75*9462e066SShawn McCarney     int fd = createOpenFileDescriptor();
76*9462e066SShawn McCarney     FileDescriptor descriptor1{fd};
77*9462e066SShawn McCarney     EXPECT_EQ(descriptor1(), fd);
78*9462e066SShawn McCarney     EXPECT_TRUE(isValid(fd));
79*9462e066SShawn McCarney 
80*9462e066SShawn McCarney     // Create second FileDescriptor object, moving in the contents of the first
81*9462e066SShawn McCarney     FileDescriptor descriptor2{std::move(descriptor1)};
82*9462e066SShawn McCarney 
83*9462e066SShawn McCarney     // Verify descriptor has been moved out of first object
84*9462e066SShawn McCarney     EXPECT_EQ(descriptor1(), -1);
85*9462e066SShawn McCarney 
86*9462e066SShawn McCarney     // Verify descriptor has been moved into second object
87*9462e066SShawn McCarney     EXPECT_EQ(descriptor2(), fd);
88*9462e066SShawn McCarney 
89*9462e066SShawn McCarney     // Verify descriptor is still valid/open
90*9462e066SShawn McCarney     EXPECT_TRUE(isValid(fd));
91*9462e066SShawn McCarney }
92*9462e066SShawn McCarney 
93*9462e066SShawn McCarney TEST(FileDescriptorTests, MoveAssignmentOperator)
94*9462e066SShawn McCarney {
95*9462e066SShawn McCarney     // Test where move is valid
96*9462e066SShawn McCarney     {
97*9462e066SShawn McCarney         // Create first FileDescriptor object with open file descriptor
98*9462e066SShawn McCarney         int fd1 = createOpenFileDescriptor();
99*9462e066SShawn McCarney         FileDescriptor descriptor1{fd1};
100*9462e066SShawn McCarney         EXPECT_EQ(descriptor1(), fd1);
101*9462e066SShawn McCarney         EXPECT_TRUE(isValid(fd1));
102*9462e066SShawn McCarney 
103*9462e066SShawn McCarney         // Create second FileDescriptor object with open file descriptor
104*9462e066SShawn McCarney         int fd2 = createOpenFileDescriptor();
105*9462e066SShawn McCarney         FileDescriptor descriptor2{fd2};
106*9462e066SShawn McCarney         EXPECT_EQ(descriptor2(), fd2);
107*9462e066SShawn McCarney         EXPECT_TRUE(isValid(fd2));
108*9462e066SShawn McCarney 
109*9462e066SShawn McCarney         // Move second FileDescriptor object into the first
110*9462e066SShawn McCarney         descriptor1 = std::move(descriptor2);
111*9462e066SShawn McCarney 
112*9462e066SShawn McCarney         // Verify second file descriptor has been moved into first object
113*9462e066SShawn McCarney         EXPECT_EQ(descriptor1(), fd2);
114*9462e066SShawn McCarney 
115*9462e066SShawn McCarney         // Verify second file descriptor has been moved out of second object
116*9462e066SShawn McCarney         EXPECT_EQ(descriptor2(), -1);
117*9462e066SShawn McCarney 
118*9462e066SShawn McCarney         // Verify first file descriptor has been closed and is no longer valid
119*9462e066SShawn McCarney         EXPECT_FALSE(isValid(fd1));
120*9462e066SShawn McCarney 
121*9462e066SShawn McCarney         // Verify second file descriptor is still valid
122*9462e066SShawn McCarney         EXPECT_TRUE(isValid(fd2));
123*9462e066SShawn McCarney     }
124*9462e066SShawn McCarney 
125*9462e066SShawn McCarney     // Test where move is invalid: Attempt to move object into itself
126*9462e066SShawn McCarney     {
127*9462e066SShawn McCarney         // Create FileDescriptor object with open file descriptor
128*9462e066SShawn McCarney         int fd = createOpenFileDescriptor();
129*9462e066SShawn McCarney         FileDescriptor descriptor{fd};
130*9462e066SShawn McCarney         EXPECT_EQ(descriptor(), fd);
131*9462e066SShawn McCarney         EXPECT_TRUE(isValid(fd));
132*9462e066SShawn McCarney 
133*9462e066SShawn McCarney         // Try to move object into itself
134*9462e066SShawn McCarney         descriptor = std::move(descriptor);
135*9462e066SShawn McCarney 
136*9462e066SShawn McCarney         // Verify object still contains file descriptor
137*9462e066SShawn McCarney         EXPECT_EQ(descriptor(), fd);
138*9462e066SShawn McCarney         EXPECT_TRUE(isValid(fd));
139*9462e066SShawn McCarney     }
140*9462e066SShawn McCarney }
141*9462e066SShawn McCarney 
142*9462e066SShawn McCarney TEST(FileDescriptorTests, Destructor)
143*9462e066SShawn McCarney {
144*9462e066SShawn McCarney     // Test where file descriptor was never set
145*9462e066SShawn McCarney     {
146*9462e066SShawn McCarney         FileDescriptor descriptor;
147*9462e066SShawn McCarney         EXPECT_EQ(descriptor(), -1);
148*9462e066SShawn McCarney     }
149*9462e066SShawn McCarney 
150*9462e066SShawn McCarney     // Test where file descriptor was already closed
151*9462e066SShawn McCarney     {
152*9462e066SShawn McCarney         // Create FileDescriptor object with open file descriptor.  Close the
153*9462e066SShawn McCarney         // descriptor explicitly.
154*9462e066SShawn McCarney         int fd = createOpenFileDescriptor();
155*9462e066SShawn McCarney         {
156*9462e066SShawn McCarney             FileDescriptor descriptor{fd};
157*9462e066SShawn McCarney             EXPECT_EQ(descriptor(), fd);
158*9462e066SShawn McCarney             EXPECT_TRUE(isValid(fd));
159*9462e066SShawn McCarney 
160*9462e066SShawn McCarney             EXPECT_EQ(descriptor.close(), 0);
161*9462e066SShawn McCarney             EXPECT_EQ(descriptor(), -1);
162*9462e066SShawn McCarney             EXPECT_FALSE(isValid(fd));
163*9462e066SShawn McCarney         }
164*9462e066SShawn McCarney         EXPECT_FALSE(isValid(fd));
165*9462e066SShawn McCarney     }
166*9462e066SShawn McCarney 
167*9462e066SShawn McCarney     // Test where file descriptor needs to be closed
168*9462e066SShawn McCarney     {
169*9462e066SShawn McCarney         // Create FileDescriptor object with open file descriptor.  Destructor
170*9462e066SShawn McCarney         // will close descriptor.
171*9462e066SShawn McCarney         int fd = createOpenFileDescriptor();
172*9462e066SShawn McCarney         {
173*9462e066SShawn McCarney             FileDescriptor descriptor{fd};
174*9462e066SShawn McCarney             EXPECT_EQ(descriptor(), fd);
175*9462e066SShawn McCarney             EXPECT_TRUE(isValid(fd));
176*9462e066SShawn McCarney         }
177*9462e066SShawn McCarney         EXPECT_FALSE(isValid(fd));
178*9462e066SShawn McCarney     }
179*9462e066SShawn McCarney }
180*9462e066SShawn McCarney 
181*9462e066SShawn McCarney TEST(FileDescriptorTests, FunctionCallOperator)
182*9462e066SShawn McCarney {
183*9462e066SShawn McCarney     // Test where FileDescriptor object does not contain a valid file descriptor
184*9462e066SShawn McCarney     FileDescriptor descriptor{};
185*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
186*9462e066SShawn McCarney 
187*9462e066SShawn McCarney     // Test where FileDescriptor object contains a valid file descriptor
188*9462e066SShawn McCarney     int fd = createOpenFileDescriptor();
189*9462e066SShawn McCarney     descriptor.set(fd);
190*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd);
191*9462e066SShawn McCarney }
192*9462e066SShawn McCarney 
193*9462e066SShawn McCarney TEST(FileDescriptorTests, OperatorBool)
194*9462e066SShawn McCarney {
195*9462e066SShawn McCarney     // Test where FileDescriptor object does not contain a valid file descriptor
196*9462e066SShawn McCarney     FileDescriptor descriptor{};
197*9462e066SShawn McCarney     EXPECT_FALSE(descriptor.operator bool());
198*9462e066SShawn McCarney     if (descriptor)
199*9462e066SShawn McCarney     {
200*9462e066SShawn McCarney         ADD_FAILURE() << "Should not have reached this line.";
201*9462e066SShawn McCarney     }
202*9462e066SShawn McCarney 
203*9462e066SShawn McCarney     // Test where FileDescriptor object contains a valid file descriptor
204*9462e066SShawn McCarney     int fd = createOpenFileDescriptor();
205*9462e066SShawn McCarney     descriptor.set(fd);
206*9462e066SShawn McCarney     EXPECT_TRUE(descriptor.operator bool());
207*9462e066SShawn McCarney     if (!descriptor)
208*9462e066SShawn McCarney     {
209*9462e066SShawn McCarney         ADD_FAILURE() << "Should not have reached this line.";
210*9462e066SShawn McCarney     }
211*9462e066SShawn McCarney 
212*9462e066SShawn McCarney     // Test where file descriptor has been closed
213*9462e066SShawn McCarney     EXPECT_EQ(descriptor.close(), 0);
214*9462e066SShawn McCarney     EXPECT_FALSE(descriptor.operator bool());
215*9462e066SShawn McCarney     if (descriptor)
216*9462e066SShawn McCarney     {
217*9462e066SShawn McCarney         ADD_FAILURE() << "Should not have reached this line.";
218*9462e066SShawn McCarney     }
219*9462e066SShawn McCarney }
220*9462e066SShawn McCarney 
221*9462e066SShawn McCarney TEST(FileDescriptorTests, Close)
222*9462e066SShawn McCarney {
223*9462e066SShawn McCarney     // Test where object contains an open file descriptor
224*9462e066SShawn McCarney     int fd = createOpenFileDescriptor();
225*9462e066SShawn McCarney     FileDescriptor descriptor{fd};
226*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd);
227*9462e066SShawn McCarney     EXPECT_TRUE(isValid(fd));
228*9462e066SShawn McCarney     EXPECT_EQ(descriptor.close(), 0);
229*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
230*9462e066SShawn McCarney     EXPECT_FALSE(isValid(fd));
231*9462e066SShawn McCarney 
232*9462e066SShawn McCarney     // Test where object does not contain an open file descriptor
233*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
234*9462e066SShawn McCarney     EXPECT_EQ(descriptor.close(), 0);
235*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
236*9462e066SShawn McCarney 
237*9462e066SShawn McCarney     // Test where close() fails due to invalid file descriptor
238*9462e066SShawn McCarney     descriptor.set(999999);
239*9462e066SShawn McCarney     EXPECT_EQ(descriptor.close(), -1);
240*9462e066SShawn McCarney     EXPECT_EQ(errno, EBADF);
241*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
242*9462e066SShawn McCarney }
243*9462e066SShawn McCarney 
244*9462e066SShawn McCarney TEST(FileDescriptorTests, Set)
245*9462e066SShawn McCarney {
246*9462e066SShawn McCarney     // Test where object does not contain an open file descriptor
247*9462e066SShawn McCarney     FileDescriptor descriptor{};
248*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
249*9462e066SShawn McCarney     int fd1 = createOpenFileDescriptor();
250*9462e066SShawn McCarney     descriptor.set(fd1);
251*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd1);
252*9462e066SShawn McCarney     EXPECT_TRUE(isValid(fd1));
253*9462e066SShawn McCarney 
254*9462e066SShawn McCarney     // Test where object contains an open file descriptor.  Should close
255*9462e066SShawn McCarney     // previous descriptor.
256*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd1);
257*9462e066SShawn McCarney     EXPECT_TRUE(isValid(fd1));
258*9462e066SShawn McCarney     int fd2 = createOpenFileDescriptor();
259*9462e066SShawn McCarney     descriptor.set(fd2);
260*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd2);
261*9462e066SShawn McCarney     EXPECT_FALSE(isValid(fd1));
262*9462e066SShawn McCarney     EXPECT_TRUE(isValid(fd2));
263*9462e066SShawn McCarney 
264*9462e066SShawn McCarney     // Test where -1 is specified.  Should close previous descriptor.
265*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd2);
266*9462e066SShawn McCarney     EXPECT_TRUE(isValid(fd2));
267*9462e066SShawn McCarney     descriptor.set(-1);
268*9462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
269*9462e066SShawn McCarney     EXPECT_FALSE(isValid(fd2));
270*9462e066SShawn McCarney }
271