xref: /openbmc/phosphor-power/test/file_descriptor_tests.cpp (revision 81e554c87de45de05c2d7be4bda18ac48deadcb5)
19462e066SShawn McCarney /**
29462e066SShawn McCarney  * Copyright © 2020 IBM Corporation
39462e066SShawn McCarney  *
49462e066SShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
59462e066SShawn McCarney  * you may not use this file except in compliance with the License.
69462e066SShawn McCarney  * You may obtain a copy of the License at
79462e066SShawn McCarney  *
89462e066SShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
99462e066SShawn McCarney  *
109462e066SShawn McCarney  * Unless required by applicable law or agreed to in writing, software
119462e066SShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
129462e066SShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139462e066SShawn McCarney  * See the License for the specific language governing permissions and
149462e066SShawn McCarney  * limitations under the License.
159462e066SShawn McCarney  */
169462e066SShawn McCarney #include "file_descriptor.hpp"
179462e066SShawn McCarney 
189462e066SShawn McCarney #include <errno.h>     // for errno
199462e066SShawn McCarney #include <fcntl.h>     // for open() and fcntl()
209462e066SShawn McCarney #include <sys/stat.h>  // for open()
219462e066SShawn McCarney #include <sys/types.h> // for open()
229462e066SShawn McCarney #include <unistd.h>    // for fcntl()
239462e066SShawn McCarney 
249462e066SShawn McCarney #include <utility>
259462e066SShawn McCarney 
269462e066SShawn McCarney #include <gtest/gtest.h>
279462e066SShawn McCarney 
289462e066SShawn McCarney using namespace phosphor::power::util;
299462e066SShawn McCarney 
309462e066SShawn McCarney /**
319462e066SShawn McCarney  * Returns whether the specified file descriptor is valid/open.
329462e066SShawn McCarney  *
339462e066SShawn McCarney  * @param[in] fd - File descriptor
349462e066SShawn McCarney  * @return true if descriptor is valid/open, false otherwise
359462e066SShawn McCarney  */
isValid(int fd)369462e066SShawn McCarney bool isValid(int fd)
379462e066SShawn McCarney {
389462e066SShawn McCarney     return (fcntl(fd, F_GETFL) != -1) || (errno != EBADF);
399462e066SShawn McCarney }
409462e066SShawn McCarney 
419462e066SShawn McCarney /**
429462e066SShawn McCarney  * Creates an open file descriptor.
439462e066SShawn McCarney  *
449462e066SShawn McCarney  * Verifies the file descriptor is valid.
459462e066SShawn McCarney  *
469462e066SShawn McCarney  * @return file descriptor
479462e066SShawn McCarney  */
createOpenFileDescriptor()489462e066SShawn McCarney int createOpenFileDescriptor()
499462e066SShawn McCarney {
509462e066SShawn McCarney     int fd = open("/etc/hosts", O_RDONLY);
519462e066SShawn McCarney     EXPECT_NE(fd, -1);
529462e066SShawn McCarney     EXPECT_TRUE(isValid(fd));
539462e066SShawn McCarney     return fd;
549462e066SShawn McCarney }
559462e066SShawn McCarney 
TEST(FileDescriptorTests,DefaultConstructor)569462e066SShawn McCarney TEST(FileDescriptorTests, DefaultConstructor)
579462e066SShawn McCarney {
589462e066SShawn McCarney     FileDescriptor descriptor;
599462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
609462e066SShawn McCarney     EXPECT_FALSE(descriptor.operator bool());
619462e066SShawn McCarney }
629462e066SShawn McCarney 
TEST(FileDescriptorTests,IntConstructor)639462e066SShawn McCarney TEST(FileDescriptorTests, IntConstructor)
649462e066SShawn McCarney {
659462e066SShawn McCarney     int fd = createOpenFileDescriptor();
669462e066SShawn McCarney     FileDescriptor descriptor{fd};
679462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd);
689462e066SShawn McCarney     EXPECT_TRUE(descriptor.operator bool());
699462e066SShawn McCarney     EXPECT_TRUE(isValid(fd));
709462e066SShawn McCarney }
719462e066SShawn McCarney 
TEST(FileDescriptorTests,MoveConstructor)729462e066SShawn McCarney TEST(FileDescriptorTests, MoveConstructor)
739462e066SShawn McCarney {
749462e066SShawn McCarney     // Create first FileDescriptor object with open file descriptor
759462e066SShawn McCarney     int fd = createOpenFileDescriptor();
769462e066SShawn McCarney     FileDescriptor descriptor1{fd};
779462e066SShawn McCarney     EXPECT_EQ(descriptor1(), fd);
789462e066SShawn McCarney     EXPECT_TRUE(isValid(fd));
799462e066SShawn McCarney 
809462e066SShawn McCarney     // Create second FileDescriptor object, moving in the contents of the first
819462e066SShawn McCarney     FileDescriptor descriptor2{std::move(descriptor1)};
829462e066SShawn McCarney 
839462e066SShawn McCarney     // Verify descriptor has been moved out of first object
849462e066SShawn McCarney     EXPECT_EQ(descriptor1(), -1);
859462e066SShawn McCarney 
869462e066SShawn McCarney     // Verify descriptor has been moved into second object
879462e066SShawn McCarney     EXPECT_EQ(descriptor2(), fd);
889462e066SShawn McCarney 
899462e066SShawn McCarney     // Verify descriptor is still valid/open
909462e066SShawn McCarney     EXPECT_TRUE(isValid(fd));
919462e066SShawn McCarney }
929462e066SShawn McCarney 
TEST(FileDescriptorTests,MoveAssignmentOperator)939462e066SShawn McCarney TEST(FileDescriptorTests, MoveAssignmentOperator)
949462e066SShawn McCarney {
959462e066SShawn McCarney     // Test where move is valid
969462e066SShawn McCarney     {
979462e066SShawn McCarney         // Create first FileDescriptor object with open file descriptor
989462e066SShawn McCarney         int fd1 = createOpenFileDescriptor();
999462e066SShawn McCarney         FileDescriptor descriptor1{fd1};
1009462e066SShawn McCarney         EXPECT_EQ(descriptor1(), fd1);
1019462e066SShawn McCarney         EXPECT_TRUE(isValid(fd1));
1029462e066SShawn McCarney 
1039462e066SShawn McCarney         // Create second FileDescriptor object with open file descriptor
1049462e066SShawn McCarney         int fd2 = createOpenFileDescriptor();
1059462e066SShawn McCarney         FileDescriptor descriptor2{fd2};
1069462e066SShawn McCarney         EXPECT_EQ(descriptor2(), fd2);
1079462e066SShawn McCarney         EXPECT_TRUE(isValid(fd2));
1089462e066SShawn McCarney 
1099462e066SShawn McCarney         // Move second FileDescriptor object into the first
1109462e066SShawn McCarney         descriptor1 = std::move(descriptor2);
1119462e066SShawn McCarney 
1129462e066SShawn McCarney         // Verify second file descriptor has been moved into first object
1139462e066SShawn McCarney         EXPECT_EQ(descriptor1(), fd2);
1149462e066SShawn McCarney 
1159462e066SShawn McCarney         // Verify second file descriptor has been moved out of second object
1169462e066SShawn McCarney         EXPECT_EQ(descriptor2(), -1);
1179462e066SShawn McCarney 
1189462e066SShawn McCarney         // Verify first file descriptor has been closed and is no longer valid
1199462e066SShawn McCarney         EXPECT_FALSE(isValid(fd1));
1209462e066SShawn McCarney 
1219462e066SShawn McCarney         // Verify second file descriptor is still valid
1229462e066SShawn McCarney         EXPECT_TRUE(isValid(fd2));
1239462e066SShawn McCarney     }
1249462e066SShawn McCarney 
1259462e066SShawn McCarney     // Test where move is invalid: Attempt to move object into itself
1269462e066SShawn McCarney     {
1279462e066SShawn McCarney         // Create FileDescriptor object with open file descriptor
1289462e066SShawn McCarney         int fd = createOpenFileDescriptor();
1299462e066SShawn McCarney         FileDescriptor descriptor{fd};
1309462e066SShawn McCarney         EXPECT_EQ(descriptor(), fd);
1319462e066SShawn McCarney         EXPECT_TRUE(isValid(fd));
1329462e066SShawn McCarney 
1339462e066SShawn McCarney         // Try to move object into itself
134*81e554c8SPatrick Williams         descriptor = static_cast<FileDescriptor&&>(descriptor);
1359462e066SShawn McCarney 
1369462e066SShawn McCarney         // Verify object still contains file descriptor
1379462e066SShawn McCarney         EXPECT_EQ(descriptor(), fd);
1389462e066SShawn McCarney         EXPECT_TRUE(isValid(fd));
1399462e066SShawn McCarney     }
1409462e066SShawn McCarney }
1419462e066SShawn McCarney 
TEST(FileDescriptorTests,Destructor)1429462e066SShawn McCarney TEST(FileDescriptorTests, Destructor)
1439462e066SShawn McCarney {
1449462e066SShawn McCarney     // Test where file descriptor was never set
1459462e066SShawn McCarney     {
1469462e066SShawn McCarney         FileDescriptor descriptor;
1479462e066SShawn McCarney         EXPECT_EQ(descriptor(), -1);
1489462e066SShawn McCarney     }
1499462e066SShawn McCarney 
1509462e066SShawn McCarney     // Test where file descriptor was already closed
1519462e066SShawn McCarney     {
1529462e066SShawn McCarney         // Create FileDescriptor object with open file descriptor.  Close the
1539462e066SShawn McCarney         // descriptor explicitly.
1549462e066SShawn McCarney         int fd = createOpenFileDescriptor();
1559462e066SShawn McCarney         {
1569462e066SShawn McCarney             FileDescriptor descriptor{fd};
1579462e066SShawn McCarney             EXPECT_EQ(descriptor(), fd);
1589462e066SShawn McCarney             EXPECT_TRUE(isValid(fd));
1599462e066SShawn McCarney 
1609462e066SShawn McCarney             EXPECT_EQ(descriptor.close(), 0);
1619462e066SShawn McCarney             EXPECT_EQ(descriptor(), -1);
1629462e066SShawn McCarney             EXPECT_FALSE(isValid(fd));
1639462e066SShawn McCarney         }
1649462e066SShawn McCarney         EXPECT_FALSE(isValid(fd));
1659462e066SShawn McCarney     }
1669462e066SShawn McCarney 
1679462e066SShawn McCarney     // Test where file descriptor needs to be closed
1689462e066SShawn McCarney     {
1699462e066SShawn McCarney         // Create FileDescriptor object with open file descriptor.  Destructor
1709462e066SShawn McCarney         // will close descriptor.
1719462e066SShawn McCarney         int fd = createOpenFileDescriptor();
1729462e066SShawn McCarney         {
1739462e066SShawn McCarney             FileDescriptor descriptor{fd};
1749462e066SShawn McCarney             EXPECT_EQ(descriptor(), fd);
1759462e066SShawn McCarney             EXPECT_TRUE(isValid(fd));
1769462e066SShawn McCarney         }
1779462e066SShawn McCarney         EXPECT_FALSE(isValid(fd));
1789462e066SShawn McCarney     }
1799462e066SShawn McCarney }
1809462e066SShawn McCarney 
TEST(FileDescriptorTests,FunctionCallOperator)1819462e066SShawn McCarney TEST(FileDescriptorTests, FunctionCallOperator)
1829462e066SShawn McCarney {
1839462e066SShawn McCarney     // Test where FileDescriptor object does not contain a valid file descriptor
1849462e066SShawn McCarney     FileDescriptor descriptor{};
1859462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
1869462e066SShawn McCarney 
1879462e066SShawn McCarney     // Test where FileDescriptor object contains a valid file descriptor
1889462e066SShawn McCarney     int fd = createOpenFileDescriptor();
1899462e066SShawn McCarney     descriptor.set(fd);
1909462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd);
1919462e066SShawn McCarney }
1929462e066SShawn McCarney 
TEST(FileDescriptorTests,OperatorBool)1939462e066SShawn McCarney TEST(FileDescriptorTests, OperatorBool)
1949462e066SShawn McCarney {
1959462e066SShawn McCarney     // Test where FileDescriptor object does not contain a valid file descriptor
1969462e066SShawn McCarney     FileDescriptor descriptor{};
1979462e066SShawn McCarney     EXPECT_FALSE(descriptor.operator bool());
1989462e066SShawn McCarney     if (descriptor)
1999462e066SShawn McCarney     {
2009462e066SShawn McCarney         ADD_FAILURE() << "Should not have reached this line.";
2019462e066SShawn McCarney     }
2029462e066SShawn McCarney 
2039462e066SShawn McCarney     // Test where FileDescriptor object contains a valid file descriptor
2049462e066SShawn McCarney     int fd = createOpenFileDescriptor();
2059462e066SShawn McCarney     descriptor.set(fd);
2069462e066SShawn McCarney     EXPECT_TRUE(descriptor.operator bool());
2079462e066SShawn McCarney     if (!descriptor)
2089462e066SShawn McCarney     {
2099462e066SShawn McCarney         ADD_FAILURE() << "Should not have reached this line.";
2109462e066SShawn McCarney     }
2119462e066SShawn McCarney 
2129462e066SShawn McCarney     // Test where file descriptor has been closed
2139462e066SShawn McCarney     EXPECT_EQ(descriptor.close(), 0);
2149462e066SShawn McCarney     EXPECT_FALSE(descriptor.operator bool());
2159462e066SShawn McCarney     if (descriptor)
2169462e066SShawn McCarney     {
2179462e066SShawn McCarney         ADD_FAILURE() << "Should not have reached this line.";
2189462e066SShawn McCarney     }
2199462e066SShawn McCarney }
2209462e066SShawn McCarney 
TEST(FileDescriptorTests,Close)2219462e066SShawn McCarney TEST(FileDescriptorTests, Close)
2229462e066SShawn McCarney {
2239462e066SShawn McCarney     // Test where object contains an open file descriptor
2249462e066SShawn McCarney     int fd = createOpenFileDescriptor();
2259462e066SShawn McCarney     FileDescriptor descriptor{fd};
2269462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd);
2279462e066SShawn McCarney     EXPECT_TRUE(isValid(fd));
2289462e066SShawn McCarney     EXPECT_EQ(descriptor.close(), 0);
2299462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
2309462e066SShawn McCarney     EXPECT_FALSE(isValid(fd));
2319462e066SShawn McCarney 
2329462e066SShawn McCarney     // Test where object does not contain an open file descriptor
2339462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
2349462e066SShawn McCarney     EXPECT_EQ(descriptor.close(), 0);
2359462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
2369462e066SShawn McCarney 
2379462e066SShawn McCarney     // Test where close() fails due to invalid file descriptor
2389462e066SShawn McCarney     descriptor.set(999999);
2399462e066SShawn McCarney     EXPECT_EQ(descriptor.close(), -1);
2409462e066SShawn McCarney     EXPECT_EQ(errno, EBADF);
2419462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
2429462e066SShawn McCarney }
2439462e066SShawn McCarney 
TEST(FileDescriptorTests,Set)2449462e066SShawn McCarney TEST(FileDescriptorTests, Set)
2459462e066SShawn McCarney {
2469462e066SShawn McCarney     // Test where object does not contain an open file descriptor
2479462e066SShawn McCarney     FileDescriptor descriptor{};
2489462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
2499462e066SShawn McCarney     int fd1 = createOpenFileDescriptor();
2509462e066SShawn McCarney     descriptor.set(fd1);
2519462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd1);
2529462e066SShawn McCarney     EXPECT_TRUE(isValid(fd1));
2539462e066SShawn McCarney 
2549462e066SShawn McCarney     // Test where object contains an open file descriptor.  Should close
2559462e066SShawn McCarney     // previous descriptor.
2569462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd1);
2579462e066SShawn McCarney     EXPECT_TRUE(isValid(fd1));
2589462e066SShawn McCarney     int fd2 = createOpenFileDescriptor();
2599462e066SShawn McCarney     descriptor.set(fd2);
2609462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd2);
2619462e066SShawn McCarney     EXPECT_FALSE(isValid(fd1));
2629462e066SShawn McCarney     EXPECT_TRUE(isValid(fd2));
2639462e066SShawn McCarney 
2649462e066SShawn McCarney     // Test where -1 is specified.  Should close previous descriptor.
2659462e066SShawn McCarney     EXPECT_EQ(descriptor(), fd2);
2669462e066SShawn McCarney     EXPECT_TRUE(isValid(fd2));
2679462e066SShawn McCarney     descriptor.set(-1);
2689462e066SShawn McCarney     EXPECT_EQ(descriptor(), -1);
2699462e066SShawn McCarney     EXPECT_FALSE(isValid(fd2));
2709462e066SShawn McCarney }
271