Add support for --gtest_flagfile
This commit is contained in:
parent
0928adbfea
commit
195610d30c
|
@ -587,6 +587,11 @@ inline std::string GetPrefixUntilComma(const char* str) {
|
|||
return comma == NULL ? str : std::string(str, comma);
|
||||
}
|
||||
|
||||
// Splits a given string on a given delimiter, populating a given
|
||||
// vector with the fields.
|
||||
void SplitString(const ::std::string& str, char delimiter,
|
||||
::std::vector< ::std::string>* dest);
|
||||
|
||||
// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
|
||||
// registers a list of type-parameterized tests with Google Test. The
|
||||
// return value is insignificant - we just need to return something
|
||||
|
|
|
@ -1403,6 +1403,14 @@ GTEST_API_ std::string GetCapturedStderr();
|
|||
|
||||
#endif // GTEST_HAS_STREAM_REDIRECTION
|
||||
|
||||
// Returns a path to temporary directory.
|
||||
GTEST_API_ std::string TempDir();
|
||||
|
||||
// Returns the size (in bytes) of a file.
|
||||
GTEST_API_ size_t GetFileSize(FILE* file);
|
||||
|
||||
// Reads the entire content of a file as a string.
|
||||
GTEST_API_ std::string ReadEntireFile(FILE* file);
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
|
|
|
@ -1204,26 +1204,6 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Splits a given string on a given delimiter, populating a given
|
||||
// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have
|
||||
// ::std::string, so we can use it here.
|
||||
static void SplitString(const ::std::string& str, char delimiter,
|
||||
::std::vector< ::std::string>* dest) {
|
||||
::std::vector< ::std::string> parsed;
|
||||
::std::string::size_type pos = 0;
|
||||
while (::testing::internal::AlwaysTrue()) {
|
||||
const ::std::string::size_type colon = str.find(delimiter, pos);
|
||||
if (colon == ::std::string::npos) {
|
||||
parsed.push_back(str.substr(pos));
|
||||
break;
|
||||
} else {
|
||||
parsed.push_back(str.substr(pos, colon - pos));
|
||||
pos = colon + 1;
|
||||
}
|
||||
}
|
||||
dest->swap(parsed);
|
||||
}
|
||||
|
||||
# if GTEST_OS_WINDOWS
|
||||
// Recreates the pipe and event handles from the provided parameters,
|
||||
// signals the event, and returns a file descriptor wrapped around the pipe
|
||||
|
|
|
@ -100,6 +100,7 @@ const char kShuffleFlag[] = "shuffle";
|
|||
const char kStackTraceDepthFlag[] = "stack_trace_depth";
|
||||
const char kStreamResultToFlag[] = "stream_result_to";
|
||||
const char kThrowOnFailureFlag[] = "throw_on_failure";
|
||||
const char kFlagfileFlag[] = "flagfile";
|
||||
|
||||
// A valid random seed must be in [1, kMaxRandomSeed].
|
||||
const int kMaxRandomSeed = 99999;
|
||||
|
|
|
@ -962,12 +962,6 @@ class CapturedStream {
|
|||
}
|
||||
|
||||
private:
|
||||
// Reads the entire content of a file as an std::string.
|
||||
static std::string ReadEntireFile(FILE* file);
|
||||
|
||||
// Returns the size (in bytes) of a file.
|
||||
static size_t GetFileSize(FILE* file);
|
||||
|
||||
const int fd_; // A stream to capture.
|
||||
int uncaptured_fd_;
|
||||
// Name of the temporary file holding the stderr output.
|
||||
|
@ -976,35 +970,6 @@ class CapturedStream {
|
|||
GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
|
||||
};
|
||||
|
||||
// Returns the size (in bytes) of a file.
|
||||
size_t CapturedStream::GetFileSize(FILE* file) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
return static_cast<size_t>(ftell(file));
|
||||
}
|
||||
|
||||
// Reads the entire content of a file as a string.
|
||||
std::string CapturedStream::ReadEntireFile(FILE* file) {
|
||||
const size_t file_size = GetFileSize(file);
|
||||
char* const buffer = new char[file_size];
|
||||
|
||||
size_t bytes_last_read = 0; // # of bytes read in the last fread()
|
||||
size_t bytes_read = 0; // # of bytes read so far
|
||||
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
// Keeps reading the file until we cannot read further or the
|
||||
// pre-determined file size is reached.
|
||||
do {
|
||||
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
|
||||
bytes_read += bytes_last_read;
|
||||
} while (bytes_last_read > 0 && bytes_read < file_size);
|
||||
|
||||
const std::string content(buffer, bytes_read);
|
||||
delete[] buffer;
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
|
||||
static CapturedStream* g_captured_stderr = NULL;
|
||||
|
@ -1051,6 +1016,51 @@ std::string GetCapturedStderr() {
|
|||
|
||||
#endif // GTEST_HAS_STREAM_REDIRECTION
|
||||
|
||||
std::string TempDir() {
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
return "\\temp\\";
|
||||
#elif GTEST_OS_WINDOWS
|
||||
const char* temp_dir = posix::GetEnv("TEMP");
|
||||
if (temp_dir == NULL || temp_dir[0] == '\0')
|
||||
return "\\temp\\";
|
||||
else if (temp_dir[strlen(temp_dir) - 1] == '\\')
|
||||
return temp_dir;
|
||||
else
|
||||
return std::string(temp_dir) + "\\";
|
||||
#elif GTEST_OS_LINUX_ANDROID
|
||||
return "/sdcard/";
|
||||
#else
|
||||
return "/tmp/";
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
|
||||
size_t GetFileSize(FILE* file) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
return static_cast<size_t>(ftell(file));
|
||||
}
|
||||
|
||||
std::string ReadEntireFile(FILE* file) {
|
||||
const size_t file_size = GetFileSize(file);
|
||||
char* const buffer = new char[file_size];
|
||||
|
||||
size_t bytes_last_read = 0; // # of bytes read in the last fread()
|
||||
size_t bytes_read = 0; // # of bytes read so far
|
||||
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
// Keeps reading the file until we cannot read further or the
|
||||
// pre-determined file size is reached.
|
||||
do {
|
||||
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
|
||||
bytes_read += bytes_last_read;
|
||||
} while (bytes_last_read > 0 && bytes_read < file_size);
|
||||
|
||||
const std::string content(buffer, bytes_read);
|
||||
delete[] buffer;
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
// A copy of all command line arguments. Set by InitGoogleTest().
|
||||
|
|
123
src/gtest.cc
123
src/gtest.cc
|
@ -295,6 +295,11 @@ GTEST_DEFINE_bool_(
|
|||
"if exceptions are enabled or exit the program with a non-zero code "
|
||||
"otherwise.");
|
||||
|
||||
GTEST_DEFINE_string_(
|
||||
flagfile,
|
||||
internal::StringFromGTestEnv("flagfile", ""),
|
||||
"This flag specifies the flagfile to read command-line flags from.");
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Generates a random number from [0, range), using a Linear
|
||||
|
@ -905,6 +910,23 @@ static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
|
|||
|
||||
#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
|
||||
|
||||
void SplitString(const ::std::string& str, char delimiter,
|
||||
::std::vector< ::std::string>* dest) {
|
||||
::std::vector< ::std::string> parsed;
|
||||
::std::string::size_type pos = 0;
|
||||
while (::testing::internal::AlwaysTrue()) {
|
||||
const ::std::string::size_type colon = str.find(delimiter, pos);
|
||||
if (colon == ::std::string::npos) {
|
||||
parsed.push_back(str.substr(pos));
|
||||
break;
|
||||
} else {
|
||||
parsed.push_back(str.substr(pos, colon - pos));
|
||||
pos = colon + 1;
|
||||
}
|
||||
}
|
||||
dest->swap(parsed);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Constructs an empty Message.
|
||||
|
@ -5178,6 +5200,56 @@ static const char kColorEncodedHelpMessage[] =
|
|||
"(not one in your own code or tests), please report it to\n"
|
||||
"@G<" GTEST_DEV_EMAIL_ ">@D.\n";
|
||||
|
||||
bool ParseGoogleTestFlag(const char* const arg) {
|
||||
return ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
|
||||
>EST_FLAG(also_run_disabled_tests)) ||
|
||||
ParseBoolFlag(arg, kBreakOnFailureFlag,
|
||||
>EST_FLAG(break_on_failure)) ||
|
||||
ParseBoolFlag(arg, kCatchExceptionsFlag,
|
||||
>EST_FLAG(catch_exceptions)) ||
|
||||
ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) ||
|
||||
ParseStringFlag(arg, kDeathTestStyleFlag,
|
||||
>EST_FLAG(death_test_style)) ||
|
||||
ParseBoolFlag(arg, kDeathTestUseFork,
|
||||
>EST_FLAG(death_test_use_fork)) ||
|
||||
ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) ||
|
||||
ParseStringFlag(arg, kInternalRunDeathTestFlag,
|
||||
>EST_FLAG(internal_run_death_test)) ||
|
||||
ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) ||
|
||||
ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) ||
|
||||
ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) ||
|
||||
ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) ||
|
||||
ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) ||
|
||||
ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) ||
|
||||
ParseInt32Flag(arg, kStackTraceDepthFlag,
|
||||
>EST_FLAG(stack_trace_depth)) ||
|
||||
ParseStringFlag(arg, kStreamResultToFlag,
|
||||
>EST_FLAG(stream_result_to)) ||
|
||||
ParseBoolFlag(arg, kThrowOnFailureFlag,
|
||||
>EST_FLAG(throw_on_failure));
|
||||
}
|
||||
|
||||
void LoadFlagsFromFile(const std::string& path) {
|
||||
FILE* flagfile = posix::FOpen(path.c_str(), "r");
|
||||
if (!flagfile) {
|
||||
fprintf(stderr,
|
||||
"Unable to open file \"%s\"\n",
|
||||
GTEST_FLAG(flagfile).c_str());
|
||||
fflush(stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
std::string contents(ReadEntireFile(flagfile));
|
||||
posix::FClose(flagfile);
|
||||
std::vector<std::string> lines;
|
||||
SplitString(contents, '\n', &lines);
|
||||
for (size_t i = 0; i < lines.size(); ++i) {
|
||||
if (lines[i].empty())
|
||||
continue;
|
||||
if (!ParseGoogleTestFlag(lines[i].c_str()))
|
||||
g_help_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Parses the command line for Google Test flags, without initializing
|
||||
// other parts of Google Test. The type parameter CharType can be
|
||||
// instantiated to either char or wchar_t.
|
||||
|
@ -5191,35 +5263,22 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
|
|||
using internal::ParseInt32Flag;
|
||||
using internal::ParseStringFlag;
|
||||
|
||||
// Do we see a Google Test flag?
|
||||
if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
|
||||
>EST_FLAG(also_run_disabled_tests)) ||
|
||||
ParseBoolFlag(arg, kBreakOnFailureFlag,
|
||||
>EST_FLAG(break_on_failure)) ||
|
||||
ParseBoolFlag(arg, kCatchExceptionsFlag,
|
||||
>EST_FLAG(catch_exceptions)) ||
|
||||
ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) ||
|
||||
ParseStringFlag(arg, kDeathTestStyleFlag,
|
||||
>EST_FLAG(death_test_style)) ||
|
||||
ParseBoolFlag(arg, kDeathTestUseFork,
|
||||
>EST_FLAG(death_test_use_fork)) ||
|
||||
ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) ||
|
||||
ParseStringFlag(arg, kInternalRunDeathTestFlag,
|
||||
>EST_FLAG(internal_run_death_test)) ||
|
||||
ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) ||
|
||||
ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) ||
|
||||
ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) ||
|
||||
ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) ||
|
||||
ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) ||
|
||||
ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) ||
|
||||
ParseInt32Flag(arg, kStackTraceDepthFlag,
|
||||
>EST_FLAG(stack_trace_depth)) ||
|
||||
ParseStringFlag(arg, kStreamResultToFlag,
|
||||
>EST_FLAG(stream_result_to)) ||
|
||||
ParseBoolFlag(arg, kThrowOnFailureFlag,
|
||||
>EST_FLAG(throw_on_failure))
|
||||
) {
|
||||
// Yes. Shift the remainder of the argv list left by one. Note
|
||||
bool remove_flag = false;
|
||||
if (ParseGoogleTestFlag(arg)) {
|
||||
remove_flag = true;
|
||||
} else if (ParseStringFlag(arg, kFlagfileFlag, >EST_FLAG(flagfile))) {
|
||||
LoadFlagsFromFile(GTEST_FLAG(flagfile));
|
||||
remove_flag = true;
|
||||
} else if (arg_string == "--help" || arg_string == "-h" ||
|
||||
arg_string == "-?" || arg_string == "/?" ||
|
||||
HasGoogleTestFlagPrefix(arg)) {
|
||||
// Both help flag and unrecognized Google Test flags (excluding
|
||||
// internal ones) trigger help display.
|
||||
g_help_flag = true;
|
||||
}
|
||||
|
||||
if (remove_flag) {
|
||||
// Shift the remainder of the argv list left by one. Note
|
||||
// that argv has (*argc + 1) elements, the last one always being
|
||||
// NULL. The following loop moves the trailing NULL element as
|
||||
// well.
|
||||
|
@ -5233,12 +5292,6 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
|
|||
// We also need to decrement the iterator as we just removed
|
||||
// an element.
|
||||
i--;
|
||||
} else if (arg_string == "--help" || arg_string == "-h" ||
|
||||
arg_string == "-?" || arg_string == "/?" ||
|
||||
HasGoogleTestFlagPrefix(arg)) {
|
||||
// Both help flag and unrecognized Google Test flags (excluding
|
||||
// internal ones) trigger help display.
|
||||
g_help_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -514,24 +514,6 @@ class DirectoryCreationTest : public Test {
|
|||
posix::RmDir(testdata_path_.c_str());
|
||||
}
|
||||
|
||||
std::string TempDir() const {
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
return "\\temp\\";
|
||||
#elif GTEST_OS_WINDOWS
|
||||
const char* temp_dir = posix::GetEnv("TEMP");
|
||||
if (temp_dir == NULL || temp_dir[0] == '\0')
|
||||
return "\\temp\\";
|
||||
else if (temp_dir[strlen(temp_dir) - 1] == '\\')
|
||||
return temp_dir;
|
||||
else
|
||||
return std::string(temp_dir) + "\\";
|
||||
#elif GTEST_OS_LINUX_ANDROID
|
||||
return "/sdcard/";
|
||||
#else
|
||||
return "/tmp/";
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
|
||||
void CreateTextFile(const char* filename) {
|
||||
FILE* f = posix::FOpen(filename, "w");
|
||||
fprintf(f, "text\n");
|
||||
|
|
|
@ -6345,6 +6345,105 @@ TEST_F(InitGoogleTestTest, WideStrings) {
|
|||
}
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
class FlagfileTest : public InitGoogleTestTest {
|
||||
public:
|
||||
virtual void SetUp() {
|
||||
InitGoogleTestTest::SetUp();
|
||||
|
||||
testdata_path_.Set(internal::FilePath(
|
||||
internal::TempDir() + internal::GetCurrentExecutableName().string() +
|
||||
"_flagfile_test"));
|
||||
testing::internal::posix::RmDir(testdata_path_.c_str());
|
||||
EXPECT_TRUE(testdata_path_.CreateFolder());
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
testing::internal::posix::RmDir(testdata_path_.c_str());
|
||||
InitGoogleTestTest::TearDown();
|
||||
}
|
||||
|
||||
internal::FilePath CreateFlagfile(const char* contents) {
|
||||
internal::FilePath file_path(internal::FilePath::GenerateUniqueFileName(
|
||||
testdata_path_, internal::FilePath("unique"), "txt"));
|
||||
FILE* f = testing::internal::posix::FOpen(file_path.c_str(), "w");
|
||||
fprintf(f, "%s", contents);
|
||||
fclose(f);
|
||||
return file_path;
|
||||
}
|
||||
|
||||
private:
|
||||
internal::FilePath testdata_path_;
|
||||
};
|
||||
|
||||
// Tests an empty flagfile.
|
||||
TEST_F(FlagfileTest, Empty) {
|
||||
internal::FilePath flagfile_path(CreateFlagfile(""));
|
||||
std::string flagfile_flag =
|
||||
std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
|
||||
|
||||
const char* argv[] = {
|
||||
"foo.exe",
|
||||
flagfile_flag.c_str(),
|
||||
NULL
|
||||
};
|
||||
|
||||
const char* argv2[] = {
|
||||
"foo.exe",
|
||||
NULL
|
||||
};
|
||||
|
||||
GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
|
||||
}
|
||||
|
||||
// Tests passing a non-empty --gtest_filter flag via --gtest_flagfile.
|
||||
TEST_F(FlagfileTest, FilterNonEmpty) {
|
||||
internal::FilePath flagfile_path(CreateFlagfile(
|
||||
"--" GTEST_FLAG_PREFIX_ "filter=abc"));
|
||||
std::string flagfile_flag =
|
||||
std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
|
||||
|
||||
const char* argv[] = {
|
||||
"foo.exe",
|
||||
flagfile_flag.c_str(),
|
||||
NULL
|
||||
};
|
||||
|
||||
const char* argv2[] = {
|
||||
"foo.exe",
|
||||
NULL
|
||||
};
|
||||
|
||||
GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("abc"), false);
|
||||
}
|
||||
|
||||
// Tests passing several flags via --gtest_flagfile.
|
||||
TEST_F(FlagfileTest, SeveralFlags) {
|
||||
internal::FilePath flagfile_path(CreateFlagfile(
|
||||
"--" GTEST_FLAG_PREFIX_ "filter=abc\n"
|
||||
"--" GTEST_FLAG_PREFIX_ "break_on_failure\n"
|
||||
"--" GTEST_FLAG_PREFIX_ "list_tests"));
|
||||
std::string flagfile_flag =
|
||||
std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
|
||||
|
||||
const char* argv[] = {
|
||||
"foo.exe",
|
||||
flagfile_flag.c_str(),
|
||||
NULL
|
||||
};
|
||||
|
||||
const char* argv2[] = {
|
||||
"foo.exe",
|
||||
NULL
|
||||
};
|
||||
|
||||
Flags expected_flags;
|
||||
expected_flags.break_on_failure = true;
|
||||
expected_flags.filter = "abc";
|
||||
expected_flags.list_tests = true;
|
||||
|
||||
GTEST_TEST_PARSING_FLAGS_(argv, argv2, expected_flags, false);
|
||||
}
|
||||
|
||||
// Tests current_test_info() in UnitTest.
|
||||
class CurrentTestInfoTest : public Test {
|
||||
protected:
|
||||
|
|
Loading…
Reference in New Issue
Block a user