Skip to content

Commit 446d015

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

File tree

4 files changed

+694
-0
lines changed

4 files changed

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

0 commit comments

Comments
 (0)