From 019d19af978f05b774407e0d46a3bda2c18c67c6 Mon Sep 17 00:00:00 2001 From: shiqian Date: Fri, 12 Sep 2008 04:01:37 +0000 Subject: Improves thread-safe death tests by changing to the original working directory before they are executed; also fixes out-dated comments about death tests. --- include/gtest/gtest-death-test.h | 36 ++++++++++++++++++--------------- include/gtest/gtest.h | 4 ++++ include/gtest/internal/gtest-filepath.h | 6 ++++++ 3 files changed, 30 insertions(+), 16 deletions(-) (limited to 'include/gtest') diff --git a/include/gtest/gtest-death-test.h b/include/gtest/gtest-death-test.h index cbd41fe6..6fae47fb 100644 --- a/include/gtest/gtest-death-test.h +++ b/include/gtest/gtest-death-test.h @@ -56,29 +56,19 @@ GTEST_DECLARE_string(death_test_style); // Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is // executed: // -// 1. The assertion fails immediately if there are more than one -// active threads. This is because it's safe to fork() only when -// there is a single thread. +// 1. It generates a warning if there is more than one active +// thread. This is because it's safe to fork() or clone() only +// when there is a single thread. // -// 2. The parent process forks a sub-process and runs the death test -// in it; the sub-process exits with code 0 at the end of the death -// test, if it hasn't exited already. +// 2. The parent process clone()s a sub-process and runs the death +// test in it; the sub-process exits with code 0 at the end of the +// death test, if it hasn't exited already. // // 3. The parent process waits for the sub-process to terminate. // // 4. The parent process checks the exit code and error message of // the sub-process. // -// Note: -// -// It's not safe to call exit() if the current process is forked from -// a multi-threaded process, so people usually call _exit() instead in -// such a case. However, we are not concerned with this as we run -// death tests only when there is a single thread. Since exit() has a -// cleaner semantics (it also calls functions registered with atexit() -// and on_exit()), this macro calls exit() instead of _exit() to -// terminate the child process. -// // Examples: // // ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number"); @@ -95,6 +85,20 @@ GTEST_DECLARE_string(death_test_style); // } // // ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); +// +// Known caveats: +// +// A "threadsafe" style death test obtains the path to the test +// program from argv[0] and re-executes it in the sub-process. For +// simplicity, the current implementation doesn't search the PATH +// when launching the sub-process. This means that the user must +// invoke the test program via a path that contains at least one +// path separator (e.g. path/to/foo_test and +// /absolute/path/to/bar_test are fine, but foo_test is not). This +// is rarely a problem as people usually don't put the test binary +// directory in PATH. +// +// TODO(wan@google.com): make thread-safe death tests search the PATH. // Asserts that a given statement causes the program to exit, with an // integer exit status that satisfies predicate, and emitting error output diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h index 37ea6b04..057efa26 100644 --- a/include/gtest/gtest.h +++ b/include/gtest/gtest.h @@ -479,6 +479,10 @@ class UnitTest { // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. int Run() GTEST_MUST_USE_RESULT; + // Returns the working directory when the first TEST() or TEST_F() + // was executed. The UnitTest object owns the string. + const char* original_working_dir() const; + // Returns the TestCase object for the test that's currently running, // or NULL if no test is running. const TestCase* current_test_case() const; diff --git a/include/gtest/internal/gtest-filepath.h b/include/gtest/internal/gtest-filepath.h index 308a2c64..fecdddcc 100644 --- a/include/gtest/internal/gtest-filepath.h +++ b/include/gtest/internal/gtest-filepath.h @@ -70,6 +70,9 @@ class FilePath { String ToString() const { return pathname_; } const char* c_str() const { return pathname_.c_str(); } + // Returns the current working directory, or "" if unsuccessful. + static FilePath GetCurrentDir(); + // Given directory = "dir", base_name = "test", number = 0, // extension = "xml", returns "dir/test.xml". If number is greater // than zero (e.g., 12), returns "dir/test_12.xml". @@ -91,6 +94,9 @@ class FilePath { const FilePath& base_name, const char* extension); + // Returns true iff the path is NULL or "". + bool IsEmpty() const { return c_str() == NULL || *c_str() == '\0'; } + // If input name has a trailing separator character, removes it and returns // the name, otherwise return the name string unmodified. // On Windows platform, uses \ as the separator, other platforms use /. -- cgit v1.2.3