184 lines
4.9 KiB
C++
184 lines
4.9 KiB
C++
/*
|
|
* Copyright 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "ShellDriverTest.h"
|
|
|
|
#include <errno.h>
|
|
#include <gtest/gtest.h>
|
|
#include <limits.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <unistd.h>
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
#include <VtsDriverCommUtil.h>
|
|
#include "test/vts/proto/VtsDriverControlMessage.pb.h"
|
|
|
|
#include "ShellDriver.h"
|
|
|
|
using namespace std;
|
|
|
|
namespace android {
|
|
namespace vts {
|
|
|
|
static int kMaxRetry = 3;
|
|
|
|
/*
|
|
* send a command to the driver on specified UNIX domain socket and print out
|
|
* the outputs from driver.
|
|
*/
|
|
static string vts_shell_driver_test_client_start(const string& command,
|
|
const string& socket_address) {
|
|
struct sockaddr_un address;
|
|
int socket_fd;
|
|
|
|
socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
|
if (socket_fd < 0) {
|
|
fprintf(stderr, "socket() failed\n");
|
|
return "";
|
|
}
|
|
|
|
VtsDriverCommUtil driverUtil(socket_fd);
|
|
|
|
memset(&address, 0, sizeof(struct sockaddr_un));
|
|
|
|
address.sun_family = AF_UNIX;
|
|
strncpy(address.sun_path, socket_address.c_str(),
|
|
sizeof(address.sun_path) - 1);
|
|
|
|
int conn_success;
|
|
int retry_count = 0;
|
|
|
|
conn_success = connect(socket_fd, (struct sockaddr*)&address,
|
|
sizeof(struct sockaddr_un));
|
|
for (retry_count = 0; retry_count < kMaxRetry && conn_success != 0;
|
|
retry_count++) { // retry if server not ready
|
|
printf("Client: connection failed, retrying...\n");
|
|
retry_count++;
|
|
if (usleep(50 * pow(retry_count, 3)) != 0) {
|
|
fprintf(stderr, "shell driver unit test: sleep intrupted.");
|
|
}
|
|
|
|
conn_success = connect(socket_fd, (struct sockaddr*)&address,
|
|
sizeof(struct sockaddr_un));
|
|
}
|
|
|
|
if (conn_success != 0) {
|
|
fprintf(stderr, "connect() failed\n");
|
|
return "";
|
|
}
|
|
|
|
VtsDriverControlCommandMessage cmd_msg;
|
|
|
|
cmd_msg.add_shell_command(command);
|
|
cmd_msg.set_command_type(EXECUTE_COMMAND);
|
|
|
|
if (!driverUtil.VtsSocketSendMessage(cmd_msg)) {
|
|
return NULL;
|
|
}
|
|
|
|
// read driver output
|
|
VtsDriverControlResponseMessage out_msg;
|
|
|
|
if (!driverUtil.VtsSocketRecvMessage(
|
|
static_cast<google::protobuf::Message*>(&out_msg))) {
|
|
return "";
|
|
}
|
|
|
|
// TODO(yuexima) use vector for output messages
|
|
stringstream ss;
|
|
for (int i = 0; i < out_msg.stdout_size(); i++) {
|
|
string out_str = out_msg.stdout(i);
|
|
cout << "[Shell driver] output for command " << i << ": " << out_str
|
|
<< endl;
|
|
ss << out_str;
|
|
}
|
|
close(socket_fd);
|
|
|
|
cout << "[Client] receiving output: " << ss.str() << endl;
|
|
return ss.str();
|
|
}
|
|
|
|
/*
|
|
* Prototype unit test helper. It first forks a vts_shell_driver process
|
|
* and then call a client function to execute a command.
|
|
*/
|
|
static string test_shell_command_output(const string& command,
|
|
const string& socket_address) {
|
|
pid_t p_driver;
|
|
string res_client;
|
|
|
|
VtsShellDriver shellDriver(socket_address.c_str());
|
|
|
|
p_driver = fork();
|
|
if (p_driver == 0) { // child
|
|
int res_driver = shellDriver.StartListen();
|
|
|
|
if (res_driver != 0) {
|
|
fprintf(stderr, "Driver reported error. The error code is: %d.\n",
|
|
res_driver);
|
|
exit(res_driver);
|
|
}
|
|
|
|
exit(0);
|
|
} else if (p_driver > 0) { // parent
|
|
res_client = vts_shell_driver_test_client_start(command, socket_address);
|
|
if (res_client.empty()) {
|
|
fprintf(stderr, "Client reported error.\n");
|
|
exit(1);
|
|
}
|
|
cout << "Client receiving: " << res_client << endl;
|
|
} else {
|
|
fprintf(stderr,
|
|
"shell_driver_test.cpp: create child process failed for driver.");
|
|
exit(-1);
|
|
}
|
|
|
|
// send kill signal to insure the process would not block
|
|
kill(p_driver, SIGKILL);
|
|
|
|
return res_client;
|
|
}
|
|
|
|
/*
|
|
* This test tests whether the output of "uname" is "Linux\n"
|
|
*/
|
|
TEST(vts_shell_driver_start, vts_shell_driver_unit_test_uname) {
|
|
string expected = "Linux\n";
|
|
string output =
|
|
test_shell_command_output("uname", "/data/local/tmp/test1_1.tmp");
|
|
ASSERT_EQ(output.compare(expected), 0);
|
|
}
|
|
|
|
/*
|
|
* This test tests whether the output of "which ls" is "/system/bin/ls\n"
|
|
*/
|
|
TEST(vts_shell_driver_start, vts_shell_driver_unit_test_which_ls) {
|
|
string expected = "/system/bin/ls\n";
|
|
string output =
|
|
test_shell_command_output("which ls", "/data/local/tmp/test1_2.tmp");
|
|
ASSERT_EQ(output.compare(expected), 0);
|
|
}
|
|
|
|
} // namespace vts
|
|
} // namespace android
|