blob: 57542057bca4e0a997a5031a97d0eb0d8e958a88 [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.
// See help usage message in main() for basic description.
#include <cstdlib>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <brillo/flag_helper.h>
#include <google/protobuf/message.h>
#include "diagnostics/dpsl/public/dpsl_global_context.h"
#include "diagnostics/dpsl/public/dpsl_requester.h"
#include "diagnostics/dpsl/public/dpsl_thread_context.h"
#include "diagnostics/dpsl/test_utils/common.h"
#include "wilco_dtc_supportd.pb.h" // NOLINT(build/include)
namespace diagnostics {
namespace {
// A member function of DpslRequester, used to call a gRPC method which
// takes a |Request| as a parameter and returns a |Response| via a callback.
template <typename Request, typename Response>
using GrpcRequestFunction = void (DpslRequester::*)(
std::unique_ptr<Request>, std::function<void(std::unique_ptr<Response>)>);
// Used to make gRPC requests to wilco_dtc_supportd.
// Parse the supplied |request_json| to a proto of type |Request|, and then
// call the provided |request_function| on the |requester| with that
// |Request| as the argument. The result proto of type |Response| is passed to
// the |callback| method.
template <typename Request, typename Response>
bool MakeRequest(
DpslRequester* requester,
GrpcRequestFunction<Request, Response> request_function,
const std::string& request_json,
std::function<void(std::unique_ptr<google::protobuf::Message>)> callback) {
auto request = test_utils::JsonToProto<Request>(request_json);
if (!request) {
return false;
}
((*requester).*request_function)(std::move(request), callback);
return true;
}
} // namespace
} // namespace diagnostics
int main(int argc, char** argv) {
DEFINE_string(message_name, "",
"Name of gRPC request to make. Options are:"
"GetAvailableRoutines,"
"GetConfigurationData,"
"GetDriveSystemData,"
"GetEcTelemetry,"
"GetOsVersion,"
"GetProcData,"
"GetRoutineUpdate,"
"GetStatefulPartitionAvailableCapacity,"
"GetSysfsData,"
"GetVpdField,"
"PerformWebRequest,"
"RunRoutine,"
"SendMessageToUi");
DEFINE_string(message_body, "",
"JSON-formatted body of proto to send as argument of request");
constexpr char kUsageMessage[] =
R"(DPSL Requester Utility
Command line utility to test DPSL communication into and out of a VM. The
utility sends an outgoing gRPC request to wilco_dtc_supportd and prints the
returned response. The response is printed as JSON, so you can see both the name
and the actual content of the proto.
EXAMPLE USAGE
(VM)$ diagnostics_dpsl_test_requester \
--message_name=GetEcTelemetry --message_body='{"payload":"OAAE"}'
{
"body": {
"payload": "AABFcnIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"status": "STATUS_OK"
},
"name": "GetEcTelemetryResponse"
})";
brillo::FlagHelper::Init(argc, argv, kUsageMessage);
if (FLAGS_message_name.empty() || FLAGS_message_body.empty()) {
std::cerr << "Both --message_name and --message_body must be provided\n";
return EXIT_FAILURE;
}
auto global_context = diagnostics::DpslGlobalContext::Create();
auto thread_context =
diagnostics::DpslThreadContext::Create(global_context.get());
auto requester = diagnostics::DpslRequester::Create(
thread_context.get(),
diagnostics::DpslRequester::GrpcClientUri::kVmVsock);
if (!requester) {
std::cerr << "Failed to create DpslRequester\n";
return EXIT_FAILURE;
}
// Set up our callback that will be called when the response is received.
bool response_succeeded = false;
auto callback = [&response_succeeded, &thread_context](
std::unique_ptr<google::protobuf::Message> response) {
if (!response) {
std::cerr << "DPSL reports that request failed\n";
response_succeeded = false;
} else {
response_succeeded = diagnostics::test_utils::PrintProto(*response);
}
thread_context->QuitEventLoop();
};
bool request_succeeded = false;
if (FLAGS_message_name == "GetAvailableRoutines") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::GetAvailableRoutines,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "GetConfigurationData") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::GetConfigurationData,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "GetDriveSystemData") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::GetDriveSystemData,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "GetEcTelemetry") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::GetEcTelemetry,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "GetOsVersion") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::GetOsVersion,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "GetProcData") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::GetProcData,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "GetRoutineUpdate") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::GetRoutineUpdate,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "GetStatefulPartitionAvailableCapacity") {
request_succeeded = diagnostics::MakeRequest(
requester.get(),
&diagnostics::DpslRequester::GetStatefulPartitionAvailableCapacity,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "GetSysfsData") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::GetSysfsData,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "GetVpdField") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::GetVpdField,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "PerformWebRequest") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::PerformWebRequest,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "RequestBluetoothDataNotification") {
request_succeeded = diagnostics::MakeRequest(
requester.get(),
&diagnostics::DpslRequester::RequestBluetoothDataNotification,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "RunRoutine") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::RunRoutine,
FLAGS_message_body, callback);
} else if (FLAGS_message_name == "SendMessageToUi") {
request_succeeded = diagnostics::MakeRequest(
requester.get(), &diagnostics::DpslRequester::SendMessageToUi,
FLAGS_message_body, callback);
} else {
std::cerr
<< "Provided --message_name did not match any available gRPC request\n";
return EXIT_FAILURE;
}
if (!request_succeeded) {
std::cerr << "Failed to send request\n";
return EXIT_FAILURE;
}
// Blocks until |thread_context->QuitEventLoop()| in |callback| is called.
thread_context->RunEventLoop();
return response_succeeded ? EXIT_SUCCESS : EXIT_FAILURE;
}