Skip to content

Commit

Permalink
gnmi sanity tests & gnmi interface state tests. (sonic-net#342)
Browse files Browse the repository at this point in the history
Co-authored-by: rhalstea <[email protected]>
Co-authored-by: bhagatgit <[email protected]>
  • Loading branch information
3 people authored Jul 17, 2024
1 parent 0ca380a commit fe10c61
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 0 deletions.
12 changes: 12 additions & 0 deletions pins_infra_deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,15 @@ def pins_infra_deps():
],
sha256 = "a89e203d3cf264e564fcb96b6e06dd70bc0557356eb48400ce4b5d97c2c3720d",
)
if not native.existing_rule("com_github_nlohmann_json"):
http_archive(
name = "com_github_nlohmann_json",
# JSON for Modern C++
url = "https://github.com/nlohmann/json/archive/v3.7.3.zip",
strip_prefix = "json-3.7.3",
sha256 = "e109cd4a9d1d463a62f0a81d7c6719ecd780a52fb80a22b901ed5b6fe43fb45b",
build_file_content = """cc_library(name="json",
visibility=["//visibility:public"],
hdrs=["single_include/nlohmann/json.hpp"]
)""",
)
99 changes: 99 additions & 0 deletions tests/thinkit_sanity_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,30 @@

#include "absl/status/statusor.h"
#include "absl/time/time.h"
#include "glog/logging.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "gutil/status.h"
#include "gutil/status_matchers.h"
#include "p4/v1/p4runtime.grpc.pb.h"
#include "p4_pdpi/p4_runtime_session.h"
#include "proto/gnmi/gnmi.grpc.pb.h"
#include "include/nlohmann/json.hpp"
#include "thinkit/ssh_client.h"
#include "thinkit/switch.h"

