1 /* 2 * Copyright (C) 2014 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 <errno.h> 18 #include <limits.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <unistd.h> 23 24 #include <cstring> 25 #include <string_view> 26 #include <vector> 27 28 #include <gtest/gtest.h> 29 #include <gtest_extras/IsolateMain.h> 30 31 #include "Color.h" 32 #include "Isolate.h" 33 34 namespace android { 35 namespace gtest_extras { 36 37 static void PrintHelpInfo() { 38 printf("Unit Test Options:\n"); 39 ColoredPrintf(COLOR_GREEN, " -j "); 40 ColoredPrintf(COLOR_YELLOW, "[JOB_COUNT]"); 41 printf(" or "); 42 ColoredPrintf(COLOR_GREEN, "-j"); 43 ColoredPrintf(COLOR_YELLOW, "[JOB_COUNT]\n"); 44 printf( 45 " Run up to JOB_COUNT tests in parallel.\n" 46 " Use isolation mode, Run each test in a separate process.\n" 47 " If JOB_COUNT is not given, it is set to the count of available processors.\n"); 48 ColoredPrintf(COLOR_GREEN, " --no_isolate\n"); 49 printf( 50 " Don't use isolation mode, run all tests in a single process.\n" 51 " If the test seems to be running in a debugger (based on the parent's name) this will\n" 52 " be automatically set. If this behavior is not desired use the '--force_isolate' flag\n" 53 " below.\n"); 54 ColoredPrintf(COLOR_GREEN, " --force_isolate\n"); 55 printf( 56 " Force the use of isolation mode, even if it looks like we are running in a\n" 57 " debugger.\n"); 58 ColoredPrintf(COLOR_GREEN, " --deadline_threshold_ms="); 59 ColoredPrintf(COLOR_YELLOW, "[TIME_IN_MS]\n"); 60 printf(" Run each test in no longer than "); 61 ColoredPrintf(COLOR_YELLOW, "[TIME_IN_MS]"); 62 printf( 63 " time.\n" 64 " Only valid in isolation mode. Default deadline is 90000 ms.\n"); 65 ColoredPrintf(COLOR_GREEN, " --slow_threshold_ms="); 66 ColoredPrintf(COLOR_YELLOW, "[TIME_IN_MS]\n"); 67 printf(" Test running longer than "); 68 ColoredPrintf(COLOR_YELLOW, "[TIME_IN_MS]"); 69 printf( 70 " will be called slow.\n" 71 " Only valid in isolation mode. Default slow threshold is 2000 ms.\n"); 72 printf( 73 "\nIn isolation mode, you can send SIGQUIT to the parent process to show the\n" 74 "current running tests, or send SIGINT to the parent process to stop all\n" 75 "running tests.\n" 76 "\n"); 77 } 78 79 static int GtestRun(std::vector<const char*>* args) { 80 int argc = args->size(); 81 args->push_back(nullptr); 82 ::testing::InitGoogleTest(&argc, const_cast<char**>(args->data())); 83 return RUN_ALL_TESTS(); 84 } 85 86 static bool RunInIsolationMode(std::vector<const char*>& args) { 87 // Parse arguments that can't be used in isolation mode. 88 bool isolation_forced = false; 89 for (size_t i = 1; i < args.size(); ++i) { 90 if (strcmp(args[i], "--no_isolate") == 0) { 91 return false; 92 } else if (strcmp(args[i], "--force_isolate") == 0) { 93 // We want to make sure we prioritize --no_isolate and --gtest_list_tests. 94 isolation_forced = true; 95 } else if (strcmp(args[i], "--gtest_list_tests") == 0) { 96 return false; 97 } 98 } 99 if (!isolation_forced) { 100 // Check if we are running gdb/gdbserver/lldb/lldb-server. No need to be sneaky we are assuming 101 // no one is hiding. 102 pid_t ppid = getppid(); 103 std::string exe_path = std::string("/proc/") + std::to_string(ppid) + "/exe"; 104 char buf[PATH_MAX + 1]; 105 size_t len; 106 // NB We can't use things like android::base::* or std::filesystem::* due to linking 107 // issues. 108 // Since PATH_MAX is the longest a symlink can be in posix we don't need to 109 // deal with truncation. Anyway this isn't critical for correctness and is 110 // just a QOL thing so it's fine if we are wrong. 111 if ((len = TEMP_FAILURE_RETRY(readlink(exe_path.c_str(), buf, sizeof(buf) - 1))) > 0) { 112 buf[len] = '\0'; 113 std::string_view file(basename(buf)); 114 return file != "gdb" && file != "gdbserver" && file != "gdbserver64" && 115 file != "gdbserver32" && file != "lldb" && file != "lldb-server"; 116 } 117 // If we can't figure out what our parent was just assume we are fine to isolate. 118 } 119 return true; 120 } 121 122 } // namespace gtest_extras 123 } // namespace android 124 125 // Tests that override this weak function can add default arguments. 126 extern "C" bool __attribute__((weak)) GetInitialArgs(const char***, size_t*); 127 128 int IsolateMain(int argc, char** argv, char**) { 129 std::vector<const char*> args{argv[0]}; 130 131 bool print_help = false; 132 size_t gtest_color_index = 0; 133 for (int i = 1; i < argc; ++i) { 134 args.push_back(argv[i]); 135 if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { 136 print_help = true; 137 } else if (strncmp(argv[i], "--gtest_color=", 14) == 0) { 138 gtest_color_index = args.size() - 1; 139 } 140 } 141 142 if (print_help) { 143 std::vector<const char*> help_args{args[0], "--help"}; 144 if (gtest_color_index != 0) { 145 // This is the only option that changes the way the help is printed. 146 help_args.push_back(args[gtest_color_index]); 147 ::testing::GTEST_FLAG(color) = args[gtest_color_index] + 14; 148 } 149 android::gtest_extras::PrintHelpInfo(); 150 return android::gtest_extras::GtestRun(&help_args); 151 } 152 153 if (!android::gtest_extras::RunInIsolationMode(args)) { 154 return android::gtest_extras::GtestRun(&args); 155 } 156 157 const char** start_args; 158 size_t num_args; 159 if (GetInitialArgs != nullptr && GetInitialArgs(&start_args, &num_args)) { 160 std::vector<const char*> initial_args; 161 for (size_t i = 0; i < num_args; i++) { 162 initial_args.push_back(start_args[i]); 163 } 164 args.insert(args.begin() + 1, initial_args.begin(), initial_args.end()); 165 } 166 167 std::vector<char*> child_args; 168 android::gtest_extras::Options options; 169 if (!options.Process(args, &child_args)) { 170 return 1; 171 } 172 173 // Add the --no_isolate option to force child processes not to rerun 174 // in isolation mode. 175 child_args.push_back(strdup("--no_isolate")); 176 177 // Set the flag values. 178 ::testing::GTEST_FLAG(color) = options.color(); 179 ::testing::GTEST_FLAG(print_time) = options.print_time(); 180 181 android::gtest_extras::Isolate isolate(options, child_args); 182 int return_val = isolate.Run(); 183 for (auto child_arg : child_args) { 184 free(child_arg); 185 } 186 return return_val; 187 } 188