| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <getopt.h> |
| #include <lib/fit/defer.h> |
| |
| #include <ctime> |
| |
| #include <fbl/function.h> |
| #include <fbl/string_printf.h> |
| #include <zxtest/base/log-sink.h> |
| #include <zxtest/base/runner.h> |
| |
| namespace zxtest { |
| |
| namespace { |
| using Options = Runner::Options; |
| |
| bool GetBoolFlag(const char* arg) { |
| return arg == nullptr || strlen(arg) == 0 || strcmp("true", arg) == 0; |
| } |
| |
| // getopt_long ignores -f value and --flag value opt args, and requires either = or -fvalue for |
| // optional arguments. This will return an opt arg if available. |
| char* GetOptArg(int opt, int argc, char** argv) { |
| // We might need to check we ar enot skipping any argument. |
| int index = opt; |
| |
| if (index >= argc) { |
| return nullptr; |
| } |
| |
| if (argv[index] == nullptr) { |
| return nullptr; |
| } |
| |
| if (argv[index][0] == '\0') { |
| return nullptr; |
| } |
| |
| if (argv[index][0] == '-') { |
| return nullptr; |
| } |
| |
| return argv[index]; |
| } |
| |
| constexpr char kUsageMsg[] = R"( |
| [OPTIONS] |
| --help[-h] Prints this message. |
| --gtest_filter[-f] PATTERN Runner will consider only registered |
| tests that match PATTERN. |
| --gtest_list_tests[-l] BOOL Runner will list all registered tests |
| that would be executed. |
| --gtest_shuffle[-s] BOOL Runner will shuffle test and test case |
| execution order. |
| --gtest_repeat[-i] REPEAT Runner will run REPEAT iterations of |
| each test case. If -1 will run until killed. |
| --gtest_random_seed[-r] SEED Runner will use SEED for random decisions. |
| --gtest_break_on_failure[-b] BOOL Runner will break upon encountering the first |
| fatal failure. |
| --gtest_also_run_disabled_tests[-a] BOOL Runner will include test and testcases prefixed with |
| 'DISABLED_' for execution and listing. |
| )"; |
| |
| } // namespace |
| |
| void Options::Usage(char* bin, LogSink* sink) { |
| sink->Write(" Usage: %s [OPTIONS]\n", bin); |
| sink->Write(kUsageMsg); |
| } |
| |
| Options Options::FromArgs(int argc, char** argv, fbl::Vector<fbl::String>* errors) { |
| // Reset index of parsed arguments. |
| optind = 0; |
| static const struct option opts[] = { |
| {"help", optional_argument, nullptr, 'h'}, |
| {"gtest_filter", optional_argument, nullptr, 'f'}, |
| {"gtest_list_tests", optional_argument, nullptr, 'l'}, |
| {"gtest_shuffle", optional_argument, nullptr, 's'}, |
| {"gtest_also_run_disabled_tests", optional_argument, nullptr, 'a'}, |
| {"gtest_repeat", required_argument, nullptr, 'i'}, |
| {"gtest_random_seed", required_argument, nullptr, 'r'}, |
| {"gtest_break_on_failure", optional_argument, nullptr, 'b'}, |
| {0, 0, 0, 0}, |
| }; |
| Runner::Options options; |
| |
| auto reset = fit::defer([]() { optind = 0; }); |
| |
| int c = -1; |
| int option_index = -1; |
| char* val = nullptr; |
| |
| // Pick a random seed by default. Overwrite it if a value was explicitly set. |
| options.seed = static_cast<int>(time(nullptr)); |
| |
| while ((c = getopt_long(argc, argv, "f::l::b::s::a::i:r:h::", opts, &option_index)) >= 0) { |
| val = optarg; |
| if (val == nullptr) { |
| // Verifies that the flag value could be in the form -f value not just -fValue. |
| val = GetOptArg(optind, argc, argv); |
| if (val != nullptr) { |
| ++optind; |
| } |
| } |
| |
| switch (c) { |
| case 'h': |
| options.help = GetBoolFlag(val); |
| return options; |
| case 'f': |
| // -f with no args resets the filter. |
| options.filter = (val == nullptr ? "" : val); |
| break; |
| case 'l': |
| options.list = GetBoolFlag(val); |
| break; |
| case 's': |
| options.shuffle = GetBoolFlag(val); |
| break; |
| case 'i': { |
| int iters = atoi(val); |
| if (iters < -1 || iters == 0) { |
| options.help = true; |
| errors->push_back(fbl::StringPrintf( |
| "--gtest_repeat(-i) must take a positive value or -1. (value was %d)", iters)); |
| return options; |
| } |
| options.repeat = iters; |
| break; |
| } |
| case 'r': |
| options.seed = atoi(val); |
| break; |
| case 'b': |
| options.break_on_failure = GetBoolFlag(val); |
| break; |
| case 'a': |
| options.run_disabled = GetBoolFlag(val); |
| break; |
| } |
| } |
| |
| return options; |
| } |
| } // namespace zxtest |