Skip to content

Commit 2253140

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

File tree

4 files changed

+692
-0
lines changed

4 files changed

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

0 commit comments

Comments
 (0)