namespace pins_test {
namespace {

using ::nlohmann::json;
using ::testing::Eq;

} // namespace

constexpr char kOpenconfigStr[] = "openconfig";
constexpr char kStateUp[] = "UP";
constexpr char kInterfaces[] = "interfaces";

void TestSSHCommand(thinkit::SSHClient& ssh_client, thinkit::Switch& sut) {
ASSERT_OK_AND_ASSIGN(std::string output,
ssh_client.RunCommand(sut.ChassisName(), "echo foo",
Expand All @@ -53,4 +61,95 @@ void TestP4Session(thinkit::Switch& sut) {
pdpi::P4RuntimeSession::Create(std::move(sut_p4runtime_stub), kDeviceId));
}

void TestGnmiCheckSpecificInterfaceStateOperation(thinkit::Switch& sut,
std::string if_name) {
ASSERT_OK_AND_ASSIGN(auto sut_gnmi_stub, sut.CreateGnmiStub());
gnmi::GetRequest req;
req.set_type(gnmi::GetRequest_DataType_STATE);
req.mutable_prefix()->set_origin(kOpenconfigStr);
gnmi::Path* path = req.add_path();
path->add_elem()->set_name(kInterfaces);
auto elem = path->add_elem();
elem->set_name("interface");
(*elem->mutable_key())["name"] = if_name;
path->add_elem()->set_name("state");
path->add_elem()->set_name("oper-status");

req.set_encoding(::gnmi::Encoding::JSON_IETF);
LOG(INFO) << "Sending GET request: " << req.ShortDebugString();

gnmi::GetResponse resp;
grpc::ClientContext context;
ASSERT_OK(sut_gnmi_stub->Get(&context, req, &resp));
LOG(INFO) << "Received GET response: " << resp.ShortDebugString();
ASSERT_EQ(resp.notification_size(), 1);
ASSERT_EQ(resp.notification(0).update_size(), 1);
const std::string val_str =
resp.notification(0).update(0).val().json_ietf_val();
auto const resp_json = json::parse(val_str);
auto const oper_status = resp_json.find("openconfig-interfaces:oper-status");
ASSERT_NE(oper_status, resp_json.end());
EXPECT_THAT(oper_status->dump(), testing::HasSubstr(kStateUp));
}

void TestGnmiCheckInterfaceStateOperation(thinkit::Switch& sut) {
ASSERT_OK_AND_ASSIGN(auto sut_gnmi_stub, sut.CreateGnmiStub());
gnmi::GetRequest req;
req.mutable_prefix()->set_origin(kOpenconfigStr);
req.set_type(gnmi::GetRequest_DataType_STATE);
gnmi::Path* path = req.add_path();
path->add_elem()->set_name(kInterfaces);
req.set_encoding(::gnmi::Encoding::JSON_IETF);
LOG(INFO) << "Sending GET request: " << req.ShortDebugString();

gnmi::GetResponse resp;
grpc::ClientContext context;
ASSERT_OK(sut_gnmi_stub->Get(&context, req, &resp));
LOG(INFO) << "Received GET response: " << resp.ShortDebugString();
ASSERT_EQ(resp.notification_size(), 1);
ASSERT_EQ(resp.notification(0).update_size(), 1);
auto const resp_json =
json::parse(resp.notification(0).update(0).val().json_ietf_val());
auto const oc_intf_json = resp_json.find("openconfig-interfaces:interfaces");
ASSERT_NE(oc_intf_json, resp_json.end());
auto const oc_intf_list_json = oc_intf_json->find("interface");
ASSERT_NE(oc_intf_list_json, oc_intf_json->end());
for (auto const& element : oc_intf_list_json->items()) {
auto const element_state_json = element.value().find("state");
ASSERT_NE(element_state_json, element.value().end());

auto const element_status_json = element_state_json->find("oper-status");
ASSERT_NE(element_status_json, element_state_json->end());

EXPECT_THAT(element_status_json->dump(), testing::HasSubstr(kStateUp));
}
}
void TestGnmiGetInterfaceOperation(thinkit::Switch& sut) {
ASSERT_OK_AND_ASSIGN(auto sut_gnmi_stub, sut.CreateGnmiStub());
gnmi::GetRequest req;
req.mutable_prefix()->set_origin(kOpenconfigStr);
req.set_type(gnmi::GetRequest_DataType_ALL);
gnmi::Path* path = req.add_path();
path->add_elem()->set_name(kInterfaces);
req.set_encoding(::gnmi::Encoding::JSON_IETF);
LOG(INFO) << "Sending GET request: " << req.ShortDebugString();
gnmi::GetResponse resp;
grpc::ClientContext context;
ASSERT_OK(sut_gnmi_stub->Get(&context, req, &resp));
LOG(INFO) << "Received GET response: " << resp.ShortDebugString();
}

void TestGnmiGetAllOperation(thinkit::Switch& sut) {
ASSERT_OK_AND_ASSIGN(auto sut_gnmi_stub, sut.CreateGnmiStub());
gnmi::GetRequest req;
req.mutable_prefix()->set_origin(kOpenconfigStr);
req.set_type(gnmi::GetRequest_DataType_ALL);
req.set_encoding(gnmi::Encoding::JSON_IETF);
LOG(INFO) << "Sending GET request: " << req.ShortDebugString();
gnmi::GetResponse resp;
grpc::ClientContext context;
ASSERT_OK(sut_gnmi_stub->Get(&context, req, &resp));
LOG(INFO) << "Received GET response: " << resp.ShortDebugString();
}

} // namespace pins_test
12 changes: 12 additions & 0 deletions tests/thinkit_sanity_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ void TestSSHCommand(thinkit::SSHClient& ssh_client, thinkit::Switch& sut);
// Tests that P4 Sessions can be established with the switch.
void TestP4Session(thinkit::Switch& sut);

// Tests that gNMI get interface works fine with SUT.
void TestGnmiGetInterfaceOperation(thinkit::Switch& sut);

// Tests that gNMI get all works fine with SUT.
void TestGnmiGetAllOperation(thinkit::Switch& sut);

// Tests that SUT all ports state is UP.
void TestGnmiCheckInterfaceStateOperation(thinkit::Switch& sut);

// Tests that SUT specific port state is UP.
void TestGnmiCheckSpecificInterfaceStateOperation(thinkit::Switch& sut,
std::string if_name);
} // namespace pins_test

#endif // GOOGLE_TESTS_THINKIT_SANITY_TESTS_H_

0 comments on commit fe10c61

Please sign in to comment.