Unverified Commit 120863ba authored by Romain Deterre's avatar Romain Deterre Committed by GitHub
Browse files

Update Google Test to v1.10.0 (#840)

This commit updates the version of Google Test from 1.8 to 1.10.
parent b2f89386
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// This sample shows how to test common properties of multiple // This sample shows how to test common properties of multiple
// implementations of the same interface (aka interface tests). // implementations of the same interface (aka interface tests).
...@@ -36,7 +35,7 @@ ...@@ -36,7 +35,7 @@
#include "prime_tables.h" #include "prime_tables.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
namespace {
// First, we define some factory functions for creating instances of // First, we define some factory functions for creating instances of
// the implementations. You may be able to skip this step if all your // the implementations. You may be able to skip this step if all your
// implementations can be constructed the same way. // implementations can be constructed the same way.
...@@ -62,7 +61,7 @@ class PrimeTableTest : public testing::Test { ...@@ -62,7 +61,7 @@ class PrimeTableTest : public testing::Test {
// implemented by T. // implemented by T.
PrimeTableTest() : table_(CreatePrimeTable<T>()) {} PrimeTableTest() : table_(CreatePrimeTable<T>()) {}
virtual ~PrimeTableTest() { delete table_; } ~PrimeTableTest() override { delete table_; }
// Note that we test an implementation via the base interface // Note that we test an implementation via the base interface
// instead of the actual implementation class. This is important // instead of the actual implementation class. This is important
...@@ -85,7 +84,7 @@ using testing::Types; ...@@ -85,7 +84,7 @@ using testing::Types;
// To write a typed test case, first use // To write a typed test case, first use
// //
// TYPED_TEST_CASE(TestCaseName, TypeList); // TYPED_TEST_SUITE(TestCaseName, TypeList);
// //
// to declare it and specify the type parameters. As with TEST_F, // to declare it and specify the type parameters. As with TEST_F,
// TestCaseName must match the test fixture name. // TestCaseName must match the test fixture name.
...@@ -93,7 +92,7 @@ using testing::Types; ...@@ -93,7 +92,7 @@ using testing::Types;
// The list of types we want to test. // The list of types we want to test.
typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> Implementations; typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> Implementations;
TYPED_TEST_CASE(PrimeTableTest, Implementations); TYPED_TEST_SUITE(PrimeTableTest, Implementations);
// Then use TYPED_TEST(TestCaseName, TestName) to define a typed test, // Then use TYPED_TEST(TestCaseName, TestName) to define a typed test,
// similar to TEST_F. // similar to TEST_F.
...@@ -132,7 +131,7 @@ TYPED_TEST(PrimeTableTest, CanGetNextPrime) { ...@@ -132,7 +131,7 @@ TYPED_TEST(PrimeTableTest, CanGetNextPrime) {
} }
// That's it! Google Test will repeat each TYPED_TEST for each type // That's it! Google Test will repeat each TYPED_TEST for each type
// in the type list specified in TYPED_TEST_CASE. Sit back and be // in the type list specified in TYPED_TEST_SUITE. Sit back and be
// happy that you don't have to define them multiple times. // happy that you don't have to define them multiple times.
#endif // GTEST_HAS_TYPED_TEST #endif // GTEST_HAS_TYPED_TEST
...@@ -164,7 +163,7 @@ class PrimeTableTest2 : public PrimeTableTest<T> { ...@@ -164,7 +163,7 @@ class PrimeTableTest2 : public PrimeTableTest<T> {
// Then, declare the test case. The argument is the name of the test // Then, declare the test case. The argument is the name of the test
// fixture, and also the name of the test case (as usual). The _P // fixture, and also the name of the test case (as usual). The _P
// suffix is for "parameterized" or "pattern". // suffix is for "parameterized" or "pattern".
TYPED_TEST_CASE_P(PrimeTableTest2); TYPED_TEST_SUITE_P(PrimeTableTest2);
// Next, use TYPED_TEST_P(TestCaseName, TestName) to define a test, // Next, use TYPED_TEST_P(TestCaseName, TestName) to define a test,
// similar to what you do with TEST_F. // similar to what you do with TEST_F.
...@@ -197,7 +196,7 @@ TYPED_TEST_P(PrimeTableTest2, CanGetNextPrime) { ...@@ -197,7 +196,7 @@ TYPED_TEST_P(PrimeTableTest2, CanGetNextPrime) {
// Type-parameterized tests involve one extra step: you have to // Type-parameterized tests involve one extra step: you have to
// enumerate the tests you defined: // enumerate the tests you defined:
REGISTER_TYPED_TEST_CASE_P( REGISTER_TYPED_TEST_SUITE_P(
PrimeTableTest2, // The first argument is the test case name. PrimeTableTest2, // The first argument is the test case name.
// The rest of the arguments are the test names. // The rest of the arguments are the test names.
ReturnsFalseForNonPrimes, ReturnsTrueForPrimes, CanGetNextPrime); ReturnsFalseForNonPrimes, ReturnsTrueForPrimes, CanGetNextPrime);
...@@ -217,8 +216,9 @@ REGISTER_TYPED_TEST_CASE_P( ...@@ -217,8 +216,9 @@ REGISTER_TYPED_TEST_CASE_P(
// defined at the time we write the TYPED_TEST_P()s. // defined at the time we write the TYPED_TEST_P()s.
typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable>
PrimeTableImplementations; PrimeTableImplementations;
INSTANTIATE_TYPED_TEST_CASE_P(OnTheFlyAndPreCalculated, // Instance name INSTANTIATE_TYPED_TEST_SUITE_P(OnTheFlyAndPreCalculated, // Instance name
PrimeTableTest2, // Test case name PrimeTableTest2, // Test case name
PrimeTableImplementations); // Type list PrimeTableImplementations); // Type list
#endif // GTEST_HAS_TYPED_TEST_P #endif // GTEST_HAS_TYPED_TEST_P
} // namespace
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vladl@google.com (Vlad Losev)
// This sample shows how to test common properties of multiple // This sample shows how to test common properties of multiple
// implementations of an interface (aka interface tests) using // implementations of an interface (aka interface tests) using
...@@ -39,8 +38,7 @@ ...@@ -39,8 +38,7 @@
#include "prime_tables.h" #include "prime_tables.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
namespace {
#if GTEST_HAS_PARAM_TEST
using ::testing::TestWithParam; using ::testing::TestWithParam;
using ::testing::Values; using ::testing::Values;
...@@ -65,20 +63,20 @@ PrimeTable* CreatePreCalculatedPrimeTable() { ...@@ -65,20 +63,20 @@ PrimeTable* CreatePreCalculatedPrimeTable() {
// can refer to the test parameter by GetParam(). In this case, the test // can refer to the test parameter by GetParam(). In this case, the test
// parameter is a factory function which we call in fixture's SetUp() to // parameter is a factory function which we call in fixture's SetUp() to
// create and store an instance of PrimeTable. // create and store an instance of PrimeTable.
class PrimeTableTest : public TestWithParam<CreatePrimeTableFunc*> { class PrimeTableTestSmpl7 : public TestWithParam<CreatePrimeTableFunc*> {
public: public:
virtual ~PrimeTableTest() { delete table_; } ~PrimeTableTestSmpl7() override { delete table_; }
virtual void SetUp() { table_ = (*GetParam())(); } void SetUp() override { table_ = (*GetParam())(); }
virtual void TearDown() { void TearDown() override {
delete table_; delete table_;
table_ = NULL; table_ = nullptr;
} }
protected: protected:
PrimeTable* table_; PrimeTable* table_;
}; };
TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) { TEST_P(PrimeTableTestSmpl7, ReturnsFalseForNonPrimes) {
EXPECT_FALSE(table_->IsPrime(-5)); EXPECT_FALSE(table_->IsPrime(-5));
EXPECT_FALSE(table_->IsPrime(0)); EXPECT_FALSE(table_->IsPrime(0));
EXPECT_FALSE(table_->IsPrime(1)); EXPECT_FALSE(table_->IsPrime(1));
...@@ -87,7 +85,7 @@ TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) { ...@@ -87,7 +85,7 @@ TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) {
EXPECT_FALSE(table_->IsPrime(100)); EXPECT_FALSE(table_->IsPrime(100));
} }
TEST_P(PrimeTableTest, ReturnsTrueForPrimes) { TEST_P(PrimeTableTestSmpl7, ReturnsTrueForPrimes) {
EXPECT_TRUE(table_->IsPrime(2)); EXPECT_TRUE(table_->IsPrime(2));
EXPECT_TRUE(table_->IsPrime(3)); EXPECT_TRUE(table_->IsPrime(3));
EXPECT_TRUE(table_->IsPrime(5)); EXPECT_TRUE(table_->IsPrime(5));
...@@ -96,7 +94,7 @@ TEST_P(PrimeTableTest, ReturnsTrueForPrimes) { ...@@ -96,7 +94,7 @@ TEST_P(PrimeTableTest, ReturnsTrueForPrimes) {
EXPECT_TRUE(table_->IsPrime(131)); EXPECT_TRUE(table_->IsPrime(131));
} }
TEST_P(PrimeTableTest, CanGetNextPrime) { TEST_P(PrimeTableTestSmpl7, CanGetNextPrime) {
EXPECT_EQ(2, table_->GetNextPrime(0)); EXPECT_EQ(2, table_->GetNextPrime(0));
EXPECT_EQ(3, table_->GetNextPrime(2)); EXPECT_EQ(3, table_->GetNextPrime(2));
EXPECT_EQ(5, table_->GetNextPrime(3)); EXPECT_EQ(5, table_->GetNextPrime(3));
...@@ -112,19 +110,8 @@ TEST_P(PrimeTableTest, CanGetNextPrime) { ...@@ -112,19 +110,8 @@ TEST_P(PrimeTableTest, CanGetNextPrime) {
// //
// Here, we instantiate our tests with a list of two PrimeTable object // Here, we instantiate our tests with a list of two PrimeTable object
// factory functions: // factory functions:
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_SUITE_P(OnTheFlyAndPreCalculated, PrimeTableTestSmpl7,
OnTheFlyAndPreCalculated, Values(&CreateOnTheFlyPrimeTable,
PrimeTableTest, &CreatePreCalculatedPrimeTable<1000>));
Values(&CreateOnTheFlyPrimeTable, &CreatePreCalculatedPrimeTable<1000>));
#else
// Google Test may not support value-parameterized tests with some
// compilers. If we use conditional compilation to compile out all
// code referring to the gtest_main library, MSVC linker will not link
// that library at all and consequently complain about missing entry
// point defined in that library (fatal error LNK1561: entry point
// must be defined). This dummy test keeps gtest_main linked in.
TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}
#endif // GTEST_HAS_PARAM_TEST } // namespace
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vladl@google.com (Vlad Losev)
// This sample shows how to test code relying on some global flag variables. // This sample shows how to test code relying on some global flag variables.
// Combine() helps with generating all possible combinations of such flags, // Combine() helps with generating all possible combinations of such flags,
...@@ -37,8 +36,7 @@ ...@@ -37,8 +36,7 @@
#include "prime_tables.h" #include "prime_tables.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
namespace {
#if GTEST_HAS_COMBINE
// Suppose we want to introduce a new, improved implementation of PrimeTable // Suppose we want to introduce a new, improved implementation of PrimeTable
// which combines speed of PrecalcPrimeTable and versatility of // which combines speed of PrecalcPrimeTable and versatility of
...@@ -51,24 +49,25 @@ class HybridPrimeTable : public PrimeTable { ...@@ -51,24 +49,25 @@ class HybridPrimeTable : public PrimeTable {
public: public:
HybridPrimeTable(bool force_on_the_fly, int max_precalculated) HybridPrimeTable(bool force_on_the_fly, int max_precalculated)
: on_the_fly_impl_(new OnTheFlyPrimeTable), : on_the_fly_impl_(new OnTheFlyPrimeTable),
precalc_impl_(force_on_the_fly ? NULL : precalc_impl_(force_on_the_fly
new PreCalculatedPrimeTable(max_precalculated)), ? nullptr
: new PreCalculatedPrimeTable(max_precalculated)),
max_precalculated_(max_precalculated) {} max_precalculated_(max_precalculated) {}
virtual ~HybridPrimeTable() { ~HybridPrimeTable() override {
delete on_the_fly_impl_; delete on_the_fly_impl_;
delete precalc_impl_; delete precalc_impl_;
} }
virtual bool IsPrime(int n) const { bool IsPrime(int n) const override {
if (precalc_impl_ != NULL && n < max_precalculated_) if (precalc_impl_ != nullptr && n < max_precalculated_)
return precalc_impl_->IsPrime(n); return precalc_impl_->IsPrime(n);
else else
return on_the_fly_impl_->IsPrime(n); return on_the_fly_impl_->IsPrime(n);
} }
virtual int GetNextPrime(int p) const { int GetNextPrime(int p) const override {
int next_prime = -1; int next_prime = -1;
if (precalc_impl_ != NULL && p < max_precalculated_) if (precalc_impl_ != nullptr && p < max_precalculated_)
next_prime = precalc_impl_->GetNextPrime(p); next_prime = precalc_impl_->GetNextPrime(p);
return next_prime != -1 ? next_prime : on_the_fly_impl_->GetNextPrime(p); return next_prime != -1 ? next_prime : on_the_fly_impl_->GetNextPrime(p);
...@@ -90,24 +89,17 @@ using ::testing::Combine; ...@@ -90,24 +89,17 @@ using ::testing::Combine;
// PreCalculatedPrimeTable disabled. We do this by defining fixture which will // PreCalculatedPrimeTable disabled. We do this by defining fixture which will
// accept different combinations of parameters for instantiating a // accept different combinations of parameters for instantiating a
// HybridPrimeTable instance. // HybridPrimeTable instance.
class PrimeTableTest : public TestWithParam< ::testing::tuple<bool, int> > { class PrimeTableTest : public TestWithParam< ::std::tuple<bool, int> > {
protected: protected:
virtual void SetUp() { void SetUp() override {
// This can be written as bool force_on_the_fly;
// int max_precalculated;
// bool force_on_the_fly; std::tie(force_on_the_fly, max_precalculated) = GetParam();
// int max_precalculated;
// tie(force_on_the_fly, max_precalculated) = GetParam();
//
// once the Google C++ Style Guide allows use of ::std::tr1::tie.
//
bool force_on_the_fly = ::testing::get<0>(GetParam());
int max_precalculated = ::testing::get<1>(GetParam());
table_ = new HybridPrimeTable(force_on_the_fly, max_precalculated); table_ = new HybridPrimeTable(force_on_the_fly, max_precalculated);
} }
virtual void TearDown() { void TearDown() override {
delete table_; delete table_;
table_ = NULL; table_ = nullptr;
} }
HybridPrimeTable* table_; HybridPrimeTable* table_;
}; };
...@@ -156,18 +148,7 @@ TEST_P(PrimeTableTest, CanGetNextPrime) { ...@@ -156,18 +148,7 @@ TEST_P(PrimeTableTest, CanGetNextPrime) {
// will put some of the tested numbers beyond the capability of the // will put some of the tested numbers beyond the capability of the
// PrecalcPrimeTable instance and some inside it (10). Combine will produce all // PrecalcPrimeTable instance and some inside it (10). Combine will produce all
// possible combinations. // possible combinations.
INSTANTIATE_TEST_CASE_P(MeaningfulTestParameters, INSTANTIATE_TEST_SUITE_P(MeaningfulTestParameters, PrimeTableTest,
PrimeTableTest, Combine(Bool(), Values(1, 10)));
Combine(Bool(), Values(1, 10)));
#else
// Google Test may not support Combine() with some compilers. If we
// use conditional compilation to compile out all code referring to
// the gtest_main library, MSVC linker will not link that library at
// all and consequently complain about missing entry point defined in
// that library (fatal error LNK1561: entry point must be
// defined). This dummy test keeps gtest_main linked in.
TEST(DummyTest, CombineIsNotSupportedOnThisPlatform) {}
#endif // GTEST_HAS_COMBINE } // namespace
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vladl@google.com (Vlad Losev)
// This sample shows how to use Google Test listener API to implement // This sample shows how to use Google Test listener API to implement
// an alternative console output and how to use the UnitTest reflection API // an alternative console output and how to use the UnitTest reflection API
...@@ -44,24 +43,22 @@ using ::testing::TestEventListeners; ...@@ -44,24 +43,22 @@ using ::testing::TestEventListeners;
using ::testing::TestInfo; using ::testing::TestInfo;
using ::testing::TestPartResult; using ::testing::TestPartResult;
using ::testing::UnitTest; using ::testing::UnitTest;
namespace { namespace {
// Provides alternative output mode which produces minimal amount of // Provides alternative output mode which produces minimal amount of
// information about tests. // information about tests.
class TersePrinter : public EmptyTestEventListener { class TersePrinter : public EmptyTestEventListener {
private: private:
// Called before any test activity starts. // Called before any test activity starts.
virtual void OnTestProgramStart(const UnitTest& /* unit_test */) {} void OnTestProgramStart(const UnitTest& /* unit_test */) override {}
// Called after all test activities have ended. // Called after all test activities have ended.
virtual void OnTestProgramEnd(const UnitTest& unit_test) { void OnTestProgramEnd(const UnitTest& unit_test) override {
fprintf(stdout, "TEST %s\n", unit_test.Passed() ? "PASSED" : "FAILED"); fprintf(stdout, "TEST %s\n", unit_test.Passed() ? "PASSED" : "FAILED");
fflush(stdout); fflush(stdout);
} }
// Called before a test starts. // Called before a test starts.
virtual void OnTestStart(const TestInfo& test_info) { void OnTestStart(const TestInfo& test_info) override {
fprintf(stdout, fprintf(stdout,
"*** Test %s.%s starting.\n", "*** Test %s.%s starting.\n",
test_info.test_case_name(), test_info.test_case_name(),
...@@ -70,7 +67,7 @@ class TersePrinter : public EmptyTestEventListener { ...@@ -70,7 +67,7 @@ class TersePrinter : public EmptyTestEventListener {
} }
// Called after a failed assertion or a SUCCEED() invocation. // Called after a failed assertion or a SUCCEED() invocation.
virtual void OnTestPartResult(const TestPartResult& test_part_result) { void OnTestPartResult(const TestPartResult& test_part_result) override {
fprintf(stdout, fprintf(stdout,
"%s in %s:%d\n%s\n", "%s in %s:%d\n%s\n",
test_part_result.failed() ? "*** Failure" : "Success", test_part_result.failed() ? "*** Failure" : "Success",
...@@ -81,7 +78,7 @@ class TersePrinter : public EmptyTestEventListener { ...@@ -81,7 +78,7 @@ class TersePrinter : public EmptyTestEventListener {
} }
// Called after a test ends. // Called after a test ends.
virtual void OnTestEnd(const TestInfo& test_info) { void OnTestEnd(const TestInfo& test_info) override {
fprintf(stdout, fprintf(stdout,
"*** Test %s.%s ending.\n", "*** Test %s.%s ending.\n",
test_info.test_case_name(), test_info.test_case_name(),
...@@ -102,7 +99,6 @@ TEST(CustomOutputTest, Fails) { ...@@ -102,7 +99,6 @@ TEST(CustomOutputTest, Fails) {
EXPECT_EQ(1, 2) EXPECT_EQ(1, 2)
<< "This test fails in order to demonstrate alternative failure messages"; << "This test fails in order to demonstrate alternative failure messages";
} }
} // namespace } // namespace
int main(int argc, char **argv) { int main(int argc, char **argv) {
...@@ -139,10 +135,10 @@ int main(int argc, char **argv) { ...@@ -139,10 +135,10 @@ int main(int argc, char **argv) {
// This is an example of using the UnitTest reflection API to inspect test // This is an example of using the UnitTest reflection API to inspect test
// results. Here we discount failures from the tests we expected to fail. // results. Here we discount failures from the tests we expected to fail.
int unexpectedly_failed_tests = 0; int unexpectedly_failed_tests = 0;
for (int i = 0; i < unit_test.total_test_case_count(); ++i) { for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
const TestCase& test_case = *unit_test.GetTestCase(i); const testing::TestSuite& test_suite = *unit_test.GetTestSuite(i);
for (int j = 0; j < test_case.total_test_count(); ++j) { for (int j = 0; j < test_suite.total_test_count(); ++j) {
const TestInfo& test_info = *test_case.GetTestInfo(j); const TestInfo& test_info = *test_suite.GetTestInfo(j);
// Counts failed tests that were not meant to fail (those without // Counts failed tests that were not meant to fail (those without
// 'Fails' in the name). // 'Fails' in the name).
if (test_info.result()->Failed() && if (test_info.result()->Failed() &&
......
...@@ -52,7 +52,7 @@ EXAMPLES ...@@ -52,7 +52,7 @@ EXAMPLES
This tool is experimental. In particular, it assumes that there is no This tool is experimental. In particular, it assumes that there is no
conditional inclusion of Google Test headers. Please report any conditional inclusion of Google Test headers. Please report any
problems to googletestframework@googlegroups.com. You can read problems to googletestframework@googlegroups.com. You can read
http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide for https://github.com/google/googletest/blob/master/googletest/docs/advanced.md for
more information. more information.
""" """
......
...@@ -115,10 +115,9 @@ def HeaderPreamble(n): ...@@ -115,10 +115,9 @@ def HeaderPreamble(n):
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ #ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ #define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
// Makes sure this header is not included before gtest.h. #include "gtest/gtest.h"
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
# error Do not include gtest_pred_impl.h directly. Include gtest.h instead. namespace testing {
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
// This header implements a family of generic predicate assertion // This header implements a family of generic predicate assertion
// macros: // macros:
...@@ -295,16 +294,17 @@ def HeaderPostamble(): ...@@ -295,16 +294,17 @@ def HeaderPostamble():
return """ return """
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ #endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
""" """
def GenerateFile(path, content): def GenerateFile(path, content):
"""Given a file path and a content string, overwrites it with the """Given a file path and a content string
given content.""" overwrites it with the given content.
"""
print 'Updating file %s . . .' % path print 'Updating file %s . . .' % path
f = file(path, 'w+') f = file(path, 'w+')
print >>f, content, print >>f, content,
f.close() f.close()
...@@ -314,8 +314,8 @@ def GenerateFile(path, content): ...@@ -314,8 +314,8 @@ def GenerateFile(path, content):
def GenerateHeader(n): def GenerateHeader(n):
"""Given the maximum arity n, updates the header file that implements """Given the maximum arity n, updates the header file that implements
the predicate assertions.""" the predicate assertions.
"""
GenerateFile(HEADER, GenerateFile(HEADER,
HeaderPreamble(n) HeaderPreamble(n)
+ ''.join([ImplementationForArity(i) for i in OneTo(n)]) + ''.join([ImplementationForArity(i) for i in OneTo(n)])
......
...@@ -242,7 +242,7 @@ class AbstractRpcServer(object): ...@@ -242,7 +242,7 @@ class AbstractRpcServer(object):
The authentication process works as follows: The authentication process works as follows:
1) We get a username and password from the user 1) We get a username and password from the user
2) We use ClientLogin to obtain an AUTH token for the user 2) We use ClientLogin to obtain an AUTH token for the user
(see http://code.google.com/apis/accounts/AuthForInstalledApps.html). (see https://developers.google.com/identity/protocols/AuthForInstalledApps).
3) We pass the auth token to /_ah/login on the server to obtain an 3) We pass the auth token to /_ah/login on the server to obtain an
authentication cookie. If login was successful, it tries to redirect authentication cookie. If login was successful, it tries to redirect
us to the URL we provided. us to the URL we provided.
...@@ -506,7 +506,7 @@ def EncodeMultipartFormData(fields, files): ...@@ -506,7 +506,7 @@ def EncodeMultipartFormData(fields, files):
(content_type, body) ready for httplib.HTTP instance. (content_type, body) ready for httplib.HTTP instance.
Source: Source:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306 https://web.archive.org/web/20160116052001/code.activestate.com/recipes/146306
""" """
BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-' BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
CRLF = '\r\n' CRLF = '\r\n'
...@@ -732,7 +732,7 @@ class SubversionVCS(VersionControlSystem): ...@@ -732,7 +732,7 @@ class SubversionVCS(VersionControlSystem):
else: else:
self.rev_start = self.rev_end = None self.rev_start = self.rev_end = None
# Cache output from "svn list -r REVNO dirname". # Cache output from "svn list -r REVNO dirname".
# Keys: dirname, Values: 2-tuple (ouput for start rev and end rev). # Keys: dirname, Values: 2-tuple (output for start rev and end rev).
self.svnls_cache = {} self.svnls_cache = {}
# SVN base URL is required to fetch files deleted in an older revision. # SVN base URL is required to fetch files deleted in an older revision.
# Result is cached to not guess it over and over again in GetBaseFile(). # Result is cached to not guess it over and over again in GetBaseFile().
...@@ -807,7 +807,7 @@ class SubversionVCS(VersionControlSystem): ...@@ -807,7 +807,7 @@ class SubversionVCS(VersionControlSystem):
# svn cat translates keywords but svn diff doesn't. As a result of this # svn cat translates keywords but svn diff doesn't. As a result of this
# behavior patching.PatchChunks() fails with a chunk mismatch error. # behavior patching.PatchChunks() fails with a chunk mismatch error.
# This part was originally written by the Review Board development team # This part was originally written by the Review Board development team
# who had the same problem (http://reviews.review-board.org/r/276/). # who had the same problem (https://reviews.reviewboard.org/r/276/).
# Mapping of keywords to known aliases # Mapping of keywords to known aliases
svn_keywords = { svn_keywords = {
# Standard keywords # Standard keywords
...@@ -860,7 +860,7 @@ class SubversionVCS(VersionControlSystem): ...@@ -860,7 +860,7 @@ class SubversionVCS(VersionControlSystem):
status_lines = status.splitlines() status_lines = status.splitlines()
# If file is in a cl, the output will begin with # If file is in a cl, the output will begin with
# "\n--- Changelist 'cl_name':\n". See # "\n--- Changelist 'cl_name':\n". See
# http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt # https://web.archive.org/web/20090918234815/svn.collab.net/repos/svn/trunk/notes/changelist-design.txt
if (len(status_lines) == 3 and if (len(status_lines) == 3 and
not status_lines[0] and not status_lines[0] and
status_lines[1].startswith("--- Changelist")): status_lines[1].startswith("--- Changelist")):
......
...@@ -26,10 +26,9 @@ ...@@ -26,10 +26,9 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// Author: mheule@google.com (Markus Heule) // Google C++ Testing and Mocking Framework (Google Test)
//
// Google C++ Testing Framework (Google Test)
// //
// Sometimes it's desirable to build Google Test by compiling a single file. // Sometimes it's desirable to build Google Test by compiling a single file.
// This file serves this purpose. // This file serves this purpose.
...@@ -42,6 +41,7 @@ ...@@ -42,6 +41,7 @@
#include "src/gtest.cc" #include "src/gtest.cc"
#include "src/gtest-death-test.cc" #include "src/gtest-death-test.cc"
#include "src/gtest-filepath.cc" #include "src/gtest-filepath.cc"
#include "src/gtest-matchers.cc"
#include "src/gtest-port.cc" #include "src/gtest-port.cc"
#include "src/gtest-printers.cc" #include "src/gtest-printers.cc"
#include "src/gtest-test-part.cc" #include "src/gtest-test-part.cc"
......
...@@ -26,12 +26,14 @@ ...@@ -26,12 +26,14 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
// //
// This file implements death tests. // This file implements death tests.
#include "gtest/gtest-death-test.h" #include "gtest/gtest-death-test.h"
#include <utility>
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#include "gtest/internal/custom/gtest.h" #include "gtest/internal/custom/gtest.h"
...@@ -62,26 +64,36 @@ ...@@ -62,26 +64,36 @@
# include <spawn.h> # include <spawn.h>
# endif // GTEST_OS_QNX # endif // GTEST_OS_QNX
# if GTEST_OS_FUCHSIA
# include <lib/fdio/fd.h>
# include <lib/fdio/io.h>
# include <lib/fdio/spawn.h>
# include <lib/zx/channel.h>
# include <lib/zx/port.h>
# include <lib/zx/process.h>
# include <lib/zx/socket.h>
# include <zircon/processargs.h>
# include <zircon/syscalls.h>
# include <zircon/syscalls/policy.h>
# include <zircon/syscalls/port.h>
# endif // GTEST_OS_FUCHSIA
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
#include "gtest/gtest-message.h" #include "gtest/gtest-message.h"
#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick exists to
// prevent the accidental inclusion of gtest-internal-inl.h in the
// user's code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
namespace testing { namespace testing {
// Constants. // Constants.
// The default death test style. // The default death test style.
static const char kDefaultDeathTestStyle[] = "fast"; //
// This is defined in internal/gtest-port.h as "fast", but can be overridden by
// a definition in internal/custom/gtest-port.h. The recommended value, which is
// used internally at Google, is "threadsafe".
static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE;
GTEST_DEFINE_string_( GTEST_DEFINE_string_(
death_test_style, death_test_style,
...@@ -110,8 +122,8 @@ GTEST_DEFINE_string_( ...@@ -110,8 +122,8 @@ GTEST_DEFINE_string_(
"Indicates the file, line number, temporal index of " "Indicates the file, line number, temporal index of "
"the single death test to run, and a file descriptor to " "the single death test to run, and a file descriptor to "
"which a success code may be sent, all separated by " "which a success code may be sent, all separated by "
"the '|' characters. This flag is specified if and only if the current " "the '|' characters. This flag is specified if and only if the "
"process is a sub-process launched for running a thread-safe " "current process is a sub-process launched for running a thread-safe "
"death test. FOR INTERNAL USE ONLY."); "death test. FOR INTERNAL USE ONLY.");
} // namespace internal } // namespace internal
...@@ -121,7 +133,7 @@ namespace internal { ...@@ -121,7 +133,7 @@ namespace internal {
// Valid only for fast death tests. Indicates the code is running in the // Valid only for fast death tests. Indicates the code is running in the
// child process of a fast style death test. // child process of a fast style death test.
# if !GTEST_OS_WINDOWS # if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
static bool g_in_fast_death_test_child = false; static bool g_in_fast_death_test_child = false;
# endif # endif
...@@ -131,10 +143,10 @@ static bool g_in_fast_death_test_child = false; ...@@ -131,10 +143,10 @@ static bool g_in_fast_death_test_child = false;
// tests. IMPORTANT: This is an internal utility. Using it may break the // tests. IMPORTANT: This is an internal utility. Using it may break the
// implementation of death tests. User code MUST NOT use it. // implementation of death tests. User code MUST NOT use it.
bool InDeathTestChild() { bool InDeathTestChild() {
# if GTEST_OS_WINDOWS # if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
// On Windows, death tests are thread-safe regardless of the value of the // On Windows and Fuchsia, death tests are thread-safe regardless of the value
// death_test_style flag. // of the death_test_style flag.
return !GTEST_FLAG(internal_run_death_test).empty(); return !GTEST_FLAG(internal_run_death_test).empty();
# else # else
...@@ -154,7 +166,7 @@ ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { ...@@ -154,7 +166,7 @@ ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
// ExitedWithCode function-call operator. // ExitedWithCode function-call operator.
bool ExitedWithCode::operator()(int exit_status) const { bool ExitedWithCode::operator()(int exit_status) const {
# if GTEST_OS_WINDOWS # if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
return exit_status == exit_code_; return exit_status == exit_code_;
...@@ -162,10 +174,10 @@ bool ExitedWithCode::operator()(int exit_status) const { ...@@ -162,10 +174,10 @@ bool ExitedWithCode::operator()(int exit_status) const {
return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
# endif // GTEST_OS_WINDOWS # endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
} }
# if !GTEST_OS_WINDOWS # if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
// KilledBySignal constructor. // KilledBySignal constructor.
KilledBySignal::KilledBySignal(int signum) : signum_(signum) { KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
} }
...@@ -182,7 +194,7 @@ bool KilledBySignal::operator()(int exit_status) const { ...@@ -182,7 +194,7 @@ bool KilledBySignal::operator()(int exit_status) const {
# endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_) # endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
} }
# endif // !GTEST_OS_WINDOWS # endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
namespace internal { namespace internal {
...@@ -193,7 +205,7 @@ namespace internal { ...@@ -193,7 +205,7 @@ namespace internal {
static std::string ExitSummary(int exit_code) { static std::string ExitSummary(int exit_code) {
Message m; Message m;
# if GTEST_OS_WINDOWS # if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
m << "Exited with exit status " << exit_code; m << "Exited with exit status " << exit_code;
...@@ -209,7 +221,7 @@ static std::string ExitSummary(int exit_code) { ...@@ -209,7 +221,7 @@ static std::string ExitSummary(int exit_code) {
m << " (core dumped)"; m << " (core dumped)";
} }
# endif # endif
# endif // GTEST_OS_WINDOWS # endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
return m.GetString(); return m.GetString();
} }
...@@ -220,7 +232,7 @@ bool ExitedUnsuccessfully(int exit_status) { ...@@ -220,7 +232,7 @@ bool ExitedUnsuccessfully(int exit_status) {
return !ExitedWithCode(0)(exit_status); return !ExitedWithCode(0)(exit_status);
} }
# if !GTEST_OS_WINDOWS # if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
// Generates a textual failure message when a death test finds more than // Generates a textual failure message when a death test finds more than
// one thread running, or cannot determine the number of threads, prior // one thread running, or cannot determine the number of threads, prior
// to executing the given statement. It is the responsibility of the // to executing the given statement. It is the responsibility of the
...@@ -229,13 +241,19 @@ static std::string DeathTestThreadWarning(size_t thread_count) { ...@@ -229,13 +241,19 @@ static std::string DeathTestThreadWarning(size_t thread_count) {
Message msg; Message msg;
msg << "Death tests use fork(), which is unsafe particularly" msg << "Death tests use fork(), which is unsafe particularly"
<< " in a threaded context. For this test, " << GTEST_NAME_ << " "; << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
if (thread_count == 0) if (thread_count == 0) {
msg << "couldn't detect the number of threads."; msg << "couldn't detect the number of threads.";
else } else {
msg << "detected " << thread_count << " threads."; msg << "detected " << thread_count << " threads.";
}
msg << " See "
"https://github.com/google/googletest/blob/master/googletest/docs/"
"advanced.md#death-tests-and-threads"
<< " for more explanation and suggested solutions, especially if"
<< " this is the last message you see before your test times out.";
return msg.GetString(); return msg.GetString();
} }
# endif // !GTEST_OS_WINDOWS # endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
// Flag characters for reporting a death test that did not die. // Flag characters for reporting a death test that did not die.
static const char kDeathTestLived = 'L'; static const char kDeathTestLived = 'L';
...@@ -243,6 +261,13 @@ static const char kDeathTestReturned = 'R'; ...@@ -243,6 +261,13 @@ static const char kDeathTestReturned = 'R';
static const char kDeathTestThrew = 'T'; static const char kDeathTestThrew = 'T';
static const char kDeathTestInternalError = 'I'; static const char kDeathTestInternalError = 'I';
#if GTEST_OS_FUCHSIA
// File descriptor used for the pipe in the child process.
static const int kFuchsiaReadPipeFd = 3;
#endif
// An enumeration describing all of the possible ways that a death test can // An enumeration describing all of the possible ways that a death test can
// conclude. DIED means that the process died while executing the test // conclude. DIED means that the process died while executing the test
// code; LIVED means that process lived beyond the end of the test code; // code; LIVED means that process lived beyond the end of the test code;
...@@ -250,8 +275,6 @@ static const char kDeathTestInternalError = 'I'; ...@@ -250,8 +275,6 @@ static const char kDeathTestInternalError = 'I';
// statement, which is not allowed; THREW means that the test statement // statement, which is not allowed; THREW means that the test statement
// returned control by throwing an exception. IN_PROGRESS means the test // returned control by throwing an exception. IN_PROGRESS means the test
// has not yet concluded. // has not yet concluded.
// TODO(vladl@google.com): Unify names and possibly values for
// AbortReason, DeathTestOutcome, and flag characters above.
enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
// Routine for aborting the program which is safe to call from an // Routine for aborting the program which is safe to call from an
...@@ -259,13 +282,13 @@ enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; ...@@ -259,13 +282,13 @@ enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
// message is propagated back to the parent process. Otherwise, the // message is propagated back to the parent process. Otherwise, the
// message is simply printed to stderr. In either case, the program // message is simply printed to stderr. In either case, the program
// then exits with status 1. // then exits with status 1.
void DeathTestAbort(const std::string& message) { static void DeathTestAbort(const std::string& message) {
// On a POSIX system, this function may be called from a threadsafe-style // On a POSIX system, this function may be called from a threadsafe-style
// death test child process, which operates on a very small stack. Use // death test child process, which operates on a very small stack. Use
// the heap for any additional non-minuscule memory requirements. // the heap for any additional non-minuscule memory requirements.
const InternalRunDeathTestFlag* const flag = const InternalRunDeathTestFlag* const flag =
GetUnitTestImpl()->internal_run_death_test_flag(); GetUnitTestImpl()->internal_run_death_test_flag();
if (flag != NULL) { if (flag != nullptr) {
FILE* parent = posix::FDOpen(flag->write_fd(), "w"); FILE* parent = posix::FDOpen(flag->write_fd(), "w");
fputc(kDeathTestInternalError, parent); fputc(kDeathTestInternalError, parent);
fprintf(parent, "%s", message.c_str()); fprintf(parent, "%s", message.c_str());
...@@ -345,7 +368,7 @@ static void FailFromInternalError(int fd) { ...@@ -345,7 +368,7 @@ static void FailFromInternalError(int fd) {
// for the current test. // for the current test.
DeathTest::DeathTest() { DeathTest::DeathTest() {
TestInfo* const info = GetUnitTestImpl()->current_test_info(); TestInfo* const info = GetUnitTestImpl()->current_test_info();
if (info == NULL) { if (info == nullptr) {
DeathTestAbort("Cannot run a death test outside of a TEST or " DeathTestAbort("Cannot run a death test outside of a TEST or "
"TEST_F construct"); "TEST_F construct");
} }
...@@ -353,10 +376,11 @@ DeathTest::DeathTest() { ...@@ -353,10 +376,11 @@ DeathTest::DeathTest() {
// Creates and returns a death test by dispatching to the current // Creates and returns a death test by dispatching to the current
// death test factory. // death test factory.
bool DeathTest::Create(const char* statement, const RE* regex, bool DeathTest::Create(const char* statement,
const char* file, int line, DeathTest** test) { Matcher<const std::string&> matcher, const char* file,
int line, DeathTest** test) {
return GetUnitTestImpl()->death_test_factory()->Create( return GetUnitTestImpl()->death_test_factory()->Create(
statement, regex, file, line, test); statement, std::move(matcher), file, line, test);
} }
const char* DeathTest::LastMessage() { const char* DeathTest::LastMessage() {
...@@ -372,9 +396,9 @@ std::string DeathTest::last_death_test_message_; ...@@ -372,9 +396,9 @@ std::string DeathTest::last_death_test_message_;
// Provides cross platform implementation for some death functionality. // Provides cross platform implementation for some death functionality.
class DeathTestImpl : public DeathTest { class DeathTestImpl : public DeathTest {
protected: protected:
DeathTestImpl(const char* a_statement, const RE* a_regex) DeathTestImpl(const char* a_statement, Matcher<const std::string&> matcher)
: statement_(a_statement), : statement_(a_statement),
regex_(a_regex), matcher_(std::move(matcher)),
spawned_(false), spawned_(false),
status_(-1), status_(-1),
outcome_(IN_PROGRESS), outcome_(IN_PROGRESS),
...@@ -382,13 +406,12 @@ class DeathTestImpl : public DeathTest { ...@@ -382,13 +406,12 @@ class DeathTestImpl : public DeathTest {
write_fd_(-1) {} write_fd_(-1) {}
// read_fd_ is expected to be closed and cleared by a derived class. // read_fd_ is expected to be closed and cleared by a derived class.
~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } ~DeathTestImpl() override { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
void Abort(AbortReason reason); void Abort(AbortReason reason) override;
virtual bool Passed(bool status_ok); bool Passed(bool status_ok) override;
const char* statement() const { return statement_; } const char* statement() const { return statement_; }
const RE* regex() const { return regex_; }
bool spawned() const { return spawned_; } bool spawned() const { return spawned_; }
void set_spawned(bool is_spawned) { spawned_ = is_spawned; } void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
int status() const { return status_; } int status() const { return status_; }
...@@ -406,13 +429,15 @@ class DeathTestImpl : public DeathTest { ...@@ -406,13 +429,15 @@ class DeathTestImpl : public DeathTest {
// case of unexpected codes. // case of unexpected codes.
void ReadAndInterpretStatusByte(); void ReadAndInterpretStatusByte();
// Returns stderr output from the child process.
virtual std::string GetErrorLogs();
private: private:
// The textual content of the code this object is testing. This class // The textual content of the code this object is testing. This class
// doesn't own this string and should not attempt to delete it. // doesn't own this string and should not attempt to delete it.
const char* const statement_; const char* const statement_;
// The regular expression which test output must match. DeathTestImpl // A matcher that's expected to match the stderr output by the child process.
// doesn't own this object and should not attempt to delete it. Matcher<const std::string&> matcher_;
const RE* const regex_;
// True if the death test child process has been successfully spawned. // True if the death test child process has been successfully spawned.
bool spawned_; bool spawned_;
// The exit status of the child process. // The exit status of the child process.
...@@ -474,6 +499,10 @@ void DeathTestImpl::ReadAndInterpretStatusByte() { ...@@ -474,6 +499,10 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
set_read_fd(-1); set_read_fd(-1);
} }
std::string DeathTestImpl::GetErrorLogs() {
return GetCapturedStderr();
}
// Signals that the death test code which should have exited, didn't. // Signals that the death test code which should have exited, didn't.
// Should be called only in a death test child process. // Should be called only in a death test child process.
// Writes a status byte to the child's status file descriptor, then // Writes a status byte to the child's status file descriptor, then
...@@ -527,22 +556,21 @@ static ::std::string FormatDeathTestOutput(const ::std::string& output) { ...@@ -527,22 +556,21 @@ static ::std::string FormatDeathTestOutput(const ::std::string& output) {
// in the format specified by wait(2). On Windows, this is the // in the format specified by wait(2). On Windows, this is the
// value supplied to the ExitProcess() API or a numeric code // value supplied to the ExitProcess() API or a numeric code
// of the exception that terminated the program. // of the exception that terminated the program.
// regex: A regular expression object to be applied to // matcher_: A matcher that's expected to match the stderr output by the child
// the test's captured standard error output; the death test // process.
// fails if it does not match.
// //
// Argument: // Argument:
// status_ok: true if exit_status is acceptable in the context of // status_ok: true if exit_status is acceptable in the context of
// this particular death test, which fails if it is false // this particular death test, which fails if it is false
// //
// Returns true iff all of the above conditions are met. Otherwise, the // Returns true if and only if all of the above conditions are met. Otherwise,
// first failing condition, in the order given above, is the one that is // the first failing condition, in the order given above, is the one that is
// reported. Also sets the last death test message string. // reported. Also sets the last death test message string.
bool DeathTestImpl::Passed(bool status_ok) { bool DeathTestImpl::Passed(bool status_ok) {
if (!spawned()) if (!spawned())
return false; return false;
const std::string error_message = GetCapturedStderr(); const std::string error_message = GetErrorLogs();
bool success = false; bool success = false;
Message buffer; Message buffer;
...@@ -563,13 +591,15 @@ bool DeathTestImpl::Passed(bool status_ok) { ...@@ -563,13 +591,15 @@ bool DeathTestImpl::Passed(bool status_ok) {
break; break;
case DIED: case DIED:
if (status_ok) { if (status_ok) {
const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); if (matcher_.Matches(error_message)) {
if (matched) {
success = true; success = true;
} else { } else {
std::ostringstream stream;
matcher_.DescribeTo(&stream);
buffer << " Result: died but not with expected error.\n" buffer << " Result: died but not with expected error.\n"
<< " Expected: " << regex()->pattern() << "\n" << " Expected: " << stream.str() << "\n"
<< "Actual msg:\n" << FormatDeathTestOutput(error_message); << "Actual msg:\n"
<< FormatDeathTestOutput(error_message);
} }
} else { } else {
buffer << " Result: died but not with expected exit code:\n" buffer << " Result: died but not with expected exit code:\n"
...@@ -618,11 +648,11 @@ bool DeathTestImpl::Passed(bool status_ok) { ...@@ -618,11 +648,11 @@ bool DeathTestImpl::Passed(bool status_ok) {
// //
class WindowsDeathTest : public DeathTestImpl { class WindowsDeathTest : public DeathTestImpl {
public: public:
WindowsDeathTest(const char* a_statement, WindowsDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
const RE* a_regex, const char* file, int line)
const char* file, : DeathTestImpl(a_statement, std::move(matcher)),
int line) file_(file),
: DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} line_(line) {}
// All of these virtual functions are inherited from DeathTest. // All of these virtual functions are inherited from DeathTest.
virtual int Wait(); virtual int Wait();
...@@ -699,7 +729,7 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { ...@@ -699,7 +729,7 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
const TestInfo* const info = impl->current_test_info(); const TestInfo* const info = impl->current_test_info();
const int death_test_index = info->result()->death_test_count(); const int death_test_index = info->result()->death_test_count();
if (flag != NULL) { if (flag != nullptr) {
// ParseInternalRunDeathTestFlag() has performed all the necessary // ParseInternalRunDeathTestFlag() has performed all the necessary
// processing. // processing.
set_write_fd(flag->write_fd()); set_write_fd(flag->write_fd());
...@@ -708,8 +738,8 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { ...@@ -708,8 +738,8 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
// WindowsDeathTest uses an anonymous pipe to communicate results of // WindowsDeathTest uses an anonymous pipe to communicate results of
// a death test. // a death test.
SECURITY_ATTRIBUTES handles_are_inheritable = { SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES),
sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; nullptr, TRUE};
HANDLE read_handle, write_handle; HANDLE read_handle, write_handle;
GTEST_DEATH_TEST_CHECK_( GTEST_DEATH_TEST_CHECK_(
::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
...@@ -720,13 +750,13 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { ...@@ -720,13 +750,13 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
write_handle_.Reset(write_handle); write_handle_.Reset(write_handle);
event_handle_.Reset(::CreateEvent( event_handle_.Reset(::CreateEvent(
&handles_are_inheritable, &handles_are_inheritable,
TRUE, // The event will automatically reset to non-signaled state. TRUE, // The event will automatically reset to non-signaled state.
FALSE, // The initial state is non-signalled. FALSE, // The initial state is non-signalled.
NULL)); // The even is unnamed. nullptr)); // The even is unnamed.
GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr);
const std::string filter_flag = const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + kFilterFlag + "=" + info->test_suite_name() +
info->test_case_name() + "." + info->name(); "." + info->name();
const std::string internal_flag = const std::string internal_flag =
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
"=" + file_ + "|" + StreamableToString(line_) + "|" + "=" + file_ + "|" + StreamableToString(line_) + "|" +
...@@ -739,10 +769,9 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { ...@@ -739,10 +769,9 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
"|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get())); "|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
char executable_path[_MAX_PATH + 1]; // NOLINT char executable_path[_MAX_PATH + 1]; // NOLINT
GTEST_DEATH_TEST_CHECK_( GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr,
_MAX_PATH + 1 != ::GetModuleFileNameA(NULL, executable_path,
executable_path, _MAX_PATH));
_MAX_PATH));
std::string command_line = std::string command_line =
std::string(::GetCommandLineA()) + " " + filter_flag + " \"" + std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
...@@ -763,33 +792,290 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { ...@@ -763,33 +792,290 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
PROCESS_INFORMATION process_info; PROCESS_INFORMATION process_info;
GTEST_DEATH_TEST_CHECK_(::CreateProcessA( GTEST_DEATH_TEST_CHECK_(
executable_path, ::CreateProcessA(
const_cast<char*>(command_line.c_str()), executable_path, const_cast<char*>(command_line.c_str()),
NULL, // Retuned process handle is not inheritable. nullptr, // Retuned process handle is not inheritable.
NULL, // Retuned thread handle is not inheritable. nullptr, // Retuned thread handle is not inheritable.
TRUE, // Child inherits all inheritable handles (for write_handle_). TRUE, // Child inherits all inheritable handles (for write_handle_).
0x0, // Default creation flags. 0x0, // Default creation flags.
NULL, // Inherit the parent's environment. nullptr, // Inherit the parent's environment.
UnitTest::GetInstance()->original_working_dir(), UnitTest::GetInstance()->original_working_dir(), &startup_info,
&startup_info, &process_info) != FALSE);
&process_info) != FALSE);
child_handle_.Reset(process_info.hProcess); child_handle_.Reset(process_info.hProcess);
::CloseHandle(process_info.hThread); ::CloseHandle(process_info.hThread);
set_spawned(true); set_spawned(true);
return OVERSEE_TEST; return OVERSEE_TEST;
} }
# else // We are not on Windows.
# elif GTEST_OS_FUCHSIA
class FuchsiaDeathTest : public DeathTestImpl {
public:
FuchsiaDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
const char* file, int line)
: DeathTestImpl(a_statement, std::move(matcher)),
file_(file),
line_(line) {}
// All of these virtual functions are inherited from DeathTest.
int Wait() override;
TestRole AssumeRole() override;
std::string GetErrorLogs() override;
private:
// The name of the file in which the death test is located.
const char* const file_;
// The line number on which the death test is located.
const int line_;
// The stderr data captured by the child process.
std::string captured_stderr_;
zx::process child_process_;
zx::channel exception_channel_;
zx::socket stderr_socket_;
};
// Utility class for accumulating command-line arguments.
class Arguments {
public:
Arguments() { args_.push_back(nullptr); }
~Arguments() {
for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
++i) {
free(*i);
}
}
void AddArgument(const char* argument) {
args_.insert(args_.end() - 1, posix::StrDup(argument));
}
template <typename Str>
void AddArguments(const ::std::vector<Str>& arguments) {
for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
i != arguments.end();
++i) {
args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
}
}
char* const* Argv() {
return &args_[0];
}
int size() {
return args_.size() - 1;
}
private:
std::vector<char*> args_;
};
// Waits for the child in a death test to exit, returning its exit
// status, or 0 if no child process exists. As a side effect, sets the
// outcome data member.
int FuchsiaDeathTest::Wait() {
const int kProcessKey = 0;
const int kSocketKey = 1;
const int kExceptionKey = 2;
if (!spawned())
return 0;
// Create a port to wait for socket/task/exception events.
zx_status_t status_zx;
zx::port port;
status_zx = zx::port::create(0, &port);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
// Register to wait for the child process to terminate.
status_zx = child_process_.wait_async(
port, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
// Register to wait for the socket to be readable or closed.
status_zx = stderr_socket_.wait_async(
port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
ZX_WAIT_ASYNC_ONCE);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
// Register to wait for an exception.
status_zx = exception_channel_.wait_async(
port, kExceptionKey, ZX_CHANNEL_READABLE, ZX_WAIT_ASYNC_ONCE);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
bool process_terminated = false;
bool socket_closed = false;
do {
zx_port_packet_t packet = {};
status_zx = port.wait(zx::time::infinite(), &packet);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
if (packet.key == kExceptionKey) {
// Process encountered an exception. Kill it directly rather than
// letting other handlers process the event. We will get a kProcessKey
// event when the process actually terminates.
status_zx = child_process_.kill();
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
} else if (packet.key == kProcessKey) {
// Process terminated.
GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
process_terminated = true;
} else if (packet.key == kSocketKey) {
GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
if (packet.signal.observed & ZX_SOCKET_READABLE) {
// Read data from the socket.
constexpr size_t kBufferSize = 1024;
do {
size_t old_length = captured_stderr_.length();
size_t bytes_read = 0;
captured_stderr_.resize(old_length + kBufferSize);
status_zx = stderr_socket_.read(
0, &captured_stderr_.front() + old_length, kBufferSize,
&bytes_read);
captured_stderr_.resize(old_length + bytes_read);
} while (status_zx == ZX_OK);
if (status_zx == ZX_ERR_PEER_CLOSED) {
socket_closed = true;
} else {
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT);
status_zx = stderr_socket_.wait_async(
port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
ZX_WAIT_ASYNC_ONCE);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
}
} else {
GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_SOCKET_PEER_CLOSED);
socket_closed = true;
}
}
} while (!process_terminated && !socket_closed);
ReadAndInterpretStatusByte();
zx_info_process_t buffer;
status_zx = child_process_.get_info(
ZX_INFO_PROCESS, &buffer, sizeof(buffer), nullptr, nullptr);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
GTEST_DEATH_TEST_CHECK_(buffer.exited);
set_status(buffer.return_code);
return status();
}
// The AssumeRole process for a Fuchsia death test. It creates a child
// process with the same executable as the current process to run the
// death test. The child process is given the --gtest_filter and
// --gtest_internal_run_death_test flags such that it knows to run the
// current death test only.
DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
const UnitTestImpl* const impl = GetUnitTestImpl();
const InternalRunDeathTestFlag* const flag =
impl->internal_run_death_test_flag();
const TestInfo* const info = impl->current_test_info();
const int death_test_index = info->result()->death_test_count();
if (flag != nullptr) {
// ParseInternalRunDeathTestFlag() has performed all the necessary
// processing.
set_write_fd(kFuchsiaReadPipeFd);
return EXECUTE_TEST;
}
// Flush the log buffers since the log streams are shared with the child.
FlushInfoLog();
// Build the child process command line.
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
kFilterFlag + "=" + info->test_suite_name() +
"." + info->name();
const std::string internal_flag =
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
+ file_ + "|"
+ StreamableToString(line_) + "|"
+ StreamableToString(death_test_index);
Arguments args;
args.AddArguments(GetInjectableArgvs());
args.AddArgument(filter_flag.c_str());
args.AddArgument(internal_flag.c_str());
// Build the pipe for communication with the child.
zx_status_t status;
zx_handle_t child_pipe_handle;
int child_pipe_fd;
status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
set_read_fd(child_pipe_fd);
// Set the pipe handle for the child.
fdio_spawn_action_t spawn_actions[2] = {};
fdio_spawn_action_t* add_handle_action = &spawn_actions[0];
add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd);
add_handle_action->h.handle = child_pipe_handle;
// Create a socket pair will be used to receive the child process' stderr.
zx::socket stderr_producer_socket;
status =
zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
GTEST_DEATH_TEST_CHECK_(status >= 0);
int stderr_producer_fd = -1;
status =
fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd);
GTEST_DEATH_TEST_CHECK_(status >= 0);
// Make the stderr socket nonblocking.
GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0);
fdio_spawn_action_t* add_stderr_action = &spawn_actions[1];
add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD;
add_stderr_action->fd.local_fd = stderr_producer_fd;
add_stderr_action->fd.target_fd = STDERR_FILENO;
// Create a child job.
zx_handle_t child_job = ZX_HANDLE_INVALID;
status = zx_job_create(zx_job_default(), 0, & child_job);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
zx_policy_basic_t policy;
policy.condition = ZX_POL_NEW_ANY;
policy.policy = ZX_POL_ACTION_ALLOW;
status = zx_job_set_policy(
child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy, 1);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
// Create an exception channel attached to the |child_job|, to allow
// us to suppress the system default exception handler from firing.
status =
zx_task_create_exception_channel(
child_job, 0, exception_channel_.reset_and_get_address());
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
// Spawn the child process.
status = fdio_spawn_etc(
child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr,
2, spawn_actions, child_process_.reset_and_get_address(), nullptr);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
set_spawned(true);
return OVERSEE_TEST;
}
std::string FuchsiaDeathTest::GetErrorLogs() {
return captured_stderr_;
}
#else // We are neither on Windows, nor on Fuchsia.
// ForkingDeathTest provides implementations for most of the abstract // ForkingDeathTest provides implementations for most of the abstract
// methods of the DeathTest interface. Only the AssumeRole method is // methods of the DeathTest interface. Only the AssumeRole method is
// left undefined. // left undefined.
class ForkingDeathTest : public DeathTestImpl { class ForkingDeathTest : public DeathTestImpl {
public: public:
ForkingDeathTest(const char* statement, const RE* regex); ForkingDeathTest(const char* statement, Matcher<const std::string&> matcher);
// All of these virtual functions are inherited from DeathTest. // All of these virtual functions are inherited from DeathTest.
virtual int Wait(); int Wait() override;
protected: protected:
void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
...@@ -800,9 +1086,9 @@ class ForkingDeathTest : public DeathTestImpl { ...@@ -800,9 +1086,9 @@ class ForkingDeathTest : public DeathTestImpl {
}; };
// Constructs a ForkingDeathTest. // Constructs a ForkingDeathTest.
ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) ForkingDeathTest::ForkingDeathTest(const char* a_statement,
: DeathTestImpl(a_statement, a_regex), Matcher<const std::string&> matcher)
child_pid_(-1) {} : DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {}
// Waits for the child in a death test to exit, returning its exit // Waits for the child in a death test to exit, returning its exit
// status, or 0 if no child process exists. As a side effect, sets the // status, or 0 if no child process exists. As a side effect, sets the
...@@ -823,9 +1109,9 @@ int ForkingDeathTest::Wait() { ...@@ -823,9 +1109,9 @@ int ForkingDeathTest::Wait() {
// in the child process. // in the child process.
class NoExecDeathTest : public ForkingDeathTest { class NoExecDeathTest : public ForkingDeathTest {
public: public:
NoExecDeathTest(const char* a_statement, const RE* a_regex) : NoExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher)
ForkingDeathTest(a_statement, a_regex) { } : ForkingDeathTest(a_statement, std::move(matcher)) {}
virtual TestRole AssumeRole(); TestRole AssumeRole() override;
}; };
// The AssumeRole process for a fork-and-run death test. It implements a // The AssumeRole process for a fork-and-run death test. It implements a
...@@ -878,16 +1164,18 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() { ...@@ -878,16 +1164,18 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
// only this specific death test to be run. // only this specific death test to be run.
class ExecDeathTest : public ForkingDeathTest { class ExecDeathTest : public ForkingDeathTest {
public: public:
ExecDeathTest(const char* a_statement, const RE* a_regex, ExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
const char* file, int line) : const char* file, int line)
ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } : ForkingDeathTest(a_statement, std::move(matcher)),
virtual TestRole AssumeRole(); file_(file),
line_(line) {}
TestRole AssumeRole() override;
private: private:
static ::std::vector<testing::internal::string> static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
GetArgvsForDeathTestChildProcess() { ::std::vector<std::string> args = GetInjectableArgvs();
::std::vector<testing::internal::string> args = GetInjectableArgvs();
# if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_) # if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
::std::vector<testing::internal::string> extra_args = ::std::vector<std::string> extra_args =
GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_(); GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
args.insert(args.end(), extra_args.begin(), extra_args.end()); args.insert(args.end(), extra_args.begin(), extra_args.end());
# endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_) # endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
...@@ -902,9 +1190,7 @@ class ExecDeathTest : public ForkingDeathTest { ...@@ -902,9 +1190,7 @@ class ExecDeathTest : public ForkingDeathTest {
// Utility class for accumulating command-line arguments. // Utility class for accumulating command-line arguments.
class Arguments { class Arguments {
public: public:
Arguments() { Arguments() { args_.push_back(nullptr); }
args_.push_back(NULL);
}
~Arguments() { ~Arguments() {
for (std::vector<char*>::iterator i = args_.begin(); i != args_.end(); for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
...@@ -986,6 +1272,7 @@ static int ExecDeathTestChildMain(void* child_arg) { ...@@ -986,6 +1272,7 @@ static int ExecDeathTestChildMain(void* child_arg) {
} }
# endif // !GTEST_OS_QNX # endif // !GTEST_OS_QNX
# if GTEST_HAS_CLONE
// Two utility routines that together determine the direction the stack // Two utility routines that together determine the direction the stack
// grows. // grows.
// This could be accomplished more elegantly by a single recursive // This could be accomplished more elegantly by a single recursive
...@@ -995,20 +1282,26 @@ static int ExecDeathTestChildMain(void* child_arg) { ...@@ -995,20 +1282,26 @@ static int ExecDeathTestChildMain(void* child_arg) {
// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining // GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
// StackLowerThanAddress into StackGrowsDown, which then doesn't give // StackLowerThanAddress into StackGrowsDown, which then doesn't give
// correct answer. // correct answer.
void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_; static void StackLowerThanAddress(const void* ptr,
void StackLowerThanAddress(const void* ptr, bool* result) { bool* result) GTEST_NO_INLINE_;
// HWAddressSanitizer add a random tag to the MSB of the local variable address,
// making comparison result unpredictable.
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
static void StackLowerThanAddress(const void* ptr, bool* result) {
int dummy; int dummy;
*result = (&dummy < ptr); *result = (&dummy < ptr);
} }
// Make sure AddressSanitizer does not tamper with the stack here. // Make sure AddressSanitizer does not tamper with the stack here.
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
bool StackGrowsDown() { GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
static bool StackGrowsDown() {
int dummy; int dummy;
bool result; bool result;
StackLowerThanAddress(&dummy, &result); StackLowerThanAddress(&dummy, &result);
return result; return result;
} }
# endif // GTEST_HAS_CLONE
// Spawns a child process with the same executable as the current process in // Spawns a child process with the same executable as the current process in
// a thread-safe manner and instructs it to run the death test. The // a thread-safe manner and instructs it to run the death test. The
...@@ -1046,7 +1339,8 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { ...@@ -1046,7 +1339,8 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
fd_flags | FD_CLOEXEC)); fd_flags | FD_CLOEXEC));
struct inheritance inherit = {0}; struct inheritance inherit = {0};
// spawn is a system call. // spawn is a system call.
child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron()); child_pid =
spawn(args.argv[0], 0, nullptr, &inherit, args.argv, GetEnviron());
// Restores the current working directory. // Restores the current working directory.
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
...@@ -1070,9 +1364,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { ...@@ -1070,9 +1364,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
if (!use_fork) { if (!use_fork) {
static const bool stack_grows_down = StackGrowsDown(); static const bool stack_grows_down = StackGrowsDown();
const size_t stack_size = getpagesize(); const auto stack_size = static_cast<size_t>(getpagesize());
// MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0); MAP_ANON | MAP_PRIVATE, -1, 0);
GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
...@@ -1086,8 +1380,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { ...@@ -1086,8 +1380,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
void* const stack_top = void* const stack_top =
static_cast<char*>(stack) + static_cast<char*>(stack) +
(stack_grows_down ? stack_size - kMaxStackAlignment : 0); (stack_grows_down ? stack_size - kMaxStackAlignment : 0);
GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment && GTEST_DEATH_TEST_CHECK_(
reinterpret_cast<intptr_t>(stack_top) % kMaxStackAlignment == 0); static_cast<size_t>(stack_size) > kMaxStackAlignment &&
reinterpret_cast<uintptr_t>(stack_top) % kMaxStackAlignment == 0);
child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
...@@ -1104,7 +1399,7 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { ...@@ -1104,7 +1399,7 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
# endif // GTEST_OS_QNX # endif // GTEST_OS_QNX
# if GTEST_OS_LINUX # if GTEST_OS_LINUX
GTEST_DEATH_TEST_CHECK_SYSCALL_( GTEST_DEATH_TEST_CHECK_SYSCALL_(
sigaction(SIGPROF, &saved_sigprof_action, NULL)); sigaction(SIGPROF, &saved_sigprof_action, nullptr));
# endif // GTEST_OS_LINUX # endif // GTEST_OS_LINUX
GTEST_DEATH_TEST_CHECK_(child_pid != -1); GTEST_DEATH_TEST_CHECK_(child_pid != -1);
...@@ -1122,7 +1417,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { ...@@ -1122,7 +1417,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
const TestInfo* const info = impl->current_test_info(); const TestInfo* const info = impl->current_test_info();
const int death_test_index = info->result()->death_test_count(); const int death_test_index = info->result()->death_test_count();
if (flag != NULL) { if (flag != nullptr) {
set_write_fd(flag->write_fd()); set_write_fd(flag->write_fd());
return EXECUTE_TEST; return EXECUTE_TEST;
} }
...@@ -1133,9 +1428,9 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { ...@@ -1133,9 +1428,9 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
// it be closed when the child process does an exec: // it be closed when the child process does an exec:
GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
const std::string filter_flag = const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" kFilterFlag + "=" + info->test_suite_name() +
+ info->test_case_name() + "." + info->name(); "." + info->name();
const std::string internal_flag = const std::string internal_flag =
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
+ file_ + "|" + StreamableToString(line_) + "|" + file_ + "|" + StreamableToString(line_) + "|"
...@@ -1168,7 +1463,8 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { ...@@ -1168,7 +1463,8 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
// by the "test" argument to its address. If the test should be // by the "test" argument to its address. If the test should be
// skipped, sets that pointer to NULL. Returns true, unless the // skipped, sets that pointer to NULL. Returns true, unless the
// flag is set to an invalid value. // flag is set to an invalid value.
bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, bool DefaultDeathTestFactory::Create(const char* statement,
Matcher<const std::string&> matcher,
const char* file, int line, const char* file, int line,
DeathTest** test) { DeathTest** test) {
UnitTestImpl* const impl = GetUnitTestImpl(); UnitTestImpl* const impl = GetUnitTestImpl();
...@@ -1177,7 +1473,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, ...@@ -1177,7 +1473,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
const int death_test_index = impl->current_test_info() const int death_test_index = impl->current_test_info()
->increment_death_test_count(); ->increment_death_test_count();
if (flag != NULL) { if (flag != nullptr) {
if (death_test_index > flag->index()) { if (death_test_index > flag->index()) {
DeathTest::set_last_death_test_message( DeathTest::set_last_death_test_message(
"Death test count (" + StreamableToString(death_test_index) "Death test count (" + StreamableToString(death_test_index)
...@@ -1188,7 +1484,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, ...@@ -1188,7 +1484,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
if (!(flag->file() == file && flag->line() == line && if (!(flag->file() == file && flag->line() == line &&
flag->index() == death_test_index)) { flag->index() == death_test_index)) {
*test = NULL; *test = nullptr;
return true; return true;
} }
} }
...@@ -1197,15 +1493,22 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, ...@@ -1197,15 +1493,22 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
if (GTEST_FLAG(death_test_style) == "threadsafe" || if (GTEST_FLAG(death_test_style) == "threadsafe" ||
GTEST_FLAG(death_test_style) == "fast") { GTEST_FLAG(death_test_style) == "fast") {
*test = new WindowsDeathTest(statement, regex, file, line); *test = new WindowsDeathTest(statement, std::move(matcher), file, line);
}
# elif GTEST_OS_FUCHSIA
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
GTEST_FLAG(death_test_style) == "fast") {
*test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
} }
# else # else
if (GTEST_FLAG(death_test_style) == "threadsafe") { if (GTEST_FLAG(death_test_style) == "threadsafe") {
*test = new ExecDeathTest(statement, regex, file, line); *test = new ExecDeathTest(statement, std::move(matcher), file, line);
} else if (GTEST_FLAG(death_test_style) == "fast") { } else if (GTEST_FLAG(death_test_style) == "fast") {
*test = new NoExecDeathTest(statement, regex); *test = new NoExecDeathTest(statement, std::move(matcher));
} }
# endif // GTEST_OS_WINDOWS # endif // GTEST_OS_WINDOWS
...@@ -1224,7 +1527,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, ...@@ -1224,7 +1527,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
// Recreates the pipe and event handles from the provided parameters, // Recreates the pipe and event handles from the provided parameters,
// signals the event, and returns a file descriptor wrapped around the pipe // signals the event, and returns a file descriptor wrapped around the pipe
// handle. This function is called in the child process only. // handle. This function is called in the child process only.
int GetStatusFileDescriptor(unsigned int parent_process_id, static int GetStatusFileDescriptor(unsigned int parent_process_id,
size_t write_handle_as_size_t, size_t write_handle_as_size_t,
size_t event_handle_as_size_t) { size_t event_handle_as_size_t) {
AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
...@@ -1235,15 +1538,13 @@ int GetStatusFileDescriptor(unsigned int parent_process_id, ...@@ -1235,15 +1538,13 @@ int GetStatusFileDescriptor(unsigned int parent_process_id,
StreamableToString(parent_process_id)); StreamableToString(parent_process_id));
} }
// TODO(vladl@google.com): Replace the following check with a
// compile-time assertion when available.
GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
const HANDLE write_handle = const HANDLE write_handle =
reinterpret_cast<HANDLE>(write_handle_as_size_t); reinterpret_cast<HANDLE>(write_handle_as_size_t);
HANDLE dup_write_handle; HANDLE dup_write_handle;
// The newly initialized handle is accessible only in in the parent // The newly initialized handle is accessible only in the parent
// process. To obtain one accessible within the child, we need to use // process. To obtain one accessible within the child, we need to use
// DuplicateHandle. // DuplicateHandle.
if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
...@@ -1292,7 +1593,7 @@ int GetStatusFileDescriptor(unsigned int parent_process_id, ...@@ -1292,7 +1593,7 @@ int GetStatusFileDescriptor(unsigned int parent_process_id,
// initialized from the GTEST_FLAG(internal_run_death_test) flag if // initialized from the GTEST_FLAG(internal_run_death_test) flag if
// the flag is specified; otherwise returns NULL. // the flag is specified; otherwise returns NULL.
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
if (GTEST_FLAG(internal_run_death_test) == "") return NULL; if (GTEST_FLAG(internal_run_death_test) == "") return nullptr;
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
// can use it here. // can use it here.
...@@ -1320,6 +1621,16 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { ...@@ -1320,6 +1621,16 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
write_fd = GetStatusFileDescriptor(parent_process_id, write_fd = GetStatusFileDescriptor(parent_process_id,
write_handle_as_size_t, write_handle_as_size_t,
event_handle_as_size_t); event_handle_as_size_t);
# elif GTEST_OS_FUCHSIA
if (fields.size() != 3
|| !ParseNaturalNumber(fields[1], &line)
|| !ParseNaturalNumber(fields[2], &index)) {
DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
+ GTEST_FLAG(internal_run_death_test));
}
# else # else
if (fields.size() != 4 if (fields.size() != 4
......
...@@ -26,28 +26,25 @@ ...@@ -26,28 +26,25 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: keith.ray@gmail.com (Keith Ray)
#include "gtest/gtest-message.h"
#include "gtest/internal/gtest-filepath.h" #include "gtest/internal/gtest-filepath.h"
#include "gtest/internal/gtest-port.h"
#include <stdlib.h> #include <stdlib.h>
#include "gtest/internal/gtest-port.h"
#include "gtest/gtest-message.h"
#if GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS_MOBILE
# include <windows.h> # include <windows.h>
#elif GTEST_OS_WINDOWS #elif GTEST_OS_WINDOWS
# include <direct.h> # include <direct.h>
# include <io.h> # include <io.h>
#elif GTEST_OS_SYMBIAN
// Symbian OpenC has PATH_MAX in sys/syslimits.h
# include <sys/syslimits.h>
#else #else
# include <limits.h> # include <limits.h>
# include <climits> // Some Linux distributions define PATH_MAX here. # include <climits> // Some Linux distributions define PATH_MAX here.
#endif // GTEST_OS_WINDOWS_MOBILE #endif // GTEST_OS_WINDOWS_MOBILE
#include "gtest/internal/gtest-string.h"
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
# define GTEST_PATH_MAX_ _MAX_PATH # define GTEST_PATH_MAX_ _MAX_PATH
#elif defined(PATH_MAX) #elif defined(PATH_MAX)
...@@ -58,8 +55,6 @@ ...@@ -58,8 +55,6 @@
# define GTEST_PATH_MAX_ _POSIX_PATH_MAX # define GTEST_PATH_MAX_ _POSIX_PATH_MAX
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
#include "gtest/internal/gtest-string.h"
namespace testing { namespace testing {
namespace internal { namespace internal {
...@@ -97,13 +92,14 @@ static bool IsPathSeparator(char c) { ...@@ -97,13 +92,14 @@ static bool IsPathSeparator(char c) {
// Returns the current working directory, or "" if unsuccessful. // Returns the current working directory, or "" if unsuccessful.
FilePath FilePath::GetCurrentDir() { FilePath FilePath::GetCurrentDir() {
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT #if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
// Windows CE doesn't have a current directory, so we just return GTEST_OS_WINDOWS_RT || ARDUINO || defined(ESP_PLATFORM)
// These platforms do not have a current directory, so we just return
// something reasonable. // something reasonable.
return FilePath(kCurrentDirectoryString); return FilePath(kCurrentDirectoryString);
#elif GTEST_OS_WINDOWS #elif GTEST_OS_WINDOWS
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
#else #else
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
char* result = getcwd(cwd, sizeof(cwd)); char* result = getcwd(cwd, sizeof(cwd));
...@@ -111,9 +107,9 @@ FilePath FilePath::GetCurrentDir() { ...@@ -111,9 +107,9 @@ FilePath FilePath::GetCurrentDir() {
// getcwd will likely fail in NaCl due to the sandbox, so return something // getcwd will likely fail in NaCl due to the sandbox, so return something
// reasonable. The user may have provided a shim implementation for getcwd, // reasonable. The user may have provided a shim implementation for getcwd,
// however, so fallback only when failure is detected. // however, so fallback only when failure is detected.
return FilePath(result == NULL ? kCurrentDirectoryString : cwd); return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
# endif // GTEST_OS_NACL # endif // GTEST_OS_NACL
return FilePath(result == NULL ? "" : cwd); return FilePath(result == nullptr ? "" : cwd);
#endif // GTEST_OS_WINDOWS_MOBILE #endif // GTEST_OS_WINDOWS_MOBILE
} }
...@@ -130,7 +126,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const { ...@@ -130,7 +126,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const {
return *this; return *this;
} }
// Returns a pointer to the last occurence of a valid path separator in // Returns a pointer to the last occurrence of a valid path separator in
// the FilePath. On Windows, for example, both '/' and '\' are valid path // the FilePath. On Windows, for example, both '/' and '\' are valid path
// separators. Returns NULL if no path separator was found. // separators. Returns NULL if no path separator was found.
const char* FilePath::FindLastPathSeparator() const { const char* FilePath::FindLastPathSeparator() const {
...@@ -138,8 +134,8 @@ const char* FilePath::FindLastPathSeparator() const { ...@@ -138,8 +134,8 @@ const char* FilePath::FindLastPathSeparator() const {
#if GTEST_HAS_ALT_PATH_SEP_ #if GTEST_HAS_ALT_PATH_SEP_
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
// Comparing two pointers of which only one is NULL is undefined. // Comparing two pointers of which only one is NULL is undefined.
if (last_alt_sep != NULL && if (last_alt_sep != nullptr &&
(last_sep == NULL || last_alt_sep > last_sep)) { (last_sep == nullptr || last_alt_sep > last_sep)) {
return last_alt_sep; return last_alt_sep;
} }
#endif #endif
...@@ -167,7 +163,7 @@ FilePath FilePath::RemoveFileName() const { ...@@ -167,7 +163,7 @@ FilePath FilePath::RemoveFileName() const {
const char* const last_sep = FindLastPathSeparator(); const char* const last_sep = FindLastPathSeparator();
std::string dir; std::string dir;
if (last_sep) { if (last_sep) {
dir = std::string(c_str(), last_sep + 1 - c_str()); dir = std::string(c_str(), static_cast<size_t>(last_sep + 1 - c_str()));
} else { } else {
dir = kCurrentDirectoryString; dir = kCurrentDirectoryString;
} }
...@@ -252,9 +248,6 @@ bool FilePath::DirectoryExists() const { ...@@ -252,9 +248,6 @@ bool FilePath::DirectoryExists() const {
// root directory per disk drive.) // root directory per disk drive.)
bool FilePath::IsRootDirectory() const { bool FilePath::IsRootDirectory() const {
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
// TODO(wan@google.com): on Windows a network share like
// \\server\share can be a root directory, although it cannot be the
// current directory. Handle this properly.
return pathname_.length() == 3 && IsAbsolutePath(); return pathname_.length() == 3 && IsAbsolutePath();
#else #else
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
...@@ -326,7 +319,7 @@ bool FilePath::CreateFolder() const { ...@@ -326,7 +319,7 @@ bool FilePath::CreateFolder() const {
#if GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS_MOBILE
FilePath removed_sep(this->RemoveTrailingPathSeparator()); FilePath removed_sep(this->RemoveTrailingPathSeparator());
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
int result = CreateDirectory(unicode, NULL) ? 0 : -1; int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
delete [] unicode; delete [] unicode;
#elif GTEST_OS_WINDOWS #elif GTEST_OS_WINDOWS
int result = _mkdir(pathname_.c_str()); int result = _mkdir(pathname_.c_str());
...@@ -352,9 +345,8 @@ FilePath FilePath::RemoveTrailingPathSeparator() const { ...@@ -352,9 +345,8 @@ FilePath FilePath::RemoveTrailingPathSeparator() const {
// Removes any redundant separators that might be in the pathname. // Removes any redundant separators that might be in the pathname.
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
// redundancies that might be in a pathname involving "." or "..". // redundancies that might be in a pathname involving "." or "..".
// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
void FilePath::Normalize() { void FilePath::Normalize() {
if (pathname_.c_str() == NULL) { if (pathname_.c_str() == nullptr) {
pathname_ = ""; pathname_ = "";
return; return;
} }
......
...@@ -27,24 +27,13 @@ ...@@ -27,24 +27,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Utility functions and classes used by the Google C++ testing framework. // Utility functions and classes used by the Google C++ testing framework.//
//
// Author: wan@google.com (Zhanyong Wan)
//
// This file contains purely Google Test's internal implementation. Please // This file contains purely Google Test's internal implementation. Please
// DO NOT #INCLUDE IT IN A USER PROGRAM. // DO NOT #INCLUDE IT IN A USER PROGRAM.
#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ #ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
#define GTEST_SRC_GTEST_INTERNAL_INL_H_ #define GTEST_SRC_GTEST_INTERNAL_INL_H_
// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
// part of Google Test's implementation; otherwise it's undefined.
#if !GTEST_IMPLEMENTATION_
// If this file is included from the user's code, just say no.
# error "gtest-internal-inl.h is part of Google Test's internal implementation."
# error "It must not be included except by Google Test itself."
#endif // GTEST_IMPLEMENTATION_
#ifndef _WIN32_WCE #ifndef _WIN32_WCE
# include <errno.h> # include <errno.h>
#endif // !_WIN32_WCE #endif // !_WIN32_WCE
...@@ -53,6 +42,7 @@ ...@@ -53,6 +42,7 @@
#include <string.h> // For memmove. #include <string.h> // For memmove.
#include <algorithm> #include <algorithm>
#include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
...@@ -67,9 +57,12 @@ ...@@ -67,9 +57,12 @@
# include <windows.h> // NOLINT # include <windows.h> // NOLINT
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
#include "gtest/gtest.h" // NOLINT #include "gtest/gtest.h"
#include "gtest/gtest-spi.h" #include "gtest/gtest-spi.h"
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
/* class A needs to have dll-interface to be used by clients of class B */)
namespace testing { namespace testing {
// Declares the flags. // Declares the flags.
...@@ -94,6 +87,7 @@ const char kFilterFlag[] = "filter"; ...@@ -94,6 +87,7 @@ const char kFilterFlag[] = "filter";
const char kListTestsFlag[] = "list_tests"; const char kListTestsFlag[] = "list_tests";
const char kOutputFlag[] = "output"; const char kOutputFlag[] = "output";
const char kPrintTimeFlag[] = "print_time"; const char kPrintTimeFlag[] = "print_time";
const char kPrintUTF8Flag[] = "print_utf8";
const char kRandomSeedFlag[] = "random_seed"; const char kRandomSeedFlag[] = "random_seed";
const char kRepeatFlag[] = "repeat"; const char kRepeatFlag[] = "repeat";
const char kShuffleFlag[] = "shuffle"; const char kShuffleFlag[] = "shuffle";
...@@ -105,14 +99,14 @@ const char kFlagfileFlag[] = "flagfile"; ...@@ -105,14 +99,14 @@ const char kFlagfileFlag[] = "flagfile";
// A valid random seed must be in [1, kMaxRandomSeed]. // A valid random seed must be in [1, kMaxRandomSeed].
const int kMaxRandomSeed = 99999; const int kMaxRandomSeed = 99999;
// g_help_flag is true iff the --help flag or an equivalent form is // g_help_flag is true if and only if the --help flag or an equivalent form
// specified on the command line. // is specified on the command line.
GTEST_API_ extern bool g_help_flag; GTEST_API_ extern bool g_help_flag;
// Returns the current time in milliseconds. // Returns the current time in milliseconds.
GTEST_API_ TimeInMillis GetTimeInMillis(); GTEST_API_ TimeInMillis GetTimeInMillis();
// Returns true iff Google Test should use colors in the output. // Returns true if and only if Google Test should use colors in the output.
GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
// Formats the given time in milliseconds as seconds. // Formats the given time in milliseconds as seconds.
...@@ -174,6 +168,7 @@ class GTestFlagSaver { ...@@ -174,6 +168,7 @@ class GTestFlagSaver {
list_tests_ = GTEST_FLAG(list_tests); list_tests_ = GTEST_FLAG(list_tests);
output_ = GTEST_FLAG(output); output_ = GTEST_FLAG(output);
print_time_ = GTEST_FLAG(print_time); print_time_ = GTEST_FLAG(print_time);
print_utf8_ = GTEST_FLAG(print_utf8);
random_seed_ = GTEST_FLAG(random_seed); random_seed_ = GTEST_FLAG(random_seed);
repeat_ = GTEST_FLAG(repeat); repeat_ = GTEST_FLAG(repeat);
shuffle_ = GTEST_FLAG(shuffle); shuffle_ = GTEST_FLAG(shuffle);
...@@ -195,6 +190,7 @@ class GTestFlagSaver { ...@@ -195,6 +190,7 @@ class GTestFlagSaver {
GTEST_FLAG(list_tests) = list_tests_; GTEST_FLAG(list_tests) = list_tests_;
GTEST_FLAG(output) = output_; GTEST_FLAG(output) = output_;
GTEST_FLAG(print_time) = print_time_; GTEST_FLAG(print_time) = print_time_;
GTEST_FLAG(print_utf8) = print_utf8_;
GTEST_FLAG(random_seed) = random_seed_; GTEST_FLAG(random_seed) = random_seed_;
GTEST_FLAG(repeat) = repeat_; GTEST_FLAG(repeat) = repeat_;
GTEST_FLAG(shuffle) = shuffle_; GTEST_FLAG(shuffle) = shuffle_;
...@@ -216,6 +212,7 @@ class GTestFlagSaver { ...@@ -216,6 +212,7 @@ class GTestFlagSaver {
bool list_tests_; bool list_tests_;
std::string output_; std::string output_;
bool print_time_; bool print_time_;
bool print_utf8_;
internal::Int32 random_seed_; internal::Int32 random_seed_;
internal::Int32 repeat_; internal::Int32 repeat_;
bool shuffle_; bool shuffle_;
...@@ -234,7 +231,7 @@ GTEST_API_ std::string CodePointToUtf8(UInt32 code_point); ...@@ -234,7 +231,7 @@ GTEST_API_ std::string CodePointToUtf8(UInt32 code_point);
// Converts a wide string to a narrow string in UTF-8 encoding. // Converts a wide string to a narrow string in UTF-8 encoding.
// The wide string is assumed to have the following encoding: // The wide string is assumed to have the following encoding:
// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) // UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin)
// UTF-32 if sizeof(wchar_t) == 4 (on Linux) // UTF-32 if sizeof(wchar_t) == 4 (on Linux)
// Parameter str points to a null-terminated wide string. // Parameter str points to a null-terminated wide string.
// Parameter num_chars may additionally limit the number // Parameter num_chars may additionally limit the number
...@@ -269,8 +266,8 @@ GTEST_API_ bool ShouldShard(const char* total_shards_str, ...@@ -269,8 +266,8 @@ GTEST_API_ bool ShouldShard(const char* total_shards_str,
GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
// Given the total number of shards, the shard index, and the test id, // Given the total number of shards, the shard index, and the test id,
// returns true iff the test should be run on this shard. The test id is // returns true if and only if the test should be run on this shard. The test id
// some arbitrary but unique non-negative integer assigned to each test // is some arbitrary but unique non-negative integer assigned to each test
// method. Assumes that 0 <= shard_index < total_shards. // method. Assumes that 0 <= shard_index < total_shards.
GTEST_API_ bool ShouldRunTestOnShard( GTEST_API_ bool ShouldRunTestOnShard(
int total_shards, int shard_index, int test_id); int total_shards, int shard_index, int test_id);
...@@ -301,7 +298,8 @@ void ForEach(const Container& c, Functor functor) { ...@@ -301,7 +298,8 @@ void ForEach(const Container& c, Functor functor) {
// in range [0, v.size()). // in range [0, v.size()).
template <typename E> template <typename E>
inline E GetElementOr(const std::vector<E>& v, int i, E default_value) { inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i]; return (i < 0 || i >= static_cast<int>(v.size())) ? default_value
: v[static_cast<size_t>(i)];
} }
// Performs an in-place shuffle of a range of the vector's elements. // Performs an in-place shuffle of a range of the vector's elements.
...@@ -323,8 +321,11 @@ void ShuffleRange(internal::Random* random, int begin, int end, ...@@ -323,8 +321,11 @@ void ShuffleRange(internal::Random* random, int begin, int end,
// http://en.wikipedia.org/wiki/Fisher-Yates_shuffle // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
for (int range_width = end - begin; range_width >= 2; range_width--) { for (int range_width = end - begin; range_width >= 2; range_width--) {
const int last_in_range = begin + range_width - 1; const int last_in_range = begin + range_width - 1;
const int selected = begin + random->Generate(range_width); const int selected =
std::swap((*v)[selected], (*v)[last_in_range]); begin +
static_cast<int>(random->Generate(static_cast<UInt32>(range_width)));
std::swap((*v)[static_cast<size_t>(selected)],
(*v)[static_cast<size_t>(last_in_range)]);
} }
} }
...@@ -351,7 +352,7 @@ class TestPropertyKeyIs { ...@@ -351,7 +352,7 @@ class TestPropertyKeyIs {
// TestPropertyKeyIs has NO default constructor. // TestPropertyKeyIs has NO default constructor.
explicit TestPropertyKeyIs(const std::string& key) : key_(key) {} explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
// Returns true iff the test name of test property matches on key_. // Returns true if and only if the test name of test property matches on key_.
bool operator()(const TestProperty& test_property) const { bool operator()(const TestProperty& test_property) const {
return test_property.key() == key_; return test_property.key() == key_;
} }
...@@ -384,17 +385,17 @@ class GTEST_API_ UnitTestOptions { ...@@ -384,17 +385,17 @@ class GTEST_API_ UnitTestOptions {
// Functions for processing the gtest_filter flag. // Functions for processing the gtest_filter flag.
// Returns true iff the wildcard pattern matches the string. The // Returns true if and only if the wildcard pattern matches the string.
// first ':' or '\0' character in pattern marks the end of it. // The first ':' or '\0' character in pattern marks the end of it.
// //
// This recursive algorithm isn't very efficient, but is clear and // This recursive algorithm isn't very efficient, but is clear and
// works well enough for matching test names, which are short. // works well enough for matching test names, which are short.
static bool PatternMatchesString(const char *pattern, const char *str); static bool PatternMatchesString(const char *pattern, const char *str);
// Returns true iff the user-specified filter matches the test case // Returns true if and only if the user-specified filter matches the test
// name and the test name. // suite name and the test name.
static bool FilterMatchesTest(const std::string &test_case_name, static bool FilterMatchesTest(const std::string& test_suite_name,
const std::string &test_name); const std::string& test_name);
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
// Function for supporting the gtest_catch_exception flag. // Function for supporting the gtest_catch_exception flag.
...@@ -426,7 +427,7 @@ class OsStackTraceGetterInterface { ...@@ -426,7 +427,7 @@ class OsStackTraceGetterInterface {
// in the trace. // in the trace.
// skip_count - the number of top frames to be skipped; doesn't count // skip_count - the number of top frames to be skipped; doesn't count
// against max_depth. // against max_depth.
virtual string CurrentStackTrace(int max_depth, int skip_count) = 0; virtual std::string CurrentStackTrace(int max_depth, int skip_count) = 0;
// UponLeavingGTest() should be called immediately before Google Test calls // UponLeavingGTest() should be called immediately before Google Test calls
// user code. It saves some information about the current stack that // user code. It saves some information about the current stack that
...@@ -446,10 +447,20 @@ class OsStackTraceGetter : public OsStackTraceGetterInterface { ...@@ -446,10 +447,20 @@ class OsStackTraceGetter : public OsStackTraceGetterInterface {
public: public:
OsStackTraceGetter() {} OsStackTraceGetter() {}
virtual string CurrentStackTrace(int max_depth, int skip_count); std::string CurrentStackTrace(int max_depth, int skip_count) override;
virtual void UponLeavingGTest(); void UponLeavingGTest() override;
private: private:
#if GTEST_HAS_ABSL
Mutex mutex_; // Protects all internal state.
// We save the stack frame below the frame that calls user code.
// We do this because the address of the frame immediately below
// the user code changes between the call to UponLeavingGTest()
// and any calls to the stack trace code from within the user code.
void* caller_frame_ = nullptr;
#endif // GTEST_HAS_ABSL
GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
}; };
...@@ -468,7 +479,7 @@ class DefaultGlobalTestPartResultReporter ...@@ -468,7 +479,7 @@ class DefaultGlobalTestPartResultReporter
explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
// Implements the TestPartResultReporterInterface. Reports the test part // Implements the TestPartResultReporterInterface. Reports the test part
// result in the current test. // result in the current test.
virtual void ReportTestPartResult(const TestPartResult& result); void ReportTestPartResult(const TestPartResult& result) override;
private: private:
UnitTestImpl* const unit_test_; UnitTestImpl* const unit_test_;
...@@ -484,7 +495,7 @@ class DefaultPerThreadTestPartResultReporter ...@@ -484,7 +495,7 @@ class DefaultPerThreadTestPartResultReporter
explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
// Implements the TestPartResultReporterInterface. The implementation just // Implements the TestPartResultReporterInterface. The implementation just
// delegates to the current global test part result reporter of *unit_test_. // delegates to the current global test part result reporter of *unit_test_.
virtual void ReportTestPartResult(const TestPartResult& result); void ReportTestPartResult(const TestPartResult& result) override;
private: private:
UnitTestImpl* const unit_test_; UnitTestImpl* const unit_test_;
...@@ -522,22 +533,25 @@ class GTEST_API_ UnitTestImpl { ...@@ -522,22 +533,25 @@ class GTEST_API_ UnitTestImpl {
void SetTestPartResultReporterForCurrentThread( void SetTestPartResultReporterForCurrentThread(
TestPartResultReporterInterface* reporter); TestPartResultReporterInterface* reporter);
// Gets the number of successful test cases. // Gets the number of successful test suites.
int successful_test_case_count() const; int successful_test_suite_count() const;
// Gets the number of failed test cases. // Gets the number of failed test suites.
int failed_test_case_count() const; int failed_test_suite_count() const;
// Gets the number of all test cases. // Gets the number of all test suites.
int total_test_case_count() const; int total_test_suite_count() const;
// Gets the number of all test cases that contain at least one test // Gets the number of all test suites that contain at least one test
// that should run. // that should run.
int test_case_to_run_count() const; int test_suite_to_run_count() const;
// Gets the number of successful tests. // Gets the number of successful tests.
int successful_test_count() const; int successful_test_count() const;
// Gets the number of skipped tests.
int skipped_test_count() const;
// Gets the number of failed tests. // Gets the number of failed tests.
int failed_test_count() const; int failed_test_count() const;
...@@ -563,27 +577,33 @@ class GTEST_API_ UnitTestImpl { ...@@ -563,27 +577,33 @@ class GTEST_API_ UnitTestImpl {
// Gets the elapsed time, in milliseconds. // Gets the elapsed time, in milliseconds.
TimeInMillis elapsed_time() const { return elapsed_time_; } TimeInMillis elapsed_time() const { return elapsed_time_; }
// Returns true iff the unit test passed (i.e. all test cases passed). // Returns true if and only if the unit test passed (i.e. all test suites
// passed).
bool Passed() const { return !Failed(); } bool Passed() const { return !Failed(); }
// Returns true iff the unit test failed (i.e. some test case failed // Returns true if and only if the unit test failed (i.e. some test suite
// or something outside of all tests failed). // failed or something outside of all tests failed).
bool Failed() const { bool Failed() const {
return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); return failed_test_suite_count() > 0 || ad_hoc_test_result()->Failed();
} }
// Gets the i-th test case among all the test cases. i can range from 0 to // Gets the i-th test suite among all the test suites. i can range from 0 to
// total_test_case_count() - 1. If i is not in that range, returns NULL. // total_test_suite_count() - 1. If i is not in that range, returns NULL.
const TestCase* GetTestCase(int i) const { const TestSuite* GetTestSuite(int i) const {
const int index = GetElementOr(test_case_indices_, i, -1); const int index = GetElementOr(test_suite_indices_, i, -1);
return index < 0 ? NULL : test_cases_[i]; return index < 0 ? nullptr : test_suites_[static_cast<size_t>(i)];
} }
// Gets the i-th test case among all the test cases. i can range from 0 to // Legacy API is deprecated but still available
// total_test_case_count() - 1. If i is not in that range, returns NULL. #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
TestCase* GetMutableTestCase(int i) { const TestCase* GetTestCase(int i) const { return GetTestSuite(i); }
const int index = GetElementOr(test_case_indices_, i, -1); #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
return index < 0 ? NULL : test_cases_[index];
// Gets the i-th test suite among all the test suites. i can range from 0 to
// total_test_suite_count() - 1. If i is not in that range, returns NULL.
TestSuite* GetMutableSuiteCase(int i) {
const int index = GetElementOr(test_suite_indices_, i, -1);
return index < 0 ? nullptr : test_suites_[static_cast<size_t>(index)];
} }
// Provides access to the event listener list. // Provides access to the event listener list.
...@@ -620,30 +640,38 @@ class GTEST_API_ UnitTestImpl { ...@@ -620,30 +640,38 @@ class GTEST_API_ UnitTestImpl {
// trace but Bar() and CurrentOsStackTraceExceptTop() won't. // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_; std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
// Finds and returns a TestCase with the given name. If one doesn't // Finds and returns a TestSuite with the given name. If one doesn't
// exist, creates one and returns it. // exist, creates one and returns it.
// //
// Arguments: // Arguments:
// //
// test_case_name: name of the test case // test_suite_name: name of the test suite
// type_param: the name of the test's type parameter, or NULL if // type_param: the name of the test's type parameter, or NULL if
// this is not a typed or a type-parameterized test. // this is not a typed or a type-parameterized test.
// set_up_tc: pointer to the function that sets up the test case // set_up_tc: pointer to the function that sets up the test suite
// tear_down_tc: pointer to the function that tears down the test case // tear_down_tc: pointer to the function that tears down the test suite
TestCase* GetTestCase(const char* test_case_name, TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param,
const char* type_param, internal::SetUpTestSuiteFunc set_up_tc,
Test::SetUpTestCaseFunc set_up_tc, internal::TearDownTestSuiteFunc tear_down_tc);
Test::TearDownTestCaseFunc tear_down_tc);
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
TestCase* GetTestCase(const char* test_case_name, const char* type_param,
internal::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc) {
return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc);
}
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
// Adds a TestInfo to the unit test. // Adds a TestInfo to the unit test.
// //
// Arguments: // Arguments:
// //
// set_up_tc: pointer to the function that sets up the test case // set_up_tc: pointer to the function that sets up the test suite
// tear_down_tc: pointer to the function that tears down the test case // tear_down_tc: pointer to the function that tears down the test suite
// test_info: the TestInfo object // test_info: the TestInfo object
void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc, void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc, internal::TearDownTestSuiteFunc tear_down_tc,
TestInfo* test_info) { TestInfo* test_info) {
// In order to support thread-safe death tests, we need to // In order to support thread-safe death tests, we need to
// remember the original working directory when the test program // remember the original working directory when the test program
...@@ -658,23 +686,20 @@ class GTEST_API_ UnitTestImpl { ...@@ -658,23 +686,20 @@ class GTEST_API_ UnitTestImpl {
<< "Failed to get the current working directory."; << "Failed to get the current working directory.";
} }
GetTestCase(test_info->test_case_name(), GetTestSuite(test_info->test_suite_name(), test_info->type_param(),
test_info->type_param(), set_up_tc, tear_down_tc)
set_up_tc, ->AddTestInfo(test_info);
tear_down_tc)->AddTestInfo(test_info);
} }
#if GTEST_HAS_PARAM_TEST // Returns ParameterizedTestSuiteRegistry object used to keep track of
// Returns ParameterizedTestCaseRegistry object used to keep track of
// value-parameterized tests and instantiate and register them. // value-parameterized tests and instantiate and register them.
internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { internal::ParameterizedTestSuiteRegistry& parameterized_test_registry() {
return parameterized_test_registry_; return parameterized_test_registry_;
} }
#endif // GTEST_HAS_PARAM_TEST
// Sets the TestCase object for the test that's currently running. // Sets the TestSuite object for the test that's currently running.
void set_current_test_case(TestCase* a_current_test_case) { void set_current_test_suite(TestSuite* a_current_test_suite) {
current_test_case_ = a_current_test_case; current_test_suite_ = a_current_test_suite;
} }
// Sets the TestInfo object for the test that's currently running. If // Sets the TestInfo object for the test that's currently running. If
...@@ -685,7 +710,7 @@ class GTEST_API_ UnitTestImpl { ...@@ -685,7 +710,7 @@ class GTEST_API_ UnitTestImpl {
} }
// Registers all parameterized tests defined using TEST_P and // Registers all parameterized tests defined using TEST_P and
// INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter // INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter
// combination. This method can be called more then once; it has guards // combination. This method can be called more then once; it has guards
// protecting from registering the tests more then once. If // protecting from registering the tests more then once. If
// value-parameterized tests are disabled, RegisterParameterizedTests is // value-parameterized tests are disabled, RegisterParameterizedTests is
...@@ -700,7 +725,7 @@ class GTEST_API_ UnitTestImpl { ...@@ -700,7 +725,7 @@ class GTEST_API_ UnitTestImpl {
// Clears the results of all tests, except the ad hoc tests. // Clears the results of all tests, except the ad hoc tests.
void ClearNonAdHocTestResult() { void ClearNonAdHocTestResult() {
ForEach(test_cases_, TestCase::ClearTestCaseResult); ForEach(test_suites_, TestSuite::ClearTestSuiteResult);
} }
// Clears the results of ad-hoc test assertions. // Clears the results of ad-hoc test assertions.
...@@ -709,7 +734,7 @@ class GTEST_API_ UnitTestImpl { ...@@ -709,7 +734,7 @@ class GTEST_API_ UnitTestImpl {
} }
// Adds a TestProperty to the current TestResult object when invoked in a // Adds a TestProperty to the current TestResult object when invoked in a
// context of a test or a test case, or to the global property set. If the // context of a test or a test suite, or to the global property set. If the
// result already contains a property with the same key, the value will be // result already contains a property with the same key, the value will be
// updated. // updated.
void RecordProperty(const TestProperty& test_property); void RecordProperty(const TestProperty& test_property);
...@@ -721,7 +746,7 @@ class GTEST_API_ UnitTestImpl { ...@@ -721,7 +746,7 @@ class GTEST_API_ UnitTestImpl {
// Matches the full name of each test against the user-specified // Matches the full name of each test against the user-specified
// filter to decide whether the test should run, then records the // filter to decide whether the test should run, then records the
// result in each TestCase and TestInfo object. // result in each TestSuite and TestInfo object.
// If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
// based on sharding variables in the environment. // based on sharding variables in the environment.
// Returns the number of tests that should run. // Returns the number of tests that should run.
...@@ -730,7 +755,7 @@ class GTEST_API_ UnitTestImpl { ...@@ -730,7 +755,7 @@ class GTEST_API_ UnitTestImpl {
// Prints the names of the tests matching the user-specified filter flag. // Prints the names of the tests matching the user-specified filter flag.
void ListTestsMatchingFilter(); void ListTestsMatchingFilter();
const TestCase* current_test_case() const { return current_test_case_; } const TestSuite* current_test_suite() const { return current_test_suite_; }
TestInfo* current_test_info() { return current_test_info_; } TestInfo* current_test_info() { return current_test_info_; }
const TestInfo* current_test_info() const { return current_test_info_; } const TestInfo* current_test_info() const { return current_test_info_; }
...@@ -791,11 +816,11 @@ class GTEST_API_ UnitTestImpl { ...@@ -791,11 +816,11 @@ class GTEST_API_ UnitTestImpl {
// Gets the random number generator. // Gets the random number generator.
internal::Random* random() { return &random_; } internal::Random* random() { return &random_; }
// Shuffles all test cases, and the tests within each test case, // Shuffles all test suites, and the tests within each test suite,
// making sure that death tests are still run first. // making sure that death tests are still run first.
void ShuffleTests(); void ShuffleTests();
// Restores the test cases and tests to their order before the first shuffle. // Restores the test suites and tests to their order before the first shuffle.
void UnshuffleTests(); void UnshuffleTests();
// Returns the value of GTEST_FLAG(catch_exceptions) at the moment // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
...@@ -835,33 +860,31 @@ class GTEST_API_ UnitTestImpl { ...@@ -835,33 +860,31 @@ class GTEST_API_ UnitTestImpl {
// before/after the tests are run. // before/after the tests are run.
std::vector<Environment*> environments_; std::vector<Environment*> environments_;
// The vector of TestCases in their original order. It owns the // The vector of TestSuites in their original order. It owns the
// elements in the vector. // elements in the vector.
std::vector<TestCase*> test_cases_; std::vector<TestSuite*> test_suites_;
// Provides a level of indirection for the test case list to allow // Provides a level of indirection for the test suite list to allow
// easy shuffling and restoring the test case order. The i-th // easy shuffling and restoring the test suite order. The i-th
// element of this vector is the index of the i-th test case in the // element of this vector is the index of the i-th test suite in the
// shuffled order. // shuffled order.
std::vector<int> test_case_indices_; std::vector<int> test_suite_indices_;
#if GTEST_HAS_PARAM_TEST
// ParameterizedTestRegistry object used to register value-parameterized // ParameterizedTestRegistry object used to register value-parameterized
// tests. // tests.
internal::ParameterizedTestCaseRegistry parameterized_test_registry_; internal::ParameterizedTestSuiteRegistry parameterized_test_registry_;
// Indicates whether RegisterParameterizedTests() has been called already. // Indicates whether RegisterParameterizedTests() has been called already.
bool parameterized_tests_registered_; bool parameterized_tests_registered_;
#endif // GTEST_HAS_PARAM_TEST
// Index of the last death test case registered. Initially -1. // Index of the last death test suite registered. Initially -1.
int last_death_test_case_; int last_death_test_suite_;
// This points to the TestCase for the currently running test. It // This points to the TestSuite for the currently running test. It
// changes as Google Test goes through one test case after another. // changes as Google Test goes through one test suite after another.
// When no test is running, this is set to NULL and Google Test // When no test is running, this is set to NULL and Google Test
// stores assertion results in ad_hoc_test_result_. Initially NULL. // stores assertion results in ad_hoc_test_result_. Initially NULL.
TestCase* current_test_case_; TestSuite* current_test_suite_;
// This points to the TestInfo for the currently running test. It // This points to the TestInfo for the currently running test. It
// changes as Google Test goes through one test after another. When // changes as Google Test goes through one test after another. When
...@@ -889,7 +912,7 @@ class GTEST_API_ UnitTestImpl { ...@@ -889,7 +912,7 @@ class GTEST_API_ UnitTestImpl {
// desired. // desired.
OsStackTraceGetterInterface* os_stack_trace_getter_; OsStackTraceGetterInterface* os_stack_trace_getter_;
// True iff PostFlagParsingInit() has been called. // True if and only if PostFlagParsingInit() has been called.
bool post_flag_parse_init_performed_; bool post_flag_parse_init_performed_;
// The random number seed used at the beginning of the test run. // The random number seed used at the beginning of the test run.
...@@ -908,8 +931,8 @@ class GTEST_API_ UnitTestImpl { ...@@ -908,8 +931,8 @@ class GTEST_API_ UnitTestImpl {
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
// The decomposed components of the gtest_internal_run_death_test flag, // The decomposed components of the gtest_internal_run_death_test flag,
// parsed when RUN_ALL_TESTS is called. // parsed when RUN_ALL_TESTS is called.
internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_; std::unique_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_; std::unique_ptr<internal::DeathTestFactory> death_test_factory_;
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
// A per-thread stack of traces created by the SCOPED_TRACE() macro. // A per-thread stack of traces created by the SCOPED_TRACE() macro.
...@@ -992,8 +1015,6 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) { ...@@ -992,8 +1015,6 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
const bool parse_success = *end == '\0' && errno == 0; const bool parse_success = *end == '\0' && errno == 0;
// TODO(vladl@google.com): Convert this to compile time assertion when it is
// available.
GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
const Integer result = static_cast<Integer>(parsed); const Integer result = static_cast<Integer>(parsed);
...@@ -1032,7 +1053,7 @@ class TestResultAccessor { ...@@ -1032,7 +1053,7 @@ class TestResultAccessor {
#if GTEST_CAN_STREAM_RESULTS_ #if GTEST_CAN_STREAM_RESULTS_
// Streams test results to the given port on the given host machine. // Streams test results to the given port on the given host machine.
class GTEST_API_ StreamingListener : public EmptyTestEventListener { class StreamingListener : public EmptyTestEventListener {
public: public:
// Abstract base class for writing strings to a socket. // Abstract base class for writing strings to a socket.
class AbstractSocketWriter { class AbstractSocketWriter {
...@@ -1040,37 +1061,35 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { ...@@ -1040,37 +1061,35 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener {
virtual ~AbstractSocketWriter() {} virtual ~AbstractSocketWriter() {}
// Sends a string to the socket. // Sends a string to the socket.
virtual void Send(const string& message) = 0; virtual void Send(const std::string& message) = 0;
// Closes the socket. // Closes the socket.
virtual void CloseConnection() {} virtual void CloseConnection() {}
// Sends a string and a newline to the socket. // Sends a string and a newline to the socket.
void SendLn(const string& message) { void SendLn(const std::string& message) { Send(message + "\n"); }
Send(message + "\n");
}
}; };
// Concrete class for actually writing strings to a socket. // Concrete class for actually writing strings to a socket.
class SocketWriter : public AbstractSocketWriter { class SocketWriter : public AbstractSocketWriter {
public: public:
SocketWriter(const string& host, const string& port) SocketWriter(const std::string& host, const std::string& port)
: sockfd_(-1), host_name_(host), port_num_(port) { : sockfd_(-1), host_name_(host), port_num_(port) {
MakeConnection(); MakeConnection();
} }
virtual ~SocketWriter() { ~SocketWriter() override {
if (sockfd_ != -1) if (sockfd_ != -1)
CloseConnection(); CloseConnection();
} }
// Sends a string to the socket. // Sends a string to the socket.
virtual void Send(const string& message) { void Send(const std::string& message) override {
GTEST_CHECK_(sockfd_ != -1) GTEST_CHECK_(sockfd_ != -1)
<< "Send() can be called only when there is a connection."; << "Send() can be called only when there is a connection.";
const int len = static_cast<int>(message.length()); const auto len = static_cast<size_t>(message.length());
if (write(sockfd_, message.c_str(), len) != len) { if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
GTEST_LOG_(WARNING) GTEST_LOG_(WARNING)
<< "stream_result_to: failed to stream to " << "stream_result_to: failed to stream to "
<< host_name_ << ":" << port_num_; << host_name_ << ":" << port_num_;
...@@ -1082,7 +1101,7 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { ...@@ -1082,7 +1101,7 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener {
void MakeConnection(); void MakeConnection();
// Closes the socket. // Closes the socket.
void CloseConnection() { void CloseConnection() override {
GTEST_CHECK_(sockfd_ != -1) GTEST_CHECK_(sockfd_ != -1)
<< "CloseConnection() can be called only when there is a connection."; << "CloseConnection() can be called only when there is a connection.";
...@@ -1091,26 +1110,28 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { ...@@ -1091,26 +1110,28 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener {
} }
int sockfd_; // socket file descriptor int sockfd_; // socket file descriptor
const string host_name_; const std::string host_name_;
const string port_num_; const std::string port_num_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter); GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter);
}; // class SocketWriter }; // class SocketWriter
// Escapes '=', '&', '%', and '\n' characters in str as "%xx". // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
static string UrlEncode(const char* str); static std::string UrlEncode(const char* str);
StreamingListener(const string& host, const string& port) StreamingListener(const std::string& host, const std::string& port)
: socket_writer_(new SocketWriter(host, port)) { Start(); } : socket_writer_(new SocketWriter(host, port)) {
Start();
}
explicit StreamingListener(AbstractSocketWriter* socket_writer) explicit StreamingListener(AbstractSocketWriter* socket_writer)
: socket_writer_(socket_writer) { Start(); } : socket_writer_(socket_writer) { Start(); }
void OnTestProgramStart(const UnitTest& /* unit_test */) { void OnTestProgramStart(const UnitTest& /* unit_test */) override {
SendLn("event=TestProgramStart"); SendLn("event=TestProgramStart");
} }
void OnTestProgramEnd(const UnitTest& unit_test) { void OnTestProgramEnd(const UnitTest& unit_test) override {
// Note that Google Test current only report elapsed time for each // Note that Google Test current only report elapsed time for each
// test iteration, not for the entire test program. // test iteration, not for the entire test program.
SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed())); SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
...@@ -1119,42 +1140,47 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { ...@@ -1119,42 +1140,47 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener {
socket_writer_->CloseConnection(); socket_writer_->CloseConnection();
} }
void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { void OnTestIterationStart(const UnitTest& /* unit_test */,
int iteration) override {
SendLn("event=TestIterationStart&iteration=" + SendLn("event=TestIterationStart&iteration=" +
StreamableToString(iteration)); StreamableToString(iteration));
} }
void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { void OnTestIterationEnd(const UnitTest& unit_test,
int /* iteration */) override {
SendLn("event=TestIterationEnd&passed=" + SendLn("event=TestIterationEnd&passed=" +
FormatBool(unit_test.Passed()) + "&elapsed_time=" + FormatBool(unit_test.Passed()) + "&elapsed_time=" +
StreamableToString(unit_test.elapsed_time()) + "ms"); StreamableToString(unit_test.elapsed_time()) + "ms");
} }
void OnTestCaseStart(const TestCase& test_case) { // Note that "event=TestCaseStart" is a wire format and has to remain
// "case" for compatibilty
void OnTestCaseStart(const TestCase& test_case) override {
SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
} }
void OnTestCaseEnd(const TestCase& test_case) { // Note that "event=TestCaseEnd" is a wire format and has to remain
SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) // "case" for compatibilty
+ "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) void OnTestCaseEnd(const TestCase& test_case) override {
+ "ms"); SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) +
"&elapsed_time=" + StreamableToString(test_case.elapsed_time()) +
"ms");
} }
void OnTestStart(const TestInfo& test_info) { void OnTestStart(const TestInfo& test_info) override {
SendLn(std::string("event=TestStart&name=") + test_info.name()); SendLn(std::string("event=TestStart&name=") + test_info.name());
} }
void OnTestEnd(const TestInfo& test_info) { void OnTestEnd(const TestInfo& test_info) override {
SendLn("event=TestEnd&passed=" + SendLn("event=TestEnd&passed=" +
FormatBool((test_info.result())->Passed()) + FormatBool((test_info.result())->Passed()) +
"&elapsed_time=" + "&elapsed_time=" +
StreamableToString((test_info.result())->elapsed_time()) + "ms"); StreamableToString((test_info.result())->elapsed_time()) + "ms");
} }
void OnTestPartResult(const TestPartResult& test_part_result) { void OnTestPartResult(const TestPartResult& test_part_result) override {
const char* file_name = test_part_result.file_name(); const char* file_name = test_part_result.file_name();
if (file_name == NULL) if (file_name == nullptr) file_name = "";
file_name = "";
SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
"&line=" + StreamableToString(test_part_result.line_number()) + "&line=" + StreamableToString(test_part_result.line_number()) +
"&message=" + UrlEncode(test_part_result.message())); "&message=" + UrlEncode(test_part_result.message()));
...@@ -1162,15 +1188,15 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { ...@@ -1162,15 +1188,15 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener {
private: private:
// Sends the given message and a newline to the socket. // Sends the given message and a newline to the socket.
void SendLn(const string& message) { socket_writer_->SendLn(message); } void SendLn(const std::string& message) { socket_writer_->SendLn(message); }
// Called at the start of streaming to notify the receiver what // Called at the start of streaming to notify the receiver what
// protocol we are using. // protocol we are using.
void Start() { SendLn("gtest_streaming_protocol_version=1.0"); } void Start() { SendLn("gtest_streaming_protocol_version=1.0"); }
string FormatBool(bool value) { return value ? "1" : "0"; } std::string FormatBool(bool value) { return value ? "1" : "0"; }
const scoped_ptr<AbstractSocketWriter> socket_writer_; const std::unique_ptr<AbstractSocketWriter> socket_writer_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
}; // class StreamingListener }; // class StreamingListener
...@@ -1180,4 +1206,6 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { ...@@ -1180,4 +1206,6 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener {
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ #endif // GTEST_SRC_GTEST_INTERNAL_INL_H_
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// The Google C++ Testing and Mocking Framework (Google Test)
//
// This file implements just enough of the matcher interface to allow
// EXPECT_DEATH and friends to accept a matcher argument.
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-port.h"
#include "gtest/gtest-matchers.h"
#include <string>
namespace testing {
// Constructs a matcher that matches a const std::string& whose value is
// equal to s.
Matcher<const std::string&>::Matcher(const std::string& s) { *this = Eq(s); }
// Constructs a matcher that matches a const std::string& whose value is
// equal to s.
Matcher<const std::string&>::Matcher(const char* s) {
*this = Eq(std::string(s));
}
// Constructs a matcher that matches a std::string whose value is equal to
// s.
Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
// Constructs a matcher that matches a std::string whose value is equal to
// s.
Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); }
#if GTEST_HAS_ABSL
// Constructs a matcher that matches a const absl::string_view& whose value is
// equal to s.
Matcher<const absl::string_view&>::Matcher(const std::string& s) {
*this = Eq(s);
}
// Constructs a matcher that matches a const absl::string_view& whose value is
// equal to s.
Matcher<const absl::string_view&>::Matcher(const char* s) {
*this = Eq(std::string(s));
}
// Constructs a matcher that matches a const absl::string_view& whose value is
// equal to s.
Matcher<const absl::string_view&>::Matcher(absl::string_view s) {
*this = Eq(std::string(s));
}
// Constructs a matcher that matches a absl::string_view whose value is equal to
// s.
Matcher<absl::string_view>::Matcher(const std::string& s) { *this = Eq(s); }
// Constructs a matcher that matches a absl::string_view whose value is equal to
// s.
Matcher<absl::string_view>::Matcher(const char* s) {
*this = Eq(std::string(s));
}
// Constructs a matcher that matches a absl::string_view whose value is equal to
// s.
Matcher<absl::string_view>::Matcher(absl::string_view s) {
*this = Eq(std::string(s));
}
#endif // GTEST_HAS_ABSL
} // namespace testing
...@@ -26,22 +26,25 @@ ...@@ -26,22 +26,25 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#include <limits.h> #include <limits.h>
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <fstream> #include <fstream>
#include <memory>
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
# include <windows.h> # include <windows.h>
# include <io.h> # include <io.h>
# include <sys/stat.h> # include <sys/stat.h>
# include <map> // Used in ThreadLocal. # include <map> // Used in ThreadLocal.
# ifdef _MSC_VER
# include <crtdbg.h>
# endif // _MSC_VER
#else #else
# include <unistd.h> # include <unistd.h>
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
...@@ -52,6 +55,14 @@ ...@@ -52,6 +55,14 @@
# include <mach/vm_map.h> # include <mach/vm_map.h>
#endif // GTEST_OS_MAC #endif // GTEST_OS_MAC
#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
GTEST_OS_NETBSD || GTEST_OS_OPENBSD
# include <sys/sysctl.h>
# if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
# include <sys/user.h>
# endif
#endif
#if GTEST_OS_QNX #if GTEST_OS_QNX
# include <devctl.h> # include <devctl.h>
# include <fcntl.h> # include <fcntl.h>
...@@ -63,19 +74,16 @@ ...@@ -63,19 +74,16 @@
# include <sys/types.h> # include <sys/types.h>
#endif // GTEST_OS_AIX #endif // GTEST_OS_AIX
#if GTEST_OS_FUCHSIA
# include <zircon/process.h>
# include <zircon/syscalls.h>
#endif // GTEST_OS_FUCHSIA
#include "gtest/gtest-spi.h" #include "gtest/gtest-spi.h"
#include "gtest/gtest-message.h" #include "gtest/gtest-message.h"
#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick exists to
// prevent the accidental inclusion of gtest-internal-inl.h in the
// user's code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
namespace testing { namespace testing {
namespace internal { namespace internal {
...@@ -93,7 +101,7 @@ const int kStdErrFileno = STDERR_FILENO; ...@@ -93,7 +101,7 @@ const int kStdErrFileno = STDERR_FILENO;
namespace { namespace {
template <typename T> template <typename T>
T ReadProcFileField(const string& filename, int field) { T ReadProcFileField(const std::string& filename, int field) {
std::string dummy; std::string dummy;
std::ifstream file(filename.c_str()); std::ifstream file(filename.c_str());
while (field-- > 0) { while (field-- > 0) {
...@@ -107,9 +115,9 @@ T ReadProcFileField(const string& filename, int field) { ...@@ -107,9 +115,9 @@ T ReadProcFileField(const string& filename, int field) {
// Returns the number of active threads, or 0 when there is an error. // Returns the number of active threads, or 0 when there is an error.
size_t GetThreadCount() { size_t GetThreadCount() {
const string filename = const std::string filename =
(Message() << "/proc/" << getpid() << "/stat").GetString(); (Message() << "/proc/" << getpid() << "/stat").GetString();
return ReadProcFileField<int>(filename, 19); return ReadProcFileField<size_t>(filename, 19);
} }
#elif GTEST_OS_MAC #elif GTEST_OS_MAC
...@@ -131,6 +139,81 @@ size_t GetThreadCount() { ...@@ -131,6 +139,81 @@ size_t GetThreadCount() {
} }
} }
#elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
GTEST_OS_NETBSD
#if GTEST_OS_NETBSD
#undef KERN_PROC
#define KERN_PROC KERN_PROC2
#define kinfo_proc kinfo_proc2
#endif
#if GTEST_OS_DRAGONFLY
#define KP_NLWP(kp) (kp.kp_nthreads)
#elif GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
#define KP_NLWP(kp) (kp.ki_numthreads)
#elif GTEST_OS_NETBSD
#define KP_NLWP(kp) (kp.p_nlwps)
#endif
// Returns the number of threads running in the process, or 0 to indicate that
// we cannot detect it.
size_t GetThreadCount() {
int mib[] = {
CTL_KERN,
KERN_PROC,
KERN_PROC_PID,
getpid(),
#if GTEST_OS_NETBSD
sizeof(struct kinfo_proc),
1,
#endif
};
u_int miblen = sizeof(mib) / sizeof(mib[0]);
struct kinfo_proc info;
size_t size = sizeof(info);
if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
return 0;
}
return static_cast<size_t>(KP_NLWP(info));
}
#elif GTEST_OS_OPENBSD
// Returns the number of threads running in the process, or 0 to indicate that
// we cannot detect it.
size_t GetThreadCount() {
int mib[] = {
CTL_KERN,
KERN_PROC,
KERN_PROC_PID | KERN_PROC_SHOW_THREADS,
getpid(),
sizeof(struct kinfo_proc),
0,
};
u_int miblen = sizeof(mib) / sizeof(mib[0]);
// get number of structs
size_t size;
if (sysctl(mib, miblen, NULL, &size, NULL, 0)) {
return 0;
}
mib[5] = size / mib[4];
// populate array of structs
struct kinfo_proc info[mib[5]];
if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
return 0;
}
// exclude empty members
int nthreads = 0;
for (int i = 0; i < size / mib[4]; i++) {
if (info[i].p_tid != -1)
nthreads++;
}
return nthreads;
}
#elif GTEST_OS_QNX #elif GTEST_OS_QNX
// Returns the number of threads running in the process, or 0 to indicate that // Returns the number of threads running in the process, or 0 to indicate that
...@@ -142,7 +225,7 @@ size_t GetThreadCount() { ...@@ -142,7 +225,7 @@ size_t GetThreadCount() {
} }
procfs_info process_info; procfs_info process_info;
const int status = const int status =
devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL); devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), nullptr);
close(fd); close(fd);
if (status == EOK) { if (status == EOK) {
return static_cast<size_t>(process_info.num_threads); return static_cast<size_t>(process_info.num_threads);
...@@ -156,7 +239,7 @@ size_t GetThreadCount() { ...@@ -156,7 +239,7 @@ size_t GetThreadCount() {
size_t GetThreadCount() { size_t GetThreadCount() {
struct procentry64 entry; struct procentry64 entry;
pid_t pid = getpid(); pid_t pid = getpid();
int status = getprocs64(&entry, sizeof(entry), NULL, 0, &pid, 1); int status = getprocs64(&entry, sizeof(entry), nullptr, 0, &pid, 1);
if (status == 1) { if (status == 1) {
return entry.pi_thcount; return entry.pi_thcount;
} else { } else {
...@@ -164,6 +247,25 @@ size_t GetThreadCount() { ...@@ -164,6 +247,25 @@ size_t GetThreadCount() {
} }
} }
#elif GTEST_OS_FUCHSIA
size_t GetThreadCount() {
int dummy_buffer;
size_t avail;
zx_status_t status = zx_object_get_info(
zx_process_self(),
ZX_INFO_PROCESS_THREADS,
&dummy_buffer,
0,
nullptr,
&avail);
if (status == ZX_OK) {
return avail;
} else {
return 0;
}
}
#else #else
size_t GetThreadCount() { size_t GetThreadCount() {
...@@ -177,7 +279,7 @@ size_t GetThreadCount() { ...@@ -177,7 +279,7 @@ size_t GetThreadCount() {
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS #if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
void SleepMilliseconds(int n) { void SleepMilliseconds(int n) {
::Sleep(n); ::Sleep(static_cast<DWORD>(n));
} }
AutoHandle::AutoHandle() AutoHandle::AutoHandle()
...@@ -215,15 +317,15 @@ void AutoHandle::Reset(HANDLE handle) { ...@@ -215,15 +317,15 @@ void AutoHandle::Reset(HANDLE handle) {
bool AutoHandle::IsCloseable() const { bool AutoHandle::IsCloseable() const {
// Different Windows APIs may use either of these values to represent an // Different Windows APIs may use either of these values to represent an
// invalid handle. // invalid handle.
return handle_ != NULL && handle_ != INVALID_HANDLE_VALUE; return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
} }
Notification::Notification() Notification::Notification()
: event_(::CreateEvent(NULL, // Default security attributes. : event_(::CreateEvent(nullptr, // Default security attributes.
TRUE, // Do not reset automatically. TRUE, // Do not reset automatically.
FALSE, // Initially unset. FALSE, // Initially unset.
NULL)) { // Anonymous event. nullptr)) { // Anonymous event.
GTEST_CHECK_(event_.Get() != NULL); GTEST_CHECK_(event_.Get() != nullptr);
} }
void Notification::Notify() { void Notification::Notify() {
...@@ -246,13 +348,10 @@ Mutex::Mutex() ...@@ -246,13 +348,10 @@ Mutex::Mutex()
Mutex::~Mutex() { Mutex::~Mutex() {
// Static mutexes are leaked intentionally. It is not thread-safe to try // Static mutexes are leaked intentionally. It is not thread-safe to try
// to clean them up. // to clean them up.
// TODO(yukawa): Switch to Slim Reader/Writer (SRW) Locks, which requires
// nothing to clean it up but is available only on Vista and later.
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa904937.aspx
if (type_ == kDynamic) { if (type_ == kDynamic) {
::DeleteCriticalSection(critical_section_); ::DeleteCriticalSection(critical_section_);
delete critical_section_; delete critical_section_;
critical_section_ = NULL; critical_section_ = nullptr;
} }
} }
...@@ -279,6 +378,41 @@ void Mutex::AssertHeld() { ...@@ -279,6 +378,41 @@ void Mutex::AssertHeld() {
<< "The current thread is not holding the mutex @" << this; << "The current thread is not holding the mutex @" << this;
} }
namespace {
#ifdef _MSC_VER
// Use the RAII idiom to flag mem allocs that are intentionally never
// deallocated. The motivation is to silence the false positive mem leaks
// that are reported by the debug version of MS's CRT which can only detect
// if an alloc is missing a matching deallocation.
// Example:
// MemoryIsNotDeallocated memory_is_not_deallocated;
// critical_section_ = new CRITICAL_SECTION;
//
class MemoryIsNotDeallocated
{
public:
MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
// Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
// doesn't report mem leak if there's no matching deallocation.
_CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
}
~MemoryIsNotDeallocated() {
// Restore the original _CRTDBG_ALLOC_MEM_DF flag
_CrtSetDbgFlag(old_crtdbg_flag_);
}
private:
int old_crtdbg_flag_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated);
};
#endif // _MSC_VER
} // namespace
// Initializes owner_thread_id_ and critical_section_ in static mutexes. // Initializes owner_thread_id_ and critical_section_ in static mutexes.
void Mutex::ThreadSafeLazyInit() { void Mutex::ThreadSafeLazyInit() {
// Dynamic mutexes are initialized in the constructor. // Dynamic mutexes are initialized in the constructor.
...@@ -289,7 +423,13 @@ void Mutex::ThreadSafeLazyInit() { ...@@ -289,7 +423,13 @@ void Mutex::ThreadSafeLazyInit() {
// If critical_section_init_phase_ was 0 before the exchange, we // If critical_section_init_phase_ was 0 before the exchange, we
// are the first to test it and need to perform the initialization. // are the first to test it and need to perform the initialization.
owner_thread_id_ = 0; owner_thread_id_ = 0;
critical_section_ = new CRITICAL_SECTION; {
// Use RAII to flag that following mem alloc is never deallocated.
#ifdef _MSC_VER
MemoryIsNotDeallocated memory_is_not_deallocated;
#endif // _MSC_VER
critical_section_ = new CRITICAL_SECTION;
}
::InitializeCriticalSection(critical_section_); ::InitializeCriticalSection(critical_section_);
// Updates the critical_section_init_phase_ to 2 to signal // Updates the critical_section_init_phase_ to 2 to signal
// initialization complete. // initialization complete.
...@@ -328,17 +468,16 @@ class ThreadWithParamSupport : public ThreadWithParamBase { ...@@ -328,17 +468,16 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
Notification* thread_can_start) { Notification* thread_can_start) {
ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start); ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
DWORD thread_id; DWORD thread_id;
// TODO(yukawa): Consider to use _beginthreadex instead.
HANDLE thread_handle = ::CreateThread( HANDLE thread_handle = ::CreateThread(
NULL, // Default security. nullptr, // Default security.
0, // Default stack size. 0, // Default stack size.
&ThreadWithParamSupport::ThreadMain, &ThreadWithParamSupport::ThreadMain,
param, // Parameter to ThreadMainStatic param, // Parameter to ThreadMainStatic
0x0, // Default creation flags. 0x0, // Default creation flags.
&thread_id); // Need a valid pointer for the call to work under Win98. &thread_id); // Need a valid pointer for the call to work under Win98.
GTEST_CHECK_(thread_handle != NULL) << "CreateThread failed with error " GTEST_CHECK_(thread_handle != nullptr)
<< ::GetLastError() << "."; << "CreateThread failed with error " << ::GetLastError() << ".";
if (thread_handle == NULL) { if (thread_handle == nullptr) {
delete param; delete param;
} }
return thread_handle; return thread_handle;
...@@ -350,15 +489,15 @@ class ThreadWithParamSupport : public ThreadWithParamBase { ...@@ -350,15 +489,15 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
: runnable_(runnable), : runnable_(runnable),
thread_can_start_(thread_can_start) { thread_can_start_(thread_can_start) {
} }
scoped_ptr<Runnable> runnable_; std::unique_ptr<Runnable> runnable_;
// Does not own. // Does not own.
Notification* thread_can_start_; Notification* thread_can_start_;
}; };
static DWORD WINAPI ThreadMain(void* ptr) { static DWORD WINAPI ThreadMain(void* ptr) {
// Transfers ownership. // Transfers ownership.
scoped_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr)); std::unique_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
if (param->thread_can_start_ != NULL) if (param->thread_can_start_ != nullptr)
param->thread_can_start_->WaitForNotification(); param->thread_can_start_->WaitForNotification();
param->runnable_->Run(); param->runnable_->Run();
return 0; return 0;
...@@ -416,7 +555,7 @@ class ThreadLocalRegistryImpl { ...@@ -416,7 +555,7 @@ class ThreadLocalRegistryImpl {
thread_local_values thread_local_values
.insert(std::make_pair( .insert(std::make_pair(
thread_local_instance, thread_local_instance,
linked_ptr<ThreadLocalValueHolderBase>( std::shared_ptr<ThreadLocalValueHolderBase>(
thread_local_instance->NewValueForCurrentThread()))) thread_local_instance->NewValueForCurrentThread())))
.first; .first;
} }
...@@ -425,7 +564,7 @@ class ThreadLocalRegistryImpl { ...@@ -425,7 +564,7 @@ class ThreadLocalRegistryImpl {
static void OnThreadLocalDestroyed( static void OnThreadLocalDestroyed(
const ThreadLocalBase* thread_local_instance) { const ThreadLocalBase* thread_local_instance) {
std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders; std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
// Clean up the ThreadLocalValues data structure while holding the lock, but // Clean up the ThreadLocalValues data structure while holding the lock, but
// defer the destruction of the ThreadLocalValueHolderBases. // defer the destruction of the ThreadLocalValueHolderBases.
{ {
...@@ -453,7 +592,7 @@ class ThreadLocalRegistryImpl { ...@@ -453,7 +592,7 @@ class ThreadLocalRegistryImpl {
static void OnThreadExit(DWORD thread_id) { static void OnThreadExit(DWORD thread_id) {
GTEST_CHECK_(thread_id != 0) << ::GetLastError(); GTEST_CHECK_(thread_id != 0) << ::GetLastError();
std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders; std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
// Clean up the ThreadIdToThreadLocals data structure while holding the // Clean up the ThreadIdToThreadLocals data structure while holding the
// lock, but defer the destruction of the ThreadLocalValueHolderBases. // lock, but defer the destruction of the ThreadLocalValueHolderBases.
{ {
...@@ -480,7 +619,8 @@ class ThreadLocalRegistryImpl { ...@@ -480,7 +619,8 @@ class ThreadLocalRegistryImpl {
private: private:
// In a particular thread, maps a ThreadLocal object to its value. // In a particular thread, maps a ThreadLocal object to its value.
typedef std::map<const ThreadLocalBase*, typedef std::map<const ThreadLocalBase*,
linked_ptr<ThreadLocalValueHolderBase> > ThreadLocalValues; std::shared_ptr<ThreadLocalValueHolderBase> >
ThreadLocalValues;
// Stores all ThreadIdToThreadLocals having values in a thread, indexed by // Stores all ThreadIdToThreadLocals having values in a thread, indexed by
// thread's ID. // thread's ID.
typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals; typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
...@@ -495,18 +635,17 @@ class ThreadLocalRegistryImpl { ...@@ -495,18 +635,17 @@ class ThreadLocalRegistryImpl {
HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
FALSE, FALSE,
thread_id); thread_id);
GTEST_CHECK_(thread != NULL); GTEST_CHECK_(thread != nullptr);
// We need to to pass a valid thread ID pointer into CreateThread for it // We need to pass a valid thread ID pointer into CreateThread for it
// to work correctly under Win98. // to work correctly under Win98.
DWORD watcher_thread_id; DWORD watcher_thread_id;
HANDLE watcher_thread = ::CreateThread( HANDLE watcher_thread = ::CreateThread(
NULL, // Default security. nullptr, // Default security.
0, // Default stack size 0, // Default stack size
&ThreadLocalRegistryImpl::WatcherThreadFunc, &ThreadLocalRegistryImpl::WatcherThreadFunc,
reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)), reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
CREATE_SUSPENDED, CREATE_SUSPENDED, &watcher_thread_id);
&watcher_thread_id); GTEST_CHECK_(watcher_thread != nullptr);
GTEST_CHECK_(watcher_thread != NULL);
// Give the watcher thread the same priority as ours to avoid being // Give the watcher thread the same priority as ours to avoid being
// blocked by it. // blocked by it.
::SetThreadPriority(watcher_thread, ::SetThreadPriority(watcher_thread,
...@@ -531,7 +670,10 @@ class ThreadLocalRegistryImpl { ...@@ -531,7 +670,10 @@ class ThreadLocalRegistryImpl {
// Returns map of thread local instances. // Returns map of thread local instances.
static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() { static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
mutex_.AssertHeld(); mutex_.AssertHeld();
static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals; #ifdef _MSC_VER
MemoryIsNotDeallocated memory_is_not_deallocated;
#endif // _MSC_VER
static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals();
return map; return map;
} }
...@@ -573,7 +715,7 @@ RE::~RE() { ...@@ -573,7 +715,7 @@ RE::~RE() {
free(const_cast<char*>(pattern_)); free(const_cast<char*>(pattern_));
} }
// Returns true iff regular expression re matches the entire str. // Returns true if and only if regular expression re matches the entire str.
bool RE::FullMatch(const char* str, const RE& re) { bool RE::FullMatch(const char* str, const RE& re) {
if (!re.is_valid_) return false; if (!re.is_valid_) return false;
...@@ -581,8 +723,8 @@ bool RE::FullMatch(const char* str, const RE& re) { ...@@ -581,8 +723,8 @@ bool RE::FullMatch(const char* str, const RE& re) {
return regexec(&re.full_regex_, str, 1, &match, 0) == 0; return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
} }
// Returns true iff regular expression re matches a substring of str // Returns true if and only if regular expression re matches a substring of
// (including str itself). // str (including str itself).
bool RE::PartialMatch(const char* str, const RE& re) { bool RE::PartialMatch(const char* str, const RE& re) {
if (!re.is_valid_) return false; if (!re.is_valid_) return false;
...@@ -622,14 +764,14 @@ void RE::Init(const char* regex) { ...@@ -622,14 +764,14 @@ void RE::Init(const char* regex) {
#elif GTEST_USES_SIMPLE_RE #elif GTEST_USES_SIMPLE_RE
// Returns true iff ch appears anywhere in str (excluding the // Returns true if and only if ch appears anywhere in str (excluding the
// terminating '\0' character). // terminating '\0' character).
bool IsInSet(char ch, const char* str) { bool IsInSet(char ch, const char* str) {
return ch != '\0' && strchr(str, ch) != NULL; return ch != '\0' && strchr(str, ch) != nullptr;
} }
// Returns true iff ch belongs to the given classification. Unlike // Returns true if and only if ch belongs to the given classification.
// similar functions in <ctype.h>, these aren't affected by the // Unlike similar functions in <ctype.h>, these aren't affected by the
// current locale. // current locale.
bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
bool IsAsciiPunct(char ch) { bool IsAsciiPunct(char ch) {
...@@ -642,13 +784,13 @@ bool IsAsciiWordChar(char ch) { ...@@ -642,13 +784,13 @@ bool IsAsciiWordChar(char ch) {
('0' <= ch && ch <= '9') || ch == '_'; ('0' <= ch && ch <= '9') || ch == '_';
} }
// Returns true iff "\\c" is a supported escape sequence. // Returns true if and only if "\\c" is a supported escape sequence.
bool IsValidEscape(char c) { bool IsValidEscape(char c) {
return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
} }
// Returns true iff the given atom (specified by escaped and pattern) // Returns true if and only if the given atom (specified by escaped and
// matches ch. The result is undefined if the atom is invalid. // pattern) matches ch. The result is undefined if the atom is invalid.
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
if (escaped) { // "\\p" where p is pattern_char. if (escaped) { // "\\p" where p is pattern_char.
switch (pattern_char) { switch (pattern_char) {
...@@ -671,7 +813,7 @@ bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { ...@@ -671,7 +813,7 @@ bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
} }
// Helper function used by ValidateRegex() to format error messages. // Helper function used by ValidateRegex() to format error messages.
std::string FormatRegexSyntaxError(const char* regex, int index) { static std::string FormatRegexSyntaxError(const char* regex, int index) {
return (Message() << "Syntax error at index " << index return (Message() << "Syntax error at index " << index
<< " in simple regular expression \"" << regex << "\": ").GetString(); << " in simple regular expression \"" << regex << "\": ").GetString();
} }
...@@ -679,17 +821,14 @@ std::string FormatRegexSyntaxError(const char* regex, int index) { ...@@ -679,17 +821,14 @@ std::string FormatRegexSyntaxError(const char* regex, int index) {
// Generates non-fatal failures and returns false if regex is invalid; // Generates non-fatal failures and returns false if regex is invalid;
// otherwise returns true. // otherwise returns true.
bool ValidateRegex(const char* regex) { bool ValidateRegex(const char* regex) {
if (regex == NULL) { if (regex == nullptr) {
// TODO(wan@google.com): fix the source file location in the
// assertion failures to match where the regex is used in user
// code.
ADD_FAILURE() << "NULL is not a valid simple regular expression."; ADD_FAILURE() << "NULL is not a valid simple regular expression.";
return false; return false;
} }
bool is_valid = true; bool is_valid = true;
// True iff ?, *, or + can follow the previous atom. // True if and only if ?, *, or + can follow the previous atom.
bool prev_repeatable = false; bool prev_repeatable = false;
for (int i = 0; regex[i]; i++) { for (int i = 0; regex[i]; i++) {
if (regex[i] == '\\') { // An escape sequence if (regex[i] == '\\') { // An escape sequence
...@@ -765,8 +904,8 @@ bool MatchRepetitionAndRegexAtHead( ...@@ -765,8 +904,8 @@ bool MatchRepetitionAndRegexAtHead(
return false; return false;
} }
// Returns true iff regex matches a prefix of str. regex must be a // Returns true if and only if regex matches a prefix of str. regex must
// valid simple regular expression and not start with "^", or the // be a valid simple regular expression and not start with "^", or the
// result is undefined. // result is undefined.
bool MatchRegexAtHead(const char* regex, const char* str) { bool MatchRegexAtHead(const char* regex, const char* str) {
if (*regex == '\0') // An empty regex matches a prefix of anything. if (*regex == '\0') // An empty regex matches a prefix of anything.
...@@ -796,8 +935,8 @@ bool MatchRegexAtHead(const char* regex, const char* str) { ...@@ -796,8 +935,8 @@ bool MatchRegexAtHead(const char* regex, const char* str) {
} }
} }
// Returns true iff regex matches any substring of str. regex must be // Returns true if and only if regex matches any substring of str. regex must
// a valid simple regular expression, or the result is undefined. // be a valid simple regular expression, or the result is undefined.
// //
// The algorithm is recursive, but the recursion depth doesn't exceed // The algorithm is recursive, but the recursion depth doesn't exceed
// the regex length, so we won't need to worry about running out of // the regex length, so we won't need to worry about running out of
...@@ -805,8 +944,7 @@ bool MatchRegexAtHead(const char* regex, const char* str) { ...@@ -805,8 +944,7 @@ bool MatchRegexAtHead(const char* regex, const char* str) {
// exponential with respect to the regex length + the string length, // exponential with respect to the regex length + the string length,
// but usually it's must faster (often close to linear). // but usually it's must faster (often close to linear).
bool MatchRegexAnywhere(const char* regex, const char* str) { bool MatchRegexAnywhere(const char* regex, const char* str) {
if (regex == NULL || str == NULL) if (regex == nullptr || str == nullptr) return false;
return false;
if (*regex == '^') if (*regex == '^')
return MatchRegexAtHead(regex + 1, str); return MatchRegexAtHead(regex + 1, str);
...@@ -826,21 +964,21 @@ RE::~RE() { ...@@ -826,21 +964,21 @@ RE::~RE() {
free(const_cast<char*>(full_pattern_)); free(const_cast<char*>(full_pattern_));
} }
// Returns true iff regular expression re matches the entire str. // Returns true if and only if regular expression re matches the entire str.
bool RE::FullMatch(const char* str, const RE& re) { bool RE::FullMatch(const char* str, const RE& re) {
return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
} }
// Returns true iff regular expression re matches a substring of str // Returns true if and only if regular expression re matches a substring of
// (including str itself). // str (including str itself).
bool RE::PartialMatch(const char* str, const RE& re) { bool RE::PartialMatch(const char* str, const RE& re) {
return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
} }
// Initializes an RE from its string representation. // Initializes an RE from its string representation.
void RE::Init(const char* regex) { void RE::Init(const char* regex) {
pattern_ = full_pattern_ = NULL; pattern_ = full_pattern_ = nullptr;
if (regex != NULL) { if (regex != nullptr) {
pattern_ = posix::StrDup(regex); pattern_ = posix::StrDup(regex);
} }
...@@ -878,7 +1016,7 @@ const char kUnknownFile[] = "unknown file"; ...@@ -878,7 +1016,7 @@ const char kUnknownFile[] = "unknown file";
// Formats a source file path and a line number as they would appear // Formats a source file path and a line number as they would appear
// in an error message from the compiler used to compile this code. // in an error message from the compiler used to compile this code.
GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
const std::string file_name(file == NULL ? kUnknownFile : file); const std::string file_name(file == nullptr ? kUnknownFile : file);
if (line < 0) { if (line < 0) {
return file_name + ":"; return file_name + ":";
...@@ -897,7 +1035,7 @@ GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { ...@@ -897,7 +1035,7 @@ GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
// to the file location it produces, unlike FormatFileLocation(). // to the file location it produces, unlike FormatFileLocation().
GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
const char* file, int line) { const char* file, int line) {
const std::string file_name(file == NULL ? kUnknownFile : file); const std::string file_name(file == nullptr ? kUnknownFile : file);
if (line < 0) if (line < 0)
return file_name; return file_name;
...@@ -923,9 +1061,10 @@ GTestLog::~GTestLog() { ...@@ -923,9 +1061,10 @@ GTestLog::~GTestLog() {
posix::Abort(); posix::Abort();
} }
} }
// Disable Microsoft deprecation warnings for POSIX functions called from // Disable Microsoft deprecation warnings for POSIX functions called from
// this class (creat, dup, dup2, and close) // this class (creat, dup, dup2, and close)
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996) GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
#if GTEST_HAS_STREAM_REDIRECTION #if GTEST_HAS_STREAM_REDIRECTION
...@@ -963,20 +1102,22 @@ class CapturedStream { ...@@ -963,20 +1102,22 @@ class CapturedStream {
// code as part of a regular standalone executable, which doesn't // code as part of a regular standalone executable, which doesn't
// run in a Dalvik process (e.g. when running it through 'adb shell'). // run in a Dalvik process (e.g. when running it through 'adb shell').
// //
// The location /sdcard is directly accessible from native code // The location /data/local/tmp is directly accessible from native code.
// and is the only location (unofficially) supported by the Android // '/sdcard' and other variants cannot be relied on, as they are not
// team. It's generally a symlink to the real SD Card mount point // guaranteed to be mounted, or may have a delay in mounting.
// which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or char name_template[] = "/data/local/tmp/gtest_captured_stream.XXXXXX";
// other OEM-customized locations. Never rely on these, and always
// use /sdcard.
char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX";
# else # else
char name_template[] = "/tmp/captured_stream.XXXXXX"; char name_template[] = "/tmp/captured_stream.XXXXXX";
# endif // GTEST_OS_LINUX_ANDROID # endif // GTEST_OS_LINUX_ANDROID
const int captured_fd = mkstemp(name_template); const int captured_fd = mkstemp(name_template);
if (captured_fd == -1) {
GTEST_LOG_(WARNING)
<< "Failed to create tmp file " << name_template
<< " for test; does the test have access to the /tmp directory?";
}
filename_ = name_template; filename_ = name_template;
# endif // GTEST_OS_WINDOWS # endif // GTEST_OS_WINDOWS
fflush(NULL); fflush(nullptr);
dup2(captured_fd, fd_); dup2(captured_fd, fd_);
close(captured_fd); close(captured_fd);
} }
...@@ -988,13 +1129,17 @@ class CapturedStream { ...@@ -988,13 +1129,17 @@ class CapturedStream {
std::string GetCapturedString() { std::string GetCapturedString() {
if (uncaptured_fd_ != -1) { if (uncaptured_fd_ != -1) {
// Restores the original stream. // Restores the original stream.
fflush(NULL); fflush(nullptr);
dup2(uncaptured_fd_, fd_); dup2(uncaptured_fd_, fd_);
close(uncaptured_fd_); close(uncaptured_fd_);
uncaptured_fd_ = -1; uncaptured_fd_ = -1;
} }
FILE* const file = posix::FOpen(filename_.c_str(), "r"); FILE* const file = posix::FOpen(filename_.c_str(), "r");
if (file == nullptr) {
GTEST_LOG_(FATAL) << "Failed to open tmp file " << filename_
<< " for capturing stream.";
}
const std::string content = ReadEntireFile(file); const std::string content = ReadEntireFile(file);
posix::FClose(file); posix::FClose(file);
return content; return content;
...@@ -1009,14 +1154,15 @@ class CapturedStream { ...@@ -1009,14 +1154,15 @@ class CapturedStream {
GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
}; };
GTEST_DISABLE_MSC_WARNINGS_POP_() GTEST_DISABLE_MSC_DEPRECATED_POP_()
static CapturedStream* g_captured_stderr = NULL; static CapturedStream* g_captured_stderr = nullptr;
static CapturedStream* g_captured_stdout = NULL; static CapturedStream* g_captured_stdout = nullptr;
// Starts capturing an output stream (stdout/stderr). // Starts capturing an output stream (stdout/stderr).
void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { static void CaptureStream(int fd, const char* stream_name,
if (*stream != NULL) { CapturedStream** stream) {
if (*stream != nullptr) {
GTEST_LOG_(FATAL) << "Only one " << stream_name GTEST_LOG_(FATAL) << "Only one " << stream_name
<< " capturer can exist at a time."; << " capturer can exist at a time.";
} }
...@@ -1024,11 +1170,11 @@ void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { ...@@ -1024,11 +1170,11 @@ void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
} }
// Stops capturing the output stream and returns the captured string. // Stops capturing the output stream and returns the captured string.
std::string GetCapturedStream(CapturedStream** captured_stream) { static std::string GetCapturedStream(CapturedStream** captured_stream) {
const std::string content = (*captured_stream)->GetCapturedString(); const std::string content = (*captured_stream)->GetCapturedString();
delete *captured_stream; delete *captured_stream;
*captured_stream = NULL; *captured_stream = nullptr;
return content; return content;
} }
...@@ -1055,23 +1201,9 @@ std::string GetCapturedStderr() { ...@@ -1055,23 +1201,9 @@ std::string GetCapturedStderr() {
#endif // GTEST_HAS_STREAM_REDIRECTION #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) { size_t GetFileSize(FILE* file) {
fseek(file, 0, SEEK_END); fseek(file, 0, SEEK_END);
...@@ -1101,22 +1233,30 @@ std::string ReadEntireFile(FILE* file) { ...@@ -1101,22 +1233,30 @@ std::string ReadEntireFile(FILE* file) {
} }
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
static const std::vector<std::string>* g_injected_test_argvs =
nullptr; // Owned.
static const ::std::vector<testing::internal::string>* g_injected_test_argvs = std::vector<std::string> GetInjectableArgvs() {
NULL; // Owned. if (g_injected_test_argvs != nullptr) {
void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
if (g_injected_test_argvs != argvs)
delete g_injected_test_argvs;
g_injected_test_argvs = argvs;
}
const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
if (g_injected_test_argvs != NULL) {
return *g_injected_test_argvs; return *g_injected_test_argvs;
} }
return GetArgvs(); return GetArgvs();
} }
void SetInjectableArgvs(const std::vector<std::string>* new_argvs) {
if (g_injected_test_argvs != new_argvs) delete g_injected_test_argvs;
g_injected_test_argvs = new_argvs;
}
void SetInjectableArgvs(const std::vector<std::string>& new_argvs) {
SetInjectableArgvs(
new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
}
void ClearInjectableArgvs() {
delete g_injected_test_argvs;
g_injected_test_argvs = nullptr;
}
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
#if GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS_MOBILE
...@@ -1148,7 +1288,7 @@ static std::string FlagToEnvVar(const char* flag) { ...@@ -1148,7 +1288,7 @@ static std::string FlagToEnvVar(const char* flag) {
// unchanged and returns false. // unchanged and returns false.
bool ParseInt32(const Message& src_text, const char* str, Int32* value) { bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
// Parses the environment variable as a decimal integer. // Parses the environment variable as a decimal integer.
char* end = NULL; char* end = nullptr;
const long long_value = strtol(str, &end, 10); // NOLINT const long long_value = strtol(str, &end, 10); // NOLINT
// Has strtol() consumed all characters in the string? // Has strtol() consumed all characters in the string?
...@@ -1187,15 +1327,16 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) { ...@@ -1187,15 +1327,16 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
// Reads and returns the Boolean environment variable corresponding to // Reads and returns the Boolean environment variable corresponding to
// the given flag; if it's not set, returns default_value. // the given flag; if it's not set, returns default_value.
// //
// The value is considered true iff it's not "0". // The value is considered true if and only if it's not "0".
bool BoolFromGTestEnv(const char* flag, bool default_value) { bool BoolFromGTestEnv(const char* flag, bool default_value) {
#if defined(GTEST_GET_BOOL_FROM_ENV_) #if defined(GTEST_GET_BOOL_FROM_ENV_)
return GTEST_GET_BOOL_FROM_ENV_(flag, default_value); return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
#endif // defined(GTEST_GET_BOOL_FROM_ENV_) #else
const std::string env_var = FlagToEnvVar(flag); const std::string env_var = FlagToEnvVar(flag);
const char* const string_value = posix::GetEnv(env_var.c_str()); const char* const string_value = posix::GetEnv(env_var.c_str());
return string_value == NULL ? return string_value == nullptr ? default_value
default_value : strcmp(string_value, "0") != 0; : strcmp(string_value, "0") != 0;
#endif // defined(GTEST_GET_BOOL_FROM_ENV_)
} }
// Reads and returns a 32-bit integer stored in the environment // Reads and returns a 32-bit integer stored in the environment
...@@ -1204,10 +1345,10 @@ bool BoolFromGTestEnv(const char* flag, bool default_value) { ...@@ -1204,10 +1345,10 @@ bool BoolFromGTestEnv(const char* flag, bool default_value) {
Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
#if defined(GTEST_GET_INT32_FROM_ENV_) #if defined(GTEST_GET_INT32_FROM_ENV_)
return GTEST_GET_INT32_FROM_ENV_(flag, default_value); return GTEST_GET_INT32_FROM_ENV_(flag, default_value);
#endif // defined(GTEST_GET_INT32_FROM_ENV_) #else
const std::string env_var = FlagToEnvVar(flag); const std::string env_var = FlagToEnvVar(flag);
const char* const string_value = posix::GetEnv(env_var.c_str()); const char* const string_value = posix::GetEnv(env_var.c_str());
if (string_value == NULL) { if (string_value == nullptr) {
// The environment variable is not set. // The environment variable is not set.
return default_value; return default_value;
} }
...@@ -1222,37 +1363,36 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { ...@@ -1222,37 +1363,36 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
} }
return result; return result;
#endif // defined(GTEST_GET_INT32_FROM_ENV_)
}
// As a special case for the 'output' flag, if GTEST_OUTPUT is not
// set, we look for XML_OUTPUT_FILE, which is set by the Bazel build
// system. The value of XML_OUTPUT_FILE is a filename without the
// "xml:" prefix of GTEST_OUTPUT.
// Note that this is meant to be called at the call site so it does
// not check that the flag is 'output'
// In essence this checks an env variable called XML_OUTPUT_FILE
// and if it is set we prepend "xml:" to its value, if it not set we return ""
std::string OutputFlagAlsoCheckEnvVar(){
std::string default_value_for_output_flag = "";
const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
if (nullptr != xml_output_file_env) {
default_value_for_output_flag = std::string("xml:") + xml_output_file_env;
}
return default_value_for_output_flag;
} }
// Reads and returns the string environment variable corresponding to // Reads and returns the string environment variable corresponding to
// the given flag; if it's not set, returns default_value. // the given flag; if it's not set, returns default_value.
std::string StringFromGTestEnv(const char* flag, const char* default_value) { const char* StringFromGTestEnv(const char* flag, const char* default_value) {
#if defined(GTEST_GET_STRING_FROM_ENV_) #if defined(GTEST_GET_STRING_FROM_ENV_)
return GTEST_GET_STRING_FROM_ENV_(flag, default_value); return GTEST_GET_STRING_FROM_ENV_(flag, default_value);
#endif // defined(GTEST_GET_STRING_FROM_ENV_) #else
const std::string env_var = FlagToEnvVar(flag); const std::string env_var = FlagToEnvVar(flag);
const char* value = posix::GetEnv(env_var.c_str()); const char* const value = posix::GetEnv(env_var.c_str());
if (value != NULL) { return value == nullptr ? default_value : value;
return value; #endif // defined(GTEST_GET_STRING_FROM_ENV_)
}
// As a special case for the 'output' flag, if GTEST_OUTPUT is not
// set, we look for XML_OUTPUT_FILE, which is set by the Bazel build
// system. The value of XML_OUTPUT_FILE is a filename without the
// "xml:" prefix of GTEST_OUTPUT.
//
// The net priority order after flag processing is thus:
// --gtest_output command line flag
// GTEST_OUTPUT environment variable
// XML_OUTPUT_FILE environment variable
// 'default_value'
if (strcmp(flag, "output") == 0) {
value = posix::GetEnv("XML_OUTPUT_FILE");
if (value != NULL) {
return std::string("xml:") + value;
}
}
return default_value;
} }
} // namespace internal } // namespace internal
......
...@@ -26,10 +26,9 @@ ...@@ -26,10 +26,9 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Test - The Google C++ Testing Framework
// Google Test - The Google C++ Testing and Mocking Framework
// //
// This file implements a universal value printer that can print a // This file implements a universal value printer that can print a
// value of any type T: // value of any type T:
...@@ -43,12 +42,13 @@ ...@@ -43,12 +42,13 @@
// defines Foo. // defines Foo.
#include "gtest/gtest-printers.h" #include "gtest/gtest-printers.h"
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <cctype>
#include <cwchar> #include <cwchar>
#include <ostream> // NOLINT #include <ostream> // NOLINT
#include <string> #include <string>
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#include "src/gtest-internal-inl.h"
namespace testing { namespace testing {
...@@ -59,6 +59,7 @@ using ::std::ostream; ...@@ -59,6 +59,7 @@ using ::std::ostream;
// Prints a segment of bytes in the given object. // Prints a segment of bytes in the given object.
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
size_t count, ostream* os) { size_t count, ostream* os) {
...@@ -89,7 +90,6 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, ...@@ -89,7 +90,6 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
// If the object size is bigger than kThreshold, we'll have to omit // If the object size is bigger than kThreshold, we'll have to omit
// some details by printing only the first and the last kChunkSize // some details by printing only the first and the last kChunkSize
// bytes. // bytes.
// TODO(wan): let the user control the threshold using a flag.
if (count < kThreshold) { if (count < kThreshold) {
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
} else { } else {
...@@ -123,7 +123,7 @@ namespace internal { ...@@ -123,7 +123,7 @@ namespace internal {
// Depending on the value of a char (or wchar_t), we print it in one // Depending on the value of a char (or wchar_t), we print it in one
// of three formats: // of three formats:
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), // - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
// - as a hexidecimal escape sequence (e.g. '\x7F'), or // - as a hexadecimal escape sequence (e.g. '\x7F'), or
// - as a special escape sequence (e.g. '\r', '\n'). // - as a special escape sequence (e.g. '\r', '\n').
enum CharFormat { enum CharFormat {
kAsIs, kAsIs,
...@@ -144,7 +144,8 @@ inline bool IsPrintableAscii(wchar_t c) { ...@@ -144,7 +144,8 @@ inline bool IsPrintableAscii(wchar_t c) {
// which is the type of c. // which is the type of c.
template <typename UnsignedChar, typename Char> template <typename UnsignedChar, typename Char>
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
switch (static_cast<wchar_t>(c)) { wchar_t w_c = static_cast<wchar_t>(c);
switch (w_c) {
case L'\0': case L'\0':
*os << "\\0"; *os << "\\0";
break; break;
...@@ -176,11 +177,14 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { ...@@ -176,11 +177,14 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
*os << "\\v"; *os << "\\v";
break; break;
default: default:
if (IsPrintableAscii(c)) { if (IsPrintableAscii(w_c)) {
*os << static_cast<char>(c); *os << static_cast<char>(c);
return kAsIs; return kAsIs;
} else { } else {
*os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c)); ostream::fmtflags flags = os->flags();
*os << "\\x" << std::hex << std::uppercase
<< static_cast<int>(static_cast<UnsignedChar>(c));
os->flags(flags);
return kHexEscape; return kHexEscape;
} }
} }
...@@ -227,13 +231,13 @@ void PrintCharAndCodeTo(Char c, ostream* os) { ...@@ -227,13 +231,13 @@ void PrintCharAndCodeTo(Char c, ostream* os) {
return; return;
*os << " (" << static_cast<int>(c); *os << " (" << static_cast<int>(c);
// For more convenience, we print c's code again in hexidecimal, // For more convenience, we print c's code again in hexadecimal,
// unless c was already printed in the form '\x##' or the code is in // unless c was already printed in the form '\x##' or the code is in
// [1, 9]. // [1, 9].
if (format == kHexEscape || (1 <= c && c <= 9)) { if (format == kHexEscape || (1 <= c && c <= 9)) {
// Do nothing. // Do nothing.
} else { } else {
*os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c)); *os << ", 0x" << String::FormatHexInt(static_cast<int>(c));
} }
*os << ")"; *os << ")";
} }
...@@ -258,12 +262,14 @@ void PrintTo(wchar_t wc, ostream* os) { ...@@ -258,12 +262,14 @@ void PrintTo(wchar_t wc, ostream* os) {
template <typename CharType> template <typename CharType>
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static void PrintCharsAsStringTo( static CharFormat PrintCharsAsStringTo(
const CharType* begin, size_t len, ostream* os) { const CharType* begin, size_t len, ostream* os) {
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
*os << kQuoteBegin; *os << kQuoteBegin;
bool is_previous_hex = false; bool is_previous_hex = false;
CharFormat print_format = kAsIs;
for (size_t index = 0; index < len; ++index) { for (size_t index = 0; index < len; ++index) {
const CharType cur = begin[index]; const CharType cur = begin[index];
if (is_previous_hex && IsXDigit(cur)) { if (is_previous_hex && IsXDigit(cur)) {
...@@ -273,8 +279,13 @@ static void PrintCharsAsStringTo( ...@@ -273,8 +279,13 @@ static void PrintCharsAsStringTo(
*os << "\" " << kQuoteBegin; *os << "\" " << kQuoteBegin;
} }
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
// Remember if any characters required hex escaping.
if (is_previous_hex) {
print_format = kHexEscape;
}
} }
*os << "\""; *os << "\"";
return print_format;
} }
// Prints a (const) char/wchar_t array of 'len' elements, starting at address // Prints a (const) char/wchar_t array of 'len' elements, starting at address
...@@ -282,6 +293,7 @@ static void PrintCharsAsStringTo( ...@@ -282,6 +293,7 @@ static void PrintCharsAsStringTo(
template <typename CharType> template <typename CharType>
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static void UniversalPrintCharArray( static void UniversalPrintCharArray(
const CharType* begin, size_t len, ostream* os) { const CharType* begin, size_t len, ostream* os) {
...@@ -318,7 +330,7 @@ void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) { ...@@ -318,7 +330,7 @@ void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
// Prints the given C string to the ostream. // Prints the given C string to the ostream.
void PrintTo(const char* s, ostream* os) { void PrintTo(const char* s, ostream* os) {
if (s == NULL) { if (s == nullptr) {
*os << "NULL"; *os << "NULL";
} else { } else {
*os << ImplicitCast_<const void*>(s) << " pointing to "; *os << ImplicitCast_<const void*>(s) << " pointing to ";
...@@ -335,32 +347,89 @@ void PrintTo(const char* s, ostream* os) { ...@@ -335,32 +347,89 @@ void PrintTo(const char* s, ostream* os) {
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
// Prints the given wide C string to the ostream. // Prints the given wide C string to the ostream.
void PrintTo(const wchar_t* s, ostream* os) { void PrintTo(const wchar_t* s, ostream* os) {
if (s == NULL) { if (s == nullptr) {
*os << "NULL"; *os << "NULL";
} else { } else {
*os << ImplicitCast_<const void*>(s) << " pointing to "; *os << ImplicitCast_<const void*>(s) << " pointing to ";
PrintCharsAsStringTo(s, std::wcslen(s), os); PrintCharsAsStringTo(s, wcslen(s), os);
} }
} }
#endif // wchar_t is native #endif // wchar_t is native
// Prints a ::string object. namespace {
#if GTEST_HAS_GLOBAL_STRING
void PrintStringTo(const ::string& s, ostream* os) { bool ContainsUnprintableControlCodes(const char* str, size_t length) {
PrintCharsAsStringTo(s.data(), s.size(), os); const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
for (size_t i = 0; i < length; i++) {
unsigned char ch = *s++;
if (std::iscntrl(ch)) {
switch (ch) {
case '\t':
case '\n':
case '\r':
break;
default:
return true;
}
}
}
return false;
} }
#endif // GTEST_HAS_GLOBAL_STRING
void PrintStringTo(const ::std::string& s, ostream* os) { bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
PrintCharsAsStringTo(s.data(), s.size(), os);
bool IsValidUTF8(const char* str, size_t length) {
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
for (size_t i = 0; i < length;) {
unsigned char lead = s[i++];
if (lead <= 0x7f) {
continue; // single-byte character (ASCII) 0..7F
}
if (lead < 0xc2) {
return false; // trail byte or non-shortest form
} else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
++i; // 2-byte character
} else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
IsUTF8TrailByte(s[i]) &&
IsUTF8TrailByte(s[i + 1]) &&
// check for non-shortest form and surrogate
(lead != 0xe0 || s[i] >= 0xa0) &&
(lead != 0xed || s[i] < 0xa0)) {
i += 2; // 3-byte character
} else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
IsUTF8TrailByte(s[i]) &&
IsUTF8TrailByte(s[i + 1]) &&
IsUTF8TrailByte(s[i + 2]) &&
// check for non-shortest form
(lead != 0xf0 || s[i] >= 0x90) &&
(lead != 0xf4 || s[i] < 0x90)) {
i += 3; // 4-byte character
} else {
return false;
}
}
return true;
} }
// Prints a ::wstring object. void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
#if GTEST_HAS_GLOBAL_WSTRING if (!ContainsUnprintableControlCodes(str, length) &&
void PrintWideStringTo(const ::wstring& s, ostream* os) { IsValidUTF8(str, length)) {
PrintCharsAsStringTo(s.data(), s.size(), os); *os << "\n As Text: \"" << str << "\"";
}
}
} // anonymous namespace
void PrintStringTo(const ::std::string& s, ostream* os) {
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
if (GTEST_FLAG(print_utf8)) {
ConditionalPrintAsText(s.data(), s.size(), os);
}
}
} }
#endif // GTEST_HAS_GLOBAL_WSTRING
#if GTEST_HAS_STD_WSTRING #if GTEST_HAS_STD_WSTRING
void PrintWideStringTo(const ::std::wstring& s, ostream* os) { void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
......
...@@ -26,21 +26,12 @@ ...@@ -26,21 +26,12 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// Author: mheule@google.com (Markus Heule) // The Google C++ Testing and Mocking Framework (Google Test)
//
// The Google C++ Testing Framework (Google Test)
#include "gtest/gtest-test-part.h" #include "gtest/gtest-test-part.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick exists to
// prevent the accidental inclusion of gtest-internal-inl.h in the
// user's code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
namespace testing { namespace testing {
...@@ -50,18 +41,21 @@ using internal::GetUnitTestImpl; ...@@ -50,18 +41,21 @@ using internal::GetUnitTestImpl;
// in it. // in it.
std::string TestPartResult::ExtractSummary(const char* message) { std::string TestPartResult::ExtractSummary(const char* message) {
const char* const stack_trace = strstr(message, internal::kStackTraceMarker); const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
return stack_trace == NULL ? message : return stack_trace == nullptr ? message : std::string(message, stack_trace);
std::string(message, stack_trace);
} }
// Prints a TestPartResult object. // Prints a TestPartResult object.
std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
return os return os << result.file_name() << ":" << result.line_number() << ": "
<< result.file_name() << ":" << result.line_number() << ": " << (result.type() == TestPartResult::kSuccess
<< (result.type() == TestPartResult::kSuccess ? "Success" : ? "Success"
result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : : result.type() == TestPartResult::kSkip
"Non-fatal failure") << ":\n" ? "Skipped"
<< result.message() << std::endl; : result.type() == TestPartResult::kFatalFailure
? "Fatal failure"
: "Non-fatal failure")
<< ":\n"
<< result.message() << std::endl;
} }
// Appends a TestPartResult to the array. // Appends a TestPartResult to the array.
...@@ -76,7 +70,7 @@ const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { ...@@ -76,7 +70,7 @@ const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
internal::posix::Abort(); internal::posix::Abort();
} }
return array_[index]; return array_[static_cast<size_t>(index)];
} }
// Returns the number of TestPartResult objects in the array. // Returns the number of TestPartResult objects in the array.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment