blob: 1bffe4a947c6514ede53005095abb2fce1724350 [file] [log] [blame]
// Copyright 2019 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 <utility>
#include <vector>
#include <base/message_loop/message_loop.h>
#include <base/time/time.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "diagnostics/diag/diag_async_grpc_client_adapter.h"
#include "diagnostics/diag/diag_routine_requester.h"
#include "wilco_dtc_supportd.pb.h" // NOLINT(build/include)
using ::testing::_;
using ::testing::ElementsAreArray;
using ::testing::Invoke;
using ::testing::StrictMock;
using ::testing::WithArg;
namespace diagnostics {
namespace {
using GetAvailableRoutinesCallback = base::Callback<void(
std::unique_ptr<grpc_api::GetAvailableRoutinesResponse> response)>;
using RunRoutineCallback = base::Callback<void(
std::unique_ptr<grpc_api::RunRoutineResponse> response)>;
using GetRoutineUpdateCallback = base::Callback<void(
std::unique_ptr<grpc_api::GetRoutineUpdateResponse> response)>;
constexpr grpc_api::DiagnosticRoutine kFakeAvailableRoutines[] = {
grpc_api::ROUTINE_BATTERY, grpc_api::ROUTINE_BATTERY_SYSFS};
constexpr int kExpectedUuid = 89769;
constexpr grpc_api::DiagnosticRoutineStatus kExpectedStatus =
grpc_api::ROUTINE_STATUS_RUNNING;
constexpr int kExpectedProgressPercent = 37;
constexpr grpc_api::DiagnosticRoutineUserMessage kExpectedUserMessage =
grpc_api::ROUTINE_USER_MESSAGE_UNSET;
constexpr char kExpectedOutput[] = "Sample output.";
class MockDiagAsyncGrpcClientAdapter : public DiagAsyncGrpcClientAdapter {
public:
void Connect(const std::string& target_uri) override {}
MOCK_CONST_METHOD0(IsConnected, bool());
MOCK_METHOD1(Shutdown, void(const base::Closure& on_shutdown));
MOCK_METHOD2(GetAvailableRoutines,
void(const grpc_api::GetAvailableRoutinesRequest& request,
GetAvailableRoutinesCallback callback));
MOCK_METHOD2(RunRoutine,
void(const grpc_api::RunRoutineRequest& request,
RunRoutineCallback callback));
MOCK_METHOD2(GetRoutineUpdate,
void(const grpc_api::GetRoutineUpdateRequest& request,
GetRoutineUpdateCallback callback));
};
grpc_api::RunRoutineRequest ConstructRunBatteryRoutineRequest(int low_mah,
int high_mah) {
grpc_api::RunRoutineRequest request;
request.set_routine(grpc_api::ROUTINE_BATTERY);
request.mutable_battery_params()->set_low_mah(low_mah);
request.mutable_battery_params()->set_high_mah(high_mah);
return request;
}
grpc_api::RunRoutineRequest ConstructRunBatterySysfsRoutineRequest(
int maximum_cycle_count, int percent_battery_wear_allowed) {
grpc_api::RunRoutineRequest request;
request.set_routine(grpc_api::ROUTINE_BATTERY_SYSFS);
request.mutable_battery_sysfs_params()->set_maximum_cycle_count(
maximum_cycle_count);
request.mutable_battery_sysfs_params()->set_percent_battery_wear_allowed(
percent_battery_wear_allowed);
return request;
}
grpc_api::RunRoutineRequest ConstructRunUrandomRoutineRequest(
int length_seconds) {
grpc_api::RunRoutineRequest request;
request.set_routine(grpc_api::ROUTINE_URANDOM);
request.mutable_urandom_params()->set_length_seconds(length_seconds);
return request;
}
} // namespace
class DiagRoutineRequesterTest : public ::testing::Test {
protected:
DiagRoutineRequesterTest() {
EXPECT_CALL(mock_adapter_, Shutdown(_))
.WillOnce(Invoke(
[](const base::Closure& on_shutdown) { on_shutdown.Run(); }));
}
// Sets the MockDiagAsyncGrpcClientAdapter to run the next callback with
// a null pointer as its response.
void SetNullptrAvailableRoutinesResponse() {
EXPECT_CALL(mock_adapter_, GetAvailableRoutines(_, _))
.WillOnce(WithArg<1>(Invoke([](GetAvailableRoutinesCallback callback) {
callback.Run(nullptr);
})));
}
void SetNullptrRunRoutineResponse() {
EXPECT_CALL(mock_adapter_, RunRoutine(_, _))
.WillOnce(WithArg<1>(Invoke(
[](RunRoutineCallback callback) { callback.Run(nullptr); })));
}
void SetNullptrGetRoutineUpdateResponse() {
EXPECT_CALL(mock_adapter_, GetRoutineUpdate(_, _))
.WillOnce(WithArg<1>(Invoke(
[](GetRoutineUpdateCallback callback) { callback.Run(nullptr); })));
}
// Sets the MockDiagAsyncGrpcClientAdapter to run the next callback with a
// fake routine list as its GetAvailableRoutinesResponse.
void SetAvailableRoutinesResponse() {
EXPECT_CALL(mock_adapter_, GetAvailableRoutines(_, _))
.WillRepeatedly(WithArg<1>(
Invoke([](GetAvailableRoutinesCallback callback) mutable {
std::unique_ptr<grpc_api::GetAvailableRoutinesResponse> reply =
std::make_unique<grpc_api::GetAvailableRoutinesResponse>();
for (auto routine : kFakeAvailableRoutines)
reply->add_routines(routine);
callback.Run(std::move(reply));
})));
}
// Sets the MockDiagAsyncGrpcClientAdapter to run the next callback with a
// fake uuid and status as its RunRoutineResponse.
void SetRunRoutineResponse(int uuid,
grpc_api::DiagnosticRoutineStatus status) {
EXPECT_CALL(mock_adapter_, RunRoutine(_, _))
.WillRepeatedly(WithArg<1>(
Invoke([uuid, status](RunRoutineCallback callback) mutable {
auto reply = std::make_unique<grpc_api::RunRoutineResponse>();
reply->set_uuid(uuid);
reply->set_status(status);
callback.Run(std::move(reply));
})));
}
// Sets the MockDiagAsyncGrpcClientAdapter to run the next callback with a
// fake GetRoutineUpdateResponse.
void SetGetRoutineUpdateResponse(
int uuid,
grpc_api::DiagnosticRoutineStatus status,
int progress_percent,
grpc_api::DiagnosticRoutineUserMessage user_message,
const std::string& output) {
EXPECT_CALL(mock_adapter_, GetRoutineUpdate(_, _))
.WillRepeatedly(Invoke(
[uuid, status, progress_percent, user_message, output](
::testing::Unused, GetRoutineUpdateCallback callback) mutable {
auto reply =
std::make_unique<grpc_api::GetRoutineUpdateResponse>();
reply->set_uuid(uuid);
reply->set_status(status);
reply->set_progress_percent(progress_percent);
reply->set_user_message(user_message);
reply->set_output(output);
callback.Run(std::move(reply));
}));
}
DiagRoutineRequester* routine_requester() { return routine_requester_.get(); }
private:
base::MessageLoopForIO message_loop_;
StrictMock<MockDiagAsyncGrpcClientAdapter> mock_adapter_;
std::unique_ptr<DiagRoutineRequester> routine_requester_ =
std::make_unique<DiagRoutineRequester>(&mock_adapter_);
DISALLOW_COPY_AND_ASSIGN(DiagRoutineRequesterTest);
};
// Test that we handle an empty GetAvailableTests response.
TEST_F(DiagRoutineRequesterTest, EmptyGetAvailableTestsResponse) {
SetNullptrAvailableRoutinesResponse();
auto response = routine_requester()->GetAvailableRoutines();
EXPECT_EQ(response, base::nullopt);
}
// Test that we handle an empty RunRoutine response.
TEST_F(DiagRoutineRequesterTest, EmptyRunRoutineResponse) {
SetNullptrRunRoutineResponse();
grpc_api::RunRoutineRequest request;
auto response = routine_requester()->RunRoutine(request);
EXPECT_EQ(response, nullptr);
}
// Test that we handle an empty GetRoutineUpdate response.
TEST_F(DiagRoutineRequesterTest, EmptyGetRoutineUpdateResponse) {
SetNullptrGetRoutineUpdateResponse();
auto response = routine_requester()->GetRoutineUpdate(
kExpectedUuid, grpc_api::GetRoutineUpdateRequest::GET_STATUS, true);
EXPECT_EQ(response, nullptr);
}
// Test that we can retrieve the available routines.
TEST_F(DiagRoutineRequesterTest, GetAvailableRoutines) {
SetAvailableRoutinesResponse();
auto response = routine_requester()->GetAvailableRoutines();
ASSERT_NE(response, base::nullopt);
EXPECT_THAT(response.value(), ElementsAreArray(kFakeAvailableRoutines));
}
// Test that we can run the battery routine.
TEST_F(DiagRoutineRequesterTest, RunBatteryRoutine) {
SetRunRoutineResponse(kExpectedUuid, kExpectedStatus);
auto response =
routine_requester()->RunRoutine(ConstructRunBatteryRoutineRequest(0, 10));
ASSERT_TRUE(response);
EXPECT_EQ(response->uuid(), kExpectedUuid);
EXPECT_EQ(response->status(), kExpectedStatus);
}
// Test that we can run the battery_sysfs routine.
TEST_F(DiagRoutineRequesterTest, RunBatterySysfsRoutine) {
SetRunRoutineResponse(kExpectedUuid, kExpectedStatus);
auto response =
routine_requester()->RunRoutine(ConstructRunBatterySysfsRoutineRequest(
5 /* maximum_cycle_count */, 90 /* percent_battery_wear_allowed */));
ASSERT_TRUE(response);
EXPECT_EQ(response->uuid(), kExpectedUuid);
EXPECT_EQ(response->status(), kExpectedStatus);
}
// Test that we can run the urandom routine.
TEST_F(DiagRoutineRequesterTest, RunUrandomRoutine) {
SetRunRoutineResponse(kExpectedUuid, kExpectedStatus);
auto response =
routine_requester()->RunRoutine(ConstructRunUrandomRoutineRequest(10));
ASSERT_TRUE(response);
EXPECT_EQ(response->uuid(), kExpectedUuid);
EXPECT_EQ(response->status(), kExpectedStatus);
}
// Test that we can send a command to an existing routine.
TEST_F(DiagRoutineRequesterTest, GetRoutineUpdate) {
SetRunRoutineResponse(kExpectedUuid, kExpectedStatus);
EXPECT_TRUE(routine_requester()->RunRoutine(
ConstructRunBatteryRoutineRequest(0, 10)));
SetGetRoutineUpdateResponse(kExpectedUuid, kExpectedStatus,
kExpectedProgressPercent, kExpectedUserMessage,
kExpectedOutput);
auto reply = routine_requester()->GetRoutineUpdate(
kExpectedUuid, grpc_api::GetRoutineUpdateRequest::GET_STATUS, true);
ASSERT_TRUE(reply);
EXPECT_EQ(reply->uuid(), kExpectedUuid);
EXPECT_EQ(reply->status(), kExpectedStatus);
EXPECT_EQ(reply->progress_percent(), kExpectedProgressPercent);
EXPECT_EQ(reply->user_message(), kExpectedUserMessage);
EXPECT_EQ(reply->output(), kExpectedOutput);
}
} // namespace diagnostics