diff options
-rw-r--r-- | Makefile.am | 17 | ||||
-rw-r--r-- | README | 26 | ||||
-rw-r--r-- | include/gtest/internal/gtest-port.h | 43 | ||||
-rw-r--r-- | include/gtest/internal/gtest-tuple.h | 945 | ||||
-rw-r--r-- | include/gtest/internal/gtest-tuple.h.pump | 320 | ||||
-rwxr-xr-x | run_tests.py | 77 | ||||
-rw-r--r-- | scons/SConscript | 39 | ||||
-rw-r--r-- | test/gtest-tuple_test.cc | 288 | ||||
-rwxr-xr-x | test/gtest_break_on_failure_unittest.py | 3 | ||||
-rwxr-xr-x | test/gtest_color_test.py | 7 | ||||
-rwxr-xr-x | test/gtest_env_var_test.py | 12 | ||||
-rwxr-xr-x | test/gtest_filter_unittest.py | 72 | ||||
-rwxr-xr-x | test/gtest_help_test.py | 5 | ||||
-rwxr-xr-x | test/gtest_list_tests_unittest.py | 7 | ||||
-rwxr-xr-x | test/gtest_nc_test.py | 5 | ||||
-rwxr-xr-x | test/gtest_output_test.py | 87 | ||||
-rwxr-xr-x | test/gtest_test_utils.py | 37 | ||||
-rwxr-xr-x | test/gtest_throw_on_failure_test.py | 5 | ||||
-rwxr-xr-x | test/gtest_uninitialized_test.py | 4 | ||||
-rwxr-xr-x | test/gtest_xml_outfiles_test.py | 15 | ||||
-rwxr-xr-x | test/gtest_xml_output_unittest.py | 31 | ||||
-rwxr-xr-x | test/gtest_xml_test_utils.py | 7 | ||||
-rwxr-xr-x | test/run_tests_test.py | 50 |
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 @@ -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
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
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
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.""" |