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 <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 
23 #include <vector>
24 
25 #include <gtest/gtest.h>
26 #include <gtest_extras/IsolateMain.h>
27 
28 #include "Color.h"
29 #include "Isolate.h"
30 
31 namespace android {
32 namespace gtest_extras {
33 
PrintHelpInfo()34 static void PrintHelpInfo() {
35   printf("Unit Test Options:\n");
36   ColoredPrintf(COLOR_GREEN, "  -j ");
37   ColoredPrintf(COLOR_YELLOW, "[JOB_COUNT]");
38   printf(" or ");
39   ColoredPrintf(COLOR_GREEN, "-j");
40   ColoredPrintf(COLOR_YELLOW, "[JOB_COUNT]\n");
41   printf(
42       "      Run up to JOB_COUNT tests in parallel.\n"
43       "      Use isolation mode, Run each test in a separate process.\n"
44       "      If JOB_COUNT is not given, it is set to the count of available processors.\n");
45   ColoredPrintf(COLOR_GREEN, "  --no_isolate\n");
46   printf("      Don't use isolation mode, run all tests in a single process.\n");
47   ColoredPrintf(COLOR_GREEN, "  --deadline_threshold_ms=");
48   ColoredPrintf(COLOR_YELLOW, "[TIME_IN_MS]\n");
49   printf("      Run each test in no longer than ");
50   ColoredPrintf(COLOR_YELLOW, "[TIME_IN_MS]");
51   printf(
52       " time.\n"
53       "      Only valid in isolation mode. Default deadline is 90000 ms.\n");
54   ColoredPrintf(COLOR_GREEN, "  --slow_threshold_ms=");
55   ColoredPrintf(COLOR_YELLOW, "[TIME_IN_MS]\n");
56   printf("      Test running longer than ");
57   ColoredPrintf(COLOR_YELLOW, "[TIME_IN_MS]");
58   printf(
59       " will be called slow.\n"
60       "      Only valid in isolation mode. Default slow threshold is 2000 ms.\n");
61   ColoredPrintf(COLOR_GREEN, "-j");
62   printf(
63       ".\n"
64       "In isolation mode, you can send SIGQUIT to the parent process to show the\n"
65       "current running tests, or send SIGINT to the parent process to stop all\n"
66       "running tests.\n"
67       "\n");
68 }
69 
GtestRun(std::vector<const char * > * args)70 static int GtestRun(std::vector<const char*>* args) {
71   int argc = args->size();
72   args->push_back(nullptr);
73   ::testing::InitGoogleTest(&argc, const_cast<char**>(args->data()));
74   return RUN_ALL_TESTS();
75 }
76 
RunInIsolationMode(std::vector<const char * > & args)77 static bool RunInIsolationMode(std::vector<const char*>& args) {
78   // Parse arguments that can't be used in isolation mode.
79   for (size_t i = 1; i < args.size(); ++i) {
80     if (strcmp(args[i], "--no_isolate") == 0) {
81       return false;
82     } else if (strcmp(args[i], "--gtest_list_tests") == 0) {
83       return false;
84     }
85   }
86   return true;
87 }
88 
89 }  // namespace gtest_extras
90 }  // namespace android
91 
92 // Tests that override this weak function can add default arguments.
93 extern "C" bool __attribute__((weak)) GetInitialArgs(const char***, size_t*);
94 
IsolateMain(int argc,char ** argv,char **)95 int IsolateMain(int argc, char** argv, char**) {
96   std::vector<const char*> args{argv[0]};
97 
98   bool print_help = false;
99   size_t gtest_color_index = 0;
100   for (int i = 1; i < argc; ++i) {
101     args.push_back(argv[i]);
102     if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
103       print_help = true;
104     } else if (strncmp(argv[i], "--gtest_color=", 14) == 0) {
105       gtest_color_index = args.size() - 1;
106     }
107   }
108 
109   if (print_help) {
110     std::vector<const char*> help_args{args[0], "--help"};
111     if (gtest_color_index != 0) {
112       // This is the only option that changes the way the help is printed.
113       help_args.push_back(args[gtest_color_index]);
114       ::testing::GTEST_FLAG(color) = args[gtest_color_index] + 14;
115     }
116     android::gtest_extras::PrintHelpInfo();
117     return android::gtest_extras::GtestRun(&help_args);
118   }
119 
120   if (!android::gtest_extras::RunInIsolationMode(args)) {
121     return android::gtest_extras::GtestRun(&args);
122   }
123 
124   const char** start_args;
125   size_t num_args;
126   if (GetInitialArgs != nullptr && GetInitialArgs(&start_args, &num_args)) {
127     std::vector<const char*> initial_args;
128     for (size_t i = 0; i < num_args; i++) {
129       initial_args.push_back(start_args[i]);
130     }
131     args.insert(args.begin() + 1, initial_args.begin(), initial_args.end());
132   }
133 
134   std::vector<char*> child_args;
135   android::gtest_extras::Options options;
136   if (!options.Process(args, &child_args)) {
137     return 1;
138   }
139 
140   // Add the --no_isolate option to force child processes not to rerun
141   // in isolation mode.
142   child_args.push_back(strdup("--no_isolate"));
143 
144   // Set the flag values.
145   ::testing::GTEST_FLAG(color) = options.color();
146   ::testing::GTEST_FLAG(print_time) = options.print_time();
147 
148   android::gtest_extras::Isolate isolate(options, child_args);
149   int return_val = isolate.Run();
150   for (auto child_arg : child_args) {
151     free(child_arg);
152   }
153   return return_val;
154 }
155