#include #include #include #include #include #include #include #include #include #include #include namespace gpioplus { namespace { using testing::DoAll; using testing::Return; using testing::SaveArgPointee; using testing::SetArgPointee; using testing::StrEq; TEST(LineFlagsTest, LineFlagsFromFlags) { LineFlags line_flags(GPIOLINE_FLAG_KERNEL | GPIOLINE_FLAG_OPEN_DRAIN | GPIOLINE_FLAG_OPEN_SOURCE); EXPECT_TRUE(line_flags.kernel); EXPECT_FALSE(line_flags.output); EXPECT_FALSE(line_flags.active_low); EXPECT_TRUE(line_flags.open_drain); EXPECT_TRUE(line_flags.open_source); line_flags = GPIOLINE_FLAG_IS_OUT | GPIOLINE_FLAG_ACTIVE_LOW; EXPECT_FALSE(line_flags.kernel); EXPECT_TRUE(line_flags.output); EXPECT_TRUE(line_flags.active_low); EXPECT_FALSE(line_flags.open_drain); EXPECT_FALSE(line_flags.open_source); } class ChipMethodTest : public testing::Test { protected: const int expected_fd = 1234; testing::StrictMock mock; std::unique_ptr chip; void SetUp() { const int chip_id = 1; const char* path = "/dev/gpiochip1"; EXPECT_CALL(mock, open(StrEq(path), O_RDONLY | O_CLOEXEC)) .WillOnce(Return(expected_fd)); chip = std::make_unique(chip_id, &mock); } void TearDown() { EXPECT_CALL(mock, close(expected_fd)).WillOnce(Return(0)); chip.reset(); } }; TEST_F(ChipMethodTest, Basic) { EXPECT_EQ(expected_fd, *chip->getFd()); EXPECT_EQ(&mock, chip->getFd().getSys()); } TEST_F(ChipMethodTest, GetChipInfoSuccess) { const ChipInfo expected_info{"name", "label", 31}; struct gpiochip_info info; ASSERT_LE(expected_info.name.size(), sizeof(info.name)); strcpy(info.name, expected_info.name.c_str()); ASSERT_LE(expected_info.label.size(), sizeof(info.label)); strcpy(info.label, expected_info.label.c_str()); info.lines = expected_info.lines; EXPECT_CALL(mock, gpio_get_chipinfo(expected_fd, testing::_)) .WillOnce(DoAll(SetArgPointee<1>(info), Return(0))); ChipInfo retrieved_info = chip->getChipInfo(); EXPECT_EQ(expected_info.name, retrieved_info.name); EXPECT_EQ(expected_info.label, retrieved_info.label); EXPECT_EQ(expected_info.lines, retrieved_info.lines); } TEST_F(ChipMethodTest, GetChipInfoFail) { EXPECT_CALL(mock, gpio_get_chipinfo(expected_fd, testing::_)) .WillOnce(Return(-EINVAL)); EXPECT_THROW(chip->getChipInfo(), std::system_error); } TEST_F(ChipMethodTest, GetLineInfoSuccess) { const uint32_t line = 176; const LineInfo expected_info{GPIOLINE_FLAG_ACTIVE_LOW, "name", "consumer"}; struct gpioline_info info, req; info.flags = GPIOLINE_FLAG_ACTIVE_LOW; ASSERT_LE(expected_info.name.size(), sizeof(info.name)); strcpy(info.name, expected_info.name.c_str()); ASSERT_LE(expected_info.consumer.size(), sizeof(info.consumer)); strcpy(info.consumer, expected_info.consumer.c_str()); EXPECT_CALL(mock, gpio_get_lineinfo(expected_fd, testing::_)) .WillOnce( DoAll(SaveArgPointee<1>(&req), SetArgPointee<1>(info), Return(0))); LineInfo retrieved_info = chip->getLineInfo(line); EXPECT_EQ(line, req.line_offset); EXPECT_FALSE(retrieved_info.flags.kernel); EXPECT_FALSE(retrieved_info.flags.output); EXPECT_TRUE(retrieved_info.flags.active_low); EXPECT_FALSE(retrieved_info.flags.open_drain); EXPECT_FALSE(retrieved_info.flags.open_source); EXPECT_EQ(expected_info.name, retrieved_info.name); EXPECT_EQ(expected_info.consumer, retrieved_info.consumer); } TEST_F(ChipMethodTest, GetLineInfoFail) { const uint32_t line = 143; struct gpioline_info info; EXPECT_CALL(mock, gpio_get_lineinfo(expected_fd, testing::_)) .WillOnce(DoAll(SaveArgPointee<1>(&info), Return(-EINVAL))); EXPECT_THROW(chip->getLineInfo(line), std::system_error); EXPECT_EQ(line, info.line_offset); } } // namespace } // namespace gpioplus