summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2009-06-17 21:06:27 +0000
committerzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2009-06-17 21:06:27 +0000
commit6d63ee6720540cadb8919037c5d41a6413cc9101 (patch)
tree1dd721d45ddd731134dda23f8368781979dc0b09
parent16b967aa9c80cf8606c65d375865b77a6bcad255 (diff)
downloadgtest-6d63ee6720540cadb8919037c5d41a6413cc9101.tar.gz
gtest-6d63ee6720540cadb8919037c5d41a6413cc9101.tar.bz2
gtest-6d63ee6720540cadb8919037c5d41a6413cc9101.tar.xz
Implements a subset of TR1 tuple needed by gtest and gmock (by Zhanyong Wan); cleaned up the Python tests (by Vlad Losev); made run_tests.py invokable from any directory (by Vlad Losev).
git-svn-id: http://googletest.googlecode.com/svn/trunk@267 861a406c-534a-0410-8894-cb66d6ee9925
-rw-r--r--Makefile.am17
-rw-r--r--README26
-rw-r--r--include/gtest/internal/gtest-port.h43
-rw-r--r--include/gtest/internal/gtest-tuple.h945
-rw-r--r--include/gtest/internal/gtest-tuple.h.pump320
-rwxr-xr-xrun_tests.py77
-rw-r--r--scons/SConscript39
-rw-r--r--test/gtest-tuple_test.cc288
-rwxr-xr-xtest/gtest_break_on_failure_unittest.py3
-rwxr-xr-xtest/gtest_color_test.py7
-rwxr-xr-xtest/gtest_env_var_test.py12
-rwxr-xr-xtest/gtest_filter_unittest.py72
-rwxr-xr-xtest/gtest_help_test.py5
-rwxr-xr-xtest/gtest_list_tests_unittest.py7
-rwxr-xr-xtest/gtest_nc_test.py5
-rwxr-xr-xtest/gtest_output_test.py87
-rwxr-xr-xtest/gtest_test_utils.py37
-rwxr-xr-xtest/gtest_throw_on_failure_test.py5
-rwxr-xr-xtest/gtest_uninitialized_test.py4
-rwxr-xr-xtest/gtest_xml_outfiles_test.py15
-rwxr-xr-xtest/gtest_xml_output_unittest.py31
-rwxr-xr-xtest/gtest_xml_test_utils.py7
-rwxr-xr-xtest/run_tests_test.py50
23 files changed, 1941 insertions, 161 deletions
diff --git a/Makefile.am b/Makefile.am
index 148a076..eba2776 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -300,6 +300,23 @@ test_gtest_no_rtti_test_SOURCES = test/gtest_unittest.cc \
src/gtest_main.cc
test_gtest_no_rtti_test_CXXFLAGS = $(AM_CXXFLAGS) -fno-rtti -DGTEST_HAS_RTTI=0
+# Verifies that Google Test's own TR1 tuple implementation works.
+TESTS += test/gtest-tuple_test
+check_PROGRAMS += test/gtest-tuple_test
+test_gtest_tuple_test_SOURCES = test/gtest-tuple_test.cc \
+ src/gtest-all.cc \
+ src/gtest_main.cc
+test_gtest_tuple_test_CXXFLAGS = $(AM_CXXFLAGS) -DGTEST_USE_OWN_TR1_TUPLE=1
+
+# Verifies that Google Test's features that use its own TR1 tuple work.
+TESTS += test/gtest_use_own_tuple_test
+check_PROGRAMS += test/gtest_use_own_tuple_test
+test_gtest_use_own_tuple_test_SOURCES = test/gtest-param-test_test.cc \
+ test/gtest-param-test2_test.cc \
+ src/gtest-all.cc
+test_gtest_use_own_tuple_test_CXXFLAGS = \
+ $(AM_CXXFLAGS) -DGTEST_USE_OWN_TR1_TUPLE=1
+
# The following tests depend on the presence of a Python installation and are
# keyed off of it. TODO(chandlerc@google.com): While we currently only attempt
# to build and execute these tests if Autoconf has found Python v2.4 on the
diff --git a/README b/README
index 4b3546f..cb8d4de 100644
--- a/README
+++ b/README
@@ -112,6 +112,32 @@ which contains all of the source code. Here are some examples in Linux:
tar -xvjf gtest-X.Y.Z.tar.bz2
unzip gtest-X.Y.Z.zip
+Choosing a TR1 Tuple Library
+----------------------------
+Some Google Test features require the C++ Technical Report 1 (TR1)
+tuple library, which is not yet widely available with all compilers.
+The good news is that Google Test implements a subset of TR1 tuple
+that's enough for its own need, and will automatically use this when
+the compiler doesn't provide TR1 tuple.
+
+Usually you don't need to care about which tuple library Google Test
+uses. However, if your project already uses TR1 tuple, you need to
+tell Google Test to use the same TR1 tuple library the rest of your
+project uses (this requirement is new in Google Test 1.4.0, so you may
+need to take care of it when upgrading from an earlier version), or
+the two tuple implementations will clash. To do that, add
+
+ -DGTEST_USE_OWN_TR1_TUPLE=0
+
+to the compiler flags while compiling Google Test and your tests.
+
+If you don't want Google Test to use tuple at all, add
+
+ -DGTEST_HAS_TR1_TUPLE=0
+
+to the compiler flags. All features using tuple will be disabled in
+this mode.
+
Building the Source
-------------------
### Linux, Mac OS X (without Xcode), and Cygwin ###
diff --git a/include/gtest/internal/gtest-port.h b/include/gtest/internal/gtest-port.h
index e6b9d14..e1a3597 100644
--- a/include/gtest/internal/gtest-port.h
+++ b/include/gtest/internal/gtest-port.h
@@ -58,11 +58,15 @@
// GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that
// std::wstring does/doesn't work (Google Test can
// be used where std::wstring is unavailable).
-// GTEST_HAS_TR1_TUPLE 1 - Define it to 1/0 to indicate tr1::tuple
+// GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple
// is/isn't available.
// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the
// compiler supports Microsoft's "Structured
// Exception Handling".
+// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google
+// Test's own tr1 tuple implementation should be
+// used. Unused when the user sets
+// GTEST_HAS_TR1_TUPLE to 0.
// This header defines the following utilities:
//
@@ -339,28 +343,41 @@
#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC)
#endif // GTEST_HAS_PTHREAD
-// Determines whether tr1/tuple is available. If you have tr1/tuple
-// on your platform, define GTEST_HAS_TR1_TUPLE=1 for both the Google
-// Test project and your tests. If you would like Google Test to detect
-// tr1/tuple on your platform automatically, please open an issue
-// ticket at http://code.google.com/p/googletest.
+// Determines whether Google Test can use tr1/tuple. You can define
+// this macro to 0 to prevent Google Test from using tuple (any
+// feature depending on tuple with be disabled in this mode).
#ifndef GTEST_HAS_TR1_TUPLE
+// The user didn't tell us not to do it, so we assume it's OK.
+#define GTEST_HAS_TR1_TUPLE 1
+#endif // GTEST_HAS_TR1_TUPLE
+
+// Determines whether Google Test's own tr1 tuple implementation
+// should be used.
+#ifndef GTEST_USE_OWN_TR1_TUPLE
// The user didn't tell us, so we need to figure it out.
-// GCC provides <tr1/tuple> since 4.0.0.
+// We use our own tr1 tuple if we aren't sure the user has an
+// implementation of it already. At this time, GCC 4.0.0+ is the only
+// mainstream compiler that comes with a TR1 tuple implementation.
+// MSVC 2008 (9.0) provides TR1 tuple in a 323 MB Feature Pack
+// download, which we cannot assume the user has. MSVC 2010 isn't
+// released yet.
#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
-#define GTEST_HAS_TR1_TUPLE 1
+#define GTEST_USE_OWN_TR1_TUPLE 0
#else
-#define GTEST_HAS_TR1_TUPLE 0
-#endif // __GNUC__
-#endif // GTEST_HAS_TR1_TUPLE
+#define GTEST_USE_OWN_TR1_TUPLE 1
+#endif // defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+
+#endif // GTEST_USE_OWN_TR1_TUPLE
// To avoid conditional compilation everywhere, we make it
// gtest-port.h's responsibility to #include the header implementing
// tr1/tuple.
#if GTEST_HAS_TR1_TUPLE
-#if GTEST_OS_SYMBIAN
+#if GTEST_USE_OWN_TR1_TUPLE
+#include <gtest/internal/gtest-tuple.h>
+#elif GTEST_OS_SYMBIAN
// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
// use STLport's tuple implementation, which unfortunately doesn't
@@ -398,7 +415,7 @@
// If the compiler is not GCC 4.0+, we assume the user is using a
// spec-conforming TR1 implementation.
#include <tuple>
-#endif // GTEST_OS_SYMBIAN
+#endif // GTEST_USE_OWN_TR1_TUPLE
#endif // GTEST_HAS_TR1_TUPLE
diff --git a/include/gtest/internal/gtest-tuple.h b/include/gtest/internal/gtest-tuple.h
new file mode 100644
index 0000000..1c2034a
--- /dev/null
+++ b/include/gtest/internal/gtest-tuple.h
@@ -0,0 +1,945 @@
+// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERAL_GTEST_TUPLE_H_
+
+#include <utility> // For ::std::pair.
+
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+#define GTEST_1_TUPLE_(T) tuple<T##0>
+#define GTEST_2_TUPLE_(T) tuple<T##0, T##1>
+#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2>
+#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3>
+#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4>
+#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5>
+#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6>
+#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, T##7>
+#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+ T##7, T##8>
+#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+ T##7, T##8, T##9>
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+#define GTEST_0_TYPENAMES_(T)
+#define GTEST_1_TYPENAMES_(T) typename T##0
+#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1
+#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2
+#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3
+#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4
+#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5
+#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6
+#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6, typename T##7
+#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6, \
+ typename T##7, typename T##8
+#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6, \
+ typename T##7, typename T##8, typename T##9
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior. We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <typename T0 = void, typename T1 = void, typename T2 = void,
+ typename T3 = void, typename T4 = void, typename T5 = void,
+ typename T6 = void, typename T7 = void, typename T8 = void,
+ typename T9 = void>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; }; // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&. This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; }; // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>. kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 0, GTEST_10_TUPLE_(T)> { typedef T0 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 1, GTEST_10_TUPLE_(T)> { typedef T1 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 2, GTEST_10_TUPLE_(T)> { typedef T2 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 3, GTEST_10_TUPLE_(T)> { typedef T3 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 4, GTEST_10_TUPLE_(T)> { typedef T4 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 5, GTEST_10_TUPLE_(T)> { typedef T5 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 6, GTEST_10_TUPLE_(T)> { typedef T6 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 7, GTEST_10_TUPLE_(T)> { typedef T7 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 8, GTEST_10_TUPLE_(T)> { typedef T8 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 9, GTEST_10_TUPLE_(T)> { typedef T9 type; };
+
+} // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+ tuple() {}
+ tuple(const tuple& /* t */) {}
+ tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+class GTEST_1_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
+
+ tuple(const tuple& t) : f0_(t.f0_) {}
+
+ template <GTEST_1_TYPENAMES_(U)>
+ tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_1_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_1_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ private:
+ template <GTEST_1_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ return *this;
+ }
+
+ T0 f0_;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+class GTEST_2_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
+ f1_(f1) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {}
+
+ template <GTEST_2_TYPENAMES_(U)>
+ tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {}
+ template <typename U0, typename U1>
+ tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_2_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_2_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+ template <typename U0, typename U1>
+ tuple& operator=(const ::std::pair<U0, U1>& p) {
+ f0_ = p.first;
+ f1_ = p.second;
+ return *this;
+ }
+
+ private:
+ template <GTEST_2_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+class GTEST_3_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+ template <GTEST_3_TYPENAMES_(U)>
+ tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_3_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_3_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ private:
+ template <GTEST_3_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+class GTEST_4_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
+ f3_(f3) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {}
+
+ template <GTEST_4_TYPENAMES_(U)>
+ tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_4_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_4_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ private:
+ template <GTEST_4_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+class GTEST_5_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
+ GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_) {}
+
+ template <GTEST_5_TYPENAMES_(U)>
+ tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_5_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_5_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ private:
+ template <GTEST_5_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+class GTEST_6_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+ f5_(f5) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_) {}
+
+ template <GTEST_6_TYPENAMES_(U)>
+ tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_6_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_6_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ private:
+ template <GTEST_6_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+class GTEST_7_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2),
+ f3_(f3), f4_(f4), f5_(f5), f6_(f6) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+ template <GTEST_7_TYPENAMES_(U)>
+ tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_7_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_7_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ private:
+ template <GTEST_7_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+class GTEST_8_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6,
+ GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+ f5_(f5), f6_(f6), f7_(f7) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+ template <GTEST_8_TYPENAMES_(U)>
+ tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_8_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_8_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ private:
+ template <GTEST_8_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ f7_ = t.f7_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+ T7 f7_;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+class GTEST_9_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+ GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+ f5_(f5), f6_(f6), f7_(f7), f8_(f8) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+ template <GTEST_9_TYPENAMES_(U)>
+ tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_9_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_9_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ private:
+ template <GTEST_9_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ f7_ = t.f7_;
+ f8_ = t.f8_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+ T7 f7_;
+ T8 f8_;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+class tuple {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+ GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2),
+ f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {}
+
+ template <GTEST_10_TYPENAMES_(U)>
+ tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_),
+ f9_(t.f9_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_10_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_10_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ private:
+ template <GTEST_10_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ f7_ = t.f7_;
+ f8_ = t.f8_;
+ f9_ = t.f9_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+ T7 f7_;
+ T8 f8_;
+ T9 f9_;
+};
+
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple(). And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+template <GTEST_1_TYPENAMES_(T)>
+inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) {
+ return GTEST_1_TUPLE_(T)(f0);
+}
+
+template <GTEST_2_TYPENAMES_(T)>
+inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) {
+ return GTEST_2_TUPLE_(T)(f0, f1);
+}
+
+template <GTEST_3_TYPENAMES_(T)>
+inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) {
+ return GTEST_3_TUPLE_(T)(f0, f1, f2);
+}
+
+template <GTEST_4_TYPENAMES_(T)>
+inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3) {
+ return GTEST_4_TUPLE_(T)(f0, f1, f2, f3);
+}
+
+template <GTEST_5_TYPENAMES_(T)>
+inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4) {
+ return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4);
+}
+
+template <GTEST_6_TYPENAMES_(T)>
+inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5) {
+ return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5);
+}
+
+template <GTEST_7_TYPENAMES_(T)>
+inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6) {
+ return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6);
+}
+
+template <GTEST_8_TYPENAMES_(T)>
+inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) {
+ return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7);
+}
+
+template <GTEST_9_TYPENAMES_(T)>
+inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+ const T8& f8) {
+ return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
+}
+
+template <GTEST_10_TYPENAMES_(T)>
+inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+ const T8& f8, const T9& f9) {
+ return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
+}
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+template <GTEST_0_TYPENAMES_(T)>
+struct tuple_size<GTEST_0_TUPLE_(T)> { static const int value = 0; };
+
+template <GTEST_1_TYPENAMES_(T)>
+struct tuple_size<GTEST_1_TUPLE_(T)> { static const int value = 1; };
+
+template <GTEST_2_TYPENAMES_(T)>
+struct tuple_size<GTEST_2_TUPLE_(T)> { static const int value = 2; };
+
+template <GTEST_3_TYPENAMES_(T)>
+struct tuple_size<GTEST_3_TUPLE_(T)> { static const int value = 3; };
+
+template <GTEST_4_TYPENAMES_(T)>
+struct tuple_size<GTEST_4_TUPLE_(T)> { static const int value = 4; };
+
+template <GTEST_5_TYPENAMES_(T)>
+struct tuple_size<GTEST_5_TUPLE_(T)> { static const int value = 5; };
+
+template <GTEST_6_TYPENAMES_(T)>
+struct tuple_size<GTEST_6_TUPLE_(T)> { static const int value = 6; };
+
+template <GTEST_7_TYPENAMES_(T)>
+struct tuple_size<GTEST_7_TUPLE_(T)> { static const int value = 7; };
+
+template <GTEST_8_TYPENAMES_(T)>
+struct tuple_size<GTEST_8_TUPLE_(T)> { static const int value = 8; };
+
+template <GTEST_9_TYPENAMES_(T)>
+struct tuple_size<GTEST_9_TUPLE_(T)> { static const int value = 9; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct tuple_size<GTEST_10_TUPLE_(T)> { static const int value = 10; };
+
+template <int k, class Tuple>
+struct tuple_element {
+ typedef typename gtest_internal::TupleElement<
+ k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+template <>
+class Get<0> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+ Field(Tuple& t) { return t.f0_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+ ConstField(const Tuple& t) { return t.f0_; }
+};
+
+template <>
+class Get<1> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+ Field(Tuple& t) { return t.f1_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+ ConstField(const Tuple& t) { return t.f1_; }
+};
+
+template <>
+class Get<2> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+ Field(Tuple& t) { return t.f2_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+ ConstField(const Tuple& t) { return t.f2_; }
+};
+
+template <>
+class Get<3> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+ Field(Tuple& t) { return t.f3_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+ ConstField(const Tuple& t) { return t.f3_; }
+};
+
+template <>
+class Get<4> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+ Field(Tuple& t) { return t.f4_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+ ConstField(const Tuple& t) { return t.f4_; }
+};
+
+template <>
+class Get<5> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+ Field(Tuple& t) { return t.f5_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+ ConstField(const Tuple& t) { return t.f5_; }
+};
+
+template <>
+class Get<6> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+ Field(Tuple& t) { return t.f6_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+ ConstField(const Tuple& t) { return t.f6_; }
+};
+
+template <>
+class Get<7> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+ Field(Tuple& t) { return t.f7_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+ ConstField(const Tuple& t) { return t.f7_; }
+};
+
+template <>
+class Get<8> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+ Field(Tuple& t) { return t.f8_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+ ConstField(const Tuple& t) { return t.f8_; }
+};
+
+template <>
+class Get<9> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+ Field(Tuple& t) { return t.f9_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+ ConstField(const Tuple& t) { return t.f9_; }
+};
+
+} // namespace gtest_internal
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(GTEST_10_TUPLE_(T)& t) {
+ return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(const GTEST_10_TUPLE_(T)& t) {
+ return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+ template <class Tuple1, class Tuple2>
+ static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+ return true;
+ }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+ template <class Tuple1, class Tuple2>
+ static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+ return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+ ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+ }
+};
+
+} // namespace gtest_internal
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator==(const GTEST_10_TUPLE_(T)& t,
+ const GTEST_10_TUPLE_(U)& u) {
+ return gtest_internal::SameSizeTuplePrefixComparator<
+ tuple_size<GTEST_10_TUPLE_(T)>::value,
+ tuple_size<GTEST_10_TUPLE_(U)>::value>::Eq(t, u);
+}
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
+ const GTEST_10_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+} // namespace tr1
+} // namespace std
+
+#undef GTEST_0_TUPLE_
+#undef GTEST_1_TUPLE_
+#undef GTEST_2_TUPLE_
+#undef GTEST_3_TUPLE_
+#undef GTEST_4_TUPLE_
+#undef GTEST_5_TUPLE_
+#undef GTEST_6_TUPLE_
+#undef GTEST_7_TUPLE_
+#undef GTEST_8_TUPLE_
+#undef GTEST_9_TUPLE_
+#undef GTEST_10_TUPLE_
+
+#undef GTEST_0_TYPENAMES_
+#undef GTEST_1_TYPENAMES_
+#undef GTEST_2_TYPENAMES_
+#undef GTEST_3_TYPENAMES_
+#undef GTEST_4_TYPENAMES_
+#undef GTEST_5_TYPENAMES_
+#undef GTEST_6_TYPENAMES_
+#undef GTEST_7_TYPENAMES_
+#undef GTEST_8_TYPENAMES_
+#undef GTEST_9_TYPENAMES_
+#undef GTEST_10_TYPENAMES_
+
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif // GTEST_INCLUDE_GTEST_INTERAL_GTEST_TUPLE_H_
diff --git a/include/gtest/internal/gtest-tuple.h.pump b/include/gtest/internal/gtest-tuple.h.pump
new file mode 100644
index 0000000..1ea7085
--- /dev/null
+++ b/include/gtest/internal/gtest-tuple.h.pump
@@ -0,0 +1,320 @@
+$$ -*- mode: c++; -*-
+$var n = 10 $$ Maximum number of tuple fields we want to support.
+$$ This meta comment fixes auto-indentation in Emacs. }}
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERAL_GTEST_TUPLE_H_
+
+#include <utility> // For ::std::pair.
+
+
+$range i 0..n-1
+$range j 0..n
+$range k 1..n
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+
+$for j [[
+$range m 0..j-1
+#define GTEST_$(j)_TUPLE_(T) tuple<$for m, [[T##$m]]>
+
+]]
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+
+$for j [[
+$range m 0..j-1
+#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
+
+
+]]
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior. We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <$for i, [[typename T$i = void]]>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; }; // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&. This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; }; // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>. kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+
+$for i [[
+template <GTEST_$(n)_TYPENAMES_(T)>
+struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T)> [[]]
+{ typedef T$i type; };
+
+
+]]
+} // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+ tuple() {}
+ tuple(const tuple& /* t */) {}
+ tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+
+$for k [[
+$range m 0..k-1
+template <GTEST_$(k)_TYPENAMES_(T)>
+class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
+ public:
+ template <int k> friend class gtest_internal::Get;
+ template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple;
+
+ tuple() {}
+
+ explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
+$for m, [[f$(m)_(f$m)]] {}
+
+ tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
+
+ template <GTEST_$(k)_TYPENAMES_(U)>
+ tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
+
+$if k == 2 [[
+ template <typename U0, typename U1>
+ tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+]]
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_$(k)_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+$if k == 2 [[
+ template <typename U0, typename U1>
+ tuple& operator=(const ::std::pair<U0, U1>& p) {
+ f0_ = p.first;
+ f1_ = p.second;
+ return *this;
+ }
+
+]]
+
+ private:
+ template <GTEST_$(k)_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
+
+$for m [[
+ f$(m)_ = t.f$(m)_;
+
+]]
+ return *this;
+ }
+
+
+$for m [[
+ T$m f$(m)_;
+
+]]
+};
+
+
+]]
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple(). And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+$for k [[
+$range m 0..k-1
+
+template <GTEST_$(k)_TYPENAMES_(T)>
+inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
+ return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
+}
+
+]]
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+
+$for j [[
+template <GTEST_$(j)_TYPENAMES_(T)>
+struct tuple_size<GTEST_$(j)_TUPLE_(T)> { static const int value = $j; };
+
+
+]]
+template <int k, class Tuple>
+struct tuple_element {
+ typedef typename gtest_internal::TupleElement<
+ k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+
+$for i [[
+template <>
+class Get<$i> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
+ Field(Tuple& t) { return t.f$(i)_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
+ ConstField(const Tuple& t) { return t.f$(i)_; }
+};
+
+
+]]
+} // namespace gtest_internal
+
+template <int k, GTEST_$(n)_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
+get(GTEST_$(n)_TUPLE_(T)& t) {
+ return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_$(n)_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
+get(const GTEST_$(n)_TUPLE_(T)& t) {
+ return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+ template <class Tuple1, class Tuple2>
+ static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+ return true;
+ }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+ template <class Tuple1, class Tuple2>
+ static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+ return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+ ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+ }
+};
+
+} // namespace gtest_internal
+
+template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
+inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
+ const GTEST_$(n)_TUPLE_(U)& u) {
+ return gtest_internal::SameSizeTuplePrefixComparator<
+ tuple_size<GTEST_$(n)_TUPLE_(T)>::value,
+ tuple_size<GTEST_$(n)_TUPLE_(U)>::value>::Eq(t, u);
+}
+
+template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
+ const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+} // namespace tr1
+} // namespace std
+
+
+$for j [[
+#undef GTEST_$(j)_TUPLE_
+
+]]
+
+
+$for j [[
+#undef GTEST_$(j)_TYPENAMES_
+
+]]
+
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif // GTEST_INCLUDE_GTEST_INTERAL_GTEST_TUPLE_H_
diff --git a/run_tests.py b/run_tests.py
index ed85f78..2aa3ddb 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -151,31 +151,30 @@ else:
GTEST_BUILD_DIR = 'GTEST_BUILD_DIR'
-def ScriptDir():
- """Returns the directory containing this script file."""
-
- my_path = sys.argv[0]
- my_dir = os.path.dirname(my_path)
- if not my_dir or __name__ != '__main__':
- my_dir = '.'
- return my_dir
-
-
-MY_DIR = ScriptDir()
-
-
-def GetBuildDirForConfig(config):
- """Returns the build directory for a given configuration."""
-
- return 'scons/build/%s/scons' % config
-
+# All paths in this script are either absolute or relative to the current
+# working directory, unless otherwise specified.
class TestRunner(object):
"""Provides facilities for running Python and binary tests for Google Test."""
- def __init__(self, injected_os=os, injected_subprocess=subprocess):
+ def __init__(self,
+ injected_os=os,
+ injected_subprocess=subprocess,
+ injected_script_dir=os.path.dirname(__file__)):
self.os = injected_os
self.subprocess = injected_subprocess
+ # If a program using this file is invoked via a relative path, the
+ # script directory will be relative to the path of the main program
+ # file. It may be '.' when this script is invoked directly or '..' when
+ # it is imported for testing. To simplify testing we inject the script
+ # directory into TestRunner.
+ self.script_dir = injected_script_dir
+
+ def GetBuildDirForConfig(self, config):
+ """Returns the build directory for a given configuration."""
+
+ return self.os.path.normpath(
+ self.os.path.join(self.script_dir, 'scons/build/%s/scons' % config))
def Run(self, args):
"""Runs the executable with given args (args[0] is the executable name).
@@ -194,23 +193,23 @@ class TestRunner(object):
return self.os.spawnv(self.os.P_WAIT, args[0], args)
def RunBinaryTest(self, test):
- """Runs the binary test script given its path relative to the gtest root.
+ """Runs the binary test given its path.
Args:
- test: Path to the test binary relative to the location of this script.
+ test: Path to the test binary.
Returns:
Process's exit code if it exits normally, or -signal if the process is
killed by a signal.
"""
- return self.Run([self.os.path.abspath(self.os.path.join(MY_DIR, test))])
+ return self.Run([test])
def RunPythonTest(self, test, build_dir):
"""Runs the Python test script with the specified build directory.
Args:
- test: Name of the test's Python script.
+ test: Path to the test's Python script.
build_dir: Path to the directory where the test binary is to be found.
Returns:
@@ -226,9 +225,8 @@ class TestRunner(object):
# If this script is run on a Windows machine that has no association
# between the .py extension and a python interpreter, simply passing
# the script name into subprocess.Popen/os.spawn will not work.
- script = self.os.path.join(MY_DIR, test)
- print 'Running %s . . .' % (script,)
- return self.Run([sys.executable, script])
+ print 'Running %s . . .' % (test,)
+ return self.Run([sys.executable, test])
finally:
if old_build_dir is None:
@@ -277,28 +275,29 @@ class TestRunner(object):
if named_configurations == 'all':
named_configurations = ','.join(available_configurations)
+ normalized_args = [self.os.path.normpath(arg) for arg in args]
+
# A final list of build directories which will be searched for the test
# binaries. First, add directories specified directly on the command
# line.
- build_dirs = [arg for arg in args if self.os.path.isdir(arg)]
+ build_dirs = filter(self.os.path.isdir, normalized_args)
# Adds build directories specified via their build configurations using
# the -c or -a options.
if named_configurations:
- build_dirs += [GetBuildDirForConfig(config)
+ build_dirs += [self.GetBuildDirForConfig(config)
for config in named_configurations.split(',')]
# Adds KNOWN BUILD DIRECTORIES if -b is specified.
if built_configurations:
- build_dirs += [GetBuildDirForConfig(config)
+ build_dirs += [self.GetBuildDirForConfig(config)
for config in available_configurations
- if self.os.path.isdir(GetBuildDirForConfig(config))]
+ if self.os.path.isdir(self.GetBuildDirForConfig(config))]
# If no directories were specified either via -a, -b, -c, or directly, use
# the default configuration.
elif not build_dirs:
- build_dirs = [GetBuildDirForConfig(config)
- for config in available_configurations[0:1]]
+ build_dirs = [self.GetBuildDirForConfig(available_configurations[0])]
# Makes sure there are no duplications.
build_dirs = sets.Set(build_dirs)
@@ -309,10 +308,12 @@ class TestRunner(object):
# Sifts through non-directory arguments fishing for any Python or binary
# tests and detecting errors.
- for argument in sets.Set(args) - build_dirs:
+ for argument in sets.Set(normalized_args) - build_dirs:
if re.search(PYTHON_TEST_REGEX, argument):
- python_path = self.os.path.join('test', self.os.path.basename(argument))
- if self.os.path.isfile(self.os.path.join(MY_DIR, python_path)):
+ python_path = self.os.path.join(self.script_dir,
+ 'test',
+ self.os.path.basename(argument))
+ if self.os.path.isfile(python_path):
listed_python_tests.append(python_path)
else:
sys.stderr.write('Unable to find Python test %s' % argument)
@@ -334,7 +335,9 @@ class TestRunner(object):
if user_has_listed_tests:
selected_python_tests = listed_python_tests
else:
- selected_python_tests = self.FindFilesByRegex('test', PYTHON_TEST_REGEX)
+ selected_python_tests = self.FindFilesByRegex(
+ self.os.path.join(self.script_dir, 'test'),
+ PYTHON_TEST_REGEX)
# TODO(vladl@google.com): skip unbuilt Python tests when -b is specified.
python_test_pairs = []
@@ -355,7 +358,7 @@ class TestRunner(object):
return (python_test_pairs, binary_test_pairs)
def RunTests(self, python_tests, binary_tests):
- """Runs Python and binary tests represented as pairs (work_dir, binary).
+ """Runs Python and binary tests and reports results to the standard output.
Args:
python_tests: List of Python tests to run in the form of tuples
diff --git a/scons/SConscript b/scons/SConscript
index c409dcb..0d38499 100644
--- a/scons/SConscript
+++ b/scons/SConscript
@@ -125,6 +125,11 @@ if env_with_exceptions['PLATFORM'] == 'win32':
cppdefines = env_with_exceptions['CPPDEFINES']
if '_TYPEINFO_' in cppdefines:
cppdefines.remove('_TYPEINFO_')
+else:
+ env_with_exceptions.Append(CCFLAGS='-fexceptions')
+ ccflags = env_with_exceptions['CCFLAGS']
+ if '-fno-exceptions' in ccflags:
+ ccflags.remove('-fno-exceptions')
env_without_rtti = env.Clone()
if env_without_rtti['PLATFORM'] == 'win32':
@@ -133,6 +138,9 @@ else:
env_without_rtti.Append(CCFLAGS = ['-fno-rtti'])
env_without_rtti.Append(CPPDEFINES = 'GTEST_HAS_RTTI=0')
+env_use_own_tuple = env.Clone()
+env_use_own_tuple.Append(CPPDEFINES = 'GTEST_USE_OWN_TR1_TUPLE=1')
+
gtest_ex_obj = env_with_exceptions.Object(target='gtest_ex',
source=gtest_source)
gtest_main_ex_obj = env_with_exceptions.Object(target='gtest_main_ex',
@@ -258,6 +266,37 @@ GtestBinary(env_without_rtti,
gtest_all_no_rtti_obj +
gtest_main_no_rtti_obj)
+# Builds a test for gtest's own TR1 tuple implementation.
+gtest_all_use_own_tuple_obj = env_use_own_tuple.Object(
+ target='gtest_all_use_own_tuple',
+ source='../src/gtest-all.cc')
+gtest_main_use_own_tuple_obj = env_use_own_tuple.Object(
+ target='gtest_main_use_own_tuple',
+ source='../src/gtest_main.cc')
+GtestBinary(env_use_own_tuple,
+ 'gtest-tuple_test',
+ [],
+ ['../test/gtest-tuple_test.cc',
+ gtest_all_use_own_tuple_obj,
+ gtest_main_use_own_tuple_obj])
+
+# Builds a test for gtest features that use tuple.
+gtest_param_test_test_use_own_tuple_obj = env_use_own_tuple.Object(
+ target='gtest_param_test_test_use_own_tuple',
+ source='../test/gtest-param-test_test.cc')
+gtest_param_test2_test_use_own_tuple_obj = env_use_own_tuple.Object(
+ target='gtest_param_test2_test_use_own_tuple',
+ source='../test/gtest-param-test2_test.cc')
+GtestBinary(env_use_own_tuple,
+ 'gtest_use_own_tuple_test',
+ [],
+ gtest_param_test_test_use_own_tuple_obj +
+ gtest_param_test2_test_use_own_tuple_obj +
+ gtest_all_use_own_tuple_obj)
+
+# TODO(wan@google.com): simplify the definition of build targets that
+# use alternative environments.
+
# We need to disable some optimization flags for some tests on
# Windows; otherwise the redirection of stdout does not work
# (apparently because of a compiler bug).
diff --git a/test/gtest-tuple_test.cc b/test/gtest-tuple_test.cc
new file mode 100644
index 0000000..3829118
--- /dev/null
+++ b/test/gtest-tuple_test.cc
@@ -0,0 +1,288 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include <gtest/internal/gtest-tuple.h>
+#include <utility>
+#include <gtest/gtest.h>
+
+namespace {
+
+using ::std::tr1::get;
+using ::std::tr1::make_tuple;
+using ::std::tr1::tuple;
+using ::std::tr1::tuple_element;
+using ::std::tr1::tuple_size;
+using ::testing::StaticAssertTypeEq;
+
+// Tests that tuple_element<K, tuple<T0, T1, ..., TN> >::type returns TK.
+TEST(tuple_element_Test, ReturnsElementType) {
+ StaticAssertTypeEq<int, tuple_element<0, tuple<int, char> >::type>();
+ StaticAssertTypeEq<int&, tuple_element<1, tuple<double, int&> >::type>();
+ StaticAssertTypeEq<bool, tuple_element<2, tuple<double, int, bool> >::type>();
+}
+
+// Tests that tuple_size<T>::value gives the number of fields in tuple
+// type T.
+TEST(tuple_size_Test, ReturnsNumberOfFields) {
+ EXPECT_EQ(0, +tuple_size<tuple<> >::value);
+ EXPECT_EQ(1, +tuple_size<tuple<void*> >::value);
+ EXPECT_EQ(1, +tuple_size<tuple<char> >::value);
+ EXPECT_EQ(1, +(tuple_size<tuple<tuple<int, double> > >::value));
+ EXPECT_EQ(2, +(tuple_size<tuple<int&, const char> >::value));
+ EXPECT_EQ(3, +(tuple_size<tuple<char*, void, const bool&> >::value));
+}
+
+// Tests comparing a tuple with itself.
+TEST(ComparisonTest, ComparesWithSelf) {
+ const tuple<int, char, bool> a(5, 'a', false);
+
+ EXPECT_TRUE(a == a);
+ EXPECT_FALSE(a != a);
+}
+
+// Tests comparing two tuples with the same value.
+TEST(ComparisonTest, ComparesEqualTuples) {
+ const tuple<int, bool> a(5, true), b(5, true);
+
+ EXPECT_TRUE(a == b);
+ EXPECT_FALSE(a != b);
+}
+
+// Tests comparing two different tuples that have no reference fields.
+TEST(ComparisonTest, ComparesUnequalTuplesWithoutReferenceFields) {
+ typedef tuple<const int, char> FooTuple;
+
+ const FooTuple a(0, 'x');
+ const FooTuple b(1, 'a');
+
+ EXPECT_TRUE(a != b);
+ EXPECT_FALSE(a == b);
+
+ const FooTuple c(1, 'b');
+
+ EXPECT_TRUE(b != c);
+ EXPECT_FALSE(b == c);
+}
+
+// Tests comparing two different tuples that have reference fields.
+TEST(ComparisonTest, ComparesUnequalTuplesWithReferenceFields) {
+ typedef tuple<int&, const char&> FooTuple;
+
+ int i = 5;
+ const char ch = 'a';
+ const FooTuple a(i, ch);
+
+ int j = 6;
+ const FooTuple b(j, ch);
+
+ EXPECT_TRUE(a != b);
+ EXPECT_FALSE(a == b);
+
+ j = 5;
+ const char ch2 = 'b';
+ const FooTuple c(j, ch2);
+
+ EXPECT_TRUE(b != c);
+ EXPECT_FALSE(b == c);
+}
+
+// Tests that a tuple field with a reference type is an alias of the
+// variable it's supposed to reference.
+TEST(ReferenceFieldTest, IsAliasOfReferencedVariable) {
+ int n = 0;
+ tuple<bool, int&> t(true, n);
+
+ n = 1;
+ EXPECT_EQ(n, get<1>(t))
+ << "Changing a underlying variable should update the reference field.";
+
+ // Makes sure that the implementation doesn't do anything funny with
+ // the & operator for the return type of get<>().
+ EXPECT_EQ(&n, &(get<1>(t)))
+ << "The address of a reference field should equal the address of "
+ << "the underlying variable.";
+
+ get<1>(t) = 2;
+ EXPECT_EQ(2, n)
+ << "Changing a reference field should update the underlying variable.";
+}
+
+// Tests tuple's default constructor.
+TEST(TupleConstructorTest, DefaultConstructor) {
+ // We are just testing that the following compiles.
+ tuple<> empty;
+ tuple<int> one_field;
+ tuple<double, char, bool*> three_fields;
+}
+
+// Tests constructing a tuple from its fields.
+TEST(TupleConstructorTest, ConstructsFromFields) {
+ int n = 1;
+ // Reference field.
+ tuple<int&> a(n);
+ EXPECT_EQ(&n, &(get<0>(a)));
+
+ // Non-reference fields.
+ tuple<int, char> b(5, 'a');
+ EXPECT_EQ(5, get<0>(b));
+ EXPECT_EQ('a', get<1>(b));
+
+ // Const reference field.
+ const int m = 2;
+ tuple<bool, const int&> c(true, m);
+ EXPECT_TRUE(get<0>(c));
+ EXPECT_EQ(&m, &(get<1>(c)));
+}
+
+// Tests tuple's copy constructor.
+TEST(TupleConstructorTest, CopyConstructor) {
+ tuple<double, bool> a(0.0, true);
+ tuple<double, bool> b(a);
+
+ EXPECT_DOUBLE_EQ(0.0, get<0>(b));
+ EXPECT_TRUE(get<1>(b));
+}
+
+// Tests constructing a tuple from another tuple that has a compatible
+// but different type.
+TEST(TupleConstructorTest, ConstructsFromDifferentTupleType) {
+ tuple<int, int, char> a(0, 1, 'a');
+ tuple<double, long, int> b(a);
+
+ EXPECT_DOUBLE_EQ(0.0, get<0>(b));
+ EXPECT_EQ(1, get<1>(b));
+ EXPECT_EQ('a', get<2>(b));
+}
+
+// Tests constructing a 2-tuple from an std::pair.
+TEST(TupleConstructorTest, ConstructsFromPair) {
+ ::std::pair<int, char> a(1, 'a');
+ tuple<int, char> b(a);
+ tuple<int, const char&> c(a);
+}
+
+// Tests assigning a tuple to another tuple with the same type.
+TEST(TupleAssignmentTest, AssignsToSameTupleType) {
+ const tuple<int, long> a(5, 7L);
+ tuple<int, long> b;
+ b = a;
+ EXPECT_EQ(5, get<0>(b));
+ EXPECT_EQ(7L, get<1>(b));
+}
+
+// Tests assigning a tuple to another tuple with a different but
+// compatible type.
+TEST(TupleAssignmentTest, AssignsToDifferentTupleType) {
+ const tuple<int, long, bool> a(1, 7L, true);
+ tuple<long, int, bool> b;
+ b = a;
+ EXPECT_EQ(1L, get<0>(b));
+ EXPECT_EQ(7, get<1>(b));
+ EXPECT_TRUE(get<2>(b));
+}
+
+// Tests assigning an std::pair to a 2-tuple.
+TEST(TupleAssignmentTest, AssignsFromPair) {
+ const ::std::pair<int, bool> a(5, true);
+ tuple<int, bool> b;
+ b = a;
+ EXPECT_EQ(5, get<0>(b));
+ EXPECT_TRUE(get<1>(b));
+
+ tuple<long, bool> c;
+ c = a;
+ EXPECT_EQ(5L, get<0>(c));
+ EXPECT_TRUE(get<1>(c));
+}
+
+// A fixture for testing big tuples.
+class BigTupleTest : public testing::Test {
+ protected:
+ typedef tuple<int, int, int, int, int, int, int, int, int, int> BigTuple;
+
+ BigTupleTest() :
+ a_(1, 0, 0, 0, 0, 0, 0, 0, 0, 2),
+ b_(1, 0, 0, 0, 0, 0, 0, 0, 0, 3) {}
+
+ BigTuple a_, b_;
+};
+
+// Tests constructing big tuples.
+TEST_F(BigTupleTest, Construction) {
+ BigTuple a;
+ BigTuple b(b_);
+}
+
+// Tests that get<N>(t) returns the N-th (0-based) field of tuple t.
+TEST_F(BigTupleTest, get) {
+ EXPECT_EQ(1, get<0>(a_));
+ EXPECT_EQ(2, get<9>(a_));
+
+ // Tests that get() works on a const tuple too.
+ const BigTuple a(a_);
+ EXPECT_EQ(1, get<0>(a));
+ EXPECT_EQ(2, get<9>(a));
+}
+
+// Tests comparing big tuples.
+TEST_F(BigTupleTest, Comparisons) {
+ EXPECT_TRUE(a_ == a_);
+ EXPECT_FALSE(a_ != a_);
+
+ EXPECT_TRUE(a_ != b_);
+ EXPECT_FALSE(a_ == b_);
+}
+
+TEST(MakeTupleTest, WorksForScalarTypes) {
+ tuple<bool, int> a;
+ a = make_tuple(true, 5);
+ EXPECT_TRUE(get<0>(a));
+ EXPECT_EQ(5, get<1>(a));
+
+ tuple<char, int, long> b;
+ b = make_tuple('a', 'b', 5);
+ EXPECT_EQ('a', get<0>(b));
+ EXPECT_EQ('b', get<1>(b));
+ EXPECT_EQ(5, get<2>(b));
+}
+
+TEST(MakeTupleTest, WorksForPointers) {
+ int a[] = { 1, 2, 3, 4 };
+ const char* const str = "hi";
+ int* const p = a;
+
+ tuple<const char*, int*> t;
+ t = make_tuple(str, p);
+ EXPECT_EQ(str, get<0>(t));
+ EXPECT_EQ(p, get<1>(t));
+}
+
+} // namespace
diff --git a/test/gtest_break_on_failure_unittest.py b/test/gtest_break_on_failure_unittest.py
index cae288a..218d371 100755
--- a/test/gtest_break_on_failure_unittest.py
+++ b/test/gtest_break_on_failure_unittest.py
@@ -43,7 +43,6 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
import gtest_test_utils
import os
import sys
-import unittest
# Constants.
@@ -94,7 +93,7 @@ def Run(command):
# The tests.
-class GTestBreakOnFailureUnitTest(unittest.TestCase):
+class GTestBreakOnFailureUnitTest(gtest_test_utils.TestCase):
"""Tests using the GTEST_BREAK_ON_FAILURE environment variable or
the --gtest_break_on_failure flag to turn assertion failures into
segmentation faults.
diff --git a/test/gtest_color_test.py b/test/gtest_color_test.py
index 1b68630..f617dc5 100755
--- a/test/gtest_color_test.py
+++ b/test/gtest_color_test.py
@@ -33,10 +33,9 @@
__author__ = 'wan@google.com (Zhanyong Wan)'
-import gtest_test_utils
import os
-import sys
-import unittest
+import gtest_test_utils
+
IS_WINDOWS = os.name = 'nt'
@@ -65,7 +64,7 @@ def UsesColor(term, color_env_var, color_flag):
return gtest_test_utils.GetExitStatus(os.system(cmd))
-class GTestColorTest(unittest.TestCase):
+class GTestColorTest(gtest_test_utils.TestCase):
def testNoEnvVarNoFlag(self):
"""Tests the case when there's neither GTEST_COLOR nor --gtest_color."""
diff --git a/test/gtest_env_var_test.py b/test/gtest_env_var_test.py
index 35e8041..54719fa 100755
--- a/test/gtest_env_var_test.py
+++ b/test/gtest_env_var_test.py
@@ -33,13 +33,12 @@
__author__ = 'wan@google.com (Zhanyong Wan)'
-import gtest_test_utils
import os
-import sys
-import unittest
+import gtest_test_utils
+
IS_WINDOWS = os.name == 'nt'
-IS_LINUX = os.name == 'posix'
+IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_env_var_test_')
@@ -97,12 +96,13 @@ def TestEnvVarAffectsFlag(command):
if IS_WINDOWS:
TestFlag(command, 'catch_exceptions', '1', '0')
+
if IS_LINUX:
- TestFlag(command, 'stack_trace_depth', '0', '100')
TestFlag(command, 'death_test_use_fork', '1', '0')
+ TestFlag(command, 'stack_trace_depth', '0', '100')
-class GTestEnvVarTest(unittest.TestCase):
+class GTestEnvVarTest(gtest_test_utils.TestCase):
def testEnvVarAffectsFlag(self):
TestEnvVarAffectsFlag(COMMAND)
diff --git a/test/gtest_filter_unittest.py b/test/gtest_filter_unittest.py
index 6002fac..4e9556b 100755
--- a/test/gtest_filter_unittest.py
+++ b/test/gtest_filter_unittest.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2005, Google Inc.
-# All rights reserved.
+# Copyright 2005 Google Inc. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -46,8 +45,6 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
import os
import re
import sets
-import tempfile
-import unittest
import gtest_test_utils
# Constants.
@@ -133,9 +130,7 @@ def SetEnvVar(env_var, value):
def Run(command):
- """Runs a Google Test program and returns a list of full names of the
- tests that were run along with the test exit code.
- """
+ """Runs a test program and returns its exit code and a list of tests run."""
stdout_file = os.popen(command, 'r')
tests_run = []
@@ -169,9 +164,7 @@ def InvokeWithModifiedEnv(extra_env, function, *args, **kwargs):
def RunWithSharding(total_shards, shard_index, command):
- """Runs the Google Test program shard and returns a list of full names of the
- tests that were run along with the exit code.
- """
+ """Runs a test program shard and returns exit code and a list of tests run."""
extra_env = {SHARD_INDEX_ENV_VAR: str(shard_index),
TOTAL_SHARDS_ENV_VAR: str(total_shards)}
@@ -180,10 +173,8 @@ def RunWithSharding(total_shards, shard_index, command):
# The unit test.
-class GTestFilterUnitTest(unittest.TestCase):
- """Tests using the GTEST_FILTER environment variable or the
- --gtest_filter flag to filter tests.
- """
+class GTestFilterUnitTest(gtest_test_utils.TestCase):
+ """Tests GTEST_FILTER env variable or --gtest_filter flag to filter tests."""
# Utilities.
@@ -206,9 +197,8 @@ class GTestFilterUnitTest(unittest.TestCase):
self.assertEqual(sets.Set(set_var), sets.Set(full_partition))
def AdjustForParameterizedTests(self, tests_to_run):
- """Adjust tests_to_run in case value parameterized tests are disabled
- in the binary.
- """
+ """Adjust tests_to_run in case value parameterized tests are disabled."""
+
global param_tests_present
if not param_tests_present:
return list(sets.Set(tests_to_run) - sets.Set(PARAM_TESTS))
@@ -216,9 +206,8 @@ class GTestFilterUnitTest(unittest.TestCase):
return tests_to_run
def RunAndVerify(self, gtest_filter, tests_to_run):
- """Runs gtest_flag_unittest_ with the given filter, and verifies
- that the right set of tests were run.
- """
+ """Checks that the binary runs correct set of tests for the given filter."""
+
tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
# First, tests using GTEST_FILTER.
@@ -248,11 +237,21 @@ class GTestFilterUnitTest(unittest.TestCase):
def RunAndVerifyWithSharding(self, gtest_filter, total_shards, tests_to_run,
command=COMMAND, check_exit_0=False):
- """Runs all shards of gtest_flag_unittest_ with the given filter, and
+ """Checks that binary runs correct tests for the given filter and shard.
+
+ Runs all shards of gtest_filter_unittest_ with the given filter, and
verifies that the right set of tests were run. The union of tests run
on each shard should be identical to tests_to_run, without duplicates.
- If check_exit_0, make sure that all shards returned 0.
+
+ Args:
+ gtest_filter: A filter to apply to the tests.
+ total_shards: A total number of shards to split test run into.
+ tests_to_run: A set of tests expected to run.
+ command: A command to invoke the test binary.
+ check_exit_0: When set to a true value, make sure that all shards
+ return 0.
"""
+
tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
# Windows removes empty variables from the environment when passing it
@@ -275,9 +274,16 @@ class GTestFilterUnitTest(unittest.TestCase):
# pylint: enable-msg=C6403
def RunAndVerifyAllowingDisabled(self, gtest_filter, tests_to_run):
- """Runs gtest_flag_unittest_ with the given filter, and enables
+ """Checks that the binary runs correct set of tests for the given filter.
+
+ Runs gtest_filter_unittest_ with the given filter, and enables
disabled tests. Verifies that the right set of tests were run.
+
+ Args:
+ gtest_filter: A filter to apply to the tests.
+ tests_to_run: A set of tests expected to run.
"""
+
tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
# Construct the command line.
@@ -294,6 +300,7 @@ class GTestFilterUnitTest(unittest.TestCase):
Determines whether value-parameterized tests are enabled in the binary and
sets the flags accordingly.
"""
+
global param_tests_present
if param_tests_present is None:
param_tests_present = PARAM_TEST_REGEX.search(
@@ -305,9 +312,8 @@ class GTestFilterUnitTest(unittest.TestCase):
self.RunAndVerify(None, ACTIVE_TESTS)
def testDefaultBehaviorWithShards(self):
- """Tests the behavior of not specifying the filter, with sharding
- enabled.
- """
+ """Tests the behavior without the filter, with sharding enabled."""
+
self.RunAndVerifyWithSharding(None, 1, ACTIVE_TESTS)
self.RunAndVerifyWithSharding(None, 2, ACTIVE_TESTS)
self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) - 1, ACTIVE_TESTS)
@@ -520,9 +526,7 @@ class GTestFilterUnitTest(unittest.TestCase):
])
def testFlagOverridesEnvVar(self):
- """Tests that the --gtest_filter flag overrides the GTEST_FILTER
- environment variable.
- """
+ """Tests that the filter flag overrides the filtering env. variable."""
SetEnvVar(FILTER_ENV_VAR, 'Foo*')
command = '%s --%s=%s' % (COMMAND, FILTER_FLAG, '*One')
@@ -534,8 +538,8 @@ class GTestFilterUnitTest(unittest.TestCase):
def testShardStatusFileIsCreated(self):
"""Tests that the shard file is created if specified in the environment."""
- test_tmpdir = tempfile.mkdtemp()
- shard_status_file = os.path.join(test_tmpdir, 'shard_status_file')
+ shard_status_file = os.path.join(gtest_test_utils.GetTempDir(),
+ 'shard_status_file')
self.assert_(not os.path.exists(shard_status_file))
extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
@@ -546,13 +550,12 @@ class GTestFilterUnitTest(unittest.TestCase):
stdout_file.close()
self.assert_(os.path.exists(shard_status_file))
os.remove(shard_status_file)
- os.removedirs(test_tmpdir)
def testShardStatusFileIsCreatedWithListTests(self):
"""Tests that the shard file is created with --gtest_list_tests."""
- test_tmpdir = tempfile.mkdtemp()
- shard_status_file = os.path.join(test_tmpdir, 'shard_status_file2')
+ shard_status_file = os.path.join(gtest_test_utils.GetTempDir(),
+ 'shard_status_file2')
self.assert_(not os.path.exists(shard_status_file))
extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
@@ -564,7 +567,6 @@ class GTestFilterUnitTest(unittest.TestCase):
stdout_file.close()
self.assert_(os.path.exists(shard_status_file))
os.remove(shard_status_file)
- os.removedirs(test_tmpdir)
def testShardingWorksWithDeathTests(self):
"""Tests integration with death tests and sharding."""
diff --git a/test/gtest_help_test.py b/test/gtest_help_test.py
index d81f149..0a2a07b 100755
--- a/test/gtest_help_test.py
+++ b/test/gtest_help_test.py
@@ -39,10 +39,9 @@ SYNOPSIS
__author__ = 'wan@google.com (Zhanyong Wan)'
-import gtest_test_utils
import os
import re
-import unittest
+import gtest_test_utils
IS_WINDOWS = os.name == 'nt'
@@ -83,7 +82,7 @@ def RunWithFlag(flag):
return child.exit_code, child.output
-class GTestHelpTest(unittest.TestCase):
+class GTestHelpTest(gtest_test_utils.TestCase):
"""Tests the --help flag and its equivalent forms."""
def TestHelpFlag(self, flag):
diff --git a/test/gtest_list_tests_unittest.py b/test/gtest_list_tests_unittest.py
index 3d006df..7dca0b8 100755
--- a/test/gtest_list_tests_unittest.py
+++ b/test/gtest_list_tests_unittest.py
@@ -39,11 +39,8 @@ Google Test) the command line flags.
__author__ = 'phanna@google.com (Patrick Hanna)'
-import gtest_test_utils
import os
-import re
-import sys
-import unittest
+import gtest_test_utils
# Constants.
@@ -105,7 +102,7 @@ def Run(command):
# The unit test.
-class GTestListTestsUnitTest(unittest.TestCase):
+class GTestListTestsUnitTest(gtest_test_utils.TestCase):
"""Tests using the --gtest_list_tests flag to list all tests."""
def RunAndVerify(self, flag_value, expected_output, other_flag):
diff --git a/test/gtest_nc_test.py b/test/gtest_nc_test.py
index 6e77d70..06ffb3f 100755
--- a/test/gtest_nc_test.py
+++ b/test/gtest_nc_test.py
@@ -38,6 +38,11 @@ import sys
import unittest
+IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
+if not IS_LINUX:
+ sys.exit(0) # Negative compilation tests are not supported on Windows & Mac.
+
+
class GTestNCTest(unittest.TestCase):
"""Negative compilation test for Google Test."""
diff --git a/test/gtest_output_test.py b/test/gtest_output_test.py
index 2751fa6..91cf915 100755
--- a/test/gtest_output_test.py
+++ b/test/gtest_output_test.py
@@ -44,7 +44,6 @@ import os
import re
import string
import sys
-import unittest
import gtest_test_utils
@@ -84,11 +83,11 @@ def ToUnixLineEnding(s):
return s.replace('\r\n', '\n').replace('\r', '\n')
-def RemoveLocations(output):
+def RemoveLocations(test_output):
"""Removes all file location info from a Google Test program's output.
Args:
- output: the output of a Google Test program.
+ test_output: the output of a Google Test program.
Returns:
output with all file location info (in the form of
@@ -97,10 +96,10 @@ def RemoveLocations(output):
'FILE_NAME:#: '.
"""
- return re.sub(r'.*[/\\](.+)(\:\d+|\(\d+\))\: ', r'\1:#: ', output)
+ return re.sub(r'.*[/\\](.+)(\:\d+|\(\d+\))\: ', r'\1:#: ', test_output)
-def RemoveStackTraces(output):
+def RemoveStackTraceDetails(output):
"""Removes all stack traces from a Google Test program's output."""
# *? means "find the shortest string that matches".
@@ -108,6 +107,13 @@ def RemoveStackTraces(output):
'Stack trace: (omitted)\n\n', output)
+def RemoveStackTraces(output):
+ """Removes all traces of stack traces from a Google Test program's output."""
+
+ # *? means "find the shortest string that matches".
+ return re.sub(r'Stack trace:(.|\n)*?\n\n', '', output)
+
+
def RemoveTime(output):
"""Removes all time information from a Google Test program's output."""
@@ -123,25 +129,28 @@ def RemoveTestCounts(output):
'? FAILED TESTS', output)
output = re.sub(r'\d+ tests from \d+ test cases',
'? tests from ? test cases', output)
+ output = re.sub(r'\d+ tests from ([a-zA-Z_])',
+ r'? tests from \1', output)
return re.sub(r'\d+ tests\.', '? tests.', output)
def RemoveMatchingTests(test_output, pattern):
- """Removes typed test information from a Google Test program's output.
+ """Removes output of specified tests from a Google Test program's output.
- This function strips not only the beginning and the end of a test but also all
- output in between.
+ This function strips not only the beginning and the end of a test but also
+ all output in between.
Args:
test_output: A string containing the test output.
- pattern: A string that matches names of test cases to remove.
+ pattern: A regex string that matches names of test cases or
+ tests to remove.
Returns:
- Contents of test_output with removed test case whose names match pattern.
+ Contents of test_output with tests whose names match pattern removed.
"""
test_output = re.sub(
- r'\[ RUN \] .*%s(.|\n)*?\[( FAILED | OK )\] .*%s.*\n' % (
+ r'.*\[ RUN \] .*%s(.|\n)*?\[( FAILED | OK )\] .*%s.*\n' % (
pattern, pattern),
'',
test_output)
@@ -153,7 +162,7 @@ def NormalizeOutput(output):
output = ToUnixLineEnding(output)
output = RemoveLocations(output)
- output = RemoveStackTraces(output)
+ output = RemoveStackTraceDetails(output)
output = RemoveTime(output)
return output
@@ -241,14 +250,28 @@ def GetOutputOfAllCommands():
test_list = GetShellCommandOutput(COMMAND_LIST_TESTS, '')
SUPPORTS_DEATH_TESTS = 'DeathTest' in test_list
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
-class GTestOutputTest(unittest.TestCase):
+class GTestOutputTest(gtest_test_utils.TestCase):
def RemoveUnsupportedTests(self, test_output):
if not SUPPORTS_DEATH_TESTS:
test_output = RemoveMatchingTests(test_output, 'DeathTest')
if not SUPPORTS_TYPED_TESTS:
test_output = RemoveMatchingTests(test_output, 'TypedTest')
+ if not SUPPORTS_THREADS:
+ test_output = RemoveMatchingTests(test_output,
+ 'ExpectFailureWithThreadsTest')
+ test_output = RemoveMatchingTests(test_output,
+ 'ScopedFakeTestPartResultReporterTest')
+ test_output = RemoveMatchingTests(test_output,
+ 'WorksConcurrently')
+ if not SUPPORTS_STACK_TRACES:
+ test_output = RemoveStackTraces(test_output)
+
return test_output
def testOutput(self):
@@ -262,26 +285,48 @@ class GTestOutputTest(unittest.TestCase):
golden = ToUnixLineEnding(golden_file.read())
golden_file.close()
- # We want the test to pass regardless of death tests being
+ # We want the test to pass regardless of certain features being
# supported or not.
- if SUPPORTS_DEATH_TESTS and SUPPORTS_TYPED_TESTS:
+ if CAN_GENERATE_GOLDEN_FILE:
self.assert_(golden == output)
else:
- self.assert_(RemoveTestCounts(self.RemoveUnsupportedTests(golden)) ==
- RemoveTestCounts(output))
+ normalized_actual = RemoveTestCounts(output)
+ normalized_golden = RemoveTestCounts(self.RemoveUnsupportedTests(golden))
+
+ # This code is very handy when debugging test differences so I left it
+ # here, commented.
+ # open(os.path.join(
+ # gtest_test_utils.GetSourceDir(),
+ # '_gtest_output_test_normalized_actual.txt'), 'wb').write(
+ # normalized_actual)
+ # open(os.path.join(
+ # gtest_test_utils.GetSourceDir(),
+ # '_gtest_output_test_normalized_golden.txt'), 'wb').write(
+ # normalized_golden)
+
+ self.assert_(normalized_golden == normalized_actual)
if __name__ == '__main__':
if sys.argv[1:] == [GENGOLDEN_FLAG]:
- if SUPPORTS_DEATH_TESTS and SUPPORTS_TYPED_TESTS:
+ if CAN_GENERATE_GOLDEN_FILE:
output = GetOutputOfAllCommands()
golden_file = open(GOLDEN_PATH, 'wb')
golden_file.write(output)
golden_file.close()
else:
- print >> sys.stderr, ('Unable to write a golden file when compiled in an '
- 'environment that does not support death tests and '
- 'typed tests. Are you using VC 7.1?')
+ message = (
+ """Unable to write a golden file when compiled in an environment
+that does not support all the required features (death tests""")
+ if IS_WINDOWS:
+ message += (
+ """\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."""
+
+ sys.stderr.write(message)
sys.exit(1)
else:
gtest_test_utils.Main()
diff --git a/test/gtest_test_utils.py b/test/gtest_test_utils.py
index 7dc8c42..45b25cd 100755
--- a/test/gtest_test_utils.py
+++ b/test/gtest_test_utils.py
@@ -33,19 +33,32 @@
__author__ = 'wan@google.com (Zhanyong Wan)'
+import atexit
import os
+import shutil
import sys
+import tempfile
import unittest
+_test_module = unittest
+# Suppresses the 'Import not at the top of the file' lint complaint.
+# pylint: disable-msg=C6204
try:
import subprocess
_SUBPROCESS_MODULE_AVAILABLE = True
except:
import popen2
_SUBPROCESS_MODULE_AVAILABLE = False
+# pylint: enable-msg=C6204
+
IS_WINDOWS = os.name == 'nt'
+# Here we expose a class from a particular module, depending on the
+# environment. The comment suppresses the 'Invalid variable name' lint
+# complaint.
+TestCase = _test_module.TestCase # pylint: disable-msg=C6409
+
# Initially maps a flag to its default value. After
# _ParseAndStripGTestFlags() is called, maps a flag to its actual value.
_flag_map = {'gtest_source_dir': os.path.dirname(sys.argv[0]),
@@ -56,7 +69,9 @@ _gtest_flags_are_parsed = False
def _ParseAndStripGTestFlags(argv):
"""Parses and strips Google Test flags from argv. This is idempotent."""
- global _gtest_flags_are_parsed
+ # Suppresses the lint complaint about a global variable since we need it
+ # here to maintain module-wide state.
+ global _gtest_flags_are_parsed # pylint: disable-msg=W0603
if _gtest_flags_are_parsed:
return
@@ -103,6 +118,24 @@ def GetBuildDir():
return os.path.abspath(GetFlag('gtest_build_dir'))
+_temp_dir = None
+
+def _RemoveTempDir():
+ if _temp_dir:
+ shutil.rmtree(_temp_dir, ignore_errors=True)
+
+atexit.register(_RemoveTempDir)
+
+
+def GetTempDir():
+ """Returns a directory for temporary files."""
+
+ global _temp_dir
+ if not _temp_dir:
+ _temp_dir = tempfile.mkdtemp()
+ return _temp_dir
+
+
def GetTestExecutablePath(executable_name):
"""Returns the absolute path of the test binary given its name.
@@ -223,4 +256,4 @@ def Main():
# unittest.main(). Otherwise the latter will be confused by the
# --gtest_* flags.
_ParseAndStripGTestFlags(sys.argv)
- unittest.main()
+ _test_module.main()
diff --git a/test/gtest_throw_on_failure_test.py b/test/gtest_throw_on_failure_test.py
index e952da5..5678ffe 100755
--- a/test/gtest_throw_on_failure_test.py
+++ b/test/gtest_throw_on_failure_test.py
@@ -37,9 +37,8 @@ Google Test) with different environments and command line flags.
__author__ = 'wan@google.com (Zhanyong Wan)'
-import gtest_test_utils
import os
-import unittest
+import gtest_test_utils
# Constants.
@@ -78,7 +77,7 @@ def Run(command):
# The tests. TODO(wan@google.com): refactor the class to share common
# logic with code in gtest_break_on_failure_unittest.py.
-class ThrowOnFailureTest(unittest.TestCase):
+class ThrowOnFailureTest(gtest_test_utils.TestCase):
"""Tests the throw-on-failure mode."""
def RunAndVerify(self, env_var_value, flag_value, should_fail):
diff --git a/test/gtest_uninitialized_test.py b/test/gtest_uninitialized_test.py
index 19b92e9..6ae57ee 100755
--- a/test/gtest_uninitialized_test.py
+++ b/test/gtest_uninitialized_test.py
@@ -34,8 +34,6 @@
__author__ = 'wan@google.com (Zhanyong Wan)'
import gtest_test_utils
-import sys
-import unittest
COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_uninitialized_test_')
@@ -63,7 +61,7 @@ def TestExitCodeAndOutput(command):
Assert('InitGoogleTest' in p.output)
-class GTestUninitializedTest(unittest.TestCase):
+class GTestUninitializedTest(gtest_test_utils.TestCase):
def testExitCodeAndOutput(self):
TestExitCodeAndOutput(COMMAND)
diff --git a/test/gtest_xml_outfiles_test.py b/test/gtest_xml_outfiles_test.py
index 9d62793..0fe947f 100755
--- a/test/gtest_xml_outfiles_test.py
+++ b/test/gtest_xml_outfiles_test.py
@@ -33,17 +33,14 @@
__author__ = "keith.ray@gmail.com (Keith Ray)"
-import gtest_test_utils
import os
-import sys
-import tempfile
-import unittest
-
from xml.dom import minidom, Node
+import gtest_test_utils
import gtest_xml_test_utils
+GTEST_OUTPUT_SUBDIR = "xml_outfiles"
GTEST_OUTPUT_1_TEST = "gtest_xml_outfile1_test_"
GTEST_OUTPUT_2_TEST = "gtest_xml_outfile2_test_"
@@ -71,7 +68,8 @@ class GTestXMLOutFilesTest(gtest_xml_test_utils.GTestXMLTestCase):
# We want the trailing '/' that the last "" provides in os.path.join, for
# telling Google Test to create an output directory instead of a single file
# for xml output.
- self.output_dir_ = os.path.join(tempfile.mkdtemp(), "")
+ self.output_dir_ = os.path.join(gtest_test_utils.GetTempDir(),
+ GTEST_OUTPUT_SUBDIR, "")
self.DeleteFilesAndDir()
def tearDown(self):
@@ -87,7 +85,7 @@ class GTestXMLOutFilesTest(gtest_xml_test_utils.GTestXMLTestCase):
except os.error:
pass
try:
- os.removedirs(self.output_dir_)
+ os.rmdir(self.output_dir_)
except os.error:
pass
@@ -100,7 +98,8 @@ class GTestXMLOutFilesTest(gtest_xml_test_utils.GTestXMLTestCase):
def _TestOutFile(self, test_name, expected_xml):
gtest_prog_path = gtest_test_utils.GetTestExecutablePath(test_name)
command = [gtest_prog_path, "--gtest_output=xml:%s" % self.output_dir_]
- p = gtest_test_utils.Subprocess(command, working_dir=tempfile.mkdtemp())
+ p = gtest_test_utils.Subprocess(command,
+ working_dir=gtest_test_utils.GetTempDir())
self.assert_(p.exited)
self.assertEquals(0, p.exit_code)
diff --git a/test/gtest_xml_output_unittest.py b/test/gtest_xml_output_unittest.py
index 622251e..a0cd4d0 100755
--- a/test/gtest_xml_output_unittest.py
+++ b/test/gtest_xml_output_unittest.py
@@ -34,19 +34,24 @@
__author__ = 'eefacm@gmail.com (Sean Mcafee)'
import errno
-import gtest_test_utils
import os
import sys
-import tempfile
-import unittest
-
from xml.dom import minidom, Node
+import gtest_test_utils
import gtest_xml_test_utils
+
GTEST_OUTPUT_FLAG = "--gtest_output"
GTEST_DEFAULT_OUTPUT_FILE = "test_detail.xml"
+SUPPORTS_STACK_TRACES = False
+
+if SUPPORTS_STACK_TRACES:
+ STACK_TRACE_TEMPLATE = "\nStack trace:\n*"
+else:
+ STACK_TRACE_TEMPLATE = ""
+
EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="13" failures="2" disabled="2" errors="0" time="*" name="AllTests">
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" errors="0" time="*">
@@ -56,7 +61,7 @@ EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testcase name="Fails" status="run" time="*" classname="FailedTest">
<failure message="Value of: 2&#x0A;Expected: 1" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
Value of: 2
-Expected: 1]]></failure>
+Expected: 1%(stack)s]]></failure>
</testcase>
</testsuite>
<testsuite name="MixedResultTest" tests="3" failures="1" disabled="1" errors="0" time="*">
@@ -64,10 +69,10 @@ Expected: 1]]></failure>
<testcase name="Fails" status="run" time="*" classname="MixedResultTest">
<failure message="Value of: 2&#x0A;Expected: 1" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
Value of: 2
-Expected: 1]]></failure>
+Expected: 1%(stack)s]]></failure>
<failure message="Value of: 3&#x0A;Expected: 2" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
Value of: 3
-Expected: 2]]></failure>
+Expected: 2%(stack)s]]></failure>
</testcase>
<testcase name="DISABLED_test" status="notrun" time="*" classname="MixedResultTest"/>
</testsuite>
@@ -85,7 +90,7 @@ Expected: 2]]></failure>
<testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" status="run" time="*" classname="NoFixtureTest" key_for_utility_int="1"/>
<testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" status="run" time="*" classname="NoFixtureTest" key_for_utility_string="1"/>
</testsuite>
-</testsuites>"""
+</testsuites>""" % {'stack': STACK_TRACE_TEMPLATE}
EXPECTED_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
@@ -120,8 +125,8 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
Confirms that Google Test produces an XML output file with the expected
default name if no name is explicitly specified.
"""
- temp_dir = tempfile.mkdtemp()
- output_file = os.path.join(temp_dir, GTEST_DEFAULT_OUTPUT_FILE)
+ output_file = os.path.join(gtest_test_utils.GetTempDir(),
+ GTEST_DEFAULT_OUTPUT_FILE)
gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
"gtest_no_test_unittest")
try:
@@ -132,7 +137,7 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
p = gtest_test_utils.Subprocess(
[gtest_prog_path, "%s=xml" % GTEST_OUTPUT_FLAG],
- working_dir=temp_dir)
+ working_dir=gtest_test_utils.GetTempDir())
self.assert_(p.exited)
self.assertEquals(0, p.exit_code)
self.assert_(os.path.isfile(output_file))
@@ -145,8 +150,8 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
XML document. Furthermore, the program's exit code must be
expected_exit_code.
"""
-
- xml_path = os.path.join(tempfile.mkdtemp(), gtest_prog_name + "out.xml")
+ xml_path = os.path.join(gtest_test_utils.GetTempDir(),
+ gtest_prog_name + "out.xml")
gtest_prog_path = gtest_test_utils.GetTestExecutablePath(gtest_prog_name)
command = [gtest_prog_path, "%s=xml:%s" % (GTEST_OUTPUT_FLAG, xml_path)]
diff --git a/test/gtest_xml_test_utils.py b/test/gtest_xml_test_utils.py
index 64eebb1..1811c40 100755
--- a/test/gtest_xml_test_utils.py
+++ b/test/gtest_xml_test_utils.py
@@ -34,14 +34,15 @@
__author__ = 'eefacm@gmail.com (Sean Mcafee)'
import re
-import unittest
-
from xml.dom import minidom, Node
+import gtest_test_utils
+
+
GTEST_OUTPUT_FLAG = "--gtest_output"
GTEST_DEFAULT_OUTPUT_FILE = "test_detail.xml"
-class GTestXMLTestCase(unittest.TestCase):
+class GTestXMLTestCase(gtest_test_utils.TestCase):
"""
Base class for tests of Google Test's XML output functionality.
"""
diff --git a/test/run_tests_test.py b/test/run_tests_test.py
index 1d9f3b7..b55739e 100755
--- a/test/run_tests_test.py
+++ b/test/run_tests_test.py
@@ -48,6 +48,8 @@ class FakePath(object):
self.tree = {}
self.path_separator = os.sep
+ # known_paths contains either absolute or relative paths. Relative paths
+ # are absolutized with self.current_dir.
if known_paths:
self._AddPaths(known_paths)
@@ -91,8 +93,11 @@ class FakePath(object):
return tree
+ def normpath(self, path):
+ return os.path.normpath(path)
+
def abspath(self, path):
- return os.path.normpath(os.path.join(self.current_dir, path))
+ return self.normpath(os.path.join(self.current_dir, path))
def isfile(self, path):
return self.PathElement(self.abspath(path)) == 1
@@ -157,7 +162,8 @@ class GetTestsToRunTest(unittest.TestCase):
'test/gtest_color_test.py']))
self.fake_configurations = ['dbg', 'opt']
self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
- injected_subprocess=None)
+ injected_subprocess=None,
+ injected_script_dir='.')
def testBinaryTestsOnly(self):
"""Exercises GetTestsToRun with parameters designating binary tests only."""
@@ -388,7 +394,8 @@ class GetTestsToRunTest(unittest.TestCase):
'scons/build/opt/scons/gtest_nontest.exe',
'test/']))
self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
- injected_subprocess=None)
+ injected_subprocess=None,
+ injected_script_dir='.')
self.AssertResultsEqual(
self.test_runner.GetTestsToRun(
[],
@@ -397,6 +404,43 @@ class GetTestsToRunTest(unittest.TestCase):
available_configurations=self.fake_configurations),
([], []))
+ def testWorksFromDifferentDir(self):
+ """Exercises GetTestsToRun from a directory different from run_test.py's."""
+
+ # Here we simulate an test script in directory /d/ called from the
+ # directory /a/b/c/.
+ self.fake_os = FakeOs(FakePath(
+ current_dir=os.path.abspath('/a/b/c'),
+ known_paths=['/a/b/c/',
+ '/d/scons/build/dbg/scons/gtest_unittest',
+ '/d/scons/build/opt/scons/gtest_unittest',
+ '/d/test/gtest_color_test.py']))
+ self.fake_configurations = ['dbg', 'opt']
+ self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
+ injected_subprocess=None,
+ injected_script_dir='/d/')
+ # A binary test.
+ self.AssertResultsEqual(
+ self.test_runner.GetTestsToRun(
+ ['gtest_unittest'],
+ '',
+ False,
+ available_configurations=self.fake_configurations),
+ ([],
+ [('/d/scons/build/dbg/scons',
+ '/d/scons/build/dbg/scons/gtest_unittest')]))
+
+ # A Python test.
+ self.AssertResultsEqual(
+ self.test_runner.GetTestsToRun(
+ ['gtest_color_test.py'],
+ '',
+ False,
+ available_configurations=self.fake_configurations),
+ ([('/d/scons/build/dbg/scons', '/d/test/gtest_color_test.py')],
+ []))
+
+
def testNonTestBinary(self):
"""Exercises GetTestsToRun with a non-test parameter."""