| // 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; |
| } |