blob: 31293e05f37da25f0670d30a20f231206e9f9192 [file]
#include "tools/base/deploy/installer/tests/fake_device.h"
#include <sys/stat.h>
#include <unistd.h>
#include <thread>
#include <grpc++/grpc++.h>
#include <grpc/grpc.h>
#include "tools/base/deploy/common/env.h"
#include "tools/base/deploy/common/log.h"
#include "tools/base/deploy/installer/tests/fake_device.grpc.pb.h"
#include "tools/base/deploy/installer/tests/fake_device.pb.h"
namespace deploy {
FakeDevice::FakeDevice() {
std::string addr = std::string("localhost:") + std::to_string(Env::port());
std::shared_ptr<grpc::Channel> channel =
grpc::CreateChannel(addr.c_str(), grpc::InsecureChannelCredentials());
client_ = FakeDeviceService::NewStub(channel);
}
void FakeDevice::RecordCommand(const std::string& command) {
RecordCommandRequest request;
RecordCommandResponse response;
request.set_command(command);
grpc::ClientContext context;
client_->RecordCommand(&context, request, &response);
}
void write_to_device(grpc::ClientReaderWriterInterface<ShellCommand, CommandResponse>* writer, int exit_fd) {
char buffer[8192];
do {
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(exit_fd, &fds);
if (select(exit_fd + 1, &fds, nullptr, nullptr, nullptr) >= 0) {
if (FD_ISSET(STDIN_FILENO, &fds)) {
int r = read(STDIN_FILENO, buffer, 8192);
if (r <= 0) {
break;
}
ShellCommand command;
command.set_stdin(buffer, r);
writer->Write(command);
}
if (FD_ISSET(exit_fd, &fds)) {
// Time to stop reading.
break;
}
}
} while (true);
}
int FakeDevice::ExecuteCommand(const std::string& cmd) {
grpc::ClientContext context;
std::unique_ptr<
grpc::ClientReaderWriterInterface<ShellCommand, CommandResponse>>
reader_writer = client_->ExecuteCommand(&context);
ShellCommand command;
command.set_command(cmd);
command.set_uid(Env::uid());
reader_writer->Write(command);
int exit_pipe[2];
pipe(exit_pipe);
std::thread write_t(write_to_device, reader_writer.get(), exit_pipe[0]);
CommandResponse response;
int ret = 0;
while (!response.terminate() && reader_writer->Read(&response)) {
std::string stdout = response.stdout();
int rem = stdout.size();
const char* buffer = stdout.data();
while (rem > 0) {
int w = write(STDOUT_FILENO, buffer, rem);
if (w <= 0) {
break;
}
buffer += w;
rem -= w;
}
ret = response.exit_code();
}
// Write a byte to the exit pipe to unblock the writing thread.
write(exit_pipe[1], "", 1);
write_t.join();
reader_writer->WritesDone();
reader_writer->Finish();
return ret;
}
bool FakeDevice::Exists(const std::string& path) {
struct stat dummy;
std::string to_exec = Env::root() + path;
return stat(to_exec.c_str(), &dummy) == 0;
}
int FakeDevice::GetAppUid(const std::string& package) {
GetAppUidRequest request;
GetAppUidResponse response;
request.set_package(package);
grpc::ClientContext context;
client_->GetAppUid(&context, request, &response);
return response.uid();
}
} // namespace deploy