17ba248adSPatrick Williams #include <linux/gpio.h>
27ba248adSPatrick Williams
3f3942f6aSWilliam A. Kennington III #include <gpioplus/event.hpp>
4f3942f6aSWilliam A. Kennington III #include <gpioplus/test/sys.hpp>
57ba248adSPatrick Williams
67ba248adSPatrick Williams #include <cerrno>
77ba248adSPatrick Williams #include <cstring>
8f3942f6aSWilliam A. Kennington III #include <memory>
9f3942f6aSWilliam A. Kennington III #include <optional>
10f3942f6aSWilliam A. Kennington III #include <stdexcept>
11f3942f6aSWilliam A. Kennington III #include <string>
12f3942f6aSWilliam A. Kennington III #include <system_error>
13f3942f6aSWilliam A. Kennington III
147ba248adSPatrick Williams #include <gmock/gmock.h>
157ba248adSPatrick Williams #include <gtest/gtest.h>
167ba248adSPatrick Williams
17f3942f6aSWilliam A. Kennington III namespace gpioplus
18f3942f6aSWilliam A. Kennington III {
19f3942f6aSWilliam A. Kennington III namespace
20f3942f6aSWilliam A. Kennington III {
21f3942f6aSWilliam A. Kennington III
22f3942f6aSWilliam A. Kennington III using testing::Assign;
23f3942f6aSWilliam A. Kennington III using testing::DoAll;
24f3942f6aSWilliam A. Kennington III using testing::Return;
25f3942f6aSWilliam A. Kennington III using testing::SaveArgPointee;
26f3942f6aSWilliam A. Kennington III using testing::SetArgPointee;
27f3942f6aSWilliam A. Kennington III using testing::WithArg;
28f3942f6aSWilliam A. Kennington III
TEST(EventFlags,EventFlagsToInt)29f3942f6aSWilliam A. Kennington III TEST(EventFlags, EventFlagsToInt)
30f3942f6aSWilliam A. Kennington III {
31f3942f6aSWilliam A. Kennington III EventFlags event_flags;
32f3942f6aSWilliam A. Kennington III event_flags.rising_edge = true;
33f3942f6aSWilliam A. Kennington III event_flags.falling_edge = true;
34f3942f6aSWilliam A. Kennington III EXPECT_EQ(GPIOEVENT_REQUEST_RISING_EDGE | GPIOEVENT_REQUEST_FALLING_EDGE,
35f3942f6aSWilliam A. Kennington III event_flags.toInt());
36f3942f6aSWilliam A. Kennington III
37f3942f6aSWilliam A. Kennington III event_flags.rising_edge = false;
38f3942f6aSWilliam A. Kennington III event_flags.falling_edge = false;
39f3942f6aSWilliam A. Kennington III EXPECT_EQ(0, event_flags.toInt());
40f3942f6aSWilliam A. Kennington III }
41f3942f6aSWilliam A. Kennington III
42f3942f6aSWilliam A. Kennington III class EventTest : public testing::Test
43f3942f6aSWilliam A. Kennington III {
44f3942f6aSWilliam A. Kennington III protected:
45f3942f6aSWilliam A. Kennington III const int chip_fd = 1234;
46f3942f6aSWilliam A. Kennington III const int event_fd = 2345;
47f3942f6aSWilliam A. Kennington III testing::StrictMock<test::SysMock> mock;
48f3942f6aSWilliam A. Kennington III std::unique_ptr<Chip> chip;
49f3942f6aSWilliam A. Kennington III
SetUp()50f3942f6aSWilliam A. Kennington III void SetUp()
51f3942f6aSWilliam A. Kennington III {
52f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, open(testing::_, testing::_))
53f3942f6aSWilliam A. Kennington III .WillOnce(Return(chip_fd));
54f3942f6aSWilliam A. Kennington III chip = std::make_unique<Chip>(0, &mock);
55f3942f6aSWilliam A. Kennington III }
56f3942f6aSWilliam A. Kennington III
TearDown()57f3942f6aSWilliam A. Kennington III void TearDown()
58f3942f6aSWilliam A. Kennington III {
59f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, close(chip_fd)).WillOnce(Return(0));
60f3942f6aSWilliam A. Kennington III chip.reset();
61f3942f6aSWilliam A. Kennington III }
62f3942f6aSWilliam A. Kennington III };
63f3942f6aSWilliam A. Kennington III
TEST_F(EventTest,ConstructSuccess)64f3942f6aSWilliam A. Kennington III TEST_F(EventTest, ConstructSuccess)
65f3942f6aSWilliam A. Kennington III {
66f3942f6aSWilliam A. Kennington III const uint32_t line_offset = 3;
67f3942f6aSWilliam A. Kennington III const std::string label{"test"};
68f3942f6aSWilliam A. Kennington III HandleFlags handle_flags(LineFlags(0));
69f3942f6aSWilliam A. Kennington III EventFlags event_flags;
70f3942f6aSWilliam A. Kennington III event_flags.rising_edge = true;
71f3942f6aSWilliam A. Kennington III event_flags.falling_edge = false;
72f3942f6aSWilliam A. Kennington III
73f3942f6aSWilliam A. Kennington III struct gpioevent_request req, ret;
74f3942f6aSWilliam A. Kennington III ret.fd = event_fd;
75f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, gpio_get_lineevent(chip_fd, testing::_))
76f3942f6aSWilliam A. Kennington III .WillOnce(
77f3942f6aSWilliam A. Kennington III DoAll(SaveArgPointee<1>(&req), SetArgPointee<1>(ret), Return(0)));
78f3942f6aSWilliam A. Kennington III Event event(*chip, line_offset, handle_flags, event_flags, label.c_str());
79f3942f6aSWilliam A. Kennington III
80f3942f6aSWilliam A. Kennington III EXPECT_EQ(event_fd, *event.getFd());
81f3942f6aSWilliam A. Kennington III EXPECT_EQ(line_offset, req.lineoffset);
82f3942f6aSWilliam A. Kennington III EXPECT_EQ(GPIOHANDLE_REQUEST_INPUT, req.handleflags);
83f3942f6aSWilliam A. Kennington III EXPECT_EQ(GPIOEVENT_REQUEST_RISING_EDGE, req.eventflags);
84f3942f6aSWilliam A. Kennington III EXPECT_EQ(label, req.consumer_label);
85f3942f6aSWilliam A. Kennington III
86f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, close(event_fd)).WillOnce(Return(0));
87f3942f6aSWilliam A. Kennington III }
88f3942f6aSWilliam A. Kennington III
TEST_F(EventTest,ConstructLabelTooLong)8912cd2543SWilliam A. Kennington III TEST_F(EventTest, ConstructLabelTooLong)
9012cd2543SWilliam A. Kennington III {
9112cd2543SWilliam A. Kennington III const size_t large_size = sizeof(
9212cd2543SWilliam A. Kennington III reinterpret_cast<struct gpioevent_request*>(NULL)->consumer_label);
9312cd2543SWilliam A. Kennington III EXPECT_THROW(Event(*chip, 0, HandleFlags(), EventFlags(),
9412cd2543SWilliam A. Kennington III std::string(large_size, '1')),
9512cd2543SWilliam A. Kennington III std::invalid_argument);
9612cd2543SWilliam A. Kennington III }
9712cd2543SWilliam A. Kennington III
TEST_F(EventTest,ConstructFailure)98f3942f6aSWilliam A. Kennington III TEST_F(EventTest, ConstructFailure)
99f3942f6aSWilliam A. Kennington III {
100f3942f6aSWilliam A. Kennington III const uint32_t line_offset = 3;
101f3942f6aSWilliam A. Kennington III const std::string label{"test"};
102f3942f6aSWilliam A. Kennington III HandleFlags handle_flags(LineFlags(0));
103f3942f6aSWilliam A. Kennington III EventFlags event_flags;
104f3942f6aSWilliam A. Kennington III event_flags.rising_edge = false;
105f3942f6aSWilliam A. Kennington III event_flags.falling_edge = false;
106f3942f6aSWilliam A. Kennington III
107f3942f6aSWilliam A. Kennington III struct gpioevent_request req;
108f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, gpio_get_lineevent(chip_fd, testing::_))
109f3942f6aSWilliam A. Kennington III .WillOnce(DoAll(SaveArgPointee<1>(&req), Return(-EINVAL)));
110*b80c584eSPatrick Williams EXPECT_THROW(Event(*chip, line_offset, handle_flags, event_flags,
111*b80c584eSPatrick Williams label.c_str()),
112f3942f6aSWilliam A. Kennington III std::system_error);
113f3942f6aSWilliam A. Kennington III
114f3942f6aSWilliam A. Kennington III EXPECT_EQ(line_offset, req.lineoffset);
115f3942f6aSWilliam A. Kennington III EXPECT_EQ(GPIOHANDLE_REQUEST_INPUT, req.handleflags);
116f3942f6aSWilliam A. Kennington III EXPECT_EQ(0, req.eventflags);
117f3942f6aSWilliam A. Kennington III EXPECT_EQ(label, req.consumer_label);
118f3942f6aSWilliam A. Kennington III }
119f3942f6aSWilliam A. Kennington III
120f3942f6aSWilliam A. Kennington III class EventMethodTest : public EventTest
121f3942f6aSWilliam A. Kennington III {
122f3942f6aSWilliam A. Kennington III protected:
123f3942f6aSWilliam A. Kennington III std::unique_ptr<Event> event;
124f3942f6aSWilliam A. Kennington III
SetUp()125f3942f6aSWilliam A. Kennington III void SetUp()
126f3942f6aSWilliam A. Kennington III {
127f3942f6aSWilliam A. Kennington III EventTest::SetUp();
128f3942f6aSWilliam A. Kennington III struct gpioevent_request ret;
129f3942f6aSWilliam A. Kennington III ret.fd = event_fd;
130f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, gpio_get_lineevent(chip_fd, testing::_))
131f3942f6aSWilliam A. Kennington III .WillOnce(DoAll(SetArgPointee<1>(ret), Return(0)));
132f3942f6aSWilliam A. Kennington III event = std::make_unique<Event>(*chip, 0, HandleFlags(LineFlags(0)),
133f3942f6aSWilliam A. Kennington III EventFlags(), "method");
134f3942f6aSWilliam A. Kennington III }
135f3942f6aSWilliam A. Kennington III
TearDown()136f3942f6aSWilliam A. Kennington III void TearDown()
137f3942f6aSWilliam A. Kennington III {
138f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, close(event_fd)).WillOnce(Return(0));
139f3942f6aSWilliam A. Kennington III event.reset();
140f3942f6aSWilliam A. Kennington III EventTest::TearDown();
141f3942f6aSWilliam A. Kennington III }
142f3942f6aSWilliam A. Kennington III };
143f3942f6aSWilliam A. Kennington III
ACTION_P(WriteStruct,data)144f3942f6aSWilliam A. Kennington III ACTION_P(WriteStruct, data)
145f3942f6aSWilliam A. Kennington III {
146f3942f6aSWilliam A. Kennington III memcpy(arg0, &data, sizeof(data));
147f3942f6aSWilliam A. Kennington III }
148f3942f6aSWilliam A. Kennington III
TEST_F(EventMethodTest,ReadSuccess)149f3942f6aSWilliam A. Kennington III TEST_F(EventMethodTest, ReadSuccess)
150f3942f6aSWilliam A. Kennington III {
151f3942f6aSWilliam A. Kennington III struct gpioevent_data ret;
152f3942f6aSWilliam A. Kennington III ret.timestamp = 5;
153f3942f6aSWilliam A. Kennington III ret.id = 15;
154f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, read(event_fd, testing::_, sizeof(struct gpioevent_data)))
155f3942f6aSWilliam A. Kennington III .WillOnce(DoAll(WithArg<1>(WriteStruct(ret)), Return(sizeof(ret))));
156f3942f6aSWilliam A. Kennington III std::optional<Event::Data> data = event->read();
157f3942f6aSWilliam A. Kennington III EXPECT_TRUE(data);
15868cce0faSWilliam A. Kennington III EXPECT_EQ(ret.timestamp, data->timestamp.count());
159f3942f6aSWilliam A. Kennington III EXPECT_EQ(ret.id, data->id);
160f3942f6aSWilliam A. Kennington III }
161f3942f6aSWilliam A. Kennington III
TEST_F(EventMethodTest,ReadAgain)162f3942f6aSWilliam A. Kennington III TEST_F(EventMethodTest, ReadAgain)
163f3942f6aSWilliam A. Kennington III {
164f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, read(event_fd, testing::_, sizeof(struct gpioevent_data)))
165f3942f6aSWilliam A. Kennington III .WillOnce(DoAll(Assign(&errno, EAGAIN), Return(-1)));
166f3942f6aSWilliam A. Kennington III EXPECT_EQ(std::nullopt, event->read());
167f3942f6aSWilliam A. Kennington III }
168f3942f6aSWilliam A. Kennington III
TEST_F(EventMethodTest,ReadFailure)169f3942f6aSWilliam A. Kennington III TEST_F(EventMethodTest, ReadFailure)
170f3942f6aSWilliam A. Kennington III {
171f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, read(event_fd, testing::_, sizeof(struct gpioevent_data)))
172f3942f6aSWilliam A. Kennington III .WillOnce(DoAll(Assign(&errno, EINVAL), Return(-1)));
173f3942f6aSWilliam A. Kennington III EXPECT_THROW(event->read(), std::system_error);
174f3942f6aSWilliam A. Kennington III }
175f3942f6aSWilliam A. Kennington III
TEST_F(EventMethodTest,ReadTooSmall)176f3942f6aSWilliam A. Kennington III TEST_F(EventMethodTest, ReadTooSmall)
177f3942f6aSWilliam A. Kennington III {
178f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, read(event_fd, testing::_, sizeof(struct gpioevent_data)))
179f3942f6aSWilliam A. Kennington III .WillOnce(Return(1));
180f3942f6aSWilliam A. Kennington III EXPECT_THROW(event->read(), std::runtime_error);
181f3942f6aSWilliam A. Kennington III }
182f3942f6aSWilliam A. Kennington III
TEST_F(EventMethodTest,GetValueSuccess)183f3942f6aSWilliam A. Kennington III TEST_F(EventMethodTest, GetValueSuccess)
184f3942f6aSWilliam A. Kennington III {
185f3942f6aSWilliam A. Kennington III struct gpiohandle_data data;
186f3942f6aSWilliam A. Kennington III data.values[0] = 1;
187f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, gpiohandle_get_line_values(event_fd, testing::_))
188f3942f6aSWilliam A. Kennington III .WillOnce(DoAll(SetArgPointee<1>(data), Return(0)));
189f3942f6aSWilliam A. Kennington III EXPECT_EQ(data.values[0], event->getValue());
190f3942f6aSWilliam A. Kennington III }
191f3942f6aSWilliam A. Kennington III
TEST_F(EventMethodTest,GetValueFailure)192f3942f6aSWilliam A. Kennington III TEST_F(EventMethodTest, GetValueFailure)
193f3942f6aSWilliam A. Kennington III {
194f3942f6aSWilliam A. Kennington III EXPECT_CALL(mock, gpiohandle_get_line_values(event_fd, testing::_))
195f3942f6aSWilliam A. Kennington III .WillOnce(Return(-EINVAL));
196f3942f6aSWilliam A. Kennington III EXPECT_THROW(event->getValue(), std::system_error);
197f3942f6aSWilliam A. Kennington III }
198f3942f6aSWilliam A. Kennington III
199f3942f6aSWilliam A. Kennington III } // namespace
200f3942f6aSWilliam A. Kennington III } // namespace gpioplus
201