Adds threading support (by Miklos Fazekas, Vlad Losev, and Chandler Carruth); adds wide InitGoogleTest to gtest.def (by Vlad Losev); updates the version number (by Zhanyong Wan); updates the release notes for 1.5.0 (by Vlad Losev); removes scons scripts from the distribution (by Zhanyong Wan); adds the cmake build script to the distribution (by Zhanyong Wan); adds fused source files to the distribution (by Vlad Losev and Chandler Carruth).
This commit is contained in:
parent
dd280cfa8d
commit
3bef459eac
21
CHANGES
21
CHANGES
|
@ -1,3 +1,24 @@
|
||||||
|
Changes for 1.5.0:
|
||||||
|
|
||||||
|
* New feature: Ability to use test assertions in multi-threaded tests
|
||||||
|
on platforms implementing pthreads.
|
||||||
|
* New feature: Predicates used inside EXPECT_TRUE() and friends
|
||||||
|
can now generate custom failure messages.
|
||||||
|
* New feature: Google Test can now be compiled as a DLL on Windows.
|
||||||
|
* New feature: The distribution package now includes fused source files.
|
||||||
|
* New feature: Prints help when encountering unrecognized Google Test flags.
|
||||||
|
* Experimental feature: CMake build script (requires CMake 2.6.4+).
|
||||||
|
* double values streamed to an assertion are printed with enough precision
|
||||||
|
to differentiate any two different values.
|
||||||
|
* Google Test now works on Solaris.
|
||||||
|
* Build and test script improvements.
|
||||||
|
* Bug fixes and implementation clean-ups.
|
||||||
|
|
||||||
|
Potentially breaking changes:
|
||||||
|
|
||||||
|
* Stopped supporting VC++ 7.1 with exceptions disabled.
|
||||||
|
* Dropped support for 'make install'.
|
||||||
|
|
||||||
Changes for 1.4.0:
|
Changes for 1.4.0:
|
||||||
|
|
||||||
* New feature: the event listener API
|
* New feature: the event listener API
|
||||||
|
|
|
@ -30,6 +30,9 @@ include_directories(
|
||||||
link_directories(
|
link_directories(
|
||||||
${gtest_BINARY_DIR}/src)
|
${gtest_BINARY_DIR}/src)
|
||||||
|
|
||||||
|
# Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
|
||||||
|
find_package(Threads)
|
||||||
|
|
||||||
# Defines the compiler/linker flags used to build gtest. You can
|
# Defines the compiler/linker flags used to build gtest. You can
|
||||||
# tweak these definitions to suit your need.
|
# tweak these definitions to suit your need.
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
@ -39,6 +42,11 @@ if (MSVC)
|
||||||
set(cxx_default "${cxx_base} -EHsc -D_HAS_EXCEPTIONS=1")
|
set(cxx_default "${cxx_base} -EHsc -D_HAS_EXCEPTIONS=1")
|
||||||
else()
|
else()
|
||||||
set(cxx_base "${CMAKE_CXX_FLAGS}")
|
set(cxx_base "${CMAKE_CXX_FLAGS}")
|
||||||
|
|
||||||
|
if (CMAKE_USE_PTHREADS_INIT) # The pthreads library is available.
|
||||||
|
set(cxx_base "${cxx_base} -DGTEST_HAS_PTHREAD=1")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(cxx_default "${cxx_base} -fexceptions")
|
set(cxx_default "${cxx_base} -fexceptions")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -53,6 +61,9 @@ function(cxx_library name cxx_flags)
|
||||||
set_target_properties(${name}
|
set_target_properties(${name}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
COMPILE_FLAGS "${cxx_flags}")
|
COMPILE_FLAGS "${cxx_flags}")
|
||||||
|
if (CMAKE_USE_PTHREADS_INIT)
|
||||||
|
target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
cxx_library(gtest "${cxx_default}" src/gtest-all.cc)
|
cxx_library(gtest "${cxx_default}" src/gtest-all.cc)
|
||||||
|
@ -150,6 +161,7 @@ endfunction()
|
||||||
cxx_test(gtest_unittest gtest_main)
|
cxx_test(gtest_unittest gtest_main)
|
||||||
|
|
||||||
if (build_all_gtest_tests)
|
if (build_all_gtest_tests)
|
||||||
|
cxx_test(gtest-death-test_test gtest_main)
|
||||||
cxx_test(gtest_environment_test gtest)
|
cxx_test(gtest_environment_test gtest)
|
||||||
cxx_test(gtest-filepath_test gtest_main)
|
cxx_test(gtest-filepath_test gtest_main)
|
||||||
cxx_test(gtest-linked_ptr_test gtest_main)
|
cxx_test(gtest-linked_ptr_test gtest_main)
|
||||||
|
@ -192,10 +204,6 @@ if (build_all_gtest_tests)
|
||||||
cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
|
cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
|
||||||
src/gtest-all.cc src/gtest_main.cc)
|
src/gtest-all.cc src/gtest_main.cc)
|
||||||
|
|
||||||
find_package(Threads) # Defines CMAKE_THREAD_LIBS_INIT.
|
|
||||||
cxx_test_with_flags(gtest-death-test_test "${cxx_default}"
|
|
||||||
"gtest_main;${CMAKE_THREAD_LIBS_INIT}" test/gtest-death-test_test.cc)
|
|
||||||
|
|
||||||
cxx_test_with_flags(gtest_no_rtti_unittest "${cxx_no_rtti}"
|
cxx_test_with_flags(gtest_no_rtti_unittest "${cxx_no_rtti}"
|
||||||
gtest_main_no_rtti test/gtest_unittest.cc)
|
gtest_main_no_rtti test/gtest_unittest.cc)
|
||||||
|
|
||||||
|
|
60
Makefile.am
60
Makefile.am
|
@ -11,10 +11,6 @@ EXTRA_DIST = \
|
||||||
include/gtest/internal/gtest-type-util.h.pump \
|
include/gtest/internal/gtest-type-util.h.pump \
|
||||||
include/gtest/internal/gtest-param-util-generated.h.pump \
|
include/gtest/internal/gtest-param-util-generated.h.pump \
|
||||||
make/Makefile \
|
make/Makefile \
|
||||||
run_tests.py \
|
|
||||||
scons/SConscript \
|
|
||||||
scons/SConstruct \
|
|
||||||
scons/SConstruct.common \
|
|
||||||
scripts/fuse_gtest_files.py \
|
scripts/fuse_gtest_files.py \
|
||||||
scripts/gen_gtest_pred_impl.py \
|
scripts/gen_gtest_pred_impl.py \
|
||||||
scripts/generate_gtest_def.py \
|
scripts/generate_gtest_def.py \
|
||||||
|
@ -28,8 +24,7 @@ EXTRA_DIST += \
|
||||||
src/gtest-internal-inl.h \
|
src/gtest-internal-inl.h \
|
||||||
src/gtest-port.cc \
|
src/gtest-port.cc \
|
||||||
src/gtest-test-part.cc \
|
src/gtest-test-part.cc \
|
||||||
src/gtest-typed-test.cc \
|
src/gtest-typed-test.cc
|
||||||
src/gtest.def
|
|
||||||
|
|
||||||
# Sample files that we don't compile.
|
# Sample files that we don't compile.
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
|
@ -112,6 +107,10 @@ EXTRA_DIST += \
|
||||||
test/run_tests_util.py \
|
test/run_tests_util.py \
|
||||||
test/run_tests_util_test.py
|
test/run_tests_util_test.py
|
||||||
|
|
||||||
|
# CMake script
|
||||||
|
EXTRA_DIST += \
|
||||||
|
CMakeLists.txt
|
||||||
|
|
||||||
# MSVC project files
|
# MSVC project files
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
msvc/gtest-md.sln \
|
msvc/gtest-md.sln \
|
||||||
|
@ -123,7 +122,8 @@ EXTRA_DIST += \
|
||||||
msvc/gtest_prod_test-md.vcproj \
|
msvc/gtest_prod_test-md.vcproj \
|
||||||
msvc/gtest_prod_test.vcproj \
|
msvc/gtest_prod_test.vcproj \
|
||||||
msvc/gtest_unittest-md.vcproj \
|
msvc/gtest_unittest-md.vcproj \
|
||||||
msvc/gtest_unittest.vcproj
|
msvc/gtest_unittest.vcproj \
|
||||||
|
msvc/gtest.def
|
||||||
|
|
||||||
# xcode project files
|
# xcode project files
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
|
@ -173,6 +173,14 @@ EXTRA_DIST += $(m4data_DATA)
|
||||||
# directories.
|
# directories.
|
||||||
AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/include
|
AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/include
|
||||||
|
|
||||||
|
# Modifies compiler and linker flags for pthreads compatibility.
|
||||||
|
if HAVE_PTHREADS
|
||||||
|
AM_CXXFLAGS = @PTHREAD_CFLAGS@ -DGTEST_HAS_PTHREAD=1
|
||||||
|
AM_LIBS = @PTHREAD_LIBS@
|
||||||
|
else
|
||||||
|
AM_CXXFLAGS = -DGTEST_HAS_PTHREAD=0
|
||||||
|
endif
|
||||||
|
|
||||||
# Build rules for libraries.
|
# Build rules for libraries.
|
||||||
lib_LTLIBRARIES = lib/libgtest.la lib/libgtest_main.la
|
lib_LTLIBRARIES = lib/libgtest.la lib/libgtest_main.la
|
||||||
|
|
||||||
|
@ -244,6 +252,38 @@ samples_sample10_unittest_LDADD = lib/libgtest.la
|
||||||
TESTS += test/gtest_all_test
|
TESTS += test/gtest_all_test
|
||||||
check_PROGRAMS += test/gtest_all_test
|
check_PROGRAMS += test/gtest_all_test
|
||||||
test_gtest_all_test_SOURCES = test/gtest_all_test.cc
|
test_gtest_all_test_SOURCES = test/gtest_all_test.cc
|
||||||
test_gtest_all_test_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
|
test_gtest_all_test_LDADD = lib/libgtest_main.la
|
||||||
test_gtest_all_test_LDADD = $(PTHREAD_LIBS) $(PTHREAD_CFLAGS) \
|
|
||||||
lib/libgtest_main.la
|
# Tests that fused gtest files compile and work.
|
||||||
|
TESTS += test/gtest_fused_test
|
||||||
|
check_PROGRAMS += test/gtest_fused_test
|
||||||
|
test_gtest_fused_test_SOURCES = fused-src/gtest/gtest-all.cc \
|
||||||
|
fused-src/gtest/gtest_main.cc \
|
||||||
|
fused-src/gtest/gtest.h \
|
||||||
|
samples/sample1.cc samples/sample1_unittest.cc
|
||||||
|
test_gtest_fused_test_CPPFLAGS = -I"$(srcdir)/fused-src"
|
||||||
|
|
||||||
|
# Build rules for putting fused Google Test files into the distribution
|
||||||
|
# package. The user can also create those files by manually running
|
||||||
|
# scripts/fuse_gtest_files.py.
|
||||||
|
$(srcdir)/fused-src/gtest/gtest-all.cc: fused-gtest-internal
|
||||||
|
|
||||||
|
$(srcdir)/fused-src/gtest/gtest.h: fused-gtest-internal
|
||||||
|
|
||||||
|
fused-gtest-internal: $(pkginclude_HEADERS) $(pkginclude_internal_HEADERS) \
|
||||||
|
$(lib_libgtest_la_SOURCES) \
|
||||||
|
scripts/fuse_gtest_files.py
|
||||||
|
mkdir -p "$(srcdir)/fused-src/gtest"
|
||||||
|
chmod -R u+w "$(srcdir)/fused-src"
|
||||||
|
rm -f "$(srcdir)/fused-src/gtest/gtest-all.cc"
|
||||||
|
rm -f "$(srcdir)/fused-src/gtest/gtest.h"
|
||||||
|
"$(srcdir)/scripts/fuse_gtest_files.py" "$(srcdir)/fused-src"
|
||||||
|
|
||||||
|
$(srcdir)/fused-src/gtest/gtest_main.cc: src/gtest_main.cc
|
||||||
|
mkdir -p "$(srcdir)/fused-src/gtest"
|
||||||
|
chmod -R u+w "$(srcdir)/fused-src"
|
||||||
|
cp -f "$(srcdir)/src/gtest_main.cc" "$(srcdir)/fused-src/gtest"
|
||||||
|
|
||||||
|
maintainer-clean-local:
|
||||||
|
chmod -R u+w "$(srcdir)/fused-src"
|
||||||
|
rm -rf "$(srcdir)/fused-src/gtest"
|
||||||
|
|
22
configure.ac
22
configure.ac
|
@ -5,7 +5,7 @@ m4_include(m4/acx_pthread.m4)
|
||||||
# "[1.0.1]"). It also asumes that there won't be any closing parenthesis
|
# "[1.0.1]"). It also asumes that there won't be any closing parenthesis
|
||||||
# between "AC_INIT(" and the closing ")" including comments and strings.
|
# between "AC_INIT(" and the closing ")" including comments and strings.
|
||||||
AC_INIT([Google C++ Testing Framework],
|
AC_INIT([Google C++ Testing Framework],
|
||||||
[1.4.0],
|
[1.5.0],
|
||||||
[googletestframework@googlegroups.com],
|
[googletestframework@googlegroups.com],
|
||||||
[gtest])
|
[gtest])
|
||||||
|
|
||||||
|
@ -39,8 +39,24 @@ AS_IF([test "$PYTHON" != ":"],
|
||||||
[AM_PYTHON_CHECK_VERSION([$PYTHON],[2.3],[:],[PYTHON=":"])])
|
[AM_PYTHON_CHECK_VERSION([$PYTHON],[2.3],[:],[PYTHON=":"])])
|
||||||
AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"])
|
AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"])
|
||||||
|
|
||||||
# Check for pthreads.
|
# Configure pthreads.
|
||||||
ACX_PTHREAD
|
AC_ARG_WITH([pthreads],
|
||||||
|
[AS_HELP_STRING([--with-pthreads],
|
||||||
|
[use pthreads (default is yes)])],
|
||||||
|
[with_pthreads=$withval],
|
||||||
|
[with_pthreads=check])
|
||||||
|
|
||||||
|
have_pthreads=no
|
||||||
|
AS_IF([test "x$with_pthreads" != "xno"],
|
||||||
|
[ACX_PTHREAD(
|
||||||
|
[],
|
||||||
|
[AS_IF([test "x$with_pthreads" != "xcheck"],
|
||||||
|
[AC_MSG_FAILURE(
|
||||||
|
[--with-pthreads was specified, but unable to be used])])])
|
||||||
|
have_pthreads="$acx_pthread_ok"])
|
||||||
|
AM_CONDITIONAL([HAVE_PTHREADS],[test "x$have_pthreads" == "xyes"])
|
||||||
|
AC_SUBST(PTHREAD_CFLAGS)
|
||||||
|
AC_SUBST(PTHREAD_LIBS)
|
||||||
|
|
||||||
# TODO(chandlerc@google.com) Check for the necessary system headers.
|
# TODO(chandlerc@google.com) Check for the necessary system headers.
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Protects copying of all linked_ptr objects.
|
// Protects copying of all linked_ptr objects.
|
||||||
extern Mutex g_linked_ptr_mutex;
|
GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
||||||
|
|
||||||
// This is used internally by all instances of linked_ptr<>. It needs to be
|
// This is used internally by all instances of linked_ptr<>. It needs to be
|
||||||
// a non-template class because different types of linked_ptr<> can refer to
|
// a non-template class because different types of linked_ptr<> can refer to
|
||||||
|
|
|
@ -343,10 +343,14 @@
|
||||||
|
|
||||||
#endif // GTEST_HAS_RTTI
|
#endif // GTEST_HAS_RTTI
|
||||||
|
|
||||||
// Determines whether <pthread.h> is available.
|
// Determines whether Google Test can use the pthreads library.
|
||||||
#ifndef GTEST_HAS_PTHREAD
|
#ifndef GTEST_HAS_PTHREAD
|
||||||
// The user didn't tell us, so we need to figure it out.
|
// The user didn't tell us explicitly, so we assume pthreads support is
|
||||||
#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_SOLARIS)
|
// available on Linux and Mac.
|
||||||
|
//
|
||||||
|
// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
|
||||||
|
// to your compiler flags.
|
||||||
|
#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC)
|
||||||
#endif // GTEST_HAS_PTHREAD
|
#endif // GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
// Determines whether Google Test can use tr1/tuple. You can define
|
// Determines whether Google Test can use tr1/tuple. You can define
|
||||||
|
@ -708,6 +712,27 @@ class GTestLog {
|
||||||
inline void LogToStderr() {}
|
inline void LogToStderr() {}
|
||||||
inline void FlushInfoLog() { fflush(NULL); }
|
inline void FlushInfoLog() { fflush(NULL); }
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DO NOT USE.
|
||||||
|
//
|
||||||
|
// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
|
||||||
|
// is not satisfied.
|
||||||
|
// Synopsys:
|
||||||
|
// GTEST_CHECK_(boolean_condition);
|
||||||
|
// or
|
||||||
|
// GTEST_CHECK_(boolean_condition) << "Additional message";
|
||||||
|
//
|
||||||
|
// This checks the condition and if the condition is not satisfied
|
||||||
|
// it prints message about the condition violation, including the
|
||||||
|
// condition itself, plus additional message streamed into it, if any,
|
||||||
|
// and then it aborts the program. It aborts the program irrespective of
|
||||||
|
// whether it is built in the debug mode or not.
|
||||||
|
#define GTEST_CHECK_(condition) \
|
||||||
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
|
if (::testing::internal::IsTrue(condition)) \
|
||||||
|
; \
|
||||||
|
else \
|
||||||
|
GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
|
||||||
|
|
||||||
#if GTEST_HAS_STREAM_REDIRECTION_
|
#if GTEST_HAS_STREAM_REDIRECTION_
|
||||||
|
|
||||||
// Defines the stderr capturer:
|
// Defines the stderr capturer:
|
||||||
|
@ -736,6 +761,260 @@ const ::std::vector<String>& GetArgvs();
|
||||||
|
|
||||||
// Defines synchronization primitives.
|
// Defines synchronization primitives.
|
||||||
|
|
||||||
|
#if GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
|
// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
|
||||||
|
// true.
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
// MutexBase and Mutex implement mutex on pthreads-based platforms. They
|
||||||
|
// are used in conjunction with class MutexLock:
|
||||||
|
//
|
||||||
|
// Mutex mutex;
|
||||||
|
// ...
|
||||||
|
// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end
|
||||||
|
// // of the current scope.
|
||||||
|
//
|
||||||
|
// MutexBase implements behavior for both statically and dynamically
|
||||||
|
// allocated mutexes. Do not use the MutexBase type directly. Instead,
|
||||||
|
// define a static mutex using the GTEST_DEFINE_STATIC_MUTEX_ macro:
|
||||||
|
//
|
||||||
|
// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
|
||||||
|
//
|
||||||
|
// Such mutex may also be forward-declared:
|
||||||
|
//
|
||||||
|
// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
|
||||||
|
//
|
||||||
|
// Do not use MutexBase for dynamic mutexes either. Use the Mutex class
|
||||||
|
// for them.
|
||||||
|
class MutexBase {
|
||||||
|
public:
|
||||||
|
void Lock();
|
||||||
|
void Unlock();
|
||||||
|
|
||||||
|
// Does nothing if the current thread holds the mutex. Otherwise, crashes
|
||||||
|
// with high probability.
|
||||||
|
void AssertHeld() const;
|
||||||
|
|
||||||
|
// We must be able to initialize objects of MutexBase used as static
|
||||||
|
// mutexes with initializer lists. This means MutexBase has to be a POD.
|
||||||
|
// The class members have to be public.
|
||||||
|
public:
|
||||||
|
pthread_mutex_t mutex_;
|
||||||
|
pthread_t owner_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Forward-declares a static mutex.
|
||||||
|
#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
|
||||||
|
extern ::testing::internal::MutexBase mutex
|
||||||
|
|
||||||
|
// Defines and statically initializes a static mutex.
|
||||||
|
#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
|
||||||
|
::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 }
|
||||||
|
|
||||||
|
// The class Mutex supports only mutexes created at runtime. It shares its
|
||||||
|
// API with MutexBase otherwise.
|
||||||
|
class Mutex : public MutexBase {
|
||||||
|
public:
|
||||||
|
Mutex();
|
||||||
|
~Mutex();
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
|
||||||
|
};
|
||||||
|
|
||||||
|
// We cannot call it MutexLock directly as the ctor declaration would
|
||||||
|
// conflict with a macro named MutexLock, which is defined on some
|
||||||
|
// platforms. Hence the typedef trick below.
|
||||||
|
class GTestMutexLock {
|
||||||
|
public:
|
||||||
|
explicit GTestMutexLock(MutexBase* mutex)
|
||||||
|
: mutex_(mutex) { mutex_->Lock(); }
|
||||||
|
|
||||||
|
~GTestMutexLock() { mutex_->Unlock(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
MutexBase* const mutex_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef GTestMutexLock MutexLock;
|
||||||
|
|
||||||
|
// Implements thread-local storage on pthreads-based systems.
|
||||||
|
//
|
||||||
|
// // Thread 1
|
||||||
|
// ThreadLocal<int> tl(100);
|
||||||
|
//
|
||||||
|
// // Thread 2
|
||||||
|
// tl.set(150);
|
||||||
|
// EXPECT_EQ(150, tl.get());
|
||||||
|
//
|
||||||
|
// // Thread 1
|
||||||
|
// EXPECT_EQ(100, tl.get()); // On Thread 1, tl.get() returns original value.
|
||||||
|
// tl.set(200);
|
||||||
|
// EXPECT_EQ(200, tl.get());
|
||||||
|
//
|
||||||
|
// The default ThreadLocal constructor requires T to have a default
|
||||||
|
// constructor. The single param constructor requires a copy contructor
|
||||||
|
// from T. A per-thread object managed by a ThreadLocal instance for a
|
||||||
|
// thread is guaranteed to exist at least until the earliest of the two
|
||||||
|
// events: (a) the thread terminates or (b) the ThreadLocal object
|
||||||
|
// managing it is destroyed.
|
||||||
|
template <typename T>
|
||||||
|
class ThreadLocal {
|
||||||
|
public:
|
||||||
|
ThreadLocal()
|
||||||
|
: key_(CreateKey()),
|
||||||
|
default_(),
|
||||||
|
instance_creator_func_(DefaultConstructNewInstance) {}
|
||||||
|
|
||||||
|
explicit ThreadLocal(const T& value)
|
||||||
|
: key_(CreateKey()),
|
||||||
|
default_(value),
|
||||||
|
instance_creator_func_(CopyConstructNewInstance) {}
|
||||||
|
|
||||||
|
~ThreadLocal() {
|
||||||
|
const int err = pthread_key_delete(key_);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_key_delete failed with error " << err;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* pointer() { return GetOrCreateValue(); }
|
||||||
|
const T* pointer() const { return GetOrCreateValue(); }
|
||||||
|
const T& get() const { return *pointer(); }
|
||||||
|
void set(const T& value) { *pointer() = value; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static pthread_key_t CreateKey() {
|
||||||
|
pthread_key_t key;
|
||||||
|
const int err = pthread_key_create(&key, &DeleteData);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_key_create failed with error " << err;
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* GetOrCreateValue() const {
|
||||||
|
T* value = static_cast<T*>(pthread_getspecific(key_));
|
||||||
|
if (value == NULL) {
|
||||||
|
value = (*instance_creator_func_)(default_);
|
||||||
|
const int err = pthread_setspecific(key_, value);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_setspecific failed with error " << err;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DeleteData(void* data) { delete static_cast<T*>(data); }
|
||||||
|
|
||||||
|
static T* DefaultConstructNewInstance(const T&) { return new T(); }
|
||||||
|
|
||||||
|
// Copy constructs new instance of T from default_. Will not be
|
||||||
|
// instantiated unless this ThreadLocal is constructed by the single
|
||||||
|
// parameter constructor.
|
||||||
|
static T* CopyConstructNewInstance(const T& t) { return new T(t); }
|
||||||
|
|
||||||
|
// A key pthreads uses for looking up per-thread values.
|
||||||
|
const pthread_key_t key_;
|
||||||
|
// Contains the value that CopyConstructNewInstance copies from.
|
||||||
|
const T default_;
|
||||||
|
// Points to either DefaultConstructNewInstance or CopyConstructNewInstance.
|
||||||
|
T* (*const instance_creator_func_)(const T& default_);
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Allows the controller thread pause execution of newly created test
|
||||||
|
// threads until signalled. Instances of this class must be created and
|
||||||
|
// destroyed in the controller thread.
|
||||||
|
//
|
||||||
|
// This class is supplied only for the purpose of testing Google Test's own
|
||||||
|
// constructs. Do not use it in user tests, either directly or indirectly.
|
||||||
|
class ThreadStartSemaphore {
|
||||||
|
public:
|
||||||
|
ThreadStartSemaphore();
|
||||||
|
~ThreadStartSemaphore();
|
||||||
|
// Signals to all test threads created with this semaphore to start. Must
|
||||||
|
// be called from the controlling thread.
|
||||||
|
void Signal();
|
||||||
|
// Blocks until the controlling thread signals. Must be called from a test
|
||||||
|
// thread.
|
||||||
|
void Wait();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// We cannot use Mutex here as this class is intended for testing it.
|
||||||
|
pthread_mutex_t mutex_;
|
||||||
|
pthread_cond_t cond_;
|
||||||
|
bool signalled_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadStartSemaphore);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper class for testing Google Test's multithreading constructs.
|
||||||
|
// Use:
|
||||||
|
//
|
||||||
|
// void ThreadFunc(int param) { /* Do things with param */ }
|
||||||
|
// ThreadSemaphore semaphore;
|
||||||
|
// ...
|
||||||
|
// // The semaphore parameter is optional; you can supply NULL.
|
||||||
|
// ThredWithParam<int> thread(&ThreadFunc, 5, &semaphore);
|
||||||
|
// sem.Signal(); // Allows the thread to start.
|
||||||
|
//
|
||||||
|
// This class is supplied only for the purpose of testing Google Test's own
|
||||||
|
// constructs. Do not use it in user tests, either directly or indirectly.
|
||||||
|
template <typename T>
|
||||||
|
class ThreadWithParam {
|
||||||
|
public:
|
||||||
|
typedef void (*UserThreadFunc)(T);
|
||||||
|
|
||||||
|
ThreadWithParam(UserThreadFunc func, T param, ThreadStartSemaphore* semaphore)
|
||||||
|
: func_(func),
|
||||||
|
param_(param),
|
||||||
|
start_semaphore_(semaphore),
|
||||||
|
finished_(false) {
|
||||||
|
// func_, param_, and start_semaphore_ must be initialized before
|
||||||
|
// pthread_create() is called.
|
||||||
|
const int err = pthread_create(&thread_, 0, ThreadMainStatic, this);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_create failed with error: "
|
||||||
|
<< strerror(err) << "(" << err << ")";
|
||||||
|
}
|
||||||
|
~ThreadWithParam() { Join(); }
|
||||||
|
|
||||||
|
void Join() {
|
||||||
|
if (!finished_) {
|
||||||
|
const int err = pthread_join(thread_, 0);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_join failed with error:"
|
||||||
|
<< strerror(err) << "(" << err << ")";
|
||||||
|
finished_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ThreadMain() {
|
||||||
|
if (start_semaphore_ != NULL)
|
||||||
|
start_semaphore_->Wait();
|
||||||
|
func_(param_);
|
||||||
|
}
|
||||||
|
static void* ThreadMainStatic(void* param) {
|
||||||
|
static_cast<ThreadWithParam<T>*>(param)->ThreadMain();
|
||||||
|
return NULL; // We are not interested in thread exit code.
|
||||||
|
}
|
||||||
|
|
||||||
|
// User supplied thread function.
|
||||||
|
const UserThreadFunc func_;
|
||||||
|
// User supplied parameter to UserThreadFunc.
|
||||||
|
const T param_;
|
||||||
|
|
||||||
|
// Native thread object.
|
||||||
|
pthread_t thread_;
|
||||||
|
// When non-NULL, used to block execution until the controller thread
|
||||||
|
// signals.
|
||||||
|
ThreadStartSemaphore* const start_semaphore_;
|
||||||
|
// true iff UserThreadFunc has not completed yet.
|
||||||
|
bool finished_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GTEST_IS_THREADSAFE 1
|
||||||
|
|
||||||
|
#else // GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
// A dummy implementation of synchronization primitives (mutex, lock,
|
// A dummy implementation of synchronization primitives (mutex, lock,
|
||||||
// and thread-local variable). Necessary for compiling Google Test where
|
// and thread-local variable). Necessary for compiling Google Test where
|
||||||
// mutex is not supported - using Google Test in multiple threads is not
|
// mutex is not supported - using Google Test in multiple threads is not
|
||||||
|
@ -744,14 +1023,14 @@ const ::std::vector<String>& GetArgvs();
|
||||||
class Mutex {
|
class Mutex {
|
||||||
public:
|
public:
|
||||||
Mutex() {}
|
Mutex() {}
|
||||||
explicit Mutex(int /*unused*/) {}
|
|
||||||
void AssertHeld() const {}
|
void AssertHeld() const {}
|
||||||
enum { NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX = 0 };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// We cannot call it MutexLock directly as the ctor declaration would
|
#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
|
||||||
// conflict with a macro named MutexLock, which is defined on some
|
extern ::testing::internal::Mutex mutex
|
||||||
// platforms. Hence the typedef trick below.
|
|
||||||
|
#define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
|
||||||
|
|
||||||
class GTestMutexLock {
|
class GTestMutexLock {
|
||||||
public:
|
public:
|
||||||
explicit GTestMutexLock(Mutex*) {} // NOLINT
|
explicit GTestMutexLock(Mutex*) {} // NOLINT
|
||||||
|
@ -772,14 +1051,16 @@ class ThreadLocal {
|
||||||
T value_;
|
T value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns the number of threads running in the process, or 0 to indicate that
|
|
||||||
// we cannot detect it.
|
|
||||||
size_t GetThreadCount();
|
|
||||||
|
|
||||||
// The above synchronization primitives have dummy implementations.
|
// The above synchronization primitives have dummy implementations.
|
||||||
// Therefore Google Test is not thread-safe.
|
// Therefore Google Test is not thread-safe.
|
||||||
#define GTEST_IS_THREADSAFE 0
|
#define GTEST_IS_THREADSAFE 0
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
|
// Returns the number of threads running in the process, or 0 to indicate that
|
||||||
|
// we cannot detect it.
|
||||||
|
size_t GetThreadCount();
|
||||||
|
|
||||||
// Passing non-POD classes through ellipsis (...) crashes the ARM
|
// Passing non-POD classes through ellipsis (...) crashes the ARM
|
||||||
// compiler and generates a warning in Sun Studio. The Nokia Symbian
|
// compiler and generates a warning in Sun Studio. The Nokia Symbian
|
||||||
// and the IBM XL C/C++ compiler try to instantiate a copy constructor
|
// and the IBM XL C/C++ compiler try to instantiate a copy constructor
|
||||||
|
@ -1024,27 +1305,6 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds.
|
||||||
|
|
||||||
// Utilities for command line flags and environment variables.
|
// Utilities for command line flags and environment variables.
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE.
|
|
||||||
//
|
|
||||||
// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
|
|
||||||
// is not satisfied.
|
|
||||||
// Synopsys:
|
|
||||||
// GTEST_CHECK_(boolean_condition);
|
|
||||||
// or
|
|
||||||
// GTEST_CHECK_(boolean_condition) << "Additional message";
|
|
||||||
//
|
|
||||||
// This checks the condition and if the condition is not satisfied
|
|
||||||
// it prints message about the condition violation, including the
|
|
||||||
// condition itself, plus additional message streamed into it, if any,
|
|
||||||
// and then it aborts the program. It aborts the program irrespective of
|
|
||||||
// whether it is built in the debug mode or not.
|
|
||||||
#define GTEST_CHECK_(condition) \
|
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
|
||||||
if (::testing::internal::IsTrue(condition)) \
|
|
||||||
; \
|
|
||||||
else \
|
|
||||||
GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
|
|
||||||
|
|
||||||
// Macro for referencing flags.
|
// Macro for referencing flags.
|
||||||
#define GTEST_FLAG(name) FLAGS_gtest_##name
|
#define GTEST_FLAG(name) FLAGS_gtest_##name
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@ EXPORTS
|
||||||
?HasNonfatalFailure@TestResult@testing@@QBE_NXZ
|
?HasNonfatalFailure@TestResult@testing@@QBE_NXZ
|
||||||
?Init@RE@internal@testing@@AAEXPBD@Z
|
?Init@RE@internal@testing@@AAEXPBD@Z
|
||||||
?InitGoogleTest@testing@@YAXPAHPAPAD@Z
|
?InitGoogleTest@testing@@YAXPAHPAPAD@Z
|
||||||
|
?InitGoogleTest@testing@@YAXPAHPAPA_W@Z
|
||||||
?IsHRESULTFailure@internal@testing@@YA?AVAssertionResult@2@PBDJ@Z
|
?IsHRESULTFailure@internal@testing@@YA?AVAssertionResult@2@PBDJ@Z
|
||||||
?IsHRESULTSuccess@internal@testing@@YA?AVAssertionResult@2@PBDJ@Z
|
?IsHRESULTSuccess@internal@testing@@YA?AVAssertionResult@2@PBDJ@Z
|
||||||
?IsTrue@internal@testing@@YA_N_N@Z
|
?IsTrue@internal@testing@@YA_N_N@Z
|
||||||
|
|
|
@ -128,6 +128,10 @@ env_with_exceptions = EnvCreator.Create(env_warning_ok,
|
||||||
EnvCreator.WithExceptions)
|
EnvCreator.WithExceptions)
|
||||||
env_without_rtti = EnvCreator.Create(env_warning_ok, EnvCreator.NoRtti)
|
env_without_rtti = EnvCreator.Create(env_warning_ok, EnvCreator.NoRtti)
|
||||||
|
|
||||||
|
env_with_exceptions_and_threads = EnvCreator.Create(env_with_threads,
|
||||||
|
EnvCreator.WithExceptions)
|
||||||
|
env_with_exceptions_and_threads['OBJ_SUFFIX'] = '_with_exceptions_and_threads'
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# Helpers for creating build targets.
|
# Helpers for creating build targets.
|
||||||
|
|
||||||
|
@ -232,7 +236,11 @@ gtest, gtest_main = GtestStaticLibraries(env)
|
||||||
gtest_ex, gtest_main_ex = GtestStaticLibraries(env_with_exceptions)
|
gtest_ex, gtest_main_ex = GtestStaticLibraries(env_with_exceptions)
|
||||||
gtest_no_rtti, gtest_main_no_rtti = GtestStaticLibraries(env_without_rtti)
|
gtest_no_rtti, gtest_main_no_rtti = GtestStaticLibraries(env_without_rtti)
|
||||||
gtest_use_own_tuple, gtest_main_use_own_tuple = GtestStaticLibraries(
|
gtest_use_own_tuple, gtest_main_use_own_tuple = GtestStaticLibraries(
|
||||||
env_use_own_tuple)
|
env_use_own_tuple)
|
||||||
|
gtest_with_threads, gtest_main_with_threads = GtestStaticLibraries(
|
||||||
|
env_with_threads)
|
||||||
|
gtest_ex_with_threads, gtest_main_ex_with_threads = GtestStaticLibraries(
|
||||||
|
env_with_exceptions_and_threads)
|
||||||
|
|
||||||
# Install the libraries if needed.
|
# Install the libraries if needed.
|
||||||
if 'LIB_OUTPUT' in env.Dictionary():
|
if 'LIB_OUTPUT' in env.Dictionary():
|
||||||
|
@ -259,7 +267,6 @@ if BUILD_TESTS:
|
||||||
additional_sources=['../test/gtest-param-test2_test.cc'])
|
additional_sources=['../test/gtest-param-test2_test.cc'])
|
||||||
GtestTest(env, 'gtest_color_test_', gtest)
|
GtestTest(env, 'gtest_color_test_', gtest)
|
||||||
GtestTest(env, 'gtest-linked_ptr_test', gtest_main)
|
GtestTest(env, 'gtest-linked_ptr_test', gtest_main)
|
||||||
GtestTest(env, 'gtest-port_test', gtest_main)
|
|
||||||
GtestTest(env, 'gtest_break_on_failure_unittest_', gtest)
|
GtestTest(env, 'gtest_break_on_failure_unittest_', gtest)
|
||||||
GtestTest(env, 'gtest_filter_unittest_', gtest)
|
GtestTest(env, 'gtest_filter_unittest_', gtest)
|
||||||
GtestTest(env, 'gtest_help_test_', gtest_main)
|
GtestTest(env, 'gtest_help_test_', gtest_main)
|
||||||
|
@ -275,10 +282,12 @@ if BUILD_TESTS:
|
||||||
############################################################
|
############################################################
|
||||||
# Tests targets using custom environments.
|
# Tests targets using custom environments.
|
||||||
GtestTest(env_warning_ok, 'gtest_unittest', gtest_main)
|
GtestTest(env_warning_ok, 'gtest_unittest', gtest_main)
|
||||||
GtestTest(env_with_exceptions, 'gtest_output_test_', gtest_ex)
|
GtestTest(env_with_exceptions_and_threads, 'gtest_output_test_',
|
||||||
|
gtest_ex_with_threads)
|
||||||
GtestTest(env_with_exceptions, 'gtest_throw_on_failure_ex_test', gtest_ex)
|
GtestTest(env_with_exceptions, 'gtest_throw_on_failure_ex_test', gtest_ex)
|
||||||
GtestTest(env_with_threads, 'gtest-death-test_test', gtest_main)
|
GtestTest(env_with_threads, 'gtest-death-test_test', gtest_main_with_threads)
|
||||||
GtestTest(env_with_threads, 'gtest_stress_test', gtest)
|
GtestTest(env_with_threads, 'gtest-port_test', gtest_main_with_threads)
|
||||||
|
GtestTest(env_with_threads, 'gtest_stress_test', gtest_with_threads)
|
||||||
GtestTest(env_less_optimized, 'gtest_env_var_test_', gtest)
|
GtestTest(env_less_optimized, 'gtest_env_var_test_', gtest)
|
||||||
GtestTest(env_less_optimized, 'gtest_uninitialized_test_', gtest)
|
GtestTest(env_less_optimized, 'gtest_uninitialized_test_', gtest)
|
||||||
GtestTest(env_use_own_tuple, 'gtest-tuple_test', gtest_main_use_own_tuple)
|
GtestTest(env_use_own_tuple, 'gtest-tuple_test', gtest_main_use_own_tuple)
|
||||||
|
|
|
@ -119,6 +119,7 @@ class EnvCreator:
|
||||||
# selecting on a platform.
|
# selecting on a platform.
|
||||||
env.Append(CCFLAGS=['-pthread'])
|
env.Append(CCFLAGS=['-pthread'])
|
||||||
env.Append(LINKFLAGS=['-pthread'])
|
env.Append(LINKFLAGS=['-pthread'])
|
||||||
|
env.Append(CPPDEFINES='GTEST_HAS_PTHREAD=1')
|
||||||
WithThreads = classmethod(WithThreads)
|
WithThreads = classmethod(WithThreads)
|
||||||
|
|
||||||
def NoRtti(cls, env):
|
def NoRtti(cls, env):
|
||||||
|
|
|
@ -200,7 +200,9 @@ class SConstructHelper:
|
||||||
'-Wall',
|
'-Wall',
|
||||||
'-Werror',
|
'-Werror',
|
||||||
'-Wshadow',
|
'-Wshadow',
|
||||||
|
'-DGTEST_HAS_PTHREAD=1'
|
||||||
])
|
])
|
||||||
|
env.Append(LINKFLAGS=['-pthread'])
|
||||||
if optimized:
|
if optimized:
|
||||||
env.Append(CCFLAGS=['-O2'], CPPDEFINES=['NDEBUG', '_NDEBUG'])
|
env.Append(CCFLAGS=['-O2'], CPPDEFINES=['NDEBUG', '_NDEBUG'])
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -214,7 +214,7 @@ if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
|
||||||
# TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
|
# TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
|
||||||
# should work to remove it, and/or remove libtool altogether, replacing it
|
# should work to remove it, and/or remove libtool altogether, replacing it
|
||||||
# with direct references to the library and a link path.
|
# with direct references to the library and a link path.
|
||||||
gtest_libs="${build_dir}/lib/libgtest.la"
|
gtest_libs="${build_dir}/lib/libgtest.la @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
|
||||||
gtest_ldflags=""
|
gtest_ldflags=""
|
||||||
|
|
||||||
# We provide hooks to include from either the source or build dir, where the
|
# We provide hooks to include from either the source or build dir, where the
|
||||||
|
@ -222,15 +222,15 @@ if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
|
||||||
# build rules for generated headers and have them automatically be preferred
|
# build rules for generated headers and have them automatically be preferred
|
||||||
# over provided versions.
|
# over provided versions.
|
||||||
gtest_cppflags="-I${build_dir}/include -I${src_dir}/include"
|
gtest_cppflags="-I${build_dir}/include -I${src_dir}/include"
|
||||||
gtest_cxxflags=""
|
gtest_cxxflags="@PTHREAD_CFLAGS@"
|
||||||
else
|
else
|
||||||
# We're using an installed gtest, although it may be staged under some
|
# We're using an installed gtest, although it may be staged under some
|
||||||
# prefix. Assume (as our own libraries do) that we can resolve the prefix,
|
# prefix. Assume (as our own libraries do) that we can resolve the prefix,
|
||||||
# and are present in the dynamic link paths.
|
# and are present in the dynamic link paths.
|
||||||
gtest_ldflags="-L${libdir}"
|
gtest_ldflags="-L${libdir}"
|
||||||
gtest_libs="-l${name}"
|
gtest_libs="-l${name} @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
|
||||||
gtest_cppflags="-I${includedir}"
|
gtest_cppflags="-I${includedir}"
|
||||||
gtest_cxxflags=""
|
gtest_cxxflags="@PTHREAD_CFLAGS@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Do an installation query if requested.
|
# Do an installation query if requested.
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
#include <windows.h> // For DWORD.
|
#include <windows.h> // For DWORD.
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h> // NOLINT
|
||||||
#include <gtest/gtest-spi.h>
|
#include <gtest/gtest-spi.h>
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
@ -1228,6 +1228,9 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
|
||||||
// TestResult contains some private methods that should be hidden from
|
// TestResult contains some private methods that should be hidden from
|
||||||
// Google Test user but are required for testing. This class allow our tests
|
// Google Test user but are required for testing. This class allow our tests
|
||||||
// to access them.
|
// to access them.
|
||||||
|
//
|
||||||
|
// This class is supplied only for the purpose of testing Google Test's own
|
||||||
|
// constructs. Do not use it in user tests, either directly or indirectly.
|
||||||
class TestResultAccessor {
|
class TestResultAccessor {
|
||||||
public:
|
public:
|
||||||
static void RecordProperty(TestResult* test_result,
|
static void RecordProperty(TestResult* test_result,
|
||||||
|
|
|
@ -75,6 +75,94 @@ const int kStdOutFileno = STDOUT_FILENO;
|
||||||
const int kStdErrFileno = STDERR_FILENO;
|
const int kStdErrFileno = STDERR_FILENO;
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
#if GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
|
// ThreadStartSemaphore allows the controller thread to pause execution of
|
||||||
|
// newly created test threads until signalled. Instances of this class must
|
||||||
|
// be created and destroyed in the controller thread.
|
||||||
|
ThreadStartSemaphore::ThreadStartSemaphore() : signalled_(false) {
|
||||||
|
int err = pthread_mutex_init(&mutex_, NULL);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_mutex_init failed with error " << err;
|
||||||
|
err = pthread_cond_init(&cond_, NULL);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_cond_init failed with error " << err;
|
||||||
|
pthread_mutex_lock(&mutex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadStartSemaphore::~ThreadStartSemaphore() {
|
||||||
|
// Every ThreadStartSemaphore object must be signalled. It locks
|
||||||
|
// internal mutex upon creation and Signal unlocks it.
|
||||||
|
GTEST_CHECK_(signalled_);
|
||||||
|
|
||||||
|
int err = pthread_mutex_destroy(&mutex_);
|
||||||
|
GTEST_CHECK_(err == 0)
|
||||||
|
<< "pthread_mutex_destroy failed with error " << err;
|
||||||
|
err = pthread_cond_destroy(&cond_);
|
||||||
|
GTEST_CHECK_(err == 0)
|
||||||
|
<< "pthread_cond_destroy failed with error " << err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signals to all test threads to start. Must be called from the
|
||||||
|
// controlling thread.
|
||||||
|
void ThreadStartSemaphore::Signal() {
|
||||||
|
signalled_ = true;
|
||||||
|
int err = pthread_cond_signal(&cond_);
|
||||||
|
GTEST_CHECK_(err == 0)
|
||||||
|
<< "pthread_cond_signal failed with error " << err;
|
||||||
|
err = pthread_mutex_unlock(&mutex_);
|
||||||
|
GTEST_CHECK_(err == 0)
|
||||||
|
<< "pthread_mutex_unlock failed with error " << err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocks until the controlling thread signals. Should be called from a
|
||||||
|
// test thread.
|
||||||
|
void ThreadStartSemaphore::Wait() {
|
||||||
|
int err = pthread_mutex_lock(&mutex_);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_mutex_lock failed with error " << err;
|
||||||
|
|
||||||
|
while (!signalled_) {
|
||||||
|
err = pthread_cond_wait(&cond_, &mutex_);
|
||||||
|
GTEST_CHECK_(err == 0)
|
||||||
|
<< "pthread_cond_wait failed with error " << err;
|
||||||
|
}
|
||||||
|
err = pthread_mutex_unlock(&mutex_);
|
||||||
|
GTEST_CHECK_(err == 0)
|
||||||
|
<< "pthread_mutex_unlock failed with error " << err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MutexBase::Lock() {
|
||||||
|
const int err = pthread_mutex_lock(&mutex_);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_mutex_lock failed with error " << err;
|
||||||
|
owner_ = pthread_self();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MutexBase::Unlock() {
|
||||||
|
// We don't protect writing to owner_ here, as it's the caller's
|
||||||
|
// responsibility to ensure that the current thread holds the mutex when
|
||||||
|
// this is called.
|
||||||
|
owner_ = 0;
|
||||||
|
const int err = pthread_mutex_unlock(&mutex_);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_mutex_unlock failed with error " << err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does nothing if the current thread holds the mutex. Otherwise, crashes
|
||||||
|
// with high probability.
|
||||||
|
void MutexBase::AssertHeld() const {
|
||||||
|
GTEST_CHECK_(owner_ == pthread_self())
|
||||||
|
<< "Current thread is not holding mutex." << this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::Mutex() {
|
||||||
|
owner_ = 0;
|
||||||
|
const int err = pthread_mutex_init(&mutex_, NULL);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_mutex_init failed with error " << err;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::~Mutex() {
|
||||||
|
const int err = pthread_mutex_destroy(&mutex_);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_mutex_destroy failed with error " << err;
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
#if GTEST_OS_MAC
|
#if GTEST_OS_MAC
|
||||||
|
|
||||||
// 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
|
||||||
|
|
|
@ -342,7 +342,7 @@ void AssertHelper::operator=(const Message& message) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutex for linked pointers.
|
// Mutex for linked pointers.
|
||||||
Mutex g_linked_ptr_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX);
|
GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
||||||
|
|
||||||
// Application pathname gotten in InitGoogleTest.
|
// Application pathname gotten in InitGoogleTest.
|
||||||
String g_executable_path;
|
String g_executable_path;
|
||||||
|
|
|
@ -410,7 +410,7 @@ void SetPthreadFlag() {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#if GTEST_HAS_CLONE
|
#if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
|
TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
|
||||||
if (!testing::GTEST_FLAG(death_test_use_fork)) {
|
if (!testing::GTEST_FLAG(death_test_use_fork)) {
|
||||||
|
@ -422,7 +422,7 @@ TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GTEST_HAS_CLONE
|
#endif // GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
// Tests that a method of another class can be used in a death test.
|
// Tests that a method of another class can be used in a death test.
|
||||||
TEST_F(TestForDeathTest, MethodOfAnotherClass) {
|
TEST_F(TestForDeathTest, MethodOfAnotherClass) {
|
||||||
|
|
|
@ -35,11 +35,16 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#if GTEST_HAS_PTHREAD
|
||||||
|
#include <unistd.h> // For nanosleep().
|
||||||
|
#endif // GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
#if GTEST_OS_MAC
|
#if GTEST_OS_MAC
|
||||||
#include <pthread.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif // GTEST_OS_MAC
|
#endif // GTEST_OS_MAC
|
||||||
|
|
||||||
|
#include <utility> // For std::pair and std::make_pair.
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gtest/gtest-spi.h>
|
#include <gtest/gtest-spi.h>
|
||||||
|
|
||||||
|
@ -52,6 +57,9 @@
|
||||||
#include "src/gtest-internal-inl.h"
|
#include "src/gtest-internal-inl.h"
|
||||||
#undef GTEST_IMPLEMENTATION_
|
#undef GTEST_IMPLEMENTATION_
|
||||||
|
|
||||||
|
using std::make_pair;
|
||||||
|
using std::pair;
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
@ -94,7 +102,7 @@ TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
|
||||||
|
|
||||||
#if GTEST_OS_MAC
|
#if GTEST_OS_MAC
|
||||||
void* ThreadFunc(void* data) {
|
void* ThreadFunc(void* data) {
|
||||||
pthread_mutex_t* mutex = reinterpret_cast<pthread_mutex_t*>(data);
|
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data);
|
||||||
pthread_mutex_lock(mutex);
|
pthread_mutex_lock(mutex);
|
||||||
pthread_mutex_unlock(mutex);
|
pthread_mutex_unlock(mutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -745,5 +753,216 @@ TEST(CaptureDeathTest, CannotReenterStdoutCapture) {
|
||||||
|
|
||||||
#endif // !GTEST_OS_WINDOWS_MOBILE
|
#endif // !GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
|
TEST(ThreadLocalTest, DefaultConstructorInitializesToDefaultValues) {
|
||||||
|
ThreadLocal<int> t1;
|
||||||
|
EXPECT_EQ(0, t1.get());
|
||||||
|
|
||||||
|
ThreadLocal<void*> t2;
|
||||||
|
EXPECT_TRUE(t2.get() == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) {
|
||||||
|
ThreadLocal<int> t1(123);
|
||||||
|
EXPECT_EQ(123, t1.get());
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
ThreadLocal<int*> t2(&i);
|
||||||
|
EXPECT_EQ(&i, t2.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoCopyConstructor {
|
||||||
|
public:
|
||||||
|
NoCopyConstructor() {}
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(NoCopyConstructor);
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(ThreadLocalTest, ValueCopyConstructorIsNotRequiredForDefaultVersion) {
|
||||||
|
ThreadLocal<NoCopyConstructor> bar;
|
||||||
|
bar.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoDefaultContructor {
|
||||||
|
public:
|
||||||
|
explicit NoDefaultContructor(const char*) {}
|
||||||
|
NoDefaultContructor(const NoDefaultContructor&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) {
|
||||||
|
ThreadLocal<NoDefaultContructor> bar(NoDefaultContructor("foo"));
|
||||||
|
bar.pointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ThreadLocalTest, GetAndPointerReturnSameValue) {
|
||||||
|
ThreadLocal<String> thread_local;
|
||||||
|
|
||||||
|
// This is why EXPECT_TRUE is used here rather than EXPECT_EQ because
|
||||||
|
// we don't care about a particular value of thread_local.pointer() here;
|
||||||
|
// we only care about pointer and reference referring to the same lvalue.
|
||||||
|
EXPECT_EQ(thread_local.pointer(), &(thread_local.get()));
|
||||||
|
|
||||||
|
// Verifies the condition still holds after calling set.
|
||||||
|
thread_local.set("foo");
|
||||||
|
EXPECT_EQ(thread_local.pointer(), &(thread_local.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ThreadLocalTest, PointerAndConstPointerReturnSameValue) {
|
||||||
|
ThreadLocal<String> thread_local;
|
||||||
|
const ThreadLocal<String>& const_thread_local = thread_local;
|
||||||
|
|
||||||
|
EXPECT_EQ(thread_local.pointer(), const_thread_local.pointer());
|
||||||
|
|
||||||
|
thread_local.set("foo");
|
||||||
|
EXPECT_EQ(thread_local.pointer(), const_thread_local.pointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GTEST_IS_THREADSAFE
|
||||||
|
TEST(MutexTestDeathTest, AssertHeldShouldAssertWhenNotLocked) {
|
||||||
|
// AssertHeld() is flaky only in the presence of multiple threads accessing
|
||||||
|
// the lock. In this case, the test is robust.
|
||||||
|
EXPECT_DEATH_IF_SUPPORTED({
|
||||||
|
Mutex m;
|
||||||
|
{ MutexLock lock(&m); }
|
||||||
|
m.AssertHeld();
|
||||||
|
},
|
||||||
|
"Current thread is not holding mutex..+");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SleepMilliseconds(int time) {
|
||||||
|
usleep(static_cast<useconds_t>(time * 1000.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
class AtomicCounterWithMutex {
|
||||||
|
public:
|
||||||
|
explicit AtomicCounterWithMutex(Mutex* mutex) :
|
||||||
|
value_(0), mutex_(mutex), random_(42) {}
|
||||||
|
|
||||||
|
void Increment() {
|
||||||
|
MutexLock lock(mutex_);
|
||||||
|
int temp = value_;
|
||||||
|
{
|
||||||
|
// Locking a mutex puts up a memory barrier, preventing reads and
|
||||||
|
// writes to value_ rearranged when observed from other threads.
|
||||||
|
//
|
||||||
|
// We cannot use Mutex and MutexLock here or rely on their memory
|
||||||
|
// barrier functionality as we are testing them here.
|
||||||
|
pthread_mutex_t memory_barrier_mutex;
|
||||||
|
int err = pthread_mutex_init(&memory_barrier_mutex, NULL);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_mutex_init failed with error " << err;
|
||||||
|
err = pthread_mutex_lock(&memory_barrier_mutex);
|
||||||
|
GTEST_CHECK_(err == 0) << "pthread_mutex_lock failed with error " << err;
|
||||||
|
|
||||||
|
SleepMilliseconds(random_.Generate(30));
|
||||||
|
|
||||||
|
err = pthread_mutex_unlock(&memory_barrier_mutex);
|
||||||
|
GTEST_CHECK_(err == 0)
|
||||||
|
<< "pthread_mutex_unlock failed with error " << err;
|
||||||
|
}
|
||||||
|
value_ = temp + 1;
|
||||||
|
}
|
||||||
|
int value() const { return value_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
volatile int value_;
|
||||||
|
Mutex* const mutex_; // Protects value_.
|
||||||
|
Random random_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) {
|
||||||
|
for (int i = 0; i < param.second; ++i)
|
||||||
|
param.first->Increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that the mutex only lets one thread at a time to lock it.
|
||||||
|
TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
|
||||||
|
Mutex mutex;
|
||||||
|
AtomicCounterWithMutex locked_counter(&mutex);
|
||||||
|
|
||||||
|
typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType;
|
||||||
|
const int kCycleCount = 20;
|
||||||
|
const int kThreadCount = 7;
|
||||||
|
scoped_ptr<ThreadType> counting_threads[kThreadCount];
|
||||||
|
ThreadStartSemaphore semaphore;
|
||||||
|
// Creates and runs kThreadCount threads that increment locked_counter
|
||||||
|
// kCycleCount times each.
|
||||||
|
for (int i = 0; i < kThreadCount; ++i) {
|
||||||
|
counting_threads[i].reset(new ThreadType(&CountingThreadFunc,
|
||||||
|
make_pair(&locked_counter,
|
||||||
|
kCycleCount),
|
||||||
|
&semaphore));
|
||||||
|
}
|
||||||
|
semaphore.Signal(); // Start the threads.
|
||||||
|
for (int i = 0; i < kThreadCount; ++i)
|
||||||
|
counting_threads[i]->Join();
|
||||||
|
|
||||||
|
// If the mutex lets more than one thread to increment the counter at a
|
||||||
|
// time, they are likely to encounter a race condition and have some
|
||||||
|
// increments overwritten, resulting in the lower then expected counter
|
||||||
|
// value.
|
||||||
|
EXPECT_EQ(kCycleCount * kThreadCount, locked_counter.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void RunFromThread(void (func)(T), T param) {
|
||||||
|
ThreadWithParam<T> thread(func, param, NULL);
|
||||||
|
thread.Join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RetrieveThreadLocalValue(pair<ThreadLocal<String>*, String*> param) {
|
||||||
|
*param.second = param.first->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) {
|
||||||
|
ThreadLocal<String> thread_local("foo");
|
||||||
|
EXPECT_STREQ("foo", thread_local.get().c_str());
|
||||||
|
|
||||||
|
thread_local.set("bar");
|
||||||
|
EXPECT_STREQ("bar", thread_local.get().c_str());
|
||||||
|
|
||||||
|
String result;
|
||||||
|
RunFromThread(&RetrieveThreadLocalValue, make_pair(&thread_local, &result));
|
||||||
|
EXPECT_STREQ("foo", result.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
class CountedDestructor {
|
||||||
|
public:
|
||||||
|
~CountedDestructor() { counter_++; }
|
||||||
|
static int counter() { return counter_; }
|
||||||
|
static void set_counter(int value) { counter_ = value; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int counter_;
|
||||||
|
};
|
||||||
|
int CountedDestructor::counter_ = 0;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void CallThreadLocalGet(ThreadLocal<T>* threadLocal) {
|
||||||
|
threadLocal->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ThreadLocalTest, DestroysManagedObjectsNoLaterThanSelf) {
|
||||||
|
CountedDestructor::set_counter(0);
|
||||||
|
{
|
||||||
|
ThreadLocal<CountedDestructor> thread_local;
|
||||||
|
ThreadWithParam<ThreadLocal<CountedDestructor>*> thread(
|
||||||
|
&CallThreadLocalGet<CountedDestructor>, &thread_local, NULL);
|
||||||
|
thread.Join();
|
||||||
|
}
|
||||||
|
// There should be 2 desctuctor calls as ThreadLocal also contains a member
|
||||||
|
// T - used as a prototype for copy ctr version.
|
||||||
|
EXPECT_EQ(2, CountedDestructor::counter());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ThreadLocalTest, ThreadLocalMutationsAffectOnlyCurrentThread) {
|
||||||
|
ThreadLocal<String> thread_local;
|
||||||
|
thread_local.set("Foo");
|
||||||
|
EXPECT_STREQ("Foo", thread_local.get().c_str());
|
||||||
|
|
||||||
|
String result;
|
||||||
|
RunFromThread(&RetrieveThreadLocalValue, make_pair(&thread_local, &result));
|
||||||
|
EXPECT_TRUE(result.c_str() == NULL);
|
||||||
|
}
|
||||||
|
#endif // GTEST_IS_THREADSAFE
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
|
@ -484,6 +484,11 @@ class MyOtherListener : public EmptyTestEventListener {};
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
testing::InitGoogleTest(&argc, argv);
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
|
||||||
|
void (*wide_init_google_test)(int*, wchar_t**) = &testing::InitGoogleTest;
|
||||||
|
|
||||||
|
// Ensures the linker doesn't throw away reference to wide InitGoogleTest.
|
||||||
|
GTEST_CHECK_(wide_init_google_test != NULL);
|
||||||
|
|
||||||
TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
|
TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
|
||||||
TestEventListener* listener = new MyListener;
|
TestEventListener* listener = new MyListener;
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,9 @@ SUPPORTS_TYPED_TESTS = 'TypedTest' in test_list
|
||||||
SUPPORTS_THREADS = 'ExpectFailureWithThreadsTest' in test_list
|
SUPPORTS_THREADS = 'ExpectFailureWithThreadsTest' in test_list
|
||||||
SUPPORTS_STACK_TRACES = False
|
SUPPORTS_STACK_TRACES = False
|
||||||
|
|
||||||
CAN_GENERATE_GOLDEN_FILE = SUPPORTS_DEATH_TESTS and SUPPORTS_TYPED_TESTS
|
CAN_GENERATE_GOLDEN_FILE = (SUPPORTS_DEATH_TESTS and
|
||||||
|
SUPPORTS_TYPED_TESTS and
|
||||||
|
SUPPORTS_THREADS)
|
||||||
|
|
||||||
|
|
||||||
class GTestOutputTest(gtest_test_utils.TestCase):
|
class GTestOutputTest(gtest_test_utils.TestCase):
|
||||||
|
@ -314,8 +316,8 @@ that does not support all the required features (death tests""")
|
||||||
"""\nand typed tests). Please check that you are using VC++ 8.0 SP1
|
"""\nand typed tests). Please check that you are using VC++ 8.0 SP1
|
||||||
or higher as your compiler.""")
|
or higher as your compiler.""")
|
||||||
else:
|
else:
|
||||||
message += """\nand typed tests). Please generate the golden file
|
message += """\ntyped tests, and threads). Please generate the
|
||||||
using a binary built with those features enabled."""
|
golden file using a binary built with those features enabled."""
|
||||||
|
|
||||||
sys.stderr.write(message)
|
sys.stderr.write(message)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
@ -7,7 +7,7 @@ Expected: true
|
||||||
gtest_output_test_.cc:#: Failure
|
gtest_output_test_.cc:#: Failure
|
||||||
Value of: 3
|
Value of: 3
|
||||||
Expected: 2
|
Expected: 2
|
||||||
[0;32m[==========] [mRunning 56 tests from 23 test cases.
|
[0;32m[==========] [mRunning 59 tests from 25 test cases.
|
||||||
[0;32m[----------] [mGlobal test environment set-up.
|
[0;32m[----------] [mGlobal test environment set-up.
|
||||||
FooEnvironment::SetUp() called.
|
FooEnvironment::SetUp() called.
|
||||||
BarEnvironment::SetUp() called.
|
BarEnvironment::SetUp() called.
|
||||||
|
@ -506,6 +506,35 @@ Failed
|
||||||
Expected non-fatal failure.
|
Expected non-fatal failure.
|
||||||
|
|
||||||
[0;31m[ FAILED ] [mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
|
[0;31m[ FAILED ] [mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
|
||||||
|
[0;32m[----------] [m2 tests from ExpectFailureWithThreadsTest
|
||||||
|
[0;32m[ RUN ] [mExpectFailureWithThreadsTest.ExpectFatalFailure
|
||||||
|
(expecting 2 failures)
|
||||||
|
gtest_output_test_.cc:#: Failure
|
||||||
|
Failed
|
||||||
|
Expected fatal failure.
|
||||||
|
gtest.cc:#: Failure
|
||||||
|
Expected: 1 fatal failure
|
||||||
|
Actual: 0 failures
|
||||||
|
[0;31m[ FAILED ] [mExpectFailureWithThreadsTest.ExpectFatalFailure
|
||||||
|
[0;32m[ RUN ] [mExpectFailureWithThreadsTest.ExpectNonFatalFailure
|
||||||
|
(expecting 2 failures)
|
||||||
|
gtest_output_test_.cc:#: Failure
|
||||||
|
Failed
|
||||||
|
Expected non-fatal failure.
|
||||||
|
gtest.cc:#: Failure
|
||||||
|
Expected: 1 non-fatal failure
|
||||||
|
Actual: 0 failures
|
||||||
|
[0;31m[ FAILED ] [mExpectFailureWithThreadsTest.ExpectNonFatalFailure
|
||||||
|
[0;32m[----------] [m1 test from ScopedFakeTestPartResultReporterTest
|
||||||
|
[0;32m[ RUN ] [mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
|
||||||
|
(expecting 2 failures)
|
||||||
|
gtest_output_test_.cc:#: Failure
|
||||||
|
Failed
|
||||||
|
Expected fatal failure.
|
||||||
|
gtest_output_test_.cc:#: Failure
|
||||||
|
Failed
|
||||||
|
Expected non-fatal failure.
|
||||||
|
[0;31m[ FAILED ] [mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
|
||||||
[0;32m[----------] [mGlobal test environment tear-down
|
[0;32m[----------] [mGlobal test environment tear-down
|
||||||
BarEnvironment::TearDown() called.
|
BarEnvironment::TearDown() called.
|
||||||
gtest_output_test_.cc:#: Failure
|
gtest_output_test_.cc:#: Failure
|
||||||
|
@ -515,9 +544,9 @@ FooEnvironment::TearDown() called.
|
||||||
gtest_output_test_.cc:#: Failure
|
gtest_output_test_.cc:#: Failure
|
||||||
Failed
|
Failed
|
||||||
Expected fatal failure.
|
Expected fatal failure.
|
||||||
[0;32m[==========] [m56 tests from 23 test cases ran.
|
[0;32m[==========] [m59 tests from 25 test cases ran.
|
||||||
[0;32m[ PASSED ] [m21 tests.
|
[0;32m[ PASSED ] [m21 tests.
|
||||||
[0;31m[ FAILED ] [m35 tests, listed below:
|
[0;31m[ FAILED ] [m38 tests, listed below:
|
||||||
[0;31m[ FAILED ] [mFatalFailureTest.FatalFailureInSubroutine
|
[0;31m[ FAILED ] [mFatalFailureTest.FatalFailureInSubroutine
|
||||||
[0;31m[ FAILED ] [mFatalFailureTest.FatalFailureInNestedSubroutine
|
[0;31m[ FAILED ] [mFatalFailureTest.FatalFailureInNestedSubroutine
|
||||||
[0;31m[ FAILED ] [mFatalFailureTest.NonfatalFailureInSubroutine
|
[0;31m[ FAILED ] [mFatalFailureTest.NonfatalFailureInSubroutine
|
||||||
|
@ -553,8 +582,11 @@ Expected fatal failure.
|
||||||
[0;31m[ FAILED ] [mExpectFailureTest.ExpectNonFatalFailure
|
[0;31m[ FAILED ] [mExpectFailureTest.ExpectNonFatalFailure
|
||||||
[0;31m[ FAILED ] [mExpectFailureTest.ExpectFatalFailureOnAllThreads
|
[0;31m[ FAILED ] [mExpectFailureTest.ExpectFatalFailureOnAllThreads
|
||||||
[0;31m[ FAILED ] [mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
|
[0;31m[ FAILED ] [mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
|
||||||
|
[0;31m[ FAILED ] [mExpectFailureWithThreadsTest.ExpectFatalFailure
|
||||||
|
[0;31m[ FAILED ] [mExpectFailureWithThreadsTest.ExpectNonFatalFailure
|
||||||
|
[0;31m[ FAILED ] [mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
|
||||||
|
|
||||||
35 FAILED TESTS
|
38 FAILED TESTS
|
||||||
[0;33m YOU HAVE 1 DISABLED TEST
|
[0;33m YOU HAVE 1 DISABLED TEST
|
||||||
|
|
||||||
[mNote: Google Test filter = FatalFailureTest.*:LoggingTest.*
|
[mNote: Google Test filter = FatalFailureTest.*:LoggingTest.*
|
||||||
|
|
|
@ -48,23 +48,17 @@
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using internal::scoped_ptr;
|
||||||
using internal::String;
|
using internal::String;
|
||||||
using internal::TestPropertyKeyIs;
|
using internal::TestPropertyKeyIs;
|
||||||
using internal::Vector;
|
using internal::Vector;
|
||||||
|
using internal::ThreadStartSemaphore;
|
||||||
|
using internal::ThreadWithParam;
|
||||||
|
|
||||||
// In order to run tests in this file, for platforms where Google Test is
|
// In order to run tests in this file, for platforms where Google Test is
|
||||||
// thread safe, implement ThreadWithParam with the following interface:
|
// thread safe, implement ThreadWithParam and ThreadStartSemaphore. See the
|
||||||
//
|
// description of their API in gtest-port.h, where they are defined for
|
||||||
// template <typename T> class ThreadWithParam {
|
// already supported platforms.
|
||||||
// public:
|
|
||||||
// // Creates the thread. The thread should execute thread_func(param) when
|
|
||||||
// // started by a call to Start().
|
|
||||||
// ThreadWithParam(void (*thread_func)(T), T param);
|
|
||||||
// // Starts the thread.
|
|
||||||
// void Start();
|
|
||||||
// // Waits for the thread to finish.
|
|
||||||
// void Join();
|
|
||||||
// };
|
|
||||||
|
|
||||||
// How many threads to create?
|
// How many threads to create?
|
||||||
const int kThreadCount = 50;
|
const int kThreadCount = 50;
|
||||||
|
@ -132,22 +126,17 @@ void CheckTestFailureCount(int expected_failures) {
|
||||||
// Tests using SCOPED_TRACE() and Google Test assertions in many threads
|
// Tests using SCOPED_TRACE() and Google Test assertions in many threads
|
||||||
// concurrently.
|
// concurrently.
|
||||||
TEST(StressTest, CanUseScopedTraceAndAssertionsInManyThreads) {
|
TEST(StressTest, CanUseScopedTraceAndAssertionsInManyThreads) {
|
||||||
ThreadWithParam<int>* threads[kThreadCount] = {};
|
{
|
||||||
for (int i = 0; i != kThreadCount; i++) {
|
scoped_ptr<ThreadWithParam<int> > threads[kThreadCount];
|
||||||
// Creates a thread to run the ManyAsserts() function.
|
ThreadStartSemaphore semaphore;
|
||||||
threads[i] = new ThreadWithParam<int>(&ManyAsserts, i);
|
for (int i = 0; i != kThreadCount; i++)
|
||||||
|
threads[i].reset(new ThreadWithParam<int>(&ManyAsserts, i, &semaphore));
|
||||||
|
|
||||||
// Starts the thread.
|
semaphore.Signal(); // Starts all the threads.
|
||||||
threads[i]->Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point, we have many threads running.
|
// Blocks until all the threads are done.
|
||||||
|
for (int i = 0; i != kThreadCount; i++)
|
||||||
for (int i = 0; i != kThreadCount; i++) {
|
threads[i]->Join();
|
||||||
// We block until the thread is done.
|
|
||||||
threads[i]->Join();
|
|
||||||
delete threads[i];
|
|
||||||
threads[i] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensures that kThreadCount*kThreadCount failures have been reported.
|
// Ensures that kThreadCount*kThreadCount failures have been reported.
|
||||||
|
@ -180,8 +169,7 @@ void FailingThread(bool is_fatal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateFatalFailureInAnotherThread(bool is_fatal) {
|
void GenerateFatalFailureInAnotherThread(bool is_fatal) {
|
||||||
ThreadWithParam<bool> thread(&FailingThread, is_fatal);
|
ThreadWithParam<bool> thread(&FailingThread, is_fatal, NULL);
|
||||||
thread.Start();
|
|
||||||
thread.Join();
|
thread.Join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,6 @@ using testing::internal::StreamableToString;
|
||||||
using testing::internal::String;
|
using testing::internal::String;
|
||||||
using testing::internal::TestEventListenersAccessor;
|
using testing::internal::TestEventListenersAccessor;
|
||||||
using testing::internal::TestResultAccessor;
|
using testing::internal::TestResultAccessor;
|
||||||
using testing::internal::ThreadLocal;
|
|
||||||
using testing::internal::UInt32;
|
using testing::internal::UInt32;
|
||||||
using testing::internal::Vector;
|
using testing::internal::Vector;
|
||||||
using testing::internal::WideStringToUtf8;
|
using testing::internal::WideStringToUtf8;
|
||||||
|
@ -6577,23 +6576,6 @@ TEST(StaticAssertTypeEqTest, CompilesForEqualTypes) {
|
||||||
StaticAssertTypeEq<int*, IntAlias*>();
|
StaticAssertTypeEq<int*, IntAlias*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ThreadLocalTest, DefaultConstructor) {
|
|
||||||
ThreadLocal<int> t1;
|
|
||||||
EXPECT_EQ(0, t1.get());
|
|
||||||
|
|
||||||
ThreadLocal<void*> t2;
|
|
||||||
EXPECT_TRUE(t2.get() == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(ThreadLocalTest, Init) {
|
|
||||||
ThreadLocal<int> t1(123);
|
|
||||||
EXPECT_EQ(123, t1.get());
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
ThreadLocal<int*> t2(&i);
|
|
||||||
EXPECT_EQ(&i, t2.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(GetCurrentOsStackTraceExceptTopTest, ReturnsTheStackTrace) {
|
TEST(GetCurrentOsStackTraceExceptTopTest, ReturnsTheStackTrace) {
|
||||||
testing::UnitTest* const unit_test = testing::UnitTest::GetInstance();
|
testing::UnitTest* const unit_test = testing::UnitTest::GetInstance();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user