Skip to content

Commit

Permalink
Add support for --gtest_flagfile
Browse files Browse the repository at this point in the history
git-svn-id: http://googletest.googlecode.com/svn/trunk@724 861a406c-534a-0410-8894-cb66d6ee9925
  • Loading branch information
[email protected] committed Jul 17, 2015
1 parent f3aba5a commit 837211f
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 108 deletions.
5 changes: 5 additions & 0 deletions include/gtest/internal/gtest-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions include/gtest/internal/gtest-port.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
20 changes: 0 additions & 20 deletions src/gtest-death-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/gtest-internal-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
80 changes: 45 additions & 35 deletions src/gtest-port.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -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().
Expand Down
123 changes: 88 additions & 35 deletions src/gtest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
&GTEST_FLAG(also_run_disabled_tests)) ||
ParseBoolFlag(arg, kBreakOnFailureFlag,
&GTEST_FLAG(break_on_failure)) ||
ParseBoolFlag(arg, kCatchExceptionsFlag,
&GTEST_FLAG(catch_exceptions)) ||
ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
ParseStringFlag(arg, kDeathTestStyleFlag,
&GTEST_FLAG(death_test_style)) ||
ParseBoolFlag(arg, kDeathTestUseFork,
&GTEST_FLAG(death_test_use_fork)) ||
ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
ParseStringFlag(arg, kInternalRunDeathTestFlag,
&GTEST_FLAG(internal_run_death_test)) ||
ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
ParseInt32Flag(arg, kStackTraceDepthFlag,
&GTEST_FLAG(stack_trace_depth)) ||
ParseStringFlag(arg, kStreamResultToFlag,
&GTEST_FLAG(stream_result_to)) ||
ParseBoolFlag(arg, kThrowOnFailureFlag,
&GTEST_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.
Expand All @@ -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,
&GTEST_FLAG(also_run_disabled_tests)) ||
ParseBoolFlag(arg, kBreakOnFailureFlag,
&GTEST_FLAG(break_on_failure)) ||
ParseBoolFlag(arg, kCatchExceptionsFlag,
&GTEST_FLAG(catch_exceptions)) ||
ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
ParseStringFlag(arg, kDeathTestStyleFlag,
&GTEST_FLAG(death_test_style)) ||
ParseBoolFlag(arg, kDeathTestUseFork,
&GTEST_FLAG(death_test_use_fork)) ||
ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
ParseStringFlag(arg, kInternalRunDeathTestFlag,
&GTEST_FLAG(internal_run_death_test)) ||
ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
ParseInt32Flag(arg, kStackTraceDepthFlag,
&GTEST_FLAG(stack_trace_depth)) ||
ParseStringFlag(arg, kStreamResultToFlag,
&GTEST_FLAG(stream_result_to)) ||
ParseBoolFlag(arg, kThrowOnFailureFlag,
&GTEST_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, &GTEST_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.
Expand All @@ -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;
}
}

Expand Down
18 changes: 0 additions & 18 deletions test/gtest-filepath_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
Loading

0 comments on commit 837211f

Please sign in to comment.