blob: 226beca45d179c9cbb10170f589b0061af57f674 [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include <base/bind.h>
#include <base/callback.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <brillo/bind_lambda.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "diagnostics/diagnosticsd/diagnosticsd_grpc_service.h"
#include "diagnostics/diagnosticsd/protobuf_test_utils.h"
#include "diagnosticsd.pb.h" // NOLINT(build/include)
using testing::StrictMock;
using testing::UnorderedElementsAre;
namespace diagnostics {
namespace {
class MockDiagnosticsdGrpcServiceDelegate
: public DiagnosticsdGrpcService::Delegate {};
// Tests for the DiagnosticsdGrpcService class.
class DiagnosticsdGrpcServiceTest : public testing::Test {
protected:
DiagnosticsdGrpcServiceTest() = default;
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
service_.set_root_dir_for_testing(temp_dir_.GetPath());
}
DiagnosticsdGrpcService* service() { return &service_; }
void CreateDirRecursivelyInTempDir(const base::FilePath& relative_dir_path) {
if (relative_dir_path == base::FilePath(base::FilePath::kCurrentDirectory))
return;
CreateDirRecursivelyInTempDir(relative_dir_path.DirName());
EXPECT_TRUE(
base::CreateDirectory(temp_dir_.GetPath().Append(relative_dir_path)));
}
void StoreFileInTempDir(const base::FilePath& relative_file_path,
const std::string& file_contents) {
EXPECT_EQ(base::WriteFile(temp_dir_.GetPath().Append(relative_file_path),
file_contents.c_str(), file_contents.size()),
file_contents.size());
}
void ExecuteGetProcData(grpc_api::GetProcDataRequest::Type request_type,
std::vector<grpc_api::FileDump>* file_dumps) {
auto request = std::make_unique<grpc_api::GetProcDataRequest>();
request->set_type(request_type);
std::unique_ptr<grpc_api::GetProcDataResponse> response;
service()->GetProcData(
std::move(request),
base::Bind(
[](std::unique_ptr<grpc_api::GetProcDataResponse>* response,
std::unique_ptr<grpc_api::GetProcDataResponse>
received_response) {
*response = std::move(received_response);
},
base::Unretained(&response)));
// Expect the method to return immediately.
ASSERT_TRUE(response);
file_dumps->assign(response->file_dump().begin(),
response->file_dump().end());
}
grpc_api::FileDump MakeFileDump(
const base::FilePath& relative_file_path,
const base::FilePath& canonical_relative_file_path,
const std::string& file_contents) const {
grpc_api::FileDump file_dump;
file_dump.set_path(temp_dir_.GetPath().Append(relative_file_path).value());
file_dump.set_canonical_path(
temp_dir_.GetPath().Append(canonical_relative_file_path).value());
file_dump.set_contents(file_contents);
return file_dump;
}
private:
base::ScopedTempDir temp_dir_;
StrictMock<MockDiagnosticsdGrpcServiceDelegate> delegate_;
DiagnosticsdGrpcService service_{&delegate_};
};
} // namespace
TEST_F(DiagnosticsdGrpcServiceTest, GetProcDataUnsetType) {
std::vector<grpc_api::FileDump> file_dumps;
ExecuteGetProcData(grpc_api::GetProcDataRequest::TYPE_UNSET, &file_dumps);
EXPECT_TRUE(file_dumps.empty())
<< "Obtained: "
<< GetProtosRangeDebugString(file_dumps.begin(), file_dumps.end());
}
namespace {
// Tests for the GetProcData() method of DiagnosticsdGrpcServiceTest when a
// single file is requested.
//
// This is a parameterized test with the following parameters:
// * |proc_data_request_type| - type of the GetProcData() request to be executed
// (see GetProcDataRequest::Type);
// * |relative_file_path| - relative path to the file which is expected to be
// read by the executed GetProcData() request.
class SingleProcFileDiagnosticsdGrpcServiceTest
: public DiagnosticsdGrpcServiceTest,
public testing::WithParamInterface<std::tuple<
grpc_api::GetProcDataRequest::Type /* proc_data_request_type */,
std::string /* relative_file_path */>> {
protected:
static constexpr char kFakeFileContentsChars[] = "\0fake row 1\nfake row 2\n";
const std::string kFakeFileContents{std::begin(kFakeFileContentsChars),
std::end(kFakeFileContentsChars)};
// Accessors to individual test parameters from the test parameter tuple
// returned by gtest's GetParam():
grpc_api::GetProcDataRequest::Type proc_data_request_type() const {
return std::get<0>(GetParam());
}
base::FilePath relative_file_path() const {
return base::FilePath(std::get<1>(GetParam()));
}
};
// Need external definition.
constexpr char
SingleProcFileDiagnosticsdGrpcServiceTest::kFakeFileContentsChars[];
} // namespace
// Test that GetProcData() returns a single item with the requested file data
// when the file exists.
TEST_P(SingleProcFileDiagnosticsdGrpcServiceTest, Basic) {
CreateDirRecursivelyInTempDir(relative_file_path().DirName());
StoreFileInTempDir(relative_file_path(), kFakeFileContents);
std::vector<grpc_api::FileDump> file_dumps;
ExecuteGetProcData(proc_data_request_type(), &file_dumps);
const auto kExpectedFileDump = MakeFileDump(
relative_file_path(), relative_file_path(), kFakeFileContents);
EXPECT_THAT(file_dumps,
UnorderedElementsAre(ProtobufEquals(kExpectedFileDump)))
<< GetProtosRangeDebugString(file_dumps.begin(), file_dumps.end());
}
// Test that GetProcData() returns empty result when the file doesn't exist.
TEST_P(SingleProcFileDiagnosticsdGrpcServiceTest, NonExisting) {
std::vector<grpc_api::FileDump> file_dumps;
ExecuteGetProcData(proc_data_request_type(), &file_dumps);
EXPECT_TRUE(file_dumps.empty())
<< "Obtained: "
<< GetProtosRangeDebugString(file_dumps.begin(), file_dumps.end());
}
INSTANTIATE_TEST_CASE_P(
,
SingleProcFileDiagnosticsdGrpcServiceTest,
testing::Values(
std::tie(grpc_api::GetProcDataRequest::FILE_UPTIME, "proc/uptime"),
std::tie(grpc_api::GetProcDataRequest::FILE_MEMINFO, "proc/meminfo"),
std::tie(grpc_api::GetProcDataRequest::FILE_LOADAVG, "proc/loadavg"),
std::tie(grpc_api::GetProcDataRequest::FILE_STAT, "proc/stat"),
std::tie(grpc_api::GetProcDataRequest::FILE_NET_NETSTAT,
"proc/net/netstat"),
std::tie(grpc_api::GetProcDataRequest::FILE_NET_DEV, "proc/net/dev")));
} // namespace diagnostics