• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <algorithm>
32 #include <iterator>
33 #include <sstream>
34 
35 namespace fastboot {
36 
37 namespace {
38 constexpr int rand_seed = 0;
39 std::default_random_engine rnd(rand_seed);
40 }  // namespace
41 
rand_legal()42 char rand_legal() {
43     return rnd() % 128;
44 }
45 
rand_illegal()46 char rand_illegal() {
47     return rand_legal() + 128;
48 }
49 
rand_char()50 char rand_char() {
51     return rnd() % 256;
52 }
53 
random_int(int start,int end)54 int random_int(int start, int end) {
55     std::uniform_int_distribution<int> uni(start, end);
56     return uni(rnd);
57 }
58 
RandomString(size_t length,std::function<char (void)> provider)59 std::string RandomString(size_t length, std::function<char(void)> provider) {
60     std::string str(length, 0);
61     std::generate_n(str.begin(), length, provider);
62     return str;
63 }
64 
RandomBuf(size_t length,std::function<char (void)> provider)65 std::vector<char> RandomBuf(size_t length, std::function<char(void)> provider) {
66     std::vector<char> ret;
67     ret.resize(length);
68     std::generate_n(ret.begin(), length, provider);
69     return ret;
70 }
71 
SplitBySpace(const std::string & s)72 std::vector<std::string> SplitBySpace(const std::string& s) {
73     std::istringstream iss(s);
74     return std::vector<std::string>{std::istream_iterator<std::string>{iss},
75                                     std::istream_iterator<std::string>{}};
76 }
77 
GeneratePartitionNames(const std::string & base,int num_slots)78 std::vector<std::string> GeneratePartitionNames(const std::string& base, int num_slots) {
79     if (!num_slots) {
80         return std::vector<std::string>{base};
81     }
82     std::vector<std::string> ret;
83     for (char c = 'a'; c < 'a' + num_slots; c++) {
84         ret.push_back(base + '_' + c);
85     }
86 
87     return ret;
88 }
89 
ParseArgs(int argc,char ** argv,std::string * err_msg)90 std::unordered_map<std::string, std::string> ParseArgs(int argc, char** argv,
91                                                        std::string* err_msg) {
92     // We ignore any gtest stuff
93     std::unordered_map<std::string, std::string> ret;
94 
95     for (int i = 1; i < argc - 1; i++) {
96         std::string arg(argv[i]);
97 
98         const std::string gtest_start("--gtest");
99         // We found a non gtest argument
100         if (!arg.find("-h") ||
101             (!arg.find("--") && arg.find("--gtest") && arg.find("=") != arg.npos)) {
102             const std::string start(arg.begin() + 2, arg.begin() + arg.find("="));
103             const std::string end(arg.begin() + arg.find("=") + 1, arg.end());
104             ret[start] = end;
105         } else if (arg.find("--gtest") != 0) {
106             *err_msg = android::base::StringPrintf("Illegal argument '%s'\n", arg.c_str());
107             return ret;
108         }
109     }
110 
111     return ret;
112 }
113 
ConfigureSerial(const std::string & port)114 int ConfigureSerial(const std::string& port) {
115     int fd = open(port.c_str(), O_RDONLY | O_NOCTTY | O_NONBLOCK);
116 
117     if (fd <= 0) {
118         return fd;
119     }
120 
121     struct termios tty;
122     tcgetattr(fd, &tty);
123 
124     cfsetospeed(&tty, (speed_t)B115200);
125     cfsetispeed(&tty, (speed_t)B115200);
126 
127     tty.c_cflag &= ~PARENB;
128     tty.c_cflag &= ~CSTOPB;
129     tty.c_cflag &= ~CSIZE;
130     tty.c_cflag |= CS8;
131 
132     tty.c_cflag &= ~CRTSCTS;
133     tty.c_cc[VMIN] = 0;
134     tty.c_cc[VTIME] = 2;
135     tty.c_cflag &= ~(ICANON | ECHO | ECHOE | ISIG);
136 
137     cfmakeraw(&tty);
138 
139     tcflush(fd, TCIFLUSH);
140     if (tcsetattr(fd, TCSANOW, &tty) != 0) {
141         return -1;
142     }
143 
144     return fd;
145 }
146 
StartProgram(const std::string program,const std::vector<std::string> args,int * rpipe)147 int StartProgram(const std::string program, const std::vector<std::string> args, int* rpipe) {
148     int link[2];
149     if (pipe(link) < 0) {
150         return -1;
151     }
152 
153     pid_t pid = fork();
154     if (pid < 0) {  // error
155         return -1;
156     }
157 
158     if (pid) {  // parent
159         close(link[1]);
160         *rpipe = link[0];
161         fcntl(*rpipe, F_SETFL, O_NONBLOCK);  // Non-blocking
162     } else {                                 // child
163         std::vector<const char*> argv(args.size() + 2, nullptr);
164         argv[0] = program.c_str();
165 
166         for (int i = 0; i < args.size(); i++) {
167             argv[i + 1] = args[i].c_str();
168         }
169 
170         // We pipe any stderr writes to the parent test process
171         dup2(link[1], STDERR_FILENO);  // close stdout and have it now be link[1]
172         // Close duplicates
173         close(link[0]);
174         close(link[1]);
175 
176         execvp(program.c_str(), const_cast<char* const*>(argv.data()));
177         fprintf(stderr, "Launching validator process '%s' failed with: %s\n", program.c_str(),
178                 strerror(errno));
179         exit(-1);
180     }
181 
182     return pid;
183 }
184 
WaitProgram(const int pid,const int pipe,std::string * error_msg)185 int WaitProgram(const int pid, const int pipe, std::string* error_msg) {
186     int status;
187     if (waitpid(pid, &status, 0) != pid) {
188         close(pipe);
189         return -1;
190     }
191     // Read from pipe
192     char buf[1024];
193     int n;
194     while ((n = read(pipe, buf, sizeof(buf))) > 0) {
195         buf[n] = 0; /* terminate the string */
196         error_msg->append(buf, n);
197     }
198     close(pipe);
199 
200     if (WIFEXITED(status)) {
201         // This WEXITSTATUS macro masks off lower bytes, with no sign extension
202         // casting it as a signed char fixes the sign extension issue
203         int retmask = WEXITSTATUS(status);
204         return reinterpret_cast<int8_t*>(&retmask)[0];
205     }
206 
207     return -1;
208 }
209 
210 }  // namespace fastboot
211