xref: /openbmc/gpioplus/test/internal/fd.cpp (revision ab995c50185c37cf11e8b9fefcbb184bcd516e2d)
126954bd4SWilliam A. Kennington III #include <fcntl.h>
226954bd4SWilliam A. Kennington III #include <signal.h>
326954bd4SWilliam A. Kennington III #include <sys/prctl.h>
47ba248adSPatrick Williams 
57ba248adSPatrick Williams #include <gpioplus/internal/fd.hpp>
67ba248adSPatrick Williams #include <gpioplus/test/sys.hpp>
77ba248adSPatrick Williams 
87ba248adSPatrick Williams #include <cerrno>
97ba248adSPatrick Williams #include <cstring>
107ba248adSPatrick Williams #include <memory>
1126954bd4SWilliam A. Kennington III #include <system_error>
1226954bd4SWilliam A. Kennington III #include <type_traits>
1326954bd4SWilliam A. Kennington III #include <utility>
1426954bd4SWilliam A. Kennington III 
157ba248adSPatrick Williams #include <gmock/gmock.h>
167ba248adSPatrick Williams #include <gtest/gtest.h>
177ba248adSPatrick Williams 
1826954bd4SWilliam A. Kennington III #ifdef HAVE_GCOV
1926954bd4SWilliam A. Kennington III // Needed for the abrt test
2026954bd4SWilliam A. Kennington III extern "C" void __gcov_flush(void);
2126954bd4SWilliam A. Kennington III #endif
2226954bd4SWilliam A. Kennington III 
2326954bd4SWilliam A. Kennington III namespace gpioplus
2426954bd4SWilliam A. Kennington III {
2526954bd4SWilliam A. Kennington III namespace internal
2626954bd4SWilliam A. Kennington III {
2726954bd4SWilliam A. Kennington III namespace
2826954bd4SWilliam A. Kennington III {
2926954bd4SWilliam A. Kennington III 
3026954bd4SWilliam A. Kennington III using testing::Assign;
3126954bd4SWilliam A. Kennington III using testing::DoAll;
3226954bd4SWilliam A. Kennington III using testing::Return;
3326954bd4SWilliam A. Kennington III 
3426954bd4SWilliam A. Kennington III class FdTest : public testing::Test
3526954bd4SWilliam A. Kennington III {
3626954bd4SWilliam A. Kennington III   protected:
3726954bd4SWilliam A. Kennington III     const int expected_fd = 1234;
3826954bd4SWilliam A. Kennington III     const int expected_fd2 = 2345;
3926954bd4SWilliam A. Kennington III     const int expected_fd3 = 3456;
4026954bd4SWilliam A. Kennington III     testing::StrictMock<test::SysMock> mock;
4126954bd4SWilliam A. Kennington III     testing::StrictMock<test::SysMock> mock2;
4226954bd4SWilliam A. Kennington III };
4326954bd4SWilliam A. Kennington III 
TEST_F(FdTest,ConstructSimple)4426954bd4SWilliam A. Kennington III TEST_F(FdTest, ConstructSimple)
4526954bd4SWilliam A. Kennington III {
4626954bd4SWilliam A. Kennington III     Fd fd(expected_fd, std::false_type(), &mock);
4726954bd4SWilliam A. Kennington III     EXPECT_EQ(expected_fd, *fd);
4826954bd4SWilliam A. Kennington III     EXPECT_EQ(&mock, fd.getSys());
4926954bd4SWilliam A. Kennington III 
5026954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0));
5126954bd4SWilliam A. Kennington III }
5226954bd4SWilliam A. Kennington III 
TEST_F(FdTest,ConstructSimplBadFd)5326954bd4SWilliam A. Kennington III TEST_F(FdTest, ConstructSimplBadFd)
5426954bd4SWilliam A. Kennington III {
5526954bd4SWilliam A. Kennington III     Fd fd(-1, std::false_type(), &mock);
5626954bd4SWilliam A. Kennington III     EXPECT_EQ(-1, *fd);
5726954bd4SWilliam A. Kennington III }
5826954bd4SWilliam A. Kennington III 
TEST_F(FdTest,ConstructDup)5926954bd4SWilliam A. Kennington III TEST_F(FdTest, ConstructDup)
6026954bd4SWilliam A. Kennington III {
6126954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, dup(expected_fd)).WillOnce(Return(expected_fd2));
6226954bd4SWilliam A. Kennington III     Fd fd(expected_fd, &mock);
6326954bd4SWilliam A. Kennington III     EXPECT_EQ(expected_fd2, *fd);
6426954bd4SWilliam A. Kennington III     EXPECT_EQ(&mock, fd.getSys());
6526954bd4SWilliam A. Kennington III 
6626954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, close(expected_fd2)).WillOnce(Return(0));
6726954bd4SWilliam A. Kennington III }
6826954bd4SWilliam A. Kennington III 
TEST_F(FdTest,ConstructDupFail)6926954bd4SWilliam A. Kennington III TEST_F(FdTest, ConstructDupFail)
7026954bd4SWilliam A. Kennington III {
7126954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, dup(expected_fd))
7226954bd4SWilliam A. Kennington III         .WillOnce(DoAll(Assign(&errno, EINVAL), Return(-1)));
7326954bd4SWilliam A. Kennington III     EXPECT_THROW(Fd(expected_fd, &mock), std::system_error);
7426954bd4SWilliam A. Kennington III }
7526954bd4SWilliam A. Kennington III 
abrt_handler(int signum)7626954bd4SWilliam A. Kennington III void abrt_handler(int signum)
7726954bd4SWilliam A. Kennington III {
7826954bd4SWilliam A. Kennington III     if (signum == SIGABRT)
7926954bd4SWilliam A. Kennington III     {
8026954bd4SWilliam A. Kennington III #ifdef HAVE_GCOV
8126954bd4SWilliam A. Kennington III         __gcov_flush();
8226954bd4SWilliam A. Kennington III #endif
8326954bd4SWilliam A. Kennington III     }
8426954bd4SWilliam A. Kennington III }
8526954bd4SWilliam A. Kennington III 
TEST_F(FdTest,CloseFails)8626954bd4SWilliam A. Kennington III TEST_F(FdTest, CloseFails)
8726954bd4SWilliam A. Kennington III {
8826954bd4SWilliam A. Kennington III     EXPECT_DEATH(
8926954bd4SWilliam A. Kennington III         {
9026954bd4SWilliam A. Kennington III             struct sigaction act;
9126954bd4SWilliam A. Kennington III             act.sa_handler = abrt_handler;
9226954bd4SWilliam A. Kennington III             sigemptyset(&act.sa_mask);
9326954bd4SWilliam A. Kennington III             act.sa_flags = 0;
9426954bd4SWilliam A. Kennington III             ASSERT_EQ(0, sigaction(SIGABRT, &act, nullptr));
9526954bd4SWilliam A. Kennington III             ASSERT_EQ(0, prctl(PR_SET_DUMPABLE, 0, 0, 0, 0));
9626954bd4SWilliam A. Kennington III             EXPECT_CALL(mock, close(expected_fd))
9726954bd4SWilliam A. Kennington III                 .WillOnce(DoAll(Assign(&errno, EINVAL), Return(-1)));
9826954bd4SWilliam A. Kennington III             Fd(expected_fd, std::false_type(), &mock);
9926954bd4SWilliam A. Kennington III         },
10026954bd4SWilliam A. Kennington III         "");
10126954bd4SWilliam A. Kennington III }
10226954bd4SWilliam A. Kennington III 
TEST_F(FdTest,ConstructSuccess)10326954bd4SWilliam A. Kennington III TEST_F(FdTest, ConstructSuccess)
10426954bd4SWilliam A. Kennington III {
10526954bd4SWilliam A. Kennington III     const char* path = "/no-such-path/gpio";
10626954bd4SWilliam A. Kennington III     const int flags = O_RDWR;
10726954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, open(path, flags)).WillOnce(Return(expected_fd));
10826954bd4SWilliam A. Kennington III     Fd fd(path, flags, &mock);
10926954bd4SWilliam A. Kennington III     EXPECT_EQ(expected_fd, *fd);
11026954bd4SWilliam A. Kennington III     EXPECT_EQ(&mock, fd.getSys());
11126954bd4SWilliam A. Kennington III 
11226954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0));
11326954bd4SWilliam A. Kennington III }
11426954bd4SWilliam A. Kennington III 
TEST_F(FdTest,ConstructError)11526954bd4SWilliam A. Kennington III TEST_F(FdTest, ConstructError)
11626954bd4SWilliam A. Kennington III {
11726954bd4SWilliam A. Kennington III     const char* path = "/no-such-path/gpio";
11826954bd4SWilliam A. Kennington III     const int flags = O_RDWR;
11926954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, open(path, flags))
12026954bd4SWilliam A. Kennington III         .WillOnce(DoAll(Assign(&errno, EBUSY), Return(-1)));
12126954bd4SWilliam A. Kennington III     EXPECT_THROW(Fd(path, flags, &mock), std::system_error);
12226954bd4SWilliam A. Kennington III }
12326954bd4SWilliam A. Kennington III 
TEST_F(FdTest,ConstructCopy)12426954bd4SWilliam A. Kennington III TEST_F(FdTest, ConstructCopy)
12526954bd4SWilliam A. Kennington III {
12626954bd4SWilliam A. Kennington III     Fd fd(expected_fd, std::false_type(), &mock);
12726954bd4SWilliam A. Kennington III     {
12826954bd4SWilliam A. Kennington III         EXPECT_CALL(mock, dup(expected_fd)).WillOnce(Return(expected_fd2));
12926954bd4SWilliam A. Kennington III         Fd fd2(fd);
13026954bd4SWilliam A. Kennington III         EXPECT_EQ(expected_fd2, *fd2);
13126954bd4SWilliam A. Kennington III         EXPECT_EQ(expected_fd, *fd);
13226954bd4SWilliam A. Kennington III 
13326954bd4SWilliam A. Kennington III         EXPECT_CALL(mock, close(expected_fd2)).WillOnce(Return(0));
13426954bd4SWilliam A. Kennington III     }
13526954bd4SWilliam A. Kennington III 
13626954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0));
13726954bd4SWilliam A. Kennington III }
13826954bd4SWilliam A. Kennington III 
TEST_F(FdTest,OperatorCopySame)13926954bd4SWilliam A. Kennington III TEST_F(FdTest, OperatorCopySame)
14026954bd4SWilliam A. Kennington III {
14126954bd4SWilliam A. Kennington III     Fd fd(expected_fd, std::false_type(), &mock);
14226954bd4SWilliam A. Kennington III     fd = fd;
14326954bd4SWilliam A. Kennington III     EXPECT_EQ(expected_fd, *fd);
14426954bd4SWilliam A. Kennington III 
14526954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0));
14626954bd4SWilliam A. Kennington III }
14726954bd4SWilliam A. Kennington III 
TEST_F(FdTest,OperatorCopy)14826954bd4SWilliam A. Kennington III TEST_F(FdTest, OperatorCopy)
14926954bd4SWilliam A. Kennington III {
15026954bd4SWilliam A. Kennington III     Fd fd(expected_fd, std::false_type(), &mock);
15126954bd4SWilliam A. Kennington III     {
15226954bd4SWilliam A. Kennington III         Fd fd2(expected_fd2, std::false_type(), &mock2);
15326954bd4SWilliam A. Kennington III         EXPECT_CALL(mock2, close(expected_fd2)).WillOnce(Return(0));
15426954bd4SWilliam A. Kennington III         EXPECT_CALL(mock, dup(expected_fd)).WillOnce(Return(expected_fd3));
15526954bd4SWilliam A. Kennington III         fd2 = fd;
15626954bd4SWilliam A. Kennington III         EXPECT_EQ(expected_fd3, *fd2);
15726954bd4SWilliam A. Kennington III         EXPECT_EQ(&mock, fd2.getSys());
15826954bd4SWilliam A. Kennington III         EXPECT_EQ(expected_fd, *fd);
15926954bd4SWilliam A. Kennington III         EXPECT_EQ(&mock, fd.getSys());
16026954bd4SWilliam A. Kennington III 
16126954bd4SWilliam A. Kennington III         EXPECT_CALL(mock, close(expected_fd3)).WillOnce(Return(0));
16226954bd4SWilliam A. Kennington III     }
16326954bd4SWilliam A. Kennington III 
16426954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0));
16526954bd4SWilliam A. Kennington III }
16626954bd4SWilliam A. Kennington III 
TEST_F(FdTest,ConstructMove)16726954bd4SWilliam A. Kennington III TEST_F(FdTest, ConstructMove)
16826954bd4SWilliam A. Kennington III {
16926954bd4SWilliam A. Kennington III     Fd fd(expected_fd, std::false_type(), &mock);
17026954bd4SWilliam A. Kennington III     {
17126954bd4SWilliam A. Kennington III         Fd fd2(std::move(fd));
17226954bd4SWilliam A. Kennington III         EXPECT_EQ(expected_fd, *fd2);
17326954bd4SWilliam A. Kennington III         EXPECT_EQ(-1, *fd);
17426954bd4SWilliam A. Kennington III 
17526954bd4SWilliam A. Kennington III         EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0));
17626954bd4SWilliam A. Kennington III     }
17726954bd4SWilliam A. Kennington III }
17826954bd4SWilliam A. Kennington III 
TEST_F(FdTest,OperatorMoveSame)17926954bd4SWilliam A. Kennington III TEST_F(FdTest, OperatorMoveSame)
18026954bd4SWilliam A. Kennington III {
18126954bd4SWilliam A. Kennington III     Fd fd(expected_fd, std::false_type(), &mock);
182*ab995c50SPatrick Williams     // Test move operator but newer compilers complain about move-to-self
183*ab995c50SPatrick Williams     // so use an explicit r-value ref cast to do the same.
184*ab995c50SPatrick Williams     fd = static_cast<Fd&&>(fd);
18526954bd4SWilliam A. Kennington III     EXPECT_EQ(expected_fd, *fd);
18626954bd4SWilliam A. Kennington III 
18726954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0));
18826954bd4SWilliam A. Kennington III }
18926954bd4SWilliam A. Kennington III 
TEST_F(FdTest,OperatorMove)19026954bd4SWilliam A. Kennington III TEST_F(FdTest, OperatorMove)
19126954bd4SWilliam A. Kennington III {
19226954bd4SWilliam A. Kennington III     Fd fd(expected_fd, std::false_type(), &mock);
19326954bd4SWilliam A. Kennington III     {
19426954bd4SWilliam A. Kennington III         Fd fd2(expected_fd2, std::false_type(), &mock2);
19526954bd4SWilliam A. Kennington III         EXPECT_CALL(mock2, close(expected_fd2)).WillOnce(Return(0));
19626954bd4SWilliam A. Kennington III         fd2 = std::move(fd);
19726954bd4SWilliam A. Kennington III         EXPECT_EQ(expected_fd, *fd2);
19826954bd4SWilliam A. Kennington III         EXPECT_EQ(&mock, fd2.getSys());
19926954bd4SWilliam A. Kennington III         EXPECT_EQ(-1, *fd);
20026954bd4SWilliam A. Kennington III         EXPECT_EQ(&mock, fd.getSys());
20126954bd4SWilliam A. Kennington III 
20226954bd4SWilliam A. Kennington III         EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0));
20326954bd4SWilliam A. Kennington III     }
20426954bd4SWilliam A. Kennington III }
20526954bd4SWilliam A. Kennington III 
20626954bd4SWilliam A. Kennington III class FdMethodTest : public FdTest
20726954bd4SWilliam A. Kennington III {
20826954bd4SWilliam A. Kennington III   protected:
20926954bd4SWilliam A. Kennington III     const int flags_blocking = O_SYNC | O_NOATIME;
21026954bd4SWilliam A. Kennington III     const int flags_noblocking = O_NONBLOCK | flags_blocking;
21126954bd4SWilliam A. Kennington III     std::unique_ptr<Fd> fd;
21226954bd4SWilliam A. Kennington III 
SetUp()21326954bd4SWilliam A. Kennington III     void SetUp()
21426954bd4SWilliam A. Kennington III     {
21526954bd4SWilliam A. Kennington III         fd = std::make_unique<Fd>(expected_fd, std::false_type(), &mock);
21626954bd4SWilliam A. Kennington III     }
21726954bd4SWilliam A. Kennington III 
TearDown()21826954bd4SWilliam A. Kennington III     void TearDown()
21926954bd4SWilliam A. Kennington III     {
22026954bd4SWilliam A. Kennington III         EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0));
22126954bd4SWilliam A. Kennington III         fd.reset();
22226954bd4SWilliam A. Kennington III     }
22326954bd4SWilliam A. Kennington III };
22426954bd4SWilliam A. Kennington III 
TEST_F(FdMethodTest,SetBlockingOnBlocking)22526954bd4SWilliam A. Kennington III TEST_F(FdMethodTest, SetBlockingOnBlocking)
22626954bd4SWilliam A. Kennington III {
22726954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_getfl(expected_fd))
22826954bd4SWilliam A. Kennington III         .WillOnce(Return(flags_blocking));
22926954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_setfl(expected_fd, flags_blocking))
23026954bd4SWilliam A. Kennington III         .WillOnce(Return(0));
23126954bd4SWilliam A. Kennington III     fd->setBlocking(true);
23226954bd4SWilliam A. Kennington III }
23326954bd4SWilliam A. Kennington III 
TEST_F(FdMethodTest,SetBlockingOnNonBlocking)23426954bd4SWilliam A. Kennington III TEST_F(FdMethodTest, SetBlockingOnNonBlocking)
23526954bd4SWilliam A. Kennington III {
23626954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_getfl(expected_fd))
23726954bd4SWilliam A. Kennington III         .WillOnce(Return(flags_noblocking));
23826954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_setfl(expected_fd, flags_blocking))
23926954bd4SWilliam A. Kennington III         .WillOnce(Return(0));
24026954bd4SWilliam A. Kennington III     fd->setBlocking(true);
24126954bd4SWilliam A. Kennington III }
24226954bd4SWilliam A. Kennington III 
TEST_F(FdMethodTest,SetNonBlockingOnBlocking)24326954bd4SWilliam A. Kennington III TEST_F(FdMethodTest, SetNonBlockingOnBlocking)
24426954bd4SWilliam A. Kennington III {
24526954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_getfl(expected_fd))
24626954bd4SWilliam A. Kennington III         .WillOnce(Return(flags_blocking));
24726954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_setfl(expected_fd, flags_noblocking))
24826954bd4SWilliam A. Kennington III         .WillOnce(Return(0));
24926954bd4SWilliam A. Kennington III     fd->setBlocking(false);
25026954bd4SWilliam A. Kennington III }
25126954bd4SWilliam A. Kennington III 
TEST_F(FdMethodTest,SetNonBlockingOnNonBlocking)25226954bd4SWilliam A. Kennington III TEST_F(FdMethodTest, SetNonBlockingOnNonBlocking)
25326954bd4SWilliam A. Kennington III {
25426954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_getfl(expected_fd))
25526954bd4SWilliam A. Kennington III         .WillOnce(Return(flags_noblocking));
25626954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_setfl(expected_fd, flags_noblocking))
25726954bd4SWilliam A. Kennington III         .WillOnce(Return(0));
25826954bd4SWilliam A. Kennington III     fd->setBlocking(false);
25926954bd4SWilliam A. Kennington III }
26026954bd4SWilliam A. Kennington III 
TEST_F(FdMethodTest,GetFlagsFail)26126954bd4SWilliam A. Kennington III TEST_F(FdMethodTest, GetFlagsFail)
26226954bd4SWilliam A. Kennington III {
26326954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_getfl(expected_fd))
26426954bd4SWilliam A. Kennington III         .WillOnce(DoAll(Assign(&errno, EINVAL), Return(-1)));
26526954bd4SWilliam A. Kennington III     EXPECT_THROW(fd->setBlocking(true), std::system_error);
26626954bd4SWilliam A. Kennington III }
26726954bd4SWilliam A. Kennington III 
TEST_F(FdMethodTest,SetFlagsFail)26826954bd4SWilliam A. Kennington III TEST_F(FdMethodTest, SetFlagsFail)
26926954bd4SWilliam A. Kennington III {
27026954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_getfl(expected_fd)).WillOnce(Return(0));
27126954bd4SWilliam A. Kennington III     EXPECT_CALL(mock, fcntl_setfl(expected_fd, 0))
27226954bd4SWilliam A. Kennington III         .WillOnce(DoAll(Assign(&errno, EINVAL), Return(-1)));
27326954bd4SWilliam A. Kennington III     EXPECT_THROW(fd->setBlocking(true), std::system_error);
27426954bd4SWilliam A. Kennington III }
27526954bd4SWilliam A. Kennington III 
27626954bd4SWilliam A. Kennington III } // namespace
27726954bd4SWilliam A. Kennington III } // namespace internal
27826954bd4SWilliam A. Kennington III } // namespace gpioplus
279