Home | History | Annotate | Download | only in shell
      1 /*
      2  * Copyright 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "ShellDriverTest.h"
     18 
     19 #include <errno.h>
     20 #include <gtest/gtest.h>
     21 #include <limits.h>
     22 #include <math.h>
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <string.h>
     26 #include <sys/socket.h>
     27 #include <sys/un.h>
     28 #include <unistd.h>
     29 
     30 #include <iostream>
     31 #include <sstream>
     32 
     33 #include <VtsDriverCommUtil.h>
     34 #include "test/vts/proto/VtsDriverControlMessage.pb.h"
     35 
     36 #include "ShellDriver.h"
     37 
     38 using namespace std;
     39 
     40 namespace android {
     41 namespace vts {
     42 
     43 static int kMaxRetry = 3;
     44 
     45 /*
     46  * send a command to the driver on specified UNIX domain socket and print out
     47  * the outputs from driver.
     48  */
     49 static string vts_shell_driver_test_client_start(const string& command,
     50                                                  const string& socket_address) {
     51   struct sockaddr_un address;
     52   int socket_fd;
     53 
     54   socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
     55   if (socket_fd < 0) {
     56     fprintf(stderr, "socket() failed\n");
     57     return "";
     58   }
     59 
     60   VtsDriverCommUtil driverUtil(socket_fd);
     61 
     62   memset(&address, 0, sizeof(struct sockaddr_un));
     63 
     64   address.sun_family = AF_UNIX;
     65   strncpy(address.sun_path, socket_address.c_str(),
     66           sizeof(address.sun_path) - 1);
     67 
     68   int conn_success;
     69   int retry_count = 0;
     70 
     71   conn_success = connect(socket_fd, (struct sockaddr*)&address,
     72                          sizeof(struct sockaddr_un));
     73   for (retry_count = 0; retry_count < kMaxRetry && conn_success != 0;
     74        retry_count++) {  // retry if server not ready
     75     printf("Client: connection failed, retrying...\n");
     76     retry_count++;
     77     if (usleep(50 * pow(retry_count, 3)) != 0) {
     78       fprintf(stderr, "shell driver unit test: sleep intrupted.");
     79     }
     80 
     81     conn_success = connect(socket_fd, (struct sockaddr*)&address,
     82                            sizeof(struct sockaddr_un));
     83   }
     84 
     85   if (conn_success != 0) {
     86     fprintf(stderr, "connect() failed\n");
     87     return "";
     88   }
     89 
     90   VtsDriverControlCommandMessage cmd_msg;
     91 
     92   cmd_msg.add_shell_command(command);
     93   cmd_msg.set_command_type(EXECUTE_COMMAND);
     94 
     95   if (!driverUtil.VtsSocketSendMessage(cmd_msg)) {
     96     return NULL;
     97   }
     98 
     99   // read driver output
    100   VtsDriverControlResponseMessage out_msg;
    101 
    102   if (!driverUtil.VtsSocketRecvMessage(
    103           static_cast<google::protobuf::Message*>(&out_msg))) {
    104     return "";
    105   }
    106 
    107   // TODO(yuexima) use vector for output messages
    108   stringstream ss;
    109   for (int i = 0; i < out_msg.stdout_size(); i++) {
    110     string out_str = out_msg.stdout(i);
    111     cout << "[Shell driver] output for command " << i << ": " << out_str
    112          << endl;
    113     ss << out_str;
    114   }
    115   close(socket_fd);
    116 
    117   cout << "[Client] receiving output: " << ss.str() << endl;
    118   return ss.str();
    119 }
    120 
    121 /*
    122  * Prototype unit test helper. It first forks a vts_shell_driver process
    123  * and then call a client function to execute a command.
    124  */
    125 static string test_shell_command_output(const string& command,
    126                                         const string& socket_address) {
    127   pid_t p_driver;
    128   string res_client;
    129 
    130   VtsShellDriver shellDriver(socket_address.c_str());
    131 
    132   p_driver = fork();
    133   if (p_driver == 0) {  // child
    134     int res_driver = shellDriver.StartListen();
    135 
    136     if (res_driver != 0) {
    137       fprintf(stderr, "Driver reported error. The error code is: %d.\n",
    138               res_driver);
    139       exit(res_driver);
    140     }
    141 
    142     exit(0);
    143   } else if (p_driver > 0) {  // parent
    144     res_client = vts_shell_driver_test_client_start(command, socket_address);
    145     if (res_client.empty()) {
    146       fprintf(stderr, "Client reported error.\n");
    147       exit(1);
    148     }
    149     cout << "Client receiving: " << res_client << endl;
    150   } else {
    151     fprintf(stderr,
    152             "shell_driver_test.cpp: create child process failed for driver.");
    153     exit(-1);
    154   }
    155 
    156   // send kill signal to insure the process would not block
    157   kill(p_driver, SIGKILL);
    158 
    159   return res_client;
    160 }
    161 
    162 /*
    163  * This test tests whether the output of "uname" is "Linux\n"
    164  */
    165 TEST(vts_shell_driver_start, vts_shell_driver_unit_test_uname) {
    166   string expected = "Linux\n";
    167   string output =
    168       test_shell_command_output("uname", "/data/local/tmp/test1_1.tmp");
    169   ASSERT_EQ(output.compare(expected), 0);
    170 }
    171 
    172 /*
    173  * This test tests whether the output of "which ls" is "/system/bin/ls\n"
    174  */
    175 TEST(vts_shell_driver_start, vts_shell_driver_unit_test_which_ls) {
    176   string expected = "/system/bin/ls\n";
    177   string output =
    178       test_shell_command_output("which ls", "/data/local/tmp/test1_2.tmp");
    179   ASSERT_EQ(output.compare(expected), 0);
    180 }
    181 
    182 }  // namespace vts
    183 }  // namespace android
    184