1 #include <cerrno> 2 #include <cstdint> 3 #include <cstring> 4 #include <fcntl.h> 5 #include <gmock/gmock.h> 6 #include <gpioplus/chip.hpp> 7 #include <gpioplus/test/sys.hpp> 8 #include <gtest/gtest.h> 9 #include <linux/gpio.h> 10 #include <memory> 11 #include <system_error> 12 13 namespace gpioplus 14 { 15 namespace 16 { 17 18 using testing::DoAll; 19 using testing::Return; 20 using testing::SaveArgPointee; 21 using testing::SetArgPointee; 22 using testing::StrEq; 23 24 TEST(LineFlagsTest, LineFlagsFromFlags) 25 { 26 LineFlags line_flags(GPIOLINE_FLAG_KERNEL | GPIOLINE_FLAG_OPEN_DRAIN | 27 GPIOLINE_FLAG_OPEN_SOURCE); 28 EXPECT_TRUE(line_flags.kernel); 29 EXPECT_FALSE(line_flags.output); 30 EXPECT_FALSE(line_flags.active_low); 31 EXPECT_TRUE(line_flags.open_drain); 32 EXPECT_TRUE(line_flags.open_source); 33 34 line_flags = GPIOLINE_FLAG_IS_OUT | GPIOLINE_FLAG_ACTIVE_LOW; 35 EXPECT_FALSE(line_flags.kernel); 36 EXPECT_TRUE(line_flags.output); 37 EXPECT_TRUE(line_flags.active_low); 38 EXPECT_FALSE(line_flags.open_drain); 39 EXPECT_FALSE(line_flags.open_source); 40 } 41 42 class ChipMethodTest : public testing::Test 43 { 44 protected: 45 const int expected_fd = 1234; 46 testing::StrictMock<test::SysMock> mock; 47 std::unique_ptr<Chip> chip; 48 49 void SetUp() 50 { 51 const int chip_id = 1; 52 const char* path = "/dev/gpiochip1"; 53 54 EXPECT_CALL(mock, open(StrEq(path), O_RDONLY | O_CLOEXEC)) 55 .WillOnce(Return(expected_fd)); 56 chip = std::make_unique<Chip>(chip_id, &mock); 57 } 58 59 void TearDown() 60 { 61 EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0)); 62 chip.reset(); 63 } 64 }; 65 66 TEST_F(ChipMethodTest, Basic) 67 { 68 EXPECT_EQ(expected_fd, *chip->getFd()); 69 EXPECT_EQ(&mock, chip->getFd().getSys()); 70 } 71 72 TEST_F(ChipMethodTest, GetChipInfoSuccess) 73 { 74 const ChipInfo expected_info{"name", "label", 31}; 75 struct gpiochip_info info; 76 ASSERT_LE(expected_info.name.size(), sizeof(info.name)); 77 strcpy(info.name, expected_info.name.c_str()); 78 ASSERT_LE(expected_info.label.size(), sizeof(info.label)); 79 strcpy(info.label, expected_info.label.c_str()); 80 info.lines = expected_info.lines; 81 82 EXPECT_CALL(mock, gpio_get_chipinfo(expected_fd, testing::_)) 83 .WillOnce(DoAll(SetArgPointee<1>(info), Return(0))); 84 ChipInfo retrieved_info = chip->getChipInfo(); 85 EXPECT_EQ(expected_info.name, retrieved_info.name); 86 EXPECT_EQ(expected_info.label, retrieved_info.label); 87 EXPECT_EQ(expected_info.lines, retrieved_info.lines); 88 } 89 90 TEST_F(ChipMethodTest, GetChipInfoFail) 91 { 92 EXPECT_CALL(mock, gpio_get_chipinfo(expected_fd, testing::_)) 93 .WillOnce(Return(-EINVAL)); 94 EXPECT_THROW(chip->getChipInfo(), std::system_error); 95 } 96 97 TEST_F(ChipMethodTest, GetLineInfoSuccess) 98 { 99 const uint32_t line = 176; 100 const LineInfo expected_info{GPIOLINE_FLAG_ACTIVE_LOW, "name", "consumer"}; 101 struct gpioline_info info, req; 102 info.flags = GPIOLINE_FLAG_ACTIVE_LOW; 103 ASSERT_LE(expected_info.name.size(), sizeof(info.name)); 104 strcpy(info.name, expected_info.name.c_str()); 105 ASSERT_LE(expected_info.consumer.size(), sizeof(info.consumer)); 106 strcpy(info.consumer, expected_info.consumer.c_str()); 107 108 EXPECT_CALL(mock, gpio_get_lineinfo(expected_fd, testing::_)) 109 .WillOnce( 110 DoAll(SaveArgPointee<1>(&req), SetArgPointee<1>(info), Return(0))); 111 LineInfo retrieved_info = chip->getLineInfo(line); 112 EXPECT_EQ(line, req.line_offset); 113 EXPECT_FALSE(retrieved_info.flags.kernel); 114 EXPECT_FALSE(retrieved_info.flags.output); 115 EXPECT_TRUE(retrieved_info.flags.active_low); 116 EXPECT_FALSE(retrieved_info.flags.open_drain); 117 EXPECT_FALSE(retrieved_info.flags.open_source); 118 EXPECT_EQ(expected_info.name, retrieved_info.name); 119 EXPECT_EQ(expected_info.consumer, retrieved_info.consumer); 120 } 121 122 TEST_F(ChipMethodTest, GetLineInfoFail) 123 { 124 const uint32_t line = 143; 125 126 struct gpioline_info info; 127 EXPECT_CALL(mock, gpio_get_lineinfo(expected_fd, testing::_)) 128 .WillOnce(DoAll(SaveArgPointee<1>(&info), Return(-EINVAL))); 129 EXPECT_THROW(chip->getLineInfo(line), std::system_error); 130 EXPECT_EQ(line, info.line_offset); 131 } 132 133 } // namespace 134 } // namespace gpioplus 135