Skip to content

Commit 4eb5b10

Browse files
rkavitha-hclKAVITHA RAMALINGAM
authored and
KAVITHA RAMALINGAM
committed
gNOI Cold Reboot - Integrated tests
1 parent 76fa407 commit 4eb5b10

File tree

4 files changed

+693
-0
lines changed

4 files changed

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

0 commit comments

Comments
 (0)