Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit de106e0

Browse files
rkavitha-hclKAVITHA RAMALINGAM
authored and
KAVITHA RAMALINGAM
committedDec 13, 2024·
gNOI Cold Reboot - Integrated tests
1 parent 68416e9 commit de106e0

File tree

4 files changed

+689
-0
lines changed

4 files changed

+689
-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
+376
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,376 @@
1+
#include "rebootbe.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 <iostream>
9+
#include <string>
10+
#include <thread>
11+
#include <vector>
12+
13+
#include "absl/time/time.h"
14+
#include "mock_reboot_interfaces.h"
15+
#include "reboot_common.h"
16+
#include "select.h"
17+
#include "status_code_util.h"
18+
#include "system/system.pb.h"
19+
#include "timestamp.h"
20+
21+
namespace rebootbackend {
22+
23+
#define ONE_SECOND (1)
24+
#define TWO_SECONDS (2)
25+
#define TENTH_SECOND_MS (100)
26+
#define SELECT_TIMEOUT_250_MS (250)
27+
28+
namespace gpu = ::google::protobuf::util;
29+
using namespace gnoi::system;
30+
31+
using ::testing::_;
32+
using ::testing::AllOf;
33+
using ::testing::AtLeast;
34+
using ::testing::ExplainMatchResult;
35+
using ::testing::HasSubstr;
36+
using ::testing::InSequence;
37+
using ::testing::Invoke;
38+
using ::testing::NiceMock;
39+
using ::testing::Return;
40+
using ::testing::StrEq;
41+
using ::testing::StrictMock;
42+
43+
MATCHER_P2(IsStatus, status, message, "") {
44+
return (arg.status().status() == status &&
45+
ExplainMatchResult(message, arg.status().message(), result_listener));
46+
}
47+
48+
MATCHER_P3(ActiveCountMethod, active, count, method, "") {
49+
return (arg.active() == active && arg.count() == (uint32_t)count &&
50+
arg.method() == method);
51+
}
52+
53+
class RebootBETestWithoutStop : public ::testing::Test {
54+
protected:
55+
RebootBETestWithoutStop()
56+
: m_dbus_interface(),
57+
m_db("STATE_DB", 0),
58+
m_config_db("CONFIG_DB", 0),
59+
m_rebootbeRequestChannel(&m_db, REBOOT_REQUEST_NOTIFICATION_CHANNEL),
60+
m_rebootbeReponseChannel(&m_db, REBOOT_RESPONSE_NOTIFICATION_CHANNEL),
61+
m_rebootbe(m_dbus_interface) {
62+
sigterm_requested = false;
63+
64+
m_s.addSelectable(&m_rebootbeReponseChannel);
65+
66+
// Make the tests log to stdout, instead of syslog.
67+
swss::Table logging_table(&m_config_db, CFG_LOGGER_TABLE_NAME);
68+
logging_table.hset("rebootbackend", swss::DAEMON_LOGOUTPUT, "STDOUT");
69+
swss::Logger::restartLogger();
70+
}
71+
virtual ~RebootBETestWithoutStop() = default;
72+
73+
void start_rebootbe() {
74+
m_rebootbe_thread =
75+
std::make_unique<std::thread>(&RebootBE::Start, &m_rebootbe);
76+
}
77+
78+
void set_mock_defaults() {
79+
ON_CALL(m_dbus_interface, Reboot(_))
80+
.WillByDefault(Return(DbusInterface::DbusResponse{
81+
DbusInterface::DbusStatus::DBUS_SUCCESS, ""}));
82+
}
83+
84+
void overwrite_reboot_timeout(uint32_t timeout_seconds) {
85+
m_rebootbe.m_RebootThread.m_reboot_timeout = timeout_seconds;
86+
}
87+
88+
void send_stop_reboot_thread() { m_rebootbe.m_RebootThread.Stop(); }
89+
90+
void SendRebootRequest(const std::string &op, const std::string &data,
91+
const std::string &field, const std::string &value) {
92+
std::vector<swss::FieldValueTuple> values;
93+
values.push_back(swss::FieldValueTuple{field, value});
94+
95+
m_rebootbeRequestChannel.send(op, data, values);
96+
}
97+
98+
void SendRebootViaProto(RebootRequest &request) {
99+
std::string json_string;
100+
gpu::MessageToJsonString(request, &json_string);
101+
102+
SendRebootRequest("Reboot", "StatusCode", DATA_TUPLE_KEY, json_string);
103+
}
104+
105+
void SendRebootStatusRequest(void) {
106+
SendRebootRequest("RebootStatus", "StatusCode", DATA_TUPLE_KEY,
107+
"json status request");
108+
}
109+
110+
void start_reboot_via_rpc(
111+
RebootRequest &request,
112+
swss::StatusCode expected_result = swss::StatusCode::SWSS_RC_SUCCESS) {
113+
SendRebootViaProto(request);
114+
while (true) {
115+
int ret;
116+
swss::Selectable *sel;
117+
ret = m_s.select(&sel, SELECT_TIMEOUT_250_MS);
118+
if (ret != swss::Select::OBJECT) continue;
119+
if (sel != &m_rebootbeReponseChannel) continue;
120+
break;
121+
}
122+
std::string op, data;
123+
std::vector<swss::FieldValueTuple> ret_values;
124+
m_rebootbeReponseChannel.pop(op, data, ret_values);
125+
126+
EXPECT_THAT(op, StrEq("Reboot"));
127+
EXPECT_THAT(data, StrEq(swss::statusCodeToStr(expected_result)));
128+
}
129+
130+
gnoi::system::RebootStatusResponse do_reboot_status_rpc() {
131+
SendRebootStatusRequest();
132+
while (true) {
133+
int ret;
134+
swss::Selectable *sel;
135+
ret = m_s.select(&sel, SELECT_TIMEOUT_250_MS);
136+
if (ret != swss::Select::OBJECT) continue;
137+
if (sel != &m_rebootbeReponseChannel) continue;
138+
break;
139+
}
140+
std::string op, data;
141+
std::vector<swss::FieldValueTuple> ret_values;
142+
m_rebootbeReponseChannel.pop(op, data, ret_values);
143+
144+
EXPECT_THAT(op, StrEq("RebootStatus"));
145+
EXPECT_EQ(data, swss::statusCodeToStr(swss::StatusCode::SWSS_RC_SUCCESS));
146+
147+
std::string json_response;
148+
for (auto &fv : ret_values) {
149+
if (DATA_TUPLE_KEY == fvField(fv)) {
150+
json_response = fvValue(fv);
151+
}
152+
}
153+
gnoi::system::RebootStatusResponse response;
154+
gpu::JsonStringToMessage(json_response, &response);
155+
return response;
156+
}
157+
158+
void GetNotificationResponse(swss::NotificationConsumer &consumer,
159+
std::string &op, std::string &data,
160+
std::vector<swss::FieldValueTuple> &values) {
161+
swss::Select s;
162+
s.addSelectable(&consumer);
163+
swss::Selectable *sel;
164+
s.select(&sel, SELECT_TIMEOUT_250_MS);
165+
166+
consumer.pop(op, data, values);
167+
}
168+
169+
NotificationResponse handle_reboot_request(std::string &json_request) {
170+
return m_rebootbe.HandleRebootRequest(json_request);
171+
}
172+
173+
// Mock interfaces.
174+
NiceMock<MockDbusInterface> m_dbus_interface;
175+
176+
// DB connectors
177+
swss::DBConnector m_db;
178+
swss::DBConnector m_config_db;
179+
180+
// Reboot thread signaling.
181+
swss::NotificationProducer m_rebootbeRequestChannel;
182+
swss::Select m_s;
183+
swss::NotificationConsumer m_rebootbeReponseChannel;
184+
185+
// Module under test.
186+
std::unique_ptr<std::thread> m_rebootbe_thread;
187+
RebootBE m_rebootbe;
188+
};
189+
190+
class RebootBETest : public RebootBETestWithoutStop {
191+
protected:
192+
~RebootBETest() {
193+
m_rebootbe.Stop();
194+
m_rebootbe_thread->join();
195+
}
196+
};
197+
198+
// Test fixture to skip through the startup sequence into the main loop.
199+
// Param indicates if RebootBE should be initialized into a state where the
200+
// system came up in warmboot.
201+
class RebootBEAutoStartTest : public RebootBETest,
202+
public ::testing::WithParamInterface<bool> {
203+
protected:
204+
RebootBEAutoStartTest() {
205+
206+
start_rebootbe();
207+
208+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
209+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
210+
}
211+
};
212+
213+
// Normal operation testing.
214+
TEST_P(RebootBEAutoStartTest, NonExistentMessage) {
215+
swss::NotificationConsumer consumer(&m_db,
216+
REBOOT_RESPONSE_NOTIFICATION_CHANNEL);
217+
218+
// No "MESSAGE" in field/values
219+
SendRebootRequest("Reboot", "StatusCode", "field1", "field1_value");
220+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
221+
222+
std::string op, data;
223+
std::vector<swss::FieldValueTuple> ret_values;
224+
GetNotificationResponse(consumer, op, data, ret_values);
225+
226+
EXPECT_THAT(op, StrEq("Reboot"));
227+
EXPECT_THAT(
228+
data,
229+
StrEq(swss::statusCodeToStr(swss::StatusCode::SWSS_RC_INVALID_PARAM)));
230+
}
231+
232+
TEST_P(RebootBEAutoStartTest, TestCancelReboot) {
233+
swss::NotificationConsumer consumer(&m_db,
234+
REBOOT_RESPONSE_NOTIFICATION_CHANNEL);
235+
236+
SendRebootRequest("CancelReboot", "StatusCode", DATA_TUPLE_KEY,
237+
"json cancelreboot request");
238+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
239+
240+
std::string op, data;
241+
std::vector<swss::FieldValueTuple> ret_values;
242+
GetNotificationResponse(consumer, op, data, ret_values);
243+
244+
EXPECT_THAT(op, StrEq("CancelReboot"));
245+
EXPECT_THAT(
246+
data,
247+
StrEq(swss::statusCodeToStr(swss::StatusCode::SWSS_RC_UNIMPLEMENTED)));
248+
}
249+
250+
TEST_P(RebootBEAutoStartTest, TestUnrecognizedOP) {
251+
swss::NotificationConsumer consumer(&m_db,
252+
REBOOT_RESPONSE_NOTIFICATION_CHANNEL);
253+
254+
SendRebootRequest("NonOp", "StatusCode", DATA_TUPLE_KEY, "invalid op code");
255+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
256+
257+
std::string op, data;
258+
std::vector<swss::FieldValueTuple> ret_values;
259+
GetNotificationResponse(consumer, op, data, ret_values);
260+
261+
EXPECT_THAT(op, StrEq("NonOp"));
262+
EXPECT_THAT(
263+
data,
264+
StrEq(swss::statusCodeToStr(swss::StatusCode::SWSS_RC_INVALID_PARAM)));
265+
}
266+
267+
TEST_P(RebootBEAutoStartTest, TestColdRebootDbusToCompletion) {
268+
DbusInterface::DbusResponse dbus_response{
269+
DbusInterface::DbusStatus::DBUS_SUCCESS, ""};
270+
EXPECT_CALL(m_dbus_interface, Reboot(_))
271+
.Times(3)
272+
.WillRepeatedly(Return(dbus_response));
273+
274+
overwrite_reboot_timeout(1);
275+
RebootRequest request;
276+
request.set_method(RebootMethod::COLD);
277+
start_reboot_via_rpc(request);
278+
279+
std::this_thread::sleep_for(std::chrono::milliseconds(TENTH_SECOND_MS));
280+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(),
281+
RebootBE::RebManagerStatus::COLD_REBOOT_IN_PROGRESS);
282+
sleep(TWO_SECONDS);
283+
284+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
285+
gnoi::system::RebootStatusResponse response = do_reboot_status_rpc();
286+
EXPECT_THAT(response, ActiveCountMethod(false, 1, RebootMethod::COLD));
287+
EXPECT_THAT(response,
288+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_FAILURE,
289+
"platform failed to reboot"));
290+
291+
start_reboot_via_rpc(request);
292+
sleep(TWO_SECONDS);
293+
294+
start_reboot_via_rpc(request);
295+
sleep(TWO_SECONDS);
296+
297+
response = do_reboot_status_rpc();
298+
// Verifiy count is 3 after three reboot attempts.
299+
EXPECT_THAT(response, ActiveCountMethod(false, 3, RebootMethod::COLD));
300+
EXPECT_THAT(response,
301+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_FAILURE,
302+
"platform failed to reboot"));
303+
}
304+
305+
TEST_P(RebootBEAutoStartTest, TestColdBootSigterm) {
306+
sigterm_requested = true;
307+
set_mock_defaults();
308+
overwrite_reboot_timeout(1);
309+
310+
RebootRequest request;
311+
request.set_method(RebootMethod::COLD);
312+
start_reboot_via_rpc(request);
313+
314+
sleep(ONE_SECOND);
315+
316+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
317+
gnoi::system::RebootStatusResponse second_resp = do_reboot_status_rpc();
318+
EXPECT_THAT(second_resp, ActiveCountMethod(false, 1, RebootMethod::COLD));
319+
EXPECT_THAT(
320+
second_resp,
321+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN, ""));
322+
}
323+
324+
TEST_P(RebootBEAutoStartTest, TestColdBootDbusError) {
325+
// Return FAIL from dbus reboot call.
326+
DbusInterface::DbusResponse dbus_response{
327+
DbusInterface::DbusStatus::DBUS_FAIL, "dbus reboot failed"};
328+
EXPECT_CALL(m_dbus_interface, Reboot(_))
329+
.Times(1)
330+
.WillOnce(Return(dbus_response));
331+
332+
RebootRequest request;
333+
request.set_method(RebootMethod::COLD);
334+
start_reboot_via_rpc(request);
335+
336+
sleep(TWO_SECONDS);
337+
338+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
339+
gnoi::system::RebootStatusResponse second_resp = do_reboot_status_rpc();
340+
EXPECT_THAT(second_resp, ActiveCountMethod(false, 1, RebootMethod::COLD));
341+
EXPECT_THAT(second_resp,
342+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_FAILURE,
343+
"dbus reboot failed"));
344+
}
345+
346+
TEST_P(RebootBEAutoStartTest, TestStopDuringColdBoot) {
347+
set_mock_defaults();
348+
349+
RebootRequest request;
350+
request.set_method(RebootMethod::COLD);
351+
start_reboot_via_rpc(request);
352+
std::this_thread::sleep_for(std::chrono::milliseconds(TENTH_SECOND_MS));
353+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(),
354+
RebootBE::RebManagerStatus::COLD_REBOOT_IN_PROGRESS);
355+
356+
send_stop_reboot_thread();
357+
std::this_thread::sleep_for(std::chrono::milliseconds(TENTH_SECOND_MS));
358+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
359+
360+
gnoi::system::RebootStatusResponse response = do_reboot_status_rpc();
361+
EXPECT_THAT(response, ActiveCountMethod(false, 1, RebootMethod::COLD));
362+
EXPECT_THAT(
363+
response,
364+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN, ""));
365+
}
366+
367+
TEST_P(RebootBEAutoStartTest, TestInvalidJsonRebootRequest) {
368+
std::string json_request = "abcd";
369+
NotificationResponse response = handle_reboot_request(json_request);
370+
EXPECT_EQ(swss::StatusCode::SWSS_RC_INTERNAL, response.status);
371+
}
372+
373+
INSTANTIATE_TEST_SUITE_P(TestWithStartupWarmbootEnabledState,
374+
RebootBEAutoStartTest, testing::Values(true, false));
375+
376+
} // namespace rebootbackend
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
#include "gtest/gtest.h"
3+
4+
int main(int argc, char* argv[]) {
5+
testing::InitGoogleTest(&argc, argv);
6+
return RUN_ALL_TESTS();
7+
}

0 commit comments

Comments
 (0)
Please sign in to comment.