Skip to content

Commit ad91226

Browse files
rkavitha-hclKAVITHA RAMALINGAM
authored and
KAVITHA RAMALINGAM
committed
gNOI Cold Reboot - Integrated tests
1 parent 9fe40e9 commit ad91226

11 files changed

+1016
-120
lines changed

src/sonic-framework/rebootbackend/redis_utils.cpp

-80
This file was deleted.

src/sonic-framework/rebootbackend/redis_utils.h

-40
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#include "init_thread.h"
2+
3+
#include <gmock/gmock.h>
4+
#include <gtest/gtest.h>
5+
#include <unistd.h>
6+
7+
#include <chrono>
8+
#include <string>
9+
#include <thread>
10+
#include <vector>
11+
12+
#include "mock_reboot_interfaces.h"
13+
#include "reboot_interfaces.h"
14+
#include "redis_utils.h"
15+
#include "select.h"
16+
#include "selectableevent.h"
17+
#include "stateverification.h"
18+
#include "status_code_util.h"
19+
#include "table.h"
20+
#include "test_utils_common.h"
21+
#include "timestamp.h"
22+
23+
namespace rebootbackend {
24+
25+
using ::testing::_;
26+
using ::testing::AtLeast;
27+
using ::testing::ExplainMatchResult;
28+
using ::testing::IsEmpty;
29+
using ::testing::Not;
30+
using ::testing::Return;
31+
using ::testing::StrEq;
32+
using ::testing::StrictMock;
33+
34+
constexpr int kSelectTimeoutSeconds = 5;
35+
constexpr int kShortSelectTimeoutSeconds = 1;
36+
37+
MATCHER(IsDoneStatus, "") {
38+
const InitThreadStatus::DetailedStatus &status = arg;
39+
if (status.thread_state.active()) {
40+
*result_listener << "Status was active, expected inactive";
41+
return false;
42+
}
43+
if (status.detailed_thread_status != InitThreadStatus::ThreadStatus::DONE) {
44+
*result_listener << "Status was not DONE: "
45+
<< status.detailed_thread_status;
46+
return false;
47+
}
48+
if (status.thread_state.status().status() !=
49+
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_SUCCESS) {
50+
*result_listener << "Proto status was not SUCCESS: "
51+
<< status.thread_state.status().status();
52+
return false;
53+
}
54+
return true;
55+
}
56+
57+
MATCHER_P(IsActiveStatus, state_matcher, "") {
58+
const InitThreadStatus::DetailedStatus &status = arg;
59+
if (!status.thread_state.active()) {
60+
*result_listener << "Status was inactive, expected active";
61+
return false;
62+
}
63+
if (status.thread_state.status().status() !=
64+
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN) {
65+
*result_listener << "Proto status was not UNKNOWN: "
66+
<< status.thread_state.status().status();
67+
return false;
68+
}
69+
return ExplainMatchResult(state_matcher, status.detailed_thread_status,
70+
result_listener);
71+
}
72+
73+
MATCHER_P(IsErrorStatus, error_condition_matcher, "") {
74+
const InitThreadStatus::DetailedStatus &status = arg;
75+
if (status.thread_state.active()) {
76+
*result_listener << "Status was active, expected inactive";
77+
return false;
78+
}
79+
if (status.detailed_thread_status != InitThreadStatus::ThreadStatus::ERROR) {
80+
*result_listener << "Status was not ERROR: "
81+
<< status.detailed_thread_status;
82+
return false;
83+
}
84+
if (status.thread_state.status().status() !=
85+
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_FAILURE) {
86+
*result_listener << "Proto status was not FAILURE: "
87+
<< status.thread_state.status().status();
88+
return false;
89+
}
90+
return ExplainMatchResult(error_condition_matcher,
91+
status.detailed_thread_error_condition,
92+
result_listener);
93+
}
94+
95+
class InitThreadTest : public ::testing::Test {
96+
public:
97+
InitThreadTest()
98+
: m_db("STATE_DB", 0),
99+
m_config_db("CONFIG_DB", 0),
100+
m_critical_interface(),
101+
m_init_thread(m_critical_interface, m_telemetry, m_finished,
102+
m_stack_unfrozen) {
103+
// sigterm_requested and the Redis tables have global state that is
104+
// maintained across tests.
105+
sigterm_requested = false;
106+
TestUtils::clear_tables(m_db);
107+
init_redis_defaults();
108+
}
109+
110+
void populate_default_init_table() {
111+
initTable.hset("docker1|app1", "timestamp", "");
112+
initTable.hset("docker2|app2", "timestamp", "");
113+
initTable.hset("docker3|app3", "timestamp", "");
114+
// The invalid entry should not end up in the list of apps.
115+
initTable.hset("invalid", "timestamp", "");
116+
}
117+
118+
void advance_through_registration() {
119+
populate_default_init_table();
120+
TestUtils::populate_registration_table(m_db, "docker1|app1", false, false,
121+
false, true);
122+
TestUtils::populate_registration_table(m_db, "docker2|app2", true, true,
123+
true, false);
124+
TestUtils::populate_registration_table(m_db, "docker3|app3", false, false,
125+
true, false);
126+
}
127+
128+
void set_apps_to_state(std::string state) {
129+
TestUtils::populate_restart_table_state(m_db, "app1", state);
130+
TestUtils::populate_restart_table_state(m_db, "app2", state);
131+
TestUtils::populate_restart_table_state(m_db, "app3", state);
132+
}
133+
134+
protected:
135+
swss::DBConnector m_db;
136+
swss::DBConnector m_config_db;
137+
StrictMock<MockCriticalStateInterface> m_critical_interface;
138+
StrictMock<MockTelemetryInterface> m_telemetry;
139+
swss::NotificationConsumer m_nsf_channel;
140+
swss::SelectableEvent m_finished;
141+
swss::SelectableEvent m_stack_unfrozen;
142+
InitThread m_init_thread;
143+
};
144+
145+
TEST_F(InitThreadTest, TestJoinWithoutStart) {
146+
EXPECT_FALSE(m_init_thread.Join());
147+
}
148+
149+
class InitThreadTestWithSvResult
150+
: public InitThreadTest,
151+
public testing::WithParamInterface<std::string> {};
152+
153+
154+
} // namespace rebootbackend
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
/*class MockInitThread : public InitThread {
19+
public:
20+
MockInitThread()
21+
: InitThread(m_unused_event,
22+
m_unused_event) {}
23+
24+
MOCK_METHOD(swss::StatusCode, Start, (), (override));
25+
MOCK_METHOD(void, Stop, (), (override));
26+
MOCK_METHOD(bool, Join, (), (override));
27+
MOCK_METHOD(gnoi::system::RebootStatusResponse, GetResponse, (), (override));
28+
MOCK_METHOD(InitThreadStatus::DetailedStatus, GetDetailedStatus, (),
29+
(override));
30+
31+
private:
32+
swss::SelectableEvent m_unused_event;
33+
};*/
34+
35+
} // namespace rebootbackend
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include "reboot_common.h"
2+
3+
#include <gmock/gmock.h>
4+
#include <gtest/gtest.h>
5+
#include <unistd.h>
6+
7+
namespace rebootbackend {
8+
9+
using ::testing::_;
10+
using ::testing::AtLeast;
11+
using ::testing::ExplainMatchResult;
12+
using ::testing::StrEq;
13+
14+
MATCHER_P2(CheckTimespec, secs, nsecs, "") {
15+
return (arg.tv_sec == secs && arg.tv_nsec == nsecs);
16+
}
17+
18+
TEST(RebootCommon, MillisecToTimespec) {
19+
timespec l_timespec = milliseconds_to_timespec(0);
20+
EXPECT_THAT(l_timespec, CheckTimespec(0, 0));
21+
l_timespec = milliseconds_to_timespec(200);
22+
EXPECT_THAT(l_timespec, CheckTimespec(0, 200 * 1000 * 1000));
23+
l_timespec = milliseconds_to_timespec(1800);
24+
EXPECT_THAT(l_timespec, CheckTimespec(1, 800 * 1000 * 1000));
25+
}
26+
27+
} // namespace rebootbackend

0 commit comments

Comments
 (0)