blob: 08a66db7da796cb81ad530efc3bb0899c8b64660 [file] [log] [blame]
William A. Kennington IIIb00dd042018-08-17 13:14:34 -07001#include <cerrno>
2#include <cstdint>
3#include <gmock/gmock.h>
4#include <gpioplus/handle.hpp>
5#include <gpioplus/test/sys.hpp>
6#include <gtest/gtest.h>
7#include <linux/gpio.h>
8#include <memory>
9#include <stdexcept>
10#include <string>
11#include <system_error>
12#include <vector>
13
14namespace gpioplus
15{
16namespace
17{
18
19using testing::DoAll;
20using testing::Return;
21using testing::SaveArgPointee;
22using testing::SetArgPointee;
23
24TEST(HandleFlags, HandleFlagsFromLineFlags)
25{
26 LineFlags line_flags(GPIOLINE_FLAG_KERNEL | GPIOLINE_FLAG_OPEN_DRAIN);
27 HandleFlags handle_flags(line_flags);
28 EXPECT_FALSE(handle_flags.output);
29 EXPECT_FALSE(handle_flags.active_low);
30 EXPECT_TRUE(handle_flags.open_drain);
31 EXPECT_FALSE(handle_flags.open_source);
32}
33
34TEST(HandleFlags, HandleFlagsToInt)
35{
36 HandleFlags handle_flags;
37 handle_flags.output = false;
38 handle_flags.active_low = true;
39 handle_flags.open_drain = false;
40 handle_flags.open_source = false;
41 EXPECT_EQ(GPIOHANDLE_REQUEST_INPUT | GPIOHANDLE_REQUEST_ACTIVE_LOW,
42 handle_flags.toInt());
43
44 handle_flags.output = true;
45 handle_flags.active_low = false;
46 handle_flags.open_drain = true;
47 handle_flags.open_source = true;
48 EXPECT_EQ(GPIOHANDLE_REQUEST_OUTPUT | GPIOHANDLE_REQUEST_OPEN_DRAIN |
49 GPIOHANDLE_REQUEST_OPEN_SOURCE,
50 handle_flags.toInt());
51}
52
53class HandleTest : public testing::Test
54{
55 protected:
56 const int chip_fd = 1234;
57 const int handle_fd = 2345;
58 testing::StrictMock<test::SysMock> mock;
59 std::unique_ptr<Chip> chip;
60
61 void SetUp()
62 {
63 EXPECT_CALL(mock, open(testing::_, testing::_))
64 .WillOnce(Return(chip_fd));
65 chip = std::make_unique<Chip>(0, &mock);
66 }
67
68 void TearDown()
69 {
70 EXPECT_CALL(mock, close(chip_fd)).WillOnce(Return(0));
71 chip.reset();
72 }
73};
74
75TEST_F(HandleTest, ConstructSuccess)
76{
77 const std::string label{"test"};
78 std::vector<Handle::Line> lines;
79 for (uint32_t i = 0; i < 7; ++i)
80 {
81 lines.push_back({i, 1});
82 }
83
84 struct gpiohandle_request req, ret;
85 ret.fd = handle_fd;
86 EXPECT_CALL(mock, gpio_get_linehandle(chip_fd, testing::_))
87 .WillOnce(
88 DoAll(SaveArgPointee<1>(&req), SetArgPointee<1>(ret), Return(0)));
89 Handle handle(*chip, lines,
90 HandleFlags(LineFlags(GPIOLINE_FLAG_ACTIVE_LOW)),
91 label.c_str());
92
93 EXPECT_EQ(handle_fd, *handle.getFd());
94 EXPECT_EQ(GPIOHANDLE_REQUEST_INPUT | GPIOHANDLE_REQUEST_ACTIVE_LOW,
95 req.flags);
96 EXPECT_EQ(label, req.consumer_label);
97 EXPECT_EQ(lines.size(), req.lines);
98 for (uint32_t i = 0; i < lines.size(); ++i)
99 {
100 EXPECT_EQ(i, req.lineoffsets[i]);
101 EXPECT_EQ(1, req.default_values[i]);
102 }
103
104 EXPECT_CALL(mock, close(handle_fd)).WillOnce(Return(0));
105}
106
107TEST_F(HandleTest, ConstructTooMany)
108{
109 const std::vector<Handle::Line> lines(GPIOHANDLES_MAX + 1);
110 EXPECT_THROW(Handle(*chip, lines, HandleFlags(), "too_many"),
111 std::runtime_error);
112}
113
114TEST_F(HandleTest, ConstructError)
115{
116 const std::string label{"error"};
117 std::vector<Handle::Line> lines;
118 for (uint32_t i = 0; i < 5; ++i)
119 {
120 lines.push_back({i, 0});
121 }
122
123 struct gpiohandle_request req;
124 EXPECT_CALL(mock, gpio_get_linehandle(chip_fd, testing::_))
125 .WillOnce(DoAll(SaveArgPointee<1>(&req), Return(-EINVAL)));
126 EXPECT_THROW(Handle(*chip, lines,
127 HandleFlags(LineFlags(GPIOLINE_FLAG_IS_OUT)),
128 label.c_str()),
129 std::runtime_error);
130
131 EXPECT_EQ(GPIOHANDLE_REQUEST_OUTPUT, req.flags);
132 EXPECT_EQ(label, req.consumer_label);
133 EXPECT_EQ(lines.size(), req.lines);
134 for (uint32_t i = 0; i < lines.size(); ++i)
135 {
136 EXPECT_EQ(i, req.lineoffsets[i]);
137 EXPECT_EQ(0, req.default_values[i]);
138 }
139}
140
141class HandleMethodTest : public HandleTest
142{
143 protected:
144 std::unique_ptr<Handle> handle;
145 const std::vector<Handle::Line> lines{{1, 1}, {4, 0}};
146
147 void SetUp()
148 {
149 HandleTest::SetUp();
150 struct gpiohandle_request ret;
151 ret.fd = handle_fd;
152 EXPECT_CALL(mock, gpio_get_linehandle(chip_fd, testing::_))
153 .WillOnce(DoAll(SetArgPointee<1>(ret), Return(0)));
154 handle = std::make_unique<Handle>(
155 *chip, lines, HandleFlags(LineFlags(GPIOLINE_FLAG_IS_OUT)),
156 "method");
157 }
158
159 void TearDown()
160 {
161 EXPECT_CALL(mock, close(handle_fd)).WillOnce(Return(0));
162 handle.reset();
163 HandleTest::TearDown();
164 }
165};
166
167TEST_F(HandleMethodTest, GetValuesRet)
168{
169 const std::vector<uint8_t> expected{0, 0};
170 struct gpiohandle_data ret;
171 ret.values[0] = 0;
172 ret.values[1] = 0;
173
174 EXPECT_CALL(mock, gpiohandle_get_line_values(handle_fd, testing::_))
175 .WillOnce(DoAll(SetArgPointee<1>(ret), Return(0)));
176 EXPECT_EQ(expected, handle->getValues());
177}
178
179TEST_F(HandleMethodTest, GetValuesSuccess)
180{
181 const std::vector<uint8_t> expected{1, 1};
182 struct gpiohandle_data ret;
183 ret.values[0] = 1;
184 ret.values[1] = 1;
185
186 EXPECT_CALL(mock, gpiohandle_get_line_values(handle_fd, testing::_))
187 .WillOnce(DoAll(SetArgPointee<1>(ret), Return(0)));
188 std::vector<uint8_t> output;
189 handle->getValues(output);
190 EXPECT_EQ(expected, output);
191}
192
193TEST_F(HandleMethodTest, GetValuesFailure)
194{
195 EXPECT_CALL(mock, gpiohandle_get_line_values(handle_fd, testing::_))
196 .WillOnce(Return(-EINVAL));
197 EXPECT_THROW(handle->getValues(), std::system_error);
198}
199
200TEST_F(HandleMethodTest, SetValuesSuccess)
201{
202 struct gpiohandle_data req;
203 EXPECT_CALL(mock, gpiohandle_set_line_values(handle_fd, testing::_))
204 .WillOnce(DoAll(SaveArgPointee<1>(&req), Return(0)));
205 handle->setValues({0, 1});
206 EXPECT_EQ(0, req.values[0]);
207 EXPECT_EQ(1, req.values[1]);
208}
209
210TEST_F(HandleMethodTest, SetValuesInvalid)
211{
212 EXPECT_THROW(handle->setValues({1}), std::runtime_error);
213 EXPECT_THROW(handle->setValues({1, 0, 1}), std::runtime_error);
214}
215
216TEST_F(HandleMethodTest, SetValuesFailure)
217{
218 struct gpiohandle_data req;
219 EXPECT_CALL(mock, gpiohandle_set_line_values(handle_fd, testing::_))
220 .WillOnce(DoAll(SaveArgPointee<1>(&req), Return(-EINVAL)));
221 EXPECT_THROW(handle->setValues({1, 1}), std::system_error);
222 EXPECT_EQ(1, req.values[0]);
223 EXPECT_EQ(1, req.values[1]);
224}
225
226} // namespace
227} // namespace gpioplus