1 /**
2  * Copyright © 2020 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "action_environment.hpp"
17 #include "action_error.hpp"
18 #include "compare_presence_action.hpp"
19 #include "device.hpp"
20 #include "i2c_interface.hpp"
21 #include "id_map.hpp"
22 #include "mock_action.hpp"
23 #include "mock_presence_service.hpp"
24 #include "mock_services.hpp"
25 #include "mocked_i2c_interface.hpp"
26 
27 #include <exception>
28 #include <memory>
29 #include <stdexcept>
30 #include <utility>
31 
32 #include <gmock/gmock.h>
33 #include <gtest/gtest.h>
34 
35 using namespace phosphor::power::regulators;
36 
37 using ::testing::Return;
38 using ::testing::Throw;
39 
40 TEST(ComparePresenceActionTests, Constructor)
41 {
42     ComparePresenceAction action{
43         "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3", true};
44     EXPECT_EQ(action.getFRU(),
45               "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3");
46     EXPECT_EQ(action.getValue(), true);
47 }
48 
49 TEST(ComparePresenceActionTests, Execute)
50 {
51     // Test where works: actual value is true.
52     try
53     {
54         // Create mock I2CInterface
55         std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
56             std::make_unique<i2c::MockedI2CInterface>();
57 
58         // Create Device, IDMap, MockServices and ActionEnvironment
59         // Actual value isPresent() is true
60         Device device{
61             "reg1", true,
62             "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
63             std::move(i2cInterface)};
64         IDMap idMap{};
65         idMap.addDevice(device);
66         MockServices services{};
67         MockPresenceService& presenceService =
68             services.getMockPresenceService();
69         EXPECT_CALL(presenceService,
70                     isPresent("/xyz/openbmc_project/inventory/system/chassis/"
71                               "motherboard/cpu2"))
72             .Times(2)
73             .WillRepeatedly(Return(true));
74         ActionEnvironment env{idMap, "reg1", services};
75 
76         // Test where works: expected value is true, return value is true.
77         {
78             ComparePresenceAction action{"/xyz/openbmc_project/inventory/"
79                                          "system/chassis/motherboard/cpu2",
80                                          true};
81             EXPECT_EQ(action.execute(env), true);
82         }
83 
84         // Test where works: expected value is false, return value is false.
85         {
86             ComparePresenceAction action{"/xyz/openbmc_project/inventory/"
87                                          "system/chassis/motherboard/cpu2",
88                                          false};
89             EXPECT_EQ(action.execute(env), false);
90         }
91     }
92     catch (...)
93     {
94         ADD_FAILURE() << "Should not have caught exception.";
95     }
96 
97     // Test where actual value is false.
98     try
99     {
100         // Create mock I2CInterface
101         std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
102             std::make_unique<i2c::MockedI2CInterface>();
103 
104         // Create Device, IDMap, MockServices and ActionEnvironment
105         // Actual value isPresent() is false
106         Device device{
107             "reg1", true,
108             "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
109             std::move(i2cInterface)};
110         IDMap idMap{};
111         idMap.addDevice(device);
112         MockServices services{};
113         MockPresenceService& presenceService =
114             services.getMockPresenceService();
115         EXPECT_CALL(presenceService,
116                     isPresent("/xyz/openbmc_project/inventory/system/chassis/"
117                               "motherboard/cpu2"))
118             .Times(2)
119             .WillRepeatedly(Return(false));
120         ActionEnvironment env{idMap, "reg1", services};
121 
122         // Test where works: expected value is true, return value is false.
123         {
124             ComparePresenceAction action{"/xyz/openbmc_project/inventory/"
125                                          "system/chassis/motherboard/cpu2",
126                                          true};
127             EXPECT_EQ(action.execute(env), false);
128         }
129 
130         // Test where works: expected value is false, return value is true.
131         {
132             ComparePresenceAction action{"/xyz/openbmc_project/inventory/"
133                                          "system/chassis/motherboard/cpu2",
134                                          false};
135             EXPECT_EQ(action.execute(env), true);
136         }
137     }
138     catch (...)
139     {
140         ADD_FAILURE() << "Should not have caught exception.";
141     }
142 
143     // Test where fails. Reading presence fails.
144     try
145     {
146         // Create mock I2CInterface
147         std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
148             std::make_unique<i2c::MockedI2CInterface>();
149 
150         // Create Device, IDMap, MockServices and ActionEnvironment
151         // PresenceService cannot get the presence
152         Device device{
153             "reg1", true,
154             "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
155             std::move(i2cInterface)};
156         IDMap idMap{};
157         idMap.addDevice(device);
158         MockServices services{};
159         MockPresenceService& presenceService =
160             services.getMockPresenceService();
161         EXPECT_CALL(presenceService,
162                     isPresent("/xyz/openbmc_project/inventory/system/chassis/"
163                               "motherboard/cpu2"))
164             .Times(1)
165             .WillOnce(Throw(std::runtime_error(
166                 "PresenceService cannot get the presence.")));
167 
168         ActionEnvironment env{idMap, "reg1", services};
169 
170         ComparePresenceAction action{"/xyz/openbmc_project/inventory/"
171                                      "system/chassis/motherboard/cpu2",
172                                      true};
173         action.execute(env);
174         ADD_FAILURE() << "Should not have reached this line.";
175     }
176     catch (const ActionError& e)
177     {
178         EXPECT_STREQ(e.what(), "ActionError: compare_presence: { fru: "
179                                "/xyz/openbmc_project/inventory/system/chassis/"
180                                "motherboard/cpu2, value: true }");
181         try
182         {
183             // Re-throw inner exception from MockPresenceService.
184             std::rethrow_if_nested(e);
185             ADD_FAILURE() << "Should not have reached this line.";
186         }
187         catch (const std::runtime_error& r_error)
188         {
189             EXPECT_STREQ(r_error.what(),
190                          "PresenceService cannot get the presence.");
191         }
192         catch (...)
193         {
194             ADD_FAILURE() << "Should not have caught exception.";
195         }
196     }
197     catch (...)
198     {
199         ADD_FAILURE() << "Should not have caught exception.";
200     }
201 }
202 
203 TEST(ComparePresenceActionTests, GetFRU)
204 {
205     ComparePresenceAction action{
206         "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2", true};
207     EXPECT_EQ(action.getFRU(),
208               "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2");
209 }
210 
211 TEST(ComparePresenceActionTests, GetValue)
212 {
213     ComparePresenceAction action{
214         "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3",
215         false};
216     EXPECT_EQ(action.getValue(), false);
217 }
218 
219 TEST(ComparePresenceActionTests, ToString)
220 {
221     ComparePresenceAction action{
222         "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2", true};
223     EXPECT_EQ(action.toString(),
224               "compare_presence: { fru: "
225               "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2, "
226               "value: true }");
227 }
228