| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
| * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
| * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| */ |
| #include "test_utils.h" |
| #include <fcntl.h> |
| #include <termios.h> |
| #include <sstream> |
| |
| namespace fastboot { |
| |
| namespace { |
| constexpr int rand_seed = 0; |
| std::default_random_engine rnd(rand_seed); |
| } // namespace |
| |
| char rand_legal() { |
| return rnd() % 128; |
| } |
| |
| char rand_illegal() { |
| return rand_legal() + 128; |
| } |
| |
| char rand_char() { |
| return rnd() % 256; |
| } |
| |
| int random_int(int start, int end) { |
| std::uniform_int_distribution<int> uni(start, end); |
| return uni(rnd); |
| } |
| |
| std::string RandomString(size_t length, std::function<char(void)> provider) { |
| std::string str(length, 0); |
| std::generate_n(str.begin(), length, provider); |
| return str; |
| } |
| |
| std::vector<char> RandomBuf(size_t length, std::function<char(void)> provider) { |
| std::vector<char> ret; |
| ret.resize(length); |
| std::generate_n(ret.begin(), length, provider); |
| return ret; |
| } |
| |
| std::vector<std::string> SplitBySpace(const std::string& s) { |
| std::istringstream iss(s); |
| return std::vector<std::string>{std::istream_iterator<std::string>{iss}, |
| std::istream_iterator<std::string>{}}; |
| } |
| |
| std::vector<std::string> GeneratePartitionNames(const std::string& base, int num_slots) { |
| if (!num_slots) { |
| return std::vector<std::string>{base}; |
| } |
| std::vector<std::string> ret; |
| for (char c = 'a'; c < 'a' + num_slots; c++) { |
| ret.push_back(base + '_' + c); |
| } |
| |
| return ret; |
| } |
| |
| std::unordered_map<std::string, std::string> ParseArgs(int argc, char** argv, |
| std::string* err_msg) { |
| // We ignore any gtest stuff |
| std::unordered_map<std::string, std::string> ret; |
| |
| for (int i = 1; i < argc - 1; i++) { |
| std::string arg(argv[i]); |
| |
| const std::string gtest_start("--gtest"); |
| // We found a non gtest argument |
| if (!arg.find("-h") || |
| (!arg.find("--") && arg.find("--gtest") && arg.find("=") != arg.npos)) { |
| const std::string start(arg.begin() + 2, arg.begin() + arg.find("=")); |
| const std::string end(arg.begin() + arg.find("=") + 1, arg.end()); |
| ret[start] = end; |
| } else if (arg.find("--gtest") != 0) { |
| *err_msg = android::base::StringPrintf("Illegal argument '%s'\n", arg.c_str()); |
| return ret; |
| } |
| } |
| |
| return ret; |
| } |
| |
| int ConfigureSerial(const std::string& port) { |
| int fd = open(port.c_str(), O_RDONLY | O_NOCTTY | O_NONBLOCK); |
| |
| if (fd <= 0) { |
| return fd; |
| } |
| |
| struct termios tty; |
| tcgetattr(fd, &tty); |
| |
| cfsetospeed(&tty, (speed_t)B115200); |
| cfsetispeed(&tty, (speed_t)B115200); |
| |
| tty.c_cflag &= ~PARENB; |
| tty.c_cflag &= ~CSTOPB; |
| tty.c_cflag &= ~CSIZE; |
| tty.c_cflag |= CS8; |
| |
| tty.c_cflag &= ~CRTSCTS; |
| tty.c_cc[VMIN] = 0; |
| tty.c_cc[VTIME] = 2; |
| tty.c_cflag &= ~(ICANON | ECHO | ECHOE | ISIG); |
| |
| cfmakeraw(&tty); |
| |
| tcflush(fd, TCIFLUSH); |
| if (tcsetattr(fd, TCSANOW, &tty) != 0) { |
| return -1; |
| } |
| |
| return fd; |
| } |
| |
| int StartProgram(const std::string program, const std::vector<std::string> args, int* rpipe) { |
| int link[2]; |
| if (pipe(link) < 0) { |
| return -1; |
| } |
| |
| pid_t pid = fork(); |
| if (pid < 0) { // error |
| return -1; |
| } |
| |
| if (pid) { // parent |
| close(link[1]); |
| *rpipe = link[0]; |
| fcntl(*rpipe, F_SETFL, O_NONBLOCK); // Non-blocking |
| } else { // child |
| std::vector<const char*> argv(args.size() + 2, nullptr); |
| argv[0] = program.c_str(); |
| |
| for (int i = 0; i < args.size(); i++) { |
| argv[i + 1] = args[i].c_str(); |
| } |
| |
| // We pipe any stderr writes to the parent test process |
| dup2(link[1], STDERR_FILENO); // close stdout and have it now be link[1] |
| // Close duplicates |
| close(link[0]); |
| close(link[1]); |
| |
| execvp(program.c_str(), const_cast<char* const*>(argv.data())); |
| fprintf(stderr, "Launching validator process '%s' failed with: %s\n", program.c_str(), |
| strerror(errno)); |
| exit(-1); |
| } |
| |
| return pid; |
| } |
| |
| int WaitProgram(const int pid, const int pipe, std::string* error_msg) { |
| int status; |
| if (waitpid(pid, &status, 0) != pid) { |
| close(pipe); |
| return -1; |
| } |
| // Read from pipe |
| char buf[1024]; |
| int n; |
| while ((n = read(pipe, buf, sizeof(buf))) > 0) { |
| buf[n] = 0; /* terminate the string */ |
| error_msg->append(buf, n); |
| } |
| close(pipe); |
| |
| if (WIFEXITED(status)) { |
| // This WEXITSTATUS macro masks off lower bytes, with no sign extension |
| // casting it as a signed char fixes the sign extension issue |
| int retmask = WEXITSTATUS(status); |
| return reinterpret_cast<int8_t*>(&retmask)[0]; |
| } |
| |
| return -1; |
| } |
| |
| } // namespace fastboot |