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