Skip to content

Commit e9bfc38

Browse files
rkavitha-hclKAVITHA RAMALINGAM
authored and
KAVITHA RAMALINGAM
committed
gNOI Cold Reboot - Integrated tests
1 parent 68416e9 commit e9bfc38

File tree

4 files changed

+691
-0
lines changed

4 files changed

+691
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
#include <gmock/gmock.h>
3+
4+
#include "reboot_interfaces.h"
5+
#include "selectableevent.h"
6+
#include "system/system.pb.h"
7+
8+
namespace rebootbackend {
9+
10+
class MockDbusInterface : public DbusInterface {
11+
public:
12+
MOCK_METHOD(DbusInterface::DbusResponse, Reboot, (const std::string &),
13+
(override));
14+
MOCK_METHOD(DbusInterface::DbusResponse, RebootStatus, (const std::string &),
15+
(override));
16+
};
17+
18+
} // namespace rebootbackend
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
#include "reboot_thread.h"
2+
3+
#include <gmock/gmock.h>
4+
#include <google/protobuf/util/json_util.h>
5+
#include <gtest/gtest.h>
6+
#include <unistd.h>
7+
8+
#include <string>
9+
#include <thread>
10+
#include <vector>
11+
12+
#include "mock_reboot_interfaces.h"
13+
#include "reboot_common.h"
14+
#include "reboot_interfaces.h"
15+
#include "select.h"
16+
#include "selectableevent.h"
17+
#include "status_code_util.h"
18+
#include "system/system.pb.h"
19+
#include "timestamp.h"
20+
21+
namespace rebootbackend {
22+
23+
24+
// using namespace gnoi::system;
25+
namespace gpu = ::google::protobuf::util;
26+
using Progress = ::rebootbackend::RebootThread::Progress;
27+
using RebootThread = ::rebootbackend::RebootThread;
28+
using ::testing::_;
29+
using ::testing::ExplainMatchResult;
30+
using ::testing::HasSubstr;
31+
using ::testing::NiceMock;
32+
using ::testing::Return;
33+
using ::testing::StrEq;
34+
using ::testing::StrictMock;
35+
36+
MATCHER_P2(IsStatus, status, message, "") {
37+
return (arg.status().status() == status &&
38+
ExplainMatchResult(message, arg.status().message(), result_listener));
39+
}
40+
41+
class RebootStatusTest : public ::testing::Test {
42+
protected:
43+
RebootStatusTest() : m_status() {}
44+
ThreadStatus m_status;
45+
};
46+
47+
TEST_F(RebootStatusTest, TestInit) {
48+
gnoi::system::RebootStatusResponse response = m_status.get_response();
49+
50+
EXPECT_FALSE(response.active());
51+
EXPECT_THAT(response.reason(), StrEq(""));
52+
EXPECT_EQ(response.count(), 0);
53+
EXPECT_EQ(response.method(), gnoi::system::RebootMethod::UNKNOWN);
54+
EXPECT_EQ(
55+
response.status().status(),
56+
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN);
57+
EXPECT_THAT(response.status().message(), StrEq(""));
58+
59+
EXPECT_FALSE(m_status.get_active());
60+
}
61+
62+
TEST_F(RebootStatusTest, TestGetStatus) {
63+
std::chrono::nanoseconds curr_ns =
64+
std::chrono::high_resolution_clock::now().time_since_epoch();
65+
66+
m_status.set_start_status(gnoi::system::RebootMethod::COLD, "reboot because");
67+
68+
gnoi::system::RebootStatusResponse response = m_status.get_response();
69+
EXPECT_EQ(
70+
response.status().status(),
71+
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN);
72+
73+
m_status.set_completed_status(
74+
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_SUCCESS,
75+
"anything");
76+
77+
response = m_status.get_response();
78+
79+
// message should be empty while reboot is active
80+
EXPECT_THAT(response.status().message(), StrEq(""));
81+
82+
uint64_t reboot_ns = response.when();
83+
EXPECT_TRUE(reboot_ns > (uint64_t)curr_ns.count());
84+
85+
m_status.set_inactive();
86+
response = m_status.get_response();
87+
EXPECT_THAT(response.status().message(), StrEq("anything"));
88+
EXPECT_EQ(
89+
response.status().status(),
90+
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_SUCCESS);
91+
EXPECT_EQ(0, response.when());
92+
}
93+
94+
class RebootThreadTest : public ::testing::Test {
95+
protected:
96+
RebootThreadTest()
97+
: m_dbus_interface(),
98+
m_db("STATE_DB", 0),
99+
m_config_db("CONFIG_DB", 0),
100+
m_reboot_thread(m_dbus_interface, m_finished) {
101+
sigterm_requested = false;
102+
}
103+
104+
void overwrite_reboot_timeout(uint32_t timeout_seconds) {
105+
m_reboot_thread.m_reboot_timeout = timeout_seconds;
106+
}
107+
108+
gnoi::system::RebootStatusResponse get_response(void) {
109+
return m_reboot_thread.m_status.get_response();
110+
}
111+
112+
void set_start_status(const gnoi::system::RebootMethod &method,
113+
const std::string &reason) {
114+
return m_reboot_thread.m_status.set_start_status(method, reason);
115+
}
116+
117+
void set_completed_status(const gnoi::system::RebootStatus_Status &status,
118+
const std::string &message) {
119+
return m_reboot_thread.m_status.set_completed_status(status, message);
120+
}
121+
122+
void force_inactive(void) { return m_reboot_thread.m_status.set_inactive(); }
123+
124+
void force_active(void) { return m_reboot_thread.m_status.set_inactive(); }
125+
126+
void do_reboot(void) { return m_reboot_thread.do_reboot(); }
127+
128+
void wait_for_finish(swss::Select &s, swss::SelectableEvent &finished,
129+
long timeout_seconds) {
130+
swss::Selectable *sel;
131+
132+
int ret = s.select(&sel, timeout_seconds * 1000);
133+
EXPECT_EQ(ret, swss::Select::OBJECT);
134+
EXPECT_EQ(sel, &finished);
135+
}
136+
137+
Progress wait_for_platform_reboot(swss::Select &s) {
138+
return m_reboot_thread.wait_for_platform_reboot(s);
139+
}
140+
141+
swss::SelectableEvent &return_m_stop_reference() {
142+
return m_reboot_thread.m_stop;
143+
}
144+
145+
swss::DBConnector m_db;
146+
swss::DBConnector m_config_db;
147+
NiceMock<MockDbusInterface> m_dbus_interface;
148+
swss::SelectableEvent m_finished;
149+
RebootThread m_reboot_thread;
150+
};
151+
152+
MATCHER_P2(Status, status, message, "") {
153+
return (arg.status().status() == status && arg.status().message() == message);
154+
}
155+
156+
TEST_F(RebootThreadTest, TestStop) {
157+
EXPECT_CALL(m_dbus_interface, Reboot(_))
158+
.Times(1)
159+
.WillOnce(Return(DbusInterface::DbusResponse{
160+
DbusInterface::DbusStatus::DBUS_SUCCESS, ""}));
161+
gnoi::system::RebootRequest request;
162+
request.set_method(gnoi::system::RebootMethod::COLD);
163+
overwrite_reboot_timeout(2);
164+
m_reboot_thread.Start(request);
165+
m_reboot_thread.Stop();
166+
m_reboot_thread.Join();
167+
gnoi::system::RebootStatusResponse response = m_reboot_thread.GetResponse();
168+
EXPECT_THAT(
169+
response,
170+
IsStatus(
171+
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN,
172+
""));
173+
}
174+
175+
TEST_F(RebootThreadTest, TestCleanExit) {
176+
EXPECT_CALL(m_dbus_interface, Reboot(_))
177+
.Times(1)
178+
.WillOnce(Return(DbusInterface::DbusResponse{
179+
DbusInterface::DbusStatus::DBUS_SUCCESS, ""}));
180+
181+
overwrite_reboot_timeout(1);
182+
183+
swss::Select s;
184+
s.addSelectable(&m_finished);
185+
186+
gnoi::system::RebootRequest request;
187+
request.set_method(gnoi::system::RebootMethod::COLD);
188+
request.set_message("time to reboot");
189+
m_reboot_thread.Start(request);
190+
wait_for_finish(s, m_finished, 5);
191+
192+
// Status should be active until we call join
193+
gnoi::system::RebootStatusResponse response = get_response();
194+
EXPECT_TRUE(response.active());
195+
EXPECT_THAT(response.reason(), StrEq("time to reboot"));
196+
EXPECT_EQ(response.count(), 1);
197+
198+
EXPECT_THAT(response.status().message(), StrEq(""));
199+
200+
m_reboot_thread.Join();
201+
202+
response = get_response();
203+
EXPECT_FALSE(response.active());
204+
EXPECT_THAT(response.status().message(), StrEq("platform failed to reboot"));
205+
}
206+
207+
TEST_F(RebootThreadTest, TestJoinWithoutStart) {
208+
bool ret = m_reboot_thread.Join();
209+
EXPECT_FALSE(ret);
210+
}
211+
212+
// Call Start a second time while first thread is still executing.
213+
TEST_F(RebootThreadTest, TestStartWhileRunning) {
214+
EXPECT_CALL(m_dbus_interface, Reboot(_))
215+
.Times(1)
216+
.WillOnce(Return(DbusInterface::DbusResponse{
217+
DbusInterface::DbusStatus::DBUS_SUCCESS, ""}));
218+
219+
overwrite_reboot_timeout(2);
220+
221+
gnoi::system::RebootRequest request;
222+
request.set_method(gnoi::system::RebootMethod::COLD);
223+
request.set_message("time to reboot");
224+
m_reboot_thread.Start(request);
225+
226+
// First thread is still running ...
227+
NotificationResponse response = m_reboot_thread.Start(request);
228+
EXPECT_EQ(response.status, swss::StatusCode::SWSS_RC_IN_USE);
229+
EXPECT_THAT(response.json_string,
230+
StrEq("RebootThread: can't Start while active"));
231+
232+
bool ret = m_reboot_thread.Join();
233+
EXPECT_TRUE(ret);
234+
}
235+
236+
// Call Start a second time after first thread completed
237+
// but before first thread was joined.
238+
// Second start should fail.
239+
TEST_F(RebootThreadTest, TestStartWithoutJoin) {
240+
EXPECT_CALL(m_dbus_interface, Reboot(_))
241+
.Times(1)
242+
.WillOnce(Return(DbusInterface::DbusResponse{
243+
DbusInterface::DbusStatus::DBUS_SUCCESS, ""}));
244+
245+
overwrite_reboot_timeout(1);
246+
247+
swss::Select s;
248+
s.addSelectable(&m_finished);
249+
250+
gnoi::system::RebootRequest request;
251+
request.set_method(gnoi::system::RebootMethod::COLD);
252+
request.set_message("time to reboot");
253+
m_reboot_thread.Start(request);
254+
wait_for_finish(s, m_finished, 3);
255+
256+
// First thread has stopped: we need to join before
257+
// restart will succeed
258+
NotificationResponse response = m_reboot_thread.Start(request);
259+
EXPECT_EQ(response.status, swss::StatusCode::SWSS_RC_IN_USE);
260+
261+
// This should join the first start.
262+
bool ret = m_reboot_thread.Join();
263+
EXPECT_TRUE(ret);
264+
}
265+
266+
TEST_F(RebootThreadTest, TestUnsupportedRebootType) {
267+
gnoi::system::RebootRequest request;
268+
request.set_method(gnoi::system::RebootMethod::POWERDOWN);
269+
270+
NotificationResponse response = m_reboot_thread.Start(request);
271+
EXPECT_EQ(response.status, swss::StatusCode::SWSS_RC_INVALID_PARAM);
272+
EXPECT_EQ(response.json_string,
273+
"RebootThread: Start rx'd unsupported method");
274+
}
275+
276+
TEST_F(RebootThreadTest, TestInvalidMethodfDoReboot) {
277+
set_start_status(gnoi::system::RebootMethod::POWERUP, "time to reboot");
278+
do_reboot();
279+
force_inactive();
280+
gnoi::system::RebootStatusResponse response = m_reboot_thread.GetResponse();
281+
EXPECT_THAT(
282+
response,
283+
IsStatus(
284+
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN,
285+
""));
286+
}
287+
288+
} // namespace rebootbackend

0 commit comments

Comments
 (0)