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:
zhanyong.wan 2010-02-24 17:19:25 +00:00
parent dd280cfa8d
commit 3bef459eac
21 changed files with 796 additions and 119 deletions

21
CHANGES
View File

@ -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:
* New feature: the event listener API

View File

@ -30,6 +30,9 @@ include_directories(
link_directories(
${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
# tweak these definitions to suit your need.
if (MSVC)
@ -39,6 +42,11 @@ if (MSVC)
set(cxx_default "${cxx_base} -EHsc -D_HAS_EXCEPTIONS=1")
else()
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")
endif()
@ -53,6 +61,9 @@ function(cxx_library name cxx_flags)
set_target_properties(${name}
PROPERTIES
COMPILE_FLAGS "${cxx_flags}")
if (CMAKE_USE_PTHREADS_INIT)
target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
endif()
endfunction()
cxx_library(gtest "${cxx_default}" src/gtest-all.cc)
@ -150,6 +161,7 @@ endfunction()
cxx_test(gtest_unittest gtest_main)
if (build_all_gtest_tests)
cxx_test(gtest-death-test_test gtest_main)
cxx_test(gtest_environment_test gtest)
cxx_test(gtest-filepath_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}"
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}"
gtest_main_no_rtti test/gtest_unittest.cc)

View File

@ -11,10 +11,6 @@ EXTRA_DIST = \
include/gtest/internal/gtest-type-util.h.pump \
include/gtest/internal/gtest-param-util-generated.h.pump \
make/Makefile \
run_tests.py \
scons/SConscript \
scons/SConstruct \
scons/SConstruct.common \
scripts/fuse_gtest_files.py \
scripts/gen_gtest_pred_impl.py \
scripts/generate_gtest_def.py \
@ -28,8 +24,7 @@ EXTRA_DIST += \
src/gtest-internal-inl.h \
src/gtest-port.cc \
src/gtest-test-part.cc \
src/gtest-typed-test.cc \
src/gtest.def
src/gtest-typed-test.cc
# Sample files that we don't compile.
EXTRA_DIST += \
@ -112,6 +107,10 @@ EXTRA_DIST += \
test/run_tests_util.py \
test/run_tests_util_test.py
# CMake script
EXTRA_DIST += \
CMakeLists.txt
# MSVC project files
EXTRA_DIST += \
msvc/gtest-md.sln \
@ -123,7 +122,8 @@ EXTRA_DIST += \
msvc/gtest_prod_test-md.vcproj \
msvc/gtest_prod_test.vcproj \
msvc/gtest_unittest-md.vcproj \
msvc/gtest_unittest.vcproj
msvc/gtest_unittest.vcproj \
msvc/gtest.def
# xcode project files
EXTRA_DIST += \
@ -173,6 +173,14 @@ EXTRA_DIST += $(m4data_DATA)
# directories.
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.
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
check_PROGRAMS += test/gtest_all_test
test_gtest_all_test_SOURCES = test/gtest_all_test.cc
test_gtest_all_test_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
test_gtest_all_test_LDADD = $(PTHREAD_LIBS) $(PTHREAD_CFLAGS) \
lib/libgtest_main.la
test_gtest_all_test_LDADD = 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"

View File

@ -5,7 +5,7 @@ m4_include(m4/acx_pthread.m4)
# "[1.0.1]"). It also asumes that there won't be any closing parenthesis
# between "AC_INIT(" and the closing ")" including comments and strings.
AC_INIT([Google C++ Testing Framework],
[1.4.0],
[1.5.0],
[googletestframework@googlegroups.com],
[gtest])
@ -39,8 +39,24 @@ AS_IF([test "$PYTHON" != ":"],
[AM_PYTHON_CHECK_VERSION([$PYTHON],[2.3],[:],[PYTHON=":"])])
AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"])
# Check for pthreads.
ACX_PTHREAD
# Configure pthreads.
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.

View File

@ -77,7 +77,7 @@ namespace testing {
namespace internal {
// 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
// a non-template class because different types of linked_ptr<> can refer to

View File

@ -343,10 +343,14 @@
#endif // GTEST_HAS_RTTI
// Determines whether <pthread.h> is available.
// Determines whether Google Test can use the pthreads library.
#ifndef GTEST_HAS_PTHREAD
// The user didn't tell us, so we need to figure it out.
#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_SOLARIS)
// The user didn't tell us explicitly, so we assume pthreads support is
// 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
// Determines whether Google Test can use tr1/tuple. You can define
@ -708,6 +712,27 @@ class GTestLog {
inline void LogToStderr() {}
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_
// Defines the stderr capturer:
@ -736,6 +761,260 @@ const ::std::vector<String>& GetArgvs();
// 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,
// and thread-local variable). Necessary for compiling Google Test where
// mutex is not supported - using Google Test in multiple threads is not
@ -744,14 +1023,14 @@ const ::std::vector<String>& GetArgvs();
class Mutex {
public:
Mutex() {}
explicit Mutex(int /*unused*/) {}
void AssertHeld() const {}
enum { NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX = 0 };
};
// 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.
#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
extern ::testing::internal::Mutex mutex
#define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
class GTestMutexLock {
public:
explicit GTestMutexLock(Mutex*) {} // NOLINT
@ -772,14 +1051,16 @@ class ThreadLocal {
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.
// Therefore Google Test is not thread-safe.
#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
// compiler and generates a warning in Sun Studio. The Nokia Symbian
// 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.
// 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.
#define GTEST_FLAG(name) FLAGS_gtest_##name

View File

@ -75,6 +75,7 @@ EXPORTS
?HasNonfatalFailure@TestResult@testing@@QBE_NXZ
?Init@RE@internal@testing@@AAEXPBD@Z
?InitGoogleTest@testing@@YAXPAHPAPAD@Z
?InitGoogleTest@testing@@YAXPAHPAPA_W@Z
?IsHRESULTFailure@internal@testing@@YA?AVAssertionResult@2@PBDJ@Z
?IsHRESULTSuccess@internal@testing@@YA?AVAssertionResult@2@PBDJ@Z
?IsTrue@internal@testing@@YA_N_N@Z

View File

@ -128,6 +128,10 @@ env_with_exceptions = EnvCreator.Create(env_warning_ok,
EnvCreator.WithExceptions)
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.
@ -232,7 +236,11 @@ gtest, gtest_main = GtestStaticLibraries(env)
gtest_ex, gtest_main_ex = GtestStaticLibraries(env_with_exceptions)
gtest_no_rtti, gtest_main_no_rtti = GtestStaticLibraries(env_without_rtti)
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.
if 'LIB_OUTPUT' in env.Dictionary():
@ -259,7 +267,6 @@ if BUILD_TESTS:
additional_sources=['../test/gtest-param-test2_test.cc'])
GtestTest(env, 'gtest_color_test_', gtest)
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_filter_unittest_', gtest)
GtestTest(env, 'gtest_help_test_', gtest_main)
@ -275,10 +282,12 @@ if BUILD_TESTS:
############################################################
# Tests targets using custom environments.
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_threads, 'gtest-death-test_test', gtest_main)
GtestTest(env_with_threads, 'gtest_stress_test', gtest)
GtestTest(env_with_threads, 'gtest-death-test_test', gtest_main_with_threads)
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_uninitialized_test_', gtest)
GtestTest(env_use_own_tuple, 'gtest-tuple_test', gtest_main_use_own_tuple)

View File

@ -119,6 +119,7 @@ class EnvCreator:
# selecting on a platform.
env.Append(CCFLAGS=['-pthread'])
env.Append(LINKFLAGS=['-pthread'])
env.Append(CPPDEFINES='GTEST_HAS_PTHREAD=1')
WithThreads = classmethod(WithThreads)
def NoRtti(cls, env):

View File

@ -200,7 +200,9 @@ class SConstructHelper:
'-Wall',
'-Werror',
'-Wshadow',
'-DGTEST_HAS_PTHREAD=1'
])
env.Append(LINKFLAGS=['-pthread'])
if optimized:
env.Append(CCFLAGS=['-O2'], CPPDEFINES=['NDEBUG', '_NDEBUG'])
else:

View File

@ -214,7 +214,7 @@ if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
# TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
# should work to remove it, and/or remove libtool altogether, replacing it
# 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=""
# 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
# over provided versions.
gtest_cppflags="-I${build_dir}/include -I${src_dir}/include"
gtest_cxxflags=""
gtest_cxxflags="@PTHREAD_CFLAGS@"
else
# 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,
# and are present in the dynamic link paths.
gtest_ldflags="-L${libdir}"
gtest_libs="-l${name}"
gtest_libs="-l${name} @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
gtest_cppflags="-I${includedir}"
gtest_cxxflags=""
gtest_cxxflags="@PTHREAD_CFLAGS@"
fi
# Do an installation query if requested.

View File

@ -60,7 +60,7 @@
#include <windows.h> // For DWORD.
#endif // GTEST_OS_WINDOWS
#include <gtest/gtest.h>
#include <gtest/gtest.h> // NOLINT
#include <gtest/gtest-spi.h>
namespace testing {
@ -1228,6 +1228,9 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
// TestResult contains some private methods that should be hidden from
// Google Test user but are required for testing. This class allow our tests
// 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 {
public:
static void RecordProperty(TestResult* test_result,

View File

@ -75,6 +75,94 @@ const int kStdOutFileno = STDOUT_FILENO;
const int kStdErrFileno = STDERR_FILENO;
#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
// Returns the number of threads running in the process, or 0 to indicate that

View File

@ -342,7 +342,7 @@ void AssertHelper::operator=(const Message& message) const {
}
// 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.
String g_executable_path;

View File

@ -410,7 +410,7 @@ void SetPthreadFlag() {
} // namespace
#if GTEST_HAS_CLONE
#if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
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.
TEST_F(TestForDeathTest, MethodOfAnotherClass) {

View File

@ -35,11 +35,16 @@
#include <stdio.h>
#if GTEST_HAS_PTHREAD
#include <unistd.h> // For nanosleep().
#endif // GTEST_HAS_PTHREAD
#if GTEST_OS_MAC
#include <pthread.h>
#include <time.h>
#endif // GTEST_OS_MAC
#include <utility> // For std::pair and std::make_pair.
#include <gtest/gtest.h>
#include <gtest/gtest-spi.h>
@ -52,6 +57,9 @@
#include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
using std::make_pair;
using std::pair;
namespace testing {
namespace internal {
@ -94,7 +102,7 @@ TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
#if GTEST_OS_MAC
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_unlock(mutex);
return NULL;
@ -745,5 +753,216 @@ TEST(CaptureDeathTest, CannotReenterStdoutCapture) {
#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 testing

View File

@ -484,6 +484,11 @@ class MyOtherListener : public EmptyTestEventListener {};
int main(int argc, char **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();
TestEventListener* listener = new MyListener;

View File

@ -238,7 +238,9 @@ SUPPORTS_TYPED_TESTS = 'TypedTest' in test_list
SUPPORTS_THREADS = 'ExpectFailureWithThreadsTest' in test_list
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):
@ -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
or higher as your compiler.""")
else:
message += """\nand typed tests). Please generate the golden file
using a binary built with those features enabled."""
message += """\ntyped tests, and threads). Please generate the
golden file using a binary built with those features enabled."""
sys.stderr.write(message)
sys.exit(1)

View File

@ -7,7 +7,7 @@ Expected: true
gtest_output_test_.cc:#: Failure
Value of: 3
Expected: 2
[==========] Running 56 tests from 23 test cases.
[==========] Running 59 tests from 25 test cases.
[----------] Global test environment set-up.
FooEnvironment::SetUp() called.
BarEnvironment::SetUp() called.
@ -506,6 +506,35 @@ Failed
Expected non-fatal failure.
[ FAILED ] ExpectFailureTest.ExpectNonFatalFailureOnAllThreads
[----------] 2 tests from ExpectFailureWithThreadsTest
[ RUN ] ExpectFailureWithThreadsTest.ExpectFatalFailure
(expecting 2 failures)
gtest_output_test_.cc:#: Failure
Failed
Expected fatal failure.
gtest.cc:#: Failure
Expected: 1 fatal failure
Actual: 0 failures
[ FAILED ] ExpectFailureWithThreadsTest.ExpectFatalFailure
[ RUN ] ExpectFailureWithThreadsTest.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
[ FAILED ] ExpectFailureWithThreadsTest.ExpectNonFatalFailure
[----------] 1 test from ScopedFakeTestPartResultReporterTest
[ RUN ] ScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
(expecting 2 failures)
gtest_output_test_.cc:#: Failure
Failed
Expected fatal failure.
gtest_output_test_.cc:#: Failure
Failed
Expected non-fatal failure.
[ FAILED ] ScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
[----------] Global test environment tear-down
BarEnvironment::TearDown() called.
gtest_output_test_.cc:#: Failure
@ -515,9 +544,9 @@ FooEnvironment::TearDown() called.
gtest_output_test_.cc:#: Failure
Failed
Expected fatal failure.
[==========] 56 tests from 23 test cases ran.
[==========] 59 tests from 25 test cases ran.
[ PASSED ] 21 tests.
[ FAILED ] 35 tests, listed below:
[ FAILED ] 38 tests, listed below:
[ FAILED ] FatalFailureTest.FatalFailureInSubroutine
[ FAILED ] FatalFailureTest.FatalFailureInNestedSubroutine
[ FAILED ] FatalFailureTest.NonfatalFailureInSubroutine
@ -553,8 +582,11 @@ Expected fatal failure.
[ FAILED ] ExpectFailureTest.ExpectNonFatalFailure
[ FAILED ] ExpectFailureTest.ExpectFatalFailureOnAllThreads
[ FAILED ] ExpectFailureTest.ExpectNonFatalFailureOnAllThreads
[ FAILED ] ExpectFailureWithThreadsTest.ExpectFatalFailure
[ FAILED ] ExpectFailureWithThreadsTest.ExpectNonFatalFailure
[ FAILED ] ScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
35 FAILED TESTS
38 FAILED TESTS
 YOU HAVE 1 DISABLED TEST
Note: Google Test filter = FatalFailureTest.*:LoggingTest.*

View File

@ -48,23 +48,17 @@
namespace testing {
namespace {
using internal::scoped_ptr;
using internal::String;
using internal::TestPropertyKeyIs;
using internal::Vector;
using internal::ThreadStartSemaphore;
using internal::ThreadWithParam;
// In order to run tests in this file, for platforms where Google Test is
// thread safe, implement ThreadWithParam with the following interface:
//
// template <typename T> class ThreadWithParam {
// 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();
// };
// thread safe, implement ThreadWithParam and ThreadStartSemaphore. See the
// description of their API in gtest-port.h, where they are defined for
// already supported platforms.
// How many threads to create?
const int kThreadCount = 50;
@ -132,22 +126,17 @@ void CheckTestFailureCount(int expected_failures) {
// Tests using SCOPED_TRACE() and Google Test assertions in many threads
// concurrently.
TEST(StressTest, CanUseScopedTraceAndAssertionsInManyThreads) {
ThreadWithParam<int>* threads[kThreadCount] = {};
for (int i = 0; i != kThreadCount; i++) {
// Creates a thread to run the ManyAsserts() function.
threads[i] = new ThreadWithParam<int>(&ManyAsserts, i);
{
scoped_ptr<ThreadWithParam<int> > threads[kThreadCount];
ThreadStartSemaphore semaphore;
for (int i = 0; i != kThreadCount; i++)
threads[i].reset(new ThreadWithParam<int>(&ManyAsserts, i, &semaphore));
// Starts the thread.
threads[i]->Start();
}
semaphore.Signal(); // Starts all the threads.
// At this point, we have many threads running.
for (int i = 0; i != kThreadCount; i++) {
// We block until the thread is done.
threads[i]->Join();
delete threads[i];
threads[i] = NULL;
// Blocks until all the threads are done.
for (int i = 0; i != kThreadCount; i++)
threads[i]->Join();
}
// Ensures that kThreadCount*kThreadCount failures have been reported.
@ -180,8 +169,7 @@ void FailingThread(bool is_fatal) {
}
void GenerateFatalFailureInAnotherThread(bool is_fatal) {
ThreadWithParam<bool> thread(&FailingThread, is_fatal);
thread.Start();
ThreadWithParam<bool> thread(&FailingThread, is_fatal, NULL);
thread.Join();
}

View File

@ -174,7 +174,6 @@ using testing::internal::StreamableToString;
using testing::internal::String;
using testing::internal::TestEventListenersAccessor;
using testing::internal::TestResultAccessor;
using testing::internal::ThreadLocal;
using testing::internal::UInt32;
using testing::internal::Vector;
using testing::internal::WideStringToUtf8;
@ -6577,23 +6576,6 @@ TEST(StaticAssertTypeEqTest, CompilesForEqualTypes) {
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) {
testing::UnitTest* const unit_test = testing::UnitTest::GetInstance();