1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28 #include "test_utils.h"
29 #include <fcntl.h>
30 #include <termios.h>
31 #include <sstream>
32
33 namespace fastboot {
34
35 namespace {
36 constexpr int rand_seed = 0;
37 std::default_random_engine rnd(rand_seed);
38 } // namespace
39
rand_legal()40 char rand_legal() {
41 return rnd() % 128;
42 }
43
rand_illegal()44 char rand_illegal() {
45 return rand_legal() + 128;
46 }
47
rand_char()48 char rand_char() {
49 return rnd() % 256;
50 }
51
random_int(int start,int end)52 int random_int(int start, int end) {
53 std::uniform_int_distribution<int> uni(start, end);
54 return uni(rnd);
55 }
56
RandomString(size_t length,std::function<char (void)> provider)57 std::string RandomString(size_t length, std::function<char(void)> provider) {
58 std::string str(length, 0);
59 std::generate_n(str.begin(), length, provider);
60 return str;
61 }
62
RandomBuf(size_t length,std::function<char (void)> provider)63 std::vector<char> RandomBuf(size_t length, std::function<char(void)> provider) {
64 std::vector<char> ret;
65 ret.resize(length);
66 std::generate_n(ret.begin(), length, provider);
67 return ret;
68 }
69
SplitBySpace(const std::string & s)70 std::vector<std::string> SplitBySpace(const std::string& s) {
71 std::istringstream iss(s);
72 return std::vector<std::string>{std::istream_iterator<std::string>{iss},
73 std::istream_iterator<std::string>{}};
74 }
75
GeneratePartitionNames(const std::string & base,int num_slots)76 std::vector<std::string> GeneratePartitionNames(const std::string& base, int num_slots) {
77 if (!num_slots) {
78 return std::vector<std::string>{base};
79 }
80 std::vector<std::string> ret;
81 for (char c = 'a'; c < 'a' + num_slots; c++) {
82 ret.push_back(base + '_' + c);
83 }
84
85 return ret;
86 }
87
ParseArgs(int argc,char ** argv,std::string * err_msg)88 std::unordered_map<std::string, std::string> ParseArgs(int argc, char** argv,
89 std::string* err_msg) {
90 // We ignore any gtest stuff
91 std::unordered_map<std::string, std::string> ret;
92
93 for (int i = 1; i < argc - 1; i++) {
94 std::string arg(argv[i]);
95
96 const std::string gtest_start("--gtest");
97 // We found a non gtest argument
98 if (!arg.find("-h") ||
99 (!arg.find("--") && arg.find("--gtest") && arg.find("=") != arg.npos)) {
100 const std::string start(arg.begin() + 2, arg.begin() + arg.find("="));
101 const std::string end(arg.begin() + arg.find("=") + 1, arg.end());
102 ret[start] = end;
103 } else if (arg.find("--gtest") != 0) {
104 *err_msg = android::base::StringPrintf("Illegal argument '%s'\n", arg.c_str());
105 return ret;
106 }
107 }
108
109 return ret;
110 }
111
ConfigureSerial(const std::string & port)112 int ConfigureSerial(const std::string& port) {
113 int fd = open(port.c_str(), O_RDONLY | O_NOCTTY | O_NONBLOCK);
114
115 if (fd <= 0) {
116 return fd;
117 }
118
119 struct termios tty;
120 tcgetattr(fd, &tty);
121
122 cfsetospeed(&tty, (speed_t)B115200);
123 cfsetispeed(&tty, (speed_t)B115200);
124
125 tty.c_cflag &= ~PARENB;
126 tty.c_cflag &= ~CSTOPB;
127 tty.c_cflag &= ~CSIZE;
128 tty.c_cflag |= CS8;
129
130 tty.c_cflag &= ~CRTSCTS;
131 tty.c_cc[VMIN] = 0;
132 tty.c_cc[VTIME] = 2;
133 tty.c_cflag &= ~(ICANON | ECHO | ECHOE | ISIG);
134
135 cfmakeraw(&tty);
136
137 tcflush(fd, TCIFLUSH);
138 if (tcsetattr(fd, TCSANOW, &tty) != 0) {
139 return -1;
140 }
141
142 return fd;
143 }
144
StartProgram(const std::string program,const std::vector<std::string> args,int * rpipe)145 int StartProgram(const std::string program, const std::vector<std::string> args, int* rpipe) {
146 int link[2];
147 if (pipe(link) < 0) {
148 return -1;
149 }
150
151 pid_t pid = fork();
152 if (pid < 0) { // error
153 return -1;
154 }
155
156 if (pid) { // parent
157 close(link[1]);
158 *rpipe = link[0];
159 fcntl(*rpipe, F_SETFL, O_NONBLOCK); // Non-blocking
160 } else { // child
161 std::vector<const char*> argv(args.size() + 2, nullptr);
162 argv[0] = program.c_str();
163
164 for (int i = 0; i < args.size(); i++) {
165 argv[i + 1] = args[i].c_str();
166 }
167
168 // We pipe any stderr writes to the parent test process
169 dup2(link[1], STDERR_FILENO); // close stdout and have it now be link[1]
170 // Close duplicates
171 close(link[0]);
172 close(link[1]);
173
174 execvp(program.c_str(), const_cast<char* const*>(argv.data()));
175 fprintf(stderr, "Launching validator process '%s' failed with: %s\n", program.c_str(),
176 strerror(errno));
177 exit(-1);
178 }
179
180 return pid;
181 }
182
WaitProgram(const int pid,const int pipe,std::string * error_msg)183 int WaitProgram(const int pid, const int pipe, std::string* error_msg) {
184 int status;
185 if (waitpid(pid, &status, 0) != pid) {
186 close(pipe);
187 return -1;
188 }
189 // Read from pipe
190 char buf[1024];
191 int n;
192 while ((n = read(pipe, buf, sizeof(buf))) > 0) {
193 buf[n] = 0; /* terminate the string */
194 error_msg->append(buf, n);
195 }
196 close(pipe);
197
198 if (WIFEXITED(status)) {
199 // This WEXITSTATUS macro masks off lower bytes, with no sign extension
200 // casting it as a signed char fixes the sign extension issue
201 int retmask = WEXITSTATUS(status);
202 return reinterpret_cast<int8_t*>(&retmask)[0];
203 }
204
205 return -1;
206 }
207
208 } // namespace fastboot
209