1 #include "gpio-presence/device_presence.hpp"
2 #include "gpio-presence/gpio_presence_manager.hpp"
3
4 #include <gpiod.hpp>
5 #include <phosphor-logging/lg2.hpp>
6
7 #include <gtest/gtest.h>
8
9 using namespace gpio_presence;
10
11 class DevicePresenceDetailedTest : public ::testing::Test
12 {
13 protected:
14 DevicePresenceDetailedTest() = default;
15 ~DevicePresenceDetailedTest() noexcept override = default;
16
17 sdbusplus::async::context ctx;
18 std::unordered_map<std::string, bool> gpioState;
19 };
20
21 // Test DevicePresence constructor with single GPIO, active low
TEST_F(DevicePresenceDetailedTest,ConstructorSingleGpioActiveLow)22 TEST_F(DevicePresenceDetailedTest, ConstructorSingleGpioActiveLow)
23 {
24 std::vector<std::string> gpioNames = {"GPIO1"};
25 std::vector<uint64_t> gpioValues = {0}; // Active low
26 std::string deviceName = "device1";
27
28 DevicePresence device(ctx, gpioNames, gpioValues, deviceName, gpioState,
29 {});
30
31 EXPECT_EQ(device.deviceName, deviceName);
32 EXPECT_EQ(device.gpioPolarity.size(), 1);
33 EXPECT_EQ(device.gpioPolarity["GPIO1"], ACTIVE_LOW);
34 }
35
36 // Test DevicePresence constructor with single GPIO, active high
TEST_F(DevicePresenceDetailedTest,ConstructorSingleGpioActiveHigh)37 TEST_F(DevicePresenceDetailedTest, ConstructorSingleGpioActiveHigh)
38 {
39 std::vector<std::string> gpioNames = {"GPIO2"};
40 std::vector<uint64_t> gpioValues = {1}; // Active high
41 std::string deviceName = "device2";
42
43 DevicePresence device(ctx, gpioNames, gpioValues, deviceName, gpioState,
44 {});
45
46 EXPECT_EQ(device.deviceName, deviceName);
47 EXPECT_EQ(device.gpioPolarity.size(), 1);
48 EXPECT_EQ(device.gpioPolarity["GPIO2"], ACTIVE_HIGH);
49 }
50
51 // Test DevicePresence constructor with multiple GPIOs with mixed polarities
TEST_F(DevicePresenceDetailedTest,ConstructorMultipleGpiosMixedPolarities)52 TEST_F(DevicePresenceDetailedTest, ConstructorMultipleGpiosMixedPolarities)
53 {
54 std::vector<std::string> gpioNames = {"GPIO1", "GPIO2", "GPIO3"};
55 std::vector<uint64_t> gpioValues = {0, 1, 0}; // Active low, high, low
56 std::string deviceName = "device3";
57
58 DevicePresence device(ctx, gpioNames, gpioValues, deviceName, gpioState,
59 {});
60
61 EXPECT_EQ(device.deviceName, deviceName);
62 EXPECT_EQ(device.gpioPolarity.size(), 3);
63 EXPECT_EQ(device.gpioPolarity["GPIO1"], ACTIVE_LOW);
64 EXPECT_EQ(device.gpioPolarity["GPIO2"], ACTIVE_HIGH);
65 EXPECT_EQ(device.gpioPolarity["GPIO3"], ACTIVE_LOW);
66 }
67
68 // Test DevicePresence isPresent method with active low GPIO is low (device
69 // present)
TEST_F(DevicePresenceDetailedTest,IsPresentActiveLowGpioLow)70 TEST_F(DevicePresenceDetailedTest, IsPresentActiveLowGpioLow)
71 {
72 std::unordered_map<std::string, bool> localGpioState;
73 std::vector<std::string> gpioNames = {"GPIO1"};
74 std::vector<uint64_t> gpioValues = {0}; // Active low
75 std::string deviceName = "device1";
76
77 localGpioState["GPIO1"] = false; // GPIO is low
78
79 DevicePresence device(ctx, gpioNames, gpioValues, deviceName,
80 localGpioState, {});
81 EXPECT_TRUE(device.isPresent());
82 }
83
84 // Test DevicePresence isPresent method with active low GPIO is high (device
85 // absent)
TEST_F(DevicePresenceDetailedTest,IsPresentActiveLowGpioHigh)86 TEST_F(DevicePresenceDetailedTest, IsPresentActiveLowGpioHigh)
87 {
88 std::unordered_map<std::string, bool> localGpioState;
89 std::vector<std::string> gpioNames = {"GPIO1"};
90 std::vector<uint64_t> gpioValues = {0}; // Active low
91 std::string deviceName = "device1";
92
93 localGpioState["GPIO1"] = true; // GPIO is high
94
95 DevicePresence device(ctx, gpioNames, gpioValues, deviceName,
96 localGpioState, {});
97 EXPECT_FALSE(device.isPresent());
98 }
99
100 // Test DevicePresence isPresent method with active high GPIO is high (device
101 // present)
TEST_F(DevicePresenceDetailedTest,IsPresentActiveHighGpioHigh)102 TEST_F(DevicePresenceDetailedTest, IsPresentActiveHighGpioHigh)
103 {
104 std::unordered_map<std::string, bool> localGpioState;
105 std::vector<std::string> gpioNames = {"GPIO1"};
106 std::vector<uint64_t> gpioValues = {1}; // Active high
107 std::string deviceName = "device1";
108
109 localGpioState["GPIO1"] = true; // GPIO is high
110
111 DevicePresence device(ctx, gpioNames, gpioValues, deviceName,
112 localGpioState, {});
113 EXPECT_TRUE(device.isPresent());
114 }
115
116 // Test DevicePresence isPresent method with active high GPIO is low (device
117 // absent)
TEST_F(DevicePresenceDetailedTest,IsPresentActiveHighGpioLow)118 TEST_F(DevicePresenceDetailedTest, IsPresentActiveHighGpioLow)
119 {
120 std::unordered_map<std::string, bool> localGpioState;
121 std::vector<std::string> gpioNames = {"GPIO1"};
122 std::vector<uint64_t> gpioValues = {1}; // Active high
123 std::string deviceName = "device1";
124
125 localGpioState["GPIO1"] = false; // GPIO is low
126
127 DevicePresence device(ctx, gpioNames, gpioValues, deviceName,
128 localGpioState, {});
129 EXPECT_FALSE(device.isPresent());
130 }
131
132 // Test DevicePresence isPresent method with multiple GPIOs all correct (device
133 // present)
TEST_F(DevicePresenceDetailedTest,IsPresentMultipleGpiosAllCorrect)134 TEST_F(DevicePresenceDetailedTest, IsPresentMultipleGpiosAllCorrect)
135 {
136 std::unordered_map<std::string, bool> localGpioState;
137 std::vector<std::string> gpioNames = {"GPIO1", "GPIO2", "GPIO3"};
138 std::vector<uint64_t> gpioValues = {0, 1, 0}; // Active low, high, low
139 std::string deviceName = "device1";
140
141 localGpioState["GPIO1"] = false; // Active low, should be low
142 localGpioState["GPIO2"] = true; // Active high, should be high
143 localGpioState["GPIO3"] = false; // Active low, should be low
144
145 DevicePresence device(ctx, gpioNames, gpioValues, deviceName,
146 localGpioState, {});
147 EXPECT_TRUE(device.isPresent());
148 }
149
150 // Test DevicePresence isPresent method with multiple GPIOs one incorrect
151 // (device absent)
TEST_F(DevicePresenceDetailedTest,IsPresentMultipleGpiosOneIncorrect)152 TEST_F(DevicePresenceDetailedTest, IsPresentMultipleGpiosOneIncorrect)
153 {
154 std::unordered_map<std::string, bool> localGpioState;
155 std::vector<std::string> gpioNames = {"GPIO1", "GPIO2", "GPIO3"};
156 std::vector<uint64_t> gpioValues = {0, 1, 0}; // Active low, high, low
157 std::string deviceName = "device1";
158
159 localGpioState["GPIO1"] = false; // Active low, should be low - correct
160 localGpioState["GPIO2"] = false; // Active high, should be high - incorrect
161 localGpioState["GPIO3"] = false; // Active low, should be low - correct
162
163 DevicePresence device(ctx, gpioNames, gpioValues, deviceName,
164 localGpioState, {});
165 EXPECT_FALSE(device.isPresent());
166 }
167
168 // Test DevicePresence isPresent method with missing GPIO state (device absent)
TEST_F(DevicePresenceDetailedTest,IsPresentMissingGpioState)169 TEST_F(DevicePresenceDetailedTest, IsPresentMissingGpioState)
170 {
171 std::unordered_map<std::string, bool> localGpioState;
172 std::vector<std::string> gpioNames = {"GPIO1"};
173 std::vector<uint64_t> gpioValues = {0}; // Active low
174 std::string deviceName = "device1";
175
176 // localGpioState["GPIO1"] is not set - simulating missing GPIO
177
178 DevicePresence device(ctx, gpioNames, gpioValues, deviceName,
179 localGpioState, {});
180 EXPECT_FALSE(device.isPresent());
181 }
182
183 // Test DevicePresence getObjPath method
TEST_F(DevicePresenceDetailedTest,GetObjPathTest)184 TEST_F(DevicePresenceDetailedTest, GetObjPathTest)
185 {
186 std::vector<std::string> gpioNames = {"GPIO1"};
187 std::vector<uint64_t> gpioValues = {0};
188 std::string deviceName = "test_device";
189
190 DevicePresence device(ctx, gpioNames, gpioValues, deviceName, gpioState,
191 {});
192
193 sdbusplus::message::object_path objPath = device.getObjPath();
194 std::string expectedPath =
195 "/xyz/openbmc_project/GPIODeviceDetected/" + deviceName;
196
197 EXPECT_EQ(objPath.str, expectedPath);
198 }
199